diff --git a/.gitattributes b/.gitattributes index 581789817cf2..449d26d8ee40 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10,3 +10,4 @@ lib/libcxx/** linguist-vendored lib/libcxxabi/** linguist-vendored lib/libunwind/** linguist-vendored lib/tsan/** linguist-vendored +deps/** linguist-vendored diff --git a/CMakeLists.txt b/CMakeLists.txt index e692feb421f3..ef194d3d03d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -797,7 +797,8 @@ set(BUILD_ZIG2_ARGS -OReleaseSmall --name zig2 -femit-bin="${ZIG2_C_SOURCE}" --mod "build_options::${ZIG_CONFIG_ZIG_OUT}" - --deps build_options + --mod "aro::deps/aro/lib.zig" + --deps build_options,aro -target "${ZIG_HOST_TARGET_TRIPLE}" ) diff --git a/build.zig b/build.zig index 8777060a89df..ad3e4f1347d2 100644 --- a/build.zig +++ b/build.zig @@ -580,6 +580,9 @@ fn addCompilerStep( .optimize = optimize, }); exe.stack_size = stack_size; + exe.addAnonymousModule("aro", .{ + .source_file = .{ .path = "deps/aro/lib.zig" }, + }); return exe; } diff --git a/deps/aro/Attribute.zig b/deps/aro/Attribute.zig new file mode 100644 index 000000000000..fc2a994cc95a --- /dev/null +++ b/deps/aro/Attribute.zig @@ -0,0 +1,1346 @@ +const std = @import("std"); +const mem = std.mem; +const ZigType = std.builtin.Type; +const CallingConvention = @import("lib.zig").CallingConvention; +const Compilation = @import("Compilation.zig"); +const Diagnostics = @import("Diagnostics.zig"); +const Parser = @import("Parser.zig"); +const Tree = @import("Tree.zig"); +const NodeIndex = Tree.NodeIndex; +const TokenIndex = Tree.TokenIndex; +const Type = @import("Type.zig"); +const Value = @import("Value.zig"); + +const Attribute = @This(); + +tag: Tag, +syntax: Syntax, +args: Arguments, + +pub const Syntax = enum { + c2x, + declspec, + gnu, + keyword, +}; + +pub const Kind = enum { + c2x, + declspec, + gnu, + + pub fn toSyntax(kind: Kind) Syntax { + return switch (kind) { + .c2x => .c2x, + .declspec => .declspec, + .gnu => .gnu, + }; + } +}; + +pub const ArgumentType = enum { + string, + identifier, + int, + alignment, + float, + expression, + nullptr_t, + + pub fn toString(self: ArgumentType) []const u8 { + return switch (self) { + .string => "a string", + .identifier => "an identifier", + .int, .alignment => "an integer constant", + .nullptr_t => "nullptr", + .float => "a floating point number", + .expression => "an expression", + }; + } + + fn fromType(comptime T: type) ArgumentType { + return switch (T) { + []const u8 => .string, + Identifier => .identifier, + u32 => .int, + Alignment => .alignment, + CallingConvention => .identifier, + else => switch (@typeInfo(T)) { + .Enum => if (T.opts.enum_kind == .string) .string else .identifier, + else => unreachable, + }, + }; + } + + fn fromVal(value: Value) ArgumentType { + return switch (value.tag) { + .int => .int, + .bytes => .string, + .unavailable => .expression, + .float => .float, + .nullptr_t => .nullptr_t, + }; + } +}; + +fn getArguments(comptime descriptor: type) []const ZigType.StructField { + return if (@hasDecl(descriptor, "Args")) std.meta.fields(descriptor.Args) else &.{}; +} + +/// number of required arguments +pub fn requiredArgCount(attr: Tag) u32 { + switch (attr) { + inline else => |tag| { + comptime var needed = 0; + comptime { + const fields = getArguments(@field(attributes, @tagName(tag))); + for (fields) |arg_field| { + if (!mem.eql(u8, arg_field.name, "__name_tok") and @typeInfo(arg_field.type) != .Optional) needed += 1; + } + } + return needed; + }, + } +} + +/// maximum number of args that can be passed +pub fn maxArgCount(attr: Tag) u32 { + switch (attr) { + inline else => |tag| { + comptime var max = 0; + comptime { + const fields = getArguments(@field(attributes, @tagName(tag))); + for (fields) |arg_field| { + if (!mem.eql(u8, arg_field.name, "__name_tok")) max += 1; + } + } + return max; + }, + } +} + +fn UnwrapOptional(comptime T: type) type { + return switch (@typeInfo(T)) { + .Optional => |optional| optional.child, + else => T, + }; +} + +pub const Formatting = struct { + /// The quote char (single or double) to use when printing identifiers/strings corresponding + /// to the enum in the first field of the Args of `attr`. Identifier enums use single quotes, string enums + /// use double quotes + fn quoteChar(attr: Tag) []const u8 { + switch (attr) { + .calling_convention => unreachable, + inline else => |tag| { + const fields = getArguments(@field(attributes, @tagName(tag))); + + if (fields.len == 0) unreachable; + const Unwrapped = UnwrapOptional(fields[0].type); + if (@typeInfo(Unwrapped) != .Enum) unreachable; + + return if (Unwrapped.opts.enum_kind == .identifier) "'" else "\""; + }, + } + } + + /// returns a comma-separated string of quoted enum values, representing the valid + /// choices for the string or identifier enum of the first field of the Args of `attr`. + pub fn choices(attr: Tag) []const u8 { + switch (attr) { + .calling_convention => unreachable, + inline else => |tag| { + const fields = getArguments(@field(attributes, @tagName(tag))); + + if (fields.len == 0) unreachable; + const Unwrapped = UnwrapOptional(fields[0].type); + if (@typeInfo(Unwrapped) != .Enum) unreachable; + + const enum_fields = @typeInfo(Unwrapped).Enum.fields; + @setEvalBranchQuota(3000); + const quote = comptime quoteChar(@enumFromInt(@intFromEnum(tag))); + comptime var values: []const u8 = quote ++ enum_fields[0].name ++ quote; + inline for (enum_fields[1..]) |enum_field| { + values = values ++ ", "; + values = values ++ quote ++ enum_field.name ++ quote; + } + return values; + }, + } + } +}; + +/// Checks if the first argument (if it exists) is an identifier enum +pub fn wantsIdentEnum(attr: Tag) bool { + switch (attr) { + .calling_convention => return false, + inline else => |tag| { + const fields = getArguments(@field(attributes, @tagName(tag))); + + if (fields.len == 0) return false; + const Unwrapped = UnwrapOptional(fields[0].type); + if (@typeInfo(Unwrapped) != .Enum) return false; + + return Unwrapped.opts.enum_kind == .identifier; + }, + } +} + +pub fn diagnoseIdent(attr: Tag, arguments: *Arguments, ident: []const u8) ?Diagnostics.Message { + switch (attr) { + inline else => |tag| { + const fields = getArguments(@field(attributes, @tagName(tag))); + if (fields.len == 0) unreachable; + const Unwrapped = UnwrapOptional(fields[0].type); + if (@typeInfo(Unwrapped) != .Enum) unreachable; + if (std.meta.stringToEnum(Unwrapped, normalize(ident))) |enum_val| { + @field(@field(arguments, @tagName(tag)), fields[0].name) = enum_val; + return null; + } + return Diagnostics.Message{ + .tag = .unknown_attr_enum, + .extra = .{ .attr_enum = .{ .tag = attr } }, + }; + }, + } +} + +pub fn wantsAlignment(attr: Tag, idx: usize) bool { + switch (attr) { + inline else => |tag| { + const fields = getArguments(@field(attributes, @tagName(tag))); + if (fields.len == 0) return false; + + return switch (idx) { + inline 0...fields.len - 1 => |i| UnwrapOptional(fields[i].type) == Alignment, + else => false, + }; + }, + } +} + +pub fn diagnoseAlignment(attr: Tag, arguments: *Arguments, arg_idx: u32, val: Value, ty: Type, comp: *Compilation) ?Diagnostics.Message { + switch (attr) { + inline else => |tag| { + const arg_fields = getArguments(@field(attributes, @tagName(tag))); + if (arg_fields.len == 0) unreachable; + + switch (arg_idx) { + inline 0...arg_fields.len - 1 => |arg_i| { + if (UnwrapOptional(arg_fields[arg_i].type) != Alignment) unreachable; + + if (val.tag != .int) return Diagnostics.Message{ .tag = .alignas_unavailable }; + if (val.compare(.lt, Value.int(0), ty, comp)) { + return Diagnostics.Message{ .tag = .negative_alignment, .extra = .{ .signed = val.signExtend(ty, comp) } }; + } + const requested = std.math.cast(u29, val.data.int) orelse { + return Diagnostics.Message{ .tag = .maximum_alignment, .extra = .{ .unsigned = val.data.int } }; + }; + if (!std.mem.isValidAlign(requested)) return Diagnostics.Message{ .tag = .non_pow2_align }; + + @field(@field(arguments, @tagName(tag)), arg_fields[arg_i].name) = Alignment{ .requested = requested }; + return null; + }, + else => unreachable, + } + }, + } +} + +fn diagnoseField( + comptime decl: ZigType.Declaration, + comptime field: ZigType.StructField, + comptime wanted: type, + arguments: *Arguments, + val: Value, + node: Tree.Node, + strings: []const u8, +) ?Diagnostics.Message { + switch (val.tag) { + .int => { + if (@typeInfo(wanted) == .Int) { + @field(@field(arguments, decl.name), field.name) = val.getInt(wanted); + return null; + } + }, + .bytes => { + const bytes = val.data.bytes.trim(1); // remove null terminator + if (wanted == Value.ByteRange) { + @field(@field(arguments, decl.name), field.name) = bytes; + return null; + } else if (@typeInfo(wanted) == .Enum and @hasDecl(wanted, "opts") and wanted.opts.enum_kind == .string) { + const str = bytes.slice(strings); + if (std.meta.stringToEnum(wanted, str)) |enum_val| { + @field(@field(arguments, decl.name), field.name) = enum_val; + return null; + } else { + @setEvalBranchQuota(3000); + return Diagnostics.Message{ + .tag = .unknown_attr_enum, + .extra = .{ .attr_enum = .{ .tag = std.meta.stringToEnum(Tag, decl.name).? } }, + }; + } + } + }, + else => { + if (wanted == Identifier and node.tag == .decl_ref_expr) { + @field(@field(arguments, decl.name), field.name) = Identifier{ .tok = node.data.decl_ref }; + return null; + } + }, + } + return Diagnostics.Message{ + .tag = .attribute_arg_invalid, + .extra = .{ .attr_arg_type = .{ .expected = ArgumentType.fromType(wanted), .actual = ArgumentType.fromVal(val) } }, + }; +} + +pub fn diagnose(attr: Tag, arguments: *Arguments, arg_idx: u32, val: Value, node: Tree.Node, strings: []const u8) ?Diagnostics.Message { + switch (attr) { + inline else => |tag| { + const decl = @typeInfo(attributes).Struct.decls[@intFromEnum(tag)]; + const max_arg_count = comptime maxArgCount(tag); + if (arg_idx >= max_arg_count) return Diagnostics.Message{ + .tag = .attribute_too_many_args, + .extra = .{ .attr_arg_count = .{ .attribute = attr, .expected = max_arg_count } }, + }; + const arg_fields = getArguments(@field(attributes, decl.name)); + switch (arg_idx) { + inline 0...arg_fields.len - 1 => |arg_i| { + return diagnoseField(decl, arg_fields[arg_i], UnwrapOptional(arg_fields[arg_i].type), arguments, val, node, strings); + }, + else => unreachable, + } + }, + } +} + +const EnumTypes = enum { + string, + identifier, +}; +pub const Alignment = struct { + node: NodeIndex = .none, + requested: u29, +}; +pub const Identifier = struct { + tok: TokenIndex = 0, +}; + +const attributes = struct { + pub const access = struct { + const gnu = "access"; + + const Args = struct { + access_mode: enum { + read_only, + read_write, + write_only, + none, + + const opts = struct { + const enum_kind = .identifier; + }; + }, + ref_index: u32, + size_index: ?u32 = null, + }; + }; + pub const alias = struct { + const gnu = "alias"; + const Args = struct { + alias: Value.ByteRange, + }; + }; + pub const aligned = struct { + const gnu = "aligned"; + const declspec = "align"; + + const Args = struct { + alignment: ?Alignment = null, + __name_tok: TokenIndex, + }; + }; + pub const alloc_align = struct { + const gnu = "alloc_align"; + + const Args = struct { + position: u32, + }; + }; + pub const alloc_size = struct { + const gnu = "alloc_size"; + + const Args = struct { + position_1: u32, + position_2: ?u32 = null, + }; + }; + pub const allocate = struct { + const declspec = "allocate"; + + const Args = struct { + segname: Value.ByteRange, + }; + }; + pub const allocator = struct { + const declspec = "allocator"; + }; + pub const always_inline = struct { + const gnu = "always_inline"; + }; + pub const appdomain = struct { + const declspec = "appdomain"; + }; + pub const artificial = struct { + const gnu = "artificial"; + }; + pub const assume_aligned = struct { + const gnu = "assume_aligned"; + const Args = struct { + alignment: Alignment, + offset: ?u32 = null, + }; + }; + pub const cleanup = struct { + const gnu = "cleanup"; + const Args = struct { + function: Identifier, + }; + }; + pub const code_seg = struct { + const declspec = "code_seg"; + const Args = struct { + segname: Value.ByteRange, + }; + }; + pub const cold = struct { + const gnu = "cold"; + }; + pub const common = struct { + const gnu = "common"; + }; + pub const @"const" = struct { + const gnu = "const"; + }; + pub const constructor = struct { + const gnu = "constructor"; + const Args = struct { + priority: ?u32 = null, + }; + }; + pub const copy = struct { + const gnu = "copy"; + const Args = struct { + function: Identifier, + }; + }; + pub const deprecated = struct { + const gnu = "deprecated"; + const declspec = "deprecated"; + const c2x = "deprecated"; + + const Args = struct { + msg: ?Value.ByteRange = null, + __name_tok: TokenIndex, + }; + }; + pub const designated_init = struct { + const gnu = "designated_init"; + }; + pub const destructor = struct { + const gnu = "destructor"; + const Args = struct { + priority: ?u32 = null, + }; + }; + pub const dllexport = struct { + const declspec = "dllexport"; + }; + pub const dllimport = struct { + const declspec = "dllimport"; + }; + pub const @"error" = struct { + const gnu = "error"; + const Args = struct { + msg: Value.ByteRange, + __name_tok: TokenIndex, + }; + }; + pub const externally_visible = struct { + const gnu = "externally_visible"; + }; + pub const fallthrough = struct { + const gnu = "fallthrough"; + const c2x = "fallthrough"; + }; + pub const flatten = struct { + const gnu = "flatten"; + }; + pub const format = struct { + const gnu = "format"; + const Args = struct { + archetype: enum { + printf, + scanf, + strftime, + strfmon, + + const opts = struct { + const enum_kind = .identifier; + }; + }, + string_index: u32, + first_to_check: u32, + }; + }; + pub const format_arg = struct { + const gnu = "format_arg"; + const Args = struct { + string_index: u32, + }; + }; + pub const gnu_inline = struct { + const gnu = "gnu_inline"; + }; + pub const hot = struct { + const gnu = "hot"; + }; + pub const ifunc = struct { + const gnu = "ifunc"; + const Args = struct { + resolver: Value.ByteRange, + }; + }; + pub const interrupt = struct { + const gnu = "interrupt"; + }; + pub const interrupt_handler = struct { + const gnu = "interrupt_handler"; + }; + pub const jitintrinsic = struct { + const declspec = "jitintrinsic"; + }; + pub const leaf = struct { + const gnu = "leaf"; + }; + pub const malloc = struct { + const gnu = "malloc"; + }; + pub const may_alias = struct { + const gnu = "may_alias"; + }; + pub const mode = struct { + const gnu = "mode"; + const Args = struct { + mode: enum { + // zig fmt: off + byte, word, pointer, + BI, QI, HI, + PSI, SI, PDI, + DI, TI, OI, + XI, QF, HF, + TQF, SF, DF, + XF, SD, DD, + TD, TF, QQ, + HQ, SQ, DQ, + TQ, UQQ, UHQ, + USQ, UDQ, UTQ, + HA, SA, DA, + TA, UHA, USA, + UDA, UTA, CC, + BLK, VOID, QC, + HC, SC, DC, + XC, TC, CQI, + CHI, CSI, CDI, + CTI, COI, CPSI, + BND32, BND64, + // zig fmt: on + + const opts = struct { + const enum_kind = .identifier; + }; + }, + }; + }; + pub const naked = struct { + const declspec = "naked"; + }; + pub const no_address_safety_analysis = struct { + const gnu = "no_address_safety_analysise"; + }; + pub const no_icf = struct { + const gnu = "no_icf"; + }; + pub const no_instrument_function = struct { + const gnu = "no_instrument_function"; + }; + pub const no_profile_instrument_function = struct { + const gnu = "no_profile_instrument_function"; + }; + pub const no_reorder = struct { + const gnu = "no_reorder"; + }; + pub const no_sanitize = struct { + const gnu = "no_sanitize"; + /// Todo: represent args as union? + const Args = struct { + alignment: Value.ByteRange, + object_size: ?Value.ByteRange = null, + }; + }; + pub const no_sanitize_address = struct { + const gnu = "no_sanitize_address"; + const declspec = "no_sanitize_address"; + }; + pub const no_sanitize_coverage = struct { + const gnu = "no_sanitize_coverage"; + }; + pub const no_sanitize_thread = struct { + const gnu = "no_sanitize_thread"; + }; + pub const no_sanitize_undefined = struct { + const gnu = "no_sanitize_undefined"; + }; + pub const no_split_stack = struct { + const gnu = "no_split_stack"; + }; + pub const no_stack_limit = struct { + const gnu = "no_stack_limit"; + }; + pub const no_stack_protector = struct { + const gnu = "no_stack_protector"; + }; + pub const @"noalias" = struct { + const declspec = "noalias"; + }; + pub const noclone = struct { + const gnu = "noclone"; + }; + pub const nocommon = struct { + const gnu = "nocommon"; + }; + pub const nodiscard = struct { + const c2x = "nodiscard"; + }; + pub const noinit = struct { + const gnu = "noinit"; + }; + pub const @"noinline" = struct { + const gnu = "noinline"; + const declspec = "noinline"; + }; + pub const noipa = struct { + const gnu = "noipa"; + }; + // TODO: arbitrary number of arguments + // const nonnull = struct { + // const gnu = "nonnull"; + // const Args = struct { + // arg_index: []const u32, + // }; + // }; + pub const nonstring = struct { + const gnu = "nonstring"; + }; + pub const noplt = struct { + const gnu = "noplt"; + }; + pub const @"noreturn" = struct { + const gnu = "noreturn"; + const c2x = "noreturn"; + const declspec = "noreturn"; + }; + // TODO: union args ? + // const optimize = struct { + // const gnu = "optimize"; + // const Args = struct { + // optimize, // u32 | []const u8 -- optimize? + // }; + // }; + pub const @"packed" = struct { + const gnu = "packed"; + }; + pub const patchable_function_entry = struct { + const gnu = "patchable_function_entry"; + }; + pub const persistent = struct { + const gnu = "persistent"; + }; + pub const process = struct { + const declspec = "process"; + }; + pub const pure = struct { + const gnu = "pure"; + }; + pub const reproducible = struct { + const c2x = "reproducible"; + }; + pub const restrict = struct { + const declspec = "restrict"; + }; + pub const retain = struct { + const gnu = "retain"; + }; + pub const returns_nonnull = struct { + const gnu = "returns_nonnull"; + }; + pub const returns_twice = struct { + const gnu = "returns_twice"; + }; + pub const safebuffers = struct { + const declspec = "safebuffers"; + }; + pub const scalar_storage_order = struct { + const gnu = "scalar_storage_order"; + const Args = struct { + order: enum { + @"little-endian", + @"big-endian", + + const opts = struct { + const enum_kind = .string; + }; + }, + }; + }; + pub const section = struct { + const gnu = "section"; + const Args = struct { + name: Value.ByteRange, + }; + }; + pub const selectany = struct { + const declspec = "selectany"; + }; + pub const sentinel = struct { + const gnu = "sentinel"; + const Args = struct { + position: ?u32 = null, + }; + }; + pub const simd = struct { + const gnu = "simd"; + const Args = struct { + mask: ?enum { + notinbranch, + inbranch, + + const opts = struct { + const enum_kind = .string; + }; + } = null, + }; + }; + pub const spectre = struct { + const declspec = "spectre"; + const Args = struct { + arg: enum { + nomitigation, + + const opts = struct { + const enum_kind = .identifier; + }; + }, + }; + }; + pub const stack_protect = struct { + const gnu = "stack_protect"; + }; + pub const symver = struct { + const gnu = "symver"; + const Args = struct { + version: Value.ByteRange, // TODO: validate format "name2@nodename" + }; + }; + pub const target = struct { + const gnu = "target"; + const Args = struct { + options: Value.ByteRange, // TODO: multiple arguments + }; + }; + pub const target_clones = struct { + const gnu = "target_clones"; + const Args = struct { + options: Value.ByteRange, // TODO: multiple arguments + }; + }; + pub const thread = struct { + const declspec = "thread"; + }; + pub const tls_model = struct { + const gnu = "tls_model"; + const Args = struct { + model: enum { + @"global-dynamic", + @"local-dynamic", + @"initial-exec", + @"local-exec", + + const opts = struct { + const enum_kind = .string; + }; + }, + }; + }; + pub const transparent_union = struct { + const gnu = "transparent_union"; + }; + pub const unavailable = struct { + const gnu = "unavailable"; + const Args = struct { + msg: ?Value.ByteRange = null, + __name_tok: TokenIndex, + }; + }; + pub const uninitialized = struct { + const gnu = "uninitialized"; + }; + pub const unsequenced = struct { + const c2x = "unsequenced"; + }; + pub const unused = struct { + const gnu = "unused"; + const c2x = "maybe_unused"; + }; + pub const used = struct { + const gnu = "used"; + }; + pub const uuid = struct { + const declspec = "uuid"; + const Args = struct { + uuid: Value.ByteRange, + }; + }; + pub const vector_size = struct { + const gnu = "vector_size"; + const Args = struct { + bytes: u32, // TODO: validate "The bytes argument must be a positive power-of-two multiple of the base type size" + }; + }; + pub const visibility = struct { + const gnu = "visibility"; + const Args = struct { + visibility_type: enum { + default, + hidden, + internal, + protected, + + const opts = struct { + const enum_kind = .string; + }; + }, + }; + }; + pub const warn_if_not_aligned = struct { + const gnu = "warn_if_not_aligned"; + const Args = struct { + alignment: Alignment, + }; + }; + pub const warn_unused_result = struct { + const gnu = "warn_unused_result"; + }; + pub const warning = struct { + const gnu = "warning"; + const Args = struct { + msg: Value.ByteRange, + __name_tok: TokenIndex, + }; + }; + pub const weak = struct { + const gnu = "weak"; + }; + pub const weakref = struct { + const gnu = "weakref"; + const Args = struct { + target: ?Value.ByteRange = null, + }; + }; + pub const zero_call_used_regs = struct { + const gnu = "zero_call_used_regs"; + const Args = struct { + choice: enum { + skip, + used, + @"used-gpr", + @"used-arg", + @"used-gpr-arg", + all, + @"all-gpr", + @"all-arg", + @"all-gpr-arg", + + const opts = struct { + const enum_kind = .string; + }; + }, + }; + }; + pub const asm_label = struct { + const Args = struct { + name: Value.ByteRange, + }; + }; + pub const calling_convention = struct { + const Args = struct { + cc: CallingConvention, + }; + }; +}; + +pub const Tag = std.meta.DeclEnum(attributes); + +pub const Arguments = blk: { + const decls = @typeInfo(attributes).Struct.decls; + var union_fields: [decls.len]ZigType.UnionField = undefined; + inline for (decls, &union_fields) |decl, *field| { + field.* = .{ + .name = decl.name, + .type = if (@hasDecl(@field(attributes, decl.name), "Args")) @field(attributes, decl.name).Args else void, + .alignment = 0, + }; + } + + break :blk @Type(.{ + .Union = .{ + .layout = .Auto, + .tag_type = null, + .fields = &union_fields, + .decls = &.{}, + }, + }); +}; + +pub fn ArgumentsForTag(comptime tag: Tag) type { + const decl = @typeInfo(attributes).Struct.decls[@intFromEnum(tag)]; + return if (@hasDecl(@field(attributes, decl.name), "Args")) @field(attributes, decl.name).Args else void; +} + +pub fn initArguments(tag: Tag, name_tok: TokenIndex) Arguments { + switch (tag) { + inline else => |arg_tag| { + const union_element = @field(attributes, @tagName(arg_tag)); + const has_args = @hasDecl(union_element, "Args"); + const init = if (has_args) std.mem.zeroInit(union_element.Args, .{}) else {}; + var args = @unionInit(Arguments, @tagName(arg_tag), init); + if (has_args and @hasField(@field(attributes, @tagName(arg_tag)).Args, "__name_tok")) { + @field(args, @tagName(arg_tag)).__name_tok = name_tok; + } + return args; + }, + } +} + +pub fn fromString(kind: Kind, namespace: ?[]const u8, name: []const u8) ?Tag { + return switch (kind) { + .c2x => fromStringC2X(namespace, name), + .declspec => fromStringDeclspec(name), + .gnu => fromStringGnu(name), + }; +} + +fn fromStringGnu(name: []const u8) ?Tag { + const normalized = normalize(name); + const decls = @typeInfo(attributes).Struct.decls; + @setEvalBranchQuota(3000); + inline for (decls, 0..) |decl, i| { + if (@hasDecl(@field(attributes, decl.name), "gnu")) { + if (mem.eql(u8, @field(attributes, decl.name).gnu, normalized)) { + return @enumFromInt(i); + } + } + } + return null; +} + +fn fromStringC2X(namespace: ?[]const u8, name: []const u8) ?Tag { + const normalized = normalize(name); + if (namespace) |ns| { + const normalized_ns = normalize(ns); + if (mem.eql(u8, normalized_ns, "gnu")) { + return fromStringGnu(normalized); + } + return null; + } + const decls = @typeInfo(attributes).Struct.decls; + inline for (decls, 0..) |decl, i| { + if (@hasDecl(@field(attributes, decl.name), "c2x")) { + if (mem.eql(u8, @field(attributes, decl.name).c2x, normalized)) { + return @enumFromInt(i); + } + } + } + return null; +} + +fn fromStringDeclspec(name: []const u8) ?Tag { + const decls = @typeInfo(attributes).Struct.decls; + inline for (decls, 0..) |decl, i| { + if (@hasDecl(@field(attributes, decl.name), "declspec")) { + if (mem.eql(u8, @field(attributes, decl.name).declspec, name)) { + return @enumFromInt(i); + } + } + } + return null; +} + +fn normalize(name: []const u8) []const u8 { + if (name.len >= 4 and mem.startsWith(u8, name, "__") and mem.endsWith(u8, name, "__")) { + return name[2 .. name.len - 2]; + } + return name; +} + +fn ignoredAttrErr(p: *Parser, tok: TokenIndex, attr: Attribute.Tag, context: []const u8) !void { + const strings_top = p.strings.items.len; + defer p.strings.items.len = strings_top; + + try p.strings.writer().print("attribute '{s}' ignored on {s}", .{ @tagName(attr), context }); + const str = try p.comp.diag.arena.allocator().dupe(u8, p.strings.items[strings_top..]); + try p.errStr(.ignored_attribute, tok, str); +} + +pub const applyParameterAttributes = applyVariableAttributes; +pub fn applyVariableAttributes(p: *Parser, ty: Type, attr_buf_start: usize, tag: ?Diagnostics.Tag) !Type { + const attrs = p.attr_buf.items(.attr)[attr_buf_start..]; + const toks = p.attr_buf.items(.tok)[attr_buf_start..]; + p.attr_application_buf.items.len = 0; + var base_ty = ty; + if (base_ty.specifier == .attributed) base_ty = base_ty.data.attributed.base; + var common = false; + var nocommon = false; + for (attrs, toks) |attr, tok| switch (attr.tag) { + // zig fmt: off + .alias, .may_alias, .deprecated, .unavailable, .unused, .warn_if_not_aligned, .weak, .used, + .noinit, .retain, .persistent, .section, .mode, .asm_label, + => try p.attr_application_buf.append(p.gpa, attr), + // zig fmt: on + .common => if (nocommon) { + try p.errTok(.ignore_common, tok); + } else { + try p.attr_application_buf.append(p.gpa, attr); + common = true; + }, + .nocommon => if (common) { + try p.errTok(.ignore_nocommon, tok); + } else { + try p.attr_application_buf.append(p.gpa, attr); + nocommon = true; + }, + .vector_size => try attr.applyVectorSize(p, tok, &base_ty), + .aligned => try attr.applyAligned(p, base_ty, tag), + .nonstring => if (!base_ty.isArray() or !(base_ty.is(.char) or base_ty.is(.uchar) or base_ty.is(.schar))) { + try p.errStr(.non_string_ignored, tok, try p.typeStr(ty)); + } else { + try p.attr_application_buf.append(p.gpa, attr); + }, + .uninitialized => if (p.func.ty == null) { + try p.errStr(.local_variable_attribute, tok, "uninitialized"); + } else { + try p.attr_application_buf.append(p.gpa, attr); + }, + .cleanup => if (p.func.ty == null) { + try p.errStr(.local_variable_attribute, tok, "cleanup"); + } else { + try p.attr_application_buf.append(p.gpa, attr); + }, + .alloc_size, + .copy, + .tls_model, + .visibility, + => std.debug.panic("apply variable attribute {s}", .{@tagName(attr.tag)}), + else => try ignoredAttrErr(p, tok, attr.tag, "variables"), + }; + const existing = ty.getAttributes(); + if (existing.len == 0 and p.attr_application_buf.items.len == 0) return base_ty; + if (existing.len == 0) return base_ty.withAttributes(p.arena, p.attr_application_buf.items); + + const attributed_type = try Type.Attributed.create(p.arena, base_ty, existing, p.attr_application_buf.items); + return Type{ .specifier = .attributed, .data = .{ .attributed = attributed_type } }; +} + +pub fn applyFieldAttributes(p: *Parser, field_ty: *Type, attr_buf_start: usize) ![]const Attribute { + const attrs = p.attr_buf.items(.attr)[attr_buf_start..]; + const toks = p.attr_buf.items(.tok)[attr_buf_start..]; + p.attr_application_buf.items.len = 0; + for (attrs, toks) |attr, tok| switch (attr.tag) { + // zig fmt: off + .@"packed", .may_alias, .deprecated, .unavailable, .unused, .warn_if_not_aligned, .mode, + => try p.attr_application_buf.append(p.gpa, attr), + // zig fmt: on + .vector_size => try attr.applyVectorSize(p, tok, field_ty), + .aligned => try attr.applyAligned(p, field_ty.*, null), + else => try ignoredAttrErr(p, tok, attr.tag, "fields"), + }; + if (p.attr_application_buf.items.len == 0) return &[0]Attribute{}; + return p.arena.dupe(Attribute, p.attr_application_buf.items); +} + +pub fn applyTypeAttributes(p: *Parser, ty: Type, attr_buf_start: usize, tag: ?Diagnostics.Tag) !Type { + const attrs = p.attr_buf.items(.attr)[attr_buf_start..]; + const toks = p.attr_buf.items(.tok)[attr_buf_start..]; + p.attr_application_buf.items.len = 0; + var base_ty = ty; + if (base_ty.specifier == .attributed) base_ty = base_ty.data.attributed.base; + for (attrs, toks) |attr, tok| switch (attr.tag) { + // zig fmt: off + .@"packed", .may_alias, .deprecated, .unavailable, .unused, .warn_if_not_aligned, .mode, + => try p.attr_application_buf.append(p.gpa, attr), + // zig fmt: on + .transparent_union => try attr.applyTransparentUnion(p, tok, base_ty), + .vector_size => try attr.applyVectorSize(p, tok, &base_ty), + .aligned => try attr.applyAligned(p, base_ty, tag), + .designated_init => if (base_ty.is(.@"struct")) { + try p.attr_application_buf.append(p.gpa, attr); + } else { + try p.errTok(.designated_init_invalid, tok); + }, + .alloc_size, + .copy, + .scalar_storage_order, + .nonstring, + => std.debug.panic("apply type attribute {s}", .{@tagName(attr.tag)}), + else => try ignoredAttrErr(p, tok, attr.tag, "types"), + }; + + const existing = ty.getAttributes(); + // TODO: the alignment annotation on a type should override + // the decl it refers to. This might not be true for others. Maybe bug. + + // if there are annotations on this type def use those. + if (p.attr_application_buf.items.len > 0) { + return try base_ty.withAttributes(p.arena, p.attr_application_buf.items); + } else if (existing.len > 0) { + // else use the ones on the typedef decl we were refering to. + return try base_ty.withAttributes(p.arena, existing); + } + return base_ty; +} + +pub fn applyFunctionAttributes(p: *Parser, ty: Type, attr_buf_start: usize) !Type { + const attrs = p.attr_buf.items(.attr)[attr_buf_start..]; + const toks = p.attr_buf.items(.tok)[attr_buf_start..]; + p.attr_application_buf.items.len = 0; + var base_ty = ty; + if (base_ty.specifier == .attributed) base_ty = base_ty.data.attributed.base; + var hot = false; + var cold = false; + var @"noinline" = false; + var always_inline = false; + for (attrs, toks) |attr, tok| switch (attr.tag) { + // zig fmt: off + .noreturn, .unused, .used, .warning, .deprecated, .unavailable, .weak, .pure, .leaf, + .@"const", .warn_unused_result, .section, .returns_nonnull, .returns_twice, .@"error", + .externally_visible, .retain, .flatten, .gnu_inline, .alias, .asm_label, .nodiscard, + .reproducible, .unsequenced, + => try p.attr_application_buf.append(p.gpa, attr), + // zig fmt: on + .hot => if (cold) { + try p.errTok(.ignore_hot, tok); + } else { + try p.attr_application_buf.append(p.gpa, attr); + hot = true; + }, + .cold => if (hot) { + try p.errTok(.ignore_cold, tok); + } else { + try p.attr_application_buf.append(p.gpa, attr); + cold = true; + }, + .always_inline => if (@"noinline") { + try p.errTok(.ignore_always_inline, tok); + } else { + try p.attr_application_buf.append(p.gpa, attr); + always_inline = true; + }, + .@"noinline" => if (always_inline) { + try p.errTok(.ignore_noinline, tok); + } else { + try p.attr_application_buf.append(p.gpa, attr); + @"noinline" = true; + }, + .aligned => try attr.applyAligned(p, base_ty, null), + .format => try attr.applyFormat(p, base_ty), + .calling_convention => switch (attr.args.calling_convention.cc) { + .C => continue, + .stdcall, .thiscall => switch (p.comp.target.cpu.arch) { + .x86 => try p.attr_application_buf.append(p.gpa, attr), + else => try p.errStr(.callconv_not_supported, tok, p.tok_ids[tok].lexeme().?), + }, + .vectorcall => switch (p.comp.target.cpu.arch) { + .x86, .aarch64, .aarch64_be, .aarch64_32 => try p.attr_application_buf.append(p.gpa, attr), + else => try p.errStr(.callconv_not_supported, tok, p.tok_ids[tok].lexeme().?), + }, + }, + .access, + .alloc_align, + .alloc_size, + .artificial, + .assume_aligned, + .constructor, + .copy, + .destructor, + .format_arg, + .ifunc, + .interrupt, + .interrupt_handler, + .malloc, + .no_address_safety_analysis, + .no_icf, + .no_instrument_function, + .no_profile_instrument_function, + .no_reorder, + .no_sanitize, + .no_sanitize_address, + .no_sanitize_coverage, + .no_sanitize_thread, + .no_sanitize_undefined, + .no_split_stack, + .no_stack_limit, + .no_stack_protector, + .noclone, + .noipa, + // .nonnull, + .noplt, + // .optimize, + .patchable_function_entry, + .sentinel, + .simd, + .stack_protect, + .symver, + .target, + .target_clones, + .visibility, + .weakref, + .zero_call_used_regs, + => std.debug.panic("apply type attribute {s}", .{@tagName(attr.tag)}), + else => try ignoredAttrErr(p, tok, attr.tag, "functions"), + }; + return ty.withAttributes(p.arena, p.attr_application_buf.items); +} + +pub fn applyLabelAttributes(p: *Parser, ty: Type, attr_buf_start: usize) !Type { + const attrs = p.attr_buf.items(.attr)[attr_buf_start..]; + const toks = p.attr_buf.items(.tok)[attr_buf_start..]; + p.attr_application_buf.items.len = 0; + var hot = false; + var cold = false; + for (attrs, toks) |attr, tok| switch (attr.tag) { + .unused => try p.attr_application_buf.append(p.gpa, attr), + .hot => if (cold) { + try p.errTok(.ignore_hot, tok); + } else { + try p.attr_application_buf.append(p.gpa, attr); + hot = true; + }, + .cold => if (hot) { + try p.errTok(.ignore_cold, tok); + } else { + try p.attr_application_buf.append(p.gpa, attr); + cold = true; + }, + else => try ignoredAttrErr(p, tok, attr.tag, "labels"), + }; + return ty.withAttributes(p.arena, p.attr_application_buf.items); +} + +pub fn applyStatementAttributes(p: *Parser, ty: Type, expr_start: TokenIndex, attr_buf_start: usize) !Type { + const attrs = p.attr_buf.items(.attr)[attr_buf_start..]; + const toks = p.attr_buf.items(.tok)[attr_buf_start..]; + p.attr_application_buf.items.len = 0; + for (attrs, toks) |attr, tok| switch (attr.tag) { + .fallthrough => if (p.tok_ids[p.tok_i] != .keyword_case and p.tok_ids[p.tok_i] != .keyword_default) { + // TODO: this condition is not completely correct; the last statement of a compound + // statement is also valid if it precedes a switch label (so intervening '}' are ok, + // but only if they close a compound statement) + try p.errTok(.invalid_fallthrough, expr_start); + } else { + try p.attr_application_buf.append(p.gpa, attr); + }, + else => try p.errStr(.cannot_apply_attribute_to_statement, tok, @tagName(attr.tag)), + }; + return ty.withAttributes(p.arena, p.attr_application_buf.items); +} + +pub fn applyEnumeratorAttributes(p: *Parser, ty: Type, attr_buf_start: usize) !Type { + const attrs = p.attr_buf.items(.attr)[attr_buf_start..]; + const toks = p.attr_buf.items(.tok)[attr_buf_start..]; + p.attr_application_buf.items.len = 0; + for (attrs, toks) |attr, tok| switch (attr.tag) { + .deprecated, .unavailable => try p.attr_application_buf.append(p.gpa, attr), + else => try ignoredAttrErr(p, tok, attr.tag, "enums"), + }; + return ty.withAttributes(p.arena, p.attr_application_buf.items); +} + +fn applyAligned(attr: Attribute, p: *Parser, ty: Type, tag: ?Diagnostics.Tag) !void { + const base = ty.canonicalize(.standard); + if (attr.args.aligned.alignment) |alignment| alignas: { + if (attr.syntax != .keyword) break :alignas; + + const align_tok = attr.args.aligned.__name_tok; + if (tag) |t| try p.errTok(t, align_tok); + + const default_align = base.alignof(p.comp); + if (ty.isFunc()) { + try p.errTok(.alignas_on_func, align_tok); + } else if (alignment.requested < default_align) { + try p.errExtra(.minimum_alignment, align_tok, .{ .unsigned = default_align }); + } + } + try p.attr_application_buf.append(p.gpa, attr); +} + +fn applyTransparentUnion(attr: Attribute, p: *Parser, tok: TokenIndex, ty: Type) !void { + const union_ty = ty.get(.@"union") orelse { + return p.errTok(.transparent_union_wrong_type, tok); + }; + // TODO validate union defined at end + if (union_ty.data.record.isIncomplete()) return; + const fields = union_ty.data.record.fields; + if (fields.len == 0) { + return p.errTok(.transparent_union_one_field, tok); + } + const first_field_size = fields[0].ty.bitSizeof(p.comp).?; + for (fields[1..]) |field| { + const field_size = field.ty.bitSizeof(p.comp).?; + if (field_size == first_field_size) continue; + const mapper = p.comp.string_interner.getSlowTypeMapper(); + const str = try std.fmt.allocPrint(p.comp.diag.arena.allocator(), "'{s}' ({d}", .{ mapper.lookup(field.name), field_size }); + try p.errStr(.transparent_union_size, field.name_tok, str); + return p.errExtra(.transparent_union_size_note, fields[0].name_tok, .{ .unsigned = first_field_size }); + } + + try p.attr_application_buf.append(p.gpa, attr); +} + +fn applyVectorSize(attr: Attribute, p: *Parser, tok: TokenIndex, ty: *Type) !void { + if (!(ty.isInt() or ty.isFloat()) or !ty.isReal()) { + const orig_ty = try p.typeStr(ty.*); + ty.* = Type.invalid; + return p.errStr(.invalid_vec_elem_ty, tok, orig_ty); + } + const vec_bytes = attr.args.vector_size.bytes; + const ty_size = ty.sizeof(p.comp).?; + if (vec_bytes % ty_size != 0) { + return p.errTok(.vec_size_not_multiple, tok); + } + const vec_size = vec_bytes / ty_size; + + const arr_ty = try p.arena.create(Type.Array); + arr_ty.* = .{ .elem = ty.*, .len = vec_size }; + ty.* = Type{ + .specifier = .vector, + .data = .{ .array = arr_ty }, + }; +} + +fn applyFormat(attr: Attribute, p: *Parser, ty: Type) !void { + // TODO validate + _ = ty; + try p.attr_application_buf.append(p.gpa, attr); +} diff --git a/deps/aro/Builtins.zig b/deps/aro/Builtins.zig new file mode 100644 index 000000000000..6fd29564c040 --- /dev/null +++ b/deps/aro/Builtins.zig @@ -0,0 +1,337 @@ +const std = @import("std"); +const Compilation = @import("Compilation.zig"); +const Type = @import("Type.zig"); +const BuiltinFunction = @import("builtins/BuiltinFunction.zig"); +const TypeDescription = @import("builtins/TypeDescription.zig"); +const target_util = @import("target.zig"); +const StringId = @import("StringInterner.zig").StringId; +const LangOpts = @import("LangOpts.zig"); +const Parser = @import("Parser.zig"); + +const Builtins = @This(); + +const Expanded = struct { + ty: Type, + builtin: BuiltinFunction, +}; + +const NameToTypeMap = std.StringHashMapUnmanaged(Type); + +_name_to_type_map: NameToTypeMap = .{}, + +pub fn deinit(b: *Builtins, gpa: std.mem.Allocator) void { + b._name_to_type_map.deinit(gpa); +} + +fn specForSize(comp: *const Compilation, size_bits: u32) Type.Builder.Specifier { + var ty = Type{ .specifier = .short }; + if (ty.sizeof(comp).? * 8 == size_bits) return .short; + + ty.specifier = .int; + if (ty.sizeof(comp).? * 8 == size_bits) return .int; + + ty.specifier = .long; + if (ty.sizeof(comp).? * 8 == size_bits) return .long; + + ty.specifier = .long_long; + if (ty.sizeof(comp).? * 8 == size_bits) return .long_long; + + unreachable; +} + +fn createType(desc: TypeDescription, it: *TypeDescription.TypeIterator, comp: *const Compilation, allocator: std.mem.Allocator) !Type { + var builder: Type.Builder = .{ .error_on_invalid = true }; + var require_native_int32 = false; + var require_native_int64 = false; + for (desc.prefix) |prefix| { + switch (prefix) { + .L => builder.combine(undefined, .long, 0) catch unreachable, + .LL => { + builder.combine(undefined, .long, 0) catch unreachable; + builder.combine(undefined, .long, 0) catch unreachable; + }, + .LLL => { + switch (builder.specifier) { + .none => builder.specifier = .int128, + .signed => builder.specifier = .sint128, + .unsigned => builder.specifier = .uint128, + else => unreachable, + } + }, + .Z => require_native_int32 = true, + .W => require_native_int64 = true, + .N => { + std.debug.assert(desc.spec == .i); + if (!target_util.isLP64(comp.target)) { + builder.combine(undefined, .long, 0) catch unreachable; + } + }, + .O => { + builder.combine(undefined, .long, 0) catch unreachable; + if (comp.target.os.tag != .opencl) { + builder.combine(undefined, .long, 0) catch unreachable; + } + }, + .S => builder.combine(undefined, .signed, 0) catch unreachable, + .U => builder.combine(undefined, .unsigned, 0) catch unreachable, + .I => { + // Todo: compile-time constant integer + }, + } + } + switch (desc.spec) { + .v => builder.combine(undefined, .void, 0) catch unreachable, + .b => builder.combine(undefined, .bool, 0) catch unreachable, + .c => builder.combine(undefined, .char, 0) catch unreachable, + .s => builder.combine(undefined, .short, 0) catch unreachable, + .i => { + if (require_native_int32) { + builder.specifier = specForSize(comp, 32); + } else if (require_native_int64) { + builder.specifier = specForSize(comp, 64); + } else { + switch (builder.specifier) { + .int128, .sint128, .uint128 => {}, + else => builder.combine(undefined, .int, 0) catch unreachable, + } + } + }, + .h => builder.combine(undefined, .fp16, 0) catch unreachable, + .x => { + // Todo: _Float16 + return .{ .specifier = .invalid }; + }, + .y => { + // Todo: __bf16 + return .{ .specifier = .invalid }; + }, + .f => builder.combine(undefined, .float, 0) catch unreachable, + .d => { + if (builder.specifier == .long_long) { + builder.specifier = .float128; + } else { + builder.combine(undefined, .double, 0) catch unreachable; + } + }, + .z => { + std.debug.assert(builder.specifier == .none); + builder.specifier = Type.Builder.fromType(comp.types.size); + }, + .w => { + std.debug.assert(builder.specifier == .none); + builder.specifier = Type.Builder.fromType(comp.types.wchar); + }, + .F => { + std.debug.assert(builder.specifier == .none); + builder.specifier = Type.Builder.fromType(comp.types.ns_constant_string.ty); + }, + .a => { + std.debug.assert(builder.specifier == .none); + std.debug.assert(desc.suffix.len == 0); + builder.specifier = Type.Builder.fromType(comp.types.va_list); + }, + .A => { + std.debug.assert(builder.specifier == .none); + std.debug.assert(desc.suffix.len == 0); + var va_list = comp.types.va_list; + if (va_list.isArray()) va_list.decayArray(); + builder.specifier = Type.Builder.fromType(va_list); + }, + .V => |element_count| { + std.debug.assert(desc.suffix.len == 0); + const child_desc = it.next().?; + const child_ty = try createType(child_desc, undefined, comp, allocator); + const arr_ty = try allocator.create(Type.Array); + arr_ty.* = .{ + .len = element_count, + .elem = child_ty, + }; + const vector_ty = .{ .specifier = .vector, .data = .{ .array = arr_ty } }; + builder.specifier = Type.Builder.fromType(vector_ty); + }, + .q => { + // Todo: scalable vector + return .{ .specifier = .invalid }; + }, + .E => { + // Todo: ext_vector (OpenCL vector) + return .{ .specifier = .invalid }; + }, + .X => |child| { + builder.combine(undefined, .complex, 0) catch unreachable; + switch (child) { + .float => builder.combine(undefined, .float, 0) catch unreachable, + .double => builder.combine(undefined, .double, 0) catch unreachable, + .longdouble => { + builder.combine(undefined, .long, 0) catch unreachable; + builder.combine(undefined, .double, 0) catch unreachable; + }, + } + }, + .Y => { + std.debug.assert(builder.specifier == .none); + std.debug.assert(desc.suffix.len == 0); + builder.specifier = Type.Builder.fromType(comp.types.ptrdiff); + }, + .P => { + std.debug.assert(builder.specifier == .none); + if (comp.types.file.specifier == .invalid) { + return comp.types.file; + } + builder.specifier = Type.Builder.fromType(comp.types.file); + }, + .J => { + std.debug.assert(builder.specifier == .none); + std.debug.assert(desc.suffix.len == 0); + if (comp.types.jmp_buf.specifier == .invalid) { + return comp.types.jmp_buf; + } + builder.specifier = Type.Builder.fromType(comp.types.jmp_buf); + }, + .SJ => { + std.debug.assert(builder.specifier == .none); + std.debug.assert(desc.suffix.len == 0); + if (comp.types.sigjmp_buf.specifier == .invalid) { + return comp.types.sigjmp_buf; + } + builder.specifier = Type.Builder.fromType(comp.types.sigjmp_buf); + }, + .K => { + std.debug.assert(builder.specifier == .none); + if (comp.types.ucontext_t.specifier == .invalid) { + return comp.types.ucontext_t; + } + builder.specifier = Type.Builder.fromType(comp.types.ucontext_t); + }, + .p => { + std.debug.assert(builder.specifier == .none); + std.debug.assert(desc.suffix.len == 0); + builder.specifier = Type.Builder.fromType(comp.types.pid_t); + }, + .@"!" => return .{ .specifier = .invalid }, + } + for (desc.suffix) |suffix| { + switch (suffix) { + .@"*" => |address_space| { + _ = address_space; // TODO: handle address space + const elem_ty = try allocator.create(Type); + elem_ty.* = builder.finish(undefined) catch unreachable; + const ty = Type{ + .specifier = .pointer, + .data = .{ .sub_type = elem_ty }, + }; + builder.qual = .{}; + builder.specifier = Type.Builder.fromType(ty); + }, + .C => builder.qual.@"const" = 0, + .D => builder.qual.@"volatile" = 0, + .R => builder.qual.restrict = 0, + } + } + return builder.finish(undefined) catch unreachable; +} + +fn createBuiltin(comp: *const Compilation, builtin: BuiltinFunction, type_arena: std.mem.Allocator) !Type { + var it = TypeDescription.TypeIterator.init(builtin.param_str); + + const ret_ty_desc = it.next().?; + if (ret_ty_desc.spec == .@"!") { + // Todo: handle target-dependent definition + } + const ret_ty = try createType(ret_ty_desc, &it, comp, type_arena); + var param_count: usize = 0; + var params: [BuiltinFunction.MaxParamCount]Type.Func.Param = undefined; + while (it.next()) |desc| : (param_count += 1) { + params[param_count] = .{ .name_tok = 0, .ty = try createType(desc, &it, comp, type_arena), .name = .empty }; + } + + const duped_params = try type_arena.dupe(Type.Func.Param, params[0..param_count]); + const func = try type_arena.create(Type.Func); + + func.* = .{ + .return_type = ret_ty, + .params = duped_params, + }; + return .{ + .specifier = if (builtin.isVarArgs()) .var_args_func else .func, + .data = .{ .func = func }, + }; +} + +/// Asserts that the builtin has already been created +pub fn lookup(b: *const Builtins, name: []const u8) Expanded { + @setEvalBranchQuota(10_000); + const builtin = BuiltinFunction.fromTag(std.meta.stringToEnum(BuiltinFunction.Tag, name).?); + const ty = b._name_to_type_map.get(name).?; + return .{ + .builtin = builtin, + .ty = ty, + }; +} + +pub fn getOrCreate(b: *Builtins, comp: *Compilation, name: []const u8, type_arena: std.mem.Allocator) !?Expanded { + const ty = b._name_to_type_map.get(name) orelse { + @setEvalBranchQuota(10_000); + const tag = std.meta.stringToEnum(BuiltinFunction.Tag, name) orelse return null; + const builtin = BuiltinFunction.fromTag(tag); + if (!comp.hasBuiltinFunction(builtin)) return null; + + try b._name_to_type_map.ensureUnusedCapacity(comp.gpa, 1); + const ty = try createBuiltin(comp, builtin, type_arena); + b._name_to_type_map.putAssumeCapacity(name, ty); + + return .{ + .builtin = builtin, + .ty = ty, + }; + }; + const builtin = BuiltinFunction.fromTag(std.meta.stringToEnum(BuiltinFunction.Tag, name).?); + return .{ + .builtin = builtin, + .ty = ty, + }; +} + +test "All builtins" { + var comp = Compilation.init(std.testing.allocator); + defer comp.deinit(); + _ = try comp.generateBuiltinMacros(); + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + + const type_arena = arena.allocator(); + + for (0..@typeInfo(BuiltinFunction.Tag).Enum.fields.len) |i| { + const tag: BuiltinFunction.Tag = @enumFromInt(i); + const name = @tagName(tag); + if (try comp.builtins.getOrCreate(&comp, name, type_arena)) |func_ty| { + const get_again = (try comp.builtins.getOrCreate(&comp, name, std.testing.failing_allocator)).?; + const found_by_lookup = comp.builtins.lookup(name); + try std.testing.expectEqual(func_ty.builtin.tag, get_again.builtin.tag); + try std.testing.expectEqual(func_ty.builtin.tag, found_by_lookup.builtin.tag); + } + } +} + +test "Allocation failures" { + const Test = struct { + fn testOne(allocator: std.mem.Allocator) !void { + var comp = Compilation.init(allocator); + defer comp.deinit(); + _ = try comp.generateBuiltinMacros(); + var arena = std.heap.ArenaAllocator.init(comp.gpa); + defer arena.deinit(); + + const type_arena = arena.allocator(); + + const num_builtins = 40; + for (0..num_builtins) |i| { + const tag: BuiltinFunction.Tag = @enumFromInt(i); + const name = @tagName(tag); + _ = try comp.builtins.getOrCreate(&comp, name, type_arena); + } + } + }; + + try std.testing.checkAllAllocationFailures(std.testing.allocator, Test.testOne, .{}); +} diff --git a/deps/aro/CharInfo.zig b/deps/aro/CharInfo.zig new file mode 100644 index 000000000000..f5935fd56ce1 --- /dev/null +++ b/deps/aro/CharInfo.zig @@ -0,0 +1,487 @@ +//! This module provides functions for classifying characters according to +//! various C standards. All classification routines *do not* consider +//! characters from the basic character set; it is assumed those will be +//! checked separately + +const assert = @import("std").debug.assert; + +/// C11 Standard Annex D +pub fn isC11IdChar(codepoint: u21) bool { + assert(codepoint > 0x7F); + return switch (codepoint) { + // 1 + 0x00A8, + 0x00AA, + 0x00AD, + 0x00AF, + 0x00B2...0x00B5, + 0x00B7...0x00BA, + 0x00BC...0x00BE, + 0x00C0...0x00D6, + 0x00D8...0x00F6, + 0x00F8...0x00FF, + + // 2 + 0x0100...0x167F, + 0x1681...0x180D, + 0x180F...0x1FFF, + + // 3 + 0x200B...0x200D, + 0x202A...0x202E, + 0x203F...0x2040, + 0x2054, + 0x2060...0x206F, + + // 4 + 0x2070...0x218F, + 0x2460...0x24FF, + 0x2776...0x2793, + 0x2C00...0x2DFF, + 0x2E80...0x2FFF, + + // 5 + 0x3004...0x3007, + 0x3021...0x302F, + 0x3031...0x303F, + + // 6 + 0x3040...0xD7FF, + + // 7 + 0xF900...0xFD3D, + 0xFD40...0xFDCF, + 0xFDF0...0xFE44, + 0xFE47...0xFFFD, + + // 8 + 0x10000...0x1FFFD, + 0x20000...0x2FFFD, + 0x30000...0x3FFFD, + 0x40000...0x4FFFD, + 0x50000...0x5FFFD, + 0x60000...0x6FFFD, + 0x70000...0x7FFFD, + 0x80000...0x8FFFD, + 0x90000...0x9FFFD, + 0xA0000...0xAFFFD, + 0xB0000...0xBFFFD, + 0xC0000...0xCFFFD, + 0xD0000...0xDFFFD, + 0xE0000...0xEFFFD, + => true, + else => false, + }; +} + +/// C99 Standard Annex D +pub fn isC99IdChar(codepoint: u21) bool { + assert(codepoint > 0x7F); + return switch (codepoint) { + // Latin + 0x00AA, + 0x00BA, + 0x00C0...0x00D6, + 0x00D8...0x00F6, + 0x00F8...0x01F5, + 0x01FA...0x0217, + 0x0250...0x02A8, + 0x1E00...0x1E9B, + 0x1EA0...0x1EF9, + 0x207F, + + // Greek + 0x0386, + 0x0388...0x038A, + 0x038C, + 0x038E...0x03A1, + 0x03A3...0x03CE, + 0x03D0...0x03D6, + 0x03DA, + 0x03DC, + 0x03DE, + 0x03E0, + 0x03E2...0x03F3, + 0x1F00...0x1F15, + 0x1F18...0x1F1D, + 0x1F20...0x1F45, + 0x1F48...0x1F4D, + 0x1F50...0x1F57, + 0x1F59, + 0x1F5B, + 0x1F5D, + 0x1F5F...0x1F7D, + 0x1F80...0x1FB4, + 0x1FB6...0x1FBC, + 0x1FC2...0x1FC4, + 0x1FC6...0x1FCC, + 0x1FD0...0x1FD3, + 0x1FD6...0x1FDB, + 0x1FE0...0x1FEC, + 0x1FF2...0x1FF4, + 0x1FF6...0x1FFC, + + // Cyrillic + 0x0401...0x040C, + 0x040E...0x044F, + 0x0451...0x045C, + 0x045E...0x0481, + 0x0490...0x04C4, + 0x04C7...0x04C8, + 0x04CB...0x04CC, + 0x04D0...0x04EB, + 0x04EE...0x04F5, + 0x04F8...0x04F9, + + // Armenian + 0x0531...0x0556, + 0x0561...0x0587, + + // Hebrew + 0x05B0...0x05B9, + 0x05BB...0x05BD, + 0x05BF, + 0x05C1...0x05C2, + 0x05D0...0x05EA, + 0x05F0...0x05F2, + + // Arabic + 0x0621...0x063A, + 0x0640...0x0652, + 0x0670...0x06B7, + 0x06BA...0x06BE, + 0x06C0...0x06CE, + 0x06D0...0x06DC, + 0x06E5...0x06E8, + 0x06EA...0x06ED, + + // Devanagari + 0x0901...0x0903, + 0x0905...0x0939, + 0x093E...0x094D, + 0x0950...0x0952, + 0x0958...0x0963, + + // Bengali + 0x0981...0x0983, + 0x0985...0x098C, + 0x098F...0x0990, + 0x0993...0x09A8, + 0x09AA...0x09B0, + 0x09B2, + 0x09B6...0x09B9, + 0x09BE...0x09C4, + 0x09C7...0x09C8, + 0x09CB...0x09CD, + 0x09DC...0x09DD, + 0x09DF...0x09E3, + 0x09F0...0x09F1, + + // Gurmukhi + 0x0A02, + 0x0A05...0x0A0A, + 0x0A0F...0x0A10, + 0x0A13...0x0A28, + 0x0A2A...0x0A30, + 0x0A32...0x0A33, + 0x0A35...0x0A36, + 0x0A38...0x0A39, + 0x0A3E...0x0A42, + 0x0A47...0x0A48, + 0x0A4B...0x0A4D, + 0x0A59...0x0A5C, + 0x0A5E, + 0x0A74, + + // Gujarati + 0x0A81...0x0A83, + 0x0A85...0x0A8B, + 0x0A8D, + 0x0A8F...0x0A91, + 0x0A93...0x0AA8, + 0x0AAA...0x0AB0, + 0x0AB2...0x0AB3, + 0x0AB5...0x0AB9, + 0x0ABD...0x0AC5, + 0x0AC7...0x0AC9, + 0x0ACB...0x0ACD, + 0x0AD0, + 0x0AE0, + + // Oriya + 0x0B01...0x0B03, + 0x0B05...0x0B0C, + 0x0B0F...0x0B10, + 0x0B13...0x0B28, + 0x0B2A...0x0B30, + 0x0B32...0x0B33, + 0x0B36...0x0B39, + 0x0B3E...0x0B43, + 0x0B47...0x0B48, + 0x0B4B...0x0B4D, + 0x0B5C...0x0B5D, + 0x0B5F...0x0B61, + + // Tamil + 0x0B82...0x0B83, + 0x0B85...0x0B8A, + 0x0B8E...0x0B90, + 0x0B92...0x0B95, + 0x0B99...0x0B9A, + 0x0B9C, + 0x0B9E...0x0B9F, + 0x0BA3...0x0BA4, + 0x0BA8...0x0BAA, + 0x0BAE...0x0BB5, + 0x0BB7...0x0BB9, + 0x0BBE...0x0BC2, + 0x0BC6...0x0BC8, + 0x0BCA...0x0BCD, + + // Telugu + 0x0C01...0x0C03, + 0x0C05...0x0C0C, + 0x0C0E...0x0C10, + 0x0C12...0x0C28, + 0x0C2A...0x0C33, + 0x0C35...0x0C39, + 0x0C3E...0x0C44, + 0x0C46...0x0C48, + 0x0C4A...0x0C4D, + 0x0C60...0x0C61, + + // Kannada + 0x0C82...0x0C83, + 0x0C85...0x0C8C, + 0x0C8E...0x0C90, + 0x0C92...0x0CA8, + 0x0CAA...0x0CB3, + 0x0CB5...0x0CB9, + 0x0CBE...0x0CC4, + 0x0CC6...0x0CC8, + 0x0CCA...0x0CCD, + 0x0CDE, + 0x0CE0...0x0CE1, + + // Malayalam + 0x0D02...0x0D03, + 0x0D05...0x0D0C, + 0x0D0E...0x0D10, + 0x0D12...0x0D28, + 0x0D2A...0x0D39, + 0x0D3E...0x0D43, + 0x0D46...0x0D48, + 0x0D4A...0x0D4D, + 0x0D60...0x0D61, + + // Thai (excluding digits 0x0E50...0x0E59; originally 0x0E01...0x0E3A and 0x0E40...0x0E5B + 0x0E01...0x0E3A, + 0x0E40...0x0E4F, + 0x0E5A...0x0E5B, + + // Lao + 0x0E81...0x0E82, + 0x0E84, + 0x0E87...0x0E88, + 0x0E8A, + 0x0E8D, + 0x0E94...0x0E97, + 0x0E99...0x0E9F, + 0x0EA1...0x0EA3, + 0x0EA5, + 0x0EA7, + 0x0EAA...0x0EAB, + 0x0EAD...0x0EAE, + 0x0EB0...0x0EB9, + 0x0EBB...0x0EBD, + 0x0EC0...0x0EC4, + 0x0EC6, + 0x0EC8...0x0ECD, + 0x0EDC...0x0EDD, + + // Tibetan + 0x0F00, + 0x0F18...0x0F19, + 0x0F35, + 0x0F37, + 0x0F39, + 0x0F3E...0x0F47, + 0x0F49...0x0F69, + 0x0F71...0x0F84, + 0x0F86...0x0F8B, + 0x0F90...0x0F95, + 0x0F97, + 0x0F99...0x0FAD, + 0x0FB1...0x0FB7, + 0x0FB9, + + // Georgian + 0x10A0...0x10C5, + 0x10D0...0x10F6, + + // Hiragana + 0x3041...0x3093, + 0x309B...0x309C, + + // Katakana + 0x30A1...0x30F6, + 0x30FB...0x30FC, + + // Bopomofo + 0x3105...0x312C, + + // CJK Unified Ideographs + 0x4E00...0x9FA5, + + // Hangul + 0xAC00...0xD7A3, + + // Digits + 0x0660...0x0669, + 0x06F0...0x06F9, + 0x0966...0x096F, + 0x09E6...0x09EF, + 0x0A66...0x0A6F, + 0x0AE6...0x0AEF, + 0x0B66...0x0B6F, + 0x0BE7...0x0BEF, + 0x0C66...0x0C6F, + 0x0CE6...0x0CEF, + 0x0D66...0x0D6F, + 0x0E50...0x0E59, + 0x0ED0...0x0ED9, + 0x0F20...0x0F33, + + // Special characters + 0x00B5, + 0x00B7, + 0x02B0...0x02B8, + 0x02BB, + 0x02BD...0x02C1, + 0x02D0...0x02D1, + 0x02E0...0x02E4, + 0x037A, + 0x0559, + 0x093D, + 0x0B3D, + 0x1FBE, + 0x203F...0x2040, + 0x2102, + 0x2107, + 0x210A...0x2113, + 0x2115, + 0x2118...0x211D, + 0x2124, + 0x2126, + 0x2128, + 0x212A...0x2131, + 0x2133...0x2138, + 0x2160...0x2182, + 0x3005...0x3007, + 0x3021...0x3029, + => true, + else => false, + }; +} + +/// C11 standard Annex D +pub fn isC11DisallowedInitialIdChar(codepoint: u21) bool { + assert(codepoint > 0x7F); + return switch (codepoint) { + 0x0300...0x036F, + 0x1DC0...0x1DFF, + 0x20D0...0x20FF, + 0xFE20...0xFE2F, + => true, + else => false, + }; +} + +/// These are "digit" characters; C99 disallows them as the first +/// character of an identifier +pub fn isC99DisallowedInitialIDChar(codepoint: u21) bool { + assert(codepoint > 0x7F); + return switch (codepoint) { + 0x0660...0x0669, + 0x06F0...0x06F9, + 0x0966...0x096F, + 0x09E6...0x09EF, + 0x0A66...0x0A6F, + 0x0AE6...0x0AEF, + 0x0B66...0x0B6F, + 0x0BE7...0x0BEF, + 0x0C66...0x0C6F, + 0x0CE6...0x0CEF, + 0x0D66...0x0D6F, + 0x0E50...0x0E59, + 0x0ED0...0x0ED9, + 0x0F20...0x0F33, + => true, + else => false, + }; +} + +pub fn isInvisible(codepoint: u21) bool { + assert(codepoint > 0x7F); + return switch (codepoint) { + 0x00ad, // SOFT HYPHEN + 0x200b, // ZERO WIDTH SPACE + 0x200c, // ZERO WIDTH NON-JOINER + 0x200d, // ZERO WIDTH JOINER + 0x2060, // WORD JOINER + 0x2061, // FUNCTION APPLICATION + 0x2062, // INVISIBLE TIMES + 0x2063, // INVISIBLE SEPARATOR + 0x2064, // INVISIBLE PLUS + 0xfeff, // ZERO WIDTH NO-BREAK SPACE + => true, + else => false, + }; +} + +/// Checks for identifier characters which resemble non-identifier characters +pub fn homoglyph(codepoint: u21) ?u21 { + assert(codepoint > 0x7F); + return switch (codepoint) { + 0x01c3 => '!', // LATIN LETTER RETROFLEX CLICK + 0x037e => ';', // GREEK QUESTION MARK + 0x2212 => '-', // MINUS SIGN + 0x2215 => '/', // DIVISION SLASH + 0x2216 => '\\', // SET MINUS + 0x2217 => '*', // ASTERISK OPERATOR + 0x2223 => '|', // DIVIDES + 0x2227 => '^', // LOGICAL AND + 0x2236 => ':', // RATIO + 0x223c => '~', // TILDE OPERATOR + 0xa789 => ':', // MODIFIER LETTER COLON + 0xff01 => '!', // FULLWIDTH EXCLAMATION MARK + 0xff03 => '#', // FULLWIDTH NUMBER SIGN + 0xff04 => '$', // FULLWIDTH DOLLAR SIGN + 0xff05 => '%', // FULLWIDTH PERCENT SIGN + 0xff06 => '&', // FULLWIDTH AMPERSAND + 0xff08 => '(', // FULLWIDTH LEFT PARENTHESIS + 0xff09 => ')', // FULLWIDTH RIGHT PARENTHESIS + 0xff0a => '*', // FULLWIDTH ASTERISK + 0xff0b => '+', // FULLWIDTH ASTERISK + 0xff0c => ',', // FULLWIDTH COMMA + 0xff0d => '-', // FULLWIDTH HYPHEN-MINUS + 0xff0e => '.', // FULLWIDTH FULL STOP + 0xff0f => '/', // FULLWIDTH SOLIDUS + 0xff1a => ':', // FULLWIDTH COLON + 0xff1b => ';', // FULLWIDTH SEMICOLON + 0xff1c => '<', // FULLWIDTH LESS-THAN SIGN + 0xff1d => '=', // FULLWIDTH EQUALS SIGN + 0xff1e => '>', // FULLWIDTH GREATER-THAN SIGN + 0xff1f => '?', // FULLWIDTH QUESTION MARK + 0xff20 => '@', // FULLWIDTH COMMERCIAL AT + 0xff3b => '[', // FULLWIDTH LEFT SQUARE BRACKET + 0xff3c => '\\', // FULLWIDTH REVERSE SOLIDUS + 0xff3d => ']', // FULLWIDTH RIGHT SQUARE BRACKET + 0xff3e => '^', // FULLWIDTH CIRCUMFLEX ACCENT + 0xff5b => '{', // FULLWIDTH LEFT CURLY BRACKET + 0xff5c => '|', // FULLWIDTH VERTICAL LINE + 0xff5d => '}', // FULLWIDTH RIGHT CURLY BRACKET + 0xff5e => '~', // FULLWIDTH TILDE + else => null, + }; +} diff --git a/deps/aro/CodeGen.zig b/deps/aro/CodeGen.zig new file mode 100644 index 000000000000..6febbbb9174d --- /dev/null +++ b/deps/aro/CodeGen.zig @@ -0,0 +1,1291 @@ +const std = @import("std"); +const Allocator = std.mem.Allocator; +const assert = std.debug.assert; +const BuiltinFunction = @import("builtins/BuiltinFunction.zig"); +const Compilation = @import("Compilation.zig"); +const Interner = @import("Interner.zig"); +const Ir = @import("Ir.zig"); +const Builder = Ir.Builder; +const StringId = @import("StringInterner.zig").StringId; +const Tree = @import("Tree.zig"); +const NodeIndex = Tree.NodeIndex; +const Type = @import("Type.zig"); +const Value = @import("Value.zig"); + +const CodeGen = @This(); + +const WipSwitch = struct { + cases: Cases = .{}, + default: ?Ir.Ref = null, + size: u64, + + const Cases = std.MultiArrayList(struct { + val: Interner.Ref, + label: Ir.Ref, + }); +}; + +const Symbol = struct { + name: StringId, + val: Ir.Ref, +}; + +const Error = Compilation.Error; + +tree: Tree, +comp: *Compilation, +builder: Builder, +node_tag: []const Tree.Tag, +node_data: []const Tree.Node.Data, +node_ty: []const Type, +wip_switch: *WipSwitch = undefined, +symbols: std.ArrayListUnmanaged(Symbol) = .{}, +ret_nodes: std.ArrayListUnmanaged(Ir.Inst.Phi.Input) = .{}, +phi_nodes: std.ArrayListUnmanaged(Ir.Inst.Phi.Input) = .{}, +record_elem_buf: std.ArrayListUnmanaged(Interner.Ref) = .{}, +cond_dummy_ty: ?Interner.Ref = null, +bool_invert: bool = false, +bool_end_label: Ir.Ref = .none, +cond_dummy_ref: Ir.Ref = undefined, +continue_label: Ir.Ref = undefined, +break_label: Ir.Ref = undefined, +return_label: Ir.Ref = undefined, + +pub fn generateTree(comp: *Compilation, tree: Tree) Compilation.Error!void { + var c = CodeGen{ + .builder = .{ + .gpa = comp.gpa, + .arena = std.heap.ArenaAllocator.init(comp.gpa), + }, + .tree = tree, + .comp = comp, + .node_tag = tree.nodes.items(.tag), + .node_data = tree.nodes.items(.data), + .node_ty = tree.nodes.items(.ty), + }; + defer c.symbols.deinit(c.comp.gpa); + defer c.ret_nodes.deinit(c.comp.gpa); + defer c.phi_nodes.deinit(c.comp.gpa); + defer c.record_elem_buf.deinit(c.comp.gpa); + defer c.builder.deinit(); + + const node_tags = tree.nodes.items(.tag); + for (tree.root_decls) |decl| { + c.builder.arena.deinit(); + c.builder.arena = std.heap.ArenaAllocator.init(comp.gpa); + + switch (node_tags[@intFromEnum(decl)]) { + .static_assert, + .typedef, + .struct_decl_two, + .union_decl_two, + .enum_decl_two, + .struct_decl, + .union_decl, + .enum_decl, + => {}, + + .fn_proto, + .static_fn_proto, + .inline_fn_proto, + .inline_static_fn_proto, + .extern_var, + .threadlocal_extern_var, + => {}, + + .fn_def, + .static_fn_def, + .inline_fn_def, + .inline_static_fn_def, + => c.genFn(decl) catch |err| switch (err) { + error.FatalError => return error.FatalError, + error.OutOfMemory => return error.OutOfMemory, + }, + + .@"var", + .static_var, + .threadlocal_var, + .threadlocal_static_var, + => c.genVar(decl) catch |err| switch (err) { + error.FatalError => return error.FatalError, + error.OutOfMemory => return error.OutOfMemory, + }, + else => unreachable, + } + } +} + +fn genType(c: *CodeGen, base_ty: Type) !Interner.Ref { + var key: Interner.Key = undefined; + const ty = base_ty.canonicalize(.standard); + switch (ty.specifier) { + .void => return .void, + .bool => return .i1, + .@"struct" => { + key = .{ + .record = .{ + .user_ptr = ty.data.record, + .elements = undefined, // Not needed for hash lookup. + }, + }; + if (c.builder.pool.has(key)) |some| return some; + const elem_buf_top = c.record_elem_buf.items.len; + defer c.record_elem_buf.items.len = elem_buf_top; + + for (ty.data.record.fields) |field| { + if (!field.isRegularField()) { + return c.comp.diag.fatalNoSrc("TODO lower struct bitfields", .{}); + } + // TODO handle padding bits + const field_ref = try c.genType(field.ty); + try c.record_elem_buf.append(c.builder.gpa, field_ref); + } + + key.record.elements = try c.builder.arena.allocator().dupe(Interner.Ref, c.record_elem_buf.items[elem_buf_top..]); + return c.builder.pool.put(c.builder.gpa, key); + }, + .@"union" => { + return c.comp.diag.fatalNoSrc("TODO lower union types", .{}); + }, + else => {}, + } + if (ty.isPtr()) return .ptr; + if (ty.isFunc()) return .func; + if (!ty.isReal()) return c.comp.diag.fatalNoSrc("TODO lower complex types", .{}); + if (ty.isInt()) { + const bits = ty.bitSizeof(c.comp).?; + key = .{ .int = @intCast(bits) }; + } else if (ty.isFloat()) { + const bits = ty.bitSizeof(c.comp).?; + key = .{ .float = @intCast(bits) }; + } else if (ty.isArray()) { + const elem = try c.genType(ty.elemType()); + key = .{ .array = .{ .child = elem, .len = ty.arrayLen().? } }; + } else if (ty.specifier == .vector) { + const elem = try c.genType(ty.elemType()); + key = .{ .vector = .{ .child = elem, .len = @intCast(ty.data.array.len) } }; + } else if (ty.is(.nullptr_t)) { + return c.comp.diag.fatalNoSrc("TODO lower nullptr_t", .{}); + } + return c.builder.pool.put(c.builder.gpa, key); +} + +fn genFn(c: *CodeGen, decl: NodeIndex) Error!void { + const name = c.tree.tokSlice(c.node_data[@intFromEnum(decl)].decl.name); + const func_ty = c.node_ty[@intFromEnum(decl)].canonicalize(.standard); + c.ret_nodes.items.len = 0; + + try c.builder.startFn(); + + for (func_ty.data.func.params) |param| { + // TODO handle calling convention here + const arg = try c.builder.addArg(try c.genType(param.ty)); + + const size: u32 = @intCast(param.ty.sizeof(c.comp).?); // TODO add error in parser + const @"align" = param.ty.alignof(c.comp); + const alloc = try c.builder.addAlloc(size, @"align"); + try c.builder.addStore(alloc, arg); + try c.symbols.append(c.comp.gpa, .{ .name = param.name, .val = alloc }); + } + + // Generate body + c.return_label = try c.builder.makeLabel("return"); + try c.genStmt(c.node_data[@intFromEnum(decl)].decl.node); + + // Relocate returns + if (c.ret_nodes.items.len == 0) { + _ = try c.builder.addInst(.ret, .{ .un = .none }, .noreturn); + } else if (c.ret_nodes.items.len == 1) { + c.builder.body.items.len -= 1; + _ = try c.builder.addInst(.ret, .{ .un = c.ret_nodes.items[0].value }, .noreturn); + } else { + try c.builder.startBlock(c.return_label); + const phi = try c.builder.addPhi(c.ret_nodes.items, try c.genType(func_ty.returnType())); + _ = try c.builder.addInst(.ret, .{ .un = phi }, .noreturn); + } + + var res = Ir{ + .pool = c.builder.pool, + .instructions = c.builder.instructions, + .arena = c.builder.arena.state, + .body = c.builder.body, + .strings = c.tree.strings, + }; + res.dump(c.builder.gpa, name, c.comp.diag.color, std.io.getStdOut().writer()) catch {}; +} + +fn addUn(c: *CodeGen, tag: Ir.Inst.Tag, operand: Ir.Ref, ty: Type) !Ir.Ref { + return c.builder.addInst(tag, .{ .un = operand }, try c.genType(ty)); +} + +fn addBin(c: *CodeGen, tag: Ir.Inst.Tag, lhs: Ir.Ref, rhs: Ir.Ref, ty: Type) !Ir.Ref { + return c.builder.addInst(tag, .{ .bin = .{ .lhs = lhs, .rhs = rhs } }, try c.genType(ty)); +} + +fn addBranch(c: *CodeGen, cond: Ir.Ref, true_label: Ir.Ref, false_label: Ir.Ref) !void { + if (true_label == c.bool_end_label) { + if (false_label == c.bool_end_label) { + try c.phi_nodes.append(c.comp.gpa, .{ .label = c.builder.current_label, .value = cond }); + return; + } + try c.addBoolPhi(!c.bool_invert); + } + if (false_label == c.bool_end_label) { + try c.addBoolPhi(c.bool_invert); + } + return c.builder.addBranch(cond, true_label, false_label); +} + +fn addBoolPhi(c: *CodeGen, value: bool) !void { + const val = try c.builder.addConstant(Value.int(@intFromBool(value)), .i1); + try c.phi_nodes.append(c.comp.gpa, .{ .label = c.builder.current_label, .value = val }); +} + +fn genStmt(c: *CodeGen, node: NodeIndex) Error!void { + _ = try c.genExpr(node); +} + +fn genExpr(c: *CodeGen, node: NodeIndex) Error!Ir.Ref { + std.debug.assert(node != .none); + const ty = c.node_ty[@intFromEnum(node)]; + if (c.tree.value_map.get(node)) |val| { + return c.builder.addConstant(val, try c.genType(ty)); + } + const data = c.node_data[@intFromEnum(node)]; + switch (c.node_tag[@intFromEnum(node)]) { + .enumeration_ref, + .bool_literal, + .int_literal, + .char_literal, + .float_literal, + .double_literal, + .imaginary_literal, + .string_literal_expr, + .alignof_expr, + => unreachable, // These should have an entry in value_map. + .fn_def, + .static_fn_def, + .inline_fn_def, + .inline_static_fn_def, + .invalid, + .threadlocal_var, + => unreachable, + .static_assert, + .fn_proto, + .static_fn_proto, + .inline_fn_proto, + .inline_static_fn_proto, + .extern_var, + .threadlocal_extern_var, + .typedef, + .struct_decl_two, + .union_decl_two, + .enum_decl_two, + .struct_decl, + .union_decl, + .enum_decl, + .enum_field_decl, + .record_field_decl, + .indirect_record_field_decl, + .struct_forward_decl, + .union_forward_decl, + .enum_forward_decl, + .null_stmt, + => {}, + .static_var, + .implicit_static_var, + .threadlocal_static_var, + => try c.genVar(node), // TODO + .@"var" => { + const size: u32 = @intCast(ty.sizeof(c.comp).?); // TODO add error in parser + const @"align" = ty.alignof(c.comp); + const alloc = try c.builder.addAlloc(size, @"align"); + const name = try c.comp.intern(c.tree.tokSlice(data.decl.name)); + try c.symbols.append(c.comp.gpa, .{ .name = name, .val = alloc }); + if (data.decl.node != .none) { + try c.genInitializer(alloc, ty, data.decl.node); + } + }, + .labeled_stmt => { + const label = try c.builder.makeLabel("label"); + try c.builder.startBlock(label); + try c.genStmt(data.decl.node); + }, + .compound_stmt_two => { + const old_sym_len = c.symbols.items.len; + c.symbols.items.len = old_sym_len; + + if (data.bin.lhs != .none) try c.genStmt(data.bin.lhs); + if (data.bin.rhs != .none) try c.genStmt(data.bin.rhs); + }, + .compound_stmt => { + const old_sym_len = c.symbols.items.len; + c.symbols.items.len = old_sym_len; + + for (c.tree.data[data.range.start..data.range.end]) |stmt| try c.genStmt(stmt); + }, + .if_then_else_stmt => { + const then_label = try c.builder.makeLabel("if.then"); + const else_label = try c.builder.makeLabel("if.else"); + const end_label = try c.builder.makeLabel("if.end"); + + try c.genBoolExpr(data.if3.cond, then_label, else_label); + + try c.builder.startBlock(then_label); + try c.genStmt(c.tree.data[data.if3.body]); // then + try c.builder.addJump(end_label); + + try c.builder.startBlock(else_label); + try c.genStmt(c.tree.data[data.if3.body + 1]); // else + + try c.builder.startBlock(end_label); + }, + .if_then_stmt => { + const then_label = try c.builder.makeLabel("if.then"); + const end_label = try c.builder.makeLabel("if.end"); + + try c.genBoolExpr(data.bin.lhs, then_label, end_label); + + try c.builder.startBlock(then_label); + try c.genStmt(data.bin.rhs); // then + try c.builder.startBlock(end_label); + }, + .switch_stmt => { + var wip_switch = WipSwitch{ + .size = c.node_ty[@intFromEnum(data.bin.lhs)].sizeof(c.comp).?, + }; + defer wip_switch.cases.deinit(c.builder.gpa); + + const old_wip_switch = c.wip_switch; + defer c.wip_switch = old_wip_switch; + c.wip_switch = &wip_switch; + + const old_break_label = c.break_label; + defer c.break_label = old_break_label; + const end_ref = try c.builder.makeLabel("switch.end"); + c.break_label = end_ref; + + const cond = try c.genExpr(data.bin.lhs); + const switch_index = c.builder.instructions.len; + _ = try c.builder.addInst(.@"switch", undefined, .noreturn); + + try c.genStmt(data.bin.rhs); // body + + const default_ref = wip_switch.default orelse end_ref; + try c.builder.startBlock(end_ref); + + const a = c.builder.arena.allocator(); + const switch_data = try a.create(Ir.Inst.Switch); + switch_data.* = .{ + .target = cond, + .cases_len = @intCast(wip_switch.cases.len), + .case_vals = (try a.dupe(Interner.Ref, wip_switch.cases.items(.val))).ptr, + .case_labels = (try a.dupe(Ir.Ref, wip_switch.cases.items(.label))).ptr, + .default = default_ref, + }; + c.builder.instructions.items(.data)[switch_index] = .{ .@"switch" = switch_data }; + }, + .case_stmt => { + const val = c.tree.value_map.get(data.bin.lhs).?; + const label = try c.builder.makeLabel("case"); + try c.builder.startBlock(label); + try c.wip_switch.cases.append(c.builder.gpa, .{ + .val = try c.builder.pool.put(c.builder.gpa, .{ .value = val }), + .label = label, + }); + try c.genStmt(data.bin.rhs); + }, + .default_stmt => { + const default = try c.builder.makeLabel("default"); + try c.builder.startBlock(default); + c.wip_switch.default = default; + try c.genStmt(data.un); + }, + .while_stmt => { + const old_break_label = c.break_label; + defer c.break_label = old_break_label; + + const old_continue_label = c.continue_label; + defer c.continue_label = old_continue_label; + + const cond_label = try c.builder.makeLabel("while.cond"); + const then_label = try c.builder.makeLabel("while.then"); + const end_label = try c.builder.makeLabel("while.end"); + + c.continue_label = cond_label; + c.break_label = end_label; + + try c.builder.startBlock(cond_label); + try c.genBoolExpr(data.bin.lhs, then_label, end_label); + + try c.builder.startBlock(then_label); + try c.genStmt(data.bin.rhs); + try c.builder.addJump(cond_label); + try c.builder.startBlock(end_label); + }, + .do_while_stmt => { + const old_break_label = c.break_label; + defer c.break_label = old_break_label; + + const old_continue_label = c.continue_label; + defer c.continue_label = old_continue_label; + + const then_label = try c.builder.makeLabel("do.then"); + const cond_label = try c.builder.makeLabel("do.cond"); + const end_label = try c.builder.makeLabel("do.end"); + + c.continue_label = cond_label; + c.break_label = end_label; + + try c.builder.startBlock(then_label); + try c.genStmt(data.bin.rhs); + + try c.builder.startBlock(cond_label); + try c.genBoolExpr(data.bin.lhs, then_label, end_label); + + try c.builder.startBlock(end_label); + }, + .for_decl_stmt => { + const old_break_label = c.break_label; + defer c.break_label = old_break_label; + + const old_continue_label = c.continue_label; + defer c.continue_label = old_continue_label; + + const for_decl = data.forDecl(c.tree); + for (for_decl.decls) |decl| try c.genStmt(decl); + + const then_label = try c.builder.makeLabel("for.then"); + var cond_label = then_label; + const cont_label = try c.builder.makeLabel("for.cont"); + const end_label = try c.builder.makeLabel("for.end"); + + c.continue_label = cont_label; + c.break_label = end_label; + + if (for_decl.cond != .none) { + cond_label = try c.builder.makeLabel("for.cond"); + try c.builder.startBlock(cond_label); + try c.genBoolExpr(for_decl.cond, then_label, end_label); + } + try c.builder.startBlock(then_label); + try c.genStmt(for_decl.body); + if (for_decl.incr != .none) { + _ = try c.genExpr(for_decl.incr); + } + try c.builder.addJump(cond_label); + try c.builder.startBlock(end_label); + }, + .forever_stmt => { + const old_break_label = c.break_label; + defer c.break_label = old_break_label; + + const old_continue_label = c.continue_label; + defer c.continue_label = old_continue_label; + + const then_label = try c.builder.makeLabel("for.then"); + const end_label = try c.builder.makeLabel("for.end"); + + c.continue_label = then_label; + c.break_label = end_label; + + try c.builder.startBlock(then_label); + try c.genStmt(data.un); + try c.builder.startBlock(end_label); + }, + .for_stmt => { + const old_break_label = c.break_label; + defer c.break_label = old_break_label; + + const old_continue_label = c.continue_label; + defer c.continue_label = old_continue_label; + + const for_stmt = data.forStmt(c.tree); + if (for_stmt.init != .none) _ = try c.genExpr(for_stmt.init); + + const then_label = try c.builder.makeLabel("for.then"); + var cond_label = then_label; + const cont_label = try c.builder.makeLabel("for.cont"); + const end_label = try c.builder.makeLabel("for.end"); + + c.continue_label = cont_label; + c.break_label = end_label; + + if (for_stmt.cond != .none) { + cond_label = try c.builder.makeLabel("for.cond"); + try c.builder.startBlock(cond_label); + try c.genBoolExpr(for_stmt.cond, then_label, end_label); + } + try c.builder.startBlock(then_label); + try c.genStmt(for_stmt.body); + if (for_stmt.incr != .none) { + _ = try c.genExpr(for_stmt.incr); + } + try c.builder.addJump(cond_label); + try c.builder.startBlock(end_label); + }, + .continue_stmt => try c.builder.addJump(c.continue_label), + .break_stmt => try c.builder.addJump(c.break_label), + .return_stmt => { + if (data.un != .none) { + const operand = try c.genExpr(data.un); + try c.ret_nodes.append(c.comp.gpa, .{ .value = operand, .label = c.builder.current_label }); + } + try c.builder.addJump(c.return_label); + }, + .implicit_return => { + if (data.return_zero) { + const operand = try c.builder.addConstant(Value.int(0), try c.genType(ty)); + try c.ret_nodes.append(c.comp.gpa, .{ .value = operand, .label = c.builder.current_label }); + } + // No need to emit a jump since implicit_return is always the last instruction. + }, + .case_range_stmt, + .goto_stmt, + .computed_goto_stmt, + .nullptr_literal, + => return c.comp.diag.fatalNoSrc("TODO CodeGen.genStmt {}\n", .{c.node_tag[@intFromEnum(node)]}), + .comma_expr => { + _ = try c.genExpr(data.bin.lhs); + return c.genExpr(data.bin.rhs); + }, + .assign_expr => { + const rhs = try c.genExpr(data.bin.rhs); + const lhs = try c.genLval(data.bin.lhs); + try c.builder.addStore(lhs, rhs); + return rhs; + }, + .mul_assign_expr => return c.genCompoundAssign(node, .mul), + .div_assign_expr => return c.genCompoundAssign(node, .div), + .mod_assign_expr => return c.genCompoundAssign(node, .mod), + .add_assign_expr => return c.genCompoundAssign(node, .add), + .sub_assign_expr => return c.genCompoundAssign(node, .sub), + .shl_assign_expr => return c.genCompoundAssign(node, .bit_shl), + .shr_assign_expr => return c.genCompoundAssign(node, .bit_shr), + .bit_and_assign_expr => return c.genCompoundAssign(node, .bit_and), + .bit_xor_assign_expr => return c.genCompoundAssign(node, .bit_xor), + .bit_or_assign_expr => return c.genCompoundAssign(node, .bit_or), + .bit_or_expr => return c.genBinOp(node, .bit_or), + .bit_xor_expr => return c.genBinOp(node, .bit_xor), + .bit_and_expr => return c.genBinOp(node, .bit_and), + .equal_expr => { + const cmp = try c.genComparison(node, .cmp_eq); + return c.addUn(.zext, cmp, ty); + }, + .not_equal_expr => { + const cmp = try c.genComparison(node, .cmp_ne); + return c.addUn(.zext, cmp, ty); + }, + .less_than_expr => { + const cmp = try c.genComparison(node, .cmp_lt); + return c.addUn(.zext, cmp, ty); + }, + .less_than_equal_expr => { + const cmp = try c.genComparison(node, .cmp_lte); + return c.addUn(.zext, cmp, ty); + }, + .greater_than_expr => { + const cmp = try c.genComparison(node, .cmp_gt); + return c.addUn(.zext, cmp, ty); + }, + .greater_than_equal_expr => { + const cmp = try c.genComparison(node, .cmp_gte); + return c.addUn(.zext, cmp, ty); + }, + .shl_expr => return c.genBinOp(node, .bit_shl), + .shr_expr => return c.genBinOp(node, .bit_shr), + .add_expr => { + if (ty.isPtr()) { + const lhs_ty = c.node_ty[@intFromEnum(data.bin.lhs)]; + if (lhs_ty.isPtr()) { + const ptr = try c.genExpr(data.bin.lhs); + const offset = try c.genExpr(data.bin.rhs); + const offset_ty = c.node_ty[@intFromEnum(data.bin.rhs)]; + return c.genPtrArithmetic(ptr, offset, offset_ty, ty); + } else { + const offset = try c.genExpr(data.bin.lhs); + const ptr = try c.genExpr(data.bin.rhs); + const offset_ty = lhs_ty; + return c.genPtrArithmetic(ptr, offset, offset_ty, ty); + } + } + return c.genBinOp(node, .add); + }, + .sub_expr => { + if (ty.isPtr()) { + const ptr = try c.genExpr(data.bin.lhs); + const offset = try c.genExpr(data.bin.rhs); + const offset_ty = c.node_ty[@intFromEnum(data.bin.rhs)]; + return c.genPtrArithmetic(ptr, offset, offset_ty, ty); + } + return c.genBinOp(node, .sub); + }, + .mul_expr => return c.genBinOp(node, .mul), + .div_expr => return c.genBinOp(node, .div), + .mod_expr => return c.genBinOp(node, .mod), + .addr_of_expr => return try c.genLval(data.un), + .deref_expr => { + const un_data = c.node_data[@intFromEnum(data.un)]; + if (c.node_tag[@intFromEnum(data.un)] == .implicit_cast and un_data.cast.kind == .function_to_pointer) { + return c.genExpr(data.un); + } + const operand = try c.genLval(data.un); + return c.addUn(.load, operand, ty); + }, + .plus_expr => return c.genExpr(data.un), + .negate_expr => { + const zero = try c.builder.addConstant(Value.int(0), try c.genType(ty)); + const operand = try c.genExpr(data.un); + return c.addBin(.sub, zero, operand, ty); + }, + .bit_not_expr => { + const operand = try c.genExpr(data.un); + return c.addUn(.bit_not, operand, ty); + }, + .bool_not_expr => { + const zero = try c.builder.addConstant(Value.int(0), try c.genType(ty)); + const operand = try c.genExpr(data.un); + return c.addBin(.cmp_ne, zero, operand, ty); + }, + .pre_inc_expr => { + const operand = try c.genLval(data.un); + const val = try c.addUn(.load, operand, ty); + const one = try c.builder.addConstant(Value.int(1), try c.genType(ty)); + const plus_one = try c.addBin(.add, val, one, ty); + try c.builder.addStore(operand, plus_one); + return plus_one; + }, + .pre_dec_expr => { + const operand = try c.genLval(data.un); + const val = try c.addUn(.load, operand, ty); + const one = try c.builder.addConstant(Value.int(1), try c.genType(ty)); + const plus_one = try c.addBin(.sub, val, one, ty); + try c.builder.addStore(operand, plus_one); + return plus_one; + }, + .post_inc_expr => { + const operand = try c.genLval(data.un); + const val = try c.addUn(.load, operand, ty); + const one = try c.builder.addConstant(Value.int(1), try c.genType(ty)); + const plus_one = try c.addBin(.add, val, one, ty); + try c.builder.addStore(operand, plus_one); + return val; + }, + .post_dec_expr => { + const operand = try c.genLval(data.un); + const val = try c.addUn(.load, operand, ty); + const one = try c.builder.addConstant(Value.int(1), try c.genType(ty)); + const plus_one = try c.addBin(.sub, val, one, ty); + try c.builder.addStore(operand, plus_one); + return val; + }, + .paren_expr => return c.genExpr(data.un), + .decl_ref_expr => unreachable, // Lval expression. + .explicit_cast, .implicit_cast => switch (data.cast.kind) { + .no_op => return c.genExpr(data.cast.operand), + .to_void => { + _ = try c.genExpr(data.cast.operand); + return .none; + }, + .lval_to_rval => { + const operand = try c.genLval(data.cast.operand); + return c.addUn(.load, operand, ty); + }, + .function_to_pointer, .array_to_pointer => { + return c.genLval(data.cast.operand); + }, + .int_cast => { + const operand = try c.genExpr(data.cast.operand); + const src_ty = c.node_ty[@intFromEnum(data.cast.operand)]; + const src_bits = src_ty.bitSizeof(c.comp).?; + const dest_bits = ty.bitSizeof(c.comp).?; + if (src_bits == dest_bits) { + return operand; + } else if (src_bits < dest_bits) { + if (src_ty.isUnsignedInt(c.comp)) + return c.addUn(.zext, operand, ty) + else + return c.addUn(.sext, operand, ty); + } else { + return c.addUn(.trunc, operand, ty); + } + }, + .bool_to_int => { + const operand = try c.genExpr(data.cast.operand); + return c.addUn(.zext, operand, ty); + }, + .pointer_to_bool, .int_to_bool, .float_to_bool => { + const lhs = try c.genExpr(data.cast.operand); + const rhs = try c.builder.addConstant(Value.int(0), try c.genType(c.node_ty[@intFromEnum(node)])); + return c.builder.addInst(.cmp_ne, .{ .bin = .{ .lhs = lhs, .rhs = rhs } }, .i1); + }, + .bitcast, + .pointer_to_int, + .bool_to_float, + .bool_to_pointer, + .int_to_float, + .complex_int_to_complex_float, + .int_to_pointer, + .float_to_int, + .complex_float_to_complex_int, + .complex_int_cast, + .complex_int_to_real, + .real_to_complex_int, + .float_cast, + .complex_float_cast, + .complex_float_to_real, + .real_to_complex_float, + .null_to_pointer, + .union_cast, + .vector_splat, + => return c.comp.diag.fatalNoSrc("TODO CodeGen gen CastKind {}\n", .{data.cast.kind}), + }, + .binary_cond_expr => { + if (c.tree.value_map.get(data.if3.cond)) |cond| { + if (cond.getBool()) { + c.cond_dummy_ref = try c.genExpr(data.if3.cond); + return c.genExpr(c.tree.data[data.if3.body]); // then + } else { + return c.genExpr(c.tree.data[data.if3.body + 1]); // else + } + } + + const then_label = try c.builder.makeLabel("ternary.then"); + const else_label = try c.builder.makeLabel("ternary.else"); + const end_label = try c.builder.makeLabel("ternary.end"); + const cond_ty = c.node_ty[@intFromEnum(data.if3.cond)]; + { + const old_cond_dummy_ty = c.cond_dummy_ty; + defer c.cond_dummy_ty = old_cond_dummy_ty; + c.cond_dummy_ty = try c.genType(cond_ty); + + try c.genBoolExpr(data.if3.cond, then_label, else_label); + } + + try c.builder.startBlock(then_label); + if (c.builder.instructions.items(.ty)[@intFromEnum(c.cond_dummy_ref)] == .i1) { + c.cond_dummy_ref = try c.addUn(.zext, c.cond_dummy_ref, cond_ty); + } + const then_val = try c.genExpr(c.tree.data[data.if3.body]); // then + try c.builder.addJump(end_label); + const then_exit = c.builder.current_label; + + try c.builder.startBlock(else_label); + const else_val = try c.genExpr(c.tree.data[data.if3.body + 1]); // else + const else_exit = c.builder.current_label; + + try c.builder.startBlock(end_label); + + var phi_buf: [2]Ir.Inst.Phi.Input = .{ + .{ .value = then_val, .label = then_exit }, + .{ .value = else_val, .label = else_exit }, + }; + return c.builder.addPhi(&phi_buf, try c.genType(ty)); + }, + .cond_dummy_expr => return c.cond_dummy_ref, + .cond_expr => { + if (c.tree.value_map.get(data.if3.cond)) |cond| { + if (cond.getBool()) { + return c.genExpr(c.tree.data[data.if3.body]); // then + } else { + return c.genExpr(c.tree.data[data.if3.body + 1]); // else + } + } + + const then_label = try c.builder.makeLabel("ternary.then"); + const else_label = try c.builder.makeLabel("ternary.else"); + const end_label = try c.builder.makeLabel("ternary.end"); + + try c.genBoolExpr(data.if3.cond, then_label, else_label); + + try c.builder.startBlock(then_label); + const then_val = try c.genExpr(c.tree.data[data.if3.body]); // then + try c.builder.addJump(end_label); + const then_exit = c.builder.current_label; + + try c.builder.startBlock(else_label); + const else_val = try c.genExpr(c.tree.data[data.if3.body + 1]); // else + const else_exit = c.builder.current_label; + + try c.builder.startBlock(end_label); + + var phi_buf: [2]Ir.Inst.Phi.Input = .{ + .{ .value = then_val, .label = then_exit }, + .{ .value = else_val, .label = else_exit }, + }; + return c.builder.addPhi(&phi_buf, try c.genType(ty)); + }, + .call_expr_one => if (data.bin.rhs == .none) { + return c.genCall(data.bin.lhs, &.{}, ty); + } else { + return c.genCall(data.bin.lhs, &.{data.bin.rhs}, ty); + }, + .call_expr => { + return c.genCall(c.tree.data[data.range.start], c.tree.data[data.range.start + 1 .. data.range.end], ty); + }, + .bool_or_expr => { + if (c.tree.value_map.get(data.bin.lhs)) |lhs| { + const cond = lhs.getBool(); + if (!cond) { + return c.builder.addConstant(Value.int(1), try c.genType(ty)); + } + return c.genExpr(data.bin.rhs); + } + + const false_label = try c.builder.makeLabel("bool_false"); + const exit_label = try c.builder.makeLabel("bool_exit"); + + const old_bool_end_label = c.bool_end_label; + defer c.bool_end_label = old_bool_end_label; + c.bool_end_label = exit_label; + + const phi_nodes_top = c.phi_nodes.items.len; + defer c.phi_nodes.items.len = phi_nodes_top; + + try c.genBoolExpr(data.bin.lhs, exit_label, false_label); + + try c.builder.startBlock(false_label); + try c.genBoolExpr(data.bin.rhs, exit_label, exit_label); + + try c.builder.startBlock(exit_label); + + const phi = try c.builder.addPhi(c.phi_nodes.items[phi_nodes_top..], .i1); + return c.addUn(.zext, phi, ty); + }, + .bool_and_expr => { + if (c.tree.value_map.get(data.bin.lhs)) |lhs| { + const cond = lhs.getBool(); + if (!cond) { + return c.builder.addConstant(Value.int(0), try c.genType(ty)); + } + return c.genExpr(data.bin.rhs); + } + + const true_label = try c.builder.makeLabel("bool_true"); + const exit_label = try c.builder.makeLabel("bool_exit"); + + const old_bool_end_label = c.bool_end_label; + defer c.bool_end_label = old_bool_end_label; + c.bool_end_label = exit_label; + + const phi_nodes_top = c.phi_nodes.items.len; + defer c.phi_nodes.items.len = phi_nodes_top; + + try c.genBoolExpr(data.bin.lhs, true_label, exit_label); + + try c.builder.startBlock(true_label); + try c.genBoolExpr(data.bin.rhs, exit_label, exit_label); + + try c.builder.startBlock(exit_label); + + const phi = try c.builder.addPhi(c.phi_nodes.items[phi_nodes_top..], .i1); + return c.addUn(.zext, phi, ty); + }, + .builtin_choose_expr => { + const cond = c.tree.value_map.get(data.if3.cond).?; + if (cond.getBool()) { + return c.genExpr(c.tree.data[data.if3.body]); + } else { + return c.genExpr(c.tree.data[data.if3.body + 1]); + } + }, + .generic_expr_one => { + const index = @intFromEnum(data.bin.rhs); + switch (c.node_tag[index]) { + .generic_association_expr, .generic_default_expr => { + return c.genExpr(c.node_data[index].un); + }, + else => unreachable, + } + }, + .generic_expr => { + const index = @intFromEnum(c.tree.data[data.range.start + 1]); + switch (c.node_tag[index]) { + .generic_association_expr, .generic_default_expr => { + return c.genExpr(c.node_data[index].un); + }, + else => unreachable, + } + }, + .generic_association_expr, .generic_default_expr => unreachable, + .stmt_expr => switch (c.node_tag[@intFromEnum(data.un)]) { + .compound_stmt_two => { + const old_sym_len = c.symbols.items.len; + c.symbols.items.len = old_sym_len; + + const stmt_data = c.node_data[@intFromEnum(data.un)]; + if (stmt_data.bin.rhs == .none) return c.genExpr(stmt_data.bin.lhs); + try c.genStmt(stmt_data.bin.lhs); + return c.genExpr(stmt_data.bin.rhs); + }, + .compound_stmt => { + const old_sym_len = c.symbols.items.len; + c.symbols.items.len = old_sym_len; + + const stmt_data = c.node_data[@intFromEnum(data.un)]; + for (c.tree.data[stmt_data.range.start .. stmt_data.range.end - 1]) |stmt| try c.genStmt(stmt); + return c.genExpr(c.tree.data[stmt_data.range.end]); + }, + else => unreachable, + }, + .builtin_call_expr_one => { + const name = c.tree.tokSlice(data.decl.name); + const builtin = c.comp.builtins.lookup(name).builtin; + if (data.decl.node == .none) { + return c.genBuiltinCall(builtin, &.{}, ty); + } else { + return c.genBuiltinCall(builtin, &.{data.decl.node}, ty); + } + }, + .builtin_call_expr => { + const name_node_idx = c.tree.data[data.range.start]; + const name = c.tree.tokSlice(@intFromEnum(name_node_idx)); + const builtin = c.comp.builtins.lookup(name).builtin; + return c.genBuiltinCall(builtin, c.tree.data[data.range.start + 1 .. data.range.end], ty); + }, + .addr_of_label, + .imag_expr, + .real_expr, + .sizeof_expr, + .special_builtin_call_one, + => return c.comp.diag.fatalNoSrc("TODO CodeGen.genExpr {}\n", .{c.node_tag[@intFromEnum(node)]}), + else => unreachable, // Not an expression. + } + return .none; +} + +fn genLval(c: *CodeGen, node: NodeIndex) Error!Ir.Ref { + std.debug.assert(node != .none); + assert(Tree.isLval(c.tree.nodes, c.tree.data, c.tree.value_map, node)); + const data = c.node_data[@intFromEnum(node)]; + switch (c.node_tag[@intFromEnum(node)]) { + .string_literal_expr => { + const val = c.tree.value_map.get(node).?; + return c.builder.addConstant(val, .ptr); + }, + .paren_expr => return c.genLval(data.un), + .decl_ref_expr => { + const slice = c.tree.tokSlice(data.decl_ref); + const name = try c.comp.intern(slice); + var i = c.symbols.items.len; + while (i > 0) { + i -= 1; + if (c.symbols.items[i].name == name) { + return c.symbols.items[i].val; + } + } + + const duped_name = try c.builder.arena.allocator().dupeZ(u8, slice); + const ref: Ir.Ref = @enumFromInt(c.builder.instructions.len); + try c.builder.instructions.append(c.builder.gpa, .{ .tag = .symbol, .data = .{ .label = duped_name }, .ty = .ptr }); + return ref; + }, + .deref_expr => return c.genExpr(data.un), + .compound_literal_expr => { + const ty = c.node_ty[@intFromEnum(node)]; + const size: u32 = @intCast(ty.sizeof(c.comp).?); // TODO add error in parser + const @"align" = ty.alignof(c.comp); + const alloc = try c.builder.addAlloc(size, @"align"); + try c.genInitializer(alloc, ty, data.un); + return alloc; + }, + .builtin_choose_expr => { + const cond = c.tree.value_map.get(data.if3.cond).?; + if (cond.getBool()) { + return c.genLval(c.tree.data[data.if3.body]); + } else { + return c.genLval(c.tree.data[data.if3.body + 1]); + } + }, + .member_access_expr, + .member_access_ptr_expr, + .array_access_expr, + => return c.comp.diag.fatalNoSrc("TODO CodeGen.genLval {}\n", .{c.node_tag[@intFromEnum(node)]}), + else => unreachable, // Not an lval expression. + } +} + +fn genBoolExpr(c: *CodeGen, base: NodeIndex, true_label: Ir.Ref, false_label: Ir.Ref) Error!void { + var node = base; + while (true) switch (c.node_tag[@intFromEnum(node)]) { + .paren_expr => { + node = c.node_data[@intFromEnum(node)].un; + }, + else => break, + }; + + const data = c.node_data[@intFromEnum(node)]; + switch (c.node_tag[@intFromEnum(node)]) { + .bool_or_expr => { + if (c.tree.value_map.get(data.bin.lhs)) |lhs| { + const cond = lhs.getBool(); + if (cond) { + if (true_label == c.bool_end_label) { + return c.addBoolPhi(!c.bool_invert); + } + return c.builder.addJump(true_label); + } + return c.genBoolExpr(data.bin.rhs, true_label, false_label); + } + + const new_false_label = try c.builder.makeLabel("bool_false"); + try c.genBoolExpr(data.bin.lhs, true_label, new_false_label); + try c.builder.startBlock(new_false_label); + + if (c.cond_dummy_ty) |ty| c.cond_dummy_ref = try c.builder.addConstant(Value.int(1), ty); + return c.genBoolExpr(data.bin.rhs, true_label, false_label); + }, + .bool_and_expr => { + if (c.tree.value_map.get(data.bin.lhs)) |lhs| { + const cond = lhs.getBool(); + if (!cond) { + if (false_label == c.bool_end_label) { + return c.addBoolPhi(c.bool_invert); + } + return c.builder.addJump(false_label); + } + return c.genBoolExpr(data.bin.rhs, true_label, false_label); + } + + const new_true_label = try c.builder.makeLabel("bool_true"); + try c.genBoolExpr(data.bin.lhs, new_true_label, false_label); + try c.builder.startBlock(new_true_label); + + if (c.cond_dummy_ty) |ty| c.cond_dummy_ref = try c.builder.addConstant(Value.int(1), ty); + return c.genBoolExpr(data.bin.rhs, true_label, false_label); + }, + .bool_not_expr => { + c.bool_invert = !c.bool_invert; + defer c.bool_invert = !c.bool_invert; + + if (c.cond_dummy_ty) |ty| c.cond_dummy_ref = try c.builder.addConstant(Value.int(0), ty); + return c.genBoolExpr(data.un, false_label, true_label); + }, + .equal_expr => { + const cmp = try c.genComparison(node, .cmp_eq); + if (c.cond_dummy_ty != null) c.cond_dummy_ref = cmp; + return c.addBranch(cmp, true_label, false_label); + }, + .not_equal_expr => { + const cmp = try c.genComparison(node, .cmp_ne); + if (c.cond_dummy_ty != null) c.cond_dummy_ref = cmp; + return c.addBranch(cmp, true_label, false_label); + }, + .less_than_expr => { + const cmp = try c.genComparison(node, .cmp_lt); + if (c.cond_dummy_ty != null) c.cond_dummy_ref = cmp; + return c.addBranch(cmp, true_label, false_label); + }, + .less_than_equal_expr => { + const cmp = try c.genComparison(node, .cmp_lte); + if (c.cond_dummy_ty != null) c.cond_dummy_ref = cmp; + return c.addBranch(cmp, true_label, false_label); + }, + .greater_than_expr => { + const cmp = try c.genComparison(node, .cmp_gt); + if (c.cond_dummy_ty != null) c.cond_dummy_ref = cmp; + return c.addBranch(cmp, true_label, false_label); + }, + .greater_than_equal_expr => { + const cmp = try c.genComparison(node, .cmp_gte); + if (c.cond_dummy_ty != null) c.cond_dummy_ref = cmp; + return c.addBranch(cmp, true_label, false_label); + }, + .explicit_cast, .implicit_cast => switch (data.cast.kind) { + .bool_to_int => { + const operand = try c.genExpr(data.cast.operand); + if (c.cond_dummy_ty != null) c.cond_dummy_ref = operand; + return c.addBranch(operand, true_label, false_label); + }, + else => {}, + }, + .binary_cond_expr => { + if (c.tree.value_map.get(data.if3.cond)) |cond| { + if (cond.getBool()) { + return c.genBoolExpr(c.tree.data[data.if3.body], true_label, false_label); // then + } else { + return c.genBoolExpr(c.tree.data[data.if3.body + 1], true_label, false_label); // else + } + } + + const new_false_label = try c.builder.makeLabel("ternary.else"); + try c.genBoolExpr(data.if3.cond, true_label, new_false_label); + + try c.builder.startBlock(new_false_label); + if (c.cond_dummy_ty) |ty| c.cond_dummy_ref = try c.builder.addConstant(Value.int(1), ty); + return c.genBoolExpr(c.tree.data[data.if3.body + 1], true_label, false_label); // else + }, + .cond_expr => { + if (c.tree.value_map.get(data.if3.cond)) |cond| { + if (cond.getBool()) { + return c.genBoolExpr(c.tree.data[data.if3.body], true_label, false_label); // then + } else { + return c.genBoolExpr(c.tree.data[data.if3.body + 1], true_label, false_label); // else + } + } + + const new_true_label = try c.builder.makeLabel("ternary.then"); + const new_false_label = try c.builder.makeLabel("ternary.else"); + try c.genBoolExpr(data.if3.cond, new_true_label, new_false_label); + + try c.builder.startBlock(new_true_label); + try c.genBoolExpr(c.tree.data[data.if3.body], true_label, false_label); // then + try c.builder.startBlock(new_false_label); + if (c.cond_dummy_ty) |ty| c.cond_dummy_ref = try c.builder.addConstant(Value.int(1), ty); + return c.genBoolExpr(c.tree.data[data.if3.body + 1], true_label, false_label); // else + }, + else => {}, + } + + if (c.tree.value_map.get(node)) |value| { + if (value.getBool()) { + if (true_label == c.bool_end_label) { + return c.addBoolPhi(!c.bool_invert); + } + return c.builder.addJump(true_label); + } else { + if (false_label == c.bool_end_label) { + return c.addBoolPhi(c.bool_invert); + } + return c.builder.addJump(false_label); + } + } + + // Assume int operand. + const lhs = try c.genExpr(node); + const rhs = try c.builder.addConstant(Value.int(0), try c.genType(c.node_ty[@intFromEnum(node)])); + const cmp = try c.builder.addInst(.cmp_ne, .{ .bin = .{ .lhs = lhs, .rhs = rhs } }, .i1); + if (c.cond_dummy_ty != null) c.cond_dummy_ref = cmp; + try c.addBranch(cmp, true_label, false_label); +} + +fn genBuiltinCall(c: *CodeGen, builtin: BuiltinFunction, arg_nodes: []const NodeIndex, ty: Type) Error!Ir.Ref { + _ = arg_nodes; + _ = ty; + return c.comp.diag.fatalNoSrc("TODO CodeGen.genBuiltinCall {s}\n", .{@tagName(builtin.tag)}); +} + +fn genCall(c: *CodeGen, fn_node: NodeIndex, arg_nodes: []const NodeIndex, ty: Type) Error!Ir.Ref { + // Detect direct calls. + const fn_ref = blk: { + const data = c.node_data[@intFromEnum(fn_node)]; + if (c.node_tag[@intFromEnum(fn_node)] != .implicit_cast or data.cast.kind != .function_to_pointer) { + break :blk try c.genExpr(fn_node); + } + + var cur = @intFromEnum(data.cast.operand); + while (true) switch (c.node_tag[cur]) { + .paren_expr, .addr_of_expr, .deref_expr => { + cur = @intFromEnum(c.node_data[cur].un); + }, + .implicit_cast => { + const cast = c.node_data[cur].cast; + if (cast.kind != .function_to_pointer) { + break :blk try c.genExpr(fn_node); + } + cur = @intFromEnum(cast.operand); + }, + .decl_ref_expr => { + const slice = c.tree.tokSlice(c.node_data[cur].decl_ref); + const name = try c.comp.intern(slice); + var i = c.symbols.items.len; + while (i > 0) { + i -= 1; + if (c.symbols.items[i].name == name) { + break :blk try c.genExpr(fn_node); + } + } + + const duped_name = try c.builder.arena.allocator().dupeZ(u8, slice); + const ref: Ir.Ref = @enumFromInt(c.builder.instructions.len); + try c.builder.instructions.append(c.builder.gpa, .{ .tag = .symbol, .data = .{ .label = duped_name }, .ty = .ptr }); + break :blk ref; + }, + else => break :blk try c.genExpr(fn_node), + }; + }; + + const args = try c.builder.arena.allocator().alloc(Ir.Ref, arg_nodes.len); + for (arg_nodes, args) |node, *arg| { + // TODO handle calling convention here + arg.* = try c.genExpr(node); + } + // TODO handle variadic call + const call = try c.builder.arena.allocator().create(Ir.Inst.Call); + call.* = .{ + .func = fn_ref, + .args_len = @intCast(args.len), + .args_ptr = args.ptr, + }; + return c.builder.addInst(.call, .{ .call = call }, try c.genType(ty)); +} + +fn genCompoundAssign(c: *CodeGen, node: NodeIndex, tag: Ir.Inst.Tag) Error!Ir.Ref { + const bin = c.node_data[@intFromEnum(node)].bin; + const ty = c.node_ty[@intFromEnum(node)]; + const rhs = try c.genExpr(bin.rhs); + const lhs = try c.genLval(bin.lhs); + const res = try c.addBin(tag, lhs, rhs, ty); + try c.builder.addStore(lhs, res); + return res; +} + +fn genBinOp(c: *CodeGen, node: NodeIndex, tag: Ir.Inst.Tag) Error!Ir.Ref { + const bin = c.node_data[@intFromEnum(node)].bin; + const ty = c.node_ty[@intFromEnum(node)]; + const lhs = try c.genExpr(bin.lhs); + const rhs = try c.genExpr(bin.rhs); + return c.addBin(tag, lhs, rhs, ty); +} + +fn genComparison(c: *CodeGen, node: NodeIndex, tag: Ir.Inst.Tag) Error!Ir.Ref { + const bin = c.node_data[@intFromEnum(node)].bin; + const lhs = try c.genExpr(bin.lhs); + const rhs = try c.genExpr(bin.rhs); + + return c.builder.addInst(tag, .{ .bin = .{ .lhs = lhs, .rhs = rhs } }, .i1); +} + +fn genPtrArithmetic(c: *CodeGen, ptr: Ir.Ref, offset: Ir.Ref, offset_ty: Type, ty: Type) Error!Ir.Ref { + // TODO consider adding a getelemptr instruction + const size = ty.elemType().sizeof(c.comp).?; + if (size == 1) { + return c.builder.addInst(.add, .{ .bin = .{ .lhs = ptr, .rhs = offset } }, try c.genType(ty)); + } + + const size_inst = try c.builder.addConstant(Value.int(size), try c.genType(offset_ty)); + const offset_inst = try c.addBin(.mul, offset, size_inst, offset_ty); + return c.addBin(.add, ptr, offset_inst, offset_ty); +} + +fn genInitializer(c: *CodeGen, ptr: Ir.Ref, dest_ty: Type, initializer: NodeIndex) Error!void { + std.debug.assert(initializer != .none); + switch (c.node_tag[@intFromEnum(initializer)]) { + .array_init_expr_two, + .array_init_expr, + .struct_init_expr_two, + .struct_init_expr, + .union_init_expr, + .array_filler_expr, + .default_init_expr, + => return c.comp.diag.fatalNoSrc("TODO CodeGen.genInitializer {}\n", .{c.node_tag[@intFromEnum(initializer)]}), + .string_literal_expr => { + const val = c.tree.value_map.get(initializer).?; + const str_ptr = try c.builder.addConstant(val, .ptr); + if (dest_ty.isArray()) { + return c.comp.diag.fatalNoSrc("TODO memcpy\n", .{}); + } else { + try c.builder.addStore(ptr, str_ptr); + } + }, + else => { + const res = try c.genExpr(initializer); + try c.builder.addStore(ptr, res); + }, + } +} + +fn genVar(c: *CodeGen, decl: NodeIndex) Error!void { + _ = decl; + return c.comp.diag.fatalNoSrc("TODO CodeGen.genVar\n", .{}); +} diff --git a/deps/aro/Codegen_legacy.zig b/deps/aro/Codegen_legacy.zig new file mode 100644 index 000000000000..b2bf3fe319ec --- /dev/null +++ b/deps/aro/Codegen_legacy.zig @@ -0,0 +1,108 @@ +const std = @import("std"); +const Compilation = @import("Compilation.zig"); +const Tree = @import("Tree.zig"); +const NodeIndex = Tree.NodeIndex; +const Object = @import("Object.zig"); +const x86_64 = @import("codegen/x86_64.zig"); + +const Codegen = @This(); + +comp: *Compilation, +tree: Tree, +obj: *Object, +node_tag: []const Tree.Tag, +node_data: []const Tree.Node.Data, + +pub const Error = Compilation.Error || error{CodegenFailed}; + +/// Generate tree to an object file. +/// Caller is responsible for flushing and freeing the returned object. +pub fn generateTree(comp: *Compilation, tree: Tree) Compilation.Error!*Object { + var c = Codegen{ + .comp = comp, + .tree = tree, + .obj = try Object.create(comp), + .node_tag = tree.nodes.items(.tag), + .node_data = tree.nodes.items(.data), + }; + errdefer c.obj.deinit(); + + const node_tags = tree.nodes.items(.tag); + for (tree.root_decls) |decl| { + switch (node_tags[@intFromEnum(decl)]) { + // these produce no code + .static_assert, + .typedef, + .struct_decl_two, + .union_decl_two, + .enum_decl_two, + .struct_decl, + .union_decl, + .enum_decl, + .struct_forward_decl, + .union_forward_decl, + .enum_forward_decl, + => {}, + + // define symbol + .fn_proto, + .static_fn_proto, + .inline_fn_proto, + .inline_static_fn_proto, + .extern_var, + .threadlocal_extern_var, + => { + const name = c.tree.tokSlice(c.node_data[@intFromEnum(decl)].decl.name); + _ = try c.obj.declareSymbol(.undefined, name, .Strong, .external, 0, 0); + }, + + // function definition + .fn_def, + .static_fn_def, + .inline_fn_def, + .inline_static_fn_def, + => c.genFn(decl) catch |err| switch (err) { + error.FatalError => return error.FatalError, + error.OutOfMemory => return error.OutOfMemory, + error.CodegenFailed => continue, + }, + + .@"var", + .static_var, + .threadlocal_var, + .threadlocal_static_var, + .implicit_static_var, + => c.genVar(decl) catch |err| switch (err) { + error.FatalError => return error.FatalError, + error.OutOfMemory => return error.OutOfMemory, + error.CodegenFailed => continue, + }, + + // TODO + .file_scope_asm => {}, + + else => unreachable, + } + } + + return c.obj; +} + +fn genFn(c: *Codegen, decl: NodeIndex) Error!void { + const section: Object.Section = .func; + const data = try c.obj.getSection(section); + const start_len = data.items.len; + switch (c.comp.target.cpu.arch) { + .x86_64 => try x86_64.genFn(c, decl, data), + else => unreachable, + } + const name = c.tree.tokSlice(c.node_data[@intFromEnum(decl)].decl.name); + _ = try c.obj.declareSymbol(section, name, .Strong, .func, start_len, data.items.len - start_len); +} + +fn genVar(c: *Codegen, decl: NodeIndex) Error!void { + switch (c.comp.target.cpu.arch) { + .x86_64 => try x86_64.genVar(c, decl), + else => unreachable, + } +} diff --git a/deps/aro/Compilation.zig b/deps/aro/Compilation.zig new file mode 100644 index 000000000000..a3b60e212296 --- /dev/null +++ b/deps/aro/Compilation.zig @@ -0,0 +1,1491 @@ +const std = @import("std"); +const assert = std.debug.assert; +const mem = std.mem; +const Allocator = mem.Allocator; +const EpochSeconds = std.time.epoch.EpochSeconds; +const Builtins = @import("Builtins.zig"); +const Diagnostics = @import("Diagnostics.zig"); +const LangOpts = @import("LangOpts.zig"); +const Source = @import("Source.zig"); +const Tokenizer = @import("Tokenizer.zig"); +const Token = Tokenizer.Token; +const Type = @import("Type.zig"); +const Pragma = @import("Pragma.zig"); +const StringInterner = @import("StringInterner.zig"); +const record_layout = @import("record_layout.zig"); +const target_util = @import("target.zig"); +const BuiltinFunction = @import("builtins/BuiltinFunction.zig"); + +const Compilation = @This(); + +pub const Error = error{ + /// A fatal error has ocurred and compilation has stopped. + FatalError, +} || Allocator.Error; + +pub const bit_int_max_bits = 128; +const path_buf_stack_limit = 1024; + +/// Environment variables used during compilation / linking. +pub const Environment = struct { + /// Directory to use for temporary files + /// TODO: not implemented yet + tmpdir: ?[]const u8 = null, + + /// PATH environment variable used to search for programs + path: ?[]const u8 = null, + + /// Directories to try when searching for subprograms. + /// TODO: not implemented yet + compiler_path: ?[]const u8 = null, + + /// Directories to try when searching for special linker files, if compiling for the native target + /// TODO: not implemented yet + library_path: ?[]const u8 = null, + + /// List of directories to be searched as if specified with -I, but after any paths given with -I options on the command line + /// Used regardless of the language being compiled + /// TODO: not implemented yet + cpath: ?[]const u8 = null, + + /// List of directories to be searched as if specified with -I, but after any paths given with -I options on the command line + /// Used if the language being compiled is C + /// TODO: not implemented yet + c_include_path: ?[]const u8 = null, + + /// UNIX timestamp to be used instead of the current date and time in the __DATE__ and __TIME__ macros + source_date_epoch: ?[]const u8 = null, + + /// Load all of the environment variables using the std.process API. Do not use if using Aro as a shared library on Linux without libc + /// See https://github.com/ziglang/zig/issues/4524 + /// Assumes that `self` has been default-initialized + pub fn loadAll(self: *Environment, allocator: std.mem.Allocator) !void { + errdefer self.deinit(allocator); + + inline for (@typeInfo(@TypeOf(self.*)).Struct.fields) |field| { + std.debug.assert(@field(self, field.name) == null); + + var env_var_buf: [field.name.len]u8 = undefined; + const env_var_name = std.ascii.upperString(&env_var_buf, field.name); + const val: ?[]const u8 = std.process.getEnvVarOwned(allocator, env_var_name) catch |err| switch (err) { + error.OutOfMemory => |e| return e, + error.EnvironmentVariableNotFound => null, + error.InvalidUtf8 => null, + }; + @field(self, field.name) = val; + } + } + + /// Use this only if environment slices were allocated with `allocator` (such as via `loadAll`) + pub fn deinit(self: *Environment, allocator: std.mem.Allocator) void { + inline for (@typeInfo(@TypeOf(self.*)).Struct.fields) |field| { + if (@field(self, field.name)) |slice| { + allocator.free(slice); + } + } + self.* = undefined; + } +}; + +gpa: Allocator, +environment: Environment = .{}, +sources: std.StringArrayHashMap(Source), +diag: Diagnostics, +include_dirs: std.ArrayList([]const u8), +system_include_dirs: std.ArrayList([]const u8), +target: std.Target = @import("builtin").target, +pragma_handlers: std.StringArrayHashMap(*Pragma), +langopts: LangOpts = .{}, +generated_buf: std.ArrayList(u8), +builtins: Builtins = .{}, +types: struct { + wchar: Type = undefined, + ptrdiff: Type = undefined, + size: Type = undefined, + va_list: Type = undefined, + pid_t: Type = undefined, + ns_constant_string: struct { + ty: Type = undefined, + record: Type.Record = undefined, + fields: [4]Type.Record.Field = undefined, + int_ty: Type = .{ .specifier = .int, .qual = .{ .@"const" = true } }, + char_ty: Type = .{ .specifier = .char, .qual = .{ .@"const" = true } }, + } = .{}, + file: Type = .{ .specifier = .invalid }, + jmp_buf: Type = .{ .specifier = .invalid }, + sigjmp_buf: Type = .{ .specifier = .invalid }, + ucontext_t: Type = .{ .specifier = .invalid }, + intmax: Type = .{ .specifier = .invalid }, + intptr: Type = .{ .specifier = .invalid }, + int16: Type = .{ .specifier = .invalid }, + int64: Type = .{ .specifier = .invalid }, +} = .{}, +/// Mapping from Source.Id to byte offset of first non-utf8 byte +invalid_utf8_locs: std.AutoHashMapUnmanaged(Source.Id, u32) = .{}, +string_interner: StringInterner = .{}, + +pub fn init(gpa: Allocator) Compilation { + return .{ + .gpa = gpa, + .sources = std.StringArrayHashMap(Source).init(gpa), + .diag = Diagnostics.init(gpa), + .include_dirs = std.ArrayList([]const u8).init(gpa), + .system_include_dirs = std.ArrayList([]const u8).init(gpa), + .pragma_handlers = std.StringArrayHashMap(*Pragma).init(gpa), + .generated_buf = std.ArrayList(u8).init(gpa), + }; +} + +pub fn deinit(comp: *Compilation) void { + for (comp.pragma_handlers.values()) |pragma| { + pragma.deinit(pragma, comp); + } + for (comp.sources.values()) |source| { + comp.gpa.free(source.path); + comp.gpa.free(source.buf); + comp.gpa.free(source.splice_locs); + } + comp.sources.deinit(); + comp.diag.deinit(); + comp.include_dirs.deinit(); + for (comp.system_include_dirs.items) |path| comp.gpa.free(path); + comp.system_include_dirs.deinit(); + comp.pragma_handlers.deinit(); + comp.generated_buf.deinit(); + comp.builtins.deinit(comp.gpa); + comp.invalid_utf8_locs.deinit(comp.gpa); + comp.string_interner.deinit(comp.gpa); +} + +pub fn intern(comp: *Compilation, str: []const u8) !StringInterner.StringId { + return comp.string_interner.intern(comp.gpa, str); +} + +pub fn getSourceEpoch(self: *const Compilation, max: i64) !?i64 { + const provided = self.environment.source_date_epoch orelse return null; + const parsed = std.fmt.parseInt(i64, provided, 10) catch return error.InvalidEpoch; + if (parsed < 0 or parsed > max) return error.InvalidEpoch; + return parsed; +} + +/// Dec 31 9999 23:59:59 +const max_timestamp = 253402300799; + +fn getTimestamp(comp: *Compilation) !u47 { + const provided: ?i64 = comp.getSourceEpoch(max_timestamp) catch blk: { + try comp.diag.add(.{ + .tag = .invalid_source_epoch, + .loc = .{ .id = .unused, .byte_offset = 0, .line = 0 }, + }, &.{}); + break :blk null; + }; + const timestamp = provided orelse std.time.timestamp(); + return @intCast(std.math.clamp(timestamp, 0, max_timestamp)); +} + +fn generateDateAndTime(w: anytype, timestamp: u47) !void { + const epoch_seconds = EpochSeconds{ .secs = timestamp }; + const epoch_day = epoch_seconds.getEpochDay(); + const day_seconds = epoch_seconds.getDaySeconds(); + const year_day = epoch_day.calculateYearDay(); + const month_day = year_day.calculateMonthDay(); + + const month_names = [_][]const u8{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + std.debug.assert(std.time.epoch.Month.jan.numeric() == 1); + + const month_name = month_names[month_day.month.numeric() - 1]; + try w.print("#define __DATE__ \"{s} {d: >2} {d}\"\n", .{ + month_name, + month_day.day_index + 1, + year_day.year, + }); + try w.print("#define __TIME__ \"{d:0>2}:{d:0>2}:{d:0>2}\"\n", .{ + day_seconds.getHoursIntoDay(), + day_seconds.getMinutesIntoHour(), + day_seconds.getSecondsIntoMinute(), + }); + + const day_names = [_][]const u8{ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; + // days since Thu Oct 1 1970 + const day_name = day_names[@intCast((epoch_day.day + 3) % 7)]; + try w.print("#define __TIMESTAMP__ \"{s} {s} {d: >2} {d:0>2}:{d:0>2}:{d:0>2} {d}\"\n", .{ + day_name, + month_name, + month_day.day_index + 1, + day_seconds.getHoursIntoDay(), + day_seconds.getMinutesIntoHour(), + day_seconds.getSecondsIntoMinute(), + year_day.year, + }); +} + +/// Generate builtin macros that will be available to each source file. +pub fn generateBuiltinMacros(comp: *Compilation) !Source { + try comp.generateBuiltinTypes(); + + var buf = std.ArrayList(u8).init(comp.gpa); + defer buf.deinit(); + const w = buf.writer(); + + // standard macros + try w.writeAll( + \\#define __VERSION__ "Aro + ++ @import("lib.zig").version_str ++ "\"\n" ++ + \\#define __Aro__ + \\#define __STDC__ 1 + \\#define __STDC_HOSTED__ 1 + \\#define __STDC_NO_ATOMICS__ 1 + \\#define __STDC_NO_COMPLEX__ 1 + \\#define __STDC_NO_THREADS__ 1 + \\#define __STDC_NO_VLA__ 1 + \\ + ); + if (comp.langopts.standard.StdCVersionMacro()) |stdc_version| { + try w.print("#define __STDC_VERSION__ {s}\n", .{stdc_version}); + } + const ptr_width = comp.target.ptrBitWidth(); + + // os macros + switch (comp.target.os.tag) { + .linux => try w.writeAll( + \\#define linux 1 + \\#define __linux 1 + \\#define __linux__ 1 + \\ + ), + .windows => if (ptr_width == 32) try w.writeAll( + \\#define WIN32 1 + \\#define _WIN32 1 + \\#define __WIN32 1 + \\#define __WIN32__ 1 + \\ + ) else try w.writeAll( + \\#define WIN32 1 + \\#define WIN64 1 + \\#define _WIN32 1 + \\#define _WIN64 1 + \\#define __WIN32 1 + \\#define __WIN64 1 + \\#define __WIN32__ 1 + \\#define __WIN64__ 1 + \\ + ), + .freebsd => try w.print("#define __FreeBSD__ {d}\n", .{comp.target.os.version_range.semver.min.major}), + .netbsd => try w.writeAll("#define __NetBSD__ 1\n"), + .openbsd => try w.writeAll("#define __OpenBSD__ 1\n"), + .dragonfly => try w.writeAll("#define __DragonFly__ 1\n"), + .solaris => try w.writeAll( + \\#define sun 1 + \\#define __sun 1 + \\ + ), + .macos => try w.writeAll( + \\#define __APPLE__ 1 + \\#define __MACH__ 1 + \\ + ), + else => {}, + } + + // unix and other additional os macros + switch (comp.target.os.tag) { + .freebsd, + .netbsd, + .openbsd, + .dragonfly, + .linux, + => try w.writeAll( + \\#define unix 1 + \\#define __unix 1 + \\#define __unix__ 1 + \\ + ), + else => {}, + } + if (comp.target.abi == .android) { + try w.writeAll("#define __ANDROID__ 1\n"); + } + + // architecture macros + switch (comp.target.cpu.arch) { + .x86_64 => try w.writeAll( + \\#define __amd64__ 1 + \\#define __amd64 1 + \\#define __x86_64 1 + \\#define __x86_64__ 1 + \\ + ), + .x86 => try w.writeAll( + \\#define i386 1 + \\#define __i386 1 + \\#define __i386__ 1 + \\ + ), + .mips, + .mipsel, + .mips64, + .mips64el, + => try w.writeAll( + \\#define __mips__ 1 + \\#define mips 1 + \\ + ), + .powerpc, + .powerpcle, + => try w.writeAll( + \\#define __powerpc__ 1 + \\#define __POWERPC__ 1 + \\#define __ppc__ 1 + \\#define __PPC__ 1 + \\#define _ARCH_PPC 1 + \\ + ), + .powerpc64, + .powerpc64le, + => try w.writeAll( + \\#define __powerpc 1 + \\#define __powerpc__ 1 + \\#define __powerpc64__ 1 + \\#define __POWERPC__ 1 + \\#define __ppc__ 1 + \\#define __ppc64__ 1 + \\#define __PPC__ 1 + \\#define __PPC64__ 1 + \\#define _ARCH_PPC 1 + \\#define _ARCH_PPC64 1 + \\ + ), + .sparc64 => try w.writeAll( + \\#define __sparc__ 1 + \\#define __sparc 1 + \\#define __sparc_v9__ 1 + \\ + ), + .sparc, .sparcel => try w.writeAll( + \\#define __sparc__ 1 + \\#define __sparc 1 + \\ + ), + .arm, .armeb => try w.writeAll( + \\#define __arm__ 1 + \\#define __arm 1 + \\ + ), + .thumb, .thumbeb => try w.writeAll( + \\#define __arm__ 1 + \\#define __arm 1 + \\#define __thumb__ 1 + \\ + ), + .aarch64, .aarch64_be => try w.writeAll("#define __aarch64__ 1\n"), + .msp430 => try w.writeAll( + \\#define MSP430 1 + \\#define __MSP430__ 1 + \\ + ), + else => {}, + } + + if (comp.target.os.tag != .windows) switch (ptr_width) { + 64 => try w.writeAll( + \\#define _LP64 1 + \\#define __LP64__ 1 + \\ + ), + 32 => try w.writeAll("#define _ILP32 1\n"), + else => {}, + }; + + try w.writeAll( + \\#define __ORDER_LITTLE_ENDIAN__ 1234 + \\#define __ORDER_BIG_ENDIAN__ 4321 + \\#define __ORDER_PDP_ENDIAN__ 3412 + \\ + ); + if (comp.target.cpu.arch.endian() == .Little) try w.writeAll( + \\#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ + \\#define __LITTLE_ENDIAN__ 1 + \\ + ) else try w.writeAll( + \\#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__ + \\#define __BIG_ENDIAN__ 1 + \\ + ); + + // timestamps + const timestamp = try comp.getTimestamp(); + try generateDateAndTime(w, timestamp); + + // types + if (comp.getCharSignedness() == .unsigned) try w.writeAll("#define __CHAR_UNSIGNED__ 1\n"); + try w.writeAll("#define __CHAR_BIT__ 8\n"); + + // int maxs + try comp.generateIntWidth(w, "BOOL", .{ .specifier = .bool }); + try comp.generateIntMaxAndWidth(w, "SCHAR", .{ .specifier = .schar }); + try comp.generateIntMaxAndWidth(w, "SHRT", .{ .specifier = .short }); + try comp.generateIntMaxAndWidth(w, "INT", .{ .specifier = .int }); + try comp.generateIntMaxAndWidth(w, "LONG", .{ .specifier = .long }); + try comp.generateIntMaxAndWidth(w, "LONG_LONG", .{ .specifier = .long_long }); + try comp.generateIntMaxAndWidth(w, "WCHAR", comp.types.wchar); + // try comp.generateIntMax(w, "WINT", comp.types.wchar); + try comp.generateIntMaxAndWidth(w, "INTMAX", comp.types.intmax); + try comp.generateIntMaxAndWidth(w, "SIZE", comp.types.size); + try comp.generateIntMaxAndWidth(w, "UINTMAX", comp.types.intmax.makeIntegerUnsigned()); + try comp.generateIntMaxAndWidth(w, "PTRDIFF", comp.types.ptrdiff); + try comp.generateIntMaxAndWidth(w, "INTPTR", comp.types.intptr); + try comp.generateIntMaxAndWidth(w, "UINTPTR", comp.types.intptr.makeIntegerUnsigned()); + + // int widths + try w.print("#define __BITINT_MAXWIDTH__ {d}\n", .{bit_int_max_bits}); + + // sizeof types + try comp.generateSizeofType(w, "__SIZEOF_FLOAT__", .{ .specifier = .float }); + try comp.generateSizeofType(w, "__SIZEOF_DOUBLE__", .{ .specifier = .double }); + try comp.generateSizeofType(w, "__SIZEOF_LONG_DOUBLE__", .{ .specifier = .long_double }); + try comp.generateSizeofType(w, "__SIZEOF_SHORT__", .{ .specifier = .short }); + try comp.generateSizeofType(w, "__SIZEOF_INT__", .{ .specifier = .int }); + try comp.generateSizeofType(w, "__SIZEOF_LONG__", .{ .specifier = .long }); + try comp.generateSizeofType(w, "__SIZEOF_LONG_LONG__", .{ .specifier = .long_long }); + try comp.generateSizeofType(w, "__SIZEOF_POINTER__", .{ .specifier = .pointer }); + try comp.generateSizeofType(w, "__SIZEOF_PTRDIFF_T__", comp.types.ptrdiff); + try comp.generateSizeofType(w, "__SIZEOF_SIZE_T__", comp.types.size); + try comp.generateSizeofType(w, "__SIZEOF_WCHAR_T__", comp.types.wchar); + // try comp.generateSizeofType(w, "__SIZEOF_WINT_T__", .{ .specifier = .pointer }); + + // various int types + const mapper = comp.string_interner.getSlowTypeMapper(); + try generateTypeMacro(w, mapper, "__INTPTR_TYPE__", comp.types.intptr, comp.langopts); + try generateTypeMacro(w, mapper, "__UINTPTR_TYPE__", comp.types.intptr.makeIntegerUnsigned(), comp.langopts); + + try generateTypeMacro(w, mapper, "__INTMAX_TYPE__", comp.types.intmax, comp.langopts); + try comp.generateSuffixMacro("__INTMAX", w, comp.types.intptr); + + try generateTypeMacro(w, mapper, "__UINTMAX_TYPE__", comp.types.intmax.makeIntegerUnsigned(), comp.langopts); + try comp.generateSuffixMacro("__UINTMAX", w, comp.types.intptr.makeIntegerUnsigned()); + + try generateTypeMacro(w, mapper, "__PTRDIFF_TYPE__", comp.types.ptrdiff, comp.langopts); + try generateTypeMacro(w, mapper, "__SIZE_TYPE__", comp.types.size, comp.langopts); + try generateTypeMacro(w, mapper, "__WCHAR_TYPE__", comp.types.wchar, comp.langopts); + + try comp.generateExactWidthTypes(w, mapper); + + if (target_util.FPSemantics.halfPrecisionType(comp.target)) |half| { + try generateFloatMacros(w, "FLT16", half, "F16"); + } + try generateFloatMacros(w, "FLT", target_util.FPSemantics.forType(.float, comp.target), "F"); + try generateFloatMacros(w, "DBL", target_util.FPSemantics.forType(.double, comp.target), ""); + try generateFloatMacros(w, "LDBL", target_util.FPSemantics.forType(.longdouble, comp.target), "L"); + + // TODO: clang treats __FLT_EVAL_METHOD__ as a special-cased macro because evaluating it within a scope + // where `#pragma clang fp eval_method(X)` has been called produces an error diagnostic. + const flt_eval_method = comp.langopts.fp_eval_method orelse target_util.defaultFpEvalMethod(comp.target); + try w.print("#define __FLT_EVAL_METHOD__ {d}\n", .{@intFromEnum(flt_eval_method)}); + + try w.writeAll( + \\#define __FLT_RADIX__ 2 + \\#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ + \\ + ); + + return comp.addSourceFromBuffer("", buf.items); +} + +fn generateFloatMacros(w: anytype, prefix: []const u8, semantics: target_util.FPSemantics, ext: []const u8) !void { + const denormMin = semantics.chooseValue( + []const u8, + .{ + "5.9604644775390625e-8", + "1.40129846e-45", + "4.9406564584124654e-324", + "3.64519953188247460253e-4951", + "4.94065645841246544176568792868221e-324", + "6.47517511943802511092443895822764655e-4966", + }, + ); + const digits = semantics.chooseValue(i32, .{ 3, 6, 15, 18, 31, 33 }); + const decimalDigits = semantics.chooseValue(i32, .{ 5, 9, 17, 21, 33, 36 }); + const epsilon = semantics.chooseValue( + []const u8, + .{ + "9.765625e-4", + "1.19209290e-7", + "2.2204460492503131e-16", + "1.08420217248550443401e-19", + "4.94065645841246544176568792868221e-324", + "1.92592994438723585305597794258492732e-34", + }, + ); + const mantissaDigits = semantics.chooseValue(i32, .{ 11, 24, 53, 64, 106, 113 }); + + const min10Exp = semantics.chooseValue(i32, .{ -4, -37, -307, -4931, -291, -4931 }); + const max10Exp = semantics.chooseValue(i32, .{ 4, 38, 308, 4932, 308, 4932 }); + + const minExp = semantics.chooseValue(i32, .{ -13, -125, -1021, -16381, -968, -16381 }); + const maxExp = semantics.chooseValue(i32, .{ 16, 128, 1024, 16384, 1024, 16384 }); + + const min = semantics.chooseValue( + []const u8, + .{ + "6.103515625e-5", + "1.17549435e-38", + "2.2250738585072014e-308", + "3.36210314311209350626e-4932", + "2.00416836000897277799610805135016e-292", + "3.36210314311209350626267781732175260e-4932", + }, + ); + const max = semantics.chooseValue( + []const u8, + .{ + "6.5504e+4", + "3.40282347e+38", + "1.7976931348623157e+308", + "1.18973149535723176502e+4932", + "1.79769313486231580793728971405301e+308", + "1.18973149535723176508575932662800702e+4932", + }, + ); + + var defPrefix = std.BoundedArray(u8, 32).init(0) catch unreachable; + defPrefix.writer().print("__{s}_", .{prefix}) catch return error.OutOfMemory; + + const prefix_slice = defPrefix.constSlice(); + + try w.print("#define {s}DENORM_MIN__ {s}{s}\n", .{ prefix_slice, denormMin, ext }); + try w.print("#define {s}HAS_DENORM__\n", .{prefix_slice}); + try w.print("#define {s}DIG__ {d}\n", .{ prefix_slice, digits }); + try w.print("#define {s}DECIMAL_DIG__ {d}\n", .{ prefix_slice, decimalDigits }); + + try w.print("#define {s}EPSILON__ {s}{s}\n", .{ prefix_slice, epsilon, ext }); + try w.print("#define {s}HAS_INFINITY__\n", .{prefix_slice}); + try w.print("#define {s}HAS_QUIET_NAN__\n", .{prefix_slice}); + try w.print("#define {s}MANT_DIG__ {d}\n", .{ prefix_slice, mantissaDigits }); + + try w.print("#define {s}MAX_10_EXP__ {d}\n", .{ prefix_slice, max10Exp }); + try w.print("#define {s}MAX_EXP__ {d}\n", .{ prefix_slice, maxExp }); + try w.print("#define {s}MAX__ {s}{s}\n", .{ prefix_slice, max, ext }); + + try w.print("#define {s}MIN_10_EXP__ ({d})\n", .{ prefix_slice, min10Exp }); + try w.print("#define {s}MIN_EXP__ ({d})\n", .{ prefix_slice, minExp }); + try w.print("#define {s}MIN__ {s}{s}\n", .{ prefix_slice, min, ext }); +} + +fn generateTypeMacro(w: anytype, mapper: StringInterner.TypeMapper, name: []const u8, ty: Type, langopts: LangOpts) !void { + try w.print("#define {s} ", .{name}); + try ty.print(mapper, langopts, w); + try w.writeByte('\n'); +} + +fn generateBuiltinTypes(comp: *Compilation) !void { + const os = comp.target.os.tag; + const wchar: Type = switch (comp.target.cpu.arch) { + .xcore => .{ .specifier = .uchar }, + .ve, .msp430 => .{ .specifier = .uint }, + .arm, .armeb, .thumb, .thumbeb => .{ + .specifier = if (os != .windows and os != .netbsd and os != .openbsd) .uint else .int, + }, + .aarch64, .aarch64_be, .aarch64_32 => .{ + .specifier = if (!os.isDarwin() and os != .netbsd) .uint else .int, + }, + .x86_64, .x86 => .{ .specifier = if (os == .windows) .ushort else .int }, + else => .{ .specifier = .int }, + }; + + const ptr_width = comp.target.ptrBitWidth(); + const ptrdiff = if (os == .windows and ptr_width == 64) + Type{ .specifier = .long_long } + else switch (ptr_width) { + 16 => Type{ .specifier = .int }, + 32 => Type{ .specifier = .int }, + 64 => Type{ .specifier = .long }, + else => unreachable, + }; + + const size = if (os == .windows and ptr_width == 64) + Type{ .specifier = .ulong_long } + else switch (ptr_width) { + 16 => Type{ .specifier = .uint }, + 32 => Type{ .specifier = .uint }, + 64 => Type{ .specifier = .ulong }, + else => unreachable, + }; + + const va_list = try comp.generateVaListType(); + + const pid_t: Type = switch (os) { + .haiku => .{ .specifier = .long }, + // Todo: pid_t is required to "a signed integer type"; are there any systems + // on which it is `short int`? + else => .{ .specifier = .int }, + }; + + const intmax = target_util.intMaxType(comp.target); + const intptr = target_util.intPtrType(comp.target); + const int16 = target_util.int16Type(comp.target); + const int64 = target_util.int64Type(comp.target); + + comp.types = .{ + .wchar = wchar, + .ptrdiff = ptrdiff, + .size = size, + .va_list = va_list, + .pid_t = pid_t, + .intmax = intmax, + .intptr = intptr, + .int16 = int16, + .int64 = int64, + }; + + try comp.generateNsConstantStringType(); +} + +fn intSize(comp: *const Compilation, specifier: Type.Specifier) u64 { + const ty = Type{ .specifier = specifier }; + return ty.sizeof(comp).?; +} + +fn generateExactWidthTypes(comp: *const Compilation, w: anytype, mapper: StringInterner.TypeMapper) !void { + try comp.generateExactWidthType(w, mapper, .schar); + + if (comp.intSize(.short) > comp.intSize(.char)) { + try comp.generateExactWidthType(w, mapper, .short); + } + + if (comp.intSize(.int) > comp.intSize(.short)) { + try comp.generateExactWidthType(w, mapper, .int); + } + + if (comp.intSize(.long) > comp.intSize(.int)) { + try comp.generateExactWidthType(w, mapper, .long); + } + + if (comp.intSize(.long_long) > comp.intSize(.long)) { + try comp.generateExactWidthType(w, mapper, .long_long); + } + + try comp.generateExactWidthType(w, mapper, .uchar); + try comp.generateExactWidthIntMax(w, .uchar); + try comp.generateExactWidthIntMax(w, .schar); + + if (comp.intSize(.short) > comp.intSize(.char)) { + try comp.generateExactWidthType(w, mapper, .ushort); + try comp.generateExactWidthIntMax(w, .ushort); + try comp.generateExactWidthIntMax(w, .short); + } + + if (comp.intSize(.int) > comp.intSize(.short)) { + try comp.generateExactWidthType(w, mapper, .uint); + try comp.generateExactWidthIntMax(w, .uint); + try comp.generateExactWidthIntMax(w, .int); + } + + if (comp.intSize(.long) > comp.intSize(.int)) { + try comp.generateExactWidthType(w, mapper, .ulong); + try comp.generateExactWidthIntMax(w, .ulong); + try comp.generateExactWidthIntMax(w, .long); + } + + if (comp.intSize(.long_long) > comp.intSize(.long)) { + try comp.generateExactWidthType(w, mapper, .ulong_long); + try comp.generateExactWidthIntMax(w, .ulong_long); + try comp.generateExactWidthIntMax(w, .long_long); + } +} + +fn generateFmt(comp: *const Compilation, prefix: []const u8, w: anytype, ty: Type) !void { + const unsigned = ty.isUnsignedInt(comp); + const modifier = ty.formatModifier(); + const formats = if (unsigned) "ouxX" else "di"; + for (formats) |c| { + try w.print("#define {s}_FMT{c}__ \"{s}{c}\"\n", .{ prefix, c, modifier, c }); + } +} + +fn generateSuffixMacro(comp: *const Compilation, prefix: []const u8, w: anytype, ty: Type) !void { + return w.print("#define {s}_C_SUFFIX__ {s}\n", .{ prefix, ty.intValueSuffix(comp) }); +} + +/// Generate the following for ty: +/// Name macro (e.g. #define __UINT32_TYPE__ unsigned int) +/// Format strings (e.g. #define __UINT32_FMTu__ "u") +/// Suffix macro (e.g. #define __UINT32_C_SUFFIX__ U) +fn generateExactWidthType(comp: *const Compilation, w: anytype, mapper: StringInterner.TypeMapper, specifier: Type.Specifier) !void { + var ty = Type{ .specifier = specifier }; + const width = 8 * ty.sizeof(comp).?; + const unsigned = ty.isUnsignedInt(comp); + + if (width == 16) { + ty = if (unsigned) comp.types.int16.makeIntegerUnsigned() else comp.types.int16; + } else if (width == 64) { + ty = if (unsigned) comp.types.int64.makeIntegerUnsigned() else comp.types.int64; + } + + var prefix = std.BoundedArray(u8, 16).init(0) catch unreachable; + prefix.writer().print("{s}{d}", .{ if (unsigned) "__UINT" else "__INT", width }) catch return error.OutOfMemory; + + { + const len = prefix.len; + defer prefix.resize(len) catch unreachable; // restoring previous size + prefix.appendSliceAssumeCapacity("_TYPE__"); + try generateTypeMacro(w, mapper, prefix.constSlice(), ty, comp.langopts); + } + + try comp.generateFmt(prefix.constSlice(), w, ty); + try comp.generateSuffixMacro(prefix.constSlice(), w, ty); +} + +pub fn hasHalfPrecisionFloatABI(comp: *const Compilation) bool { + return comp.langopts.allow_half_args_and_returns or target_util.hasHalfPrecisionFloatABI(comp.target); +} + +fn generateNsConstantStringType(comp: *Compilation) !void { + comp.types.ns_constant_string.record = .{ + .name = try comp.intern("__NSConstantString_tag"), + .fields = &comp.types.ns_constant_string.fields, + .field_attributes = null, + .type_layout = undefined, + }; + const const_int_ptr = Type{ .specifier = .pointer, .data = .{ .sub_type = &comp.types.ns_constant_string.int_ty } }; + const const_char_ptr = Type{ .specifier = .pointer, .data = .{ .sub_type = &comp.types.ns_constant_string.char_ty } }; + + comp.types.ns_constant_string.fields[0] = .{ .name = try comp.intern("isa"), .ty = const_int_ptr }; + comp.types.ns_constant_string.fields[1] = .{ .name = try comp.intern("flags"), .ty = .{ .specifier = .int } }; + comp.types.ns_constant_string.fields[2] = .{ .name = try comp.intern("str"), .ty = const_char_ptr }; + comp.types.ns_constant_string.fields[3] = .{ .name = try comp.intern("length"), .ty = .{ .specifier = .long } }; + comp.types.ns_constant_string.ty = .{ .specifier = .@"struct", .data = .{ .record = &comp.types.ns_constant_string.record } }; + record_layout.compute(&comp.types.ns_constant_string.record, comp.types.ns_constant_string.ty, comp, null); +} + +fn generateVaListType(comp: *Compilation) !Type { + const Kind = enum { char_ptr, void_ptr, aarch64_va_list, x86_64_va_list }; + const kind: Kind = switch (comp.target.cpu.arch) { + .aarch64 => switch (comp.target.os.tag) { + .windows => @as(Kind, .char_ptr), + .ios, .macos, .tvos, .watchos => .char_ptr, + else => .aarch64_va_list, + }, + .sparc, .wasm32, .wasm64, .bpfel, .bpfeb, .riscv32, .riscv64, .avr, .spirv32, .spirv64 => .void_ptr, + .powerpc => switch (comp.target.os.tag) { + .ios, .macos, .tvos, .watchos, .aix => @as(Kind, .char_ptr), + else => return Type{ .specifier = .void }, // unknown + }, + .x86, .msp430 => .char_ptr, + .x86_64 => switch (comp.target.os.tag) { + .windows => @as(Kind, .char_ptr), + else => .x86_64_va_list, + }, + else => return Type{ .specifier = .void }, // unknown + }; + + // TODO this might be bad? + const arena = comp.diag.arena.allocator(); + + var ty: Type = undefined; + switch (kind) { + .char_ptr => ty = .{ .specifier = .char }, + .void_ptr => ty = .{ .specifier = .void }, + .aarch64_va_list => { + const record_ty = try arena.create(Type.Record); + record_ty.* = .{ + .name = try comp.intern("__va_list_tag"), + .fields = try arena.alloc(Type.Record.Field, 5), + .field_attributes = null, + .type_layout = undefined, // computed below + }; + const void_ty = try arena.create(Type); + void_ty.* = .{ .specifier = .void }; + const void_ptr = Type{ .specifier = .pointer, .data = .{ .sub_type = void_ty } }; + record_ty.fields[0] = .{ .name = try comp.intern("__stack"), .ty = void_ptr }; + record_ty.fields[1] = .{ .name = try comp.intern("__gr_top"), .ty = void_ptr }; + record_ty.fields[2] = .{ .name = try comp.intern("__vr_top"), .ty = void_ptr }; + record_ty.fields[3] = .{ .name = try comp.intern("__gr_offs"), .ty = .{ .specifier = .int } }; + record_ty.fields[4] = .{ .name = try comp.intern("__vr_offs"), .ty = .{ .specifier = .int } }; + ty = .{ .specifier = .@"struct", .data = .{ .record = record_ty } }; + record_layout.compute(record_ty, ty, comp, null); + }, + .x86_64_va_list => { + const record_ty = try arena.create(Type.Record); + record_ty.* = .{ + .name = try comp.intern("__va_list_tag"), + .fields = try arena.alloc(Type.Record.Field, 4), + .field_attributes = null, + .type_layout = undefined, // computed below + }; + const void_ty = try arena.create(Type); + void_ty.* = .{ .specifier = .void }; + const void_ptr = Type{ .specifier = .pointer, .data = .{ .sub_type = void_ty } }; + record_ty.fields[0] = .{ .name = try comp.intern("gp_offset"), .ty = .{ .specifier = .uint } }; + record_ty.fields[1] = .{ .name = try comp.intern("fp_offset"), .ty = .{ .specifier = .uint } }; + record_ty.fields[2] = .{ .name = try comp.intern("overflow_arg_area"), .ty = void_ptr }; + record_ty.fields[3] = .{ .name = try comp.intern("reg_save_area"), .ty = void_ptr }; + ty = .{ .specifier = .@"struct", .data = .{ .record = record_ty } }; + record_layout.compute(record_ty, ty, comp, null); + }, + } + if (kind == .char_ptr or kind == .void_ptr) { + const elem_ty = try arena.create(Type); + elem_ty.* = ty; + ty = Type{ .specifier = .pointer, .data = .{ .sub_type = elem_ty } }; + } else { + const arr_ty = try arena.create(Type.Array); + arr_ty.* = .{ .len = 1, .elem = ty }; + ty = Type{ .specifier = .array, .data = .{ .array = arr_ty } }; + } + + return ty; +} + +fn generateIntMax(comp: *const Compilation, w: anytype, name: []const u8, ty: Type) !void { + const bit_count: u8 = @intCast(ty.sizeof(comp).? * 8); + const unsigned = ty.isUnsignedInt(comp); + const max = if (bit_count == 128) + @as(u128, if (unsigned) std.math.maxInt(u128) else std.math.maxInt(u128)) + else + ty.maxInt(comp); + try w.print("#define __{s}_MAX__ {d}{s}\n", .{ name, max, ty.intValueSuffix(comp) }); +} + +fn generateExactWidthIntMax(comp: *const Compilation, w: anytype, specifier: Type.Specifier) !void { + var ty = Type{ .specifier = specifier }; + const bit_count: u8 = @intCast(ty.sizeof(comp).? * 8); + const unsigned = ty.isUnsignedInt(comp); + + if (bit_count == 64) { + ty = if (unsigned) comp.types.int64.makeIntegerUnsigned() else comp.types.int64; + } + + var name = std.BoundedArray(u8, 6).init(0) catch unreachable; + name.writer().print("{s}{d}", .{ if (unsigned) "UINT" else "INT", bit_count }) catch return error.OutOfMemory; + + return comp.generateIntMax(w, name.constSlice(), ty); +} + +fn generateIntWidth(comp: *Compilation, w: anytype, name: []const u8, ty: Type) !void { + try w.print("#define __{s}_WIDTH__ {d}\n", .{ name, 8 * ty.sizeof(comp).? }); +} + +fn generateIntMaxAndWidth(comp: *Compilation, w: anytype, name: []const u8, ty: Type) !void { + try comp.generateIntMax(w, name, ty); + try comp.generateIntWidth(w, name, ty); +} + +fn generateSizeofType(comp: *Compilation, w: anytype, name: []const u8, ty: Type) !void { + try w.print("#define {s} {d}\n", .{ name, ty.sizeof(comp).? }); +} + +pub fn nextLargestIntSameSign(comp: *const Compilation, ty: Type) ?Type { + assert(ty.isInt()); + const specifiers = if (ty.isUnsignedInt(comp)) + [_]Type.Specifier{ .short, .int, .long, .long_long } + else + [_]Type.Specifier{ .ushort, .uint, .ulong, .ulong_long }; + const size = ty.sizeof(comp).?; + for (specifiers) |specifier| { + const candidate = Type{ .specifier = specifier }; + if (candidate.sizeof(comp).? > size) return candidate; + } + return null; +} + +/// If `enum E { ... }` syntax has a fixed underlying integer type regardless of the presence of +/// __attribute__((packed)) or the range of values of the corresponding enumerator constants, +/// specify it here. +/// TODO: likely incomplete +pub fn fixedEnumTagSpecifier(comp: *const Compilation) ?Type.Specifier { + switch (comp.langopts.emulate) { + .msvc => return .int, + .clang => if (comp.target.os.tag == .windows) return .int, + .gcc => {}, + } + return null; +} + +pub fn getCharSignedness(comp: *const Compilation) std.builtin.Signedness { + return comp.langopts.char_signedness_override orelse comp.target.charSignedness(); +} + +pub fn defineSystemIncludes(comp: *Compilation, aro_dir: []const u8) !void { + var stack_fallback = std.heap.stackFallback(path_buf_stack_limit, comp.gpa); + const allocator = stack_fallback.get(); + var search_path = aro_dir; + while (std.fs.path.dirname(search_path)) |dirname| : (search_path = dirname) { + var base_dir = std.fs.cwd().openDir(dirname, .{}) catch continue; + defer base_dir.close(); + + base_dir.access("include/stddef.h", .{}) catch continue; + const path = try std.fs.path.join(comp.gpa, &.{ dirname, "include" }); + errdefer comp.gpa.free(path); + try comp.system_include_dirs.append(path); + break; + } else return error.AroIncludeNotFound; + + if (comp.target.os.tag == .linux) { + const triple_str = try comp.target.linuxTriple(allocator); + defer allocator.free(triple_str); + + const multiarch_path = try std.fs.path.join(allocator, &.{ "/usr/include", triple_str }); + defer allocator.free(multiarch_path); + + if (!std.meta.isError(std.fs.accessAbsolute(multiarch_path, .{}))) { + const duped = try comp.gpa.dupe(u8, multiarch_path); + errdefer comp.gpa.free(duped); + try comp.system_include_dirs.append(duped); + } + } + const usr_include = try comp.gpa.dupe(u8, "/usr/include"); + errdefer comp.gpa.free(usr_include); + try comp.system_include_dirs.append(usr_include); +} + +pub fn getSource(comp: *const Compilation, id: Source.Id) Source { + if (id == .generated) return .{ + .path = "", + .buf = comp.generated_buf.items, + .id = .generated, + .splice_locs = &.{}, + }; + return comp.sources.values()[@intFromEnum(id) - 2]; +} + +/// Creates a Source from the contents of `reader` and adds it to the Compilation +/// Performs newline splicing, line-ending normalization to '\n', and UTF-8 validation. +/// caller retains ownership of `path` +/// `expected_size` will be allocated to hold the contents of `reader` and *must* be at least +/// as large as the entire contents of `reader`. +/// To add a pre-existing buffer as a Source, see addSourceFromBuffer +/// To add a file's contents given its path, see addSourceFromPath +pub fn addSourceFromReader(comp: *Compilation, reader: anytype, path: []const u8, expected_size: u32) !Source { + var contents = try comp.gpa.alloc(u8, expected_size); + errdefer comp.gpa.free(contents); + + const duped_path = try comp.gpa.dupe(u8, path); + errdefer comp.gpa.free(duped_path); + + var splice_list = std.ArrayList(u32).init(comp.gpa); + defer splice_list.deinit(); + + const source_id: Source.Id = @enumFromInt(comp.sources.count() + 2); + + var i: u32 = 0; + var backslash_loc: u32 = undefined; + var state: enum { + beginning_of_file, + bom1, + bom2, + start, + back_slash, + cr, + back_slash_cr, + trailing_ws, + } = .beginning_of_file; + var line: u32 = 1; + + while (true) { + const byte = reader.readByte() catch |err| switch (err) { + error.EndOfStream => break, + else => |e| return e, + }; + contents[i] = byte; + + switch (byte) { + '\r' => { + switch (state) { + .start, .cr, .beginning_of_file => { + state = .start; + line += 1; + state = .cr; + contents[i] = '\n'; + i += 1; + }, + .back_slash, .trailing_ws, .back_slash_cr => { + i = backslash_loc; + try splice_list.append(i); + if (state == .trailing_ws) { + try comp.diag.add(.{ + .tag = .backslash_newline_escape, + .loc = .{ .id = source_id, .byte_offset = i, .line = line }, + }, &.{}); + } + state = if (state == .back_slash_cr) .cr else .back_slash_cr; + }, + .bom1, .bom2 => break, // invalid utf-8 + } + }, + '\n' => { + switch (state) { + .start, .beginning_of_file => { + state = .start; + line += 1; + i += 1; + }, + .cr, .back_slash_cr => {}, + .back_slash, .trailing_ws => { + i = backslash_loc; + if (state == .back_slash or state == .trailing_ws) { + try splice_list.append(i); + } + if (state == .trailing_ws) { + try comp.diag.add(.{ + .tag = .backslash_newline_escape, + .loc = .{ .id = source_id, .byte_offset = i, .line = line }, + }, &.{}); + } + }, + .bom1, .bom2 => break, + } + state = .start; + }, + '\\' => { + backslash_loc = i; + state = .back_slash; + i += 1; + }, + '\t', '\x0B', '\x0C', ' ' => { + switch (state) { + .start, .trailing_ws => {}, + .beginning_of_file => state = .start, + .cr, .back_slash_cr => state = .start, + .back_slash => state = .trailing_ws, + .bom1, .bom2 => break, + } + i += 1; + }, + '\xEF' => { + i += 1; + state = switch (state) { + .beginning_of_file => .bom1, + else => .start, + }; + }, + '\xBB' => { + i += 1; + state = switch (state) { + .bom1 => .bom2, + else => .start, + }; + }, + '\xBF' => { + switch (state) { + .bom2 => i = 0, // rewind and overwrite the BOM + else => i += 1, + } + state = .start; + }, + else => { + i += 1; + state = .start; + }, + } + } + + const splice_locs = try splice_list.toOwnedSlice(); + errdefer comp.gpa.free(splice_locs); + + if (i != contents.len) contents = try comp.gpa.realloc(contents, i); + + var source = Source{ + .id = source_id, + .path = duped_path, + .buf = contents, + .splice_locs = splice_locs, + }; + + try comp.sources.put(duped_path, source); + if (source.offsetOfInvalidUtf8()) |offset| { + try comp.invalid_utf8_locs.putNoClobber(comp.gpa, source_id, offset); + } + return source; +} + +/// Caller retains ownership of `path` and `buf`. +pub fn addSourceFromBuffer(comp: *Compilation, path: []const u8, buf: []const u8) !Source { + if (comp.sources.get(path)) |some| return some; + + const size = std.math.cast(u32, buf.len) orelse return error.StreamTooLong; + var buf_reader = std.io.fixedBufferStream(buf); + + return comp.addSourceFromReader(buf_reader.reader(), path, size); +} + +/// Caller retains ownership of `path` +pub fn addSourceFromPath(comp: *Compilation, path: []const u8) !Source { + if (comp.sources.get(path)) |some| return some; + + if (mem.indexOfScalar(u8, path, 0) != null) { + return error.FileNotFound; + } + + const file = try std.fs.cwd().openFile(path, .{}); + defer file.close(); + + const size = std.math.cast(u32, try file.getEndPos()) orelse return error.StreamTooLong; + var buf_reader = std.io.bufferedReader(file.reader()); + + return comp.addSourceFromReader(buf_reader.reader(), path, size); +} + +pub const IncludeDirIterator = struct { + comp: *const Compilation, + cwd_source_id: ?Source.Id, + include_dirs_idx: usize = 0, + sys_include_dirs_idx: usize = 0, + + fn next(self: *IncludeDirIterator) ?[]const u8 { + if (self.cwd_source_id) |source_id| { + self.cwd_source_id = null; + const path = self.comp.getSource(source_id).path; + return std.fs.path.dirname(path) orelse "."; + } + if (self.include_dirs_idx < self.comp.include_dirs.items.len) { + defer self.include_dirs_idx += 1; + return self.comp.include_dirs.items[self.include_dirs_idx]; + } + if (self.sys_include_dirs_idx < self.comp.system_include_dirs.items.len) { + defer self.sys_include_dirs_idx += 1; + return self.comp.system_include_dirs.items[self.sys_include_dirs_idx]; + } + return null; + } + + /// Returned value must be freed by allocator + fn nextWithFile(self: *IncludeDirIterator, filename: []const u8, allocator: Allocator) !?[]const u8 { + while (self.next()) |dir| { + return try std.fs.path.join(allocator, &.{ dir, filename }); + } + return null; + } + + /// Advance the iterator until it finds an include directory that matches + /// the directory which contains `source`. + fn skipUntilDirMatch(self: *IncludeDirIterator, source: Source.Id) void { + const path = self.comp.getSource(source).path; + const includer_path = std.fs.path.dirname(path) orelse "."; + while (self.next()) |dir| { + if (mem.eql(u8, includer_path, dir)) break; + } + } +}; + +pub fn hasInclude( + comp: *const Compilation, + filename: []const u8, + includer_token_source: Source.Id, + /// angle bracket vs quotes + include_type: IncludeType, + /// __has_include vs __has_include_next + which: WhichInclude, +) !bool { + const cwd = std.fs.cwd(); + if (std.fs.path.isAbsolute(filename)) { + if (which == .next) return false; + return !std.meta.isError(cwd.access(filename, .{})); + } + + const cwd_source_id = switch (include_type) { + .quotes => switch (which) { + .first => includer_token_source, + .next => null, + }, + .angle_brackets => null, + }; + var it = IncludeDirIterator{ .comp = comp, .cwd_source_id = cwd_source_id }; + if (which == .next) { + it.skipUntilDirMatch(includer_token_source); + } + + var stack_fallback = std.heap.stackFallback(path_buf_stack_limit, comp.gpa); + + while (try it.nextWithFile(filename, stack_fallback.get())) |path| { + defer stack_fallback.get().free(path); + if (!std.meta.isError(cwd.access(path, .{}))) return true; + } + return false; +} + +pub const WhichInclude = enum { + first, + next, +}; + +pub const IncludeType = enum { + quotes, + angle_brackets, +}; + +fn getFileContents(comp: *Compilation, path: []const u8) ![]const u8 { + if (mem.indexOfScalar(u8, path, 0) != null) { + return error.FileNotFound; + } + + const file = try std.fs.cwd().openFile(path, .{}); + defer file.close(); + + return file.readToEndAlloc(comp.gpa, std.math.maxInt(u32)); +} + +pub fn findEmbed( + comp: *Compilation, + filename: []const u8, + includer_token_source: Source.Id, + /// angle bracket vs quotes + include_type: IncludeType, +) !?[]const u8 { + if (std.fs.path.isAbsolute(filename)) { + return if (comp.getFileContents(filename)) |some| + some + else |err| switch (err) { + error.OutOfMemory => |e| return e, + else => null, + }; + } + + const cwd_source_id = switch (include_type) { + .quotes => includer_token_source, + .angle_brackets => null, + }; + var it = IncludeDirIterator{ .comp = comp, .cwd_source_id = cwd_source_id }; + var stack_fallback = std.heap.stackFallback(path_buf_stack_limit, comp.gpa); + + while (try it.nextWithFile(filename, stack_fallback.get())) |path| { + defer stack_fallback.get().free(path); + if (comp.getFileContents(path)) |some| + return some + else |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + else => {}, + } + } + return null; +} + +pub fn findInclude( + comp: *Compilation, + filename: []const u8, + includer_token_source: Source.Id, + /// angle bracket vs quotes + include_type: IncludeType, + /// include vs include_next + which: WhichInclude, +) !?Source { + if (std.fs.path.isAbsolute(filename)) { + if (which == .next) return null; + return if (comp.addSourceFromPath(filename)) |some| + some + else |err| switch (err) { + error.OutOfMemory => |e| return e, + else => null, + }; + } + const cwd_source_id = switch (include_type) { + .quotes => switch (which) { + .first => includer_token_source, + .next => null, + }, + .angle_brackets => null, + }; + var it = IncludeDirIterator{ .comp = comp, .cwd_source_id = cwd_source_id }; + + if (which == .next) { + it.skipUntilDirMatch(includer_token_source); + } + + var stack_fallback = std.heap.stackFallback(path_buf_stack_limit, comp.gpa); + while (try it.nextWithFile(filename, stack_fallback.get())) |path| { + defer stack_fallback.get().free(path); + if (comp.addSourceFromPath(path)) |some| + return some + else |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + else => {}, + } + } + return null; +} + +pub fn addPragmaHandler(comp: *Compilation, name: []const u8, handler: *Pragma) Allocator.Error!void { + try comp.pragma_handlers.putNoClobber(name, handler); +} + +pub fn addDefaultPragmaHandlers(comp: *Compilation) Allocator.Error!void { + const GCC = @import("pragmas/gcc.zig"); + var gcc = try GCC.init(comp.gpa); + errdefer gcc.deinit(gcc, comp); + + const Once = @import("pragmas/once.zig"); + var once = try Once.init(comp.gpa); + errdefer once.deinit(once, comp); + + const Message = @import("pragmas/message.zig"); + var message = try Message.init(comp.gpa); + errdefer message.deinit(message, comp); + + const Pack = @import("pragmas/pack.zig"); + var pack = try Pack.init(comp.gpa); + errdefer pack.deinit(pack, comp); + + try comp.addPragmaHandler("GCC", gcc); + try comp.addPragmaHandler("once", once); + try comp.addPragmaHandler("message", message); + try comp.addPragmaHandler("pack", pack); +} + +pub fn getPragma(comp: *Compilation, name: []const u8) ?*Pragma { + return comp.pragma_handlers.get(name); +} + +const PragmaEvent = enum { + before_preprocess, + before_parse, + after_parse, +}; + +pub fn pragmaEvent(comp: *Compilation, event: PragmaEvent) void { + for (comp.pragma_handlers.values()) |pragma| { + const maybe_func = switch (event) { + .before_preprocess => pragma.beforePreprocess, + .before_parse => pragma.beforeParse, + .after_parse => pragma.afterParse, + }; + if (maybe_func) |func| func(pragma, comp); + } +} + +pub fn hasBuiltin(comp: *const Compilation, name: []const u8) bool { + if (std.mem.eql(u8, name, "__builtin_va_arg") or + std.mem.eql(u8, name, "__builtin_choose_expr") or + std.mem.eql(u8, name, "__builtin_bitoffsetof") or + std.mem.eql(u8, name, "__builtin_offsetof") or + std.mem.eql(u8, name, "__builtin_types_compatible_p")) return true; + + @setEvalBranchQuota(10_000); + const tag = std.meta.stringToEnum(BuiltinFunction.Tag, name) orelse return false; + const builtin = BuiltinFunction.fromTag(tag); + return comp.hasBuiltinFunction(builtin); +} + +pub fn hasBuiltinFunction(comp: *const Compilation, builtin: BuiltinFunction) bool { + if (!target_util.builtinEnabled(comp.target, builtin.properties.target_set)) return false; + + switch (builtin.properties.language) { + .all_languages => return true, + .all_ms_languages => return comp.langopts.emulate == .msvc, + .gnu_lang, .all_gnu_languages => return comp.langopts.standard.isGNU(), + } +} + +pub const renderErrors = Diagnostics.render; + +test "addSourceFromReader" { + const Test = struct { + fn addSourceFromReader(str: []const u8, expected: []const u8, warning_count: u32, splices: []const u32) !void { + var comp = Compilation.init(std.testing.allocator); + defer comp.deinit(); + + var buf_reader = std.io.fixedBufferStream(str); + const source = try comp.addSourceFromReader(buf_reader.reader(), "path", @intCast(str.len)); + + try std.testing.expectEqualStrings(expected, source.buf); + try std.testing.expectEqual(warning_count, @as(u32, @intCast(comp.diag.list.items.len))); + try std.testing.expectEqualSlices(u32, splices, source.splice_locs); + } + + fn withAllocationFailures(allocator: std.mem.Allocator) !void { + var comp = Compilation.init(allocator); + defer comp.deinit(); + + _ = try comp.addSourceFromBuffer("path", "spliced\\\nbuffer\n"); + _ = try comp.addSourceFromBuffer("path", "non-spliced buffer\n"); + } + }; + try Test.addSourceFromReader("ab\\\nc", "abc", 0, &.{2}); + try Test.addSourceFromReader("ab\\\rc", "abc", 0, &.{2}); + try Test.addSourceFromReader("ab\\\r\nc", "abc", 0, &.{2}); + try Test.addSourceFromReader("ab\\ \nc", "abc", 1, &.{2}); + try Test.addSourceFromReader("ab\\\t\nc", "abc", 1, &.{2}); + try Test.addSourceFromReader("ab\\ \t\nc", "abc", 1, &.{2}); + try Test.addSourceFromReader("ab\\\r \nc", "ab \nc", 0, &.{2}); + try Test.addSourceFromReader("ab\\\\\nc", "ab\\c", 0, &.{3}); + try Test.addSourceFromReader("ab\\ \r\nc", "abc", 1, &.{2}); + try Test.addSourceFromReader("ab\\ \\\nc", "ab\\ c", 0, &.{4}); + try Test.addSourceFromReader("ab\\\r\\\nc", "abc", 0, &.{ 2, 2 }); + try Test.addSourceFromReader("ab\\ \rc", "abc", 1, &.{2}); + try Test.addSourceFromReader("ab\\", "ab\\", 0, &.{}); + try Test.addSourceFromReader("ab\\\\", "ab\\\\", 0, &.{}); + try Test.addSourceFromReader("ab\\ ", "ab\\ ", 0, &.{}); + try Test.addSourceFromReader("ab\\\n", "ab", 0, &.{2}); + try Test.addSourceFromReader("ab\\\r\n", "ab", 0, &.{2}); + try Test.addSourceFromReader("ab\\\r", "ab", 0, &.{2}); + + // carriage return normalization + try Test.addSourceFromReader("ab\r", "ab\n", 0, &.{}); + try Test.addSourceFromReader("ab\r\r", "ab\n\n", 0, &.{}); + try Test.addSourceFromReader("ab\r\r\n", "ab\n\n", 0, &.{}); + try Test.addSourceFromReader("ab\r\r\n\r", "ab\n\n\n", 0, &.{}); + try Test.addSourceFromReader("\r\\", "\n\\", 0, &.{}); + try Test.addSourceFromReader("\\\r\\", "\\", 0, &.{0}); + + try std.testing.checkAllAllocationFailures(std.testing.allocator, Test.withAllocationFailures, .{}); +} + +test "addSourceFromReader - exhaustive check for carriage return elimination" { + const alphabet = [_]u8{ '\r', '\n', ' ', '\\', 'a' }; + const alen = alphabet.len; + var buf: [alphabet.len]u8 = [1]u8{alphabet[0]} ** alen; + + var comp = Compilation.init(std.testing.allocator); + defer comp.deinit(); + + var source_count: u32 = 0; + + while (true) { + const source = try comp.addSourceFromBuffer(&buf, &buf); + source_count += 1; + try std.testing.expect(std.mem.indexOfScalar(u8, source.buf, '\r') == null); + + if (std.mem.allEqual(u8, &buf, alphabet[alen - 1])) break; + + var idx = std.mem.indexOfScalar(u8, &alphabet, buf[buf.len - 1]).?; + buf[buf.len - 1] = alphabet[(idx + 1) % alen]; + var j = buf.len - 1; + while (j > 0) : (j -= 1) { + idx = std.mem.indexOfScalar(u8, &alphabet, buf[j - 1]).?; + if (buf[j] == alphabet[0]) buf[j - 1] = alphabet[(idx + 1) % alen] else break; + } + } + try std.testing.expect(source_count == std.math.powi(usize, alen, alen) catch unreachable); +} + +test "ignore BOM at beginning of file" { + const BOM = "\xEF\xBB\xBF"; + + const Test = struct { + fn run(buf: []const u8, input_type: enum { valid_utf8, invalid_utf8 }) !void { + var comp = Compilation.init(std.testing.allocator); + defer comp.deinit(); + + var buf_reader = std.io.fixedBufferStream(buf); + const source = try comp.addSourceFromReader(buf_reader.reader(), "file.c", @intCast(buf.len)); + switch (input_type) { + .valid_utf8 => { + const expected_output = if (mem.startsWith(u8, buf, BOM)) buf[BOM.len..] else buf; + try std.testing.expectEqualStrings(expected_output, source.buf); + try std.testing.expect(!comp.invalid_utf8_locs.contains(source.id)); + }, + .invalid_utf8 => try std.testing.expect(comp.invalid_utf8_locs.contains(source.id)), + } + } + }; + + try Test.run(BOM, .valid_utf8); + try Test.run(BOM ++ "x", .valid_utf8); + try Test.run("x" ++ BOM, .valid_utf8); + try Test.run(BOM ++ " ", .valid_utf8); + try Test.run(BOM ++ "\n", .valid_utf8); + try Test.run(BOM ++ "\\", .valid_utf8); + + try Test.run(BOM[0..1] ++ "x", .invalid_utf8); + try Test.run(BOM[0..2] ++ "x", .invalid_utf8); + try Test.run(BOM[1..] ++ "x", .invalid_utf8); + try Test.run(BOM[2..] ++ "x", .invalid_utf8); +} diff --git a/deps/aro/Diagnostics.zig b/deps/aro/Diagnostics.zig new file mode 100644 index 000000000000..68fa38b78b29 --- /dev/null +++ b/deps/aro/Diagnostics.zig @@ -0,0 +1,2787 @@ +const std = @import("std"); +const mem = std.mem; +const Allocator = mem.Allocator; +const Source = @import("Source.zig"); +const Compilation = @import("Compilation.zig"); +const Attribute = @import("Attribute.zig"); +const BuiltinFunction = @import("builtins/BuiltinFunction.zig"); +const Header = @import("builtins/Properties.zig").Header; +const Tree = @import("Tree.zig"); +const util = @import("util.zig"); +const is_windows = @import("builtin").os.tag == .windows; + +const Diagnostics = @This(); + +const PointerSignMessage = " converts between pointers to integer types with different sign"; + +pub const Message = struct { + tag: Tag, + kind: Kind = undefined, + loc: Source.Location = .{}, + extra: Extra = .{ .none = {} }, + + pub const Extra = union { + str: []const u8, + tok_id: struct { + expected: Tree.Token.Id, + actual: Tree.Token.Id, + }, + tok_id_expected: Tree.Token.Id, + arguments: struct { + expected: u32, + actual: u32, + }, + codepoints: struct { + actual: u21, + resembles: u21, + }, + attr_arg_count: struct { + attribute: Attribute.Tag, + expected: u32, + }, + attr_arg_type: struct { + expected: Attribute.ArgumentType, + actual: Attribute.ArgumentType, + }, + attr_enum: struct { + tag: Attribute.Tag, + }, + ignored_record_attr: struct { + tag: Attribute.Tag, + specifier: enum { @"struct", @"union", @"enum" }, + }, + builtin_with_header: struct { + builtin: BuiltinFunction.Tag, + header: Header, + }, + actual_codepoint: u21, + ascii: u7, + unsigned: u64, + pow_2_as_string: u8, + signed: i64, + none: void, + }; +}; + +pub const Tag = std.meta.DeclEnum(messages); + +// u4 to avoid any possible packed struct issues +pub const Kind = enum(u4) { @"fatal error", @"error", note, warning, off, default }; + +pub const Options = packed struct { + // do not directly use these, instead add `const NAME = true;` + all: Kind = .default, + extra: Kind = .default, + pedantic: Kind = .default, + + @"unsupported-pragma": Kind = .default, + @"c99-extensions": Kind = .default, + @"implicit-int": Kind = .default, + @"duplicate-decl-specifier": Kind = .default, + @"missing-declaration": Kind = .default, + @"extern-initializer": Kind = .default, + @"implicit-function-declaration": Kind = .default, + @"unused-value": Kind = .default, + @"unreachable-code": Kind = .default, + @"unknown-warning-option": Kind = .default, + @"gnu-empty-struct": Kind = .default, + @"gnu-alignof-expression": Kind = .default, + @"macro-redefined": Kind = .default, + @"generic-qual-type": Kind = .default, + multichar: Kind = .default, + @"pointer-integer-compare": Kind = .default, + @"compare-distinct-pointer-types": Kind = .default, + @"literal-conversion": Kind = .default, + @"cast-qualifiers": Kind = .default, + @"array-bounds": Kind = .default, + @"int-conversion": Kind = .default, + @"pointer-type-mismatch": Kind = .default, + @"c2x-extensions": Kind = .default, + @"incompatible-pointer-types": Kind = .default, + @"excess-initializers": Kind = .default, + @"division-by-zero": Kind = .default, + @"initializer-overrides": Kind = .default, + @"incompatible-pointer-types-discards-qualifiers": Kind = .default, + @"unknown-attributes": Kind = .default, + @"ignored-attributes": Kind = .default, + @"builtin-macro-redefined": Kind = .default, + @"gnu-label-as-value": Kind = .default, + @"malformed-warning-check": Kind = .default, + @"#pragma-messages": Kind = .default, + @"newline-eof": Kind = .default, + @"empty-translation-unit": Kind = .default, + @"implicitly-unsigned-literal": Kind = .default, + @"c99-compat": Kind = .default, + @"unicode-zero-width": Kind = .default, + @"unicode-homoglyph": Kind = .default, + @"return-type": Kind = .default, + @"dollar-in-identifier-extension": Kind = .default, + @"unknown-pragmas": Kind = .default, + @"predefined-identifier-outside-function": Kind = .default, + @"many-braces-around-scalar-init": Kind = .default, + uninitialized: Kind = .default, + @"gnu-statement-expression": Kind = .default, + @"gnu-imaginary-constant": Kind = .default, + @"gnu-complex-integer": Kind = .default, + @"ignored-qualifiers": Kind = .default, + @"integer-overflow": Kind = .default, + @"extra-semi": Kind = .default, + @"gnu-binary-literal": Kind = .default, + @"variadic-macros": Kind = .default, + varargs: Kind = .default, + @"#warnings": Kind = .default, + @"deprecated-declarations": Kind = .default, + @"backslash-newline-escape": Kind = .default, + @"pointer-to-int-cast": Kind = .default, + @"gnu-case-range": Kind = .default, + @"c++-compat": Kind = .default, + vla: Kind = .default, + @"float-overflow-conversion": Kind = .default, + @"float-zero-conversion": Kind = .default, + @"float-conversion": Kind = .default, + @"gnu-folding-constant": Kind = .default, + undef: Kind = .default, + @"ignored-pragmas": Kind = .default, + @"gnu-include-next": Kind = .default, + @"include-next-outside-header": Kind = .default, + @"include-next-absolute-path": Kind = .default, + @"enum-too-large": Kind = .default, + @"fixed-enum-extension": Kind = .default, + @"designated-init": Kind = .default, + @"attribute-warning": Kind = .default, + @"invalid-noreturn": Kind = .default, + @"zero-length-array": Kind = .default, + @"old-style-flexible-struct": Kind = .default, + @"gnu-zero-variadic-macro-arguments": Kind = .default, + @"main-return-type": Kind = .default, + @"expansion-to-defined": Kind = .default, + @"bit-int-extension": Kind = .default, + @"keyword-macro": Kind = .default, + @"pointer-arith": Kind = .default, + @"sizeof-array-argument": Kind = .default, + @"pre-c2x-compat": Kind = .default, + @"pointer-bool-conversion": Kind = .default, + @"string-conversion": Kind = .default, + @"gnu-auto-type": Kind = .default, + @"gnu-union-cast": Kind = .default, + @"pointer-sign": Kind = .default, + @"fuse-ld-path": Kind = .default, + @"language-extension-token": Kind = .default, + @"complex-component-init": Kind = .default, +}; + +const messages = struct { + pub const todo = struct { // Maybe someday this will no longer be needed. + const msg = "TODO: {s}"; + const extra = .str; + const kind = .@"error"; + }; + pub const error_directive = struct { + const msg = "{s}"; + const extra = .str; + const kind = .@"error"; + }; + pub const warning_directive = struct { + const msg = "{s}"; + const opt = "#warnings"; + const extra = .str; + const kind = .warning; + }; + pub const elif_without_if = struct { + const msg = "#elif without #if"; + const kind = .@"error"; + }; + pub const elif_after_else = struct { + const msg = "#elif after #else"; + const kind = .@"error"; + }; + pub const elifdef_without_if = struct { + const msg = "#elifdef without #if"; + const kind = .@"error"; + }; + pub const elifdef_after_else = struct { + const msg = "#elifdef after #else"; + const kind = .@"error"; + }; + pub const elifndef_without_if = struct { + const msg = "#elifndef without #if"; + const kind = .@"error"; + }; + pub const elifndef_after_else = struct { + const msg = "#elifndef after #else"; + const kind = .@"error"; + }; + pub const else_without_if = struct { + const msg = "#else without #if"; + const kind = .@"error"; + }; + pub const else_after_else = struct { + const msg = "#else after #else"; + const kind = .@"error"; + }; + pub const endif_without_if = struct { + const msg = "#endif without #if"; + const kind = .@"error"; + }; + pub const unknown_pragma = struct { + const msg = "unknown pragma ignored"; + const opt = "unknown-pragmas"; + const kind = .off; + const all = true; + }; + pub const line_simple_digit = struct { + const msg = "#line directive requires a simple digit sequence"; + const kind = .@"error"; + }; + pub const line_invalid_filename = struct { + const msg = "invalid filename for #line directive"; + const kind = .@"error"; + }; + pub const unterminated_conditional_directive = struct { + const msg = "unterminated conditional directive"; + const kind = .@"error"; + }; + pub const invalid_preprocessing_directive = struct { + const msg = "invalid preprocessing directive"; + const kind = .@"error"; + }; + pub const macro_name_missing = struct { + const msg = "macro name missing"; + const kind = .@"error"; + }; + pub const extra_tokens_directive_end = struct { + const msg = "extra tokens at end of macro directive"; + const kind = .@"error"; + }; + pub const expected_value_in_expr = struct { + const msg = "expected value in expression"; + const kind = .@"error"; + }; + pub const closing_paren = struct { + const msg = "expected closing ')'"; + const kind = .@"error"; + }; + pub const to_match_paren = struct { + const msg = "to match this '('"; + const kind = .note; + }; + pub const to_match_brace = struct { + const msg = "to match this '{'"; + const kind = .note; + }; + pub const to_match_bracket = struct { + const msg = "to match this '['"; + const kind = .note; + }; + pub const header_str_closing = struct { + const msg = "expected closing '>'"; + const kind = .@"error"; + }; + pub const header_str_match = struct { + const msg = "to match this '<'"; + const kind = .note; + }; + pub const string_literal_in_pp_expr = struct { + const msg = "string literal in preprocessor expression"; + const kind = .@"error"; + }; + pub const float_literal_in_pp_expr = struct { + const msg = "floating point literal in preprocessor expression"; + const kind = .@"error"; + }; + pub const defined_as_macro_name = struct { + const msg = "'defined' cannot be used as a macro name"; + const kind = .@"error"; + }; + pub const macro_name_must_be_identifier = struct { + const msg = "macro name must be an identifier"; + const kind = .@"error"; + }; + pub const whitespace_after_macro_name = struct { + const msg = "ISO C99 requires whitespace after the macro name"; + const opt = "c99-extensions"; + const kind = .warning; + }; + pub const hash_hash_at_start = struct { + const msg = "'##' cannot appear at the start of a macro expansion"; + const kind = .@"error"; + }; + pub const hash_hash_at_end = struct { + const msg = "'##' cannot appear at the end of a macro expansion"; + const kind = .@"error"; + }; + pub const pasting_formed_invalid = struct { + const msg = "pasting formed '{s}', an invalid preprocessing token"; + const extra = .str; + const kind = .@"error"; + }; + pub const missing_paren_param_list = struct { + const msg = "missing ')' in macro parameter list"; + const kind = .@"error"; + }; + pub const unterminated_macro_param_list = struct { + const msg = "unterminated macro param list"; + const kind = .@"error"; + }; + pub const invalid_token_param_list = struct { + const msg = "invalid token in macro parameter list"; + const kind = .@"error"; + }; + pub const expected_comma_param_list = struct { + const msg = "expected comma in macro parameter list"; + const kind = .@"error"; + }; + pub const hash_not_followed_param = struct { + const msg = "'#' is not followed by a macro parameter"; + const kind = .@"error"; + }; + pub const expected_filename = struct { + const msg = "expected \"FILENAME\" or "; + const kind = .@"error"; + }; + pub const empty_filename = struct { + const msg = "empty filename"; + const kind = .@"error"; + }; + pub const expected_invalid = struct { + const msg = "expected '{s}', found invalid bytes"; + const extra = .tok_id_expected; + const kind = .@"error"; + }; + pub const expected_eof = struct { + const msg = "expected '{s}' before end of file"; + const extra = .tok_id_expected; + const kind = .@"error"; + }; + pub const expected_token = struct { + const msg = "expected '{s}', found '{s}'"; + const extra = .tok_id; + const kind = .@"error"; + }; + pub const expected_expr = struct { + const msg = "expected expression"; + const kind = .@"error"; + }; + pub const expected_integer_constant_expr = struct { + const msg = "expression is not an integer constant expression"; + const kind = .@"error"; + }; + pub const missing_type_specifier = struct { + const msg = "type specifier missing, defaults to 'int'"; + const opt = "implicit-int"; + const kind = .warning; + const all = true; + }; + pub const multiple_storage_class = struct { + const msg = "cannot combine with previous '{s}' declaration specifier"; + const extra = .str; + const kind = .@"error"; + }; + pub const static_assert_failure = struct { + const msg = "static assertion failed"; + const kind = .@"error"; + }; + pub const static_assert_failure_message = struct { + const msg = "static assertion failed {s}"; + const extra = .str; + const kind = .@"error"; + }; + pub const expected_type = struct { + const msg = "expected a type"; + const kind = .@"error"; + }; + pub const cannot_combine_spec = struct { + const msg = "cannot combine with previous '{s}' specifier"; + const extra = .str; + const kind = .@"error"; + }; + pub const duplicate_decl_spec = struct { + const msg = "duplicate '{s}' declaration specifier"; + const extra = .str; + const opt = "duplicate-decl-specifier"; + const kind = .warning; + const all = true; + }; + pub const restrict_non_pointer = struct { + const msg = "restrict requires a pointer or reference ('{s}' is invalid)"; + const extra = .str; + const kind = .@"error"; + }; + pub const expected_external_decl = struct { + const msg = "expected external declaration"; + const kind = .@"error"; + }; + pub const expected_ident_or_l_paren = struct { + const msg = "expected identifier or '('"; + const kind = .@"error"; + }; + pub const missing_declaration = struct { + const msg = "declaration does not declare anything"; + const opt = "missing-declaration"; + const kind = .warning; + }; + pub const func_not_in_root = struct { + const msg = "function definition is not allowed here"; + const kind = .@"error"; + }; + pub const illegal_initializer = struct { + const msg = "illegal initializer (only variables can be initialized)"; + const kind = .@"error"; + }; + pub const extern_initializer = struct { + const msg = "extern variable has initializer"; + const opt = "extern-initializer"; + const kind = .warning; + }; + pub const spec_from_typedef = struct { + const msg = "'{s}' came from typedef"; + const extra = .str; + const kind = .note; + }; + pub const param_before_var_args = struct { + const msg = "ISO C requires a named parameter before '...'"; + const kind = .@"error"; + }; + pub const void_only_param = struct { + const msg = "'void' must be the only parameter if specified"; + const kind = .@"error"; + }; + pub const void_param_qualified = struct { + const msg = "'void' parameter cannot be qualified"; + const kind = .@"error"; + }; + pub const void_must_be_first_param = struct { + const msg = "'void' must be the first parameter if specified"; + const kind = .@"error"; + }; + pub const invalid_storage_on_param = struct { + const msg = "invalid storage class on function parameter"; + const kind = .@"error"; + }; + pub const threadlocal_non_var = struct { + const msg = "_Thread_local only allowed on variables"; + const kind = .@"error"; + }; + pub const func_spec_non_func = struct { + const msg = "'{s}' can only appear on functions"; + const extra = .str; + const kind = .@"error"; + }; + pub const illegal_storage_on_func = struct { + const msg = "illegal storage class on function"; + const kind = .@"error"; + }; + pub const illegal_storage_on_global = struct { + const msg = "illegal storage class on global variable"; + const kind = .@"error"; + }; + pub const expected_stmt = struct { + const msg = "expected statement"; + const kind = .@"error"; + }; + pub const func_cannot_return_func = struct { + const msg = "function cannot return a function"; + const kind = .@"error"; + }; + pub const func_cannot_return_array = struct { + const msg = "function cannot return an array"; + const kind = .@"error"; + }; + pub const undeclared_identifier = struct { + const msg = "use of undeclared identifier '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const not_callable = struct { + const msg = "cannot call non function type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const unsupported_str_cat = struct { + const msg = "unsupported string literal concatenation"; + const kind = .@"error"; + }; + pub const static_func_not_global = struct { + const msg = "static functions must be global"; + const kind = .@"error"; + }; + pub const implicit_func_decl = struct { + const msg = "implicit declaration of function '{s}' is invalid in C99"; + const extra = .str; + const opt = "implicit-function-declaration"; + const kind = .warning; + const all = true; + }; + pub const unknown_builtin = struct { + const msg = "use of unknown builtin '{s}'"; + const extra = .str; + const opt = "implicit-function-declaration"; + const kind = .@"error"; + const all = true; + }; + pub const implicit_builtin = struct { + const msg = "implicitly declaring library function '{s}'"; + const extra = .str; + const opt = "implicit-function-declaration"; + const kind = .@"error"; + const all = true; + }; + pub const implicit_builtin_header_note = struct { + const msg = "include the header <{s}.h> or explicitly provide a declaration for '{s}'"; + const extra = .builtin_with_header; + const opt = "implicit-function-declaration"; + const kind = .note; + const all = true; + }; + pub const expected_param_decl = struct { + const msg = "expected parameter declaration"; + const kind = .@"error"; + }; + pub const invalid_old_style_params = struct { + const msg = "identifier parameter lists are only allowed in function definitions"; + const kind = .@"error"; + }; + pub const expected_fn_body = struct { + const msg = "expected function body after function declaration"; + const kind = .@"error"; + }; + pub const invalid_void_param = struct { + const msg = "parameter cannot have void type"; + const kind = .@"error"; + }; + pub const unused_value = struct { + const msg = "expression result unused"; + const opt = "unused-value"; + const kind = .warning; + const all = true; + }; + pub const continue_not_in_loop = struct { + const msg = "'continue' statement not in a loop"; + const kind = .@"error"; + }; + pub const break_not_in_loop_or_switch = struct { + const msg = "'break' statement not in a loop or a switch"; + const kind = .@"error"; + }; + pub const unreachable_code = struct { + const msg = "unreachable code"; + const opt = "unreachable-code"; + const kind = .warning; + const all = true; + }; + pub const duplicate_label = struct { + const msg = "duplicate label '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const previous_label = struct { + const msg = "previous definition of label '{s}' was here"; + const extra = .str; + const kind = .note; + }; + pub const undeclared_label = struct { + const msg = "use of undeclared label '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const case_not_in_switch = struct { + const msg = "'{s}' statement not in a switch statement"; + const extra = .str; + const kind = .@"error"; + }; + pub const duplicate_switch_case_signed = struct { + const msg = "duplicate case value '{d}'"; + const extra = .signed; + const kind = .@"error"; + }; + pub const duplicate_switch_case_unsigned = struct { + const msg = "duplicate case value '{d}'"; + const extra = .unsigned; + const kind = .@"error"; + }; + pub const multiple_default = struct { + const msg = "multiple default cases in the same switch"; + const kind = .@"error"; + }; + pub const previous_case = struct { + const msg = "previous case defined here"; + const kind = .note; + }; + pub const expected_arguments = struct { + const msg = "expected {d} argument(s) got {d}"; + const extra = .arguments; + const kind = .@"error"; + }; + pub const expected_arguments_old = struct { + const msg = expected_arguments.msg; + const extra = .arguments; + const kind = .warning; + }; + pub const expected_at_least_arguments = struct { + const msg = "expected at least {d} argument(s) got {d}"; + const extra = .arguments; + const kind = .warning; + }; + pub const invalid_static_star = struct { + const msg = "'static' may not be used with an unspecified variable length array size"; + const kind = .@"error"; + }; + pub const static_non_param = struct { + const msg = "'static' used outside of function parameters"; + const kind = .@"error"; + }; + pub const array_qualifiers = struct { + const msg = "type qualifier in non parameter array type"; + const kind = .@"error"; + }; + pub const star_non_param = struct { + const msg = "star modifier used outside of function parameters"; + const kind = .@"error"; + }; + pub const variable_len_array_file_scope = struct { + const msg = "variable length arrays not allowed at file scope"; + const kind = .@"error"; + }; + pub const useless_static = struct { + const msg = "'static' useless without a constant size"; + const kind = .warning; + const w_extra = true; + }; + pub const negative_array_size = struct { + const msg = "array size must be 0 or greater"; + const kind = .@"error"; + }; + pub const array_incomplete_elem = struct { + const msg = "array has incomplete element type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const array_func_elem = struct { + const msg = "arrays cannot have functions as their element type"; + const kind = .@"error"; + }; + pub const static_non_outermost_array = struct { + const msg = "'static' used in non-outermost array type"; + const kind = .@"error"; + }; + pub const qualifier_non_outermost_array = struct { + const msg = "type qualifier used in non-outermost array type"; + const kind = .@"error"; + }; + pub const unterminated_macro_arg_list = struct { + const msg = "unterminated function macro argument list"; + const kind = .@"error"; + }; + pub const unknown_warning = struct { + const msg = "unknown warning '{s}'"; + const extra = .str; + const opt = "unknown-warning-option"; + const kind = .warning; + }; + pub const overflow_signed = struct { + const msg = "overflow in expression; result is '{d}'"; + const extra = .signed; + const opt = "integer-overflow"; + const kind = .warning; + }; + pub const overflow_unsigned = struct { + const msg = overflow_signed.msg; + const extra = .unsigned; + const opt = "integer-overflow"; + const kind = .warning; + }; + pub const int_literal_too_big = struct { + const msg = "integer literal is too large to be represented in any integer type"; + const kind = .@"error"; + }; + pub const indirection_ptr = struct { + const msg = "indirection requires pointer operand"; + const kind = .@"error"; + }; + pub const addr_of_rvalue = struct { + const msg = "cannot take the address of an rvalue"; + const kind = .@"error"; + }; + pub const addr_of_bitfield = struct { + const msg = "address of bit-field requested"; + const kind = .@"error"; + }; + pub const not_assignable = struct { + const msg = "expression is not assignable"; + const kind = .@"error"; + }; + pub const ident_or_l_brace = struct { + const msg = "expected identifier or '{'"; + const kind = .@"error"; + }; + pub const empty_enum = struct { + const msg = "empty enum is invalid"; + const kind = .@"error"; + }; + pub const redefinition = struct { + const msg = "redefinition of '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const previous_definition = struct { + const msg = "previous definition is here"; + const kind = .note; + }; + pub const expected_identifier = struct { + const msg = "expected identifier"; + const kind = .@"error"; + }; + pub const expected_str_literal = struct { + const msg = "expected string literal for diagnostic message in static_assert"; + const kind = .@"error"; + }; + pub const expected_str_literal_in = struct { + const msg = "expected string literal in '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const parameter_missing = struct { + const msg = "parameter named '{s}' is missing"; + const extra = .str; + const kind = .@"error"; + }; + pub const empty_record = struct { + const msg = "empty {s} is a GNU extension"; + const extra = .str; + const opt = "gnu-empty-struct"; + const kind = .off; + const pedantic = true; + }; + pub const empty_record_size = struct { + const msg = "empty {s} has size 0 in C, size 1 in C++"; + const extra = .str; + const opt = "c++-compat"; + const kind = .off; + }; + pub const wrong_tag = struct { + const msg = "use of '{s}' with tag type that does not match previous definition"; + const extra = .str; + const kind = .@"error"; + }; + pub const expected_parens_around_typename = struct { + const msg = "expected parentheses around type name"; + const kind = .@"error"; + }; + pub const alignof_expr = struct { + const msg = "'_Alignof' applied to an expression is a GNU extension"; + const opt = "gnu-alignof-expression"; + const kind = .warning; + const suppress_gnu = true; + }; + pub const invalid_alignof = struct { + const msg = "invalid application of 'alignof' to an incomplete type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const invalid_sizeof = struct { + const msg = "invalid application of 'sizeof' to an incomplete type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const macro_redefined = struct { + const msg = "'{s}' macro redefined"; + const extra = .str; + const opt = "macro-redefined"; + const kind = .warning; + }; + pub const generic_qual_type = struct { + const msg = "generic association with qualifiers cannot be matched with"; + const opt = "generic-qual-type"; + const kind = .warning; + }; + pub const generic_array_type = struct { + const msg = "generic association array type cannot be matched with"; + const opt = "generic-qual-type"; + const kind = .warning; + }; + pub const generic_func_type = struct { + const msg = "generic association function type cannot be matched with"; + const opt = "generic-qual-type"; + const kind = .warning; + }; + pub const generic_duplicate = struct { + const msg = "type '{s}' in generic association compatible with previously specified type"; + const extra = .str; + const kind = .@"error"; + }; + pub const generic_duplicate_here = struct { + const msg = "compatible type '{s}' specified here"; + const extra = .str; + const kind = .note; + }; + pub const generic_duplicate_default = struct { + const msg = "duplicate default generic association"; + const kind = .@"error"; + }; + pub const generic_no_match = struct { + const msg = "controlling expression type '{s}' not compatible with any generic association type"; + const extra = .str; + const kind = .@"error"; + }; + pub const escape_sequence_overflow = struct { + const msg = "escape sequence out of range"; + const kind = .@"error"; + }; + pub const invalid_universal_character = struct { + const msg = "invalid universal character"; + const kind = .@"error"; + }; + pub const multichar_literal = struct { + const msg = "multi-character character constant"; + const opt = "multichar"; + const kind = .warning; + const all = true; + }; + pub const unicode_multichar_literal = struct { + const msg = "Unicode character literals may not contain multiple characters"; + const kind = .@"error"; + }; + pub const wide_multichar_literal = struct { + const msg = "extraneous characters in character constant ignored"; + const kind = .warning; + }; + pub const char_lit_too_wide = struct { + const msg = "character constant too long for its type"; + const kind = .warning; + const all = true; + }; + pub const char_too_large = struct { + const msg = "character too large for enclosing character literal type"; + const kind = .@"error"; + }; + pub const must_use_struct = struct { + const msg = "must use 'struct' tag to refer to type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const must_use_union = struct { + const msg = "must use 'union' tag to refer to type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const must_use_enum = struct { + const msg = "must use 'enum' tag to refer to type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const redefinition_different_sym = struct { + const msg = "redefinition of '{s}' as different kind of symbol"; + const extra = .str; + const kind = .@"error"; + }; + pub const redefinition_incompatible = struct { + const msg = "redefinition of '{s}' with a different type"; + const extra = .str; + const kind = .@"error"; + }; + pub const redefinition_of_parameter = struct { + const msg = "redefinition of parameter '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const invalid_bin_types = struct { + const msg = "invalid operands to binary expression ({s})"; + const extra = .str; + const kind = .@"error"; + }; + pub const comparison_ptr_int = struct { + const msg = "comparison between pointer and integer ({s})"; + const extra = .str; + const opt = "pointer-integer-compare"; + const kind = .warning; + }; + pub const comparison_distinct_ptr = struct { + const msg = "comparison of distinct pointer types ({s})"; + const extra = .str; + const opt = "compare-distinct-pointer-types"; + const kind = .warning; + }; + pub const incompatible_pointers = struct { + const msg = "incompatible pointer types ({s})"; + const extra = .str; + const kind = .@"error"; + }; + pub const invalid_argument_un = struct { + const msg = "invalid argument type '{s}' to unary expression"; + const extra = .str; + const kind = .@"error"; + }; + pub const incompatible_assign = struct { + const msg = "assignment to {s}"; + const extra = .str; + const kind = .@"error"; + }; + pub const implicit_ptr_to_int = struct { + const msg = "implicit pointer to integer conversion from {s}"; + const extra = .str; + const opt = "int-conversion"; + const kind = .warning; + }; + pub const invalid_cast_to_float = struct { + const msg = "pointer cannot be cast to type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const invalid_cast_to_pointer = struct { + const msg = "operand of type '{s}' cannot be cast to a pointer type"; + const extra = .str; + const kind = .@"error"; + }; + pub const invalid_cast_type = struct { + const msg = "cannot cast to non arithmetic or pointer type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const qual_cast = struct { + const msg = "cast to type '{s}' will not preserve qualifiers"; + const extra = .str; + const opt = "cast-qualifiers"; + const kind = .warning; + }; + pub const invalid_index = struct { + const msg = "array subscript is not an integer"; + const kind = .@"error"; + }; + pub const invalid_subscript = struct { + const msg = "subscripted value is not an array or pointer"; + const kind = .@"error"; + }; + pub const array_after = struct { + const msg = "array index {d} is past the end of the array"; + const extra = .unsigned; + const opt = "array-bounds"; + const kind = .warning; + }; + pub const array_before = struct { + const msg = "array index {d} is before the beginning of the array"; + const extra = .signed; + const opt = "array-bounds"; + const kind = .warning; + }; + pub const statement_int = struct { + const msg = "statement requires expression with integer type ('{s}' invalid)"; + const extra = .str; + const kind = .@"error"; + }; + pub const statement_scalar = struct { + const msg = "statement requires expression with scalar type ('{s}' invalid)"; + const extra = .str; + const kind = .@"error"; + }; + pub const func_should_return = struct { + const msg = "non-void function '{s}' should return a value"; + const extra = .str; + const opt = "return-type"; + const kind = .@"error"; + const all = true; + }; + pub const incompatible_return = struct { + const msg = "returning {s}"; + const extra = .str; + const kind = .@"error"; + }; + pub const incompatible_return_sign = struct { + const msg = "returning {s}" ++ PointerSignMessage; + const extra = .str; + const kind = .warning; + const opt = "pointer-sign"; + }; + pub const implicit_int_to_ptr = struct { + const msg = "implicit integer to pointer conversion from {s}"; + const extra = .str; + const opt = "int-conversion"; + const kind = .warning; + }; + pub const func_does_not_return = struct { + const msg = "non-void function '{s}' does not return a value"; + const extra = .str; + const opt = "return-type"; + const kind = .warning; + const all = true; + }; + pub const void_func_returns_value = struct { + const msg = "void function '{s}' should not return a value"; + const extra = .str; + const opt = "return-type"; + const kind = .@"error"; + const all = true; + }; + pub const incompatible_arg = struct { + const msg = "passing {s}"; + const extra = .str; + const kind = .@"error"; + }; + pub const incompatible_ptr_arg = struct { + const msg = "passing {s}"; + const extra = .str; + const kind = .warning; + const opt = "incompatible-pointer-types"; + }; + pub const incompatible_ptr_arg_sign = struct { + const msg = "passing {s}" ++ PointerSignMessage; + const extra = .str; + const kind = .warning; + const opt = "pointer-sign"; + }; + pub const parameter_here = struct { + const msg = "passing argument to parameter here"; + const kind = .note; + }; + pub const atomic_array = struct { + const msg = "atomic cannot be applied to array type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const atomic_func = struct { + const msg = "atomic cannot be applied to function type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const atomic_incomplete = struct { + const msg = "atomic cannot be applied to incomplete type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const addr_of_register = struct { + const msg = "address of register variable requested"; + const kind = .@"error"; + }; + pub const variable_incomplete_ty = struct { + const msg = "variable has incomplete type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const parameter_incomplete_ty = struct { + const msg = "parameter has incomplete type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const tentative_array = struct { + const msg = "tentative array definition assumed to have one element"; + const kind = .warning; + }; + pub const deref_incomplete_ty_ptr = struct { + const msg = "dereferencing pointer to incomplete type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const alignas_on_func = struct { + const msg = "'_Alignas' attribute only applies to variables and fields"; + const kind = .@"error"; + }; + pub const alignas_on_param = struct { + const msg = "'_Alignas' attribute cannot be applied to a function parameter"; + const kind = .@"error"; + }; + pub const minimum_alignment = struct { + const msg = "requested alignment is less than minimum alignment of {d}"; + const extra = .unsigned; + const kind = .@"error"; + }; + pub const maximum_alignment = struct { + const msg = "requested alignment of {d} is too large"; + const extra = .unsigned; + const kind = .@"error"; + }; + pub const negative_alignment = struct { + const msg = "requested negative alignment of {d} is invalid"; + const extra = .signed; + const kind = .@"error"; + }; + pub const align_ignored = struct { + const msg = "'_Alignas' attribute is ignored here"; + const kind = .warning; + }; + pub const zero_align_ignored = struct { + const msg = "requested alignment of zero is ignored"; + const kind = .warning; + }; + pub const non_pow2_align = struct { + const msg = "requested alignment is not a power of 2"; + const kind = .@"error"; + }; + pub const pointer_mismatch = struct { + const msg = "pointer type mismatch ({s})"; + const extra = .str; + const opt = "pointer-type-mismatch"; + const kind = .warning; + }; + pub const static_assert_not_constant = struct { + const msg = "static_assert expression is not an integral constant expression"; + const kind = .@"error"; + }; + pub const static_assert_missing_message = struct { + const msg = "static_assert with no message is a C2X extension"; + const opt = "c2x-extensions"; + const kind = .warning; + const suppress_version = .c2x; + }; + pub const pre_c2x_compat = struct { + const msg = "{s} is incompatible with C standards before C2x"; + const extra = .str; + const kind = .off; + const suppress_unless_version = .c2x; + const opt = "pre-c2x-compat"; + }; + pub const unbound_vla = struct { + const msg = "variable length array must be bound in function definition"; + const kind = .@"error"; + }; + pub const array_too_large = struct { + const msg = "array is too large"; + const kind = .@"error"; + }; + pub const incompatible_ptr_init = struct { + const msg = "incompatible pointer types initializing {s}"; + const extra = .str; + const opt = "incompatible-pointer-types"; + const kind = .warning; + }; + pub const incompatible_ptr_init_sign = struct { + const msg = "incompatible pointer types initializing {s}" ++ PointerSignMessage; + const extra = .str; + const opt = "pointer-sign"; + const kind = .warning; + }; + pub const incompatible_ptr_assign = struct { + const msg = "incompatible pointer types assigning to {s}"; + const extra = .str; + const opt = "incompatible-pointer-types"; + const kind = .warning; + }; + pub const incompatible_ptr_assign_sign = struct { + const msg = "incompatible pointer types assigning to {s} " ++ PointerSignMessage; + const extra = .str; + const opt = "pointer-sign"; + const kind = .warning; + }; + pub const vla_init = struct { + const msg = "variable-sized object may not be initialized"; + const kind = .@"error"; + }; + pub const func_init = struct { + const msg = "illegal initializer type"; + const kind = .@"error"; + }; + pub const incompatible_init = struct { + const msg = "initializing {s}"; + const extra = .str; + const kind = .@"error"; + }; + pub const empty_scalar_init = struct { + const msg = "scalar initializer cannot be empty"; + const kind = .@"error"; + }; + pub const excess_scalar_init = struct { + const msg = "excess elements in scalar initializer"; + const opt = "excess-initializers"; + const kind = .warning; + }; + pub const excess_str_init = struct { + const msg = "excess elements in string initializer"; + const opt = "excess-initializers"; + const kind = .warning; + }; + pub const excess_struct_init = struct { + const msg = "excess elements in struct initializer"; + const opt = "excess-initializers"; + const kind = .warning; + }; + pub const excess_array_init = struct { + const msg = "excess elements in array initializer"; + const opt = "excess-initializers"; + const kind = .warning; + }; + pub const str_init_too_long = struct { + const msg = "initializer-string for char array is too long"; + const opt = "excess-initializers"; + const kind = .warning; + }; + pub const arr_init_too_long = struct { + const msg = "cannot initialize type ({s})"; + const extra = .str; + const kind = .@"error"; + }; + pub const invalid_typeof = struct { + const msg = "'{s} typeof' is invalid"; + const extra = .str; + const kind = .@"error"; + }; + pub const division_by_zero = struct { + const msg = "{s} by zero is undefined"; + const extra = .str; + const opt = "division-by-zero"; + const kind = .warning; + }; + pub const division_by_zero_macro = struct { + const msg = "{s} by zero in preprocessor expression"; + const extra = .str; + const kind = .@"error"; + }; + pub const builtin_choose_cond = struct { + const msg = "'__builtin_choose_expr' requires a constant expression"; + const kind = .@"error"; + }; + pub const alignas_unavailable = struct { + const msg = "'_Alignas' attribute requires integer constant expression"; + const kind = .@"error"; + }; + pub const case_val_unavailable = struct { + const msg = "case value must be an integer constant expression"; + const kind = .@"error"; + }; + pub const enum_val_unavailable = struct { + const msg = "enum value must be an integer constant expression"; + const kind = .@"error"; + }; + pub const incompatible_array_init = struct { + const msg = "cannot initialize array of type {s}"; + const extra = .str; + const kind = .@"error"; + }; + pub const array_init_str = struct { + const msg = "array initializer must be an initializer list or wide string literal"; + const kind = .@"error"; + }; + pub const initializer_overrides = struct { + const msg = "initializer overrides previous initialization"; + const opt = "initializer-overrides"; + const kind = .warning; + const w_extra = true; + }; + pub const previous_initializer = struct { + const msg = "previous initialization"; + const kind = .note; + }; + pub const invalid_array_designator = struct { + const msg = "array designator used for non-array type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const negative_array_designator = struct { + const msg = "array designator value {d} is negative"; + const extra = .signed; + const kind = .@"error"; + }; + pub const oob_array_designator = struct { + const msg = "array designator index {d} exceeds array bounds"; + const extra = .unsigned; + const kind = .@"error"; + }; + pub const invalid_field_designator = struct { + const msg = "field designator used for non-record type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const no_such_field_designator = struct { + const msg = "record type has no field named '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const empty_aggregate_init_braces = struct { + const msg = "initializer for aggregate with no elements requires explicit braces"; + const kind = .@"error"; + }; + pub const ptr_init_discards_quals = struct { + const msg = "initializing {s} discards qualifiers"; + const extra = .str; + const opt = "incompatible-pointer-types-discards-qualifiers"; + const kind = .warning; + }; + pub const ptr_assign_discards_quals = struct { + const msg = "assigning to {s} discards qualifiers"; + const extra = .str; + const opt = "incompatible-pointer-types-discards-qualifiers"; + const kind = .warning; + }; + pub const ptr_ret_discards_quals = struct { + const msg = "returning {s} discards qualifiers"; + const extra = .str; + const opt = "incompatible-pointer-types-discards-qualifiers"; + const kind = .warning; + }; + pub const ptr_arg_discards_quals = struct { + const msg = "passing {s} discards qualifiers"; + const extra = .str; + const opt = "incompatible-pointer-types-discards-qualifiers"; + const kind = .warning; + }; + pub const unknown_attribute = struct { + const msg = "unknown attribute '{s}' ignored"; + const extra = .str; + const opt = "unknown-attributes"; + const kind = .warning; + }; + pub const ignored_attribute = struct { + const msg = "{s}"; + const extra = .str; + const opt = "ignored-attributes"; + const kind = .warning; + }; + pub const invalid_fallthrough = struct { + const msg = "fallthrough annotation does not directly precede switch label"; + const kind = .@"error"; + }; + pub const cannot_apply_attribute_to_statement = struct { + const msg = "'{s}' attribute cannot be applied to a statement"; + const extra = .str; + const kind = .@"error"; + }; + pub const builtin_macro_redefined = struct { + const msg = "redefining builtin macro"; + const opt = "builtin-macro-redefined"; + const kind = .warning; + }; + pub const feature_check_requires_identifier = struct { + const msg = "builtin feature check macro requires a parenthesized identifier"; + const kind = .@"error"; + }; + pub const missing_tok_builtin = struct { + const msg = "missing '{s}', after builtin feature-check macro"; + const extra = .tok_id_expected; + const kind = .@"error"; + }; + pub const gnu_label_as_value = struct { + const msg = "use of GNU address-of-label extension"; + const opt = "gnu-label-as-value"; + const kind = .off; + const pedantic = true; + }; + pub const expected_record_ty = struct { + const msg = "member reference base type '{s}' is not a structure or union"; + const extra = .str; + const kind = .@"error"; + }; + pub const member_expr_not_ptr = struct { + const msg = "member reference type '{s}' is not a pointer; did you mean to use '.'?"; + const extra = .str; + const kind = .@"error"; + }; + pub const member_expr_ptr = struct { + const msg = "member reference type '{s}' is a pointer; did you mean to use '->'?"; + const extra = .str; + const kind = .@"error"; + }; + pub const no_such_member = struct { + const msg = "no member named {s}"; + const extra = .str; + const kind = .@"error"; + }; + pub const malformed_warning_check = struct { + const msg = "{s} expected option name (e.g. \"-Wundef\")"; + const extra = .str; + const opt = "malformed-warning-check"; + const kind = .warning; + const all = true; + }; + pub const invalid_computed_goto = struct { + const msg = "computed goto in function with no address-of-label expressions"; + const kind = .@"error"; + }; + pub const pragma_warning_message = struct { + const msg = "{s}"; + const extra = .str; + const opt = "#pragma-messages"; + const kind = .warning; + }; + pub const pragma_error_message = struct { + const msg = "{s}"; + const extra = .str; + const kind = .@"error"; + }; + pub const pragma_message = struct { + const msg = "#pragma message: {s}"; + const extra = .str; + const kind = .note; + }; + pub const pragma_requires_string_literal = struct { + const msg = "pragma {s} requires string literal"; + const extra = .str; + const kind = .@"error"; + }; + pub const poisoned_identifier = struct { + const msg = "attempt to use a poisoned identifier"; + const kind = .@"error"; + }; + pub const pragma_poison_identifier = struct { + const msg = "can only poison identifier tokens"; + const kind = .@"error"; + }; + pub const pragma_poison_macro = struct { + const msg = "poisoning existing macro"; + const kind = .warning; + }; + pub const newline_eof = struct { + const msg = "no newline at end of file"; + const opt = "newline-eof"; + const kind = .off; + const pedantic = true; + }; + pub const empty_translation_unit = struct { + const msg = "ISO C requires a translation unit to contain at least one declaration"; + const opt = "empty-translation-unit"; + const kind = .off; + const pedantic = true; + }; + pub const omitting_parameter_name = struct { + const msg = "omitting the parameter name in a function definition is a C2x extension"; + const opt = "c2x-extensions"; + const kind = .warning; + const suppress_version = .c2x; + }; + pub const non_int_bitfield = struct { + const msg = "bit-field has non-integer type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const negative_bitwidth = struct { + const msg = "bit-field has negative width ({d})"; + const extra = .signed; + const kind = .@"error"; + }; + pub const zero_width_named_field = struct { + const msg = "named bit-field has zero width"; + const kind = .@"error"; + }; + pub const bitfield_too_big = struct { + const msg = "width of bit-field exceeds width of its type"; + const kind = .@"error"; + }; + pub const invalid_utf8 = struct { + const msg = "source file is not valid UTF-8"; + const kind = .@"error"; + }; + pub const implicitly_unsigned_literal = struct { + const msg = "integer literal is too large to be represented in a signed integer type, interpreting as unsigned"; + const opt = "implicitly-unsigned-literal"; + const kind = .warning; + }; + pub const invalid_preproc_operator = struct { + const msg = "token is not a valid binary operator in a preprocessor subexpression"; + const kind = .@"error"; + }; + pub const invalid_preproc_expr_start = struct { + const msg = "invalid token at start of a preprocessor expression"; + const kind = .@"error"; + }; + pub const c99_compat = struct { + const msg = "using this character in an identifier is incompatible with C99"; + const opt = "c99-compat"; + const kind = .off; + }; + pub const unicode_zero_width = struct { + const msg = "identifier contains Unicode character 4}> that is invisible in some environments"; + const opt = "unicode-homoglyph"; + const extra = .actual_codepoint; + const kind = .warning; + }; + pub const unicode_homoglyph = struct { + const msg = "treating Unicode character 4}> as identifier character rather than as '{u}' symbol"; + const extra = .codepoints; + const opt = "unicode-homoglyph"; + const kind = .warning; + }; + pub const meaningless_asm_qual = struct { + const msg = "meaningless '{s}' on assembly outside function"; + const extra = .str; + const kind = .@"error"; + }; + pub const duplicate_asm_qual = struct { + const msg = "duplicate asm qualifier '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const invalid_asm_str = struct { + const msg = "cannot use {s} string literal in assembly"; + const extra = .str; + const kind = .@"error"; + }; + pub const dollar_in_identifier_extension = struct { + const msg = "'$' in identifier"; + const opt = "dollar-in-identifier-extension"; + const kind = .off; + const suppress_language_option = "dollars_in_identifiers"; + const pedantic = true; + }; + pub const dollars_in_identifiers = struct { + const msg = "illegal character '$' in identifier"; + const kind = .@"error"; + }; + pub const expanded_from_here = struct { + const msg = "expanded from here"; + const kind = .note; + }; + pub const skipping_macro_backtrace = struct { + const msg = "(skipping {d} expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)"; + const extra = .unsigned; + const kind = .note; + }; + pub const pragma_operator_string_literal = struct { + const msg = "_Pragma requires exactly one string literal token"; + const kind = .@"error"; + }; + pub const unknown_gcc_pragma = struct { + const msg = "pragma GCC expected 'error', 'warning', 'diagnostic', 'poison'"; + const opt = "unknown-pragmas"; + const kind = .off; + const all = true; + }; + pub const unknown_gcc_pragma_directive = struct { + const msg = "pragma GCC diagnostic expected 'error', 'warning', 'ignored', 'fatal', 'push', or 'pop'"; + const opt = "unknown-pragmas"; + const kind = .warning; + const all = true; + }; + pub const predefined_top_level = struct { + const msg = "predefined identifier is only valid inside function"; + const opt = "predefined-identifier-outside-function"; + const kind = .warning; + }; + pub const incompatible_va_arg = struct { + const msg = "first argument to va_arg, is of type '{s}' and not 'va_list'"; + const extra = .str; + const kind = .@"error"; + }; + pub const too_many_scalar_init_braces = struct { + const msg = "too many braces around scalar initializer"; + const opt = "many-braces-around-scalar-init"; + const kind = .warning; + }; + pub const uninitialized_in_own_init = struct { + const msg = "variable '{s}' is uninitialized when used within its own initialization"; + const extra = .str; + const opt = "uninitialized"; + const kind = .off; + const all = true; + }; + pub const gnu_statement_expression = struct { + const msg = "use of GNU statement expression extension"; + const opt = "gnu-statement-expression"; + const kind = .off; + const suppress_gnu = true; + const pedantic = true; + }; + pub const stmt_expr_not_allowed_file_scope = struct { + const msg = "statement expression not allowed at file scope"; + const kind = .@"error"; + }; + pub const gnu_imaginary_constant = struct { + const msg = "imaginary constants are a GNU extension"; + const opt = "gnu-imaginary-constant"; + const kind = .off; + const suppress_gnu = true; + const pedantic = true; + }; + pub const plain_complex = struct { + const msg = "plain '_Complex' requires a type specifier; assuming '_Complex double'"; + const kind = .warning; + }; + pub const complex_int = struct { + const msg = "complex integer types are a GNU extension"; + const opt = "gnu-complex-integer"; + const suppress_gnu = true; + const kind = .off; + }; + pub const qual_on_ret_type = struct { + const msg = "'{s}' type qualifier on return type has no effect"; + const opt = "ignored-qualifiers"; + const extra = .str; + const kind = .off; + const all = true; + }; + pub const cli_invalid_standard = struct { + const msg = "invalid standard '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const cli_invalid_target = struct { + const msg = "invalid target '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const cli_invalid_emulate = struct { + const msg = "invalid compiler '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const cli_unknown_arg = struct { + const msg = "unknown argument '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const cli_error = struct { + const msg = "{s}"; + const extra = .str; + const kind = .@"error"; + }; + pub const cli_unused_link_object = struct { + const msg = "{s}: linker input file unused because linking not done"; + const extra = .str; + const kind = .warning; + }; + pub const cli_unknown_linker = struct { + const msg = "unrecognized linker '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const extra_semi = struct { + const msg = "extra ';' outside of a function"; + const opt = "extra-semi"; + const kind = .off; + const pedantic = true; + }; + pub const func_field = struct { + const msg = "field declared as a function"; + const kind = .@"error"; + }; + pub const vla_field = struct { + const msg = "variable length array fields extension is not supported"; + const kind = .@"error"; + }; + pub const field_incomplete_ty = struct { + const msg = "field has incomplete type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const flexible_in_union = struct { + const msg = "flexible array member in union is not allowed"; + const kind = .@"error"; + const suppress_msvc = true; + }; + pub const flexible_non_final = struct { + const msg = "flexible array member is not at the end of struct"; + const kind = .@"error"; + }; + pub const flexible_in_empty = struct { + const msg = "flexible array member in otherwise empty struct"; + const kind = .@"error"; + const suppress_msvc = true; + }; + pub const duplicate_member = struct { + const msg = "duplicate member '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const binary_integer_literal = struct { + const msg = "binary integer literals are a GNU extension"; + const kind = .off; + const opt = "gnu-binary-literal"; + const pedantic = true; + }; + pub const gnu_va_macro = struct { + const msg = "named variadic macros are a GNU extension"; + const opt = "variadic-macros"; + const kind = .off; + const pedantic = true; + }; + pub const builtin_must_be_called = struct { + const msg = "builtin function must be directly called"; + const kind = .@"error"; + }; + pub const va_start_not_in_func = struct { + const msg = "'va_start' cannot be used outside a function"; + const kind = .@"error"; + }; + pub const va_start_fixed_args = struct { + const msg = "'va_start' used in a function with fixed args"; + const kind = .@"error"; + }; + pub const va_start_not_last_param = struct { + const msg = "second argument to 'va_start' is not the last named parameter"; + const opt = "varargs"; + const kind = .warning; + }; + pub const attribute_not_enough_args = struct { + const msg = "'{s}' attribute takes at least {d} argument(s)"; + const kind = .@"error"; + const extra = .attr_arg_count; + }; + pub const attribute_too_many_args = struct { + const msg = "'{s}' attribute takes at most {d} argument(s)"; + const kind = .@"error"; + const extra = .attr_arg_count; + }; + pub const attribute_arg_invalid = struct { + const msg = "Attribute argument is invalid, expected {s} but got {s}"; + const kind = .@"error"; + const extra = .attr_arg_type; + }; + pub const unknown_attr_enum = struct { + const msg = "Unknown `{s}` argument. Possible values are: {s}"; + const kind = .@"error"; + const extra = .attr_enum; + }; + pub const attribute_requires_identifier = struct { + const msg = "'{s}' attribute requires an identifier"; + const kind = .@"error"; + const extra = .str; + }; + pub const declspec_not_enabled = struct { + const msg = "'__declspec' attributes are not enabled; use '-fdeclspec' or '-fms-extensions' to enable support for __declspec attributes"; + const kind = .@"error"; + }; + pub const declspec_attr_not_supported = struct { + const msg = "__declspec attribute '{s}' is not supported"; + const extra = .str; + const opt = "ignored-attributes"; + const kind = .warning; + }; + pub const deprecated_declarations = struct { + const msg = "{s}"; + const extra = .str; + const opt = "deprecated-declarations"; + const kind = .warning; + }; + pub const deprecated_note = struct { + const msg = "'{s}' has been explicitly marked deprecated here"; + const extra = .str; + const opt = "deprecated-declarations"; + const kind = .note; + }; + pub const unavailable = struct { + const msg = "{s}"; + const extra = .str; + const kind = .@"error"; + }; + pub const unavailable_note = struct { + const msg = "'{s}' has been explicitly marked unavailable here"; + const extra = .str; + const kind = .note; + }; + pub const warning_attribute = struct { + const msg = "{s}"; + const extra = .str; + const kind = .warning; + const opt = "attribute-warning"; + }; + pub const error_attribute = struct { + const msg = "{s}"; + const extra = .str; + const kind = .@"error"; + }; + pub const ignored_record_attr = struct { + const msg = "attribute '{s}' is ignored, place it after \"{s}\" to apply attribute to type declaration"; + const extra = .ignored_record_attr; + const kind = .warning; + const opt = "ignored-attributes"; + }; + pub const backslash_newline_escape = struct { + const msg = "backslash and newline separated by space"; + const kind = .warning; + const opt = "backslash-newline-escape"; + }; + pub const array_size_non_int = struct { + const msg = "size of array has non-integer type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const cast_to_smaller_int = struct { + const msg = "cast to smaller integer type {s}"; + const extra = .str; + const kind = .warning; + const opt = "pointer-to-int-cast"; + }; + pub const gnu_switch_range = struct { + const msg = "use of GNU case range extension"; + const opt = "gnu-case-range"; + const kind = .off; + const pedantic = true; + }; + pub const empty_case_range = struct { + const msg = "empty case range specified"; + const kind = .warning; + }; + pub const non_standard_escape_char = struct { + const msg = "use of non-standard escape character '\\e'"; + const kind = .off; + const opt = "pedantic"; + }; + pub const invalid_pp_stringify_escape = struct { + const msg = "invalid string literal, ignoring final '\\'"; + const kind = .warning; + }; + pub const vla = struct { + const msg = "variable length array used"; + const kind = .off; + const opt = "vla"; + }; + pub const float_overflow_conversion = struct { + const msg = "implicit conversion of non-finite value from {s} is undefined"; + const extra = .str; + const kind = .off; + const opt = "float-overflow-conversion"; + }; + pub const float_out_of_range = struct { + const msg = "implicit conversion of out of range value from {s} is undefined"; + const extra = .str; + const kind = .warning; + const opt = "literal-conversion"; + }; + pub const float_zero_conversion = struct { + const msg = "implicit conversion from {s}"; + const extra = .str; + const kind = .off; + const opt = "float-zero-conversion"; + }; + pub const float_value_changed = struct { + const msg = "implicit conversion from {s}"; + const extra = .str; + const kind = .warning; + const opt = "float-conversion"; + }; + pub const float_to_int = struct { + const msg = "implicit conversion turns floating-point number into integer: {s}"; + const extra = .str; + const kind = .off; + const opt = "literal-conversion"; + }; + pub const const_decl_folded = struct { + const msg = "expression is not an integer constant expression; folding it to a constant is a GNU extension"; + const kind = .off; + const opt = "gnu-folding-constant"; + const pedantic = true; + }; + pub const const_decl_folded_vla = struct { + const msg = "variable length array folded to constant array as an extension"; + const kind = .off; + const opt = "gnu-folding-constant"; + const pedantic = true; + }; + pub const redefinition_of_typedef = struct { + const msg = "typedef redefinition with different types ({s})"; + const extra = .str; + const kind = .@"error"; + }; + pub const undefined_macro = struct { + const msg = "'{s}' is not defined, evaluates to 0"; + const extra = .str; + const kind = .off; + const opt = "undef"; + }; + pub const fn_macro_undefined = struct { + const msg = "function-like macro '{s}' is not defined"; + const extra = .str; + const kind = .@"error"; + }; + pub const preprocessing_directive_only = struct { + const msg = "'{s}' must be used within a preprocessing directive"; + const extra = .tok_id_expected; + const kind = .@"error"; + }; + pub const missing_lparen_after_builtin = struct { + const msg = "Missing '(' after built-in macro '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const offsetof_ty = struct { + const msg = "offsetof requires struct or union type, '{s}' invalid"; + const extra = .str; + const kind = .@"error"; + }; + pub const offsetof_incomplete = struct { + const msg = "offsetof of incomplete type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const offsetof_array = struct { + const msg = "offsetof requires array type, '{s}' invalid"; + const extra = .str; + const kind = .@"error"; + }; + pub const pragma_pack_lparen = struct { + const msg = "missing '(' after '#pragma pack' - ignoring"; + const kind = .warning; + const opt = "ignored-pragmas"; + }; + pub const pragma_pack_rparen = struct { + const msg = "missing ')' after '#pragma pack' - ignoring"; + const kind = .warning; + const opt = "ignored-pragmas"; + }; + pub const pragma_pack_unknown_action = struct { + const msg = "unknown action for '#pragma pack' - ignoring"; + const opt = "ignored-pragmas"; + const kind = .warning; + }; + pub const pragma_pack_show = struct { + const msg = "value of #pragma pack(show) == {d}"; + const extra = .unsigned; + const kind = .warning; + }; + pub const pragma_pack_int = struct { + const msg = "expected #pragma pack parameter to be '1', '2', '4', '8', or '16'"; + const opt = "ignored-pragmas"; + const kind = .warning; + }; + pub const pragma_pack_int_ident = struct { + const msg = "expected integer or identifier in '#pragma pack' - ignored"; + const opt = "ignored-pragmas"; + const kind = .warning; + }; + pub const pragma_pack_undefined_pop = struct { + const msg = "specifying both a name and alignment to 'pop' is undefined"; + const kind = .warning; + }; + pub const pragma_pack_empty_stack = struct { + const msg = "#pragma pack(pop, ...) failed: stack empty"; + const opt = "ignored-pragmas"; + const kind = .warning; + }; + pub const cond_expr_type = struct { + const msg = "used type '{s}' where arithmetic or pointer type is required"; + const extra = .str; + const kind = .@"error"; + }; + pub const too_many_includes = struct { + const msg = "#include nested too deeply"; + const kind = .@"error"; + }; + pub const enumerator_too_small = struct { + const msg = "ISO C restricts enumerator values to range of 'int' ({d} is too small)"; + const extra = .signed; + const kind = .off; + const opt = "pedantic"; + }; + pub const enumerator_too_large = struct { + const msg = "ISO C restricts enumerator values to range of 'int' ({d} is too large)"; + const extra = .unsigned; + const kind = .off; + const opt = "pedantic"; + }; + pub const include_next = struct { + const msg = "#include_next is a language extension"; + const kind = .off; + const pedantic = true; + const opt = "gnu-include-next"; + }; + pub const include_next_outside_header = struct { + const msg = "#include_next in primary source file; will search from start of include path"; + const kind = .warning; + const opt = "include-next-outside-header"; + }; + pub const enumerator_overflow = struct { + const msg = "overflow in enumeration value"; + const kind = .warning; + }; + pub const enum_not_representable = struct { + const msg = "incremented enumerator value {s} is not representable in the largest integer type"; + const kind = .warning; + const opt = "enum-too-large"; + const extra = .pow_2_as_string; + }; + pub const enum_too_large = struct { + const msg = "enumeration values exceed range of largest integer"; + const kind = .warning; + const opt = "enum-too-large"; + }; + pub const enum_fixed = struct { + const msg = "enumeration types with a fixed underlying type are a Clang extension"; + const kind = .off; + const pedantic = true; + const opt = "fixed-enum-extension"; + }; + pub const enum_prev_nonfixed = struct { + const msg = "enumeration previously declared with nonfixed underlying type"; + const kind = .@"error"; + }; + pub const enum_prev_fixed = struct { + const msg = "enumeration previously declared with fixed underlying type"; + const kind = .@"error"; + }; + pub const enum_different_explicit_ty = struct { + // str will be like 'new' (was 'old' + const msg = "enumeration redeclared with different underlying type {s})"; + const extra = .str; + const kind = .@"error"; + }; + pub const enum_not_representable_fixed = struct { + const msg = "enumerator value is not representable in the underlying type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const transparent_union_wrong_type = struct { + const msg = "'transparent_union' attribute only applies to unions"; + const opt = "ignored-attributes"; + const kind = .warning; + }; + pub const transparent_union_one_field = struct { + const msg = "transparent union definition must contain at least one field; transparent_union attribute ignored"; + const opt = "ignored-attributes"; + const kind = .warning; + }; + pub const transparent_union_size = struct { + const msg = "size of field {s} bits) does not match the size of the first field in transparent union; transparent_union attribute ignored"; + const extra = .str; + const opt = "ignored-attributes"; + const kind = .warning; + }; + pub const transparent_union_size_note = struct { + const msg = "size of first field is {d}"; + const extra = .unsigned; + const kind = .note; + }; + pub const designated_init_invalid = struct { + const msg = "'designated_init' attribute is only valid on 'struct' type'"; + const kind = .@"error"; + }; + pub const designated_init_needed = struct { + const msg = "positional initialization of field in 'struct' declared with 'designated_init' attribute"; + const opt = "designated-init"; + const kind = .warning; + }; + pub const ignore_common = struct { + const msg = "ignoring attribute 'common' because it conflicts with attribute 'nocommon'"; + const opt = "ignored-attributes"; + const kind = .warning; + }; + pub const ignore_nocommon = struct { + const msg = "ignoring attribute 'nocommon' because it conflicts with attribute 'common'"; + const opt = "ignored-attributes"; + const kind = .warning; + }; + pub const non_string_ignored = struct { + const msg = "'nonstring' attribute ignored on objects of type '{s}'"; + const opt = "ignored-attributes"; + const kind = .warning; + }; + pub const local_variable_attribute = struct { + const msg = "'{s}' attribute only applies to local variables"; + const extra = .str; + const opt = "ignored-attributes"; + const kind = .warning; + }; + pub const ignore_cold = struct { + const msg = "ignoring attribute 'cold' because it conflicts with attribute 'hot'"; + const opt = "ignored-attributes"; + const kind = .warning; + }; + pub const ignore_hot = struct { + const msg = "ignoring attribute 'hot' because it conflicts with attribute 'cold'"; + const opt = "ignored-attributes"; + const kind = .warning; + }; + pub const ignore_noinline = struct { + const msg = "ignoring attribute 'noinline' because it conflicts with attribute 'always_inline'"; + const opt = "ignored-attributes"; + const kind = .warning; + }; + pub const ignore_always_inline = struct { + const msg = "ignoring attribute 'always_inline' because it conflicts with attribute 'noinline'"; + const opt = "ignored-attributes"; + const kind = .warning; + }; + pub const invalid_noreturn = struct { + const msg = "function '{s}' declared 'noreturn' should not return"; + const extra = .str; + const kind = .warning; + const opt = "invalid-noreturn"; + }; + pub const nodiscard_unused = struct { + const msg = "ignoring return value of '{s}', declared with 'nodiscard' attribute"; + const extra = .str; + const kind = .warning; + const op = "unused-result"; + }; + pub const warn_unused_result = struct { + const msg = "ignoring return value of '{s}', declared with 'warn_unused_result' attribute"; + const extra = .str; + const kind = .warning; + const op = "unused-result"; + }; + pub const invalid_vec_elem_ty = struct { + const msg = "invalid vector element type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const vec_size_not_multiple = struct { + const msg = "vector size not an integral multiple of component size"; + const kind = .@"error"; + }; + pub const invalid_imag = struct { + const msg = "invalid type '{s}' to __imag operator"; + const extra = .str; + const kind = .@"error"; + }; + pub const invalid_real = struct { + const msg = "invalid type '{s}' to __real operator"; + const extra = .str; + const kind = .@"error"; + }; + pub const zero_length_array = struct { + const msg = "zero size arrays are an extension"; + const kind = .off; + const pedantic = true; + const opt = "zero-length-array"; + }; + pub const old_style_flexible_struct = struct { + const msg = "array index {d} is past the end of the array"; + const extra = .unsigned; + const kind = .off; + const pedantic = true; + const opt = "old-style-flexible-struct"; + }; + pub const comma_deletion_va_args = struct { + const msg = "token pasting of ',' and __VA_ARGS__ is a GNU extension"; + const kind = .off; + const pedantic = true; + const opt = "gnu-zero-variadic-macro-arguments"; + const suppress_gcc = true; + }; + pub const main_return_type = struct { + const msg = "return type of 'main' is not 'int'"; + const kind = .warning; + const opt = "main-return-type"; + }; + pub const expansion_to_defined = struct { + const msg = "macro expansion producing 'defined' has undefined behavior"; + const kind = .off; + const pedantic = true; + const opt = "expansion-to-defined"; + }; + pub const invalid_int_suffix = struct { + const msg = "invalid suffix '{s}' on integer constant"; + const extra = .str; + const kind = .@"error"; + }; + pub const invalid_float_suffix = struct { + const msg = "invalid suffix '{s}' on floating constant"; + const extra = .str; + const kind = .@"error"; + }; + pub const invalid_octal_digit = struct { + const msg = "invalid digit '{c}' in octal constant"; + const extra = .ascii; + const kind = .@"error"; + }; + pub const invalid_binary_digit = struct { + const msg = "invalid digit '{c}' in binary constant"; + const extra = .ascii; + const kind = .@"error"; + }; + pub const exponent_has_no_digits = struct { + const msg = "exponent has no digits"; + const kind = .@"error"; + }; + pub const hex_floating_constant_requires_exponent = struct { + const msg = "hexadecimal floating constant requires an exponent"; + const kind = .@"error"; + }; + pub const sizeof_returns_zero = struct { + const msg = "sizeof returns 0"; + const kind = .warning; + const suppress_gcc = true; + const suppress_clang = true; + }; + pub const declspec_not_allowed_after_declarator = struct { + const msg = "'declspec' attribute not allowed after declarator"; + const kind = .@"error"; + }; + pub const declarator_name_tok = struct { + const msg = "this declarator"; + const kind = .note; + }; + pub const type_not_supported_on_target = struct { + const msg = "{s} is not supported on this target"; + const extra = .str; + const kind = .@"error"; + }; + pub const bit_int = struct { + const msg = "'_BitInt' in C17 and earlier is a Clang extension'"; + const kind = .off; + const pedantic = true; + const opt = "bit-int-extension"; + const suppress_version = .c2x; + }; + pub const unsigned_bit_int_too_small = struct { + const msg = "{s} must have a bit size of at least 1"; + const extra = .str; + const kind = .@"error"; + }; + pub const signed_bit_int_too_small = struct { + const msg = "{s} must have a bit size of at least 2"; + const extra = .str; + const kind = .@"error"; + }; + pub const bit_int_too_big = struct { + const msg = "{s} of bit sizes greater than " ++ std.fmt.comptimePrint("{d}", .{Compilation.bit_int_max_bits}) ++ " not supported"; + const extra = .str; + const kind = .@"error"; + }; + pub const keyword_macro = struct { + const msg = "keyword is hidden by macro definition"; + const kind = .off; + const pedantic = true; + const opt = "keyword-macro"; + }; + pub const ptr_arithmetic_incomplete = struct { + const msg = "arithmetic on a pointer to an incomplete type '{s}'"; + const extra = .str; + const kind = .@"error"; + }; + pub const callconv_not_supported = struct { + const msg = "'{s}' calling convention is not supported for this target"; + const extra = .str; + const opt = "ignored-attributes"; + const kind = .warning; + }; + pub const pointer_arith_void = struct { + const msg = "invalid application of '{s}' to a void type"; + const extra = .str; + const kind = .off; + const pedantic = true; + const opt = "pointer-arith"; + }; + pub const sizeof_array_arg = struct { + const msg = "sizeof on array function parameter will return size of {s}"; + const extra = .str; + const kind = .warning; + const opt = "sizeof-array-argument"; + }; + pub const array_address_to_bool = struct { + const msg = "address of array '{s}' will always evaluate to 'true'"; + const extra = .str; + const kind = .warning; + const opt = "pointer-bool-conversion"; + }; + pub const string_literal_to_bool = struct { + const msg = "implicit conversion turns string literal into bool: {s}"; + const extra = .str; + const kind = .off; + const opt = "string-conversion"; + }; + pub const constant_expression_conversion_not_allowed = struct { + const msg = "this conversion is not allowed in a constant expression"; + const kind = .note; + }; + pub const invalid_object_cast = struct { + const msg = "cannot cast an object of type {s}"; + const extra = .str; + const kind = .@"error"; + }; + pub const cli_invalid_fp_eval_method = struct { + const msg = "unsupported argument '{s}' to option '-ffp-eval-method='; expected 'source', 'double', or 'extended'"; + const extra = .str; + const kind = .@"error"; + }; + pub const suggest_pointer_for_invalid_fp16 = struct { + const msg = "{s} cannot have __fp16 type; did you forget * ?"; + const extra = .str; + const kind = .@"error"; + }; + pub const bitint_suffix = struct { + const msg = "'_BitInt' suffix for literals is a C2x extension"; + const opt = "c2x-extensions"; + const kind = .warning; + const suppress_version = .c2x; + }; + pub const auto_type_extension = struct { + const msg = "'__auto_type' is a GNU extension"; + const opt = "gnu-auto-type"; + const kind = .off; + const pedantic = true; + }; + pub const auto_type_not_allowed = struct { + const msg = "'__auto_type' not allowed in {s}"; + const kind = .@"error"; + const extra = .str; + }; + pub const auto_type_requires_initializer = struct { + const msg = "declaration of variable '{s}' with deduced type requires an initializer"; + const kind = .@"error"; + const extra = .str; + }; + pub const auto_type_requires_single_declarator = struct { + const msg = "'__auto_type' may only be used with a single declarator"; + const kind = .@"error"; + }; + pub const auto_type_requires_plain_declarator = struct { + const msg = "'__auto_type' requires a plain identifier as declarator"; + const kind = .@"error"; + }; + pub const invalid_cast_to_auto_type = struct { + const msg = "invalid cast to '__auto_type'"; + const kind = .@"error"; + }; + pub const auto_type_from_bitfield = struct { + const msg = "cannot use bit-field as '__auto_type' initializer"; + const kind = .@"error"; + }; + pub const array_of_auto_type = struct { + const msg = "'{s}' declared as array of '__auto_type'"; + const kind = .@"error"; + const extra = .str; + }; + pub const auto_type_with_init_list = struct { + const msg = "cannot use '__auto_type' with initializer list"; + const kind = .@"error"; + }; + pub const missing_semicolon = struct { + const msg = "expected ';' at end of declaration list"; + const kind = .warning; + }; + pub const tentative_definition_incomplete = struct { + const msg = "tentative definition has type '{s}' that is never completed"; + const kind = .@"error"; + const extra = .str; + }; + pub const forward_declaration_here = struct { + const msg = "forward declaration of '{s}'"; + const kind = .note; + const extra = .str; + }; + pub const gnu_union_cast = struct { + const msg = "cast to union type is a GNU extension"; + const opt = "gnu-union-cast"; + const kind = .off; + const pedantic = true; + }; + pub const invalid_union_cast = struct { + const msg = "cast to union type from type '{s}' not present in union"; + const kind = .@"error"; + const extra = .str; + }; + pub const cast_to_incomplete_type = struct { + const msg = "cast to incomplete type '{s}'"; + const kind = .@"error"; + const extra = .str; + }; + pub const invalid_source_epoch = struct { + const msg = "environment variable SOURCE_DATE_EPOCH must expand to a non-negative integer less than or equal to 253402300799"; + const kind = .@"error"; + }; + pub const fuse_ld_path = struct { + const msg = "'-fuse-ld=' taking a path is deprecated; use '--ld-path=' instead"; + const kind = .off; + const opt = "fuse-ld-path"; + }; + pub const invalid_rtlib = struct { + const msg = "invalid runtime library name '{s}'"; + const kind = .@"error"; + const extra = .str; + }; + pub const unsupported_rtlib_gcc = struct { + const msg = "unsupported runtime library 'libgcc' for platform '{s}'"; + const kind = .@"error"; + const extra = .str; + }; + pub const invalid_unwindlib = struct { + const msg = "invalid unwind library name '{s}'"; + const kind = .@"error"; + const extra = .str; + }; + pub const incompatible_unwindlib = struct { + const msg = "--rtlib=libgcc requires --unwindlib=libgcc"; + const kind = .@"error"; + }; + pub const gnu_asm_disabled = struct { + const msg = "GNU-style inline assembly is disabled"; + const kind = .@"error"; + }; + pub const extension_token_used = struct { + const msg = "extension used"; + const kind = .off; + const pedantic = true; + const opt = "language-extension-token"; + }; + pub const complex_component_init = struct { + const msg = "complex initialization specifying real and imaginary components is an extension"; + const opt = "complex-component-init"; + const kind = .off; + const pedantic = true; + }; + pub const complex_prefix_postfix_op = struct { + const msg = "ISO C does not support '++'/'--' on complex type '{s}'"; + const opt = "pedantic"; + const extra = .str; + const kind = .off; + const pedantic = true; + }; + pub const not_floating_type = struct { + const msg = "argument type '{s}' is not a real floating point type"; + const extra = .str; + const kind = .@"error"; + }; + pub const argument_types_differ = struct { + const msg = "arguments are of different types ({s})"; + const extra = .str; + const kind = .@"error"; + }; +}; + +list: std.ArrayListUnmanaged(Message) = .{}, +arena: std.heap.ArenaAllocator, +color: bool = true, +fatal_errors: bool = false, +options: Options = .{}, +errors: u32 = 0, +macro_backtrace_limit: u32 = 6, + +pub fn warningExists(name: []const u8) bool { + inline for (std.meta.fields(Options)) |f| { + if (mem.eql(u8, f.name, name)) return true; + } + return false; +} + +pub fn set(diag: *Diagnostics, name: []const u8, to: Kind) !void { + inline for (std.meta.fields(Options)) |f| { + if (mem.eql(u8, f.name, name)) { + @field(diag.options, f.name) = to; + return; + } + } + try diag.add(.{ + .tag = .unknown_warning, + .extra = .{ .str = name }, + }, &.{}); +} + +pub fn init(gpa: Allocator) Diagnostics { + return .{ + .arena = std.heap.ArenaAllocator.init(gpa), + }; +} + +pub fn deinit(diag: *Diagnostics) void { + diag.list.deinit(diag.arena.allocator()); + diag.arena.deinit(); +} + +pub fn add(diag: *Diagnostics, msg: Message, expansion_locs: []const Source.Location) Compilation.Error!void { + const kind = diag.tagKind(msg.tag); + if (kind == .off) return; + var copy = msg; + copy.kind = kind; + + if (expansion_locs.len != 0) copy.loc = expansion_locs[expansion_locs.len - 1]; + try diag.list.append(diag.arena.allocator(), copy); + if (expansion_locs.len != 0) { + // Add macro backtrace notes in reverse order omitting from the middle if needed. + var i = expansion_locs.len - 1; + const half = diag.macro_backtrace_limit / 2; + const limit = if (i < diag.macro_backtrace_limit) 0 else i - half; + try diag.list.ensureUnusedCapacity( + diag.arena.allocator(), + if (limit == 0) expansion_locs.len else diag.macro_backtrace_limit + 1, + ); + while (i > limit) { + i -= 1; + diag.list.appendAssumeCapacity(.{ + .tag = .expanded_from_here, + .kind = .note, + .loc = expansion_locs[i], + }); + } + if (limit != 0) { + diag.list.appendAssumeCapacity(.{ + .tag = .skipping_macro_backtrace, + .kind = .note, + .extra = .{ .unsigned = expansion_locs.len - diag.macro_backtrace_limit }, + }); + i = half - 1; + while (i > 0) { + i -= 1; + diag.list.appendAssumeCapacity(.{ + .tag = .expanded_from_here, + .kind = .note, + .loc = expansion_locs[i], + }); + } + } + + diag.list.appendAssumeCapacity(.{ + .tag = .expanded_from_here, + .kind = .note, + .loc = msg.loc, + }); + } + if (kind == .@"fatal error" or (kind == .@"error" and diag.fatal_errors)) + return error.FatalError; +} + +pub fn fatal( + diag: *Diagnostics, + path: []const u8, + line: []const u8, + line_no: u32, + col: u32, + comptime fmt: []const u8, + args: anytype, +) Compilation.Error { + var m = MsgWriter.init(diag.color); + defer m.deinit(); + + m.location(path, line_no, col); + m.start(.@"fatal error"); + m.print(fmt, args); + m.end(line, col, false); + + diag.errors += 1; + return error.FatalError; +} + +pub fn fatalNoSrc(diag: *Diagnostics, comptime fmt: []const u8, args: anytype) error{FatalError} { + if (!diag.color) { + std.debug.print("fatal error: " ++ fmt ++ "\n", args); + } else { + const std_err = std.io.getStdErr().writer(); + util.setColor(.red, std_err); + std_err.writeAll("fatal error: ") catch {}; + util.setColor(.white, std_err); + std_err.print(fmt ++ "\n", args) catch {}; + util.setColor(.reset, std_err); + } + diag.errors += 1; + return error.FatalError; +} + +pub fn render(comp: *Compilation) void { + if (comp.diag.list.items.len == 0) return; + var m = defaultMsgWriter(comp); + defer m.deinit(); + renderMessages(comp, &m); +} +pub fn defaultMsgWriter(comp: *const Compilation) MsgWriter { + return MsgWriter.init(comp.diag.color); +} + +pub fn renderMessages(comp: *Compilation, m: anytype) void { + var errors: u32 = 0; + var warnings: u32 = 0; + for (comp.diag.list.items) |msg| { + switch (msg.kind) { + .@"fatal error", .@"error" => errors += 1, + .warning => warnings += 1, + .note => {}, + .off => continue, // happens if an error is added before it is disabled + .default => unreachable, + } + renderMessage(comp, m, msg); + } + const w_s: []const u8 = if (warnings == 1) "" else "s"; + const e_s: []const u8 = if (errors == 1) "" else "s"; + if (errors != 0 and warnings != 0) { + m.print("{d} warning{s} and {d} error{s} generated.\n", .{ warnings, w_s, errors, e_s }); + } else if (warnings != 0) { + m.print("{d} warning{s} generated.\n", .{ warnings, w_s }); + } else if (errors != 0) { + m.print("{d} error{s} generated.\n", .{ errors, e_s }); + } + + comp.diag.list.items.len = 0; + comp.diag.errors += errors; +} + +pub fn renderMessage(comp: *Compilation, m: anytype, msg: Message) void { + var line: ?[]const u8 = null; + var end_with_splice = false; + const width = if (msg.loc.id != .unused) blk: { + var loc = msg.loc; + switch (msg.tag) { + .escape_sequence_overflow, + .invalid_universal_character, + .non_standard_escape_char, + // use msg.extra.unsigned for index into string literal + => loc.byte_offset += @truncate(msg.extra.unsigned), + else => {}, + } + const source = comp.getSource(loc.id); + var line_col = source.lineCol(loc); + line = line_col.line; + end_with_splice = line_col.end_with_splice; + if (msg.tag == .backslash_newline_escape) { + line = line_col.line[0 .. line_col.col - 1]; + line_col.col += 1; + line_col.width += 1; + } + m.location(source.path, line_col.line_no, line_col.col); + break :blk line_col.width; + } else 0; + + m.start(msg.kind); + @setEvalBranchQuota(1500); + switch (msg.tag) { + inline else => |tag| { + const info = @field(messages, @tagName(tag)); + if (@hasDecl(info, "extra")) { + switch (info.extra) { + .str => m.print(info.msg, .{msg.extra.str}), + .tok_id => m.print(info.msg, .{ + msg.extra.tok_id.expected.symbol(), + msg.extra.tok_id.actual.symbol(), + }), + .tok_id_expected => m.print(info.msg, .{msg.extra.tok_id_expected.symbol()}), + .arguments => m.print(info.msg, .{ msg.extra.arguments.expected, msg.extra.arguments.actual }), + .codepoints => m.print(info.msg, .{ + msg.extra.codepoints.actual, + msg.extra.codepoints.resembles, + }), + .attr_arg_count => m.print(info.msg, .{ + @tagName(msg.extra.attr_arg_count.attribute), + msg.extra.attr_arg_count.expected, + }), + .attr_arg_type => m.print(info.msg, .{ + msg.extra.attr_arg_type.expected.toString(), + msg.extra.attr_arg_type.actual.toString(), + }), + .actual_codepoint => m.print(info.msg, .{msg.extra.actual_codepoint}), + .ascii => m.print(info.msg, .{msg.extra.ascii}), + .unsigned => m.print(info.msg, .{msg.extra.unsigned}), + .pow_2_as_string => m.print(info.msg, .{switch (msg.extra.pow_2_as_string) { + 63 => "9223372036854775808", + 64 => "18446744073709551616", + 127 => "170141183460469231731687303715884105728", + 128 => "340282366920938463463374607431768211456", + else => unreachable, + }}), + .signed => m.print(info.msg, .{msg.extra.signed}), + .attr_enum => m.print(info.msg, .{ + @tagName(msg.extra.attr_enum.tag), + Attribute.Formatting.choices(msg.extra.attr_enum.tag), + }), + .ignored_record_attr => m.print(info.msg, .{ + @tagName(msg.extra.ignored_record_attr.tag), + @tagName(msg.extra.ignored_record_attr.specifier), + }), + .builtin_with_header => m.print(info.msg, .{ + @tagName(msg.extra.builtin_with_header.header), + @tagName(msg.extra.builtin_with_header.builtin), + }), + else => @compileError("invalid extra kind " ++ @tagName(info.extra)), + } + } else { + m.write(info.msg); + } + + if (@hasDecl(info, "opt")) { + if (msg.kind == .@"error" and info.kind != .@"error") { + m.print(" [-Werror,-W{s}]", .{info.opt}); + } else if (msg.kind != .note) { + m.print(" [-W{s}]", .{info.opt}); + } + } + }, + } + + m.end(line, width, end_with_splice); +} + +fn tagKind(diag: *Diagnostics, tag: Tag) Kind { + // XXX: horrible hack, do not do this + const comp = @fieldParentPtr(Compilation, "diag", diag); + + var kind: Kind = undefined; + switch (tag) { + inline else => |tag_val| { + const info = @field(messages, @tagName(tag_val)); + kind = info.kind; + + // stage1 doesn't like when I combine these ifs + if (@hasDecl(info, "all")) { + if (diag.options.all != .default) kind = diag.options.all; + } + if (@hasDecl(info, "w_extra")) { + if (diag.options.extra != .default) kind = diag.options.extra; + } + if (@hasDecl(info, "pedantic")) { + if (diag.options.pedantic != .default) kind = diag.options.pedantic; + } + if (@hasDecl(info, "opt")) { + if (@field(diag.options, info.opt) != .default) kind = @field(diag.options, info.opt); + } + if (@hasDecl(info, "suppress_version")) if (comp.langopts.standard.atLeast(info.suppress_version)) return .off; + if (@hasDecl(info, "suppress_unless_version")) if (!comp.langopts.standard.atLeast(info.suppress_unless_version)) return .off; + if (@hasDecl(info, "suppress_gnu")) if (comp.langopts.standard.isExplicitGNU()) return .off; + if (@hasDecl(info, "suppress_language_option")) if (!@field(comp.langopts, info.suppress_language_option)) return .off; + if (@hasDecl(info, "suppress_gcc")) if (comp.langopts.emulate == .gcc) return .off; + if (@hasDecl(info, "suppress_clang")) if (comp.langopts.emulate == .clang) return .off; + if (@hasDecl(info, "suppress_msvc")) if (comp.langopts.emulate == .msvc) return .off; + if (kind == .@"error" and diag.fatal_errors) kind = .@"fatal error"; + return kind; + }, + } +} + +const MsgWriter = struct { + w: std.io.BufferedWriter(4096, std.fs.File.Writer), + color: bool, + + fn init(color: bool) MsgWriter { + std.debug.getStderrMutex().lock(); + return .{ + .w = std.io.bufferedWriter(std.io.getStdErr().writer()), + .color = color, + }; + } + + pub fn deinit(m: *MsgWriter) void { + m.w.flush() catch {}; + std.debug.getStderrMutex().unlock(); + } + + pub fn print(m: *MsgWriter, comptime fmt: []const u8, args: anytype) void { + m.w.writer().print(fmt, args) catch {}; + } + + fn write(m: *MsgWriter, msg: []const u8) void { + m.w.writer().writeAll(msg) catch {}; + } + + fn setColor(m: *MsgWriter, color: util.Color) void { + util.setColor(color, m.w.writer()); + } + + fn location(m: *MsgWriter, path: []const u8, line: u32, col: u32) void { + const prefix = if (std.fs.path.dirname(path) == null and path[0] != '<') "." ++ std.fs.path.sep_str else ""; + if (!m.color) { + m.print("{s}{s}:{d}:{d}: ", .{ prefix, path, line, col }); + } else { + m.setColor(.white); + m.print("{s}{s}:{d}:{d}: ", .{ prefix, path, line, col }); + } + } + + fn start(m: *MsgWriter, kind: Kind) void { + if (!m.color) { + m.print("{s}: ", .{@tagName(kind)}); + } else { + switch (kind) { + .@"fatal error", .@"error" => m.setColor(.red), + .note => m.setColor(.cyan), + .warning => m.setColor(.purple), + .off, .default => unreachable, + } + m.write(switch (kind) { + .@"fatal error" => "fatal error: ", + .@"error" => "error: ", + .note => "note: ", + .warning => "warning: ", + .off, .default => unreachable, + }); + m.setColor(.white); + } + } + + fn end(m: *MsgWriter, maybe_line: ?[]const u8, col: u32, end_with_splice: bool) void { + const line = maybe_line orelse { + m.write("\n"); + return; + }; + const trailer = if (end_with_splice) "\\ " else ""; + if (!m.color) { + m.print("\n{s}{s}\n", .{ line, trailer }); + m.print("{s: >[1]}^\n", .{ "", col }); + } else { + m.setColor(.reset); + m.print("\n{s}{s}\n{s: >[3]}", .{ line, trailer, "", col }); + m.setColor(.green); + m.write("^\n"); + m.setColor(.reset); + } + } +}; diff --git a/deps/aro/Driver.zig b/deps/aro/Driver.zig new file mode 100644 index 000000000000..f3ebde583be2 --- /dev/null +++ b/deps/aro/Driver.zig @@ -0,0 +1,683 @@ +const std = @import("std"); +const mem = std.mem; +const Allocator = mem.Allocator; +const process = std.process; +const Codegen = @import("Codegen_legacy.zig"); +const Compilation = @import("Compilation.zig"); +const LangOpts = @import("LangOpts.zig"); +const Preprocessor = @import("Preprocessor.zig"); +const Parser = @import("Parser.zig"); +const Source = @import("Source.zig"); +const Toolchain = @import("Toolchain.zig"); +const util = @import("util.zig"); +const target_util = @import("target.zig"); + +const Driver = @This(); + +pub const Linker = enum { + ld, + bfd, + gold, + lld, + mold, +}; + +comp: *Compilation, +inputs: std.ArrayListUnmanaged(Source) = .{}, +link_objects: std.ArrayListUnmanaged([]const u8) = .{}, +output_name: ?[]const u8 = null, +sysroot: ?[]const u8 = null, +temp_file_count: u32 = 0, +only_preprocess: bool = false, +only_syntax: bool = false, +only_compile: bool = false, +only_preprocess_and_compile: bool = false, +verbose_ast: bool = false, +verbose_pp: bool = false, +verbose_ir: bool = false, +verbose_linker_args: bool = false, + +/// Full path to the aro executable +aro_name: []const u8 = "", + +/// Value of --triple= passed via CLI +raw_target_triple: ?[]const u8 = null, + +// linker options +use_linker: ?[]const u8 = null, +linker_path: ?[]const u8 = null, +nodefaultlibs: bool = false, +nolibc: bool = false, +nostartfiles: bool = false, +nostdlib: bool = false, +pie: ?bool = null, +rdynamic: bool = false, +relocatable: bool = false, +rtlib: ?[]const u8 = null, +shared: bool = false, +shared_libgcc: bool = false, +static: bool = false, +static_libgcc: bool = false, +static_pie: bool = false, +strip: bool = false, +unwindlib: ?[]const u8 = null, + +pub fn deinit(d: *Driver) void { + for (d.link_objects.items[d.link_objects.items.len - d.temp_file_count ..]) |obj| { + std.fs.deleteFileAbsolute(obj) catch {}; + d.comp.gpa.free(obj); + } + d.inputs.deinit(d.comp.gpa); + d.link_objects.deinit(d.comp.gpa); + d.* = undefined; +} + +pub const usage = + \\Usage {s}: [options] file.. + \\ + \\General options: + \\ -h, --help Print this message. + \\ -v, --version Print aro version. + \\ + \\Compile options: + \\ -c, --compile Only run preprocess, compile, and assemble steps + \\ -D = Define to (defaults to 1) + \\ -E Only run the preprocessor + \\ -fchar8_t Enable char8_t (enabled by default in C2X and later) + \\ -fno-char8_t Disable char8_t (disabled by default for pre-C2X) + \\ -fcolor-diagnostics Enable colors in diagnostics + \\ -fno-color-diagnostics Disable colors in diagnostics + \\ -fdeclspec Enable support for __declspec attributes + \\ -fno-declspec Disable support for __declspec attributes + \\ -ffp-eval-method=[source|double|extended] + \\ Evaluation method to use for floating-point arithmetic + \\ -fgnu-inline-asm Enable GNU style inline asm (default: enabled) + \\ -fno-gnu-inline-asm Disable GNU style inline asm + \\ -fms-extensions Enable support for Microsoft extensions + \\ -fno-ms-extensions Disable support for Microsoft extensions + \\ -fdollars-in-identifiers + \\ Allow '$' in identifiers + \\ -fno-dollars-in-identifiers + \\ Disallow '$' in identifiers + \\ -fmacro-backtrace-limit= + \\ Set limit on how many macro expansion traces are shown in errors (default 6) + \\ -fnative-half-type Use the native half type for __fp16 instead of promoting to float + \\ -fnative-half-arguments-and-returns + \\ Allow half-precision function arguments and return values + \\ -fshort-enums Use the narrowest possible integer type for enums + \\ -fno-short-enums Use "int" as the tag type for enums + \\ -fsigned-char "char" is signed + \\ -fno-signed-char "char" is unsigned + \\ -fsyntax-only Only run the preprocessor, parser, and semantic analysis stages + \\ -funsigned-char "char" is unsigned + \\ -fno-unsigned-char "char" is signed + \\ -I Add directory to include search path + \\ -isystem Add directory to SYSTEM include search path + \\ --emulate=[clang|gcc|msvc] + \\ Select which C compiler to emulate (default clang) + \\ -o Write output to + \\ -pedantic Warn on language extensions + \\ --rtlib= Compiler runtime library to use (libgcc or compiler-rt) + \\ -std= Specify language standard + \\ -S, --assemble Only run preprocess and compilation steps + \\ --sysroot= Use dir as the logical root directory for headers and libraries (not fully implemented) + \\ --target= Generate code for the given target + \\ -U Undefine + \\ -Werror Treat all warnings as errors + \\ -Werror= Treat warning as error + \\ -W Enable the specified warning + \\ -Wno- Disable the specified warning + \\ + \\Link options: + \\ -fuse-ld=[bfd|gold|lld|mold] + \\ Use specific linker + \\ -nodefaultlibs Do not use the standard system libraries when linking. + \\ -nolibc Do not use the C library or system libraries tightly coupled with it when linking. + \\ -nostdlib Do not use the standard system startup files or libraries when linking + \\ -nostartfiles Do not use the standard system startup files when linking. + \\ -pie Produce a dynamically linked position independent executable on targets that support it. + \\ --ld-path= Use linker specified by + \\ -r Produce a relocatable object as output. + \\ -rdynamic Pass the flag -export-dynamic to the ELF linker, on targets that support it. + \\ -s Remove all symbol table and relocation information from the executable. + \\ -shared Produce a shared object which can then be linked with other objects to form an executable. + \\ -shared-libgcc On systems that provide libgcc as a shared library, force the use of the shared version + \\ -static On systems that support dynamic linking, this overrides -pie and prevents linking with the shared libraries. + \\ -static-libgcc On systems that provide libgcc as a shared library, force the use of the static version + \\ -static-pie Produce a static position independent executable on targets that support it. + \\ --unwindlib= Unwind library to use ("none", "libgcc", or "libunwind") If not specified, will match runtime library + \\ + \\Debug options: + \\ --verbose-ast Dump produced AST to stdout + \\ --verbose-pp Dump preprocessor state + \\ --verbose-ir Dump ir to stdout + \\ --verbose-linker-args Dump linker args to stdout + \\ + \\ +; + +/// Process command line arguments, returns true if something was written to std_out. +pub fn parseArgs( + d: *Driver, + std_out: anytype, + macro_buf: anytype, + args: []const []const u8, +) !bool { + var i: usize = 1; + var color_setting: enum { + on, + off, + unset, + } = .unset; + while (i < args.len) : (i += 1) { + const arg = args[i]; + if (mem.startsWith(u8, arg, "-") and arg.len > 1) { + if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { + std_out.print(usage, .{args[0]}) catch |er| { + return d.fatal("unable to print usage: {s}", .{util.errorDescription(er)}); + }; + return true; + } else if (mem.eql(u8, arg, "-v") or mem.eql(u8, arg, "--version")) { + std_out.writeAll(@import("lib.zig").version_str ++ "\n") catch |er| { + return d.fatal("unable to print version: {s}", .{util.errorDescription(er)}); + }; + return true; + } else if (mem.startsWith(u8, arg, "-D")) { + var macro = arg["-D".len..]; + if (macro.len == 0) { + i += 1; + if (i >= args.len) { + try d.err("expected argument after -I"); + continue; + } + macro = args[i]; + } + var value: []const u8 = "1"; + if (mem.indexOfScalar(u8, macro, '=')) |some| { + value = macro[some + 1 ..]; + macro = macro[0..some]; + } + try macro_buf.print("#define {s} {s}\n", .{ macro, value }); + } else if (mem.startsWith(u8, arg, "-U")) { + var macro = arg["-U".len..]; + if (macro.len == 0) { + i += 1; + if (i >= args.len) { + try d.err("expected argument after -I"); + continue; + } + macro = args[i]; + } + try macro_buf.print("#undef {s}\n", .{macro}); + } else if (mem.eql(u8, arg, "-c") or mem.eql(u8, arg, "--compile")) { + d.only_compile = true; + } else if (mem.eql(u8, arg, "-E")) { + d.only_preprocess = true; + } else if (mem.eql(u8, arg, "-fchar8_t")) { + d.comp.langopts.has_char8_t_override = true; + } else if (mem.eql(u8, arg, "-fno-char8_t")) { + d.comp.langopts.has_char8_t_override = false; + } else if (mem.eql(u8, arg, "-fcolor-diagnostics")) { + color_setting = .on; + } else if (mem.eql(u8, arg, "-fno-color-diagnostics")) { + color_setting = .off; + } else if (mem.eql(u8, arg, "-fdollars-in-identifiers")) { + d.comp.langopts.dollars_in_identifiers = true; + } else if (mem.eql(u8, arg, "-fno-dollars-in-identifiers")) { + d.comp.langopts.dollars_in_identifiers = false; + } else if (mem.eql(u8, arg, "-fdigraphs")) { + d.comp.langopts.digraphs = true; + } else if (mem.eql(u8, arg, "-fgnu-inline-asm")) { + d.comp.langopts.gnu_asm = true; + } else if (mem.eql(u8, arg, "-fno-gnu-inline-asm")) { + d.comp.langopts.gnu_asm = false; + } else if (mem.eql(u8, arg, "-fno-digraphs")) { + d.comp.langopts.digraphs = false; + } else if (option(arg, "-fmacro-backtrace-limit=")) |limit_str| { + var limit = std.fmt.parseInt(u32, limit_str, 10) catch { + try d.err("-fmacro-backtrace-limit takes a number argument"); + continue; + }; + + if (limit == 0) limit = std.math.maxInt(u32); + d.comp.diag.macro_backtrace_limit = limit; + } else if (mem.eql(u8, arg, "-fnative-half-type")) { + d.comp.langopts.use_native_half_type = true; + } else if (mem.eql(u8, arg, "-fnative-half-arguments-and-returns")) { + d.comp.langopts.allow_half_args_and_returns = true; + } else if (mem.eql(u8, arg, "-fshort-enums")) { + d.comp.langopts.short_enums = true; + } else if (mem.eql(u8, arg, "-fno-short-enums")) { + d.comp.langopts.short_enums = false; + } else if (mem.eql(u8, arg, "-fsigned-char")) { + d.comp.langopts.setCharSignedness(.signed); + } else if (mem.eql(u8, arg, "-fno-signed-char")) { + d.comp.langopts.setCharSignedness(.unsigned); + } else if (mem.eql(u8, arg, "-funsigned-char")) { + d.comp.langopts.setCharSignedness(.unsigned); + } else if (mem.eql(u8, arg, "-fno-unsigned-char")) { + d.comp.langopts.setCharSignedness(.signed); + } else if (mem.eql(u8, arg, "-fdeclspec")) { + d.comp.langopts.declspec_attrs = true; + } else if (mem.eql(u8, arg, "-fno-declspec")) { + d.comp.langopts.declspec_attrs = false; + } else if (mem.eql(u8, arg, "-fms-extensions")) { + d.comp.langopts.enableMSExtensions(); + } else if (mem.eql(u8, arg, "-fno-ms-extensions")) { + d.comp.langopts.disableMSExtensions(); + } else if (mem.startsWith(u8, arg, "-I")) { + var path = arg["-I".len..]; + if (path.len == 0) { + i += 1; + if (i >= args.len) { + try d.err("expected argument after -I"); + continue; + } + path = args[i]; + } + try d.comp.include_dirs.append(path); + } else if (mem.startsWith(u8, arg, "-fsyntax-only")) { + d.only_syntax = true; + } else if (mem.startsWith(u8, arg, "-fno-syntax-only")) { + d.only_syntax = false; + } else if (mem.startsWith(u8, arg, "-isystem")) { + var path = arg["-isystem".len..]; + if (path.len == 0) { + i += 1; + if (i >= args.len) { + try d.err("expected argument after -isystem"); + continue; + } + path = args[i]; + } + const duped = try d.comp.gpa.dupe(u8, path); + errdefer d.comp.gpa.free(duped); + try d.comp.system_include_dirs.append(duped); + } else if (option(arg, "--emulate=")) |compiler_str| { + const compiler = std.meta.stringToEnum(LangOpts.Compiler, compiler_str) orelse { + try d.comp.diag.add(.{ .tag = .cli_invalid_emulate, .extra = .{ .str = arg } }, &.{}); + continue; + }; + d.comp.langopts.setEmulatedCompiler(compiler); + } else if (option(arg, "-ffp-eval-method=")) |fp_method_str| { + const fp_eval_method = std.meta.stringToEnum(LangOpts.FPEvalMethod, fp_method_str) orelse .indeterminate; + if (fp_eval_method == .indeterminate) { + try d.comp.diag.add(.{ .tag = .cli_invalid_fp_eval_method, .extra = .{ .str = fp_method_str } }, &.{}); + continue; + } + d.comp.langopts.setFpEvalMethod(fp_eval_method); + } else if (mem.startsWith(u8, arg, "-o")) { + var file = arg["-o".len..]; + if (file.len == 0) { + i += 1; + if (i >= args.len) { + try d.err("expected argument after -o"); + continue; + } + file = args[i]; + } + d.output_name = file; + } else if (option(arg, "--sysroot=")) |sysroot| { + d.sysroot = sysroot; + } else if (mem.eql(u8, arg, "-pedantic")) { + d.comp.diag.options.pedantic = .warning; + } else if (option(arg, "--rtlib=")) |rtlib| { + if (mem.eql(u8, rtlib, "compiler-rt") or mem.eql(u8, rtlib, "libgcc") or mem.eql(u8, rtlib, "platform")) { + d.rtlib = rtlib; + } else { + try d.comp.diag.add(.{ .tag = .invalid_rtlib, .extra = .{ .str = rtlib } }, &.{}); + } + } else if (option(arg, "-Werror=")) |err_name| { + try d.comp.diag.set(err_name, .@"error"); + } else if (mem.eql(u8, arg, "-Wno-fatal-errors")) { + d.comp.diag.fatal_errors = false; + } else if (option(arg, "-Wno-")) |err_name| { + try d.comp.diag.set(err_name, .off); + } else if (mem.eql(u8, arg, "-Wfatal-errors")) { + d.comp.diag.fatal_errors = true; + } else if (option(arg, "-W")) |err_name| { + try d.comp.diag.set(err_name, .warning); + } else if (option(arg, "-std=")) |standard| { + d.comp.langopts.setStandard(standard) catch + try d.comp.diag.add(.{ .tag = .cli_invalid_standard, .extra = .{ .str = arg } }, &.{}); + } else if (mem.eql(u8, arg, "-S") or mem.eql(u8, arg, "--assemble")) { + d.only_preprocess_and_compile = true; + } else if (option(arg, "--target=")) |triple| { + const cross = std.zig.CrossTarget.parse(.{ .arch_os_abi = triple }) catch { + try d.comp.diag.add(.{ .tag = .cli_invalid_target, .extra = .{ .str = arg } }, &.{}); + continue; + }; + d.comp.target = cross.toTarget(); // TODO deprecated + d.comp.langopts.setEmulatedCompiler(target_util.systemCompiler(d.comp.target)); + d.raw_target_triple = triple; + } else if (mem.eql(u8, arg, "--verbose-ast")) { + d.verbose_ast = true; + } else if (mem.eql(u8, arg, "--verbose-pp")) { + d.verbose_pp = true; + } else if (mem.eql(u8, arg, "--verbose-ir")) { + d.verbose_ir = true; + } else if (mem.eql(u8, arg, "--verbose-linker-args")) { + d.verbose_linker_args = true; + } else if (option(arg, "-fuse-ld=")) |linker_name| { + d.use_linker = linker_name; + } else if (mem.eql(u8, arg, "-fuse-ld=")) { + d.use_linker = null; + } else if (option(arg, "--ld-path=")) |linker_path| { + d.linker_path = linker_path; + } else if (mem.eql(u8, arg, "-r")) { + d.relocatable = true; + } else if (mem.eql(u8, arg, "-shared")) { + d.shared = true; + } else if (mem.eql(u8, arg, "-shared-libgcc")) { + d.shared_libgcc = true; + } else if (mem.eql(u8, arg, "-static")) { + d.static = true; + } else if (mem.eql(u8, arg, "-static-libgcc")) { + d.static_libgcc = true; + } else if (mem.eql(u8, arg, "-static-pie")) { + d.static_pie = true; + } else if (mem.eql(u8, arg, "-pie")) { + d.pie = true; + } else if (mem.eql(u8, arg, "-no-pie") or mem.eql(u8, arg, "-nopie")) { + d.pie = false; + } else if (mem.eql(u8, arg, "-rdynamic")) { + d.rdynamic = true; + } else if (mem.eql(u8, arg, "-s")) { + d.strip = true; + } else if (mem.eql(u8, arg, "-nodefaultlibs")) { + d.nodefaultlibs = true; + } else if (mem.eql(u8, arg, "-nolibc")) { + d.nolibc = true; + } else if (mem.eql(u8, arg, "-nostdlib")) { + d.nostdlib = true; + } else if (mem.eql(u8, arg, "-nostartfiles")) { + d.nostartfiles = true; + } else if (option(arg, "--unwindlib=")) |unwindlib| { + const valid_unwindlibs: [5][]const u8 = .{ "", "none", "platform", "libunwind", "libgcc" }; + for (valid_unwindlibs) |name| { + if (mem.eql(u8, name, unwindlib)) { + d.unwindlib = unwindlib; + break; + } + } else { + try d.comp.diag.add(.{ .tag = .invalid_unwindlib, .extra = .{ .str = unwindlib } }, &.{}); + } + } else { + try d.comp.diag.add(.{ .tag = .cli_unknown_arg, .extra = .{ .str = arg } }, &.{}); + } + } else if (std.mem.endsWith(u8, arg, ".o") or std.mem.endsWith(u8, arg, ".obj")) { + try d.link_objects.append(d.comp.gpa, arg); + } else { + const source = d.addSource(arg) catch |er| { + return d.fatal("unable to add source file '{s}': {s}", .{ arg, util.errorDescription(er) }); + }; + try d.inputs.append(d.comp.gpa, source); + } + } + d.comp.diag.color = switch (color_setting) { + .on => true, + .off => false, + .unset => util.fileSupportsColor(std.io.getStdErr()) and !std.process.hasEnvVarConstant("NO_COLOR"), + }; + return false; +} + +fn option(arg: []const u8, name: []const u8) ?[]const u8 { + if (std.mem.startsWith(u8, arg, name) and arg.len > name.len) { + return arg[name.len..]; + } + return null; +} + +fn addSource(d: *Driver, path: []const u8) !Source { + if (mem.eql(u8, "-", path)) { + const stdin = std.io.getStdIn().reader(); + const input = try stdin.readAllAlloc(d.comp.gpa, std.math.maxInt(u32)); + defer d.comp.gpa.free(input); + return d.comp.addSourceFromBuffer("", input); + } + return d.comp.addSourceFromPath(path); +} + +pub fn err(d: *Driver, msg: []const u8) !void { + try d.comp.diag.add(.{ .tag = .cli_error, .extra = .{ .str = msg } }, &.{}); +} + +pub fn fatal(d: *Driver, comptime fmt: []const u8, args: anytype) error{FatalError} { + d.comp.renderErrors(); + return d.comp.diag.fatalNoSrc(fmt, args); +} + +pub fn main(d: *Driver, tc: *Toolchain, args: []const []const u8) !void { + var macro_buf = std.ArrayList(u8).init(d.comp.gpa); + defer macro_buf.deinit(); + + const std_out = std.io.getStdOut().writer(); + if (try parseArgs(d, std_out, macro_buf.writer(), args)) return; + + const linking = !(d.only_preprocess or d.only_syntax or d.only_compile or d.only_preprocess_and_compile); + + if (d.inputs.items.len == 0) { + return d.fatal("no input files", .{}); + } else if (d.inputs.items.len != 1 and d.output_name != null and !linking) { + return d.fatal("cannot specify -o when generating multiple output files", .{}); + } + + if (!linking) for (d.link_objects.items) |obj| { + try d.comp.diag.add(.{ .tag = .cli_unused_link_object, .extra = .{ .str = obj } }, &.{}); + }; + + d.comp.defineSystemIncludes(d.aro_name) catch |er| switch (er) { + error.OutOfMemory => return error.OutOfMemory, + error.AroIncludeNotFound => return d.fatal("unable to find Aro builtin headers", .{}), + }; + + const builtin = try d.comp.generateBuiltinMacros(); + const user_macros = try d.comp.addSourceFromBuffer("", macro_buf.items); + + const fast_exit = @import("builtin").mode != .Debug; + + if (fast_exit and d.inputs.items.len == 1) { + d.processSource(tc, d.inputs.items[0], builtin, user_macros, fast_exit) catch |e| switch (e) { + error.FatalError => { + d.comp.renderErrors(); + d.exitWithCleanup(1); + }, + else => |er| return er, + }; + unreachable; + } + + for (d.inputs.items) |source| { + d.processSource(tc, source, builtin, user_macros, fast_exit) catch |e| switch (e) { + error.FatalError => { + d.comp.renderErrors(); + }, + else => |er| return er, + }; + } + if (d.comp.diag.errors != 0) { + if (fast_exit) d.exitWithCleanup(1); + return; + } + if (linking) { + try d.invokeLinker(tc, fast_exit); + } + if (fast_exit) std.process.exit(0); +} + +fn processSource( + d: *Driver, + tc: *Toolchain, + source: Source, + builtin: Source, + user_macros: Source, + comptime fast_exit: bool, +) !void { + d.comp.generated_buf.items.len = 0; + var pp = Preprocessor.init(d.comp); + defer pp.deinit(); + + if (d.verbose_pp) pp.verbose = true; + if (d.only_preprocess) pp.preserve_whitespace = true; + try pp.addBuiltinMacros(); + + _ = try pp.preprocess(builtin); + _ = try pp.preprocess(user_macros); + const eof = try pp.preprocess(source); + try pp.tokens.append(pp.comp.gpa, eof); + + if (d.only_preprocess) { + d.comp.renderErrors(); + + const file = if (d.output_name) |some| + std.fs.cwd().createFile(some, .{}) catch |er| + return d.fatal("unable to create output file '{s}': {s}", .{ some, util.errorDescription(er) }) + else + std.io.getStdOut(); + defer if (d.output_name != null) file.close(); + + var buf_w = std.io.bufferedWriter(file.writer()); + pp.prettyPrintTokens(buf_w.writer()) catch |er| + return d.fatal("unable to write result: {s}", .{util.errorDescription(er)}); + + buf_w.flush() catch |er| + return d.fatal("unable to write result: {s}", .{util.errorDescription(er)}); + if (fast_exit) std.process.exit(0); // Not linking, no need for cleanup. + return; + } + + var tree = try Parser.parse(&pp); + defer tree.deinit(); + + if (d.verbose_ast) { + const stdout = std.io.getStdOut(); + var buf_writer = std.io.bufferedWriter(stdout.writer()); + const color = d.comp.diag.color and util.fileSupportsColor(stdout); + tree.dump(color, buf_writer.writer()) catch {}; + buf_writer.flush() catch {}; + } + + const prev_errors = d.comp.diag.errors; + d.comp.renderErrors(); + + if (d.comp.diag.errors != prev_errors) { + if (fast_exit) d.exitWithCleanup(1); + return; // do not compile if there were errors + } + + if (d.only_syntax) { + if (fast_exit) std.process.exit(0); // Not linking, no need for cleanup. + return; + } + + if (d.comp.target.ofmt != .elf or d.comp.target.cpu.arch != .x86_64) { + return d.fatal( + "unsupported target {s}-{s}-{s}, currently only x86-64 elf is supported", + .{ @tagName(d.comp.target.cpu.arch), @tagName(d.comp.target.os.tag), @tagName(d.comp.target.abi) }, + ); + } + + if (d.verbose_ir) { + try @import("CodeGen.zig").generateTree(d.comp, tree); + } + + const obj = try Codegen.generateTree(d.comp, tree); + defer obj.deinit(); + + // If it's used, name_buf will either hold a filename or `/tmp/<12 random bytes with base-64 encoding>.` + // both of which should fit into MAX_NAME_BYTES for all systems + var name_buf: [std.fs.MAX_NAME_BYTES]u8 = undefined; + + const out_file_name = if (d.only_compile) blk: { + const fmt_template = "{s}{s}"; + const fmt_args = .{ + std.fs.path.stem(source.path), + d.comp.target.ofmt.fileExt(d.comp.target.cpu.arch), + }; + break :blk d.output_name orelse + std.fmt.bufPrint(&name_buf, fmt_template, fmt_args) catch return d.fatal("Filename too long for filesystem: " ++ fmt_template, fmt_args); + } else blk: { + const random_bytes_count = 12; + const sub_path_len = comptime std.fs.base64_encoder.calcSize(random_bytes_count); + + var random_bytes: [random_bytes_count]u8 = undefined; + std.crypto.random.bytes(&random_bytes); + var random_name: [sub_path_len]u8 = undefined; + _ = std.fs.base64_encoder.encode(&random_name, &random_bytes); + + const fmt_template = "/tmp/{s}{s}"; + const fmt_args = .{ + random_name, + d.comp.target.ofmt.fileExt(d.comp.target.cpu.arch), + }; + break :blk std.fmt.bufPrint(&name_buf, fmt_template, fmt_args) catch return d.fatal("Filename too long for filesystem: " ++ fmt_template, fmt_args); + }; + + const out_file = std.fs.cwd().createFile(out_file_name, .{}) catch |er| + return d.fatal("unable to create output file '{s}': {s}", .{ out_file_name, util.errorDescription(er) }); + defer out_file.close(); + + obj.finish(out_file) catch |er| + return d.fatal("could not output to object file '{s}': {s}", .{ out_file_name, util.errorDescription(er) }); + + if (d.only_compile) { + if (fast_exit) std.process.exit(0); // Not linking, no need for cleanup. + return; + } + try d.link_objects.ensureUnusedCapacity(d.comp.gpa, 1); + d.link_objects.appendAssumeCapacity(try d.comp.gpa.dupe(u8, out_file_name)); + d.temp_file_count += 1; + if (fast_exit) { + try d.invokeLinker(tc, fast_exit); + } +} + +fn dumpLinkerArgs(items: []const []const u8) !void { + const stdout = std.io.getStdOut().writer(); + for (items, 0..) |item, i| { + if (i > 0) try stdout.writeByte(' '); + try stdout.print("\"{}\"", .{std.zig.fmtEscapes(item)}); + } + try stdout.writeByte('\n'); +} + +pub fn invokeLinker(d: *Driver, tc: *Toolchain, comptime fast_exit: bool) !void { + try tc.discover(); + + var argv = std.ArrayList([]const u8).init(d.comp.gpa); + defer argv.deinit(); + + var linker_path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + const linker_path = try tc.getLinkerPath(&linker_path_buf); + try argv.append(linker_path); + + try tc.buildLinkerArgs(&argv); + + if (d.verbose_linker_args) { + dumpLinkerArgs(argv.items) catch |er| { + return d.fatal("unable to dump linker args: {s}", .{util.errorDescription(er)}); + }; + } + var child = std.ChildProcess.init(argv.items, d.comp.gpa); + // TODO handle better + child.stdin_behavior = .Inherit; + child.stdout_behavior = .Inherit; + child.stderr_behavior = .Inherit; + + const term = child.spawnAndWait() catch |er| { + return d.fatal("unable to spawn linker: {s}", .{util.errorDescription(er)}); + }; + switch (term) { + .Exited => |code| if (code != 0) d.exitWithCleanup(code), + else => std.process.abort(), + } + if (fast_exit) d.exitWithCleanup(0); +} + +fn exitWithCleanup(d: *Driver, code: u8) noreturn { + for (d.link_objects.items[d.link_objects.items.len - d.temp_file_count ..]) |obj| { + std.fs.deleteFileAbsolute(obj) catch {}; + } + std.process.exit(code); +} diff --git a/deps/aro/Driver/Distro.zig b/deps/aro/Driver/Distro.zig new file mode 100644 index 000000000000..749bbf09f6a9 --- /dev/null +++ b/deps/aro/Driver/Distro.zig @@ -0,0 +1,329 @@ +//! Tools for figuring out what Linux distro we're running on + +const std = @import("std"); +const mem = std.mem; +const util = @import("../util.zig"); +const Filesystem = @import("Filesystem.zig").Filesystem; + +const MAX_BYTES = 1024; // TODO: Can we assume 1024 bytes enough for the info we need? + +/// Value for linker `--hash-style=` argument +pub const HashStyle = enum { + both, + gnu, +}; + +pub const Tag = enum { + alpine, + arch, + debian_lenny, + debian_squeeze, + debian_wheezy, + debian_jessie, + debian_stretch, + debian_buster, + debian_bullseye, + debian_bookworm, + debian_trixie, + exherbo, + rhel5, + rhel6, + rhel7, + fedora, + gentoo, + open_suse, + ubuntu_hardy, + ubuntu_intrepid, + ubuntu_jaunty, + ubuntu_karmic, + ubuntu_lucid, + ubuntu_maverick, + ubuntu_natty, + ubuntu_oneiric, + ubuntu_precise, + ubuntu_quantal, + ubuntu_raring, + ubuntu_saucy, + ubuntu_trusty, + ubuntu_utopic, + ubuntu_vivid, + ubuntu_wily, + ubuntu_xenial, + ubuntu_yakkety, + ubuntu_zesty, + ubuntu_artful, + ubuntu_bionic, + ubuntu_cosmic, + ubuntu_disco, + ubuntu_eoan, + ubuntu_focal, + ubuntu_groovy, + ubuntu_hirsute, + ubuntu_impish, + ubuntu_jammy, + ubuntu_kinetic, + ubuntu_lunar, + unknown, + + pub fn getHashStyle(self: Tag) HashStyle { + if (self.isOpenSUSE()) return .both; + return switch (self) { + .ubuntu_lucid, + .ubuntu_jaunty, + .ubuntu_karmic, + => .both, + else => .gnu, + }; + } + + pub fn isRedhat(self: Tag) bool { + return switch (self) { + .fedora, + .rhel5, + .rhel6, + .rhel7, + => true, + else => false, + }; + } + + pub fn isOpenSUSE(self: Tag) bool { + return self == .open_suse; + } + + pub fn isDebian(self: Tag) bool { + return switch (self) { + .debian_lenny, + .debian_squeeze, + .debian_wheezy, + .debian_jessie, + .debian_stretch, + .debian_buster, + .debian_bullseye, + .debian_bookworm, + .debian_trixie, + => true, + else => false, + }; + } + pub fn isUbuntu(self: Tag) bool { + return switch (self) { + .ubuntu_hardy, + .ubuntu_intrepid, + .ubuntu_jaunty, + .ubuntu_karmic, + .ubuntu_lucid, + .ubuntu_maverick, + .ubuntu_natty, + .ubuntu_oneiric, + .ubuntu_precise, + .ubuntu_quantal, + .ubuntu_raring, + .ubuntu_saucy, + .ubuntu_trusty, + .ubuntu_utopic, + .ubuntu_vivid, + .ubuntu_wily, + .ubuntu_xenial, + .ubuntu_yakkety, + .ubuntu_zesty, + .ubuntu_artful, + .ubuntu_bionic, + .ubuntu_cosmic, + .ubuntu_disco, + .ubuntu_eoan, + .ubuntu_focal, + .ubuntu_groovy, + .ubuntu_hirsute, + .ubuntu_impish, + .ubuntu_jammy, + .ubuntu_kinetic, + .ubuntu_lunar, + => true, + + else => false, + }; + } + pub fn isAlpine(self: Tag) bool { + return self == .alpine; + } + pub fn isGentoo(self: Tag) bool { + return self == .gentoo; + } +}; + +fn scanForOsRelease(buf: []const u8) ?Tag { + var it = mem.splitScalar(u8, buf, '\n'); + while (it.next()) |line| { + if (mem.startsWith(u8, line, "ID=")) { + const rest = line["ID=".len..]; + if (mem.eql(u8, rest, "alpine")) return .alpine; + if (mem.eql(u8, rest, "fedora")) return .fedora; + if (mem.eql(u8, rest, "gentoo")) return .gentoo; + if (mem.eql(u8, rest, "arch")) return .arch; + if (mem.eql(u8, rest, "sles")) return .open_suse; + if (mem.eql(u8, rest, "opensuse")) return .open_suse; + if (mem.eql(u8, rest, "exherbo")) return .exherbo; + } + } + return null; +} + +fn detectOsRelease(fs: Filesystem) ?Tag { + var buf: [MAX_BYTES]u8 = undefined; + const data = fs.readFile("/etc/os-release", &buf) orelse fs.readFile("/usr/lib/os-release", &buf) orelse return null; + return scanForOsRelease(data); +} + +fn scanForLSBRelease(buf: []const u8) ?Tag { + var it = mem.splitScalar(u8, buf, '\n'); + while (it.next()) |line| { + if (mem.startsWith(u8, line, "DISTRIB_CODENAME=")) { + const rest = line["DISTRIB_CODENAME=".len..]; + if (mem.eql(u8, rest, "hardy")) return .ubuntu_hardy; + if (mem.eql(u8, rest, "intrepid")) return .ubuntu_intrepid; + if (mem.eql(u8, rest, "jaunty")) return .ubuntu_jaunty; + if (mem.eql(u8, rest, "karmic")) return .ubuntu_karmic; + if (mem.eql(u8, rest, "lucid")) return .ubuntu_lucid; + if (mem.eql(u8, rest, "maverick")) return .ubuntu_maverick; + if (mem.eql(u8, rest, "natty")) return .ubuntu_natty; + if (mem.eql(u8, rest, "oneiric")) return .ubuntu_oneiric; + if (mem.eql(u8, rest, "precise")) return .ubuntu_precise; + if (mem.eql(u8, rest, "quantal")) return .ubuntu_quantal; + if (mem.eql(u8, rest, "raring")) return .ubuntu_raring; + if (mem.eql(u8, rest, "saucy")) return .ubuntu_saucy; + if (mem.eql(u8, rest, "trusty")) return .ubuntu_trusty; + if (mem.eql(u8, rest, "utopic")) return .ubuntu_utopic; + if (mem.eql(u8, rest, "vivid")) return .ubuntu_vivid; + if (mem.eql(u8, rest, "wily")) return .ubuntu_wily; + if (mem.eql(u8, rest, "xenial")) return .ubuntu_xenial; + if (mem.eql(u8, rest, "yakkety")) return .ubuntu_yakkety; + if (mem.eql(u8, rest, "zesty")) return .ubuntu_zesty; + if (mem.eql(u8, rest, "artful")) return .ubuntu_artful; + if (mem.eql(u8, rest, "bionic")) return .ubuntu_bionic; + if (mem.eql(u8, rest, "cosmic")) return .ubuntu_cosmic; + if (mem.eql(u8, rest, "disco")) return .ubuntu_disco; + if (mem.eql(u8, rest, "eoan")) return .ubuntu_eoan; + if (mem.eql(u8, rest, "focal")) return .ubuntu_focal; + if (mem.eql(u8, rest, "groovy")) return .ubuntu_groovy; + if (mem.eql(u8, rest, "hirsute")) return .ubuntu_hirsute; + if (mem.eql(u8, rest, "impish")) return .ubuntu_impish; + if (mem.eql(u8, rest, "jammy")) return .ubuntu_jammy; + if (mem.eql(u8, rest, "kinetic")) return .ubuntu_kinetic; + if (mem.eql(u8, rest, "lunar")) return .ubuntu_lunar; + } + } + return null; +} + +fn detectLSBRelease(fs: Filesystem) ?Tag { + var buf: [MAX_BYTES]u8 = undefined; + const data = fs.readFile("/etc/lsb-release", &buf) orelse return null; + + return scanForLSBRelease(data); +} + +fn scanForRedHat(buf: []const u8) Tag { + if (mem.startsWith(u8, buf, "Fedora release")) return .fedora; + if (mem.startsWith(u8, buf, "Red Hat Enterprise Linux") or mem.startsWith(u8, buf, "CentOS") or mem.startsWith(u8, buf, "Scientific Linux")) { + if (mem.indexOfPos(u8, buf, 0, "release 7") != null) return .rhel7; + if (mem.indexOfPos(u8, buf, 0, "release 6") != null) return .rhel6; + if (mem.indexOfPos(u8, buf, 0, "release 5") != null) return .rhel5; + } + + return .unknown; +} + +fn detectRedhat(fs: Filesystem) ?Tag { + var buf: [MAX_BYTES]u8 = undefined; + const data = fs.readFile("/etc/redhat-release", &buf) orelse return null; + return scanForRedHat(data); +} + +fn scanForDebian(buf: []const u8) Tag { + var it = mem.splitScalar(u8, buf, '.'); + if (std.fmt.parseInt(u8, it.next().?, 10)) |major| { + return switch (major) { + 5 => .debian_lenny, + 6 => .debian_squeeze, + 7 => .debian_wheezy, + 8 => .debian_jessie, + 9 => .debian_stretch, + 10 => .debian_buster, + 11 => .debian_bullseye, + 12 => .debian_bookworm, + 13 => .debian_trixie, + else => .unknown, + }; + } else |_| {} + + it = mem.splitScalar(u8, buf, '\n'); + const name = it.next().?; + if (mem.eql(u8, name, "squeeze/sid")) return .debian_squeeze; + if (mem.eql(u8, name, "wheezy/sid")) return .debian_wheezy; + if (mem.eql(u8, name, "jessie/sid")) return .debian_jessie; + if (mem.eql(u8, name, "stretch/sid")) return .debian_stretch; + if (mem.eql(u8, name, "buster/sid")) return .debian_buster; + if (mem.eql(u8, name, "bullseye/sid")) return .debian_bullseye; + if (mem.eql(u8, name, "bookworm/sid")) return .debian_bookworm; + + return .unknown; +} + +fn detectDebian(fs: Filesystem) ?Tag { + var buf: [MAX_BYTES]u8 = undefined; + const data = fs.readFile("/etc/debian_version", &buf) orelse return null; + return scanForDebian(data); +} + +pub fn detect(target: std.Target, fs: Filesystem) Tag { + if (target.os.tag != .linux) return .unknown; + + if (detectOsRelease(fs)) |tag| return tag; + if (detectLSBRelease(fs)) |tag| return tag; + if (detectRedhat(fs)) |tag| return tag; + if (detectDebian(fs)) |tag| return tag; + + if (fs.exists("/etc/gentoo-release")) return .gentoo; + + return .unknown; +} + +test scanForDebian { + try std.testing.expectEqual(Tag.debian_squeeze, scanForDebian("squeeze/sid")); + try std.testing.expectEqual(Tag.debian_bullseye, scanForDebian("11.1.2")); + try std.testing.expectEqual(Tag.unknown, scanForDebian("None")); + try std.testing.expectEqual(Tag.unknown, scanForDebian("")); +} + +test scanForRedHat { + try std.testing.expectEqual(Tag.fedora, scanForRedHat("Fedora release 7")); + try std.testing.expectEqual(Tag.rhel7, scanForRedHat("Red Hat Enterprise Linux release 7")); + try std.testing.expectEqual(Tag.rhel5, scanForRedHat("CentOS release 5")); + try std.testing.expectEqual(Tag.unknown, scanForRedHat("CentOS release 4")); + try std.testing.expectEqual(Tag.unknown, scanForRedHat("")); +} + +test scanForLSBRelease { + const text = + \\DISTRIB_ID=Ubuntu + \\DISTRIB_RELEASE=20.04 + \\DISTRIB_CODENAME=focal + \\DISTRIB_DESCRIPTION="Ubuntu 20.04.6 LTS" + \\ + ; + try std.testing.expectEqual(Tag.ubuntu_focal, scanForLSBRelease(text).?); +} + +test scanForOsRelease { + const text = + \\NAME="Alpine Linux" + \\ID=alpine + \\VERSION_ID=3.18.2 + \\PRETTY_NAME="Alpine Linux v3.18" + \\HOME_URL="https://alpinelinux.org/" + \\BUG_REPORT_URL="https://gitlab.alpinelinux.org/alpine/aports/-/issues" + \\ + ; + try std.testing.expectEqual(Tag.alpine, scanForOsRelease(text).?); +} diff --git a/deps/aro/Driver/Filesystem.zig b/deps/aro/Driver/Filesystem.zig new file mode 100644 index 000000000000..7ffab2b15244 --- /dev/null +++ b/deps/aro/Driver/Filesystem.zig @@ -0,0 +1,242 @@ +const std = @import("std"); +const mem = std.mem; +const builtin = @import("builtin"); +const system_defaults = @import("system_defaults"); +const is_windows = builtin.os.tag == .windows; + +fn readFileFake(entries: []const Filesystem.Entry, path: []const u8, buf: []u8) ?[]const u8 { + @setCold(true); + for (entries) |entry| { + if (mem.eql(u8, entry.path, path)) { + const len = @min(entry.contents.len, buf.len); + @memcpy(buf[0..len], entry.contents[0..len]); + return buf[0..len]; + } + } + return null; +} + +fn findProgramByNameFake(entries: []const Filesystem.Entry, name: []const u8, path: ?[]const u8, buf: []u8) ?[]const u8 { + @setCold(true); + if (mem.indexOfScalar(u8, name, '/') != null) { + @memcpy(buf[0..name.len], name); + return buf[0..name.len]; + } + const path_env = path orelse return null; + var fib = std.heap.FixedBufferAllocator.init(buf); + + var it = mem.tokenizeScalar(u8, path_env, system_defaults.path_sep); + while (it.next()) |path_dir| { + defer fib.reset(); + const full_path = std.fs.path.join(fib.allocator(), &.{ path_dir, name }) catch continue; + if (canExecuteFake(entries, full_path)) return full_path; + } + + return null; +} + +fn canExecuteFake(entries: []const Filesystem.Entry, path: []const u8) bool { + @setCold(true); + for (entries) |entry| { + if (mem.eql(u8, entry.path, path)) { + return entry.executable; + } + } + return false; +} + +fn existsFake(entries: []const Filesystem.Entry, path: []const u8) bool { + @setCold(true); + var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + var fib = std.heap.FixedBufferAllocator.init(&buf); + const resolved = std.fs.path.resolvePosix(fib.allocator(), &.{path}) catch return false; + for (entries) |entry| { + if (mem.eql(u8, entry.path, resolved)) return true; + } + return false; +} + +fn canExecutePosix(path: []const u8) bool { + std.os.access(path, std.os.X_OK) catch return false; + // Todo: ensure path is not a directory + return true; +} + +/// TODO +fn canExecuteWindows(path: []const u8) bool { + _ = path; + return true; +} + +/// TODO +fn findProgramByNameWindows(allocator: std.mem.Allocator, name: []const u8, path: ?[]const u8, buf: []u8) ?[]const u8 { + _ = path; + _ = buf; + _ = name; + _ = allocator; + return null; +} + +/// TODO: does WASI need special handling? +fn findProgramByNamePosix(name: []const u8, path: ?[]const u8, buf: []u8) ?[]const u8 { + if (mem.indexOfScalar(u8, name, '/') != null) { + @memcpy(buf[0..name.len], name); + return buf[0..name.len]; + } + const path_env = path orelse return null; + var fib = std.heap.FixedBufferAllocator.init(buf); + + var it = mem.tokenizeScalar(u8, path_env, system_defaults.path_sep); + while (it.next()) |path_dir| { + defer fib.reset(); + const full_path = std.fs.path.join(fib.allocator(), &.{ path_dir, name }) catch continue; + if (canExecutePosix(full_path)) return full_path; + } + + return null; +} + +pub const Filesystem = union(enum) { + real: void, + fake: []const Entry, + + const Entry = struct { + path: []const u8, + contents: []const u8 = "", + executable: bool = false, + }; + + const FakeDir = struct { + entries: []const Entry, + path: []const u8, + + fn iterate(self: FakeDir) FakeDir.Iterator { + return .{ + .entries = self.entries, + .base = self.path, + }; + } + + const Iterator = struct { + entries: []const Entry, + base: []const u8, + i: usize = 0, + + const Self = @This(); + + fn next(self: *@This()) !?std.fs.IterableDir.Entry { + while (self.i < self.entries.len) { + const entry = self.entries[self.i]; + self.i += 1; + if (entry.path.len == self.base.len) continue; + if (std.mem.startsWith(u8, entry.path, self.base)) { + const remaining = entry.path[self.base.len + 1 ..]; + if (std.mem.indexOfScalar(u8, remaining, std.fs.path.sep) != null) continue; + const extension = std.fs.path.extension(remaining); + const kind: std.fs.IterableDir.Entry.Kind = if (extension.len == 0) .directory else .file; + return .{ .name = remaining, .kind = kind }; + } + } + return null; + } + }; + }; + + const IterableDir = union(enum) { + dir: std.fs.IterableDir, + fake: FakeDir, + + pub fn iterate(self: IterableDir) Iterator { + return switch (self) { + .dir => |dir| .{ .iterator = dir.iterate() }, + .fake => |fake| .{ .fake = fake.iterate() }, + }; + } + + pub fn close(self: *IterableDir) void { + switch (self.*) { + .dir => |*d| d.close(), + .fake => {}, + } + } + }; + + const Iterator = union(enum) { + iterator: std.fs.IterableDir.Iterator, + fake: FakeDir.Iterator, + + pub fn next(self: *Iterator) std.fs.IterableDir.Iterator.Error!?std.fs.IterableDir.Entry { + return switch (self.*) { + .iterator => |*it| it.next(), + .fake => |*it| it.next(), + }; + } + }; + + pub fn exists(fs: Filesystem, path: []const u8) bool { + switch (fs) { + .real => { + std.os.access(path, std.os.F_OK) catch return false; + return true; + }, + .fake => |paths| return existsFake(paths, path), + } + } + + pub fn joinedExists(fs: Filesystem, parts: []const []const u8) bool { + var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + var fib = std.heap.FixedBufferAllocator.init(&buf); + const joined = std.fs.path.join(fib.allocator(), parts) catch return false; + return fs.exists(joined); + } + + pub fn canExecute(fs: Filesystem, path: []const u8) bool { + return switch (fs) { + .real => if (is_windows) canExecuteWindows(path) else canExecutePosix(path), + .fake => |entries| canExecuteFake(entries, path), + }; + } + + /// Search for an executable named `name` using platform-specific logic + /// If it's found, write the full path to `buf` and return a slice of it + /// Otherwise retun null + pub fn findProgramByName(fs: Filesystem, allocator: std.mem.Allocator, name: []const u8, path: ?[]const u8, buf: []u8) ?[]const u8 { + std.debug.assert(name.len > 0); + return switch (fs) { + .real => if (is_windows) findProgramByNameWindows(allocator, name, path, buf) else findProgramByNamePosix(name, path, buf), + .fake => |entries| findProgramByNameFake(entries, name, path, buf), + }; + } + + /// Read the file at `path` into `buf`. + /// Returns null if any errors are encountered + /// Otherwise returns a slice of `buf`. If the file is larger than `buf` partial contents are returned + pub fn readFile(fs: Filesystem, path: []const u8, buf: []u8) ?[]const u8 { + return switch (fs) { + .real => { + const file = std.fs.cwd().openFile(path, .{}) catch return null; + defer file.close(); + + const bytes_read = file.readAll(buf) catch return null; + return buf[0..bytes_read]; + }, + .fake => |entries| readFileFake(entries, path, buf), + }; + } + + pub fn openIterableDir(fs: Filesystem, dir_name: []const u8) std.fs.Dir.OpenError!IterableDir { + return switch (fs) { + .real => .{ .dir = try std.fs.cwd().openIterableDir(dir_name, .{ .access_sub_paths = false }) }, + .fake => |entries| .{ .fake = .{ .entries = entries, .path = dir_name } }, + }; + } +}; + +test "Fake filesystem" { + const fs: Filesystem = .{ .fake = &.{ + .{ .path = "/usr/bin" }, + } }; + try std.testing.expect(fs.exists("/usr/bin")); + try std.testing.expect(fs.exists("/usr/bin/foo/..")); + try std.testing.expect(!fs.exists("/usr/bin/bar")); +} diff --git a/deps/aro/Driver/GCCDetector.zig b/deps/aro/Driver/GCCDetector.zig new file mode 100644 index 000000000000..21c115503808 --- /dev/null +++ b/deps/aro/Driver/GCCDetector.zig @@ -0,0 +1,610 @@ +const std = @import("std"); +const Toolchain = @import("../Toolchain.zig"); +const target_util = @import("../target.zig"); +const system_defaults = @import("system_defaults"); +const util = @import("../util.zig"); +const GCCVersion = @import("GCCVersion.zig"); +const Multilib = @import("Multilib.zig"); +const GCCDetector = @This(); + +is_valid: bool = false, +install_path: []const u8 = "", +parent_lib_path: []const u8 = "", +version: GCCVersion = .{}, +gcc_triple: []const u8 = "", +selected: Multilib = .{}, +biarch_sibling: ?Multilib = null, + +pub fn deinit(self: *GCCDetector) void { + if (!self.is_valid) return; +} + +pub fn appendToolPath(self: *const GCCDetector, tc: *Toolchain) !void { + if (!self.is_valid) return; + return tc.addPathFromComponents(&.{ + self.parent_lib_path, + "..", + self.gcc_triple, + "bin", + }, .program); +} + +fn addDefaultGCCPrefixes(prefixes: *PathPrefixes, tc: *const Toolchain) !void { + const sysroot = tc.getSysroot(); + const target = tc.getTarget(); + if (sysroot.len == 0 and target.os.tag == .linux and tc.filesystem.exists("/opt/rh")) { + prefixes.appendAssumeCapacity("/opt/rh/gcc-toolset-12/root/usr"); + prefixes.appendAssumeCapacity("/opt/rh/gcc-toolset-11/root/usr"); + prefixes.appendAssumeCapacity("/opt/rh/gcc-toolset-10/root/usr"); + prefixes.appendAssumeCapacity("/opt/rh/devtoolset-12/root/usr"); + prefixes.appendAssumeCapacity("/opt/rh/devtoolset-11/root/usr"); + prefixes.appendAssumeCapacity("/opt/rh/devtoolset-10/root/usr"); + prefixes.appendAssumeCapacity("/opt/rh/devtoolset-9/root/usr"); + prefixes.appendAssumeCapacity("/opt/rh/devtoolset-8/root/usr"); + prefixes.appendAssumeCapacity("/opt/rh/devtoolset-7/root/usr"); + prefixes.appendAssumeCapacity("/opt/rh/devtoolset-6/root/usr"); + prefixes.appendAssumeCapacity("/opt/rh/devtoolset-4/root/usr"); + prefixes.appendAssumeCapacity("/opt/rh/devtoolset-3/root/usr"); + prefixes.appendAssumeCapacity("/opt/rh/devtoolset-2/root/usr"); + } + if (sysroot.len == 0) { + prefixes.appendAssumeCapacity("/usr"); + } else { + var usr_path = try tc.arena.alloc(u8, 4 + sysroot.len); + @memcpy(usr_path[0..4], "/usr"); + @memcpy(usr_path[4..], sysroot); + prefixes.appendAssumeCapacity(usr_path); + } +} + +const PathPrefixes = std.BoundedArray([]const u8, 16); + +fn collectLibDirsAndTriples( + tc: *Toolchain, + lib_dirs: *PathPrefixes, + triple_aliases: *PathPrefixes, + biarch_libdirs: *PathPrefixes, + biarch_triple_aliases: *PathPrefixes, +) !void { + const AArch64LibDirs: [2][]const u8 = .{ "/lib64", "/lib" }; + const AArch64Triples: [4][]const u8 = .{ "aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-redhat-linux", "aarch64-suse-linux" }; + const AArch64beLibDirs: [1][]const u8 = .{"/lib"}; + const AArch64beTriples: [2][]const u8 = .{ "aarch64_be-none-linux-gnu", "aarch64_be-linux-gnu" }; + + const ARMLibDirs: [1][]const u8 = .{"/lib"}; + const ARMTriples: [1][]const u8 = .{"arm-linux-gnueabi"}; + const ARMHFTriples: [4][]const u8 = .{ "arm-linux-gnueabihf", "armv7hl-redhat-linux-gnueabi", "armv6hl-suse-linux-gnueabi", "armv7hl-suse-linux-gnueabi" }; + + const ARMebLibDirs: [1][]const u8 = .{"/lib"}; + const ARMebTriples: [1][]const u8 = .{"armeb-linux-gnueabi"}; + const ARMebHFTriples: [2][]const u8 = .{ "armeb-linux-gnueabihf", "armebv7hl-redhat-linux-gnueabi" }; + + const AVRLibDirs: [1][]const u8 = .{"/lib"}; + const AVRTriples: [1][]const u8 = .{"avr"}; + + const CSKYLibDirs: [1][]const u8 = .{"/lib"}; + const CSKYTriples: [3][]const u8 = .{ "csky-linux-gnuabiv2", "csky-linux-uclibcabiv2", "csky-elf-noneabiv2" }; + + const X86_64LibDirs: [2][]const u8 = .{ "/lib64", "/lib" }; + const X86_64Triples: [11][]const u8 = .{ + "x86_64-linux-gnu", "x86_64-unknown-linux-gnu", + "x86_64-pc-linux-gnu", "x86_64-redhat-linux6E", + "x86_64-redhat-linux", "x86_64-suse-linux", + "x86_64-manbo-linux-gnu", "x86_64-linux-gnu", + "x86_64-slackware-linux", "x86_64-unknown-linux", + "x86_64-amazon-linux", + }; + const X32Triples: [2][]const u8 = .{ "x86_64-linux-gnux32", "x86_64-pc-linux-gnux32" }; + const X32LibDirs: [2][]const u8 = .{ "/libx32", "/lib" }; + const X86LibDirs: [2][]const u8 = .{ "/lib32", "/lib" }; + const X86Triples: [9][]const u8 = .{ + "i586-linux-gnu", "i686-linux-gnu", "i686-pc-linux-gnu", + "i386-redhat-linux6E", "i686-redhat-linux", "i386-redhat-linux", + "i586-suse-linux", "i686-montavista-linux", "i686-gnu", + }; + + const LoongArch64LibDirs: [2][]const u8 = .{ "/lib64", "/lib" }; + const LoongArch64Triples: [2][]const u8 = .{ "loongarch64-linux-gnu", "loongarch64-unknown-linux-gnu" }; + + const M68kLibDirs: [1][]const u8 = .{"/lib"}; + const M68kTriples: [3][]const u8 = .{ "m68k-linux-gnu", "m68k-unknown-linux-gnu", "m68k-suse-linux" }; + + const MIPSLibDirs: [2][]const u8 = .{ "/libo32", "/lib" }; + const MIPSTriples: [5][]const u8 = .{ + "mips-linux-gnu", "mips-mti-linux", + "mips-mti-linux-gnu", "mips-img-linux-gnu", + "mipsisa32r6-linux-gnu", + }; + const MIPSELLibDirs: [2][]const u8 = .{ "/libo32", "/lib" }; + const MIPSELTriples: [3][]const u8 = .{ "mipsel-linux-gnu", "mips-img-linux-gnu", "mipsisa32r6el-linux-gnu" }; + + const MIPS64LibDirs: [2][]const u8 = .{ "/lib64", "/lib" }; + const MIPS64Triples: [6][]const u8 = .{ + "mips64-linux-gnu", "mips-mti-linux-gnu", + "mips-img-linux-gnu", "mips64-linux-gnuabi64", + "mipsisa64r6-linux-gnu", "mipsisa64r6-linux-gnuabi64", + }; + const MIPS64ELLibDirs: [2][]const u8 = .{ "/lib64", "/lib" }; + const MIPS64ELTriples: [6][]const u8 = .{ + "mips64el-linux-gnu", "mips-mti-linux-gnu", + "mips-img-linux-gnu", "mips64el-linux-gnuabi64", + "mipsisa64r6el-linux-gnu", "mipsisa64r6el-linux-gnuabi64", + }; + + const MIPSN32LibDirs: [1][]const u8 = .{"/lib32"}; + const MIPSN32Triples: [2][]const u8 = .{ "mips64-linux-gnuabin32", "mipsisa64r6-linux-gnuabin32" }; + const MIPSN32ELLibDirs: [1][]const u8 = .{"/lib32"}; + const MIPSN32ELTriples: [2][]const u8 = .{ "mips64el-linux-gnuabin32", "mipsisa64r6el-linux-gnuabin32" }; + + const MSP430LibDirs: [1][]const u8 = .{"/lib"}; + const MSP430Triples: [1][]const u8 = .{"msp430-elf"}; + + const PPCLibDirs: [2][]const u8 = .{ "/lib32", "/lib" }; + const PPCTriples: [5][]const u8 = .{ + "powerpc-linux-gnu", "powerpc-unknown-linux-gnu", "powerpc-linux-gnuspe", + // On 32-bit PowerPC systems running SUSE Linux, gcc is configured as a + // 64-bit compiler which defaults to "-m32", hence "powerpc64-suse-linux". + "powerpc64-suse-linux", "powerpc-montavista-linuxspe", + }; + const PPCLELibDirs: [2][]const u8 = .{ "/lib32", "/lib" }; + const PPCLETriples: [3][]const u8 = .{ "powerpcle-linux-gnu", "powerpcle-unknown-linux-gnu", "powerpcle-linux-musl" }; + + const PPC64LibDirs: [2][]const u8 = .{ "/lib64", "/lib" }; + const PPC64Triples: [4][]const u8 = .{ + "powerpc64-linux-gnu", "powerpc64-unknown-linux-gnu", + "powerpc64-suse-linux", "ppc64-redhat-linux", + }; + const PPC64LELibDirs: [2][]const u8 = .{ "/lib64", "/lib" }; + const PPC64LETriples: [5][]const u8 = .{ + "powerpc64le-linux-gnu", "powerpc64le-unknown-linux-gnu", + "powerpc64le-none-linux-gnu", "powerpc64le-suse-linux", + "ppc64le-redhat-linux", + }; + + const RISCV32LibDirs: [2][]const u8 = .{ "/lib32", "/lib" }; + const RISCV32Triples: [3][]const u8 = .{ "riscv32-unknown-linux-gnu", "riscv32-linux-gnu", "riscv32-unknown-elf" }; + const RISCV64LibDirs: [2][]const u8 = .{ "/lib64", "/lib" }; + const RISCV64Triples: [3][]const u8 = .{ + "riscv64-unknown-linux-gnu", + "riscv64-linux-gnu", + "riscv64-unknown-elf", + }; + + const SPARCv8LibDirs: [2][]const u8 = .{ "/lib32", "/lib" }; + const SPARCv8Triples: [2][]const u8 = .{ "sparc-linux-gnu", "sparcv8-linux-gnu" }; + const SPARCv9LibDirs: [2][]const u8 = .{ "/lib64", "/lib" }; + const SPARCv9Triples: [2][]const u8 = .{ "sparc64-linux-gnu", "sparcv9-linux-gnu" }; + + const SystemZLibDirs: [2][]const u8 = .{ "/lib64", "/lib" }; + const SystemZTriples: [5][]const u8 = .{ + "s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu", + "s390x-suse-linux", "s390x-redhat-linux", + }; + const target = tc.getTarget(); + if (target.os.tag == .solaris) { + // TODO + return; + } + if (target.isAndroid()) { + const AArch64AndroidTriples: [1][]const u8 = .{"aarch64-linux-android"}; + const ARMAndroidTriples: [1][]const u8 = .{"arm-linux-androideabi"}; + const MIPSELAndroidTriples: [1][]const u8 = .{"mipsel-linux-android"}; + const MIPS64ELAndroidTriples: [1][]const u8 = .{"mips64el-linux-android"}; + const X86AndroidTriples: [1][]const u8 = .{"i686-linux-android"}; + const X86_64AndroidTriples: [1][]const u8 = .{"x86_64-linux-android"}; + + switch (target.cpu.arch) { + .aarch64 => { + lib_dirs.appendSliceAssumeCapacity(&AArch64LibDirs); + triple_aliases.appendSliceAssumeCapacity(&AArch64AndroidTriples); + }, + .arm, + .thumb, + => { + lib_dirs.appendSliceAssumeCapacity(&ARMLibDirs); + triple_aliases.appendSliceAssumeCapacity(&ARMAndroidTriples); + }, + .mipsel => { + lib_dirs.appendSliceAssumeCapacity(&MIPSELLibDirs); + triple_aliases.appendSliceAssumeCapacity(&MIPSELAndroidTriples); + biarch_libdirs.appendSliceAssumeCapacity(&MIPS64ELLibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&MIPS64ELAndroidTriples); + }, + .mips64el => { + lib_dirs.appendSliceAssumeCapacity(&MIPS64ELLibDirs); + triple_aliases.appendSliceAssumeCapacity(&MIPS64ELAndroidTriples); + biarch_libdirs.appendSliceAssumeCapacity(&MIPSELLibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&MIPSELAndroidTriples); + }, + .x86_64 => { + lib_dirs.appendSliceAssumeCapacity(&X86_64LibDirs); + triple_aliases.appendSliceAssumeCapacity(&X86_64AndroidTriples); + biarch_libdirs.appendSliceAssumeCapacity(&X86LibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&X86AndroidTriples); + }, + .x86 => { + lib_dirs.appendSliceAssumeCapacity(&X86LibDirs); + triple_aliases.appendSliceAssumeCapacity(&X86AndroidTriples); + biarch_libdirs.appendSliceAssumeCapacity(&X86_64LibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&X86_64AndroidTriples); + }, + else => {}, + } + return; + } + switch (target.cpu.arch) { + .aarch64 => { + lib_dirs.appendSliceAssumeCapacity(&AArch64LibDirs); + triple_aliases.appendSliceAssumeCapacity(&AArch64Triples); + biarch_libdirs.appendSliceAssumeCapacity(&AArch64LibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&AArch64Triples); + }, + .aarch64_be => { + lib_dirs.appendSliceAssumeCapacity(&AArch64beLibDirs); + triple_aliases.appendSliceAssumeCapacity(&AArch64beTriples); + biarch_libdirs.appendSliceAssumeCapacity(&AArch64beLibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&AArch64beTriples); + }, + .arm, .thumb => { + lib_dirs.appendSliceAssumeCapacity(&ARMLibDirs); + if (target.abi == .gnueabihf) { + triple_aliases.appendSliceAssumeCapacity(&ARMHFTriples); + } else { + triple_aliases.appendSliceAssumeCapacity(&ARMTriples); + } + }, + .armeb, .thumbeb => { + lib_dirs.appendSliceAssumeCapacity(&ARMebLibDirs); + if (target.abi == .gnueabihf) { + triple_aliases.appendSliceAssumeCapacity(&ARMebHFTriples); + } else { + triple_aliases.appendSliceAssumeCapacity(&ARMebTriples); + } + }, + .avr => { + lib_dirs.appendSliceAssumeCapacity(&AVRLibDirs); + triple_aliases.appendSliceAssumeCapacity(&AVRTriples); + }, + .csky => { + lib_dirs.appendSliceAssumeCapacity(&CSKYLibDirs); + triple_aliases.appendSliceAssumeCapacity(&CSKYTriples); + }, + .x86_64 => { + if (target.abi == .gnux32 or target.abi == .muslx32) { + lib_dirs.appendSliceAssumeCapacity(&X32LibDirs); + triple_aliases.appendSliceAssumeCapacity(&X32Triples); + biarch_libdirs.appendSliceAssumeCapacity(&X86_64LibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&X86_64Triples); + } else { + lib_dirs.appendSliceAssumeCapacity(&X86_64LibDirs); + triple_aliases.appendSliceAssumeCapacity(&X86_64Triples); + biarch_libdirs.appendSliceAssumeCapacity(&X32LibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&X32Triples); + } + biarch_libdirs.appendSliceAssumeCapacity(&X86LibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&X86Triples); + }, + .x86 => { + lib_dirs.appendSliceAssumeCapacity(&X86LibDirs); + // MCU toolchain is 32 bit only and its triple alias is TargetTriple + // itself, which will be appended below. + if (target.os.tag != .elfiamcu) { + triple_aliases.appendSliceAssumeCapacity(&X86Triples); + biarch_libdirs.appendSliceAssumeCapacity(&X86_64LibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&X86_64Triples); + biarch_libdirs.appendSliceAssumeCapacity(&X32LibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&X32Triples); + } + }, + .loongarch64 => { + lib_dirs.appendSliceAssumeCapacity(&LoongArch64LibDirs); + triple_aliases.appendSliceAssumeCapacity(&LoongArch64Triples); + }, + .m68k => { + lib_dirs.appendSliceAssumeCapacity(&M68kLibDirs); + triple_aliases.appendSliceAssumeCapacity(&M68kTriples); + }, + .mips => { + lib_dirs.appendSliceAssumeCapacity(&MIPSLibDirs); + triple_aliases.appendSliceAssumeCapacity(&MIPSTriples); + biarch_libdirs.appendSliceAssumeCapacity(&MIPS64LibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&MIPS64Triples); + biarch_libdirs.appendSliceAssumeCapacity(&MIPSN32LibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&MIPSN32Triples); + }, + .mipsel => { + lib_dirs.appendSliceAssumeCapacity(&MIPSELLibDirs); + triple_aliases.appendSliceAssumeCapacity(&MIPSELTriples); + triple_aliases.appendSliceAssumeCapacity(&MIPSTriples); + biarch_libdirs.appendSliceAssumeCapacity(&MIPS64ELLibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&MIPS64ELTriples); + biarch_libdirs.appendSliceAssumeCapacity(&MIPSN32ELLibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&MIPSN32ELTriples); + }, + .mips64 => { + lib_dirs.appendSliceAssumeCapacity(&MIPS64LibDirs); + triple_aliases.appendSliceAssumeCapacity(&MIPS64Triples); + biarch_libdirs.appendSliceAssumeCapacity(&MIPSLibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&MIPSTriples); + biarch_libdirs.appendSliceAssumeCapacity(&MIPSN32LibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&MIPSN32Triples); + }, + .mips64el => { + lib_dirs.appendSliceAssumeCapacity(&MIPS64ELLibDirs); + triple_aliases.appendSliceAssumeCapacity(&MIPS64ELTriples); + biarch_libdirs.appendSliceAssumeCapacity(&MIPSELLibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&MIPSELTriples); + biarch_libdirs.appendSliceAssumeCapacity(&MIPSN32ELLibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&MIPSN32ELTriples); + biarch_triple_aliases.appendSliceAssumeCapacity(&MIPSTriples); + }, + .msp430 => { + lib_dirs.appendSliceAssumeCapacity(&MSP430LibDirs); + triple_aliases.appendSliceAssumeCapacity(&MSP430Triples); + }, + .powerpc => { + lib_dirs.appendSliceAssumeCapacity(&PPCLibDirs); + triple_aliases.appendSliceAssumeCapacity(&PPCTriples); + biarch_libdirs.appendSliceAssumeCapacity(&PPC64LibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&PPC64Triples); + }, + .powerpcle => { + lib_dirs.appendSliceAssumeCapacity(&PPCLELibDirs); + triple_aliases.appendSliceAssumeCapacity(&PPCLETriples); + biarch_libdirs.appendSliceAssumeCapacity(&PPC64LELibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&PPC64LETriples); + }, + .powerpc64 => { + lib_dirs.appendSliceAssumeCapacity(&PPC64LibDirs); + triple_aliases.appendSliceAssumeCapacity(&PPC64Triples); + biarch_libdirs.appendSliceAssumeCapacity(&PPCLibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&PPCTriples); + }, + .powerpc64le => { + lib_dirs.appendSliceAssumeCapacity(&PPC64LELibDirs); + triple_aliases.appendSliceAssumeCapacity(&PPC64LETriples); + biarch_libdirs.appendSliceAssumeCapacity(&PPCLELibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&PPCLETriples); + }, + .riscv32 => { + lib_dirs.appendSliceAssumeCapacity(&RISCV32LibDirs); + triple_aliases.appendSliceAssumeCapacity(&RISCV32Triples); + biarch_libdirs.appendSliceAssumeCapacity(&RISCV64LibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&RISCV64Triples); + }, + .riscv64 => { + lib_dirs.appendSliceAssumeCapacity(&RISCV64LibDirs); + triple_aliases.appendSliceAssumeCapacity(&RISCV64Triples); + biarch_libdirs.appendSliceAssumeCapacity(&RISCV32LibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&RISCV32Triples); + }, + .sparc, .sparcel => { + lib_dirs.appendSliceAssumeCapacity(&SPARCv8LibDirs); + triple_aliases.appendSliceAssumeCapacity(&SPARCv8Triples); + biarch_libdirs.appendSliceAssumeCapacity(&SPARCv9LibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&SPARCv9Triples); + }, + .sparc64 => { + lib_dirs.appendSliceAssumeCapacity(&SPARCv9LibDirs); + triple_aliases.appendSliceAssumeCapacity(&SPARCv9Triples); + biarch_libdirs.appendSliceAssumeCapacity(&SPARCv8LibDirs); + biarch_triple_aliases.appendSliceAssumeCapacity(&SPARCv8Triples); + }, + .s390x => { + lib_dirs.appendSliceAssumeCapacity(&SystemZLibDirs); + triple_aliases.appendSliceAssumeCapacity(&SystemZTriples); + }, + else => {}, + } +} + +pub fn discover(self: *GCCDetector, tc: *Toolchain) !void { + var path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + var fib = std.heap.FixedBufferAllocator.init(&path_buf); + + const target = tc.getTarget(); + const biarch_variant_target = if (target.ptrBitWidth() == 32) target_util.get64BitArchVariant(target) else target_util.get32BitArchVariant(target); + + var candidate_lib_dirs: PathPrefixes = .{}; + var candidate_biarch_lib_dirs: PathPrefixes = .{}; + var candidate_triple_aliases: PathPrefixes = .{}; + var candidate_biarch_triple_aliases: PathPrefixes = .{}; + try collectLibDirsAndTriples(tc, &candidate_lib_dirs, &candidate_biarch_lib_dirs, &candidate_triple_aliases, &candidate_biarch_triple_aliases); + + var target_buf: [64]u8 = undefined; + const triple_str = target_util.toLLVMTriple(target, &target_buf); + candidate_triple_aliases.appendAssumeCapacity(triple_str); + + // Also include the multiarch variant if it's different. + var biarch_buf: [64]u8 = undefined; + if (biarch_variant_target) |biarch_target| { + const biarch_triple_str = target_util.toLLVMTriple(biarch_target, &biarch_buf); + if (!std.mem.eql(u8, biarch_triple_str, triple_str)) { + candidate_triple_aliases.appendAssumeCapacity(biarch_triple_str); + } + } + + var prefixes: PathPrefixes = .{}; + const gcc_toolchain_dir = gccToolchainDir(tc); + if (gcc_toolchain_dir.len != 0) { + const adjusted = if (gcc_toolchain_dir[gcc_toolchain_dir.len - 1] == '/') + gcc_toolchain_dir[0 .. gcc_toolchain_dir.len - 1] + else + gcc_toolchain_dir; + prefixes.appendAssumeCapacity(adjusted); + } else { + const sysroot = tc.getSysroot(); + if (sysroot.len > 0) { + prefixes.appendAssumeCapacity(sysroot); + try addDefaultGCCPrefixes(&prefixes, tc); + } + + if (sysroot.len == 0) { + try addDefaultGCCPrefixes(&prefixes, tc); + } + // TODO: Special-case handling for Gentoo + } + + const v0 = GCCVersion.parse("0.0.0"); + for (prefixes.constSlice()) |prefix| { + if (!tc.filesystem.exists(prefix)) continue; + + for (candidate_lib_dirs.constSlice()) |suffix| { + defer fib.reset(); + const lib_dir = std.fs.path.join(fib.allocator(), &.{ prefix, suffix }) catch continue; + if (!tc.filesystem.exists(lib_dir)) continue; + + const gcc_dir_exists = tc.filesystem.joinedExists(&.{ lib_dir, "/gcc" }); + const gcc_cross_dir_exists = tc.filesystem.joinedExists(&.{ lib_dir, "/gcc-cross" }); + + try self.scanLibDirForGCCTriple(tc, target, lib_dir, triple_str, false, gcc_dir_exists, gcc_cross_dir_exists); + for (candidate_triple_aliases.constSlice()) |candidate| { + try self.scanLibDirForGCCTriple(tc, target, lib_dir, candidate, false, gcc_dir_exists, gcc_cross_dir_exists); + } + } + for (candidate_biarch_lib_dirs.constSlice()) |suffix| { + const lib_dir = std.fs.path.join(fib.allocator(), &.{ prefix, suffix }) catch continue; + if (!tc.filesystem.exists(lib_dir)) continue; + + const gcc_dir_exists = tc.filesystem.joinedExists(&.{ lib_dir, "/gcc" }); + const gcc_cross_dir_exists = tc.filesystem.joinedExists(&.{ lib_dir, "/gcc-cross" }); + for (candidate_biarch_triple_aliases.constSlice()) |candidate| { + try self.scanLibDirForGCCTriple(tc, target, lib_dir, candidate, true, gcc_dir_exists, gcc_cross_dir_exists); + } + } + if (self.version.order(v0) == .gt) break; + } +} + +fn findBiarchMultilibs(tc: *const Toolchain, result: *Multilib.Detected, target: std.Target, path: [2][]const u8, needs_biarch_suffix: bool) !bool { + const suff64 = if (target.os.tag == .solaris) switch (target.cpu.arch) { + .x86, .x86_64 => "/amd64", + .sparc => "/sparcv9", + else => "/64", + } else "/64"; + + const alt_64 = Multilib.init(suff64, suff64, &.{ "-m32", "+m64", "-mx32" }); + const alt_32 = Multilib.init("/32", "/32", &.{ "+m32", "-m64", "-mx32" }); + const alt_x32 = Multilib.init("/x32", "/x32", &.{ "-m32", "-m64", "+mx32" }); + + const multilib_filter = Multilib.Filter{ + .base = path, + .file = if (target.os.tag == .elfiamcu) "libgcc.a" else "crtbegin.o", + }; + + const Want = enum { + want32, + want64, + wantx32, + }; + const is_x32 = target.abi == .gnux32 or target.abi == .muslx32; + const target_ptr_width = target.ptrBitWidth(); + const want: Want = if (target_ptr_width == 32 and multilib_filter.exists(alt_32, tc.filesystem)) + .want64 + else if (target_ptr_width == 64 and is_x32 and multilib_filter.exists(alt_x32, tc.filesystem)) + .want64 + else if (target_ptr_width == 64 and !is_x32 and multilib_filter.exists(alt_64, tc.filesystem)) + .want32 + else if (target_ptr_width == 32) + if (needs_biarch_suffix) .want64 else .want32 + else if (is_x32) + if (needs_biarch_suffix) .want64 else .wantx32 + else if (needs_biarch_suffix) .want32 else .want64; + + const default = switch (want) { + .want32 => Multilib.init("", "", &.{ "+m32", "-m64", "-mx32" }), + .want64 => Multilib.init("", "", &.{ "-m32", "+m64", "-mx32" }), + .wantx32 => Multilib.init("", "", &.{ "-m32", "-m64", "+mx32" }), + }; + result.multilibs.appendSliceAssumeCapacity(&.{ + default, + alt_64, + alt_32, + alt_x32, + }); + result.filter(multilib_filter, tc.filesystem); + var flags: Multilib.Flags = .{}; + flags.appendAssumeCapacity(if (target_ptr_width == 64 and !is_x32) "+m64" else "-m64"); + flags.appendAssumeCapacity(if (target_ptr_width == 32) "+m32" else "-m32"); + flags.appendAssumeCapacity(if (target_ptr_width == 64 and is_x32) "+mx32" else "-mx32"); + + return result.select(flags); +} + +fn scanGCCForMultilibs(self: *GCCDetector, tc: *const Toolchain, target: std.Target, path: [2][]const u8, needs_biarch_suffix: bool) !bool { + var detected: Multilib.Detected = .{}; + if (target.cpu.arch == .csky) { + // TODO + } else if (target.cpu.arch.isMIPS()) { + // TODO + } else if (target.cpu.arch.isRISCV()) { + // TODO + } else if (target.cpu.arch == .msp430) { + // TODO + } else if (target.cpu.arch == .avr) { + // No multilibs + } else if (!try findBiarchMultilibs(tc, &detected, target, path, needs_biarch_suffix)) { + return false; + } + self.selected = detected.selected; + self.biarch_sibling = detected.biarch_sibling; + return true; +} + +fn scanLibDirForGCCTriple( + self: *GCCDetector, + tc: *const Toolchain, + target: std.Target, + lib_dir: []const u8, + candidate_triple: []const u8, + needs_biarch_suffix: bool, + gcc_dir_exists: bool, + gcc_cross_dir_exists: bool, +) !void { + var path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + var fib = std.heap.FixedBufferAllocator.init(&path_buf); + for (0..2) |i| { + if (i == 0 and !gcc_dir_exists) continue; + if (i == 1 and !gcc_cross_dir_exists) continue; + defer fib.reset(); + + const base: []const u8 = if (i == 0) "gcc" else "gcc-cross"; + var lib_suffix_buf: [64]u8 = undefined; + var suffix_buf_fib = std.heap.FixedBufferAllocator.init(&lib_suffix_buf); + const lib_suffix = std.fs.path.join(suffix_buf_fib.allocator(), &.{ base, candidate_triple }) catch continue; + + const dir_name = std.fs.path.join(fib.allocator(), &.{ lib_dir, lib_suffix }) catch continue; + var parent_dir = tc.filesystem.openIterableDir(dir_name) catch continue; + defer parent_dir.close(); + + var it = parent_dir.iterate(); + while (it.next() catch continue) |entry| { + if (entry.kind != .directory) continue; + + const version_text = entry.name; + const candidate_version = GCCVersion.parse(version_text); + if (candidate_version.major != -1) { + // TODO: cache path so we're not repeatedly scanning + } + if (candidate_version.isLessThan(4, 1, 1, "")) continue; + switch (candidate_version.order(self.version)) { + .lt, .eq => continue, + .gt => {}, + } + + if (!try self.scanGCCForMultilibs(tc, target, .{ dir_name, version_text }, needs_biarch_suffix)) continue; + + self.version = candidate_version; + self.gcc_triple = try tc.arena.dupe(u8, candidate_triple); + self.install_path = try std.fs.path.join(tc.arena, &.{ lib_dir, lib_suffix, version_text }); + self.parent_lib_path = try std.fs.path.join(tc.arena, &.{ self.install_path, "..", "..", ".." }); + self.is_valid = true; + } + } +} + +fn gccToolchainDir(tc: *const Toolchain) []const u8 { + const sysroot = tc.getSysroot(); + if (sysroot.len != 0) return ""; + return system_defaults.gcc_install_prefix; +} diff --git a/deps/aro/Driver/GCCVersion.zig b/deps/aro/Driver/GCCVersion.zig new file mode 100644 index 000000000000..c4d6a65e5e99 --- /dev/null +++ b/deps/aro/Driver/GCCVersion.zig @@ -0,0 +1,122 @@ +const std = @import("std"); +const mem = std.mem; +const Order = std.math.Order; + +const GCCVersion = @This(); + +/// Raw version number text +raw: []const u8 = "", + +/// -1 indicates not present +major: i32 = -1, +/// -1 indicates not present +minor: i32 = -1, +/// -1 indicates not present +patch: i32 = -1, + +/// Text of parsed major version number +major_str: []const u8 = "", +/// Text of parsed major + minor version number +minor_str: []const u8 = "", + +/// Patch number suffix +suffix: []const u8 = "", + +/// This orders versions according to the preferred usage order, not a notion of release-time ordering +/// Higher version numbers are preferred, but nonexistent minor/patch/suffix is preferred to one that does exist +/// e.g. `4.1` is preferred over `4.0` but `4` is preferred over both `4.0` and `4.1` +pub fn isLessThan(self: GCCVersion, rhs_major: i32, rhs_minor: i32, rhs_patch: i32, rhs_suffix: []const u8) bool { + if (self.major != rhs_major) { + return self.major < rhs_major; + } + if (self.minor != rhs_minor) { + if (rhs_minor == -1) return true; + if (self.minor == -1) return false; + return self.minor < rhs_minor; + } + if (self.patch != rhs_patch) { + if (rhs_patch == -1) return true; + if (self.patch == -1) return false; + return self.patch < rhs_patch; + } + if (!mem.eql(u8, self.suffix, rhs_suffix)) { + if (rhs_suffix.len == 0) return true; + if (self.suffix.len == 0) return false; + return switch (std.mem.order(u8, self.suffix, rhs_suffix)) { + .lt => true, + .eq => unreachable, + .gt => false, + }; + } + return false; +} + +/// Strings in the returned GCCVersion struct have the same lifetime as `text` +pub fn parse(text: []const u8) GCCVersion { + const bad = GCCVersion{ .major = -1 }; + var good = bad; + + var it = mem.splitScalar(u8, text, '.'); + const first = it.next().?; + const second = it.next() orelse ""; + const rest = it.next() orelse ""; + + good.major = std.fmt.parseInt(i32, first, 10) catch return bad; + if (good.major < 0) return bad; + good.major_str = first; + + if (second.len == 0) return good; + var minor_str = second; + + if (rest.len == 0) { + const end = mem.indexOfNone(u8, minor_str, "0123456789") orelse minor_str.len; + if (end > 0) { + good.suffix = minor_str[end..]; + minor_str = minor_str[0..end]; + } + } + good.minor = std.fmt.parseInt(i32, minor_str, 10) catch return bad; + if (good.minor < 0) return bad; + good.minor_str = minor_str; + + if (rest.len > 0) { + const end = mem.indexOfNone(u8, rest, "0123456789") orelse rest.len; + if (end > 0) { + const patch_num_text = rest[0..end]; + good.patch = std.fmt.parseInt(i32, patch_num_text, 10) catch return bad; + if (good.patch < 0) return bad; + good.suffix = rest[end..]; + } + } + + return good; +} + +pub fn order(a: GCCVersion, b: GCCVersion) Order { + if (a.isLessThan(b.major, b.minor, b.patch, b.suffix)) return .lt; + if (b.isLessThan(a.major, a.minor, a.patch, a.suffix)) return .gt; + return .eq; +} + +test parse { + const versions = [10]GCCVersion{ + parse("5"), + parse("4"), + parse("4.2"), + parse("4.0"), + parse("4.0-patched"), + parse("4.0.2"), + parse("4.0.1"), + parse("4.0.1-patched"), + parse("4.0.0"), + parse("4.0.0-patched"), + }; + + for (versions[0 .. versions.len - 1], versions[1..versions.len]) |first, second| { + try std.testing.expectEqual(Order.eq, first.order(first)); + try std.testing.expectEqual(Order.gt, first.order(second)); + try std.testing.expectEqual(Order.lt, second.order(first)); + } + const last = versions[versions.len - 1]; + try std.testing.expectEqual(Order.eq, last.order(last)); +} diff --git a/deps/aro/Driver/Multilib.zig b/deps/aro/Driver/Multilib.zig new file mode 100644 index 000000000000..673ae6f24fc7 --- /dev/null +++ b/deps/aro/Driver/Multilib.zig @@ -0,0 +1,72 @@ +const std = @import("std"); +const util = @import("../util.zig"); +const Filesystem = @import("Filesystem.zig").Filesystem; + +pub const Flags = std.BoundedArray([]const u8, 6); + +/// Large enough for GCCDetector for Linux; may need to be increased to support other toolchains. +const max_multilibs = 4; + +const MultilibArray = std.BoundedArray(Multilib, max_multilibs); + +pub const Detected = struct { + multilibs: MultilibArray = .{}, + selected: Multilib = .{}, + biarch_sibling: ?Multilib = null, + + pub fn filter(self: *Detected, multilib_filter: Filter, fs: Filesystem) void { + var found_count: usize = 0; + for (self.multilibs.constSlice()) |multilib| { + if (multilib_filter.exists(multilib, fs)) { + self.multilibs.set(found_count, multilib); + found_count += 1; + } + } + self.multilibs.resize(found_count) catch unreachable; + } + + pub fn select(self: *Detected, flags: Flags) !bool { + var filtered: MultilibArray = .{}; + for (self.multilibs.constSlice()) |multilib| { + for (multilib.flags.constSlice()) |multilib_flag| { + const matched = for (flags.constSlice()) |arg_flag| { + if (std.mem.eql(u8, arg_flag[1..], multilib_flag[1..])) break arg_flag; + } else multilib_flag; + if (matched[0] != multilib_flag[0]) break; + } else { + filtered.appendAssumeCapacity(multilib); + } + } + if (filtered.len == 0) return false; + if (filtered.len == 1) { + self.selected = filtered.get(0); + return true; + } + return error.TooManyMultilibs; + } +}; + +pub const Filter = struct { + base: [2][]const u8, + file: []const u8, + pub fn exists(self: Filter, m: Multilib, fs: Filesystem) bool { + return fs.joinedExists(&.{ self.base[0], self.base[1], m.gcc_suffix, self.file }); + } +}; + +const Multilib = @This(); + +gcc_suffix: []const u8 = "", +os_suffix: []const u8 = "", +include_suffix: []const u8 = "", +flags: Flags = .{}, +priority: u32 = 0, + +pub fn init(gcc_suffix: []const u8, os_suffix: []const u8, flags: []const []const u8) Multilib { + var self: Multilib = .{ + .gcc_suffix = gcc_suffix, + .os_suffix = os_suffix, + }; + self.flags.appendSliceAssumeCapacity(flags); + return self; +} diff --git a/deps/aro/InitList.zig b/deps/aro/InitList.zig new file mode 100644 index 000000000000..b4eae645d909 --- /dev/null +++ b/deps/aro/InitList.zig @@ -0,0 +1,153 @@ +//! Sparsely populated list of used indexes. +//! Used for detecting duplicate initializers. +const std = @import("std"); +const Allocator = std.mem.Allocator; +const testing = std.testing; +const Tree = @import("Tree.zig"); +const Token = Tree.Token; +const TokenIndex = Tree.TokenIndex; +const NodeIndex = Tree.NodeIndex; +const Type = @import("Type.zig"); +const Diagnostics = @import("Diagnostics.zig"); +const NodeList = std.ArrayList(NodeIndex); +const Parser = @import("Parser.zig"); + +const InitList = @This(); + +const Item = struct { + list: InitList = .{}, + index: u64, + + fn order(_: void, a: Item, b: Item) std.math.Order { + return std.math.order(a.index, b.index); + } +}; + +list: std.ArrayListUnmanaged(Item) = .{}, +node: NodeIndex = .none, +tok: TokenIndex = 0, + +/// Deinitialize freeing all memory. +pub fn deinit(il: *InitList, gpa: Allocator) void { + for (il.list.items) |*item| item.list.deinit(gpa); + il.list.deinit(gpa); + il.* = undefined; +} + +/// Insert initializer at index, returning previous entry if one exists. +pub fn put(il: *InitList, gpa: Allocator, index: usize, node: NodeIndex, tok: TokenIndex) !?TokenIndex { + const items = il.list.items; + var left: usize = 0; + var right: usize = items.len; + + // Append new value to empty list + if (left == right) { + const item = try il.list.addOne(gpa); + item.* = .{ + .list = .{ .node = node, .tok = tok }, + .index = index, + }; + return null; + } + + while (left < right) { + // Avoid overflowing in the midpoint calculation + const mid = left + (right - left) / 2; + // Compare the key with the midpoint element + switch (std.math.order(index, items[mid].index)) { + .eq => { + // Replace previous entry. + const prev = items[mid].list.tok; + items[mid].list.deinit(gpa); + items[mid] = .{ + .list = .{ .node = node, .tok = tok }, + .index = index, + }; + return prev; + }, + .gt => left = mid + 1, + .lt => right = mid, + } + } + + // Insert a new value into a sorted position. + try il.list.insert(gpa, left, .{ + .list = .{ .node = node, .tok = tok }, + .index = index, + }); + return null; +} + +/// Find item at index, create new if one does not exist. +pub fn find(il: *InitList, gpa: Allocator, index: u64) !*InitList { + const items = il.list.items; + var left: usize = 0; + var right: usize = items.len; + + // Append new value to empty list + if (left == right) { + const item = try il.list.addOne(gpa); + item.* = .{ + .list = .{ .node = .none, .tok = 0 }, + .index = index, + }; + return &item.list; + } + + while (left < right) { + // Avoid overflowing in the midpoint calculation + const mid = left + (right - left) / 2; + // Compare the key with the midpoint element + switch (std.math.order(index, items[mid].index)) { + .eq => return &items[mid].list, + .gt => left = mid + 1, + .lt => right = mid, + } + } + + // Insert a new value into a sorted position. + try il.list.insert(gpa, left, .{ + .list = .{ .node = .none, .tok = 0 }, + .index = index, + }); + return &il.list.items[left].list; +} + +test "basic usage" { + const gpa = testing.allocator; + var il: InitList = .{}; + defer il.deinit(gpa); + + { + var i: usize = 0; + while (i < 5) : (i += 1) { + const prev = try il.put(gpa, i, .none, 0); + try testing.expect(prev == null); + } + } + + { + const failing = testing.failing_allocator; + var i: usize = 0; + while (i < 5) : (i += 1) { + _ = try il.find(failing, i); + } + } + + { + var item = try il.find(gpa, 0); + var i: usize = 1; + while (i < 5) : (i += 1) { + item = try item.find(gpa, i); + } + } + + { + const failing = testing.failing_allocator; + var item = try il.find(failing, 0); + var i: usize = 1; + while (i < 5) : (i += 1) { + item = try item.find(failing, i); + } + } +} diff --git a/deps/aro/Interner.zig b/deps/aro/Interner.zig new file mode 100644 index 000000000000..023a3e79f0f4 --- /dev/null +++ b/deps/aro/Interner.zig @@ -0,0 +1,180 @@ +const Interner = @This(); +const std = @import("std"); +const Allocator = std.mem.Allocator; +const assert = std.debug.assert; +const Value = @import("Value.zig"); + +map: std.ArrayHashMapUnmanaged(Key, void, KeyContext, false) = .{}, + +const KeyContext = struct { + pub fn eql(_: @This(), a: Key, b: Key, _: usize) bool { + return b.eql(a); + } + + pub fn hash(_: @This(), a: Key) u32 { + return a.hash(); + } +}; + +pub const Key = union(enum) { + int: u16, + float: u16, + ptr, + noreturn, + void, + func, + array: struct { + len: u64, + child: Ref, + }, + vector: struct { + len: u32, + child: Ref, + }, + value: Value, + record: struct { + /// Pointer to user data, value used for hash and equality check. + user_ptr: *anyopaque, + /// TODO make smaller if Value is made smaller + elements: []const Ref, + }, + + pub fn hash(key: Key) u32 { + var hasher = std.hash.Wyhash.init(0); + switch (key) { + .value => |val| { + std.hash.autoHash(&hasher, val.tag); + switch (val.tag) { + .unavailable => unreachable, + .nullptr_t => std.hash.autoHash(&hasher, @as(u64, 0)), + .int => std.hash.autoHash(&hasher, val.data.int), + .float => std.hash.autoHash(&hasher, @as(u64, @bitCast(val.data.float))), + .bytes => std.hash.autoHashStrat(&hasher, val.data.bytes, .Shallow), + } + }, + .record => |info| { + std.hash.autoHash(&hasher, @intFromPtr(info.user_ptr)); + }, + inline else => |info| { + std.hash.autoHash(&hasher, info); + }, + } + return @truncate(hasher.final()); + } + + pub fn eql(a: Key, b: Key) bool { + const KeyTag = std.meta.Tag(Key); + const a_tag: KeyTag = a; + const b_tag: KeyTag = b; + if (a_tag != b_tag) return false; + switch (a) { + .value => |a_info| { + const b_info = b.value; + if (a_info.tag != b_info.tag) return false; + switch (a_info.tag) { + .unavailable => unreachable, + .nullptr_t => return true, + .int => return a_info.data.int == b_info.data.int, + .float => return a_info.data.float == b_info.data.float, + .bytes => return a_info.data.bytes.start == b_info.data.bytes.start and a_info.data.bytes.end == b_info.data.bytes.end, + } + }, + .record => |a_info| { + return a_info.user_ptr == b.record.user_ptr; + }, + inline else => |a_info, tag| { + const b_info = @field(b, @tagName(tag)); + return std.meta.eql(a_info, b_info); + }, + } + } + + fn toRef(key: Key) ?Ref { + switch (key) { + .int => |bits| switch (bits) { + 1 => return .i1, + 8 => return .i8, + 16 => return .i16, + 32 => return .i32, + 64 => return .i64, + 128 => return .i128, + else => {}, + }, + .float => |bits| switch (bits) { + 16 => return .f16, + 32 => return .f32, + 64 => return .f64, + 80 => return .f80, + 128 => return .f128, + else => unreachable, + }, + .ptr => return .ptr, + .func => return .func, + .noreturn => return .noreturn, + .void => return .void, + else => {}, + } + return null; + } +}; + +pub const Ref = enum(u32) { + const max = std.math.maxInt(u32); + + ptr = max - 0, + noreturn = max - 1, + void = max - 2, + i1 = max - 3, + i8 = max - 4, + i16 = max - 5, + i32 = max - 6, + i64 = max - 7, + i128 = max - 8, + f16 = max - 9, + f32 = max - 10, + f64 = max - 11, + f80 = max - 12, + f128 = max - 13, + func = max - 14, + _, +}; + +pub fn deinit(ip: *Interner, gpa: Allocator) void { + ip.map.deinit(gpa); +} + +pub fn put(ip: *Interner, gpa: Allocator, key: Key) !Ref { + if (key.toRef()) |some| return some; + const gop = try ip.map.getOrPut(gpa, key); + return @enumFromInt(gop.index); +} + +pub fn has(ip: *Interner, key: Key) ?Ref { + if (key.toRef()) |some| return some; + if (ip.map.getIndex(key)) |index| { + return @enumFromInt(index); + } + return null; +} + +pub fn get(ip: Interner, ref: Ref) Key { + switch (ref) { + .ptr => return .ptr, + .func => return .func, + .noreturn => return .noreturn, + .void => return .void, + .i1 => return .{ .int = 1 }, + .i8 => return .{ .int = 8 }, + .i16 => return .{ .int = 16 }, + .i32 => return .{ .int = 32 }, + .i64 => return .{ .int = 64 }, + .i128 => return .{ .int = 128 }, + .f16 => return .{ .float = 16 }, + .f32 => return .{ .float = 32 }, + .f64 => return .{ .float = 64 }, + .f80 => return .{ .float = 80 }, + .f128 => return .{ .float = 128 }, + else => {}, + } + return ip.map.keys()[@intFromEnum(ref)]; +} diff --git a/deps/aro/Ir.zig b/deps/aro/Ir.zig new file mode 100644 index 000000000000..4373925295c0 --- /dev/null +++ b/deps/aro/Ir.zig @@ -0,0 +1,601 @@ +const std = @import("std"); +const assert = std.debug.assert; +const Allocator = std.mem.Allocator; +const Compilation = @import("Compilation.zig"); +const Interner = @import("Interner.zig"); +const StringId = @import("StringInterner.zig").StringId; +const Value = @import("Value.zig"); + +const Ir = @This(); + +pool: Interner, +strings: []const u8, +// decls: std.StringArrayHashMapUnmanaged(Decl), + +// pub const Decl = struct { +instructions: std.MultiArrayList(Inst), +body: std.ArrayListUnmanaged(Ref), +arena: std.heap.ArenaAllocator.State, +// }; + +pub const Builder = struct { + gpa: Allocator, + arena: std.heap.ArenaAllocator, + instructions: std.MultiArrayList(Ir.Inst) = .{}, + body: std.ArrayListUnmanaged(Ref) = .{}, + alloc_count: u32 = 0, + arg_count: u32 = 0, + pool: Interner = .{}, + current_label: Ref = undefined, + + pub fn deinit(b: *Builder) void { + b.arena.deinit(); + b.instructions.deinit(b.gpa); + b.body.deinit(b.gpa); + b.pool.deinit(b.gpa); + b.* = undefined; + } + + pub fn startFn(b: *Builder) Allocator.Error!void { + b.alloc_count = 0; + b.arg_count = 0; + b.instructions.len = 0; + b.body.items.len = 0; + const entry = try b.makeLabel("entry"); + try b.body.append(b.gpa, entry); + b.current_label = entry; + } + + pub fn startBlock(b: *Builder, label: Ref) !void { + try b.body.append(b.gpa, label); + b.current_label = label; + } + + pub fn addArg(b: *Builder, ty: Interner.Ref) Allocator.Error!Ref { + const ref: Ref = @enumFromInt(b.instructions.len); + try b.instructions.append(b.gpa, .{ .tag = .arg, .data = .{ .none = {} }, .ty = ty }); + try b.body.insert(b.gpa, b.arg_count, ref); + b.arg_count += 1; + return ref; + } + + pub fn addAlloc(b: *Builder, size: u32, @"align": u32) Allocator.Error!Ref { + const ref: Ref = @enumFromInt(b.instructions.len); + try b.instructions.append(b.gpa, .{ + .tag = .alloc, + .data = .{ .alloc = .{ .size = size, .@"align" = @"align" } }, + .ty = .ptr, + }); + try b.body.insert(b.gpa, b.alloc_count + b.arg_count + 1, ref); + b.alloc_count += 1; + return ref; + } + + pub fn addInst(b: *Builder, tag: Ir.Inst.Tag, data: Ir.Inst.Data, ty: Interner.Ref) Allocator.Error!Ref { + const ref: Ref = @enumFromInt(b.instructions.len); + try b.instructions.append(b.gpa, .{ .tag = tag, .data = data, .ty = ty }); + try b.body.append(b.gpa, ref); + return ref; + } + + pub fn makeLabel(b: *Builder, name: [*:0]const u8) Allocator.Error!Ref { + const ref: Ref = @enumFromInt(b.instructions.len); + try b.instructions.append(b.gpa, .{ .tag = .label, .data = .{ .label = name }, .ty = .void }); + return ref; + } + + pub fn addJump(b: *Builder, label: Ref) Allocator.Error!void { + _ = try b.addInst(.jmp, .{ .un = label }, .noreturn); + } + + pub fn addBranch(b: *Builder, cond: Ref, true_label: Ref, false_label: Ref) Allocator.Error!void { + const branch = try b.arena.allocator().create(Ir.Inst.Branch); + branch.* = .{ + .cond = cond, + .then = true_label, + .@"else" = false_label, + }; + _ = try b.addInst(.branch, .{ .branch = branch }, .noreturn); + } + + pub fn addSwitch(b: *Builder, target: Ref, values: []Interner.Ref, labels: []Ref, default: Ref) Allocator.Error!void { + assert(values.len == labels.len); + const a = b.arena.allocator(); + const @"switch" = try a.create(Ir.Inst.Switch); + @"switch".* = .{ + .target = target, + .cases_len = @intCast(values.len), + .case_vals = (try a.dupe(Interner.Ref, values)).ptr, + .case_labels = (try a.dupe(Ref, labels)).ptr, + .default = default, + }; + _ = try b.addInst(.@"switch", .{ .@"switch" = @"switch" }, .noreturn); + } + + pub fn addStore(b: *Builder, ptr: Ref, val: Ref) Allocator.Error!void { + _ = try b.addInst(.store, .{ .bin = .{ .lhs = ptr, .rhs = val } }, .void); + } + + pub fn addConstant(b: *Builder, val: Value, ty: Interner.Ref) Allocator.Error!Ref { + const ref: Ref = @enumFromInt(b.instructions.len); + const key: Interner.Key = .{ + .value = val, + }; + const val_ref = try b.pool.put(b.gpa, key); + try b.instructions.append(b.gpa, .{ .tag = .constant, .data = .{ + .constant = val_ref, + }, .ty = ty }); + return ref; + } + + pub fn addPhi(b: *Builder, inputs: []const Inst.Phi.Input, ty: Interner.Ref) Allocator.Error!Ref { + const a = b.arena.allocator(); + const input_refs = try a.alloc(Ref, inputs.len * 2 + 1); + input_refs[0] = @enumFromInt(inputs.len); + std.mem.copy(Ref, input_refs[1..], std.mem.bytesAsSlice(Ref, std.mem.sliceAsBytes(inputs))); + + return b.addInst(.phi, .{ .phi = .{ .ptr = input_refs.ptr } }, ty); + } + + pub fn addSelect(b: *Builder, cond: Ref, then: Ref, @"else": Ref, ty: Interner.Ref) Allocator.Error!Ref { + const branch = try b.arena.allocator().create(Ir.Inst.Branch); + branch.* = .{ + .cond = cond, + .then = then, + .@"else" = @"else", + }; + return b.addInst(.select, .{ .branch = branch }, ty); + } +}; + +pub const Ref = enum(u32) { none = std.math.maxInt(u32), _ }; + +pub const Inst = struct { + tag: Tag, + data: Data, + ty: Interner.Ref, + + pub const Tag = enum { + // data.constant + // not included in blocks + constant, + + // data.arg + // not included in blocks + arg, + symbol, + + // data.label + label, + + // data.block + label_addr, + jmp, + + // data.switch + @"switch", + + // data.branch + branch, + select, + + // data.un + jmp_val, + + // data.call + call, + + // data.alloc + alloc, + + // data.phi + phi, + + // data.bin + store, + bit_or, + bit_xor, + bit_and, + bit_shl, + bit_shr, + cmp_eq, + cmp_ne, + cmp_lt, + cmp_lte, + cmp_gt, + cmp_gte, + add, + sub, + mul, + div, + mod, + + // data.un + ret, + load, + bit_not, + negate, + trunc, + zext, + sext, + }; + + pub const Data = union { + constant: Interner.Ref, + none: void, + bin: struct { + lhs: Ref, + rhs: Ref, + }, + un: Ref, + arg: u32, + alloc: struct { + size: u32, + @"align": u32, + }, + @"switch": *Switch, + call: *Call, + label: [*:0]const u8, + branch: *Branch, + phi: Phi, + }; + + pub const Branch = struct { + cond: Ref, + then: Ref, + @"else": Ref, + }; + + pub const Switch = struct { + target: Ref, + cases_len: u32, + default: Ref, + case_vals: [*]Interner.Ref, + case_labels: [*]Ref, + }; + + pub const Call = struct { + func: Ref, + args_len: u32, + args_ptr: [*]Ref, + + pub fn args(c: Call) []Ref { + return c.args_ptr[0..c.args_len]; + } + }; + + pub const Phi = struct { + ptr: [*]Ir.Ref, + + pub const Input = struct { + label: Ir.Ref, + value: Ir.Ref, + }; + + pub fn inputs(p: Phi) []Input { + const len = @intFromEnum(p.ptr[0]) * 2; + const slice = (p.ptr + 1)[0..len]; + return std.mem.bytesAsSlice(Input, std.mem.sliceAsBytes(slice)); + } + }; +}; + +pub fn deinit(ir: *Ir, gpa: std.mem.Allocator) void { + ir.arena.promote(gpa).deinit(); + ir.instructions.deinit(gpa); + ir.* = undefined; +} + +const util = @import("util.zig"); +const TYPE = util.Color.purple; +const INST = util.Color.cyan; +const REF = util.Color.blue; +const LITERAL = util.Color.green; +const ATTRIBUTE = util.Color.yellow; + +const RefMap = std.AutoArrayHashMap(Ref, void); + +pub fn dump(ir: Ir, gpa: Allocator, name: []const u8, color: bool, w: anytype) !void { + const tags = ir.instructions.items(.tag); + const data = ir.instructions.items(.data); + + var ref_map = RefMap.init(gpa); + defer ref_map.deinit(); + + var label_map = RefMap.init(gpa); + defer label_map.deinit(); + + const ret_inst = ir.body.items[ir.body.items.len - 1]; + const ret_operand = data[@intFromEnum(ret_inst)].un; + const ret_ty = ir.instructions.items(.ty)[@intFromEnum(ret_operand)]; + try ir.writeType(ret_ty, color, w); + if (color) util.setColor(REF, w); + try w.print(" @{s}", .{name}); + if (color) util.setColor(.reset, w); + try w.writeAll("("); + + var arg_count: u32 = 0; + while (true) : (arg_count += 1) { + const ref = ir.body.items[arg_count]; + if (tags[@intFromEnum(ref)] != .arg) break; + if (arg_count != 0) try w.writeAll(", "); + try ref_map.put(ref, {}); + try ir.writeRef(&ref_map, ref, color, w); + if (color) util.setColor(.reset, w); + } + try w.writeAll(") {\n"); + for (ir.body.items[arg_count..]) |ref| { + switch (tags[@intFromEnum(ref)]) { + .label => try label_map.put(ref, {}), + else => {}, + } + } + + for (ir.body.items[arg_count..]) |ref| { + const i = @intFromEnum(ref); + const tag = tags[i]; + switch (tag) { + .arg, .constant, .symbol => unreachable, + .label => { + const label_index = label_map.getIndex(ref).?; + if (color) util.setColor(REF, w); + try w.print("{s}.{d}:\n", .{ data[i].label, label_index }); + }, + // .label_val => { + // const un = data[i].un; + // try w.print(" %{d} = label.{d}\n", .{ i, @intFromEnum(un) }); + // }, + .jmp => { + const un = data[i].un; + if (color) util.setColor(INST, w); + try w.writeAll(" jmp "); + try ir.writeLabel(&label_map, un, color, w); + try w.writeByte('\n'); + }, + .branch => { + const br = data[i].branch; + if (color) util.setColor(INST, w); + try w.writeAll(" branch "); + try ir.writeRef(&ref_map, br.cond, color, w); + if (color) util.setColor(.reset, w); + try w.writeAll(", "); + try ir.writeLabel(&label_map, br.then, color, w); + if (color) util.setColor(.reset, w); + try w.writeAll(", "); + try ir.writeLabel(&label_map, br.@"else", color, w); + try w.writeByte('\n'); + }, + .select => { + const br = data[i].branch; + try ir.writeNewRef(&ref_map, ref, color, w); + try w.writeAll("select "); + try ir.writeRef(&ref_map, br.cond, color, w); + if (color) util.setColor(.reset, w); + try w.writeAll(", "); + try ir.writeRef(&ref_map, br.then, color, w); + if (color) util.setColor(.reset, w); + try w.writeAll(", "); + try ir.writeRef(&ref_map, br.@"else", color, w); + try w.writeByte('\n'); + }, + // .jmp_val => { + // const bin = data[i].bin; + // try w.print(" %{s} %{d} label.{d}\n", .{ @tagName(tag), @intFromEnum(bin.lhs), @intFromEnum(bin.rhs) }); + // }, + .@"switch" => { + const @"switch" = data[i].@"switch"; + if (color) util.setColor(INST, w); + try w.writeAll(" switch "); + try ir.writeRef(&ref_map, @"switch".target, color, w); + if (color) util.setColor(.reset, w); + try w.writeAll(" {"); + for (@"switch".case_vals[0..@"switch".cases_len], @"switch".case_labels) |val_ref, label_ref| { + try w.writeAll("\n "); + try ir.writeValue(val_ref, color, w); + if (color) util.setColor(.reset, w); + try w.writeAll(" => "); + try ir.writeLabel(&label_map, label_ref, color, w); + if (color) util.setColor(.reset, w); + } + if (color) util.setColor(LITERAL, w); + try w.writeAll("\n default "); + if (color) util.setColor(.reset, w); + try w.writeAll("=> "); + try ir.writeLabel(&label_map, @"switch".default, color, w); + if (color) util.setColor(.reset, w); + try w.writeAll("\n }\n"); + }, + .call => { + const call = data[i].call; + try ir.writeNewRef(&ref_map, ref, color, w); + try w.writeAll("call "); + try ir.writeRef(&ref_map, call.func, color, w); + if (color) util.setColor(.reset, w); + try w.writeAll("("); + for (call.args(), 0..) |arg, arg_i| { + if (arg_i != 0) try w.writeAll(", "); + try ir.writeRef(&ref_map, arg, color, w); + if (color) util.setColor(.reset, w); + } + try w.writeAll(")\n"); + }, + .alloc => { + const alloc = data[i].alloc; + try ir.writeNewRef(&ref_map, ref, color, w); + try w.writeAll("alloc "); + if (color) util.setColor(ATTRIBUTE, w); + try w.writeAll("size "); + if (color) util.setColor(LITERAL, w); + try w.print("{d}", .{alloc.size}); + if (color) util.setColor(ATTRIBUTE, w); + try w.writeAll(" align "); + if (color) util.setColor(LITERAL, w); + try w.print("{d}", .{alloc.@"align"}); + try w.writeByte('\n'); + }, + .phi => { + try ir.writeNewRef(&ref_map, ref, color, w); + try w.writeAll("phi"); + if (color) util.setColor(.reset, w); + try w.writeAll(" {"); + for (data[i].phi.inputs()) |input| { + try w.writeAll("\n "); + try ir.writeLabel(&label_map, input.label, color, w); + if (color) util.setColor(.reset, w); + try w.writeAll(" => "); + try ir.writeRef(&ref_map, input.value, color, w); + if (color) util.setColor(.reset, w); + } + if (color) util.setColor(.reset, w); + try w.writeAll("\n }\n"); + }, + .store => { + const bin = data[i].bin; + if (color) util.setColor(INST, w); + try w.writeAll(" store "); + try ir.writeRef(&ref_map, bin.lhs, color, w); + if (color) util.setColor(.reset, w); + try w.writeAll(", "); + try ir.writeRef(&ref_map, bin.rhs, color, w); + try w.writeByte('\n'); + }, + .ret => { + if (color) util.setColor(INST, w); + try w.writeAll(" ret "); + if (data[i].un != .none) try ir.writeRef(&ref_map, data[i].un, color, w); + try w.writeByte('\n'); + }, + .load => { + try ir.writeNewRef(&ref_map, ref, color, w); + try w.writeAll("load "); + try ir.writeRef(&ref_map, data[i].un, color, w); + try w.writeByte('\n'); + }, + .bit_or, + .bit_xor, + .bit_and, + .bit_shl, + .bit_shr, + .cmp_eq, + .cmp_ne, + .cmp_lt, + .cmp_lte, + .cmp_gt, + .cmp_gte, + .add, + .sub, + .mul, + .div, + .mod, + => { + const bin = data[i].bin; + try ir.writeNewRef(&ref_map, ref, color, w); + try w.print("{s} ", .{@tagName(tag)}); + try ir.writeRef(&ref_map, bin.lhs, color, w); + if (color) util.setColor(.reset, w); + try w.writeAll(", "); + try ir.writeRef(&ref_map, bin.rhs, color, w); + try w.writeByte('\n'); + }, + .bit_not, + .negate, + .trunc, + .zext, + .sext, + => { + const un = data[i].un; + try ir.writeNewRef(&ref_map, ref, color, w); + try w.print("{s} ", .{@tagName(tag)}); + try ir.writeRef(&ref_map, un, color, w); + try w.writeByte('\n'); + }, + .label_addr, .jmp_val => {}, + } + } + if (color) util.setColor(.reset, w); + try w.writeAll("}\n\n"); +} + +fn writeType(ir: Ir, ty_ref: Interner.Ref, color: bool, w: anytype) !void { + const ty = ir.pool.get(ty_ref); + if (color) util.setColor(TYPE, w); + switch (ty) { + .value => unreachable, + .ptr, .noreturn, .void, .func => try w.writeAll(@tagName(ty)), + .int => |bits| try w.print("i{d}", .{bits}), + .float => |bits| try w.print("f{d}", .{bits}), + .array => |info| { + try w.print("[{d} * ", .{info.len}); + try ir.writeType(info.child, false, w); + try w.writeByte(']'); + }, + .vector => |info| { + try w.print("<{d} * ", .{info.len}); + try ir.writeType(info.child, false, w); + try w.writeByte('>'); + }, + .record => |info| { + // TODO collect into buffer and only print once + try w.writeAll("{ "); + for (info.elements, 0..) |elem, i| { + if (i != 0) try w.writeAll(", "); + try ir.writeType(elem, color, w); + } + try w.writeAll(" }"); + }, + } +} + +fn writeValue(ir: Ir, val_ref: Interner.Ref, color: bool, w: anytype) !void { + const v = ir.pool.get(val_ref).value; + if (color) util.setColor(LITERAL, w); + switch (v.tag) { + .unavailable => try w.writeAll(" unavailable"), + .int => try w.print("{d}", .{v.data.int}), + .bytes => try w.print("\"{s}\"", .{v.data.bytes.slice(ir.strings)}), + // std.fmt does @as instead of @floatCast + .float => try w.print("{d}", .{@as(f64, @floatCast(v.data.float))}), + else => try w.print("({s})", .{@tagName(v.tag)}), + } +} + +fn writeRef(ir: Ir, ref_map: *RefMap, ref: Ref, color: bool, w: anytype) !void { + assert(ref != .none); + const index = @intFromEnum(ref); + const ty_ref = ir.instructions.items(.ty)[index]; + if (ir.instructions.items(.tag)[index] == .constant) { + try ir.writeType(ty_ref, color, w); + const v_ref = ir.instructions.items(.data)[index].constant; + try w.writeByte(' '); + try ir.writeValue(v_ref, color, w); + return; + } else if (ir.instructions.items(.tag)[index] == .symbol) { + const name = ir.instructions.items(.data)[index].label; + try ir.writeType(ty_ref, color, w); + if (color) util.setColor(REF, w); + try w.print(" @{s}", .{name}); + return; + } + try ir.writeType(ty_ref, color, w); + if (color) util.setColor(REF, w); + const ref_index = ref_map.getIndex(ref).?; + try w.print(" %{d}", .{ref_index}); +} + +fn writeNewRef(ir: Ir, ref_map: *RefMap, ref: Ref, color: bool, w: anytype) !void { + try ref_map.put(ref, {}); + try w.writeAll(" "); + try ir.writeRef(ref_map, ref, color, w); + if (color) util.setColor(.reset, w); + try w.writeAll(" = "); + if (color) util.setColor(INST, w); +} + +fn writeLabel(ir: Ir, label_map: *RefMap, ref: Ref, color: bool, w: anytype) !void { + assert(ref != .none); + const index = @intFromEnum(ref); + const label = ir.instructions.items(.data)[index].label; + if (color) util.setColor(REF, w); + const label_index = label_map.getIndex(ref).?; + try w.print("{s}.{d}", .{ label, label_index }); +} diff --git a/deps/aro/LangOpts.zig b/deps/aro/LangOpts.zig new file mode 100644 index 000000000000..4cdfd3de0a90 --- /dev/null +++ b/deps/aro/LangOpts.zig @@ -0,0 +1,146 @@ +const std = @import("std"); +const DiagnosticTag = @import("Diagnostics.zig").Tag; + +const LangOpts = @This(); + +pub const Compiler = enum { + clang, + gcc, + msvc, +}; + +/// The floating-point evaluation method for intermediate results within a single expression +pub const FPEvalMethod = enum(i8) { + /// The evaluation method cannot be determined or is inconsistent for this target. + indeterminate = -1, + /// Use the type declared in the source + source = 0, + /// Use double as the floating-point evaluation method for all float expressions narrower than double. + double = 1, + /// Use long double as the floating-point evaluation method for all float expressions narrower than long double. + extended = 2, +}; + +pub const Standard = enum { + /// ISO C 1990 + c89, + /// ISO C 1990 with amendment 1 + iso9899, + /// ISO C 1990 with GNU extensions + gnu89, + /// ISO C 1999 + c99, + /// ISO C 1999 with GNU extensions + gnu99, + /// ISO C 2011 + c11, + /// ISO C 2011 with GNU extensions + gnu11, + /// ISO C 2017 + c17, + /// Default value if nothing specified; adds the GNU keywords to + /// C17 but does not suppress warnings about using GNU extensions + default, + /// ISO C 2017 with GNU extensions + gnu17, + /// Working Draft for ISO C2x + c2x, + /// Working Draft for ISO C2x with GNU extensions + gnu2x, + + const NameMap = std.ComptimeStringMap(Standard, .{ + .{ "c89", .c89 }, .{ "c90", .c89 }, .{ "iso9899:1990", .c89 }, + .{ "iso9899:199409", .iso9899 }, .{ "gnu89", .gnu89 }, .{ "gnu90", .gnu89 }, + .{ "c99", .c99 }, .{ "iso9899:1999", .c99 }, .{ "gnu99", .gnu99 }, + .{ "c11", .c11 }, .{ "iso9899:2011", .c11 }, .{ "gnu11", .gnu11 }, + .{ "c17", .c17 }, .{ "iso9899:2017", .c17 }, .{ "c18", .c17 }, + .{ "iso9899:2018", .c17 }, .{ "gnu17", .gnu17 }, .{ "gnu18", .gnu17 }, + .{ "c2x", .c2x }, .{ "gnu2x", .gnu2x }, + }); + + pub fn atLeast(self: Standard, other: Standard) bool { + return @intFromEnum(self) >= @intFromEnum(other); + } + + pub fn isGNU(standard: Standard) bool { + return switch (standard) { + .gnu89, .gnu99, .gnu11, .default, .gnu17, .gnu2x => true, + else => false, + }; + } + + pub fn isExplicitGNU(standard: Standard) bool { + return standard.isGNU() and standard != .default; + } + + /// Value reported by __STDC_VERSION__ macro + pub fn StdCVersionMacro(standard: Standard) ?[]const u8 { + return switch (standard) { + .c89, .gnu89 => null, + .iso9899 => "199409L", + .c99, .gnu99 => "199901L", + .c11, .gnu11 => "201112L", + .default, .c17, .gnu17 => "201710L", + // todo: subject to change, verify once c23 finalized + .c2x, .gnu2x => "202311L", + }; + } +}; + +emulate: Compiler = .clang, +standard: Standard = .default, +/// -fshort-enums option, makes enums only take up as much space as they need to hold all the values. +short_enums: bool = false, +dollars_in_identifiers: bool = true, +declspec_attrs: bool = false, +ms_extensions: bool = false, +/// true or false if digraph support explicitly enabled/disabled with -fdigraphs/-fno-digraphs +digraphs: ?bool = null, +/// If set, use the native half type instead of promoting to float +use_native_half_type: bool = false, +/// If set, function arguments and return values may be of type __fp16 even if there is no standard ABI for it +allow_half_args_and_returns: bool = false, +/// null indicates that the user did not select a value, use target to determine default +fp_eval_method: ?FPEvalMethod = null, +/// If set, use specified signedness for `char` instead of the target's default char signedness +char_signedness_override: ?std.builtin.Signedness = null, +/// If set, override the default availability of char8_t (by default, enabled in C2X and later; disabled otherwise) +has_char8_t_override: ?bool = null, + +/// Whether to allow GNU-style inline assembly +gnu_asm: bool = true, + +pub fn setStandard(self: *LangOpts, name: []const u8) error{InvalidStandard}!void { + self.standard = Standard.NameMap.get(name) orelse return error.InvalidStandard; +} + +pub fn enableMSExtensions(self: *LangOpts) void { + self.declspec_attrs = true; + self.ms_extensions = true; +} + +pub fn disableMSExtensions(self: *LangOpts) void { + self.declspec_attrs = false; + self.ms_extensions = true; +} + +pub fn hasChar8_T(self: *const LangOpts) bool { + return self.has_char8_t_override orelse self.standard.atLeast(.c2x); +} + +pub fn hasDigraphs(self: *const LangOpts) bool { + return self.digraphs orelse self.standard.atLeast(.gnu89); +} + +pub fn setEmulatedCompiler(self: *LangOpts, compiler: Compiler) void { + self.emulate = compiler; + if (compiler == .msvc) self.enableMSExtensions(); +} + +pub fn setFpEvalMethod(self: *LangOpts, fp_eval_method: FPEvalMethod) void { + self.fp_eval_method = fp_eval_method; +} + +pub fn setCharSignedness(self: *LangOpts, signedness: std.builtin.Signedness) void { + self.char_signedness_override = signedness; +} diff --git a/deps/aro/Object.zig b/deps/aro/Object.zig new file mode 100644 index 000000000000..d739c1676482 --- /dev/null +++ b/deps/aro/Object.zig @@ -0,0 +1,73 @@ +const std = @import("std"); +const Compilation = @import("Compilation.zig"); +const Elf = @import("object/Elf.zig"); + +const Object = @This(); + +format: std.Target.ObjectFormat, +comp: *Compilation, + +pub fn create(comp: *Compilation) !*Object { + switch (comp.target.ofmt) { + .elf => return Elf.create(comp), + else => unreachable, + } +} + +pub fn deinit(obj: *Object) void { + switch (obj.format) { + .elf => @fieldParentPtr(Elf, "obj", obj).deinit(), + else => unreachable, + } +} + +pub const Section = union(enum) { + undefined, + data, + read_only_data, + func, + strings, + custom: []const u8, +}; + +pub fn getSection(obj: *Object, section: Section) !*std.ArrayList(u8) { + switch (obj.format) { + .elf => return @fieldParentPtr(Elf, "obj", obj).getSection(section), + else => unreachable, + } +} + +pub const SymbolType = enum { + func, + variable, + external, +}; + +pub fn declareSymbol( + obj: *Object, + section: Section, + name: ?[]const u8, + linkage: std.builtin.GlobalLinkage, + @"type": SymbolType, + offset: u64, + size: u64, +) ![]const u8 { + switch (obj.format) { + .elf => return @fieldParentPtr(Elf, "obj", obj).declareSymbol(section, name, linkage, @"type", offset, size), + else => unreachable, + } +} + +pub fn addRelocation(obj: *Object, name: []const u8, section: Section, address: u64, addend: i64) !void { + switch (obj.format) { + .elf => return @fieldParentPtr(Elf, "obj", obj).addRelocation(name, section, address, addend), + else => unreachable, + } +} + +pub fn finish(obj: *Object, file: std.fs.File) !void { + switch (obj.format) { + .elf => return @fieldParentPtr(Elf, "obj", obj).finish(file), + else => unreachable, + } +} diff --git a/deps/aro/Parser.zig b/deps/aro/Parser.zig new file mode 100644 index 000000000000..461aef57aa6d --- /dev/null +++ b/deps/aro/Parser.zig @@ -0,0 +1,8200 @@ +const std = @import("std"); +const mem = std.mem; +const Allocator = mem.Allocator; +const assert = std.debug.assert; +const big = std.math.big; +const Compilation = @import("Compilation.zig"); +const Source = @import("Source.zig"); +const Tokenizer = @import("Tokenizer.zig"); +const Preprocessor = @import("Preprocessor.zig"); +const Tree = @import("Tree.zig"); +const Token = Tree.Token; +const TokenIndex = Tree.TokenIndex; +const NodeIndex = Tree.NodeIndex; +const Type = @import("Type.zig"); +const Diagnostics = @import("Diagnostics.zig"); +const NodeList = std.ArrayList(NodeIndex); +const InitList = @import("InitList.zig"); +const Attribute = @import("Attribute.zig"); +const CharInfo = @import("CharInfo.zig"); +const Value = @import("Value.zig"); +const SymbolStack = @import("SymbolStack.zig"); +const Symbol = SymbolStack.Symbol; +const record_layout = @import("record_layout.zig"); +const StringId = @import("StringInterner.zig").StringId; +const number_affixes = @import("number_affixes.zig"); +const NumberPrefix = number_affixes.Prefix; +const NumberSuffix = number_affixes.Suffix; +const BuiltinFunction = @import("builtins/BuiltinFunction.zig"); +const target_util = @import("target.zig"); + +const Parser = @This(); + +const Switch = struct { + default: ?TokenIndex = null, + ranges: std.ArrayList(Range), + ty: Type, + + const Range = struct { + first: Value, + last: Value, + tok: TokenIndex, + }; + + fn add( + self: *Switch, + comp: *Compilation, + first: Value, + last: Value, + tok: TokenIndex, + ) !?Range { + for (self.ranges.items) |range| { + if (last.compare(.gte, range.first, self.ty, comp) and first.compare(.lte, range.last, self.ty, comp)) { + return range; // They overlap. + } + } + try self.ranges.append(.{ + .first = first, + .last = last, + .tok = tok, + }); + return null; + } +}; + +const Label = union(enum) { + unresolved_goto: TokenIndex, + label: TokenIndex, +}; + +pub const Error = Compilation.Error || error{ParsingFailed}; + +/// An attribute that has been parsed but not yet validated in its context +const TentativeAttribute = struct { + attr: Attribute, + tok: TokenIndex, +}; + +/// How the parser handles const int decl references when it is expecting an integer +/// constant expression. +const ConstDeclFoldingMode = enum { + /// fold const decls as if they were literals + fold_const_decls, + /// fold const decls as if they were literals and issue GNU extension diagnostic + gnu_folding_extension, + /// fold const decls as if they were literals and issue VLA diagnostic + gnu_vla_folding_extension, + /// folding const decls is prohibited; return an unavailable value + no_const_decl_folding, +}; + +// values from preprocessor +pp: *Preprocessor, +comp: *Compilation, +gpa: mem.Allocator, +tok_ids: []const Token.Id, +tok_i: TokenIndex = 0, + +// values of the incomplete Tree +arena: Allocator, +nodes: Tree.Node.List = .{}, +data: NodeList, +retained_strings: std.ArrayList(u8), +value_map: Tree.ValueMap, + +// buffers used during compilation +syms: SymbolStack = .{}, +strings: std.ArrayList(u8), +labels: std.ArrayList(Label), +list_buf: NodeList, +decl_buf: NodeList, +param_buf: std.ArrayList(Type.Func.Param), +enum_buf: std.ArrayList(Type.Enum.Field), +record_buf: std.ArrayList(Type.Record.Field), +attr_buf: std.MultiArrayList(TentativeAttribute) = .{}, +attr_application_buf: std.ArrayListUnmanaged(Attribute) = .{}, +field_attr_buf: std.ArrayList([]const Attribute), +/// type name -> variable name location for tentative definitions (top-level defs with thus-far-incomplete types) +/// e.g. `struct Foo bar;` where `struct Foo` is not defined yet. +/// The key is the StringId of `Foo` and the value is the TokenIndex of `bar` +/// Items are removed if the type is subsequently completed with a definition. +/// We only store the first tentative definition that uses a given type because this map is only used +/// for issuing an error message, and correcting the first error for a type will fix all of them for that type. +tentative_defs: std.AutoHashMapUnmanaged(StringId, TokenIndex) = .{}, + +// configuration and miscellaneous info +no_eval: bool = false, +in_macro: bool = false, +extension_suppressed: bool = false, +contains_address_of_label: bool = false, +label_count: u32 = 0, +const_decl_folding: ConstDeclFoldingMode = .fold_const_decls, +/// location of first computed goto in function currently being parsed +/// if a computed goto is used, the function must contain an +/// address-of-label expression (tracked with contains_address_of_label) +computed_goto_tok: ?TokenIndex = null, + +/// Various variables that are different for each function. +func: struct { + /// null if not in function, will always be plain func, var_args_func or old_style_func + ty: ?Type = null, + name: TokenIndex = 0, + ident: ?Result = null, + pretty_ident: ?Result = null, +} = .{}, +/// Various variables that are different for each record. +record: struct { + // invalid means we're not parsing a record + kind: Token.Id = .invalid, + flexible_field: ?TokenIndex = null, + start: usize = 0, + field_attr_start: usize = 0, + + fn addField(r: @This(), p: *Parser, name: StringId, tok: TokenIndex) Error!void { + var i = p.record_members.items.len; + while (i > r.start) { + i -= 1; + if (p.record_members.items[i].name == name) { + try p.errStr(.duplicate_member, tok, p.tokSlice(tok)); + try p.errTok(.previous_definition, p.record_members.items[i].tok); + break; + } + } + try p.record_members.append(p.gpa, .{ .name = name, .tok = tok }); + } + + fn addFieldsFromAnonymous(r: @This(), p: *Parser, ty: Type) Error!void { + for (ty.data.record.fields) |f| { + if (f.isAnonymousRecord()) { + try r.addFieldsFromAnonymous(p, f.ty.canonicalize(.standard)); + } else if (f.name_tok != 0) { + try r.addField(p, f.name, f.name_tok); + } + } + } +} = .{}, +record_members: std.ArrayListUnmanaged(struct { tok: TokenIndex, name: StringId }) = .{}, +@"switch": ?*Switch = null, +in_loop: bool = false, +pragma_pack: ?u8 = null, +string_ids: struct { + declspec_id: StringId, + main_id: StringId, + file: StringId, + jmp_buf: StringId, + sigjmp_buf: StringId, + ucontext_t: StringId, +}, + +fn checkIdentifierCodepoint(comp: *Compilation, codepoint: u21, loc: Source.Location) Compilation.Error!bool { + if (codepoint <= 0x7F) return false; + var diagnosed = false; + if (!CharInfo.isC99IdChar(codepoint)) { + try comp.diag.add(.{ + .tag = .c99_compat, + .loc = loc, + }, &.{}); + diagnosed = true; + } + if (CharInfo.isInvisible(codepoint)) { + try comp.diag.add(.{ + .tag = .unicode_zero_width, + .loc = loc, + .extra = .{ .actual_codepoint = codepoint }, + }, &.{}); + diagnosed = true; + } + if (CharInfo.homoglyph(codepoint)) |resembles| { + try comp.diag.add(.{ + .tag = .unicode_homoglyph, + .loc = loc, + .extra = .{ .codepoints = .{ .actual = codepoint, .resembles = resembles } }, + }, &.{}); + diagnosed = true; + } + return diagnosed; +} + +fn eatIdentifier(p: *Parser) !?TokenIndex { + switch (p.tok_ids[p.tok_i]) { + .identifier => {}, + .extended_identifier => { + const slice = p.tokSlice(p.tok_i); + var it = std.unicode.Utf8View.initUnchecked(slice).iterator(); + var loc = p.pp.tokens.items(.loc)[p.tok_i]; + + if (mem.indexOfScalar(u8, slice, '$')) |i| { + loc.byte_offset += @intCast(i); + try p.comp.diag.add(.{ + .tag = .dollar_in_identifier_extension, + .loc = loc, + }, &.{}); + loc = p.pp.tokens.items(.loc)[p.tok_i]; + } + + while (it.nextCodepoint()) |c| { + if (try checkIdentifierCodepoint(p.comp, c, loc)) break; + loc.byte_offset += std.unicode.utf8CodepointSequenceLength(c) catch unreachable; + } + }, + else => return null, + } + p.tok_i += 1; + + // Handle illegal '$' characters in identifiers + if (!p.comp.langopts.dollars_in_identifiers) { + if (p.tok_ids[p.tok_i] == .invalid and p.tokSlice(p.tok_i)[0] == '$') { + try p.err(.dollars_in_identifiers); + p.tok_i += 1; + return error.ParsingFailed; + } + } + + return p.tok_i - 1; +} + +fn expectIdentifier(p: *Parser) Error!TokenIndex { + const actual = p.tok_ids[p.tok_i]; + if (actual != .identifier and actual != .extended_identifier) { + return p.errExpectedToken(.identifier, actual); + } + + return (try p.eatIdentifier()) orelse unreachable; +} + +fn eatToken(p: *Parser, id: Token.Id) ?TokenIndex { + assert(id != .identifier and id != .extended_identifier); // use eatIdentifier + if (p.tok_ids[p.tok_i] == id) { + defer p.tok_i += 1; + return p.tok_i; + } else return null; +} + +fn expectToken(p: *Parser, expected: Token.Id) Error!TokenIndex { + assert(expected != .identifier and expected != .extended_identifier); // use expectIdentifier + const actual = p.tok_ids[p.tok_i]; + if (actual != expected) return p.errExpectedToken(expected, actual); + defer p.tok_i += 1; + return p.tok_i; +} + +pub fn tokSlice(p: *Parser, tok: TokenIndex) []const u8 { + if (p.tok_ids[tok].lexeme()) |some| return some; + const loc = p.pp.tokens.items(.loc)[tok]; + var tmp_tokenizer = Tokenizer{ + .buf = p.comp.getSource(loc.id).buf, + .comp = p.comp, + .index = loc.byte_offset, + .source = .generated, + }; + const res = tmp_tokenizer.next(); + return tmp_tokenizer.buf[res.start..res.end]; +} + +fn expectClosing(p: *Parser, opening: TokenIndex, id: Token.Id) Error!void { + _ = p.expectToken(id) catch |e| { + if (e == error.ParsingFailed) { + try p.errTok(switch (id) { + .r_paren => .to_match_paren, + .r_brace => .to_match_brace, + .r_bracket => .to_match_brace, + else => unreachable, + }, opening); + } + return e; + }; +} + +fn errOverflow(p: *Parser, op_tok: TokenIndex, res: Result) !void { + if (res.ty.isUnsignedInt(p.comp)) { + try p.errExtra(.overflow_unsigned, op_tok, .{ .unsigned = res.val.data.int }); + } else { + try p.errExtra(.overflow_signed, op_tok, .{ .signed = res.val.signExtend(res.ty, p.comp) }); + } +} + +fn errExpectedToken(p: *Parser, expected: Token.Id, actual: Token.Id) Error { + switch (actual) { + .invalid => try p.errExtra(.expected_invalid, p.tok_i, .{ .tok_id_expected = expected }), + .eof => try p.errExtra(.expected_eof, p.tok_i, .{ .tok_id_expected = expected }), + else => try p.errExtra(.expected_token, p.tok_i, .{ .tok_id = .{ + .expected = expected, + .actual = actual, + } }), + } + return error.ParsingFailed; +} + +pub fn errStr(p: *Parser, tag: Diagnostics.Tag, tok_i: TokenIndex, str: []const u8) Compilation.Error!void { + @setCold(true); + return p.errExtra(tag, tok_i, .{ .str = str }); +} + +pub fn errExtra(p: *Parser, tag: Diagnostics.Tag, tok_i: TokenIndex, extra: Diagnostics.Message.Extra) Compilation.Error!void { + @setCold(true); + const tok = p.pp.tokens.get(tok_i); + var loc = tok.loc; + if (tok_i != 0 and tok.id == .eof) { + // if the token is EOF, point at the end of the previous token instead + const prev = p.pp.tokens.get(tok_i - 1); + loc = prev.loc; + loc.byte_offset += @intCast(p.tokSlice(tok_i - 1).len); + } + try p.comp.diag.add(.{ + .tag = tag, + .loc = loc, + .extra = extra, + }, tok.expansionSlice()); +} + +pub fn errTok(p: *Parser, tag: Diagnostics.Tag, tok_i: TokenIndex) Compilation.Error!void { + @setCold(true); + return p.errExtra(tag, tok_i, .{ .none = {} }); +} + +pub fn err(p: *Parser, tag: Diagnostics.Tag) Compilation.Error!void { + @setCold(true); + return p.errExtra(tag, p.tok_i, .{ .none = {} }); +} + +pub fn todo(p: *Parser, msg: []const u8) Error { + try p.errStr(.todo, p.tok_i, msg); + return error.ParsingFailed; +} + +pub fn typeStr(p: *Parser, ty: Type) ![]const u8 { + if (Type.Builder.fromType(ty).str(p.comp.langopts)) |str| return str; + const strings_top = p.strings.items.len; + defer p.strings.items.len = strings_top; + + const mapper = p.comp.string_interner.getSlowTypeMapper(); + try ty.print(mapper, p.comp.langopts, p.strings.writer()); + return try p.comp.diag.arena.allocator().dupe(u8, p.strings.items[strings_top..]); +} + +pub fn typePairStr(p: *Parser, a: Type, b: Type) ![]const u8 { + return p.typePairStrExtra(a, " and ", b); +} + +pub fn typePairStrExtra(p: *Parser, a: Type, msg: []const u8, b: Type) ![]const u8 { + const strings_top = p.strings.items.len; + defer p.strings.items.len = strings_top; + + try p.strings.append('\''); + const mapper = p.comp.string_interner.getSlowTypeMapper(); + try a.print(mapper, p.comp.langopts, p.strings.writer()); + try p.strings.append('\''); + try p.strings.appendSlice(msg); + try p.strings.append('\''); + try b.print(mapper, p.comp.langopts, p.strings.writer()); + try p.strings.append('\''); + return try p.comp.diag.arena.allocator().dupe(u8, p.strings.items[strings_top..]); +} + +pub fn floatValueChangedStr(p: *Parser, res: *Result, old_value: f64, int_ty: Type) ![]const u8 { + const strings_top = p.strings.items.len; + defer p.strings.items.len = strings_top; + + var w = p.strings.writer(); + const type_pair_str = try p.typePairStrExtra(res.ty, " to ", int_ty); + try w.writeAll(type_pair_str); + const is_zero = res.val.isZero(); + const non_zero_str: []const u8 = if (is_zero) "non-zero " else ""; + if (int_ty.is(.bool)) { + try w.print(" changes {s}value from {d} to {}", .{ non_zero_str, old_value, res.val.getBool() }); + } else if (int_ty.isUnsignedInt(p.comp)) { + try w.print(" changes {s}value from {d} to {d}", .{ non_zero_str, old_value, res.val.getInt(u64) }); + } else { + try w.print(" changes {s}value from {d} to {d}", .{ non_zero_str, old_value, res.val.getInt(i64) }); + } + + return try p.comp.diag.arena.allocator().dupe(u8, p.strings.items[strings_top..]); +} + +fn checkDeprecatedUnavailable(p: *Parser, ty: Type, usage_tok: TokenIndex, decl_tok: TokenIndex) !void { + if (ty.getAttribute(.@"error")) |@"error"| { + const strings_top = p.strings.items.len; + defer p.strings.items.len = strings_top; + + const w = p.strings.writer(); + const msg_str = p.retainedString(@"error".msg); + try w.print("call to '{s}' declared with attribute error: {s}", .{ p.tokSlice(@"error".__name_tok), msg_str }); + const str = try p.comp.diag.arena.allocator().dupe(u8, p.strings.items[strings_top..]); + try p.errStr(.error_attribute, usage_tok, str); + } + if (ty.getAttribute(.warning)) |warning| { + const strings_top = p.strings.items.len; + defer p.strings.items.len = strings_top; + + const w = p.strings.writer(); + const msg_str = p.retainedString(warning.msg); + try w.print("call to '{s}' declared with attribute warning: {s}", .{ p.tokSlice(warning.__name_tok), msg_str }); + const str = try p.comp.diag.arena.allocator().dupe(u8, p.strings.items[strings_top..]); + try p.errStr(.warning_attribute, usage_tok, str); + } + if (ty.getAttribute(.unavailable)) |unavailable| { + try p.errDeprecated(.unavailable, usage_tok, unavailable.msg); + try p.errStr(.unavailable_note, unavailable.__name_tok, p.tokSlice(decl_tok)); + return error.ParsingFailed; + } else if (ty.getAttribute(.deprecated)) |deprecated| { + try p.errDeprecated(.deprecated_declarations, usage_tok, deprecated.msg); + try p.errStr(.deprecated_note, deprecated.__name_tok, p.tokSlice(decl_tok)); + } +} + +/// Returned slice is invalidated if additional strings are added to p.retained_strings +fn retainedString(p: *Parser, range: Value.ByteRange) []const u8 { + return range.slice(p.retained_strings.items); +} + +fn errDeprecated(p: *Parser, tag: Diagnostics.Tag, tok_i: TokenIndex, msg: ?Value.ByteRange) Compilation.Error!void { + const strings_top = p.strings.items.len; + defer p.strings.items.len = strings_top; + + const w = p.strings.writer(); + try w.print("'{s}' is ", .{p.tokSlice(tok_i)}); + const reason: []const u8 = switch (tag) { + .unavailable => "unavailable", + .deprecated_declarations => "deprecated", + else => unreachable, + }; + try w.writeAll(reason); + if (msg) |m| { + const str = p.retainedString(m); + try w.print(": {s}", .{str}); + } + const str = try p.comp.diag.arena.allocator().dupe(u8, p.strings.items[strings_top..]); + return p.errStr(tag, tok_i, str); +} + +fn addNode(p: *Parser, node: Tree.Node) Allocator.Error!NodeIndex { + if (p.in_macro) return .none; + const res = p.nodes.len; + try p.nodes.append(p.gpa, node); + return @enumFromInt(res); +} + +fn addList(p: *Parser, nodes: []const NodeIndex) Allocator.Error!Tree.Node.Range { + if (p.in_macro) return Tree.Node.Range{ .start = 0, .end = 0 }; + const start: u32 = @intCast(p.data.items.len); + try p.data.appendSlice(nodes); + const end: u32 = @intCast(p.data.items.len); + return Tree.Node.Range{ .start = start, .end = end }; +} + +fn findLabel(p: *Parser, name: []const u8) ?TokenIndex { + for (p.labels.items) |item| { + switch (item) { + .label => |l| if (mem.eql(u8, p.tokSlice(l), name)) return l, + .unresolved_goto => {}, + } + } + return null; +} + +fn nodeIs(p: *Parser, node: NodeIndex, tag: Tree.Tag) bool { + return p.getNode(node, tag) != null; +} + +fn getNode(p: *Parser, node: NodeIndex, tag: Tree.Tag) ?NodeIndex { + var cur = node; + const tags = p.nodes.items(.tag); + const data = p.nodes.items(.data); + while (true) { + const cur_tag = tags[@intFromEnum(cur)]; + if (cur_tag == .paren_expr) { + cur = data[@intFromEnum(cur)].un; + } else if (cur_tag == tag) { + return cur; + } else { + return null; + } + } +} + +fn pragma(p: *Parser) Compilation.Error!bool { + var found_pragma = false; + while (p.eatToken(.keyword_pragma)) |_| { + found_pragma = true; + + const name_tok = p.tok_i; + const name = p.tokSlice(name_tok); + + const end_idx = mem.indexOfScalarPos(Token.Id, p.tok_ids, p.tok_i, .nl).?; + const pragma_len = @as(TokenIndex, @intCast(end_idx)) - p.tok_i; + defer p.tok_i += pragma_len + 1; // skip past .nl as well + if (p.comp.getPragma(name)) |prag| { + try prag.parserCB(p, p.tok_i); + } + } + return found_pragma; +} + +/// Issue errors for top-level definitions whose type was never completed. +fn diagnoseIncompleteDefinitions(p: *Parser) !void { + @setCold(true); + + const node_slices = p.nodes.slice(); + const tags = node_slices.items(.tag); + const tys = node_slices.items(.ty); + const data = node_slices.items(.data); + + const err_start = p.comp.diag.list.items.len; + for (p.decl_buf.items) |decl_node| { + const idx = @intFromEnum(decl_node); + switch (tags[idx]) { + .struct_forward_decl, .union_forward_decl, .enum_forward_decl => {}, + else => continue, + } + + const ty = tys[idx]; + const decl_type_name = if (ty.getRecord()) |rec| + rec.name + else if (ty.get(.@"enum")) |en| + en.data.@"enum".name + else + unreachable; + + const tentative_def_tok = p.tentative_defs.get(decl_type_name) orelse continue; + const type_str = try p.typeStr(ty); + try p.errStr(.tentative_definition_incomplete, tentative_def_tok, type_str); + try p.errStr(.forward_declaration_here, data[idx].decl_ref, type_str); + } + const errors_added = p.comp.diag.list.items.len - err_start; + assert(errors_added == 2 * p.tentative_defs.count()); // Each tentative def should add an error + note +} + +/// root : (decl | assembly ';' | staticAssert)* +pub fn parse(pp: *Preprocessor) Compilation.Error!Tree { + pp.comp.pragmaEvent(.before_parse); + + var arena = std.heap.ArenaAllocator.init(pp.comp.gpa); + errdefer arena.deinit(); + var p = Parser{ + .pp = pp, + .comp = pp.comp, + .gpa = pp.comp.gpa, + .arena = arena.allocator(), + .tok_ids = pp.tokens.items(.id), + .strings = std.ArrayList(u8).init(pp.comp.gpa), + .retained_strings = std.ArrayList(u8).init(pp.comp.gpa), + .value_map = Tree.ValueMap.init(pp.comp.gpa), + .data = NodeList.init(pp.comp.gpa), + .labels = std.ArrayList(Label).init(pp.comp.gpa), + .list_buf = NodeList.init(pp.comp.gpa), + .decl_buf = NodeList.init(pp.comp.gpa), + .param_buf = std.ArrayList(Type.Func.Param).init(pp.comp.gpa), + .enum_buf = std.ArrayList(Type.Enum.Field).init(pp.comp.gpa), + .record_buf = std.ArrayList(Type.Record.Field).init(pp.comp.gpa), + .field_attr_buf = std.ArrayList([]const Attribute).init(pp.comp.gpa), + .string_ids = .{ + .declspec_id = try pp.comp.intern("__declspec"), + .main_id = try pp.comp.intern("main"), + .file = try pp.comp.intern("FILE"), + .jmp_buf = try pp.comp.intern("jmp_buf"), + .sigjmp_buf = try pp.comp.intern("sigjmp_buf"), + .ucontext_t = try pp.comp.intern("ucontext_t"), + }, + }; + errdefer { + p.nodes.deinit(pp.comp.gpa); + p.retained_strings.deinit(); + p.value_map.deinit(); + } + defer { + p.data.deinit(); + p.labels.deinit(); + p.strings.deinit(); + p.syms.deinit(pp.comp.gpa); + p.list_buf.deinit(); + p.decl_buf.deinit(); + p.param_buf.deinit(); + p.enum_buf.deinit(); + p.record_buf.deinit(); + p.record_members.deinit(pp.comp.gpa); + p.attr_buf.deinit(pp.comp.gpa); + p.attr_application_buf.deinit(pp.comp.gpa); + p.tentative_defs.deinit(pp.comp.gpa); + assert(p.field_attr_buf.items.len == 0); + p.field_attr_buf.deinit(); + } + + // NodeIndex 0 must be invalid + _ = try p.addNode(.{ .tag = .invalid, .ty = undefined, .data = undefined }); + + { + if (p.comp.langopts.hasChar8_T()) { + try p.syms.defineTypedef(&p, try p.comp.intern("char8_t"), .{ .specifier = .uchar }, 0, .none); + } + try p.syms.defineTypedef(&p, try p.comp.intern("__int128_t"), .{ .specifier = .int128 }, 0, .none); + try p.syms.defineTypedef(&p, try p.comp.intern("__uint128_t"), .{ .specifier = .uint128 }, 0, .none); + + const elem_ty = try p.arena.create(Type); + elem_ty.* = .{ .specifier = .char }; + try p.syms.defineTypedef(&p, try p.comp.intern("__builtin_ms_va_list"), .{ + .specifier = .pointer, + .data = .{ .sub_type = elem_ty }, + }, 0, .none); + + const ty = &pp.comp.types.va_list; + try p.syms.defineTypedef(&p, try p.comp.intern("__builtin_va_list"), ty.*, 0, .none); + + if (ty.isArray()) ty.decayArray(); + + try p.syms.defineTypedef(&p, try p.comp.intern("__NSConstantString"), pp.comp.types.ns_constant_string.ty, 0, .none); + } + + while (p.eatToken(.eof) == null) { + if (try p.pragma()) continue; + if (try p.parseOrNextDecl(staticAssert)) continue; + if (try p.parseOrNextDecl(decl)) continue; + if (p.eatToken(.keyword_extension)) |_| { + const saved_extension = p.extension_suppressed; + defer p.extension_suppressed = saved_extension; + p.extension_suppressed = true; + + if (try p.parseOrNextDecl(decl)) continue; + switch (p.tok_ids[p.tok_i]) { + .semicolon => p.tok_i += 1, + .keyword_static_assert, + .keyword_c23_static_assert, + .keyword_pragma, + .keyword_extension, + .keyword_asm, + .keyword_asm1, + .keyword_asm2, + => {}, + else => try p.err(.expected_external_decl), + } + continue; + } + if (p.assembly(.global) catch |er| switch (er) { + error.ParsingFailed => { + p.nextExternDecl(); + continue; + }, + else => |e| return e, + }) |node| { + try p.decl_buf.append(node); + continue; + } + if (p.eatToken(.semicolon)) |tok| { + try p.errTok(.extra_semi, tok); + continue; + } + try p.err(.expected_external_decl); + p.tok_i += 1; + } + if (p.tentative_defs.count() > 0) { + try p.diagnoseIncompleteDefinitions(); + } + + const root_decls = try p.decl_buf.toOwnedSlice(); + errdefer pp.comp.gpa.free(root_decls); + if (root_decls.len == 0) { + try p.errTok(.empty_translation_unit, p.tok_i - 1); + } + pp.comp.pragmaEvent(.after_parse); + + const data = try p.data.toOwnedSlice(); + errdefer pp.comp.gpa.free(data); + const strings = try p.retained_strings.toOwnedSlice(); + errdefer pp.comp.gpa.free(strings); + return Tree{ + .comp = pp.comp, + .tokens = pp.tokens.slice(), + .arena = arena, + .generated = pp.comp.generated_buf.items, + .nodes = p.nodes.toOwnedSlice(), + .data = data, + .root_decls = root_decls, + .strings = strings, + .value_map = p.value_map, + }; +} + +fn skipToPragmaSentinel(p: *Parser) void { + while (true) : (p.tok_i += 1) { + if (p.tok_ids[p.tok_i] == .nl) return; + if (p.tok_ids[p.tok_i] == .eof) { + p.tok_i -= 1; + return; + } + } +} + +fn parseOrNextDecl(p: *Parser, comptime func: fn (*Parser) Error!bool) Compilation.Error!bool { + return func(p) catch |er| switch (er) { + error.ParsingFailed => { + p.nextExternDecl(); + return true; + }, + else => |e| return e, + }; +} + +fn nextExternDecl(p: *Parser) void { + var parens: u32 = 0; + while (true) : (p.tok_i += 1) { + switch (p.tok_ids[p.tok_i]) { + .l_paren, .l_brace, .l_bracket => parens += 1, + .r_paren, .r_brace, .r_bracket => if (parens != 0) { + parens -= 1; + }, + .keyword_typedef, + .keyword_extern, + .keyword_static, + .keyword_auto, + .keyword_register, + .keyword_thread_local, + .keyword_c23_thread_local, + .keyword_inline, + .keyword_inline1, + .keyword_inline2, + .keyword_noreturn, + .keyword_void, + .keyword_bool, + .keyword_c23_bool, + .keyword_char, + .keyword_short, + .keyword_int, + .keyword_long, + .keyword_signed, + .keyword_unsigned, + .keyword_float, + .keyword_double, + .keyword_complex, + .keyword_atomic, + .keyword_enum, + .keyword_struct, + .keyword_union, + .keyword_alignas, + .keyword_c23_alignas, + .identifier, + .extended_identifier, + .keyword_typeof, + .keyword_typeof1, + .keyword_typeof2, + .keyword_extension, + .keyword_bit_int, + => if (parens == 0) return, + .keyword_pragma => p.skipToPragmaSentinel(), + .eof => return, + .semicolon => if (parens == 0) { + p.tok_i += 1; + return; + }, + else => {}, + } + } +} + +fn skipTo(p: *Parser, id: Token.Id) void { + var parens: u32 = 0; + while (true) : (p.tok_i += 1) { + if (p.tok_ids[p.tok_i] == id and parens == 0) { + p.tok_i += 1; + return; + } + switch (p.tok_ids[p.tok_i]) { + .l_paren, .l_brace, .l_bracket => parens += 1, + .r_paren, .r_brace, .r_bracket => if (parens != 0) { + parens -= 1; + }, + .keyword_pragma => p.skipToPragmaSentinel(), + .eof => return, + else => {}, + } + } +} + +/// Called after a typedef is defined +fn typedefDefined(p: *Parser, name: StringId, ty: Type) void { + if (name == p.string_ids.file) { + p.comp.types.file = ty; + } else if (name == p.string_ids.jmp_buf) { + p.comp.types.jmp_buf = ty; + } else if (name == p.string_ids.sigjmp_buf) { + p.comp.types.sigjmp_buf = ty; + } else if (name == p.string_ids.ucontext_t) { + p.comp.types.ucontext_t = ty; + } +} + +// ====== declarations ====== + +/// decl +/// : declSpec (initDeclarator ( ',' initDeclarator)*)? ';' +/// | declSpec declarator decl* compoundStmt +fn decl(p: *Parser) Error!bool { + _ = try p.pragma(); + const first_tok = p.tok_i; + const attr_buf_top = p.attr_buf.len; + defer p.attr_buf.len = attr_buf_top; + + try p.attributeSpecifier(); + + var decl_spec = if (try p.declSpec()) |some| some else blk: { + if (p.func.ty != null) { + p.tok_i = first_tok; + return false; + } + switch (p.tok_ids[first_tok]) { + .asterisk, .l_paren, .identifier, .extended_identifier => {}, + else => if (p.tok_i != first_tok) { + try p.err(.expected_ident_or_l_paren); + return error.ParsingFailed; + } else return false, + } + var spec: Type.Builder = .{}; + break :blk DeclSpec{ .ty = try spec.finish(p) }; + }; + if (decl_spec.noreturn) |tok| { + const attr = Attribute{ .tag = .noreturn, .args = .{ .noreturn = {} }, .syntax = .keyword }; + try p.attr_buf.append(p.gpa, .{ .attr = attr, .tok = tok }); + } + var init_d = (try p.initDeclarator(&decl_spec, attr_buf_top)) orelse { + _ = try p.expectToken(.semicolon); + if (decl_spec.ty.is(.@"enum") or + (decl_spec.ty.isRecord() and !decl_spec.ty.isAnonymousRecord(p.comp) and + !decl_spec.ty.isTypeof())) // we follow GCC and clang's behavior here + { + const specifier = decl_spec.ty.canonicalize(.standard).specifier; + const attrs = p.attr_buf.items(.attr)[attr_buf_top..]; + const toks = p.attr_buf.items(.tok)[attr_buf_top..]; + for (attrs, toks) |attr, tok| { + try p.errExtra(.ignored_record_attr, tok, .{ + .ignored_record_attr = .{ .tag = attr.tag, .specifier = switch (specifier) { + .@"enum" => .@"enum", + .@"struct" => .@"struct", + .@"union" => .@"union", + else => unreachable, + } }, + }); + } + return true; + } + + try p.errTok(.missing_declaration, first_tok); + return true; + }; + + // Check for function definition. + if (init_d.d.func_declarator != null and init_d.initializer.node == .none and init_d.d.ty.isFunc()) fn_def: { + if (decl_spec.auto_type) |tok_i| { + try p.errStr(.auto_type_not_allowed, tok_i, "function return type"); + return error.ParsingFailed; + } + + switch (p.tok_ids[p.tok_i]) { + .comma, .semicolon => break :fn_def, + .l_brace => {}, + else => if (init_d.d.old_style_func == null) { + try p.err(.expected_fn_body); + return true; + }, + } + if (p.func.ty != null) try p.err(.func_not_in_root); + + const node = try p.addNode(undefined); // reserve space + const interned_declarator_name = try p.comp.intern(p.tokSlice(init_d.d.name)); + try p.syms.defineSymbol(p, interned_declarator_name, init_d.d.ty, init_d.d.name, node, .{}, false); + + const func = p.func; + p.func = .{ + .ty = init_d.d.ty, + .name = init_d.d.name, + }; + if (interned_declarator_name == p.string_ids.main_id and !init_d.d.ty.returnType().is(.int)) { + try p.errTok(.main_return_type, init_d.d.name); + } + defer p.func = func; + + try p.syms.pushScope(p); + defer p.syms.popScope(); + + // Collect old style parameter declarations. + if (init_d.d.old_style_func != null) { + const attrs = init_d.d.ty.getAttributes(); + var base_ty = if (init_d.d.ty.specifier == .attributed) init_d.d.ty.elemType() else init_d.d.ty; + base_ty.specifier = .func; + init_d.d.ty = try base_ty.withAttributes(p.arena, attrs); + + const param_buf_top = p.param_buf.items.len; + defer p.param_buf.items.len = param_buf_top; + + param_loop: while (true) { + const param_decl_spec = (try p.declSpec()) orelse break; + if (p.eatToken(.semicolon)) |semi| { + try p.errTok(.missing_declaration, semi); + continue :param_loop; + } + + while (true) { + const attr_buf_top_declarator = p.attr_buf.len; + defer p.attr_buf.len = attr_buf_top_declarator; + + var d = (try p.declarator(param_decl_spec.ty, .normal)) orelse { + try p.errTok(.missing_declaration, first_tok); + _ = try p.expectToken(.semicolon); + continue :param_loop; + }; + try p.attributeSpecifier(); + + if (d.ty.hasIncompleteSize() and !d.ty.is(.void)) try p.errStr(.parameter_incomplete_ty, d.name, try p.typeStr(d.ty)); + if (d.ty.isFunc()) { + // Params declared as functions are converted to function pointers. + const elem_ty = try p.arena.create(Type); + elem_ty.* = d.ty; + d.ty = Type{ + .specifier = .pointer, + .data = .{ .sub_type = elem_ty }, + }; + } else if (d.ty.isArray()) { + // params declared as arrays are converted to pointers + d.ty.decayArray(); + } else if (d.ty.is(.void)) { + try p.errTok(.invalid_void_param, d.name); + } + + // find and correct parameter types + // TODO check for missing declarations and redefinitions + const name_str = p.tokSlice(d.name); + const interned_name = try p.comp.intern(name_str); + for (init_d.d.ty.params()) |*param| { + if (param.name == interned_name) { + param.ty = d.ty; + break; + } + } else { + try p.errStr(.parameter_missing, d.name, name_str); + } + d.ty = try Attribute.applyParameterAttributes(p, d.ty, attr_buf_top_declarator, .alignas_on_param); + + // bypass redefinition check to avoid duplicate errors + try p.syms.syms.append(p.gpa, .{ + .kind = .def, + .name = interned_name, + .tok = d.name, + .ty = d.ty, + .val = .{}, + }); + if (p.eatToken(.comma) == null) break; + } + _ = try p.expectToken(.semicolon); + } + } else { + for (init_d.d.ty.params()) |param| { + if (param.ty.hasUnboundVLA()) try p.errTok(.unbound_vla, param.name_tok); + if (param.ty.hasIncompleteSize() and !param.ty.is(.void) and param.ty.specifier != .invalid) try p.errStr(.parameter_incomplete_ty, param.name_tok, try p.typeStr(param.ty)); + + if (param.name == .empty) { + try p.errTok(.omitting_parameter_name, param.name_tok); + continue; + } + + // bypass redefinition check to avoid duplicate errors + try p.syms.syms.append(p.gpa, .{ + .kind = .def, + .name = param.name, + .tok = param.name_tok, + .ty = param.ty, + .val = .{}, + }); + } + } + + const body = (try p.compoundStmt(true, null)) orelse { + assert(init_d.d.old_style_func != null); + try p.err(.expected_fn_body); + return true; + }; + p.nodes.set(@intFromEnum(node), .{ + .ty = init_d.d.ty, + .tag = try decl_spec.validateFnDef(p), + .data = .{ .decl = .{ .name = init_d.d.name, .node = body } }, + }); + try p.decl_buf.append(node); + + // check gotos + if (func.ty == null) { + for (p.labels.items) |item| { + if (item == .unresolved_goto) + try p.errStr(.undeclared_label, item.unresolved_goto, p.tokSlice(item.unresolved_goto)); + } + if (p.computed_goto_tok) |goto_tok| { + if (!p.contains_address_of_label) try p.errTok(.invalid_computed_goto, goto_tok); + } + p.labels.items.len = 0; + p.label_count = 0; + p.contains_address_of_label = false; + p.computed_goto_tok = null; + } + return true; + } + + // Declare all variable/typedef declarators. + while (true) { + if (init_d.d.old_style_func) |tok_i| try p.errTok(.invalid_old_style_params, tok_i); + const tag = try decl_spec.validate(p, &init_d.d.ty, init_d.initializer.node != .none); + + const node = try p.addNode(.{ .ty = init_d.d.ty, .tag = tag, .data = .{ + .decl = .{ .name = init_d.d.name, .node = init_d.initializer.node }, + } }); + try p.decl_buf.append(node); + + const interned_name = try p.comp.intern(p.tokSlice(init_d.d.name)); + if (decl_spec.storage_class == .typedef) { + try p.syms.defineTypedef(p, interned_name, init_d.d.ty, init_d.d.name, node); + p.typedefDefined(interned_name, init_d.d.ty); + } else if (init_d.initializer.node != .none or + (p.func.ty != null and decl_spec.storage_class != .@"extern")) + { + // TODO validate global variable/constexpr initializer comptime known + try p.syms.defineSymbol( + p, + interned_name, + init_d.d.ty, + init_d.d.name, + node, + if (init_d.d.ty.isConst() or decl_spec.constexpr != null) init_d.initializer.val else .{}, + decl_spec.constexpr != null, + ); + } else { + try p.syms.declareSymbol(p, interned_name, init_d.d.ty, init_d.d.name, node); + } + + if (p.eatToken(.comma) == null) break; + + if (decl_spec.auto_type) |tok_i| try p.errTok(.auto_type_requires_single_declarator, tok_i); + + init_d = (try p.initDeclarator(&decl_spec, attr_buf_top)) orelse { + try p.err(.expected_ident_or_l_paren); + continue; + }; + } + + _ = try p.expectToken(.semicolon); + return true; +} + +fn staticAssertMessage(p: *Parser, cond_node: NodeIndex, message: Result) !?[]const u8 { + const cond_tag = p.nodes.items(.tag)[@intFromEnum(cond_node)]; + if (cond_tag != .builtin_types_compatible_p and message.node == .none) return null; + + var buf = std.ArrayList(u8).init(p.gpa); + defer buf.deinit(); + + if (cond_tag == .builtin_types_compatible_p) { + const mapper = p.comp.string_interner.getSlowTypeMapper(); + const data = p.nodes.items(.data)[@intFromEnum(cond_node)].bin; + + try buf.appendSlice("'__builtin_types_compatible_p("); + + const lhs_ty = p.nodes.items(.ty)[@intFromEnum(data.lhs)]; + try lhs_ty.print(mapper, p.comp.langopts, buf.writer()); + try buf.appendSlice(", "); + + const rhs_ty = p.nodes.items(.ty)[@intFromEnum(data.rhs)]; + try rhs_ty.print(mapper, p.comp.langopts, buf.writer()); + + try buf.appendSlice(")'"); + } + if (message.node != .none) { + if (buf.items.len > 0) { + try buf.append(' '); + } + const data = message.val.data.bytes; + try buf.ensureUnusedCapacity(data.len()); + try Tree.dumpStr( + p.retained_strings.items, + data, + p.nodes.items(.tag)[@intFromEnum(message.node)], + buf.writer(), + ); + } + return try p.comp.diag.arena.allocator().dupe(u8, buf.items); +} + +/// staticAssert +/// : keyword_static_assert '(' integerConstExpr (',' STRING_LITERAL)? ')' ';' +/// | keyword_c23_static_assert '(' integerConstExpr (',' STRING_LITERAL)? ')' ';' +fn staticAssert(p: *Parser) Error!bool { + const static_assert = p.eatToken(.keyword_static_assert) orelse p.eatToken(.keyword_c23_static_assert) orelse return false; + const l_paren = try p.expectToken(.l_paren); + const res_token = p.tok_i; + var res = try p.constExpr(.gnu_folding_extension); + const res_node = res.node; + const str = if (p.eatToken(.comma) != null) + switch (p.tok_ids[p.tok_i]) { + .string_literal, + .string_literal_utf_16, + .string_literal_utf_8, + .string_literal_utf_32, + .string_literal_wide, + => try p.stringLiteral(), + else => { + try p.err(.expected_str_literal); + return error.ParsingFailed; + }, + } + else + Result{}; + try p.expectClosing(l_paren, .r_paren); + _ = try p.expectToken(.semicolon); + if (str.node == .none) { + try p.errTok(.static_assert_missing_message, static_assert); + try p.errStr(.pre_c2x_compat, static_assert, "'_Static_assert' with no message"); + } + + // Array will never be zero; a value of zero for a pointer is a null pointer constant + if ((res.ty.isArray() or res.ty.isPtr()) and !res.val.isZero()) { + const err_start = p.comp.diag.list.items.len; + try p.errTok(.const_decl_folded, res_token); + if (res.ty.isPtr() and err_start != p.comp.diag.list.items.len) { + // Don't show the note if the .const_decl_folded diagnostic was not added + try p.errTok(.constant_expression_conversion_not_allowed, res_token); + } + } + try res.boolCast(p, .{ .specifier = .bool }, res_token); + if (res.val.tag == .unavailable) { + if (res.ty.specifier != .invalid) { + try p.errTok(.static_assert_not_constant, res_token); + } + } else { + if (!res.val.getBool()) { + if (try p.staticAssertMessage(res_node, str)) |message| { + try p.errStr(.static_assert_failure_message, static_assert, message); + } else { + try p.errTok(.static_assert_failure, static_assert); + } + } + } + + const node = try p.addNode(.{ + .tag = .static_assert, + .data = .{ .bin = .{ + .lhs = res.node, + .rhs = str.node, + } }, + }); + try p.decl_buf.append(node); + return true; +} + +pub const DeclSpec = struct { + storage_class: union(enum) { + auto: TokenIndex, + @"extern": TokenIndex, + register: TokenIndex, + static: TokenIndex, + typedef: TokenIndex, + none, + } = .none, + thread_local: ?TokenIndex = null, + constexpr: ?TokenIndex = null, + @"inline": ?TokenIndex = null, + noreturn: ?TokenIndex = null, + auto_type: ?TokenIndex = null, + ty: Type, + + fn validateParam(d: DeclSpec, p: *Parser, ty: *Type) Error!void { + switch (d.storage_class) { + .none => {}, + .register => ty.qual.register = true, + .auto, .@"extern", .static, .typedef => |tok_i| try p.errTok(.invalid_storage_on_param, tok_i), + } + if (d.thread_local) |tok_i| try p.errTok(.threadlocal_non_var, tok_i); + if (d.@"inline") |tok_i| try p.errStr(.func_spec_non_func, tok_i, "inline"); + if (d.noreturn) |tok_i| try p.errStr(.func_spec_non_func, tok_i, "_Noreturn"); + if (d.constexpr) |tok_i| try p.errTok(.invalid_storage_on_param, tok_i); + if (d.auto_type) |tok_i| { + try p.errStr(.auto_type_not_allowed, tok_i, "function prototype"); + ty.* = Type.invalid; + } + } + + fn validateFnDef(d: DeclSpec, p: *Parser) Error!Tree.Tag { + switch (d.storage_class) { + .none, .@"extern", .static => {}, + .auto, .register, .typedef => |tok_i| try p.errTok(.illegal_storage_on_func, tok_i), + } + if (d.thread_local) |tok_i| try p.errTok(.threadlocal_non_var, tok_i); + if (d.constexpr) |tok_i| try p.errTok(.illegal_storage_on_func, tok_i); + + const is_static = d.storage_class == .static; + const is_inline = d.@"inline" != null; + if (is_static) { + if (is_inline) return .inline_static_fn_def; + return .static_fn_def; + } else { + if (is_inline) return .inline_fn_def; + return .fn_def; + } + } + + fn validate(d: DeclSpec, p: *Parser, ty: *Type, has_init: bool) Error!Tree.Tag { + const is_static = d.storage_class == .static; + if (ty.isFunc() and d.storage_class != .typedef) { + switch (d.storage_class) { + .none, .@"extern" => {}, + .static => |tok_i| if (p.func.ty != null) try p.errTok(.static_func_not_global, tok_i), + .typedef => unreachable, + .auto, .register => |tok_i| try p.errTok(.illegal_storage_on_func, tok_i), + } + if (d.thread_local) |tok_i| try p.errTok(.threadlocal_non_var, tok_i); + if (d.constexpr) |tok_i| try p.errTok(.illegal_storage_on_func, tok_i); + + const is_inline = d.@"inline" != null; + if (is_static) { + if (is_inline) return .inline_static_fn_proto; + return .static_fn_proto; + } else { + if (is_inline) return .inline_fn_proto; + return .fn_proto; + } + } else { + if (d.@"inline") |tok_i| try p.errStr(.func_spec_non_func, tok_i, "inline"); + // TODO move to attribute validation + if (d.noreturn) |tok_i| try p.errStr(.func_spec_non_func, tok_i, "_Noreturn"); + switch (d.storage_class) { + .auto, .register => if (p.func.ty == null) try p.err(.illegal_storage_on_global), + .typedef => return .typedef, + else => {}, + } + ty.qual.register = d.storage_class == .register; + + const is_extern = d.storage_class == .@"extern" and !has_init; + if (d.thread_local != null) { + if (is_static) return .threadlocal_static_var; + if (is_extern) return .threadlocal_extern_var; + return .threadlocal_var; + } else { + if (is_static) return .static_var; + if (is_extern) return .extern_var; + return .@"var"; + } + } + } +}; + +/// typeof +/// : keyword_typeof '(' typeName ')' +/// | keyword_typeof '(' expr ')' +fn typeof(p: *Parser) Error!?Type { + switch (p.tok_ids[p.tok_i]) { + .keyword_typeof, .keyword_typeof1, .keyword_typeof2 => p.tok_i += 1, + else => return null, + } + const l_paren = try p.expectToken(.l_paren); + if (try p.typeName()) |ty| { + try p.expectClosing(l_paren, .r_paren); + const typeof_ty = try p.arena.create(Type); + typeof_ty.* = .{ + .data = ty.data, + .qual = ty.qual.inheritFromTypeof(), + .specifier = ty.specifier, + }; + + return Type{ + .data = .{ .sub_type = typeof_ty }, + .specifier = .typeof_type, + }; + } + const typeof_expr = try p.parseNoEval(expr); + try typeof_expr.expect(p); + try p.expectClosing(l_paren, .r_paren); + // Special case nullptr_t since it's defined as typeof(nullptr) + if (typeof_expr.ty.is(.nullptr_t)) { + return Type{ .specifier = .nullptr_t, .qual = typeof_expr.ty.qual.inheritFromTypeof() }; + } + + const inner = try p.arena.create(Type.Expr); + inner.* = .{ + .node = typeof_expr.node, + .ty = .{ + .data = typeof_expr.ty.data, + .qual = typeof_expr.ty.qual.inheritFromTypeof(), + .specifier = typeof_expr.ty.specifier, + }, + }; + + return Type{ + .data = .{ .expr = inner }, + .specifier = .typeof_expr, + }; +} + +/// declSpec: (storageClassSpec | typeSpec | typeQual | funcSpec | alignSpec)+ +/// storageClassSpec: +/// : keyword_typedef +/// | keyword_extern +/// | keyword_static +/// | keyword_threadlocal +/// | keyword_auto +/// | keyword_register +/// funcSpec : keyword_inline | keyword_noreturn +fn declSpec(p: *Parser) Error!?DeclSpec { + var d: DeclSpec = .{ .ty = .{ .specifier = undefined } }; + var spec: Type.Builder = .{}; + + const start = p.tok_i; + while (true) { + if (try p.typeSpec(&spec)) continue; + const id = p.tok_ids[p.tok_i]; + switch (id) { + .keyword_typedef, + .keyword_extern, + .keyword_static, + .keyword_auto, + .keyword_register, + => { + if (d.storage_class != .none) { + try p.errStr(.multiple_storage_class, p.tok_i, @tagName(d.storage_class)); + return error.ParsingFailed; + } + if (d.thread_local != null) { + switch (id) { + .keyword_extern, .keyword_static => {}, + else => try p.errStr(.cannot_combine_spec, p.tok_i, id.lexeme().?), + } + if (d.constexpr) |tok| try p.errStr(.cannot_combine_spec, p.tok_i, p.tok_ids[tok].lexeme().?); + } + if (d.constexpr != null) { + switch (id) { + .keyword_auto, .keyword_register, .keyword_static => {}, + else => try p.errStr(.cannot_combine_spec, p.tok_i, id.lexeme().?), + } + if (d.thread_local) |tok| try p.errStr(.cannot_combine_spec, p.tok_i, p.tok_ids[tok].lexeme().?); + } + switch (id) { + .keyword_typedef => d.storage_class = .{ .typedef = p.tok_i }, + .keyword_extern => d.storage_class = .{ .@"extern" = p.tok_i }, + .keyword_static => d.storage_class = .{ .static = p.tok_i }, + .keyword_auto => d.storage_class = .{ .auto = p.tok_i }, + .keyword_register => d.storage_class = .{ .register = p.tok_i }, + else => unreachable, + } + }, + .keyword_thread_local, + .keyword_c23_thread_local, + => { + if (d.thread_local != null) { + try p.errStr(.duplicate_decl_spec, p.tok_i, id.lexeme().?); + } + if (d.constexpr) |tok| try p.errStr(.cannot_combine_spec, p.tok_i, p.tok_ids[tok].lexeme().?); + switch (d.storage_class) { + .@"extern", .none, .static => {}, + else => try p.errStr(.cannot_combine_spec, p.tok_i, @tagName(d.storage_class)), + } + d.thread_local = p.tok_i; + }, + .keyword_constexpr => { + if (d.constexpr != null) { + try p.errStr(.duplicate_decl_spec, p.tok_i, id.lexeme().?); + } + if (d.thread_local) |tok| try p.errStr(.cannot_combine_spec, p.tok_i, p.tok_ids[tok].lexeme().?); + switch (d.storage_class) { + .auto, .register, .none, .static => {}, + else => try p.errStr(.cannot_combine_spec, p.tok_i, @tagName(d.storage_class)), + } + d.constexpr = p.tok_i; + }, + .keyword_inline, .keyword_inline1, .keyword_inline2 => { + if (d.@"inline" != null) { + try p.errStr(.duplicate_decl_spec, p.tok_i, "inline"); + } + d.@"inline" = p.tok_i; + }, + .keyword_noreturn => { + if (d.noreturn != null) { + try p.errStr(.duplicate_decl_spec, p.tok_i, "_Noreturn"); + } + d.noreturn = p.tok_i; + }, + else => break, + } + p.tok_i += 1; + } + + if (p.tok_i == start) return null; + + d.ty = try spec.finish(p); + d.auto_type = spec.auto_type_tok; + return d; +} + +const InitDeclarator = struct { d: Declarator, initializer: Result = .{} }; + +/// attribute +/// : attrIdentifier +/// | attrIdentifier '(' identifier ')' +/// | attrIdentifier '(' identifier (',' expr)+ ')' +/// | attrIdentifier '(' (expr (',' expr)*)? ')' +fn attribute(p: *Parser, kind: Attribute.Kind, namespace: ?[]const u8) Error!?TentativeAttribute { + const name_tok = p.tok_i; + switch (p.tok_ids[p.tok_i]) { + .keyword_const, .keyword_const1, .keyword_const2 => p.tok_i += 1, + else => _ = try p.expectIdentifier(), + } + const name = p.tokSlice(name_tok); + + const attr = Attribute.fromString(kind, namespace, name) orelse { + const tag: Diagnostics.Tag = if (kind == .declspec) .declspec_attr_not_supported else .unknown_attribute; + try p.errStr(tag, name_tok, name); + if (p.eatToken(.l_paren)) |_| p.skipTo(.r_paren); + return null; + }; + + const required_count = Attribute.requiredArgCount(attr); + var arguments = Attribute.initArguments(attr, name_tok); + var arg_idx: u32 = 0; + + switch (p.tok_ids[p.tok_i]) { + .comma, .r_paren => {}, // will be consumed in attributeList + .l_paren => blk: { + p.tok_i += 1; + if (p.eatToken(.r_paren)) |_| break :blk; + + if (Attribute.wantsIdentEnum(attr)) { + if (try p.eatIdentifier()) |ident| { + if (Attribute.diagnoseIdent(attr, &arguments, p.tokSlice(ident))) |msg| { + try p.errExtra(msg.tag, ident, msg.extra); + p.skipTo(.r_paren); + return error.ParsingFailed; + } + } else { + try p.errExtra(.attribute_requires_identifier, name_tok, .{ .str = name }); + return error.ParsingFailed; + } + } else { + const arg_start = p.tok_i; + var first_expr = try p.assignExpr(); + try first_expr.expect(p); + if (p.diagnose(attr, &arguments, arg_idx, first_expr)) |msg| { + try p.errExtra(msg.tag, arg_start, msg.extra); + p.skipTo(.r_paren); + return error.ParsingFailed; + } + } + arg_idx += 1; + while (p.eatToken(.r_paren) == null) : (arg_idx += 1) { + _ = try p.expectToken(.comma); + + const arg_start = p.tok_i; + var arg_expr = try p.assignExpr(); + try arg_expr.expect(p); + if (p.diagnose(attr, &arguments, arg_idx, arg_expr)) |msg| { + try p.errExtra(msg.tag, arg_start, msg.extra); + p.skipTo(.r_paren); + return error.ParsingFailed; + } + } + }, + else => {}, + } + if (arg_idx < required_count) { + try p.errExtra(.attribute_not_enough_args, name_tok, .{ .attr_arg_count = .{ .attribute = attr, .expected = required_count } }); + return error.ParsingFailed; + } + return TentativeAttribute{ .attr = .{ .tag = attr, .args = arguments, .syntax = kind.toSyntax() }, .tok = name_tok }; +} + +fn diagnose(p: *Parser, attr: Attribute.Tag, arguments: *Attribute.Arguments, arg_idx: u32, res: Result) ?Diagnostics.Message { + if (Attribute.wantsAlignment(attr, arg_idx)) { + return Attribute.diagnoseAlignment(attr, arguments, arg_idx, res.val, res.ty, p.comp); + } + const node = p.nodes.get(@intFromEnum(res.node)); + return Attribute.diagnose(attr, arguments, arg_idx, res.val, node, p.retained_strings.items); +} + +/// attributeList : (attribute (',' attribute)*)? +fn gnuAttributeList(p: *Parser) Error!void { + if (p.tok_ids[p.tok_i] == .r_paren) return; + + if (try p.attribute(.gnu, null)) |attr| try p.attr_buf.append(p.gpa, attr); + while (p.tok_ids[p.tok_i] != .r_paren) { + _ = try p.expectToken(.comma); + if (try p.attribute(.gnu, null)) |attr| try p.attr_buf.append(p.gpa, attr); + } +} + +fn c2xAttributeList(p: *Parser) Error!void { + while (p.tok_ids[p.tok_i] != .r_bracket) { + var namespace_tok = try p.expectIdentifier(); + var namespace: ?[]const u8 = null; + if (p.eatToken(.colon_colon)) |_| { + namespace = p.tokSlice(namespace_tok); + } else { + p.tok_i -= 1; + } + if (try p.attribute(.c2x, namespace)) |attr| try p.attr_buf.append(p.gpa, attr); + _ = p.eatToken(.comma); + } +} + +fn msvcAttributeList(p: *Parser) Error!void { + while (p.tok_ids[p.tok_i] != .r_paren) { + if (try p.attribute(.declspec, null)) |attr| try p.attr_buf.append(p.gpa, attr); + _ = p.eatToken(.comma); + } +} + +fn c2xAttribute(p: *Parser) !bool { + if (!p.comp.langopts.standard.atLeast(.c2x)) return false; + const bracket1 = p.eatToken(.l_bracket) orelse return false; + const bracket2 = p.eatToken(.l_bracket) orelse { + p.tok_i -= 1; + return false; + }; + + try p.c2xAttributeList(); + + _ = try p.expectClosing(bracket2, .r_bracket); + _ = try p.expectClosing(bracket1, .r_bracket); + + return true; +} + +fn msvcAttribute(p: *Parser) !bool { + _ = p.eatToken(.keyword_declspec) orelse return false; + const l_paren = try p.expectToken(.l_paren); + try p.msvcAttributeList(); + _ = try p.expectClosing(l_paren, .r_paren); + + return true; +} + +fn gnuAttribute(p: *Parser) !bool { + switch (p.tok_ids[p.tok_i]) { + .keyword_attribute1, .keyword_attribute2 => p.tok_i += 1, + else => return false, + } + const paren1 = try p.expectToken(.l_paren); + const paren2 = try p.expectToken(.l_paren); + + try p.gnuAttributeList(); + + _ = try p.expectClosing(paren2, .r_paren); + _ = try p.expectClosing(paren1, .r_paren); + return true; +} + +fn attributeSpecifier(p: *Parser) Error!void { + return attributeSpecifierExtra(p, null); +} + +/// attributeSpecifier : (keyword_attribute '( '(' attributeList ')' ')')* +fn attributeSpecifierExtra(p: *Parser, declarator_name: ?TokenIndex) Error!void { + while (true) { + if (try p.gnuAttribute()) continue; + if (try p.c2xAttribute()) continue; + const maybe_declspec_tok = p.tok_i; + const attr_buf_top = p.attr_buf.len; + if (try p.msvcAttribute()) { + if (declarator_name) |name_tok| { + try p.errTok(.declspec_not_allowed_after_declarator, maybe_declspec_tok); + try p.errTok(.declarator_name_tok, name_tok); + p.attr_buf.len = attr_buf_top; + } + continue; + } + break; + } +} + +/// initDeclarator : declarator assembly? attributeSpecifier? ('=' initializer)? +fn initDeclarator(p: *Parser, decl_spec: *DeclSpec, attr_buf_top: usize) Error!?InitDeclarator { + const this_attr_buf_top = p.attr_buf.len; + defer p.attr_buf.len = this_attr_buf_top; + + var init_d = InitDeclarator{ + .d = (try p.declarator(decl_spec.ty, .normal)) orelse return null, + }; + + try p.attributeSpecifierExtra(init_d.d.name); + _ = try p.assembly(.decl_label); + try p.attributeSpecifierExtra(init_d.d.name); + + var apply_var_attributes = false; + if (decl_spec.storage_class == .typedef) { + if (decl_spec.auto_type) |tok_i| { + try p.errStr(.auto_type_not_allowed, tok_i, "typedef"); + return error.ParsingFailed; + } + init_d.d.ty = try Attribute.applyTypeAttributes(p, init_d.d.ty, attr_buf_top, null); + } else if (init_d.d.ty.isFunc()) { + init_d.d.ty = try Attribute.applyFunctionAttributes(p, init_d.d.ty, attr_buf_top); + } else { + apply_var_attributes = true; + } + + if (p.eatToken(.equal)) |eq| init: { + if (decl_spec.storage_class == .typedef or init_d.d.func_declarator != null) { + try p.errTok(.illegal_initializer, eq); + } else if (init_d.d.ty.is(.variable_len_array)) { + try p.errTok(.vla_init, eq); + } else if (decl_spec.storage_class == .@"extern") { + try p.err(.extern_initializer); + decl_spec.storage_class = .none; + } + + if (init_d.d.ty.hasIncompleteSize() and !init_d.d.ty.is(.incomplete_array)) { + try p.errStr(.variable_incomplete_ty, init_d.d.name, try p.typeStr(init_d.d.ty)); + return error.ParsingFailed; + } + + try p.syms.pushScope(p); + defer p.syms.popScope(); + + const interned_name = try p.comp.intern(p.tokSlice(init_d.d.name)); + try p.syms.declareSymbol(p, interned_name, init_d.d.ty, init_d.d.name, .none); + var init_list_expr = try p.initializer(init_d.d.ty); + init_d.initializer = init_list_expr; + if (!init_list_expr.ty.isArray()) break :init; + if (init_d.d.ty.specifier == .incomplete_array) { + // Modifying .data is exceptionally allowed for .incomplete_array. + init_d.d.ty.data.array.len = init_list_expr.ty.arrayLen() orelse break :init; + init_d.d.ty.specifier = .array; + } + } + + const name = init_d.d.name; + if (init_d.d.ty.is(.auto_type)) { + if (init_d.initializer.node == .none) { + init_d.d.ty = Type.invalid; + try p.errStr(.auto_type_requires_initializer, name, p.tokSlice(name)); + return init_d; + } else { + init_d.d.ty.specifier = init_d.initializer.ty.specifier; + init_d.d.ty.data = init_d.initializer.ty.data; + } + } + if (apply_var_attributes) { + init_d.d.ty = try Attribute.applyVariableAttributes(p, init_d.d.ty, attr_buf_top, null); + } + if (decl_spec.storage_class != .typedef and init_d.d.ty.hasIncompleteSize()) incomplete: { + const specifier = init_d.d.ty.canonicalize(.standard).specifier; + if (decl_spec.storage_class == .@"extern") switch (specifier) { + .@"struct", .@"union", .@"enum" => break :incomplete, + .incomplete_array => { + init_d.d.ty.decayArray(); + break :incomplete; + }, + else => {}, + }; + // if there was an initializer expression it must have contained an error + if (init_d.initializer.node != .none) break :incomplete; + + if (p.func.ty == null) { + if (specifier == .incomplete_array) { + // TODO properly check this after finishing parsing + try p.errStr(.tentative_array, name, try p.typeStr(init_d.d.ty)); + break :incomplete; + } else if (init_d.d.ty.getRecord()) |record| { + _ = try p.tentative_defs.getOrPutValue(p.comp.gpa, record.name, init_d.d.name); + break :incomplete; + } else if (init_d.d.ty.get(.@"enum")) |en| { + _ = try p.tentative_defs.getOrPutValue(p.comp.gpa, en.data.@"enum".name, init_d.d.name); + break :incomplete; + } + } + try p.errStr(.variable_incomplete_ty, name, try p.typeStr(init_d.d.ty)); + } + return init_d; +} + +/// typeSpec +/// : keyword_void +/// | keyword_auto_type +/// | keyword_char +/// | keyword_short +/// | keyword_int +/// | keyword_long +/// | keyword_float +/// | keyword_double +/// | keyword_signed +/// | keyword_unsigned +/// | keyword_bool +/// | keyword_c23_bool +/// | keyword_complex +/// | atomicTypeSpec +/// | recordSpec +/// | enumSpec +/// | typedef // IDENTIFIER +/// | typeof +/// | keyword_bit_int '(' integerConstExpr ')' +/// atomicTypeSpec : keyword_atomic '(' typeName ')' +/// alignSpec +/// : keyword_alignas '(' typeName ')' +/// | keyword_alignas '(' integerConstExpr ')' +/// | keyword_c23_alignas '(' typeName ')' +/// | keyword_c23_alignas '(' integerConstExpr ')' +fn typeSpec(p: *Parser, ty: *Type.Builder) Error!bool { + const start = p.tok_i; + while (true) { + try p.attributeSpecifier(); + + if (try p.typeof()) |inner_ty| { + try ty.combineFromTypeof(p, inner_ty, start); + continue; + } + if (try p.typeQual(&ty.qual)) continue; + switch (p.tok_ids[p.tok_i]) { + .keyword_void => try ty.combine(p, .void, p.tok_i), + .keyword_auto_type => { + try p.errTok(.auto_type_extension, p.tok_i); + try ty.combine(p, .auto_type, p.tok_i); + }, + .keyword_bool, .keyword_c23_bool => try ty.combine(p, .bool, p.tok_i), + .keyword_int8, .keyword_int8_2, .keyword_char => try ty.combine(p, .char, p.tok_i), + .keyword_int16, .keyword_int16_2, .keyword_short => try ty.combine(p, .short, p.tok_i), + .keyword_int32, .keyword_int32_2, .keyword_int => try ty.combine(p, .int, p.tok_i), + .keyword_long => try ty.combine(p, .long, p.tok_i), + .keyword_int64, .keyword_int64_2 => try ty.combine(p, .long_long, p.tok_i), + .keyword_int128 => try ty.combine(p, .int128, p.tok_i), + .keyword_signed => try ty.combine(p, .signed, p.tok_i), + .keyword_unsigned => try ty.combine(p, .unsigned, p.tok_i), + .keyword_fp16 => try ty.combine(p, .fp16, p.tok_i), + .keyword_float16 => try ty.combine(p, .float16, p.tok_i), + .keyword_float => try ty.combine(p, .float, p.tok_i), + .keyword_double => try ty.combine(p, .double, p.tok_i), + .keyword_complex => try ty.combine(p, .complex, p.tok_i), + .keyword_float80 => try ty.combine(p, .float80, p.tok_i), + .keyword_float128 => try ty.combine(p, .float128, p.tok_i), + .keyword_atomic => { + const atomic_tok = p.tok_i; + p.tok_i += 1; + const l_paren = p.eatToken(.l_paren) orelse { + // _Atomic qualifier not _Atomic(typeName) + p.tok_i = atomic_tok; + break; + }; + const inner_ty = (try p.typeName()) orelse { + try p.err(.expected_type); + return error.ParsingFailed; + }; + try p.expectClosing(l_paren, .r_paren); + + const new_spec = Type.Builder.fromType(inner_ty); + try ty.combine(p, new_spec, atomic_tok); + + if (ty.qual.atomic != null) + try p.errStr(.duplicate_decl_spec, atomic_tok, "atomic") + else + ty.qual.atomic = atomic_tok; + continue; + }, + .keyword_alignas, + .keyword_c23_alignas, + => { + const align_tok = p.tok_i; + p.tok_i += 1; + const l_paren = try p.expectToken(.l_paren); + const typename_start = p.tok_i; + if (try p.typeName()) |inner_ty| { + if (!inner_ty.alignable()) { + try p.errStr(.invalid_alignof, typename_start, try p.typeStr(inner_ty)); + } + const alignment = Attribute.Alignment{ .requested = inner_ty.alignof(p.comp) }; + try p.attr_buf.append(p.gpa, .{ + .attr = .{ .tag = .aligned, .args = .{ + .aligned = .{ .alignment = alignment, .__name_tok = align_tok }, + }, .syntax = .keyword }, + .tok = align_tok, + }); + } else { + const arg_start = p.tok_i; + const res = try p.integerConstExpr(.no_const_decl_folding); + if (!res.val.isZero()) { + var args = Attribute.initArguments(.aligned, align_tok); + if (p.diagnose(.aligned, &args, 0, res)) |msg| { + try p.errExtra(msg.tag, arg_start, msg.extra); + p.skipTo(.r_paren); + return error.ParsingFailed; + } + args.aligned.alignment.?.node = res.node; + try p.attr_buf.append(p.gpa, .{ + .attr = .{ .tag = .aligned, .args = args, .syntax = .keyword }, + .tok = align_tok, + }); + } + } + try p.expectClosing(l_paren, .r_paren); + continue; + }, + .keyword_stdcall, + .keyword_stdcall2, + .keyword_thiscall, + .keyword_thiscall2, + .keyword_vectorcall, + .keyword_vectorcall2, + => try p.attr_buf.append(p.gpa, .{ + .attr = .{ .tag = .calling_convention, .args = .{ + .calling_convention = .{ .cc = switch (p.tok_ids[p.tok_i]) { + .keyword_stdcall, + .keyword_stdcall2, + => .stdcall, + .keyword_thiscall, + .keyword_thiscall2, + => .thiscall, + .keyword_vectorcall, + .keyword_vectorcall2, + => .vectorcall, + else => unreachable, + } }, + }, .syntax = .keyword }, + .tok = p.tok_i, + }), + .keyword_struct, .keyword_union => { + const tag_tok = p.tok_i; + const record_ty = try p.recordSpec(); + try ty.combine(p, Type.Builder.fromType(record_ty), tag_tok); + continue; + }, + .keyword_enum => { + const tag_tok = p.tok_i; + const enum_ty = try p.enumSpec(); + try ty.combine(p, Type.Builder.fromType(enum_ty), tag_tok); + continue; + }, + .identifier, .extended_identifier => { + var interned_name = try p.comp.intern(p.tokSlice(p.tok_i)); + var declspec_found = false; + + if (interned_name == p.string_ids.declspec_id) { + try p.errTok(.declspec_not_enabled, p.tok_i); + p.tok_i += 1; + if (p.eatToken(.l_paren)) |_| { + p.skipTo(.r_paren); + continue; + } + declspec_found = true; + } + if (ty.typedef != null) break; + if (declspec_found) { + interned_name = try p.comp.intern(p.tokSlice(p.tok_i)); + } + const typedef = (try p.syms.findTypedef(p, interned_name, p.tok_i, ty.specifier != .none)) orelse break; + if (!ty.combineTypedef(p, typedef.ty, typedef.tok)) break; + }, + .keyword_bit_int => { + try p.err(.bit_int); + const bit_int_tok = p.tok_i; + p.tok_i += 1; + const l_paren = try p.expectToken(.l_paren); + const res = try p.integerConstExpr(.gnu_folding_extension); + try p.expectClosing(l_paren, .r_paren); + + var bits: i16 = undefined; + if (res.val.tag == .unavailable) { + try p.errTok(.expected_integer_constant_expr, bit_int_tok); + return error.ParsingFailed; + } else if (res.val.compare(.lte, Value.int(0), res.ty, p.comp)) { + bits = -1; + } else if (res.val.compare(.gt, Value.int(128), res.ty, p.comp)) { + bits = 129; + } else { + bits = res.val.getInt(i16); + } + + try ty.combine(p, .{ .bit_int = bits }, bit_int_tok); + continue; + }, + else => break, + } + // consume single token specifiers here + p.tok_i += 1; + } + return p.tok_i != start; +} + +fn getAnonymousName(p: *Parser, kind_tok: TokenIndex) !StringId { + const loc = p.pp.tokens.items(.loc)[kind_tok]; + const source = p.comp.getSource(loc.id); + const line_col = source.lineCol(loc); + + const kind_str = switch (p.tok_ids[kind_tok]) { + .keyword_struct, .keyword_union, .keyword_enum => p.tokSlice(kind_tok), + else => "record field", + }; + + const str = try std.fmt.allocPrint( + p.arena, + "(anonymous {s} at {s}:{d}:{d})", + .{ kind_str, source.path, line_col.line_no, line_col.col }, + ); + return p.comp.intern(str); +} + +/// recordSpec +/// : (keyword_struct | keyword_union) IDENTIFIER? { recordDecl* } +/// | (keyword_struct | keyword_union) IDENTIFIER +fn recordSpec(p: *Parser) Error!Type { + const starting_pragma_pack = p.pragma_pack; + const kind_tok = p.tok_i; + const is_struct = p.tok_ids[kind_tok] == .keyword_struct; + p.tok_i += 1; + const attr_buf_top = p.attr_buf.len; + defer p.attr_buf.len = attr_buf_top; + try p.attributeSpecifier(); + + const maybe_ident = try p.eatIdentifier(); + const l_brace = p.eatToken(.l_brace) orelse { + const ident = maybe_ident orelse { + try p.err(.ident_or_l_brace); + return error.ParsingFailed; + }; + // check if this is a reference to a previous type + const interned_name = try p.comp.intern(p.tokSlice(ident)); + if (try p.syms.findTag(p, interned_name, p.tok_ids[kind_tok], ident, p.tok_ids[p.tok_i])) |prev| { + return prev.ty; + } else { + // this is a forward declaration, create a new record Type. + const record_ty = try Type.Record.create(p.arena, interned_name); + const ty = try Attribute.applyTypeAttributes(p, .{ + .specifier = if (is_struct) .@"struct" else .@"union", + .data = .{ .record = record_ty }, + }, attr_buf_top, null); + try p.syms.syms.append(p.gpa, .{ + .kind = if (is_struct) .@"struct" else .@"union", + .name = interned_name, + .tok = ident, + .ty = ty, + .val = .{}, + }); + try p.decl_buf.append(try p.addNode(.{ + .tag = if (is_struct) .struct_forward_decl else .union_forward_decl, + .ty = ty, + .data = .{ .decl_ref = ident }, + })); + return ty; + } + }; + + var done = false; + errdefer if (!done) p.skipTo(.r_brace); + + // Get forward declared type or create a new one + var defined = false; + const record_ty: *Type.Record = if (maybe_ident) |ident| record_ty: { + const ident_str = p.tokSlice(ident); + const interned_name = try p.comp.intern(ident_str); + if (try p.syms.defineTag(p, interned_name, p.tok_ids[kind_tok], ident)) |prev| { + if (!prev.ty.hasIncompleteSize()) { + // if the record isn't incomplete, this is a redefinition + try p.errStr(.redefinition, ident, ident_str); + try p.errTok(.previous_definition, prev.tok); + } else { + defined = true; + break :record_ty prev.ty.get(if (is_struct) .@"struct" else .@"union").?.data.record; + } + } + break :record_ty try Type.Record.create(p.arena, interned_name); + } else try Type.Record.create(p.arena, try p.getAnonymousName(kind_tok)); + + // Initially create ty as a regular non-attributed type, since attributes for a record + // can be specified after the closing rbrace, which we haven't encountered yet. + var ty = Type{ + .specifier = if (is_struct) .@"struct" else .@"union", + .data = .{ .record = record_ty }, + }; + + // declare a symbol for the type + // We need to replace the symbol's type if it has attributes + var symbol_index: ?usize = null; + if (maybe_ident != null and !defined) { + symbol_index = p.syms.syms.len; + try p.syms.syms.append(p.gpa, .{ + .kind = if (is_struct) .@"struct" else .@"union", + .name = record_ty.name, + .tok = maybe_ident.?, + .ty = ty, + .val = .{}, + }); + } + + // reserve space for this record + try p.decl_buf.append(.none); + const decl_buf_top = p.decl_buf.items.len; + const record_buf_top = p.record_buf.items.len; + errdefer p.decl_buf.items.len = decl_buf_top - 1; + defer { + p.decl_buf.items.len = decl_buf_top; + p.record_buf.items.len = record_buf_top; + } + + const old_record = p.record; + const old_members = p.record_members.items.len; + const old_field_attr_start = p.field_attr_buf.items.len; + p.record = .{ + .kind = p.tok_ids[kind_tok], + .start = p.record_members.items.len, + .field_attr_start = p.field_attr_buf.items.len, + }; + defer p.record = old_record; + defer p.record_members.items.len = old_members; + defer p.field_attr_buf.items.len = old_field_attr_start; + + try p.recordDecls(); + + if (p.record.flexible_field) |some| { + if (p.record_buf.items[record_buf_top..].len == 1 and is_struct) { + try p.errTok(.flexible_in_empty, some); + } + } + + for (p.record_buf.items[record_buf_top..]) |field| { + if (field.ty.hasIncompleteSize() and !field.ty.is(.incomplete_array)) break; + } else { + record_ty.fields = try p.arena.dupe(Type.Record.Field, p.record_buf.items[record_buf_top..]); + } + if (old_field_attr_start < p.field_attr_buf.items.len) { + const field_attr_slice = p.field_attr_buf.items[old_field_attr_start..]; + const duped = try p.arena.dupe([]const Attribute, field_attr_slice); + record_ty.field_attributes = duped.ptr; + } + + if (p.record_buf.items.len == record_buf_top) { + try p.errStr(.empty_record, kind_tok, p.tokSlice(kind_tok)); + try p.errStr(.empty_record_size, kind_tok, p.tokSlice(kind_tok)); + } + try p.expectClosing(l_brace, .r_brace); + done = true; + try p.attributeSpecifier(); + + ty = try Attribute.applyTypeAttributes(p, .{ + .specifier = if (is_struct) .@"struct" else .@"union", + .data = .{ .record = record_ty }, + }, attr_buf_top, null); + if (ty.specifier == .attributed and symbol_index != null) { + p.syms.syms.items(.ty)[symbol_index.?] = ty; + } + + if (!ty.hasIncompleteSize()) { + const pragma_pack_value = switch (p.comp.langopts.emulate) { + .clang => starting_pragma_pack, + .gcc => p.pragma_pack, + // TODO: msvc considers `#pragma pack` on a per-field basis + .msvc => p.pragma_pack, + }; + record_layout.compute(record_ty, ty, p.pp.comp, pragma_pack_value); + } + + // finish by creating a node + var node: Tree.Node = .{ + .tag = if (is_struct) .struct_decl_two else .union_decl_two, + .ty = ty, + .data = .{ .bin = .{ .lhs = .none, .rhs = .none } }, + }; + const record_decls = p.decl_buf.items[decl_buf_top..]; + switch (record_decls.len) { + 0 => {}, + 1 => node.data = .{ .bin = .{ .lhs = record_decls[0], .rhs = .none } }, + 2 => node.data = .{ .bin = .{ .lhs = record_decls[0], .rhs = record_decls[1] } }, + else => { + node.tag = if (is_struct) .struct_decl else .union_decl; + node.data = .{ .range = try p.addList(record_decls) }; + }, + } + p.decl_buf.items[decl_buf_top - 1] = try p.addNode(node); + if (p.func.ty == null) { + _ = p.tentative_defs.remove(record_ty.name); + } + return ty; +} + +/// recordDecl +/// : specQual (recordDeclarator (',' recordDeclarator)*)? ; +/// | staticAssert +fn recordDecls(p: *Parser) Error!void { + while (true) { + if (try p.pragma()) continue; + if (try p.parseOrNextDecl(staticAssert)) continue; + if (p.eatToken(.keyword_extension)) |_| { + const saved_extension = p.extension_suppressed; + defer p.extension_suppressed = saved_extension; + p.extension_suppressed = true; + + if (try p.parseOrNextDecl(recordDeclarator)) continue; + try p.err(.expected_type); + p.nextExternDecl(); + continue; + } + if (try p.parseOrNextDecl(recordDeclarator)) continue; + break; + } +} + +/// recordDeclarator : keyword_extension? declarator (':' integerConstExpr)? +fn recordDeclarator(p: *Parser) Error!bool { + const attr_buf_top = p.attr_buf.len; + defer p.attr_buf.len = attr_buf_top; + const base_ty = (try p.specQual()) orelse return false; + + try p.attributeSpecifier(); // .record + while (true) { + const this_decl_top = p.attr_buf.len; + defer p.attr_buf.len = this_decl_top; + + try p.attributeSpecifier(); + + // 0 means unnamed + var name_tok: TokenIndex = 0; + var ty = base_ty; + if (ty.is(.auto_type)) { + try p.errStr(.auto_type_not_allowed, p.tok_i, if (p.record.kind == .keyword_struct) "struct member" else "union member"); + ty = Type.invalid; + } + var bits_node: NodeIndex = .none; + var bits: ?u32 = null; + const first_tok = p.tok_i; + if (try p.declarator(ty, .record)) |d| { + name_tok = d.name; + ty = d.ty; + } + + if (p.eatToken(.colon)) |_| bits: { + const bits_tok = p.tok_i; + const res = try p.integerConstExpr(.gnu_folding_extension); + if (!ty.isInt()) { + try p.errStr(.non_int_bitfield, first_tok, try p.typeStr(ty)); + break :bits; + } + + if (res.val.tag == .unavailable) { + try p.errTok(.expected_integer_constant_expr, bits_tok); + break :bits; + } else if (res.val.compare(.lt, Value.int(0), res.ty, p.comp)) { + try p.errExtra(.negative_bitwidth, first_tok, .{ + .signed = res.val.signExtend(res.ty, p.comp), + }); + break :bits; + } + + // incomplete size error is reported later + const bit_size = ty.bitSizeof(p.comp) orelse break :bits; + if (res.val.compare(.gt, Value.int(bit_size), res.ty, p.comp)) { + try p.errTok(.bitfield_too_big, name_tok); + break :bits; + } else if (res.val.isZero() and name_tok != 0) { + try p.errTok(.zero_width_named_field, name_tok); + break :bits; + } + + bits = res.val.getInt(u32); + bits_node = res.node; + } + + try p.attributeSpecifier(); // .record + const to_append = try Attribute.applyFieldAttributes(p, &ty, attr_buf_top); + + const any_fields_have_attrs = p.field_attr_buf.items.len > p.record.field_attr_start; + + if (any_fields_have_attrs) { + try p.field_attr_buf.append(to_append); + } else { + if (to_append.len > 0) { + const preceding = p.record_members.items.len - p.record.start; + if (preceding > 0) { + try p.field_attr_buf.appendNTimes(&.{}, preceding); + } + try p.field_attr_buf.append(to_append); + } + } + + if (name_tok == 0 and bits_node == .none) unnamed: { + if (ty.is(.@"enum") or ty.hasIncompleteSize()) break :unnamed; + if (ty.isAnonymousRecord(p.comp)) { + // An anonymous record appears as indirect fields on the parent + try p.record_buf.append(.{ + .name = try p.getAnonymousName(first_tok), + .ty = ty, + }); + const node = try p.addNode(.{ + .tag = .indirect_record_field_decl, + .ty = ty, + .data = undefined, + }); + try p.decl_buf.append(node); + try p.record.addFieldsFromAnonymous(p, ty); + break; // must be followed by a semicolon + } + try p.err(.missing_declaration); + } else { + const interned_name = if (name_tok != 0) try p.comp.intern(p.tokSlice(name_tok)) else try p.getAnonymousName(first_tok); + try p.record_buf.append(.{ + .name = interned_name, + .ty = ty, + .name_tok = name_tok, + .bit_width = bits, + }); + if (name_tok != 0) try p.record.addField(p, interned_name, name_tok); + const node = try p.addNode(.{ + .tag = .record_field_decl, + .ty = ty, + .data = .{ .decl = .{ .name = name_tok, .node = bits_node } }, + }); + try p.decl_buf.append(node); + } + + if (ty.isFunc()) { + try p.errTok(.func_field, first_tok); + } else if (ty.is(.variable_len_array)) { + try p.errTok(.vla_field, first_tok); + } else if (ty.is(.incomplete_array)) { + if (p.record.kind == .keyword_union) { + try p.errTok(.flexible_in_union, first_tok); + } + if (p.record.flexible_field) |some| { + if (p.record.kind == .keyword_struct) { + try p.errTok(.flexible_non_final, some); + } + } + p.record.flexible_field = first_tok; + } else if (ty.specifier != .invalid and ty.hasIncompleteSize()) { + try p.errStr(.field_incomplete_ty, first_tok, try p.typeStr(ty)); + } else if (p.record.flexible_field) |some| { + if (some != first_tok and p.record.kind == .keyword_struct) try p.errTok(.flexible_non_final, some); + } + if (p.eatToken(.comma) == null) break; + } + + if (p.eatToken(.semicolon) == null) { + const tok_id = p.tok_ids[p.tok_i]; + if (tok_id == .r_brace) { + try p.err(.missing_semicolon); + } else { + return p.errExpectedToken(.semicolon, tok_id); + } + } + + return true; +} + +/// specQual : (typeSpec | typeQual | alignSpec)+ +fn specQual(p: *Parser) Error!?Type { + var spec: Type.Builder = .{}; + if (try p.typeSpec(&spec)) { + return try spec.finish(p); + } + return null; +} + +/// enumSpec +/// : keyword_enum IDENTIFIER? (: typeName)? { enumerator (',' enumerator)? ',') } +/// | keyword_enum IDENTIFIER (: typeName)? +fn enumSpec(p: *Parser) Error!Type { + const enum_tok = p.tok_i; + p.tok_i += 1; + const attr_buf_top = p.attr_buf.len; + defer p.attr_buf.len = attr_buf_top; + try p.attributeSpecifier(); + + const maybe_ident = try p.eatIdentifier(); + const fixed_ty = if (p.eatToken(.colon)) |colon| fixed: { + const fixed = (try p.typeName()) orelse { + if (p.record.kind != .invalid) { + // This is a bit field. + p.tok_i -= 1; + break :fixed null; + } + try p.err(.expected_type); + try p.errTok(.enum_fixed, colon); + break :fixed null; + }; + try p.errTok(.enum_fixed, colon); + break :fixed fixed; + } else null; + + const l_brace = p.eatToken(.l_brace) orelse { + const ident = maybe_ident orelse { + try p.err(.ident_or_l_brace); + return error.ParsingFailed; + }; + // check if this is a reference to a previous type + const interned_name = try p.comp.intern(p.tokSlice(ident)); + if (try p.syms.findTag(p, interned_name, .keyword_enum, ident, p.tok_ids[p.tok_i])) |prev| { + try p.checkEnumFixedTy(fixed_ty, ident, prev); + return prev.ty; + } else { + // this is a forward declaration, create a new enum Type. + const enum_ty = try Type.Enum.create(p.arena, interned_name, fixed_ty); + const ty = try Attribute.applyTypeAttributes(p, .{ + .specifier = .@"enum", + .data = .{ .@"enum" = enum_ty }, + }, attr_buf_top, null); + try p.syms.syms.append(p.gpa, .{ + .kind = .@"enum", + .name = interned_name, + .tok = ident, + .ty = ty, + .val = .{}, + }); + try p.decl_buf.append(try p.addNode(.{ + .tag = .enum_forward_decl, + .ty = ty, + .data = .{ .decl_ref = ident }, + })); + return ty; + } + }; + + var done = false; + errdefer if (!done) p.skipTo(.r_brace); + + // Get forward declared type or create a new one + var defined = false; + const enum_ty: *Type.Enum = if (maybe_ident) |ident| enum_ty: { + const ident_str = p.tokSlice(ident); + const interned_name = try p.comp.intern(ident_str); + if (try p.syms.defineTag(p, interned_name, .keyword_enum, ident)) |prev| { + const enum_ty = prev.ty.get(.@"enum").?.data.@"enum"; + if (!enum_ty.isIncomplete() and !enum_ty.fixed) { + // if the enum isn't incomplete, this is a redefinition + try p.errStr(.redefinition, ident, ident_str); + try p.errTok(.previous_definition, prev.tok); + } else { + try p.checkEnumFixedTy(fixed_ty, ident, prev); + defined = true; + break :enum_ty enum_ty; + } + } + break :enum_ty try Type.Enum.create(p.arena, interned_name, fixed_ty); + } else try Type.Enum.create(p.arena, try p.getAnonymousName(enum_tok), fixed_ty); + + // reserve space for this enum + try p.decl_buf.append(.none); + const decl_buf_top = p.decl_buf.items.len; + const list_buf_top = p.list_buf.items.len; + const enum_buf_top = p.enum_buf.items.len; + errdefer p.decl_buf.items.len = decl_buf_top - 1; + defer { + p.decl_buf.items.len = decl_buf_top; + p.list_buf.items.len = list_buf_top; + p.enum_buf.items.len = enum_buf_top; + } + + const sym_stack_top = p.syms.syms.len; + var e = Enumerator.init(fixed_ty); + while (try p.enumerator(&e)) |field_and_node| { + try p.enum_buf.append(field_and_node.field); + try p.list_buf.append(field_and_node.node); + if (p.eatToken(.comma) == null) break; + } + + if (p.enum_buf.items.len == enum_buf_top) try p.err(.empty_enum); + try p.expectClosing(l_brace, .r_brace); + done = true; + try p.attributeSpecifier(); + + const ty = try Attribute.applyTypeAttributes(p, .{ + .specifier = .@"enum", + .data = .{ .@"enum" = enum_ty }, + }, attr_buf_top, null); + if (!enum_ty.fixed) { + const tag_specifier = try e.getTypeSpecifier(p, ty.enumIsPacked(p.comp), maybe_ident orelse enum_tok); + enum_ty.tag_ty = .{ .specifier = tag_specifier }; + } + + const enum_fields = p.enum_buf.items[enum_buf_top..]; + const field_nodes = p.list_buf.items[list_buf_top..]; + + if (fixed_ty == null) { + const vals = p.syms.syms.items(.val)[sym_stack_top..]; + const types = p.syms.syms.items(.ty)[sym_stack_top..]; + + for (enum_fields, 0..) |*field, i| { + if (field.ty.eql(Type.int, p.comp, false)) continue; + + var res = Result{ .node = field.node, .ty = field.ty, .val = vals[i] }; + const dest_ty = if (p.comp.fixedEnumTagSpecifier()) |some| + Type{ .specifier = some } + else if (res.intFitsInType(p, Type.int)) + Type.int + else if (!res.ty.eql(enum_ty.tag_ty, p.comp, false)) + enum_ty.tag_ty + else + continue; + + vals[i].intCast(field.ty, dest_ty, p.comp); + types[i] = dest_ty; + p.nodes.items(.ty)[@intFromEnum(field_nodes[i])] = dest_ty; + field.ty = dest_ty; + res.ty = dest_ty; + + if (res.node != .none) { + try res.implicitCast(p, .int_cast); + field.node = res.node; + p.nodes.items(.data)[@intFromEnum(field_nodes[i])].decl.node = res.node; + } + } + } + + enum_ty.fields = try p.arena.dupe(Type.Enum.Field, enum_fields); + + // declare a symbol for the type + if (maybe_ident != null and !defined) { + try p.syms.syms.append(p.gpa, .{ + .kind = .@"enum", + .name = enum_ty.name, + .ty = ty, + .tok = maybe_ident.?, + .val = .{}, + }); + } + + // finish by creating a node + var node: Tree.Node = .{ .tag = .enum_decl_two, .ty = ty, .data = .{ + .bin = .{ .lhs = .none, .rhs = .none }, + } }; + switch (field_nodes.len) { + 0 => {}, + 1 => node.data = .{ .bin = .{ .lhs = field_nodes[0], .rhs = .none } }, + 2 => node.data = .{ .bin = .{ .lhs = field_nodes[0], .rhs = field_nodes[1] } }, + else => { + node.tag = .enum_decl; + node.data = .{ .range = try p.addList(field_nodes) }; + }, + } + p.decl_buf.items[decl_buf_top - 1] = try p.addNode(node); + if (p.func.ty == null) { + _ = p.tentative_defs.remove(enum_ty.name); + } + return ty; +} + +fn checkEnumFixedTy(p: *Parser, fixed_ty: ?Type, ident_tok: TokenIndex, prev: Symbol) !void { + const enum_ty = prev.ty.get(.@"enum").?.data.@"enum"; + if (fixed_ty) |some| { + if (!enum_ty.fixed) { + try p.errTok(.enum_prev_nonfixed, ident_tok); + try p.errTok(.previous_definition, prev.tok); + return error.ParsingFailed; + } + + if (!enum_ty.tag_ty.eql(some, p.comp, false)) { + const str = try p.typePairStrExtra(some, " (was ", enum_ty.tag_ty); + try p.errStr(.enum_different_explicit_ty, ident_tok, str); + try p.errTok(.previous_definition, prev.tok); + return error.ParsingFailed; + } + } else if (enum_ty.fixed) { + try p.errTok(.enum_prev_fixed, ident_tok); + try p.errTok(.previous_definition, prev.tok); + return error.ParsingFailed; + } +} + +const Enumerator = struct { + res: Result, + num_positive_bits: usize = 0, + num_negative_bits: usize = 0, + fixed: bool, + + fn init(fixed_ty: ?Type) Enumerator { + return .{ + .res = .{ + .ty = fixed_ty orelse .{ .specifier = .int }, + .val = .{ .tag = .unavailable }, + }, + .fixed = fixed_ty != null, + }; + } + + /// Increment enumerator value adjusting type if needed. + fn incr(e: *Enumerator, p: *Parser, tok: TokenIndex) !void { + e.res.node = .none; + const old_val = e.res.val; + if (old_val.tag == .unavailable) { + // First enumerator, set to 0 fits in all types. + e.res.val = Value.int(0); + return; + } + if (e.res.val.add(e.res.val, Value.int(1), e.res.ty, p.comp)) { + const byte_size = e.res.ty.sizeof(p.comp).?; + const bit_size: u8 = @intCast(if (e.res.ty.isUnsignedInt(p.comp)) byte_size * 8 else byte_size * 8 - 1); + if (e.fixed) { + try p.errStr(.enum_not_representable_fixed, tok, try p.typeStr(e.res.ty)); + return; + } + const new_ty = if (p.comp.nextLargestIntSameSign(e.res.ty)) |larger| blk: { + try p.errTok(.enumerator_overflow, tok); + break :blk larger; + } else blk: { + try p.errExtra(.enum_not_representable, tok, .{ .pow_2_as_string = bit_size }); + break :blk Type{ .specifier = .ulong_long }; + }; + e.res.ty = new_ty; + _ = e.res.val.add(old_val, Value.int(1), e.res.ty, p.comp); + } + } + + /// Set enumerator value to specified value. + fn set(e: *Enumerator, p: *Parser, res: Result, tok: TokenIndex) !void { + if (res.ty.specifier == .invalid) return; + if (e.fixed and !res.ty.eql(e.res.ty, p.comp, false)) { + if (!res.intFitsInType(p, e.res.ty)) { + try p.errStr(.enum_not_representable_fixed, tok, try p.typeStr(e.res.ty)); + return error.ParsingFailed; + } + var copy = res; + copy.ty = e.res.ty; + try copy.implicitCast(p, .int_cast); + e.res = copy; + } else { + e.res = res; + try e.res.intCast(p, e.res.ty.integerPromotion(p.comp), tok); + } + } + + fn getTypeSpecifier(e: *const Enumerator, p: *Parser, is_packed: bool, tok: TokenIndex) !Type.Specifier { + if (p.comp.fixedEnumTagSpecifier()) |tag_specifier| return tag_specifier; + + const char_width = (Type{ .specifier = .schar }).sizeof(p.comp).? * 8; + const short_width = (Type{ .specifier = .short }).sizeof(p.comp).? * 8; + const int_width = (Type{ .specifier = .int }).sizeof(p.comp).? * 8; + if (e.num_negative_bits > 0) { + if (is_packed and e.num_negative_bits <= char_width and e.num_positive_bits < char_width) { + return .schar; + } else if (is_packed and e.num_negative_bits <= short_width and e.num_positive_bits < short_width) { + return .short; + } else if (e.num_negative_bits <= int_width and e.num_positive_bits < int_width) { + return .int; + } + const long_width = (Type{ .specifier = .long }).sizeof(p.comp).? * 8; + if (e.num_negative_bits <= long_width and e.num_positive_bits < long_width) { + return .long; + } + const long_long_width = (Type{ .specifier = .long_long }).sizeof(p.comp).? * 8; + if (e.num_negative_bits > long_long_width or e.num_positive_bits >= long_long_width) { + try p.errTok(.enum_too_large, tok); + } + return .long_long; + } + if (is_packed and e.num_positive_bits <= char_width) { + return .uchar; + } else if (is_packed and e.num_positive_bits <= short_width) { + return .ushort; + } else if (e.num_positive_bits <= int_width) { + return .uint; + } else if (e.num_positive_bits <= (Type{ .specifier = .long }).sizeof(p.comp).? * 8) { + return .ulong; + } + return .ulong_long; + } +}; + +const EnumFieldAndNode = struct { field: Type.Enum.Field, node: NodeIndex }; + +/// enumerator : IDENTIFIER ('=' integerConstExpr) +fn enumerator(p: *Parser, e: *Enumerator) Error!?EnumFieldAndNode { + _ = try p.pragma(); + const name_tok = (try p.eatIdentifier()) orelse { + if (p.tok_ids[p.tok_i] == .r_brace) return null; + try p.err(.expected_identifier); + p.skipTo(.r_brace); + return error.ParsingFailed; + }; + const attr_buf_top = p.attr_buf.len; + defer p.attr_buf.len = attr_buf_top; + try p.attributeSpecifier(); + + const err_start = p.comp.diag.list.items.len; + if (p.eatToken(.equal)) |_| { + const specified = try p.integerConstExpr(.gnu_folding_extension); + if (specified.val.tag == .unavailable) { + try p.errTok(.enum_val_unavailable, name_tok + 2); + try e.incr(p, name_tok); + } else { + try e.set(p, specified, name_tok); + } + } else { + try e.incr(p, name_tok); + } + + var res = e.res; + res.ty = try Attribute.applyEnumeratorAttributes(p, res.ty, attr_buf_top); + + if (res.ty.isUnsignedInt(p.comp) or res.val.compare(.gte, Value.int(0), res.ty, p.comp)) { + e.num_positive_bits = @max(e.num_positive_bits, res.val.minUnsignedBits(res.ty, p.comp)); + } else { + e.num_negative_bits = @max(e.num_negative_bits, res.val.minSignedBits(res.ty, p.comp)); + } + + if (err_start == p.comp.diag.list.items.len) { + // only do these warnings if we didn't already warn about overflow or non-representable values + if (e.res.val.compare(.lt, Value.int(0), e.res.ty, p.comp)) { + const val = e.res.val.getInt(i64); + if (val < (Type{ .specifier = .int }).minInt(p.comp)) { + try p.errExtra(.enumerator_too_small, name_tok, .{ + .signed = val, + }); + } + } else { + const val = e.res.val.getInt(u64); + if (val > (Type{ .specifier = .int }).maxInt(p.comp)) { + try p.errExtra(.enumerator_too_large, name_tok, .{ + .unsigned = val, + }); + } + } + } + + const interned_name = try p.comp.intern(p.tokSlice(name_tok)); + try p.syms.defineEnumeration(p, interned_name, res.ty, name_tok, e.res.val); + const node = try p.addNode(.{ + .tag = .enum_field_decl, + .ty = res.ty, + .data = .{ .decl = .{ + .name = name_tok, + .node = res.node, + } }, + }); + return EnumFieldAndNode{ .field = .{ + .name = interned_name, + .ty = res.ty, + .name_tok = name_tok, + .node = res.node, + }, .node = node }; +} + +/// typeQual : keyword_const | keyword_restrict | keyword_volatile | keyword_atomic +fn typeQual(p: *Parser, b: *Type.Qualifiers.Builder) Error!bool { + var any = false; + while (true) { + switch (p.tok_ids[p.tok_i]) { + .keyword_restrict, .keyword_restrict1, .keyword_restrict2 => { + if (b.restrict != null) + try p.errStr(.duplicate_decl_spec, p.tok_i, "restrict") + else + b.restrict = p.tok_i; + }, + .keyword_const, .keyword_const1, .keyword_const2 => { + if (b.@"const" != null) + try p.errStr(.duplicate_decl_spec, p.tok_i, "const") + else + b.@"const" = p.tok_i; + }, + .keyword_volatile, .keyword_volatile1, .keyword_volatile2 => { + if (b.@"volatile" != null) + try p.errStr(.duplicate_decl_spec, p.tok_i, "volatile") + else + b.@"volatile" = p.tok_i; + }, + .keyword_atomic => { + // _Atomic(typeName) instead of just _Atomic + if (p.tok_ids[p.tok_i + 1] == .l_paren) break; + if (b.atomic != null) + try p.errStr(.duplicate_decl_spec, p.tok_i, "atomic") + else + b.atomic = p.tok_i; + }, + else => break, + } + p.tok_i += 1; + any = true; + } + return any; +} + +const Declarator = struct { + name: TokenIndex, + ty: Type, + func_declarator: ?TokenIndex = null, + old_style_func: ?TokenIndex = null, +}; +const DeclaratorKind = enum { normal, abstract, param, record }; + +/// declarator : pointer? (IDENTIFIER | '(' declarator ')') directDeclarator* +/// abstractDeclarator +/// : pointer? ('(' abstractDeclarator ')')? directAbstractDeclarator* +fn declarator( + p: *Parser, + base_type: Type, + kind: DeclaratorKind, +) Error!?Declarator { + const start = p.tok_i; + var d = Declarator{ .name = 0, .ty = try p.pointer(base_type) }; + if (base_type.is(.auto_type) and !d.ty.is(.auto_type)) { + try p.errTok(.auto_type_requires_plain_declarator, start); + return error.ParsingFailed; + } + + const maybe_ident = p.tok_i; + if (kind != .abstract and (try p.eatIdentifier()) != null) { + d.name = maybe_ident; + const combine_tok = p.tok_i; + d.ty = try p.directDeclarator(d.ty, &d, kind); + try d.ty.validateCombinedType(p, combine_tok); + return d; + } else if (p.eatToken(.l_paren)) |l_paren| blk: { + var res = (try p.declarator(.{ .specifier = .void }, kind)) orelse { + p.tok_i = l_paren; + break :blk; + }; + try p.expectClosing(l_paren, .r_paren); + const suffix_start = p.tok_i; + const outer = try p.directDeclarator(d.ty, &d, kind); + try res.ty.combine(outer); + try res.ty.validateCombinedType(p, suffix_start); + res.old_style_func = d.old_style_func; + return res; + } + + const expected_ident = p.tok_i; + + d.ty = try p.directDeclarator(d.ty, &d, kind); + + if (kind == .normal and !d.ty.isEnumOrRecord()) { + try p.errTok(.expected_ident_or_l_paren, expected_ident); + return error.ParsingFailed; + } + try d.ty.validateCombinedType(p, expected_ident); + if (start == p.tok_i) return null; + return d; +} + +/// directDeclarator +/// : '[' typeQual* assignExpr? ']' directDeclarator? +/// | '[' keyword_static typeQual* assignExpr ']' directDeclarator? +/// | '[' typeQual+ keyword_static assignExpr ']' directDeclarator? +/// | '[' typeQual* '*' ']' directDeclarator? +/// | '(' paramDecls ')' directDeclarator? +/// | '(' (IDENTIFIER (',' IDENTIFIER))? ')' directDeclarator? +/// directAbstractDeclarator +/// : '[' typeQual* assignExpr? ']' +/// | '[' keyword_static typeQual* assignExpr ']' +/// | '[' typeQual+ keyword_static assignExpr ']' +/// | '[' '*' ']' +/// | '(' paramDecls? ')' +fn directDeclarator(p: *Parser, base_type: Type, d: *Declarator, kind: DeclaratorKind) Error!Type { + if (p.eatToken(.l_bracket)) |l_bracket| { + if (p.tok_ids[p.tok_i] == .l_bracket) { + switch (kind) { + .normal, .record => if (p.comp.langopts.standard.atLeast(.c2x)) { + p.tok_i -= 1; + return base_type; + }, + .param, .abstract => {}, + } + try p.err(.expected_expr); + return error.ParsingFailed; + } + var res_ty = Type{ + // so that we can get any restrict type that might be present + .specifier = .pointer, + }; + var quals = Type.Qualifiers.Builder{}; + + var got_quals = try p.typeQual(&quals); + var static = p.eatToken(.keyword_static); + if (static != null and !got_quals) got_quals = try p.typeQual(&quals); + var star = p.eatToken(.asterisk); + const size_tok = p.tok_i; + + const const_decl_folding = p.const_decl_folding; + p.const_decl_folding = .gnu_vla_folding_extension; + const size = if (star) |_| Result{} else try p.assignExpr(); + p.const_decl_folding = const_decl_folding; + + try p.expectClosing(l_bracket, .r_bracket); + + if (star != null and static != null) { + try p.errTok(.invalid_static_star, static.?); + static = null; + } + if (kind != .param) { + if (static != null) + try p.errTok(.static_non_param, l_bracket) + else if (got_quals) + try p.errTok(.array_qualifiers, l_bracket); + if (star) |some| try p.errTok(.star_non_param, some); + static = null; + quals = .{}; + star = null; + } else { + try quals.finish(p, &res_ty); + } + if (static) |_| try size.expect(p); + + if (base_type.is(.auto_type)) { + try p.errStr(.array_of_auto_type, d.name, p.tokSlice(d.name)); + return error.ParsingFailed; + } + const outer = try p.directDeclarator(base_type, d, kind); + var max_bits = p.comp.target.ptrBitWidth(); + if (max_bits > 61) max_bits = 61; + const max_bytes = (@as(u64, 1) << @truncate(max_bits)) - 1; + // `outer` is validated later so it may be invalid here + const outer_size = outer.sizeof(p.comp); + const max_elems = max_bytes / @max(1, outer_size orelse 1); + + if (!size.ty.isInt()) { + try p.errStr(.array_size_non_int, size_tok, try p.typeStr(size.ty)); + return error.ParsingFailed; + } + if (size.val.tag == .unavailable) { + if (size.node != .none) { + try p.errTok(.vla, size_tok); + if (p.func.ty == null and kind != .param and p.record.kind == .invalid) { + try p.errTok(.variable_len_array_file_scope, d.name); + } + const expr_ty = try p.arena.create(Type.Expr); + expr_ty.ty = .{ .specifier = .void }; + expr_ty.node = size.node; + res_ty.data = .{ .expr = expr_ty }; + res_ty.specifier = .variable_len_array; + + if (static) |some| try p.errTok(.useless_static, some); + } else if (star) |_| { + const elem_ty = try p.arena.create(Type); + elem_ty.* = .{ .specifier = .void }; + res_ty.data = .{ .sub_type = elem_ty }; + res_ty.specifier = .unspecified_variable_len_array; + } else { + const arr_ty = try p.arena.create(Type.Array); + arr_ty.elem = .{ .specifier = .void }; + arr_ty.len = 0; + res_ty.data = .{ .array = arr_ty }; + res_ty.specifier = .incomplete_array; + } + } else { + var size_val = size.val; + const size_t = p.comp.types.size; + if (size_val.isZero()) { + try p.errTok(.zero_length_array, l_bracket); + } else if (size_val.compare(.lt, Value.int(0), size_t, p.comp)) { + try p.errTok(.negative_array_size, l_bracket); + return error.ParsingFailed; + } + const arr_ty = try p.arena.create(Type.Array); + arr_ty.elem = .{ .specifier = .void }; + if (size_val.compare(.gt, Value.int(max_elems), size_t, p.comp)) { + try p.errTok(.array_too_large, l_bracket); + arr_ty.len = max_elems; + } else { + arr_ty.len = size_val.getInt(u64); + } + res_ty.data = .{ .array = arr_ty }; + res_ty.specifier = .array; + } + + try res_ty.combine(outer); + return res_ty; + } else if (p.eatToken(.l_paren)) |l_paren| { + d.func_declarator = l_paren; + + const func_ty = try p.arena.create(Type.Func); + func_ty.params = &.{}; + func_ty.return_type.specifier = .void; + var specifier: Type.Specifier = .func; + + if (p.eatToken(.ellipsis)) |_| { + try p.err(.param_before_var_args); + try p.expectClosing(l_paren, .r_paren); + var res_ty = Type{ .specifier = .func, .data = .{ .func = func_ty } }; + + const outer = try p.directDeclarator(base_type, d, kind); + try res_ty.combine(outer); + return res_ty; + } + + if (try p.paramDecls()) |params| { + func_ty.params = params; + if (p.eatToken(.ellipsis)) |_| specifier = .var_args_func; + } else if (p.tok_ids[p.tok_i] == .r_paren) { + specifier = .var_args_func; + } else if (p.tok_ids[p.tok_i] == .identifier or p.tok_ids[p.tok_i] == .extended_identifier) { + d.old_style_func = p.tok_i; + const param_buf_top = p.param_buf.items.len; + try p.syms.pushScope(p); + defer { + p.param_buf.items.len = param_buf_top; + p.syms.popScope(); + } + + specifier = .old_style_func; + while (true) { + const name_tok = try p.expectIdentifier(); + const interned_name = try p.comp.intern(p.tokSlice(name_tok)); + try p.syms.defineParam(p, interned_name, undefined, name_tok); + try p.param_buf.append(.{ + .name = interned_name, + .name_tok = name_tok, + .ty = .{ .specifier = .int }, + }); + if (p.eatToken(.comma) == null) break; + } + func_ty.params = try p.arena.dupe(Type.Func.Param, p.param_buf.items[param_buf_top..]); + } else { + try p.err(.expected_param_decl); + } + + try p.expectClosing(l_paren, .r_paren); + var res_ty = Type{ + .specifier = specifier, + .data = .{ .func = func_ty }, + }; + + const outer = try p.directDeclarator(base_type, d, kind); + try res_ty.combine(outer); + return res_ty; + } else return base_type; +} + +/// pointer : '*' typeQual* pointer? +fn pointer(p: *Parser, base_ty: Type) Error!Type { + var ty = base_ty; + while (p.eatToken(.asterisk)) |_| { + const elem_ty = try p.arena.create(Type); + elem_ty.* = ty; + ty = Type{ + .specifier = .pointer, + .data = .{ .sub_type = elem_ty }, + }; + var quals = Type.Qualifiers.Builder{}; + _ = try p.typeQual(&quals); + try quals.finish(p, &ty); + } + return ty; +} + +/// paramDecls : paramDecl (',' paramDecl)* (',' '...') +/// paramDecl : declSpec (declarator | abstractDeclarator) +fn paramDecls(p: *Parser) Error!?[]Type.Func.Param { + // TODO warn about visibility of types declared here + const param_buf_top = p.param_buf.items.len; + defer p.param_buf.items.len = param_buf_top; + try p.syms.pushScope(p); + defer p.syms.popScope(); + + while (true) { + const attr_buf_top = p.attr_buf.len; + defer p.attr_buf.len = attr_buf_top; + const param_decl_spec = if (try p.declSpec()) |some| + some + else if (p.param_buf.items.len == param_buf_top) + return null + else blk: { + var spec: Type.Builder = .{}; + break :blk DeclSpec{ .ty = try spec.finish(p) }; + }; + + var name_tok: TokenIndex = 0; + const first_tok = p.tok_i; + var param_ty = param_decl_spec.ty; + if (try p.declarator(param_decl_spec.ty, .param)) |some| { + if (some.old_style_func) |tok_i| try p.errTok(.invalid_old_style_params, tok_i); + try p.attributeSpecifier(); + + name_tok = some.name; + param_ty = some.ty; + if (some.name != 0) { + const interned_name = try p.comp.intern(p.tokSlice(name_tok)); + try p.syms.defineParam(p, interned_name, param_ty, name_tok); + } + } + param_ty = try Attribute.applyParameterAttributes(p, param_ty, attr_buf_top, .alignas_on_param); + + if (param_ty.isFunc()) { + // params declared as functions are converted to function pointers + const elem_ty = try p.arena.create(Type); + elem_ty.* = param_ty; + param_ty = Type{ + .specifier = .pointer, + .data = .{ .sub_type = elem_ty }, + }; + } else if (param_ty.isArray()) { + // params declared as arrays are converted to pointers + param_ty.decayArray(); + } else if (param_ty.is(.void)) { + // validate void parameters + if (p.param_buf.items.len == param_buf_top) { + if (p.tok_ids[p.tok_i] != .r_paren) { + try p.err(.void_only_param); + if (param_ty.anyQual()) try p.err(.void_param_qualified); + return error.ParsingFailed; + } + return &[0]Type.Func.Param{}; + } + try p.err(.void_must_be_first_param); + return error.ParsingFailed; + } + + try param_decl_spec.validateParam(p, ¶m_ty); + try p.param_buf.append(.{ + .name = if (name_tok == 0) .empty else try p.comp.intern(p.tokSlice(name_tok)), + .name_tok = if (name_tok == 0) first_tok else name_tok, + .ty = param_ty, + }); + + if (p.eatToken(.comma) == null) break; + if (p.tok_ids[p.tok_i] == .ellipsis) break; + } + return try p.arena.dupe(Type.Func.Param, p.param_buf.items[param_buf_top..]); +} + +/// typeName : specQual abstractDeclarator +fn typeName(p: *Parser) Error!?Type { + const attr_buf_top = p.attr_buf.len; + defer p.attr_buf.len = attr_buf_top; + var ty = (try p.specQual()) orelse return null; + if (try p.declarator(ty, .abstract)) |some| { + if (some.old_style_func) |tok_i| try p.errTok(.invalid_old_style_params, tok_i); + return try Attribute.applyTypeAttributes(p, some.ty, attr_buf_top, .align_ignored); + } + return try Attribute.applyTypeAttributes(p, ty, attr_buf_top, .align_ignored); +} + +/// initializer +/// : assignExpr +/// | '{' initializerItems '}' +fn initializer(p: *Parser, init_ty: Type) Error!Result { + // fast path for non-braced initializers + if (p.tok_ids[p.tok_i] != .l_brace) { + const tok = p.tok_i; + var res = try p.assignExpr(); + try res.expect(p); + if (try p.coerceArrayInit(&res, tok, init_ty)) return res; + try p.coerceInit(&res, tok, init_ty); + return res; + } + if (init_ty.is(.auto_type)) { + try p.err(.auto_type_with_init_list); + return error.ParsingFailed; + } + + var il: InitList = .{}; + defer il.deinit(p.gpa); + + _ = try p.initializerItem(&il, init_ty); + + const res = try p.convertInitList(il, init_ty); + var res_ty = p.nodes.items(.ty)[@intFromEnum(res)]; + res_ty.qual = init_ty.qual; + return Result{ .ty = res_ty, .node = res }; +} + +/// initializerItems : designation? initializer (',' designation? initializer)* ','? +/// designation : designator+ '=' +/// designator +/// : '[' integerConstExpr ']' +/// | '.' identifier +fn initializerItem(p: *Parser, il: *InitList, init_ty: Type) Error!bool { + const l_brace = p.eatToken(.l_brace) orelse { + const tok = p.tok_i; + var res = try p.assignExpr(); + if (res.empty(p)) return false; + + const arr = try p.coerceArrayInit(&res, tok, init_ty); + if (!arr) try p.coerceInit(&res, tok, init_ty); + if (il.tok != 0) { + try p.errTok(.initializer_overrides, tok); + try p.errTok(.previous_initializer, il.tok); + } + il.node = res.node; + il.tok = tok; + return true; + }; + + const is_scalar = init_ty.isScalar(); + const is_complex = init_ty.isComplex(); + const scalar_inits_needed: usize = if (is_complex) 2 else 1; + if (p.eatToken(.r_brace)) |_| { + if (is_scalar) try p.errTok(.empty_scalar_init, l_brace); + if (il.tok != 0) { + try p.errTok(.initializer_overrides, l_brace); + try p.errTok(.previous_initializer, il.tok); + } + il.node = .none; + il.tok = l_brace; + return true; + } + + var count: u64 = 0; + var warned_excess = false; + var is_str_init = false; + var index_hint: ?u64 = null; + while (true) : (count += 1) { + errdefer p.skipTo(.r_brace); + + var first_tok = p.tok_i; + var cur_ty = init_ty; + var cur_il = il; + var designation = false; + var cur_index_hint: ?u64 = null; + while (true) { + if (p.eatToken(.l_bracket)) |l_bracket| { + if (!cur_ty.isArray()) { + try p.errStr(.invalid_array_designator, l_bracket, try p.typeStr(cur_ty)); + return error.ParsingFailed; + } + const expr_tok = p.tok_i; + const index_res = try p.integerConstExpr(.gnu_folding_extension); + try p.expectClosing(l_bracket, .r_bracket); + + if (index_res.val.tag == .unavailable) { + try p.errTok(.expected_integer_constant_expr, expr_tok); + return error.ParsingFailed; + } else if (index_res.val.compare(.lt, index_res.val.zero(), index_res.ty, p.comp)) { + try p.errExtra(.negative_array_designator, l_bracket + 1, .{ + .signed = index_res.val.signExtend(index_res.ty, p.comp), + }); + return error.ParsingFailed; + } + + const max_len = cur_ty.arrayLen() orelse std.math.maxInt(usize); + if (index_res.val.data.int >= max_len) { + try p.errExtra(.oob_array_designator, l_bracket + 1, .{ .unsigned = index_res.val.data.int }); + return error.ParsingFailed; + } + const checked = index_res.val.getInt(u64); + cur_index_hint = cur_index_hint orelse checked; + + cur_il = try cur_il.find(p.gpa, checked); + cur_ty = cur_ty.elemType(); + designation = true; + } else if (p.eatToken(.period)) |period| { + const field_tok = try p.expectIdentifier(); + const field_str = p.tokSlice(field_tok); + const field_name = try p.comp.intern(field_str); + cur_ty = cur_ty.canonicalize(.standard); + if (!cur_ty.isRecord()) { + try p.errStr(.invalid_field_designator, period, try p.typeStr(cur_ty)); + return error.ParsingFailed; + } else if (!cur_ty.hasField(field_name)) { + try p.errStr(.no_such_field_designator, period, field_str); + return error.ParsingFailed; + } + + // TODO check if union already has field set + outer: while (true) { + for (cur_ty.data.record.fields, 0..) |f, i| { + if (f.isAnonymousRecord()) { + // Recurse into anonymous field if it has a field by the name. + if (!f.ty.hasField(field_name)) continue; + cur_ty = f.ty.canonicalize(.standard); + cur_il = try il.find(p.gpa, i); + cur_index_hint = cur_index_hint orelse i; + continue :outer; + } + if (field_name == f.name) { + cur_il = try cur_il.find(p.gpa, i); + cur_ty = f.ty; + cur_index_hint = cur_index_hint orelse i; + break :outer; + } + } + unreachable; // we already checked that the starting type has this field + } + designation = true; + } else break; + } + if (designation) index_hint = null; + defer index_hint = cur_index_hint orelse null; + + if (designation) _ = try p.expectToken(.equal); + + if (!designation and cur_ty.hasAttribute(.designated_init)) { + try p.err(.designated_init_needed); + } + + var saw = false; + if (is_str_init and p.isStringInit(init_ty)) { + // discard further strings + var tmp_il = InitList{}; + defer tmp_il.deinit(p.gpa); + saw = try p.initializerItem(&tmp_il, .{ .specifier = .void }); + } else if (count == 0 and p.isStringInit(init_ty)) { + is_str_init = true; + saw = try p.initializerItem(il, init_ty); + } else if (is_scalar and count >= scalar_inits_needed) { + // discard further scalars + var tmp_il = InitList{}; + defer tmp_il.deinit(p.gpa); + saw = try p.initializerItem(&tmp_il, .{ .specifier = .void }); + } else if (p.tok_ids[p.tok_i] == .l_brace) { + if (designation) { + // designation overrides previous value, let existing mechanism handle it + saw = try p.initializerItem(cur_il, cur_ty); + } else if (try p.findAggregateInitializer(&cur_il, &cur_ty, &index_hint)) { + saw = try p.initializerItem(cur_il, cur_ty); + } else { + // discard further values + var tmp_il = InitList{}; + defer tmp_il.deinit(p.gpa); + saw = try p.initializerItem(&tmp_il, .{ .specifier = .void }); + if (!warned_excess) try p.errTok(if (init_ty.isArray()) .excess_array_init else .excess_struct_init, first_tok); + warned_excess = true; + } + } else single_item: { + first_tok = p.tok_i; + var res = try p.assignExpr(); + saw = !res.empty(p); + if (!saw) break :single_item; + + excess: { + if (index_hint) |*hint| { + if (try p.findScalarInitializerAt(&cur_il, &cur_ty, res.ty, first_tok, hint)) break :excess; + } else if (try p.findScalarInitializer(&cur_il, &cur_ty, res.ty, first_tok)) break :excess; + + if (designation) break :excess; + if (!warned_excess) try p.errTok(if (init_ty.isArray()) .excess_array_init else .excess_struct_init, first_tok); + warned_excess = true; + + break :single_item; + } + + const arr = try p.coerceArrayInit(&res, first_tok, cur_ty); + if (!arr) try p.coerceInit(&res, first_tok, cur_ty); + if (cur_il.tok != 0) { + try p.errTok(.initializer_overrides, first_tok); + try p.errTok(.previous_initializer, cur_il.tok); + } + cur_il.node = res.node; + cur_il.tok = first_tok; + } + + if (!saw) { + if (designation) { + try p.err(.expected_expr); + return error.ParsingFailed; + } + break; + } else if (count == 1) { + if (is_str_init) try p.errTok(.excess_str_init, first_tok); + if (is_scalar and !is_complex) try p.errTok(.excess_scalar_init, first_tok); + } else if (count == 2) { + if (is_scalar and is_complex) try p.errTok(.excess_scalar_init, first_tok); + } + + if (p.eatToken(.comma) == null) break; + } + try p.expectClosing(l_brace, .r_brace); + + if (is_complex and count == 1) { // count of 1 means we saw exactly 2 items in the initializer list + try p.errTok(.complex_component_init, l_brace); + } + if (is_scalar or is_str_init) return true; + if (il.tok != 0) { + try p.errTok(.initializer_overrides, l_brace); + try p.errTok(.previous_initializer, il.tok); + } + il.node = .none; + il.tok = l_brace; + return true; +} + +/// Returns true if the value is unused. +fn findScalarInitializerAt(p: *Parser, il: **InitList, ty: *Type, actual_ty: Type, first_tok: TokenIndex, start_index: *u64) Error!bool { + if (ty.isArray()) { + if (il.*.node != .none) return false; + start_index.* += 1; + + const arr_ty = ty.*; + const elem_count = arr_ty.arrayLen() orelse std.math.maxInt(u64); + if (elem_count == 0) { + try p.errTok(.empty_aggregate_init_braces, first_tok); + return error.ParsingFailed; + } + const elem_ty = arr_ty.elemType(); + const arr_il = il.*; + if (start_index.* < elem_count) { + ty.* = elem_ty; + il.* = try arr_il.find(p.gpa, start_index.*); + _ = try p.findScalarInitializer(il, ty, actual_ty, first_tok); + return true; + } + return false; + } else if (ty.get(.@"struct")) |struct_ty| { + if (il.*.node != .none) return false; + start_index.* += 1; + + const fields = struct_ty.data.record.fields; + if (fields.len == 0) { + try p.errTok(.empty_aggregate_init_braces, first_tok); + return error.ParsingFailed; + } + const struct_il = il.*; + if (start_index.* < fields.len) { + const field = fields[@intCast(start_index.*)]; + ty.* = field.ty; + il.* = try struct_il.find(p.gpa, start_index.*); + _ = try p.findScalarInitializer(il, ty, actual_ty, first_tok); + return true; + } + return false; + } else if (ty.get(.@"union")) |_| { + return false; + } + return il.*.node == .none; +} + +/// Returns true if the value is unused. +fn findScalarInitializer(p: *Parser, il: **InitList, ty: *Type, actual_ty: Type, first_tok: TokenIndex) Error!bool { + if (ty.isArray() or ty.isComplex()) { + if (il.*.node != .none) return false; + const start_index = il.*.list.items.len; + var index = if (start_index != 0) il.*.list.items[start_index - 1].index else start_index; + + const arr_ty = ty.*; + const elem_count: u64 = arr_ty.expectedInitListSize() orelse std.math.maxInt(u64); + if (elem_count == 0) { + try p.errTok(.empty_aggregate_init_braces, first_tok); + return error.ParsingFailed; + } + const elem_ty = arr_ty.elemType(); + const arr_il = il.*; + while (index < elem_count) : (index += 1) { + ty.* = elem_ty; + il.* = try arr_il.find(p.gpa, index); + if (il.*.node == .none and actual_ty.eql(elem_ty, p.comp, false)) return true; + if (try p.findScalarInitializer(il, ty, actual_ty, first_tok)) return true; + } + return false; + } else if (ty.get(.@"struct")) |struct_ty| { + if (il.*.node != .none) return false; + if (actual_ty.eql(ty.*, p.pp.comp, false)) return true; + const start_index = il.*.list.items.len; + var index = if (start_index != 0) il.*.list.items[start_index - 1].index + 1 else start_index; + + const fields = struct_ty.data.record.fields; + if (fields.len == 0) { + try p.errTok(.empty_aggregate_init_braces, first_tok); + return error.ParsingFailed; + } + const struct_il = il.*; + while (index < fields.len) : (index += 1) { + const field = fields[@intCast(index)]; + ty.* = field.ty; + il.* = try struct_il.find(p.gpa, index); + if (il.*.node == .none and actual_ty.eql(field.ty, p.comp, false)) return true; + if (try p.findScalarInitializer(il, ty, actual_ty, first_tok)) return true; + } + return false; + } else if (ty.get(.@"union")) |union_ty| { + if (il.*.node != .none) return false; + if (actual_ty.eql(ty.*, p.pp.comp, false)) return true; + if (union_ty.data.record.fields.len == 0) { + try p.errTok(.empty_aggregate_init_braces, first_tok); + return error.ParsingFailed; + } + ty.* = union_ty.data.record.fields[0].ty; + il.* = try il.*.find(p.gpa, 0); + // if (il.*.node == .none and actual_ty.eql(ty, p.pp.comp, false)) return true; + if (try p.findScalarInitializer(il, ty, actual_ty, first_tok)) return true; + return false; + } + return il.*.node == .none; +} + +fn findAggregateInitializer(p: *Parser, il: **InitList, ty: *Type, start_index: *?u64) Error!bool { + if (ty.isArray()) { + if (il.*.node != .none) return false; + const list_index = il.*.list.items.len; + const index = if (start_index.*) |*some| blk: { + some.* += 1; + break :blk some.*; + } else if (list_index != 0) + il.*.list.items[list_index - 1].index + 1 + else + list_index; + + const arr_ty = ty.*; + const elem_count = arr_ty.arrayLen() orelse std.math.maxInt(u64); + const elem_ty = arr_ty.elemType(); + if (index < elem_count) { + ty.* = elem_ty; + il.* = try il.*.find(p.gpa, index); + return true; + } + return false; + } else if (ty.get(.@"struct")) |struct_ty| { + if (il.*.node != .none) return false; + const list_index = il.*.list.items.len; + const index = if (start_index.*) |*some| blk: { + some.* += 1; + break :blk some.*; + } else if (list_index != 0) + il.*.list.items[list_index - 1].index + 1 + else + list_index; + + const field_count = struct_ty.data.record.fields.len; + if (index < field_count) { + ty.* = struct_ty.data.record.fields[@intCast(index)].ty; + il.* = try il.*.find(p.gpa, index); + return true; + } + return false; + } else if (ty.get(.@"union")) |union_ty| { + if (il.*.node != .none) return false; + if (start_index.*) |_| return false; // overrides + if (union_ty.data.record.fields.len == 0) return false; + + ty.* = union_ty.data.record.fields[0].ty; + il.* = try il.*.find(p.gpa, 0); + return true; + } else { + try p.err(.too_many_scalar_init_braces); + return il.*.node == .none; + } +} + +fn coerceArrayInit(p: *Parser, item: *Result, tok: TokenIndex, target: Type) !bool { + if (!target.isArray()) return false; + + const is_str_lit = p.nodeIs(item.node, .string_literal_expr); + if (!is_str_lit and !p.nodeIs(item.node, .compound_literal_expr) or !item.ty.isArray()) { + try p.errTok(.array_init_str, tok); + return true; // do not do further coercion + } + + const target_spec = target.elemType().canonicalize(.standard).specifier; + const item_spec = item.ty.elemType().canonicalize(.standard).specifier; + + const compatible = target.elemType().eql(item.ty.elemType(), p.comp, false) or + (is_str_lit and item_spec == .char and (target_spec == .uchar or target_spec == .schar)) or + (is_str_lit and item_spec == .uchar and (target_spec == .uchar or target_spec == .schar or target_spec == .char)); + if (!compatible) { + const e_msg = " with array of type "; + try p.errStr(.incompatible_array_init, tok, try p.typePairStrExtra(target, e_msg, item.ty)); + return true; // do not do further coercion + } + + if (target.get(.array)) |arr_ty| { + assert(item.ty.specifier == .array); + var len = item.ty.arrayLen().?; + const array_len = arr_ty.arrayLen().?; + if (is_str_lit) { + // the null byte of a string can be dropped + if (len - 1 > array_len) + try p.errTok(.str_init_too_long, tok); + } else if (len > array_len) { + try p.errStr( + .arr_init_too_long, + tok, + try p.typePairStrExtra(target, " with array of type ", item.ty), + ); + } + } + return true; +} + +fn coerceInit(p: *Parser, item: *Result, tok: TokenIndex, target: Type) !void { + if (target.is(.void)) return; // Do not do type coercion on excess items + + const node = item.node; + try item.lvalConversion(p); + if (target.is(.auto_type)) { + if (p.getNode(node, .member_access_expr) orelse p.getNode(node, .member_access_ptr_expr)) |member_node| { + if (Tree.isBitfield(p.nodes.slice(), member_node)) try p.errTok(.auto_type_from_bitfield, tok); + } + return; + } + + try item.coerce(p, target, tok, .init); +} + +fn isStringInit(p: *Parser, ty: Type) bool { + if (!ty.isArray() or !ty.elemType().isInt()) return false; + var i = p.tok_i; + while (true) : (i += 1) { + switch (p.tok_ids[i]) { + .l_paren => {}, + .string_literal, + .string_literal_utf_16, + .string_literal_utf_8, + .string_literal_utf_32, + .string_literal_wide, + => return true, + else => return false, + } + } +} + +/// Convert InitList into an AST +fn convertInitList(p: *Parser, il: InitList, init_ty: Type) Error!NodeIndex { + const is_complex = init_ty.isComplex(); + if (init_ty.isScalar() and !is_complex) { + if (il.node == .none) { + return p.addNode(.{ .tag = .default_init_expr, .ty = init_ty, .data = undefined }); + } + return il.node; + } else if (init_ty.is(.variable_len_array)) { + return error.ParsingFailed; // vla invalid, reported earlier + } else if (init_ty.isArray() or is_complex) { + if (il.node != .none) { + return il.node; + } + const list_buf_top = p.list_buf.items.len; + defer p.list_buf.items.len = list_buf_top; + + const elem_ty = init_ty.elemType(); + + const max_items: u64 = init_ty.expectedInitListSize() orelse std.math.maxInt(usize); + var start: u64 = 0; + for (il.list.items) |*init| { + if (init.index > start) { + const elem = try p.addNode(.{ + .tag = .array_filler_expr, + .ty = elem_ty, + .data = .{ .int = init.index - start }, + }); + try p.list_buf.append(elem); + } + start = init.index + 1; + + const elem = try p.convertInitList(init.list, elem_ty); + try p.list_buf.append(elem); + } + + var arr_init_node: Tree.Node = .{ + .tag = .array_init_expr_two, + .ty = init_ty, + .data = .{ .bin = .{ .lhs = .none, .rhs = .none } }, + }; + + if (init_ty.specifier == .incomplete_array) { + arr_init_node.ty.specifier = .array; + arr_init_node.ty.data.array.len = start; + } else if (init_ty.is(.incomplete_array)) { + const arr_ty = try p.arena.create(Type.Array); + arr_ty.* = .{ .elem = init_ty.elemType(), .len = start }; + arr_init_node.ty = .{ + .specifier = .array, + .data = .{ .array = arr_ty }, + }; + const attrs = init_ty.getAttributes(); + arr_init_node.ty = try arr_init_node.ty.withAttributes(p.arena, attrs); + } else if (start < max_items) { + const elem = try p.addNode(.{ + .tag = .array_filler_expr, + .ty = elem_ty, + .data = .{ .int = max_items - start }, + }); + try p.list_buf.append(elem); + } + + const items = p.list_buf.items[list_buf_top..]; + switch (items.len) { + 0 => {}, + 1 => arr_init_node.data.bin.lhs = items[0], + 2 => arr_init_node.data.bin = .{ .lhs = items[0], .rhs = items[1] }, + else => { + arr_init_node.tag = .array_init_expr; + arr_init_node.data = .{ .range = try p.addList(items) }; + }, + } + return try p.addNode(arr_init_node); + } else if (init_ty.get(.@"struct")) |struct_ty| { + assert(!struct_ty.hasIncompleteSize()); + if (il.node != .none) { + return il.node; + } + + const list_buf_top = p.list_buf.items.len; + defer p.list_buf.items.len = list_buf_top; + + var init_index: usize = 0; + for (struct_ty.data.record.fields, 0..) |f, i| { + if (init_index < il.list.items.len and il.list.items[init_index].index == i) { + const item = try p.convertInitList(il.list.items[init_index].list, f.ty); + try p.list_buf.append(item); + init_index += 1; + } else { + const item = try p.addNode(.{ .tag = .default_init_expr, .ty = f.ty, .data = undefined }); + try p.list_buf.append(item); + } + } + + var struct_init_node: Tree.Node = .{ + .tag = .struct_init_expr_two, + .ty = init_ty, + .data = .{ .bin = .{ .lhs = .none, .rhs = .none } }, + }; + const items = p.list_buf.items[list_buf_top..]; + switch (items.len) { + 0 => {}, + 1 => struct_init_node.data.bin.lhs = items[0], + 2 => struct_init_node.data.bin = .{ .lhs = items[0], .rhs = items[1] }, + else => { + struct_init_node.tag = .struct_init_expr; + struct_init_node.data = .{ .range = try p.addList(items) }; + }, + } + return try p.addNode(struct_init_node); + } else if (init_ty.get(.@"union")) |union_ty| { + if (il.node != .none) { + return il.node; + } + + var union_init_node: Tree.Node = .{ + .tag = .union_init_expr, + .ty = init_ty, + .data = .{ .union_init = .{ .field_index = 0, .node = .none } }, + }; + if (union_ty.data.record.fields.len == 0) { + // do nothing for empty unions + } else if (il.list.items.len == 0) { + union_init_node.data.union_init.node = try p.addNode(.{ + .tag = .default_init_expr, + .ty = init_ty, + .data = undefined, + }); + } else { + const init = il.list.items[0]; + const index: u32 = @truncate(init.index); + const field_ty = union_ty.data.record.fields[index].ty; + union_init_node.data.union_init = .{ + .field_index = index, + .node = try p.convertInitList(init.list, field_ty), + }; + } + return try p.addNode(union_init_node); + } else { + return error.ParsingFailed; // initializer target is invalid, reported earlier + } +} + +fn msvcAsmStmt(p: *Parser) Error!?NodeIndex { + return p.todo("MSVC assembly statements"); +} + +/// asmOperand : ('[' IDENTIFIER ']')? asmStr '(' expr ')' +fn asmOperand(p: *Parser, names: *std.ArrayList(?TokenIndex), constraints: *NodeList, exprs: *NodeList) Error!void { + if (p.eatToken(.l_bracket)) |l_bracket| { + const ident = (try p.eatIdentifier()) orelse { + try p.err(.expected_identifier); + return error.ParsingFailed; + }; + try names.append(ident); + try p.expectClosing(l_bracket, .r_bracket); + } else { + try names.append(null); + } + const constraint = try p.asmStr(); + try constraints.append(constraint.node); + + const l_paren = p.eatToken(.l_paren) orelse { + try p.errExtra(.expected_token, p.tok_i, .{ .tok_id = .{ .actual = p.tok_ids[p.tok_i], .expected = .l_paren } }); + return error.ParsingFailed; + }; + const res = try p.expr(); + try p.expectClosing(l_paren, .r_paren); + try res.expect(p); + try exprs.append(res.node); +} + +/// gnuAsmStmt +/// : asmStr +/// | asmStr ':' asmOperand* +/// | asmStr ':' asmOperand* ':' asmOperand* +/// | asmStr ':' asmOperand* ':' asmOperand* : asmStr? (',' asmStr)* +/// | asmStr ':' asmOperand* ':' asmOperand* : asmStr? (',' asmStr)* : IDENTIFIER (',' IDENTIFIER)* +fn gnuAsmStmt(p: *Parser, quals: Tree.GNUAssemblyQualifiers, l_paren: TokenIndex) Error!NodeIndex { + const asm_str = try p.asmStr(); + try p.checkAsmStr(asm_str.val, l_paren); + + if (p.tok_ids[p.tok_i] == .r_paren) { + return p.addNode(.{ + .tag = .gnu_asm_simple, + .ty = .{ .specifier = .void }, + .data = .{ .un = asm_str.node }, + }); + } + + const expected_items = 8; // arbitrarily chosen, most assembly will have fewer than 8 inputs/outputs/constraints/names + const bytes_needed = expected_items * @sizeOf(?TokenIndex) + expected_items * 3 * @sizeOf(NodeIndex); + + var stack_fallback = std.heap.stackFallback(bytes_needed, p.comp.gpa); + const allocator = stack_fallback.get(); + + // TODO: Consider using a TokenIndex of 0 instead of null if we need to store the names in the tree + var names = std.ArrayList(?TokenIndex).initCapacity(allocator, expected_items) catch unreachable; // stack allocation already succeeded + defer names.deinit(); + var constraints = NodeList.initCapacity(allocator, expected_items) catch unreachable; // stack allocation already succeeded + defer constraints.deinit(); + var exprs = NodeList.initCapacity(allocator, expected_items) catch unreachable; //stack allocation already succeeded + defer exprs.deinit(); + var clobbers = NodeList.initCapacity(allocator, expected_items) catch unreachable; //stack allocation already succeeded + defer clobbers.deinit(); + + // Outputs + var ate_extra_colon = false; + if (p.eatToken(.colon) orelse p.eatToken(.colon_colon)) |tok_i| { + ate_extra_colon = p.tok_ids[tok_i] == .colon_colon; + if (!ate_extra_colon) { + if (p.tok_ids[p.tok_i].isStringLiteral() or p.tok_ids[p.tok_i] == .l_bracket) { + while (true) { + try p.asmOperand(&names, &constraints, &exprs); + if (p.eatToken(.comma) == null) break; + } + } + } + } + + const num_outputs = names.items.len; + + // Inputs + if (ate_extra_colon or p.tok_ids[p.tok_i] == .colon or p.tok_ids[p.tok_i] == .colon_colon) { + if (ate_extra_colon) { + ate_extra_colon = false; + } else { + ate_extra_colon = p.tok_ids[p.tok_i] == .colon_colon; + p.tok_i += 1; + } + if (!ate_extra_colon) { + if (p.tok_ids[p.tok_i].isStringLiteral() or p.tok_ids[p.tok_i] == .l_bracket) { + while (true) { + try p.asmOperand(&names, &constraints, &exprs); + if (p.eatToken(.comma) == null) break; + } + } + } + } + std.debug.assert(names.items.len == constraints.items.len and constraints.items.len == exprs.items.len); + const num_inputs = names.items.len - num_outputs; + _ = num_inputs; + + // Clobbers + if (ate_extra_colon or p.tok_ids[p.tok_i] == .colon or p.tok_ids[p.tok_i] == .colon_colon) { + if (ate_extra_colon) { + ate_extra_colon = false; + } else { + ate_extra_colon = p.tok_ids[p.tok_i] == .colon_colon; + p.tok_i += 1; + } + if (!ate_extra_colon and p.tok_ids[p.tok_i].isStringLiteral()) { + while (true) { + const clobber = try p.asmStr(); + try clobbers.append(clobber.node); + if (p.eatToken(.comma) == null) break; + } + } + } + + if (!quals.goto and (p.tok_ids[p.tok_i] != .r_paren or ate_extra_colon)) { + try p.errExtra(.expected_token, p.tok_i, .{ .tok_id = .{ .actual = p.tok_ids[p.tok_i], .expected = .r_paren } }); + return error.ParsingFailed; + } + + // Goto labels + var num_labels: u32 = 0; + if (ate_extra_colon or p.tok_ids[p.tok_i] == .colon) { + if (!ate_extra_colon) { + p.tok_i += 1; + } + while (true) { + const ident = (try p.eatIdentifier()) orelse { + try p.err(.expected_identifier); + return error.ParsingFailed; + }; + const ident_str = p.tokSlice(ident); + const label = p.findLabel(ident_str) orelse blk: { + try p.labels.append(.{ .unresolved_goto = ident }); + break :blk ident; + }; + try names.append(ident); + + const elem_ty = try p.arena.create(Type); + elem_ty.* = .{ .specifier = .void }; + const result_ty = Type{ .specifier = .pointer, .data = .{ .sub_type = elem_ty } }; + + const label_addr_node = try p.addNode(.{ + .tag = .addr_of_label, + .data = .{ .decl_ref = label }, + .ty = result_ty, + }); + try exprs.append(label_addr_node); + + num_labels += 1; + if (p.eatToken(.comma) == null) break; + } + } else if (quals.goto) { + try p.errExtra(.expected_token, p.tok_i, .{ .tok_id = .{ .actual = p.tok_ids[p.tok_i], .expected = .colon } }); + return error.ParsingFailed; + } + + // TODO: validate and insert into AST + return .none; +} + +fn checkAsmStr(p: *Parser, asm_str: Value, tok: TokenIndex) !void { + if (!p.comp.langopts.gnu_asm) { + const str = asm_str.data.bytes; + if (str.len() > 1) { + // Empty string (just a NUL byte) is ok because it does not emit any assembly + try p.errTok(.gnu_asm_disabled, tok); + } + } +} + +/// assembly +/// : keyword_asm asmQual* '(' asmStr ')' +/// | keyword_asm asmQual* '(' gnuAsmStmt ')' +/// | keyword_asm msvcAsmStmt +fn assembly(p: *Parser, kind: enum { global, decl_label, stmt }) Error!?NodeIndex { + const asm_tok = p.tok_i; + switch (p.tok_ids[p.tok_i]) { + .keyword_asm => { + try p.err(.extension_token_used); + p.tok_i += 1; + }, + .keyword_asm1, .keyword_asm2 => p.tok_i += 1, + else => return null, + } + + if (!p.tok_ids[p.tok_i].canOpenGCCAsmStmt()) { + return p.msvcAsmStmt(); + } + + var quals: Tree.GNUAssemblyQualifiers = .{}; + while (true) : (p.tok_i += 1) switch (p.tok_ids[p.tok_i]) { + .keyword_volatile, .keyword_volatile1, .keyword_volatile2 => { + if (kind != .stmt) try p.errStr(.meaningless_asm_qual, p.tok_i, "volatile"); + if (quals.@"volatile") try p.errStr(.duplicate_asm_qual, p.tok_i, "volatile"); + quals.@"volatile" = true; + }, + .keyword_inline, .keyword_inline1, .keyword_inline2 => { + if (kind != .stmt) try p.errStr(.meaningless_asm_qual, p.tok_i, "inline"); + if (quals.@"inline") try p.errStr(.duplicate_asm_qual, p.tok_i, "inline"); + quals.@"inline" = true; + }, + .keyword_goto => { + if (kind != .stmt) try p.errStr(.meaningless_asm_qual, p.tok_i, "goto"); + if (quals.goto) try p.errStr(.duplicate_asm_qual, p.tok_i, "goto"); + quals.goto = true; + }, + else => break, + }; + + const l_paren = try p.expectToken(.l_paren); + var result_node: NodeIndex = .none; + switch (kind) { + .decl_label => { + const asm_str = try p.asmStr(); + const str = asm_str.val.data.bytes.trim(1); // remove null-terminator + const attr = Attribute{ .tag = .asm_label, .args = .{ .asm_label = .{ .name = str } }, .syntax = .keyword }; + try p.attr_buf.append(p.gpa, .{ .attr = attr, .tok = asm_tok }); + }, + .global => { + const asm_str = try p.asmStr(); + try p.checkAsmStr(asm_str.val, l_paren); + result_node = try p.addNode(.{ + .tag = .file_scope_asm, + .ty = .{ .specifier = .void }, + .data = .{ .decl = .{ .name = asm_tok, .node = asm_str.node } }, + }); + }, + .stmt => result_node = try p.gnuAsmStmt(quals, l_paren), + } + try p.expectClosing(l_paren, .r_paren); + + if (kind != .decl_label) _ = try p.expectToken(.semicolon); + return result_node; +} + +/// Same as stringLiteral but errors on unicode and wide string literals +fn asmStr(p: *Parser) Error!Result { + var i = p.tok_i; + while (true) : (i += 1) switch (p.tok_ids[i]) { + .string_literal => {}, + .string_literal_utf_16, .string_literal_utf_8, .string_literal_utf_32 => { + try p.errStr(.invalid_asm_str, p.tok_i, "unicode"); + return error.ParsingFailed; + }, + .string_literal_wide => { + try p.errStr(.invalid_asm_str, p.tok_i, "wide"); + return error.ParsingFailed; + }, + else => break, + }; + return try p.stringLiteral(); +} + +// ====== statements ====== + +/// stmt +/// : labeledStmt +/// | compoundStmt +/// | keyword_if '(' expr ')' stmt (keyword_else stmt)? +/// | keyword_switch '(' expr ')' stmt +/// | keyword_while '(' expr ')' stmt +/// | keyword_do stmt while '(' expr ')' ';' +/// | keyword_for '(' (decl | expr? ';') expr? ';' expr? ')' stmt +/// | keyword_goto (IDENTIFIER | ('*' expr)) ';' +/// | keyword_continue ';' +/// | keyword_break ';' +/// | keyword_return expr? ';' +/// | assembly ';' +/// | expr? ';' +fn stmt(p: *Parser) Error!NodeIndex { + if (try p.labeledStmt()) |some| return some; + if (try p.compoundStmt(false, null)) |some| return some; + if (p.eatToken(.keyword_if)) |_| { + const l_paren = try p.expectToken(.l_paren); + const cond_tok = p.tok_i; + var cond = try p.expr(); + try cond.expect(p); + try cond.lvalConversion(p); + try cond.usualUnaryConversion(p, cond_tok); + if (!cond.ty.isScalar()) + try p.errStr(.statement_scalar, l_paren + 1, try p.typeStr(cond.ty)); + try cond.saveValue(p); + try p.expectClosing(l_paren, .r_paren); + + const then = try p.stmt(); + const @"else" = if (p.eatToken(.keyword_else)) |_| try p.stmt() else .none; + + if (then != .none and @"else" != .none) + return try p.addNode(.{ + .tag = .if_then_else_stmt, + .data = .{ .if3 = .{ .cond = cond.node, .body = (try p.addList(&.{ then, @"else" })).start } }, + }) + else + return try p.addNode(.{ + .tag = .if_then_stmt, + .data = .{ .bin = .{ .lhs = cond.node, .rhs = then } }, + }); + } + if (p.eatToken(.keyword_switch)) |_| { + const l_paren = try p.expectToken(.l_paren); + const cond_tok = p.tok_i; + var cond = try p.expr(); + try cond.expect(p); + try cond.lvalConversion(p); + try cond.usualUnaryConversion(p, cond_tok); + + if (!cond.ty.isInt()) + try p.errStr(.statement_int, l_paren + 1, try p.typeStr(cond.ty)); + try cond.saveValue(p); + try p.expectClosing(l_paren, .r_paren); + + const old_switch = p.@"switch"; + var @"switch" = Switch{ + .ranges = std.ArrayList(Switch.Range).init(p.gpa), + .ty = cond.ty, + }; + p.@"switch" = &@"switch"; + defer { + @"switch".ranges.deinit(); + p.@"switch" = old_switch; + } + + const body = try p.stmt(); + + return try p.addNode(.{ + .tag = .switch_stmt, + .data = .{ .bin = .{ .lhs = cond.node, .rhs = body } }, + }); + } + if (p.eatToken(.keyword_while)) |_| { + const l_paren = try p.expectToken(.l_paren); + const cond_tok = p.tok_i; + var cond = try p.expr(); + try cond.expect(p); + try cond.lvalConversion(p); + try cond.usualUnaryConversion(p, cond_tok); + if (!cond.ty.isScalar()) + try p.errStr(.statement_scalar, l_paren + 1, try p.typeStr(cond.ty)); + try cond.saveValue(p); + try p.expectClosing(l_paren, .r_paren); + + const body = body: { + const old_loop = p.in_loop; + p.in_loop = true; + defer p.in_loop = old_loop; + break :body try p.stmt(); + }; + + return try p.addNode(.{ + .tag = .while_stmt, + .data = .{ .bin = .{ .lhs = cond.node, .rhs = body } }, + }); + } + if (p.eatToken(.keyword_do)) |_| { + const body = body: { + const old_loop = p.in_loop; + p.in_loop = true; + defer p.in_loop = old_loop; + break :body try p.stmt(); + }; + + _ = try p.expectToken(.keyword_while); + const l_paren = try p.expectToken(.l_paren); + const cond_tok = p.tok_i; + var cond = try p.expr(); + try cond.expect(p); + try cond.lvalConversion(p); + try cond.usualUnaryConversion(p, cond_tok); + + if (!cond.ty.isScalar()) + try p.errStr(.statement_scalar, l_paren + 1, try p.typeStr(cond.ty)); + try cond.saveValue(p); + try p.expectClosing(l_paren, .r_paren); + + _ = try p.expectToken(.semicolon); + return try p.addNode(.{ + .tag = .do_while_stmt, + .data = .{ .bin = .{ .lhs = cond.node, .rhs = body } }, + }); + } + if (p.eatToken(.keyword_for)) |_| { + try p.syms.pushScope(p); + defer p.syms.popScope(); + const decl_buf_top = p.decl_buf.items.len; + defer p.decl_buf.items.len = decl_buf_top; + + const l_paren = try p.expectToken(.l_paren); + const got_decl = try p.decl(); + + // for (init + const init_start = p.tok_i; + var err_start = p.comp.diag.list.items.len; + var init = if (!got_decl) try p.expr() else Result{}; + try init.saveValue(p); + try init.maybeWarnUnused(p, init_start, err_start); + if (!got_decl) _ = try p.expectToken(.semicolon); + + // for (init; cond + const cond_tok = p.tok_i; + var cond = try p.expr(); + if (cond.node != .none) { + try cond.lvalConversion(p); + try cond.usualUnaryConversion(p, cond_tok); + if (!cond.ty.isScalar()) + try p.errStr(.statement_scalar, l_paren + 1, try p.typeStr(cond.ty)); + } + try cond.saveValue(p); + _ = try p.expectToken(.semicolon); + + // for (init; cond; incr + const incr_start = p.tok_i; + err_start = p.comp.diag.list.items.len; + var incr = try p.expr(); + try incr.maybeWarnUnused(p, incr_start, err_start); + try incr.saveValue(p); + try p.expectClosing(l_paren, .r_paren); + + const body = body: { + const old_loop = p.in_loop; + p.in_loop = true; + defer p.in_loop = old_loop; + break :body try p.stmt(); + }; + + if (got_decl) { + const start = (try p.addList(p.decl_buf.items[decl_buf_top..])).start; + const end = (try p.addList(&.{ cond.node, incr.node, body })).end; + + return try p.addNode(.{ + .tag = .for_decl_stmt, + .data = .{ .range = .{ .start = start, .end = end } }, + }); + } else if (init.node == .none and cond.node == .none and incr.node == .none) { + return try p.addNode(.{ + .tag = .forever_stmt, + .data = .{ .un = body }, + }); + } else return try p.addNode(.{ .tag = .for_stmt, .data = .{ .if3 = .{ + .cond = body, + .body = (try p.addList(&.{ init.node, cond.node, incr.node })).start, + } } }); + } + if (p.eatToken(.keyword_goto)) |goto_tok| { + if (p.eatToken(.asterisk)) |_| { + const expr_tok = p.tok_i; + var e = try p.expr(); + try e.expect(p); + try e.lvalConversion(p); + p.computed_goto_tok = p.computed_goto_tok orelse goto_tok; + if (!e.ty.isPtr()) { + const elem_ty = try p.arena.create(Type); + elem_ty.* = .{ .specifier = .void, .qual = .{ .@"const" = true } }; + const result_ty = Type{ + .specifier = .pointer, + .data = .{ .sub_type = elem_ty }, + }; + if (!e.ty.isInt()) { + try p.errStr(.incompatible_arg, expr_tok, try p.typePairStrExtra(e.ty, " to parameter of incompatible type ", result_ty)); + return error.ParsingFailed; + } + if (e.val.isZero()) { + try e.nullCast(p, result_ty); + } else { + try p.errStr(.implicit_int_to_ptr, expr_tok, try p.typePairStrExtra(e.ty, " to ", result_ty)); + try e.ptrCast(p, result_ty); + } + } + + try e.un(p, .computed_goto_stmt); + _ = try p.expectToken(.semicolon); + return e.node; + } + const name_tok = try p.expectIdentifier(); + const str = p.tokSlice(name_tok); + if (p.findLabel(str) == null) { + try p.labels.append(.{ .unresolved_goto = name_tok }); + } + _ = try p.expectToken(.semicolon); + return try p.addNode(.{ + .tag = .goto_stmt, + .data = .{ .decl_ref = name_tok }, + }); + } + if (p.eatToken(.keyword_continue)) |cont| { + if (!p.in_loop) try p.errTok(.continue_not_in_loop, cont); + _ = try p.expectToken(.semicolon); + return try p.addNode(.{ .tag = .continue_stmt, .data = undefined }); + } + if (p.eatToken(.keyword_break)) |br| { + if (!p.in_loop and p.@"switch" == null) try p.errTok(.break_not_in_loop_or_switch, br); + _ = try p.expectToken(.semicolon); + return try p.addNode(.{ .tag = .break_stmt, .data = undefined }); + } + if (try p.returnStmt()) |some| return some; + if (try p.assembly(.stmt)) |some| return some; + + const expr_start = p.tok_i; + const err_start = p.comp.diag.list.items.len; + + const e = try p.expr(); + if (e.node != .none) { + _ = try p.expectToken(.semicolon); + try e.maybeWarnUnused(p, expr_start, err_start); + return e.node; + } + + const attr_buf_top = p.attr_buf.len; + defer p.attr_buf.len = attr_buf_top; + try p.attributeSpecifier(); + + if (p.eatToken(.semicolon)) |_| { + var null_node: Tree.Node = .{ .tag = .null_stmt, .data = undefined }; + null_node.ty = try Attribute.applyStatementAttributes(p, null_node.ty, expr_start, attr_buf_top); + return p.addNode(null_node); + } + + try p.err(.expected_stmt); + return error.ParsingFailed; +} + +/// labeledStmt +/// : IDENTIFIER ':' stmt +/// | keyword_case integerConstExpr ':' stmt +/// | keyword_default ':' stmt +fn labeledStmt(p: *Parser) Error!?NodeIndex { + if ((p.tok_ids[p.tok_i] == .identifier or p.tok_ids[p.tok_i] == .extended_identifier) and p.tok_ids[p.tok_i + 1] == .colon) { + const name_tok = p.expectIdentifier() catch unreachable; + const str = p.tokSlice(name_tok); + if (p.findLabel(str)) |some| { + try p.errStr(.duplicate_label, name_tok, str); + try p.errStr(.previous_label, some, str); + } else { + p.label_count += 1; + try p.labels.append(.{ .label = name_tok }); + var i: usize = 0; + while (i < p.labels.items.len) { + if (p.labels.items[i] == .unresolved_goto and + mem.eql(u8, p.tokSlice(p.labels.items[i].unresolved_goto), str)) + { + _ = p.labels.swapRemove(i); + } else i += 1; + } + } + + p.tok_i += 1; + const attr_buf_top = p.attr_buf.len; + defer p.attr_buf.len = attr_buf_top; + try p.attributeSpecifier(); + + var labeled_stmt = Tree.Node{ + .tag = .labeled_stmt, + .data = .{ .decl = .{ .name = name_tok, .node = try p.stmt() } }, + }; + labeled_stmt.ty = try Attribute.applyLabelAttributes(p, labeled_stmt.ty, attr_buf_top); + return try p.addNode(labeled_stmt); + } else if (p.eatToken(.keyword_case)) |case| { + const first_item = try p.integerConstExpr(.gnu_folding_extension); + const ellipsis = p.tok_i; + const second_item = if (p.eatToken(.ellipsis) != null) blk: { + try p.errTok(.gnu_switch_range, ellipsis); + break :blk try p.integerConstExpr(.gnu_folding_extension); + } else null; + _ = try p.expectToken(.colon); + + if (p.@"switch") |some| check: { + if (some.ty.hasIncompleteSize()) break :check; // error already reported for incomplete size + + const first = first_item.val; + const last = if (second_item) |second| second.val else first; + if (first.tag == .unavailable) { + try p.errTok(.case_val_unavailable, case + 1); + break :check; + } else if (last.tag == .unavailable) { + try p.errTok(.case_val_unavailable, ellipsis + 1); + break :check; + } else if (last.compare(.lt, first, some.ty, p.comp)) { + try p.errTok(.empty_case_range, case + 1); + break :check; + } + + // TODO cast to target type + const prev = (try some.add(p.comp, first, last, case + 1)) orelse break :check; + + // TODO check which value was already handled + if (some.ty.isUnsignedInt(p.comp)) { + try p.errExtra(.duplicate_switch_case_unsigned, case + 1, .{ + .unsigned = first.data.int, + }); + } else { + try p.errExtra(.duplicate_switch_case_signed, case + 1, .{ + .signed = first.signExtend(some.ty, p.comp), + }); + } + try p.errTok(.previous_case, prev.tok); + } else { + try p.errStr(.case_not_in_switch, case, "case"); + } + + const s = try p.stmt(); + if (second_item) |some| return try p.addNode(.{ + .tag = .case_range_stmt, + .data = .{ .if3 = .{ .cond = s, .body = (try p.addList(&.{ first_item.node, some.node })).start } }, + }) else return try p.addNode(.{ + .tag = .case_stmt, + .data = .{ .bin = .{ .lhs = first_item.node, .rhs = s } }, + }); + } else if (p.eatToken(.keyword_default)) |default| { + _ = try p.expectToken(.colon); + const s = try p.stmt(); + const node = try p.addNode(.{ + .tag = .default_stmt, + .data = .{ .un = s }, + }); + const @"switch" = p.@"switch" orelse { + try p.errStr(.case_not_in_switch, default, "default"); + return node; + }; + if (@"switch".default) |previous| { + try p.errTok(.multiple_default, default); + try p.errTok(.previous_case, previous); + } else { + @"switch".default = default; + } + return node; + } else return null; +} + +const StmtExprState = struct { + last_expr_tok: TokenIndex = 0, + last_expr_res: Result = .{ .ty = .{ .specifier = .void } }, +}; + +/// compoundStmt : '{' ( decl | keyword_extension decl | staticAssert | stmt)* '}' +fn compoundStmt(p: *Parser, is_fn_body: bool, stmt_expr_state: ?*StmtExprState) Error!?NodeIndex { + const l_brace = p.eatToken(.l_brace) orelse return null; + + const decl_buf_top = p.decl_buf.items.len; + defer p.decl_buf.items.len = decl_buf_top; + + // the parameters of a function are in the same scope as the body + if (!is_fn_body) try p.syms.pushScope(p); + defer if (!is_fn_body) p.syms.popScope(); + + var noreturn_index: ?TokenIndex = null; + var noreturn_label_count: u32 = 0; + + while (p.eatToken(.r_brace) == null) : (_ = try p.pragma()) { + if (stmt_expr_state) |state| state.* = .{}; + if (try p.parseOrNextStmt(staticAssert, l_brace)) continue; + if (try p.parseOrNextStmt(decl, l_brace)) continue; + if (p.eatToken(.keyword_extension)) |ext| { + const saved_extension = p.extension_suppressed; + defer p.extension_suppressed = saved_extension; + p.extension_suppressed = true; + + if (try p.parseOrNextStmt(decl, l_brace)) continue; + p.tok_i = ext; + } + const stmt_tok = p.tok_i; + const s = p.stmt() catch |er| switch (er) { + error.ParsingFailed => { + try p.nextStmt(l_brace); + continue; + }, + else => |e| return e, + }; + if (s == .none) continue; + if (stmt_expr_state) |state| { + state.* = .{ + .last_expr_tok = stmt_tok, + .last_expr_res = .{ + .node = s, + .ty = p.nodes.items(.ty)[@intFromEnum(s)], + }, + }; + } + try p.decl_buf.append(s); + + if (noreturn_index == null and p.nodeIsNoreturn(s) == .yes) { + noreturn_index = p.tok_i; + noreturn_label_count = p.label_count; + } + switch (p.nodes.items(.tag)[@intFromEnum(s)]) { + .case_stmt, .default_stmt, .labeled_stmt => noreturn_index = null, + else => {}, + } + } + + if (noreturn_index) |some| { + // if new labels were defined we cannot be certain that the code is unreachable + if (some != p.tok_i - 1 and noreturn_label_count == p.label_count) try p.errTok(.unreachable_code, some); + } + if (is_fn_body) { + const last_noreturn = if (p.decl_buf.items.len == decl_buf_top) + .no + else + p.nodeIsNoreturn(p.decl_buf.items[p.decl_buf.items.len - 1]); + + if (last_noreturn != .yes) { + const ret_ty = p.func.ty.?.returnType(); + var return_zero = false; + if (last_noreturn == .no and !ret_ty.is(.void) and !ret_ty.isFunc() and !ret_ty.isArray()) { + const func_name = p.tokSlice(p.func.name); + const interned_name = try p.comp.intern(func_name); + if (interned_name == p.string_ids.main_id and ret_ty.is(.int)) { + return_zero = true; + } else { + try p.errStr(.func_does_not_return, p.tok_i - 1, func_name); + } + } + try p.decl_buf.append(try p.addNode(.{ .tag = .implicit_return, .ty = p.func.ty.?.returnType(), .data = .{ .return_zero = return_zero } })); + } + if (p.func.ident) |some| try p.decl_buf.insert(decl_buf_top, some.node); + if (p.func.pretty_ident) |some| try p.decl_buf.insert(decl_buf_top, some.node); + } + + var node: Tree.Node = .{ + .tag = .compound_stmt_two, + .data = .{ .bin = .{ .lhs = .none, .rhs = .none } }, + }; + const statements = p.decl_buf.items[decl_buf_top..]; + switch (statements.len) { + 0 => {}, + 1 => node.data = .{ .bin = .{ .lhs = statements[0], .rhs = .none } }, + 2 => node.data = .{ .bin = .{ .lhs = statements[0], .rhs = statements[1] } }, + else => { + node.tag = .compound_stmt; + node.data = .{ .range = try p.addList(statements) }; + }, + } + return try p.addNode(node); +} + +const NoreturnKind = enum { no, yes, complex }; + +fn nodeIsNoreturn(p: *Parser, node: NodeIndex) NoreturnKind { + switch (p.nodes.items(.tag)[@intFromEnum(node)]) { + .break_stmt, .continue_stmt, .return_stmt => return .yes, + .if_then_else_stmt => { + const data = p.data.items[p.nodes.items(.data)[@intFromEnum(node)].if3.body..]; + const then_type = p.nodeIsNoreturn(data[0]); + const else_type = p.nodeIsNoreturn(data[1]); + if (then_type == .complex or else_type == .complex) return .complex; + if (then_type == .yes and else_type == .yes) return .yes; + return .no; + }, + .compound_stmt_two => { + const data = p.nodes.items(.data)[@intFromEnum(node)]; + if (data.bin.rhs != .none) return p.nodeIsNoreturn(data.bin.rhs); + if (data.bin.lhs != .none) return p.nodeIsNoreturn(data.bin.lhs); + return .no; + }, + .compound_stmt => { + const data = p.nodes.items(.data)[@intFromEnum(node)]; + return p.nodeIsNoreturn(p.data.items[data.range.end - 1]); + }, + .labeled_stmt => { + const data = p.nodes.items(.data)[@intFromEnum(node)]; + return p.nodeIsNoreturn(data.decl.node); + }, + .switch_stmt => { + const data = p.nodes.items(.data)[@intFromEnum(node)]; + if (data.bin.rhs == .none) return .complex; + if (p.nodeIsNoreturn(data.bin.rhs) == .yes) return .yes; + return .complex; + }, + else => return .no, + } +} + +fn parseOrNextStmt(p: *Parser, comptime func: fn (*Parser) Error!bool, l_brace: TokenIndex) !bool { + return func(p) catch |er| switch (er) { + error.ParsingFailed => { + try p.nextStmt(l_brace); + return true; + }, + else => |e| return e, + }; +} + +fn nextStmt(p: *Parser, l_brace: TokenIndex) !void { + var parens: u32 = 0; + while (p.tok_i < p.tok_ids.len) : (p.tok_i += 1) { + switch (p.tok_ids[p.tok_i]) { + .l_paren, .l_brace, .l_bracket => parens += 1, + .r_paren, .r_bracket => if (parens != 0) { + parens -= 1; + }, + .r_brace => if (parens == 0) + return + else { + parens -= 1; + }, + .semicolon, + .keyword_for, + .keyword_while, + .keyword_do, + .keyword_if, + .keyword_goto, + .keyword_switch, + .keyword_case, + .keyword_default, + .keyword_continue, + .keyword_break, + .keyword_return, + .keyword_typedef, + .keyword_extern, + .keyword_static, + .keyword_auto, + .keyword_register, + .keyword_thread_local, + .keyword_c23_thread_local, + .keyword_inline, + .keyword_inline1, + .keyword_inline2, + .keyword_noreturn, + .keyword_void, + .keyword_bool, + .keyword_c23_bool, + .keyword_char, + .keyword_short, + .keyword_int, + .keyword_long, + .keyword_signed, + .keyword_unsigned, + .keyword_float, + .keyword_double, + .keyword_complex, + .keyword_atomic, + .keyword_enum, + .keyword_struct, + .keyword_union, + .keyword_alignas, + .keyword_c23_alignas, + .keyword_typeof, + .keyword_typeof1, + .keyword_typeof2, + .keyword_extension, + => if (parens == 0) return, + .keyword_pragma => p.skipToPragmaSentinel(), + else => {}, + } + } + p.tok_i -= 1; // So we can consume EOF + try p.expectClosing(l_brace, .r_brace); + unreachable; +} + +fn returnStmt(p: *Parser) Error!?NodeIndex { + const ret_tok = p.eatToken(.keyword_return) orelse return null; + + const e_tok = p.tok_i; + var e = try p.expr(); + _ = try p.expectToken(.semicolon); + const ret_ty = p.func.ty.?.returnType(); + + if (p.func.ty.?.hasAttribute(.noreturn)) { + try p.errStr(.invalid_noreturn, e_tok, p.tokSlice(p.func.name)); + } + + if (e.node == .none) { + if (!ret_ty.is(.void)) try p.errStr(.func_should_return, ret_tok, p.tokSlice(p.func.name)); + return try p.addNode(.{ .tag = .return_stmt, .data = .{ .un = e.node } }); + } else if (ret_ty.is(.void)) { + try p.errStr(.void_func_returns_value, e_tok, p.tokSlice(p.func.name)); + return try p.addNode(.{ .tag = .return_stmt, .data = .{ .un = e.node } }); + } + + try e.lvalConversion(p); + try e.coerce(p, ret_ty, e_tok, .ret); + + try e.saveValue(p); + return try p.addNode(.{ .tag = .return_stmt, .data = .{ .un = e.node } }); +} + +// ====== expressions ====== + +pub fn macroExpr(p: *Parser) Compilation.Error!bool { + const res = p.condExpr() catch |e| switch (e) { + error.OutOfMemory => return error.OutOfMemory, + error.FatalError => return error.FatalError, + error.ParsingFailed => return false, + }; + if (res.val.tag == .unavailable) { + try p.errTok(.expected_expr, p.tok_i); + return false; + } + return res.val.getBool(); +} + +const CallExpr = union(enum) { + standard: NodeIndex, + builtin: struct { + node: NodeIndex, + tag: BuiltinFunction.Tag, + }, + + fn init(p: *Parser, call_node: NodeIndex, func_node: NodeIndex) CallExpr { + if (p.getNode(call_node, .builtin_call_expr_one)) |node| { + const data = p.nodes.items(.data)[@intFromEnum(node)]; + const name = p.tokSlice(data.decl.name); + const builtin_ty = p.comp.builtins.lookup(name); + return .{ .builtin = .{ .node = node, .tag = builtin_ty.builtin.tag } }; + } + return .{ .standard = func_node }; + } + + fn shouldPerformLvalConversion(self: CallExpr, arg_idx: u32) bool { + return switch (self) { + .standard => true, + .builtin => |builtin| switch (builtin.tag) { + .__builtin_va_start, .__va_start, .va_start => arg_idx != 1, + else => true, + }, + }; + } + + fn shouldPromoteVarArg(self: CallExpr, arg_idx: u32) bool { + return switch (self) { + .standard => true, + .builtin => |builtin| switch (builtin.tag) { + .__builtin_va_start, .__va_start, .va_start => arg_idx != 1, + .__builtin_complex => false, + else => true, + }, + }; + } + + fn shouldCoerceArg(self: CallExpr, arg_idx: u32) bool { + _ = self; + _ = arg_idx; + return true; + } + + fn checkVarArg(self: CallExpr, p: *Parser, first_after: TokenIndex, param_tok: TokenIndex, arg: *Result, arg_idx: u32) !void { + if (self == .standard) return; + + const builtin_tok = p.nodes.items(.data)[@intFromEnum(self.builtin.node)].decl.name; + switch (self.builtin.tag) { + .__builtin_va_start, .__va_start, .va_start => return p.checkVaStartArg(builtin_tok, first_after, param_tok, arg, arg_idx), + .__builtin_complex => return p.checkComplexArg(builtin_tok, first_after, param_tok, arg, arg_idx), + else => {}, + } + } + + /// Some functions cannot be expressed as standard C prototypes. For example `__builtin_complex` requires + /// two arguments of the same real floating point type (e.g. two doubles or two floats). These functions are + /// encoded as varargs functions with custom typechecking. Since varargs functions do not have a fixed number + /// of arguments, `paramCountOverride` is used to tell us how many arguments we should actually expect to see for + /// these custom-typechecked functions. + fn paramCountOverride(self: CallExpr) ?u32 { + return switch (self) { + .standard => null, + .builtin => |builtin| switch (builtin.tag) { + .__builtin_complex => 2, + else => null, + }, + }; + } + + fn returnType(self: CallExpr, p: *Parser, callable_ty: Type) Type { + return switch (self) { + .standard => callable_ty.returnType(), + .builtin => |builtin| switch (builtin.tag) { + .__builtin_complex => { + const last_param = p.list_buf.items[p.list_buf.items.len - 1]; + return p.nodes.items(.ty)[@intFromEnum(last_param)].makeComplex(); + }, + else => callable_ty.returnType(), + }, + }; + } + + fn finish(self: CallExpr, p: *Parser, ty: Type, list_buf_top: usize, arg_count: u32) Error!Result { + const ret_ty = self.returnType(p, ty); + switch (self) { + .standard => |func_node| { + var call_node: Tree.Node = .{ + .tag = .call_expr_one, + .ty = ret_ty, + .data = .{ .bin = .{ .lhs = func_node, .rhs = .none } }, + }; + const args = p.list_buf.items[list_buf_top..]; + switch (arg_count) { + 0 => {}, + 1 => call_node.data.bin.rhs = args[1], // args[0] == func.node + else => { + call_node.tag = .call_expr; + call_node.data = .{ .range = try p.addList(args) }; + }, + } + return Result{ .node = try p.addNode(call_node), .ty = ret_ty }; + }, + .builtin => |builtin| { + const index = @intFromEnum(builtin.node); + var call_node = p.nodes.get(index); + defer p.nodes.set(index, call_node); + call_node.ty = ret_ty; + const args = p.list_buf.items[list_buf_top..]; + switch (arg_count) { + 0 => {}, + 1 => call_node.data.decl.node = args[1], // args[0] == func.node + else => { + call_node.tag = .builtin_call_expr; + args[0] = @enumFromInt(call_node.data.decl.name); + call_node.data = .{ .range = try p.addList(args) }; + }, + } + return Result{ .node = builtin.node, .ty = ret_ty }; + }, + } + } +}; + +const Result = struct { + node: NodeIndex = .none, + ty: Type = .{ .specifier = .int }, + val: Value = .{}, + + fn expect(res: Result, p: *Parser) Error!void { + if (p.in_macro) { + if (res.val.tag == .unavailable) { + try p.errTok(.expected_expr, p.tok_i); + return error.ParsingFailed; + } + return; + } + if (res.node == .none) { + try p.errTok(.expected_expr, p.tok_i); + return error.ParsingFailed; + } + } + + fn empty(res: Result, p: *Parser) bool { + if (p.in_macro) return res.val.tag == .unavailable; + return res.node == .none; + } + + fn maybeWarnUnused(res: Result, p: *Parser, expr_start: TokenIndex, err_start: usize) Error!void { + if (res.ty.is(.void) or res.node == .none) return; + // don't warn about unused result if the expression contained errors besides other unused results + for (p.comp.diag.list.items[err_start..]) |err_item| { + if (err_item.tag != .unused_value) return; + } + var cur_node = res.node; + while (true) switch (p.nodes.items(.tag)[@intFromEnum(cur_node)]) { + .invalid, // So that we don't need to check for node == 0 + .assign_expr, + .mul_assign_expr, + .div_assign_expr, + .mod_assign_expr, + .add_assign_expr, + .sub_assign_expr, + .shl_assign_expr, + .shr_assign_expr, + .bit_and_assign_expr, + .bit_xor_assign_expr, + .bit_or_assign_expr, + .pre_inc_expr, + .pre_dec_expr, + .post_inc_expr, + .post_dec_expr, + => return, + .call_expr_one => { + const fn_ptr = p.nodes.items(.data)[@intFromEnum(cur_node)].bin.lhs; + const fn_ty = p.nodes.items(.ty)[@intFromEnum(fn_ptr)].elemType(); + if (fn_ty.hasAttribute(.nodiscard)) try p.errStr(.nodiscard_unused, expr_start, "TODO get name"); + if (fn_ty.hasAttribute(.warn_unused_result)) try p.errStr(.warn_unused_result, expr_start, "TODO get name"); + return; + }, + .call_expr => { + const fn_ptr = p.data.items[p.nodes.items(.data)[@intFromEnum(cur_node)].range.start]; + const fn_ty = p.nodes.items(.ty)[@intFromEnum(fn_ptr)].elemType(); + if (fn_ty.hasAttribute(.nodiscard)) try p.errStr(.nodiscard_unused, expr_start, "TODO get name"); + if (fn_ty.hasAttribute(.warn_unused_result)) try p.errStr(.warn_unused_result, expr_start, "TODO get name"); + return; + }, + .stmt_expr => { + const body = p.nodes.items(.data)[@intFromEnum(cur_node)].un; + switch (p.nodes.items(.tag)[@intFromEnum(body)]) { + .compound_stmt_two => { + const body_stmt = p.nodes.items(.data)[@intFromEnum(body)].bin; + cur_node = if (body_stmt.rhs != .none) body_stmt.rhs else body_stmt.lhs; + }, + .compound_stmt => { + const data = p.nodes.items(.data)[@intFromEnum(body)]; + cur_node = p.data.items[data.range.end - 1]; + }, + else => unreachable, + } + }, + .comma_expr => cur_node = p.nodes.items(.data)[@intFromEnum(cur_node)].bin.rhs, + .paren_expr => cur_node = p.nodes.items(.data)[@intFromEnum(cur_node)].un, + else => break, + }; + try p.errTok(.unused_value, expr_start); + } + + fn boolRes(lhs: *Result, p: *Parser, tag: Tree.Tag, rhs: Result) !void { + if (lhs.val.tag == .nullptr_t) { + lhs.val = Value.int(0); + } + if (lhs.ty.specifier != .invalid) { + lhs.ty = Type.int; + } + return lhs.bin(p, tag, rhs); + } + + fn bin(lhs: *Result, p: *Parser, tag: Tree.Tag, rhs: Result) !void { + lhs.node = try p.addNode(.{ + .tag = tag, + .ty = lhs.ty, + .data = .{ .bin = .{ .lhs = lhs.node, .rhs = rhs.node } }, + }); + } + + fn un(operand: *Result, p: *Parser, tag: Tree.Tag) Error!void { + operand.node = try p.addNode(.{ + .tag = tag, + .ty = operand.ty, + .data = .{ .un = operand.node }, + }); + } + + fn implicitCast(operand: *Result, p: *Parser, kind: Tree.CastKind) Error!void { + operand.node = try p.addNode(.{ + .tag = .implicit_cast, + .ty = operand.ty, + .data = .{ .cast = .{ .operand = operand.node, .kind = kind } }, + }); + } + + fn adjustCondExprPtrs(a: *Result, tok: TokenIndex, b: *Result, p: *Parser) !bool { + assert(a.ty.isPtr() and b.ty.isPtr()); + + const a_elem = a.ty.elemType(); + const b_elem = b.ty.elemType(); + if (a_elem.eql(b_elem, p.comp, true)) return true; + + var adjusted_elem_ty = try p.arena.create(Type); + adjusted_elem_ty.* = a_elem; + + const has_void_star_branch = a.ty.isVoidStar() or b.ty.isVoidStar(); + const only_quals_differ = a_elem.eql(b_elem, p.comp, false); + const pointers_compatible = only_quals_differ or has_void_star_branch; + + if (!pointers_compatible or has_void_star_branch) { + if (!pointers_compatible) { + try p.errStr(.pointer_mismatch, tok, try p.typePairStrExtra(a.ty, " and ", b.ty)); + } + adjusted_elem_ty.* = .{ .specifier = .void }; + } + if (pointers_compatible) { + adjusted_elem_ty.qual = a_elem.qual.mergeCV(b_elem.qual); + } + if (!adjusted_elem_ty.eql(a_elem, p.comp, true)) { + a.ty = .{ + .data = .{ .sub_type = adjusted_elem_ty }, + .specifier = .pointer, + }; + try a.implicitCast(p, .bitcast); + } + if (!adjusted_elem_ty.eql(b_elem, p.comp, true)) { + b.ty = .{ + .data = .{ .sub_type = adjusted_elem_ty }, + .specifier = .pointer, + }; + try b.implicitCast(p, .bitcast); + } + return true; + } + + /// Adjust types for binary operation, returns true if the result can and should be evaluated. + fn adjustTypes(a: *Result, tok: TokenIndex, b: *Result, p: *Parser, kind: enum { + integer, + arithmetic, + boolean_logic, + relational, + equality, + conditional, + add, + sub, + }) !bool { + if (b.ty.specifier == .invalid) { + try a.saveValue(p); + a.ty = Type.invalid; + } + if (a.ty.specifier == .invalid) { + return false; + } + try a.lvalConversion(p); + try b.lvalConversion(p); + + const a_vec = a.ty.is(.vector); + const b_vec = b.ty.is(.vector); + if (a_vec and b_vec) { + if (a.ty.eql(b.ty, p.comp, false)) { + return a.shouldEval(b, p); + } + return a.invalidBinTy(tok, b, p); + } else if (a_vec) { + if (b.coerceExtra(p, a.ty.elemType(), tok, .test_coerce)) { + try b.saveValue(p); + try b.implicitCast(p, .vector_splat); + return a.shouldEval(b, p); + } else |er| switch (er) { + error.CoercionFailed => return a.invalidBinTy(tok, b, p), + else => |e| return e, + } + } else if (b_vec) { + if (a.coerceExtra(p, b.ty.elemType(), tok, .test_coerce)) { + try a.saveValue(p); + try a.implicitCast(p, .vector_splat); + return a.shouldEval(b, p); + } else |er| switch (er) { + error.CoercionFailed => return a.invalidBinTy(tok, b, p), + else => |e| return e, + } + } + + const a_int = a.ty.isInt(); + const b_int = b.ty.isInt(); + if (a_int and b_int) { + try a.usualArithmeticConversion(b, p, tok); + return a.shouldEval(b, p); + } + if (kind == .integer) return a.invalidBinTy(tok, b, p); + + const a_float = a.ty.isFloat(); + const b_float = b.ty.isFloat(); + const a_arithmetic = a_int or a_float; + const b_arithmetic = b_int or b_float; + if (a_arithmetic and b_arithmetic) { + // <, <=, >, >= only work on real types + if (kind == .relational and (!a.ty.isReal() or !b.ty.isReal())) + return a.invalidBinTy(tok, b, p); + + try a.usualArithmeticConversion(b, p, tok); + return a.shouldEval(b, p); + } + if (kind == .arithmetic) return a.invalidBinTy(tok, b, p); + + const a_nullptr = a.ty.is(.nullptr_t); + const b_nullptr = b.ty.is(.nullptr_t); + const a_ptr = a.ty.isPtr(); + const b_ptr = b.ty.isPtr(); + const a_scalar = a_arithmetic or a_ptr; + const b_scalar = b_arithmetic or b_ptr; + switch (kind) { + .boolean_logic => { + if (!(a_scalar or a_nullptr) or !(b_scalar or b_nullptr)) return a.invalidBinTy(tok, b, p); + + // Do integer promotions but nothing else + if (a_int) try a.intCast(p, a.ty.integerPromotion(p.comp), tok); + if (b_int) try b.intCast(p, b.ty.integerPromotion(p.comp), tok); + return a.shouldEval(b, p); + }, + .relational, .equality => { + if (kind == .equality and (a_nullptr or b_nullptr)) { + if (a_nullptr and b_nullptr) return a.shouldEval(b, p); + const nullptr_res = if (a_nullptr) a else b; + const other_res = if (a_nullptr) b else a; + if (other_res.ty.isPtr()) { + try nullptr_res.nullCast(p, other_res.ty); + return other_res.shouldEval(nullptr_res, p); + } else if (other_res.val.isZero()) { + other_res.val = .{ .tag = .nullptr_t }; + try other_res.nullCast(p, nullptr_res.ty); + return other_res.shouldEval(nullptr_res, p); + } + return a.invalidBinTy(tok, b, p); + } + // comparisons between floats and pointes not allowed + if (!a_scalar or !b_scalar or (a_float and b_ptr) or (b_float and a_ptr)) + return a.invalidBinTy(tok, b, p); + + if ((a_int or b_int) and !(a.val.isZero() or b.val.isZero())) { + try p.errStr(.comparison_ptr_int, tok, try p.typePairStr(a.ty, b.ty)); + } else if (a_ptr and b_ptr) { + if (!a.ty.isVoidStar() and !b.ty.isVoidStar() and !a.ty.eql(b.ty, p.comp, false)) + try p.errStr(.comparison_distinct_ptr, tok, try p.typePairStr(a.ty, b.ty)); + } else if (a_ptr) { + try b.ptrCast(p, a.ty); + } else { + assert(b_ptr); + try a.ptrCast(p, b.ty); + } + + return a.shouldEval(b, p); + }, + .conditional => { + // doesn't matter what we return here, as the result is ignored + if (a.ty.is(.void) or b.ty.is(.void)) { + try a.toVoid(p); + try b.toVoid(p); + return true; + } + if (a_nullptr and b_nullptr) return true; + if ((a_ptr and b_int) or (a_int and b_ptr)) { + if (a.val.isZero() or b.val.isZero()) { + try a.nullCast(p, b.ty); + try b.nullCast(p, a.ty); + return true; + } + const int_ty = if (a_int) a else b; + const ptr_ty = if (a_ptr) a else b; + try p.errStr(.implicit_int_to_ptr, tok, try p.typePairStrExtra(int_ty.ty, " to ", ptr_ty.ty)); + try int_ty.ptrCast(p, ptr_ty.ty); + + return true; + } + if (a_ptr and b_ptr) return a.adjustCondExprPtrs(tok, b, p); + if ((a_ptr and b_nullptr) or (a_nullptr and b_ptr)) { + const nullptr_res = if (a_nullptr) a else b; + const ptr_res = if (a_nullptr) b else a; + try nullptr_res.nullCast(p, ptr_res.ty); + return true; + } + if (a.ty.isRecord() and b.ty.isRecord() and a.ty.eql(b.ty, p.comp, false)) { + return true; + } + return a.invalidBinTy(tok, b, p); + }, + .add => { + // if both aren't arithmetic one should be pointer and the other an integer + if (a_ptr == b_ptr or a_int == b_int) return a.invalidBinTy(tok, b, p); + + // Do integer promotions but nothing else + if (a_int) try a.intCast(p, a.ty.integerPromotion(p.comp), tok); + if (b_int) try b.intCast(p, b.ty.integerPromotion(p.comp), tok); + + // The result type is the type of the pointer operand + if (a_int) a.ty = b.ty else b.ty = a.ty; + return a.shouldEval(b, p); + }, + .sub => { + // if both aren't arithmetic then either both should be pointers or just a + if (!a_ptr or !(b_ptr or b_int)) return a.invalidBinTy(tok, b, p); + + if (a_ptr and b_ptr) { + if (!a.ty.eql(b.ty, p.comp, false)) try p.errStr(.incompatible_pointers, tok, try p.typePairStr(a.ty, b.ty)); + a.ty = p.comp.types.ptrdiff; + } + + // Do integer promotion on b if needed + if (b_int) try b.intCast(p, b.ty.integerPromotion(p.comp), tok); + return a.shouldEval(b, p); + }, + else => return a.invalidBinTy(tok, b, p), + } + } + + fn lvalConversion(res: *Result, p: *Parser) Error!void { + if (res.ty.isFunc()) { + var elem_ty = try p.arena.create(Type); + elem_ty.* = res.ty; + res.ty.specifier = .pointer; + res.ty.data = .{ .sub_type = elem_ty }; + try res.implicitCast(p, .function_to_pointer); + } else if (res.ty.isArray()) { + res.val.tag = .unavailable; + res.ty.decayArray(); + try res.implicitCast(p, .array_to_pointer); + } else if (!p.in_macro and Tree.isLval(p.nodes.slice(), p.data.items, p.value_map, res.node)) { + res.ty.qual = .{}; + try res.implicitCast(p, .lval_to_rval); + } + } + + fn boolCast(res: *Result, p: *Parser, bool_ty: Type, tok: TokenIndex) Error!void { + if (res.ty.isArray()) { + if (res.val.tag == .bytes) { + try p.errStr(.string_literal_to_bool, tok, try p.typePairStrExtra(res.ty, " to ", bool_ty)); + } else { + try p.errStr(.array_address_to_bool, tok, p.tokSlice(tok)); + } + try res.lvalConversion(p); + res.val = Value.int(1); + res.ty = bool_ty; + try res.implicitCast(p, .pointer_to_bool); + } else if (res.ty.isPtr()) { + res.val.toBool(); + res.ty = bool_ty; + try res.implicitCast(p, .pointer_to_bool); + } else if (res.ty.isInt() and !res.ty.is(.bool)) { + res.val.toBool(); + res.ty = bool_ty; + try res.implicitCast(p, .int_to_bool); + } else if (res.ty.isFloat()) { + const old_value = res.val; + const value_change_kind = res.val.floatToInt(res.ty, bool_ty, p.comp); + try res.floatToIntWarning(p, bool_ty, old_value, value_change_kind, tok); + if (!res.ty.isReal()) { + res.ty = res.ty.makeReal(); + try res.implicitCast(p, .complex_float_to_real); + } + res.ty = bool_ty; + try res.implicitCast(p, .float_to_bool); + } + } + + fn intCast(res: *Result, p: *Parser, int_ty: Type, tok: TokenIndex) Error!void { + if (int_ty.hasIncompleteSize()) return error.ParsingFailed; // Diagnostic already issued + if (res.ty.is(.bool)) { + res.ty = int_ty.makeReal(); + try res.implicitCast(p, .bool_to_int); + if (!int_ty.isReal()) { + res.ty = int_ty; + try res.implicitCast(p, .real_to_complex_int); + } + } else if (res.ty.isPtr()) { + res.ty = int_ty.makeReal(); + try res.implicitCast(p, .pointer_to_int); + if (!int_ty.isReal()) { + res.ty = int_ty; + try res.implicitCast(p, .real_to_complex_int); + } + } else if (res.ty.isFloat()) { + const old_value = res.val; + const value_change_kind = res.val.floatToInt(res.ty, int_ty, p.comp); + try res.floatToIntWarning(p, int_ty, old_value, value_change_kind, tok); + const old_real = res.ty.isReal(); + const new_real = int_ty.isReal(); + if (old_real and new_real) { + res.ty = int_ty; + try res.implicitCast(p, .float_to_int); + } else if (old_real) { + res.ty = int_ty.makeReal(); + try res.implicitCast(p, .float_to_int); + res.ty = int_ty; + try res.implicitCast(p, .real_to_complex_int); + } else if (new_real) { + res.ty = res.ty.makeReal(); + try res.implicitCast(p, .complex_float_to_real); + res.ty = int_ty; + try res.implicitCast(p, .float_to_int); + } else { + res.ty = int_ty; + try res.implicitCast(p, .complex_float_to_complex_int); + } + } else if (!res.ty.eql(int_ty, p.comp, true)) { + res.val.intCast(res.ty, int_ty, p.comp); + const old_real = res.ty.isReal(); + const new_real = int_ty.isReal(); + if (old_real and new_real) { + res.ty = int_ty; + try res.implicitCast(p, .int_cast); + } else if (old_real) { + const real_int_ty = int_ty.makeReal(); + if (!res.ty.eql(real_int_ty, p.comp, false)) { + res.ty = real_int_ty; + try res.implicitCast(p, .int_cast); + } + res.ty = int_ty; + try res.implicitCast(p, .real_to_complex_int); + } else if (new_real) { + res.ty = res.ty.makeReal(); + try res.implicitCast(p, .complex_int_to_real); + res.ty = int_ty; + try res.implicitCast(p, .int_cast); + } else { + res.ty = int_ty; + try res.implicitCast(p, .complex_int_cast); + } + } + } + + fn floatToIntWarning(res: *Result, p: *Parser, int_ty: Type, old_value: Value, change_kind: Value.FloatToIntChangeKind, tok: TokenIndex) !void { + switch (change_kind) { + .none => return p.errStr(.float_to_int, tok, try p.typePairStrExtra(res.ty, " to ", int_ty)), + .out_of_range => return p.errStr(.float_out_of_range, tok, try p.typePairStrExtra(res.ty, " to ", int_ty)), + .overflow => return p.errStr(.float_overflow_conversion, tok, try p.typePairStrExtra(res.ty, " to ", int_ty)), + .nonzero_to_zero => return p.errStr(.float_zero_conversion, tok, try p.floatValueChangedStr(res, old_value.getFloat(f64), int_ty)), + .value_changed => return p.errStr(.float_value_changed, tok, try p.floatValueChangedStr(res, old_value.getFloat(f64), int_ty)), + } + } + + fn floatCast(res: *Result, p: *Parser, float_ty: Type) Error!void { + if (res.ty.is(.bool)) { + res.val.intToFloat(res.ty, float_ty, p.comp); + res.ty = float_ty.makeReal(); + try res.implicitCast(p, .bool_to_float); + if (!float_ty.isReal()) { + res.ty = float_ty; + try res.implicitCast(p, .real_to_complex_float); + } + } else if (res.ty.isInt()) { + res.val.intToFloat(res.ty, float_ty, p.comp); + const old_real = res.ty.isReal(); + const new_real = float_ty.isReal(); + if (old_real and new_real) { + res.ty = float_ty; + try res.implicitCast(p, .int_to_float); + } else if (old_real) { + res.ty = float_ty.makeReal(); + try res.implicitCast(p, .int_to_float); + res.ty = float_ty; + try res.implicitCast(p, .real_to_complex_float); + } else if (new_real) { + res.ty = res.ty.makeReal(); + try res.implicitCast(p, .complex_int_to_real); + res.ty = float_ty; + try res.implicitCast(p, .int_to_float); + } else { + res.ty = float_ty; + try res.implicitCast(p, .complex_int_to_complex_float); + } + } else if (!res.ty.eql(float_ty, p.comp, true)) { + res.val.floatCast(res.ty, float_ty, p.comp); + const old_real = res.ty.isReal(); + const new_real = float_ty.isReal(); + if (old_real and new_real) { + res.ty = float_ty; + try res.implicitCast(p, .float_cast); + } else if (old_real) { + if (res.ty.floatRank() != float_ty.floatRank()) { + res.ty = float_ty.makeReal(); + try res.implicitCast(p, .float_cast); + } + res.ty = float_ty; + try res.implicitCast(p, .real_to_complex_float); + } else if (new_real) { + res.ty = res.ty.makeReal(); + try res.implicitCast(p, .complex_float_to_real); + if (res.ty.floatRank() != float_ty.floatRank()) { + res.ty = float_ty; + try res.implicitCast(p, .float_cast); + } + } else { + res.ty = float_ty; + try res.implicitCast(p, .complex_float_cast); + } + } + } + + /// Converts a bool or integer to a pointer + fn ptrCast(res: *Result, p: *Parser, ptr_ty: Type) Error!void { + if (res.ty.is(.bool)) { + res.ty = ptr_ty; + try res.implicitCast(p, .bool_to_pointer); + } else if (res.ty.isInt()) { + res.val.intCast(res.ty, ptr_ty, p.comp); + res.ty = ptr_ty; + try res.implicitCast(p, .int_to_pointer); + } + } + + /// Convert pointer to one with a different child type + fn ptrChildTypeCast(res: *Result, p: *Parser, ptr_ty: Type) Error!void { + res.ty = ptr_ty; + return res.implicitCast(p, .bitcast); + } + + fn toVoid(res: *Result, p: *Parser) Error!void { + if (!res.ty.is(.void)) { + res.ty = .{ .specifier = .void }; + try res.implicitCast(p, .to_void); + } + } + + fn nullCast(res: *Result, p: *Parser, ptr_ty: Type) Error!void { + if (!res.ty.is(.nullptr_t) and !res.val.isZero()) return; + res.ty = ptr_ty; + try res.implicitCast(p, .null_to_pointer); + } + + fn usualUnaryConversion(res: *Result, p: *Parser, tok: TokenIndex) Error!void { + if (res.ty.isFloat()) fp_eval: { + const eval_method = p.comp.langopts.fp_eval_method orelse break :fp_eval; + switch (eval_method) { + .source => {}, + .indeterminate => unreachable, + .double => { + if (res.ty.floatRank() < (Type{ .specifier = .double }).floatRank()) { + const spec: Type.Specifier = if (res.ty.isReal()) .double else .complex_double; + return res.floatCast(p, .{ .specifier = spec }); + } + }, + .extended => { + if (res.ty.floatRank() < (Type{ .specifier = .long_double }).floatRank()) { + const spec: Type.Specifier = if (res.ty.isReal()) .long_double else .complex_long_double; + return res.floatCast(p, .{ .specifier = spec }); + } + }, + } + } + + if (res.ty.is(.fp16) and !p.comp.langopts.use_native_half_type) { + return res.floatCast(p, .{ .specifier = .float }); + } + if (res.ty.isInt()) { + const slice = p.nodes.slice(); + if (Tree.bitfieldWidth(slice, res.node, true)) |width| { + if (res.ty.bitfieldPromotion(p.comp, width)) |promotion_ty| { + return res.intCast(p, promotion_ty, tok); + } + } + return res.intCast(p, res.ty.integerPromotion(p.comp), tok); + } + } + + fn usualArithmeticConversion(a: *Result, b: *Result, p: *Parser, tok: TokenIndex) Error!void { + try a.usualUnaryConversion(p, tok); + try b.usualUnaryConversion(p, tok); + + // if either is a float cast to that type + if (a.ty.isFloat() or b.ty.isFloat()) { + const float_types = [7][2]Type.Specifier{ + .{ .complex_long_double, .long_double }, + .{ .complex_float128, .float128 }, + .{ .complex_float80, .float80 }, + .{ .complex_double, .double }, + .{ .complex_float, .float }, + // No `_Complex __fp16` type + .{ .invalid, .fp16 }, + // No `_Complex _Float16` + .{ .invalid, .float16 }, + }; + const a_spec = a.ty.canonicalize(.standard).specifier; + const b_spec = b.ty.canonicalize(.standard).specifier; + if (p.comp.target.c_type_bit_size(.longdouble) == 128) { + if (try a.floatConversion(b, a_spec, b_spec, p, float_types[0])) return; + } + if (try a.floatConversion(b, a_spec, b_spec, p, float_types[1])) return; + if (p.comp.target.c_type_bit_size(.longdouble) == 80) { + if (try a.floatConversion(b, a_spec, b_spec, p, float_types[0])) return; + } + if (try a.floatConversion(b, a_spec, b_spec, p, float_types[2])) return; + if (p.comp.target.c_type_bit_size(.longdouble) == 64) { + if (try a.floatConversion(b, a_spec, b_spec, p, float_types[0])) return; + } + if (try a.floatConversion(b, a_spec, b_spec, p, float_types[3])) return; + if (try a.floatConversion(b, a_spec, b_spec, p, float_types[4])) return; + if (try a.floatConversion(b, a_spec, b_spec, p, float_types[5])) return; + if (try a.floatConversion(b, a_spec, b_spec, p, float_types[6])) return; + } + + if (a.ty.eql(b.ty, p.comp, true)) { + // cast to promoted type + try a.intCast(p, a.ty, tok); + try b.intCast(p, b.ty, tok); + return; + } + + const target = a.ty.integerConversion(b.ty, p.comp); + if (!target.isReal()) { + try a.saveValue(p); + try b.saveValue(p); + } + try a.intCast(p, target, tok); + try b.intCast(p, target, tok); + } + + fn floatConversion(a: *Result, b: *Result, a_spec: Type.Specifier, b_spec: Type.Specifier, p: *Parser, pair: [2]Type.Specifier) !bool { + if (a_spec == pair[0] or a_spec == pair[1] or + b_spec == pair[0] or b_spec == pair[1]) + { + const both_real = a.ty.isReal() and b.ty.isReal(); + const res_spec = pair[@intFromBool(both_real)]; + const ty = Type{ .specifier = res_spec }; + try a.floatCast(p, ty); + try b.floatCast(p, ty); + return true; + } + return false; + } + + fn invalidBinTy(a: *Result, tok: TokenIndex, b: *Result, p: *Parser) Error!bool { + try p.errStr(.invalid_bin_types, tok, try p.typePairStr(a.ty, b.ty)); + a.val.tag = .unavailable; + b.val.tag = .unavailable; + a.ty = Type.invalid; + return false; + } + + fn shouldEval(a: *Result, b: *Result, p: *Parser) Error!bool { + if (p.no_eval) return false; + if (a.val.tag != .unavailable and b.val.tag != .unavailable) + return true; + + try a.saveValue(p); + try b.saveValue(p); + return p.no_eval; + } + + /// Saves value and replaces it with `.unavailable`. + fn saveValue(res: *Result, p: *Parser) !void { + assert(!p.in_macro); + if (res.val.tag == .unavailable or res.val.tag == .nullptr_t) return; + if (!p.in_macro) try p.value_map.put(res.node, res.val); + res.val.tag = .unavailable; + } + + fn castType(res: *Result, p: *Parser, to: Type, tok: TokenIndex) !void { + var cast_kind: Tree.CastKind = undefined; + + if (to.is(.void)) { + // everything can cast to void + cast_kind = .to_void; + res.val.tag = .unavailable; + } else if (to.is(.nullptr_t)) { + if (res.ty.is(.nullptr_t)) { + cast_kind = .no_op; + } else { + try p.errStr(.invalid_object_cast, tok, try p.typePairStrExtra(res.ty, " to ", to)); + return error.ParsingFailed; + } + } else if (res.ty.is(.nullptr_t)) { + if (to.is(.bool)) { + try res.nullCast(p, res.ty); + res.val.toBool(); + res.ty = .{ .specifier = .bool }; + try res.implicitCast(p, .pointer_to_bool); + try res.saveValue(p); + } else if (to.isPtr()) { + try res.nullCast(p, to); + } else { + try p.errStr(.invalid_object_cast, tok, try p.typePairStrExtra(res.ty, " to ", to)); + return error.ParsingFailed; + } + cast_kind = .no_op; + } else if (res.val.isZero() and to.isPtr()) { + cast_kind = .null_to_pointer; + } else if (to.isScalar()) cast: { + const old_float = res.ty.isFloat(); + const new_float = to.isFloat(); + + if (new_float and res.ty.isPtr()) { + try p.errStr(.invalid_cast_to_float, tok, try p.typeStr(to)); + return error.ParsingFailed; + } else if (old_float and to.isPtr()) { + try p.errStr(.invalid_cast_to_pointer, tok, try p.typeStr(res.ty)); + return error.ParsingFailed; + } + const old_real = res.ty.isReal(); + const new_real = to.isReal(); + + if (to.eql(res.ty, p.comp, false)) { + cast_kind = .no_op; + } else if (to.is(.bool)) { + if (res.ty.isPtr()) { + cast_kind = .pointer_to_bool; + } else if (res.ty.isInt()) { + if (!old_real) { + res.ty = res.ty.makeReal(); + try res.implicitCast(p, .complex_int_to_real); + } + cast_kind = .int_to_bool; + } else if (old_float) { + if (!old_real) { + res.ty = res.ty.makeReal(); + try res.implicitCast(p, .complex_float_to_real); + } + cast_kind = .float_to_bool; + } + } else if (to.isInt()) { + if (res.ty.is(.bool)) { + if (!new_real) { + res.ty = to.makeReal(); + try res.implicitCast(p, .bool_to_int); + cast_kind = .real_to_complex_int; + } else { + cast_kind = .bool_to_int; + } + } else if (res.ty.isInt()) { + if (old_real and new_real) { + cast_kind = .int_cast; + } else if (old_real) { + res.ty = to.makeReal(); + try res.implicitCast(p, .int_cast); + cast_kind = .real_to_complex_int; + } else if (new_real) { + res.ty = res.ty.makeReal(); + try res.implicitCast(p, .complex_int_to_real); + cast_kind = .int_cast; + } else { + cast_kind = .complex_int_cast; + } + } else if (res.ty.isPtr()) { + if (!new_real) { + res.ty = to.makeReal(); + try res.implicitCast(p, .pointer_to_int); + cast_kind = .real_to_complex_int; + } else { + cast_kind = .pointer_to_int; + } + } else if (old_real and new_real) { + cast_kind = .float_to_int; + } else if (old_real) { + res.ty = to.makeReal(); + try res.implicitCast(p, .float_to_int); + cast_kind = .real_to_complex_int; + } else if (new_real) { + res.ty = res.ty.makeReal(); + try res.implicitCast(p, .complex_float_to_real); + cast_kind = .float_to_int; + } else { + cast_kind = .complex_float_to_complex_int; + } + } else if (to.isPtr()) { + if (res.ty.isArray()) + cast_kind = .array_to_pointer + else if (res.ty.isPtr()) + cast_kind = .bitcast + else if (res.ty.isFunc()) + cast_kind = .function_to_pointer + else if (res.ty.is(.bool)) + cast_kind = .bool_to_pointer + else if (res.ty.isInt()) { + if (!old_real) { + res.ty = res.ty.makeReal(); + try res.implicitCast(p, .complex_int_to_real); + } + cast_kind = .int_to_pointer; + } + } else if (new_float) { + if (res.ty.is(.bool)) { + if (!new_real) { + res.ty = to.makeReal(); + try res.implicitCast(p, .bool_to_float); + cast_kind = .real_to_complex_float; + } else { + cast_kind = .bool_to_float; + } + } else if (res.ty.isInt()) { + if (old_real and new_real) { + cast_kind = .int_to_float; + } else if (old_real) { + res.ty = to.makeReal(); + try res.implicitCast(p, .int_to_float); + cast_kind = .real_to_complex_float; + } else if (new_real) { + res.ty = res.ty.makeReal(); + try res.implicitCast(p, .complex_int_to_real); + cast_kind = .int_to_float; + } else { + cast_kind = .complex_int_to_complex_float; + } + } else if (old_real and new_real) { + cast_kind = .float_cast; + } else if (old_real) { + res.ty = to.makeReal(); + try res.implicitCast(p, .float_cast); + cast_kind = .real_to_complex_float; + } else if (new_real) { + res.ty = res.ty.makeReal(); + try res.implicitCast(p, .complex_float_to_real); + cast_kind = .float_cast; + } else { + cast_kind = .complex_float_cast; + } + } + if (res.val.tag == .unavailable) break :cast; + + const old_int = res.ty.isInt() or res.ty.isPtr(); + const new_int = to.isInt() or to.isPtr(); + if (to.is(.bool)) { + res.val.toBool(); + } else if (old_float and new_int) { + // Explicit cast, no conversion warning + _ = res.val.floatToInt(res.ty, to, p.comp); + } else if (new_float and old_int) { + res.val.intToFloat(res.ty, to, p.comp); + } else if (new_float and old_float) { + res.val.floatCast(res.ty, to, p.comp); + } else if (old_int and new_int) { + if (to.hasIncompleteSize()) { + try p.errStr(.cast_to_incomplete_type, tok, try p.typeStr(to)); + return error.ParsingFailed; + } + res.val.intCast(res.ty, to, p.comp); + } + } else if (to.get(.@"union")) |union_ty| { + if (union_ty.data.record.hasFieldOfType(res.ty, p.comp)) { + cast_kind = .union_cast; + try p.errTok(.gnu_union_cast, tok); + } else { + if (union_ty.data.record.isIncomplete()) { + try p.errStr(.cast_to_incomplete_type, tok, try p.typeStr(to)); + } else { + try p.errStr(.invalid_union_cast, tok, try p.typeStr(res.ty)); + } + return error.ParsingFailed; + } + } else { + if (to.is(.auto_type)) { + try p.errTok(.invalid_cast_to_auto_type, tok); + } else { + try p.errStr(.invalid_cast_type, tok, try p.typeStr(to)); + } + return error.ParsingFailed; + } + if (to.anyQual()) try p.errStr(.qual_cast, tok, try p.typeStr(to)); + if (to.isInt() and res.ty.isPtr() and to.sizeCompare(res.ty, p.comp) == .lt) { + try p.errStr(.cast_to_smaller_int, tok, try p.typePairStrExtra(to, " from ", res.ty)); + } + res.ty = to; + res.ty.qual = .{}; + res.node = try p.addNode(.{ + .tag = .explicit_cast, + .ty = res.ty, + .data = .{ .cast = .{ .operand = res.node, .kind = cast_kind } }, + }); + } + + fn intFitsInType(res: Result, p: *Parser, ty: Type) bool { + const max_int = Value.int(ty.maxInt(p.comp)); + const min_int = Value.int(ty.minInt(p.comp)); + return res.val.compare(.lte, max_int, res.ty, p.comp) and + (res.ty.isUnsignedInt(p.comp) or res.val.compare(.gte, min_int, res.ty, p.comp)); + } + + const CoerceContext = union(enum) { + assign, + init, + ret, + arg: TokenIndex, + test_coerce, + + fn note(ctx: CoerceContext, p: *Parser) !void { + switch (ctx) { + .arg => |tok| try p.errTok(.parameter_here, tok), + .test_coerce => unreachable, + else => {}, + } + } + + fn typePairStr(ctx: CoerceContext, p: *Parser, dest_ty: Type, src_ty: Type) ![]const u8 { + switch (ctx) { + .assign, .init => return p.typePairStrExtra(dest_ty, " from incompatible type ", src_ty), + .ret => return p.typePairStrExtra(src_ty, " from a function with incompatible result type ", dest_ty), + .arg => return p.typePairStrExtra(src_ty, " to parameter of incompatible type ", dest_ty), + .test_coerce => unreachable, + } + } + }; + + /// Perform assignment-like coercion to `dest_ty`. + fn coerce(res: *Result, p: *Parser, dest_ty: Type, tok: TokenIndex, ctx: CoerceContext) Error!void { + if (res.ty.specifier == .invalid or dest_ty.specifier == .invalid) { + res.ty = Type.invalid; + return; + } + return res.coerceExtra(p, dest_ty, tok, ctx) catch |er| switch (er) { + error.CoercionFailed => unreachable, + else => |e| return e, + }; + } + + const Stage1Limitation = Error || error{CoercionFailed}; + fn coerceExtra(res: *Result, p: *Parser, dest_ty: Type, tok: TokenIndex, ctx: CoerceContext) Stage1Limitation!void { + // Subject of the coercion does not need to be qualified. + var unqual_ty = dest_ty.canonicalize(.standard); + unqual_ty.qual = .{}; + if (unqual_ty.is(.nullptr_t)) { + if (res.ty.is(.nullptr_t)) return; + } else if (unqual_ty.is(.bool)) { + if (res.ty.isScalar() and !res.ty.is(.nullptr_t)) { + // this is ridiculous but it's what clang does + try res.boolCast(p, unqual_ty, tok); + return; + } + } else if (unqual_ty.isInt()) { + if (res.ty.isInt() or res.ty.isFloat()) { + try res.intCast(p, unqual_ty, tok); + return; + } else if (res.ty.isPtr()) { + if (ctx == .test_coerce) return error.CoercionFailed; + try p.errStr(.implicit_ptr_to_int, tok, try p.typePairStrExtra(res.ty, " to ", dest_ty)); + try ctx.note(p); + try res.intCast(p, unqual_ty, tok); + return; + } + } else if (unqual_ty.isFloat()) { + if (res.ty.isInt() or res.ty.isFloat()) { + try res.floatCast(p, unqual_ty); + return; + } + } else if (unqual_ty.isPtr()) { + if (res.ty.is(.nullptr_t) or res.val.isZero()) { + try res.nullCast(p, dest_ty); + return; + } else if (res.ty.isInt() and res.ty.isReal()) { + if (ctx == .test_coerce) return error.CoercionFailed; + try p.errStr(.implicit_int_to_ptr, tok, try p.typePairStrExtra(res.ty, " to ", dest_ty)); + try ctx.note(p); + try res.ptrCast(p, unqual_ty); + return; + } else if (res.ty.isVoidStar() or unqual_ty.eql(res.ty, p.comp, true)) { + return; // ok + } else if (unqual_ty.isVoidStar() and res.ty.isPtr() or (res.ty.isInt() and res.ty.isReal())) { + return; // ok + } else if (unqual_ty.eql(res.ty, p.comp, false)) { + if (!unqual_ty.elemType().qual.hasQuals(res.ty.elemType().qual)) { + try p.errStr(switch (ctx) { + .assign => .ptr_assign_discards_quals, + .init => .ptr_init_discards_quals, + .ret => .ptr_ret_discards_quals, + .arg => .ptr_arg_discards_quals, + .test_coerce => return error.CoercionFailed, + }, tok, try ctx.typePairStr(p, dest_ty, res.ty)); + } + try res.ptrCast(p, unqual_ty); + return; + } else if (res.ty.isPtr()) { + const different_sign_only = unqual_ty.elemType().sameRankDifferentSign(res.ty.elemType(), p.comp); + try p.errStr(switch (ctx) { + .assign => ([2]Diagnostics.Tag{ .incompatible_ptr_assign, .incompatible_ptr_assign_sign })[@intFromBool(different_sign_only)], + .init => ([2]Diagnostics.Tag{ .incompatible_ptr_init, .incompatible_ptr_init_sign })[@intFromBool(different_sign_only)], + .ret => ([2]Diagnostics.Tag{ .incompatible_return, .incompatible_return_sign })[@intFromBool(different_sign_only)], + .arg => ([2]Diagnostics.Tag{ .incompatible_ptr_arg, .incompatible_ptr_arg_sign })[@intFromBool(different_sign_only)], + .test_coerce => return error.CoercionFailed, + }, tok, try ctx.typePairStr(p, dest_ty, res.ty)); + try ctx.note(p); + try res.ptrChildTypeCast(p, unqual_ty); + return; + } + } else if (unqual_ty.isRecord()) { + if (unqual_ty.eql(res.ty, p.comp, false)) { + return; // ok + } + + if (ctx == .arg) if (unqual_ty.get(.@"union")) |union_ty| { + if (dest_ty.hasAttribute(.transparent_union)) transparent_union: { + res.coerceExtra(p, union_ty.data.record.fields[0].ty, tok, .test_coerce) catch |er| switch (er) { + error.CoercionFailed => break :transparent_union, + else => |e| return e, + }; + res.node = try p.addNode(.{ + .tag = .union_init_expr, + .ty = dest_ty, + .data = .{ .union_init = .{ .field_index = 0, .node = res.node } }, + }); + res.ty = dest_ty; + return; + } + }; + } else if (unqual_ty.is(.vector)) { + if (unqual_ty.eql(res.ty, p.comp, false)) { + return; // ok + } + } else { + if (ctx == .assign and (unqual_ty.isArray() or unqual_ty.isFunc())) { + try p.errTok(.not_assignable, tok); + return; + } else if (ctx == .test_coerce) { + return error.CoercionFailed; + } + // This case should not be possible and an error should have already been emitted but we + // might still have attempted to parse further so return error.ParsingFailed here to stop. + return error.ParsingFailed; + } + + try p.errStr(switch (ctx) { + .assign => .incompatible_assign, + .init => .incompatible_init, + .ret => .incompatible_return, + .arg => .incompatible_arg, + .test_coerce => return error.CoercionFailed, + }, tok, try ctx.typePairStr(p, dest_ty, res.ty)); + try ctx.note(p); + } +}; + +/// expr : assignExpr (',' assignExpr)* +fn expr(p: *Parser) Error!Result { + var expr_start = p.tok_i; + var err_start = p.comp.diag.list.items.len; + var lhs = try p.assignExpr(); + if (p.tok_ids[p.tok_i] == .comma) try lhs.expect(p); + while (p.eatToken(.comma)) |_| { + try lhs.maybeWarnUnused(p, expr_start, err_start); + expr_start = p.tok_i; + err_start = p.comp.diag.list.items.len; + + var rhs = try p.assignExpr(); + try rhs.expect(p); + try rhs.lvalConversion(p); + lhs.val = rhs.val; + lhs.ty = rhs.ty; + try lhs.bin(p, .comma_expr, rhs); + } + return lhs; +} + +fn tokToTag(p: *Parser, tok: TokenIndex) Tree.Tag { + return switch (p.tok_ids[tok]) { + .equal => .assign_expr, + .asterisk_equal => .mul_assign_expr, + .slash_equal => .div_assign_expr, + .percent_equal => .mod_assign_expr, + .plus_equal => .add_assign_expr, + .minus_equal => .sub_assign_expr, + .angle_bracket_angle_bracket_left_equal => .shl_assign_expr, + .angle_bracket_angle_bracket_right_equal => .shr_assign_expr, + .ampersand_equal => .bit_and_assign_expr, + .caret_equal => .bit_xor_assign_expr, + .pipe_equal => .bit_or_assign_expr, + .equal_equal => .equal_expr, + .bang_equal => .not_equal_expr, + .angle_bracket_left => .less_than_expr, + .angle_bracket_left_equal => .less_than_equal_expr, + .angle_bracket_right => .greater_than_expr, + .angle_bracket_right_equal => .greater_than_equal_expr, + .angle_bracket_angle_bracket_left => .shl_expr, + .angle_bracket_angle_bracket_right => .shr_expr, + .plus => .add_expr, + .minus => .sub_expr, + .asterisk => .mul_expr, + .slash => .div_expr, + .percent => .mod_expr, + else => unreachable, + }; +} + +/// assignExpr +/// : condExpr +/// | unExpr ('=' | '*=' | '/=' | '%=' | '+=' | '-=' | '<<=' | '>>=' | '&=' | '^=' | '|=') assignExpr +fn assignExpr(p: *Parser) Error!Result { + var lhs = try p.condExpr(); + if (lhs.empty(p)) return lhs; + + const tok = p.tok_i; + const eq = p.eatToken(.equal); + const mul = eq orelse p.eatToken(.asterisk_equal); + const div = mul orelse p.eatToken(.slash_equal); + const mod = div orelse p.eatToken(.percent_equal); + const add = mod orelse p.eatToken(.plus_equal); + const sub = add orelse p.eatToken(.minus_equal); + const shl = sub orelse p.eatToken(.angle_bracket_angle_bracket_left_equal); + const shr = shl orelse p.eatToken(.angle_bracket_angle_bracket_right_equal); + const bit_and = shr orelse p.eatToken(.ampersand_equal); + const bit_xor = bit_and orelse p.eatToken(.caret_equal); + const bit_or = bit_xor orelse p.eatToken(.pipe_equal); + + const tag = p.tokToTag(bit_or orelse return lhs); + var rhs = try p.assignExpr(); + try rhs.expect(p); + try rhs.lvalConversion(p); + + var is_const: bool = undefined; + if (!Tree.isLvalExtra(p.nodes.slice(), p.data.items, p.value_map, lhs.node, &is_const) or is_const) { + try p.errTok(.not_assignable, tok); + return error.ParsingFailed; + } + + // adjustTypes will do do lvalue conversion but we do not want that + var lhs_copy = lhs; + switch (tag) { + .assign_expr => {}, // handle plain assignment separately + .mul_assign_expr, + .div_assign_expr, + .mod_assign_expr, + => { + if (rhs.val.isZero() and lhs.ty.isInt() and rhs.ty.isInt()) { + switch (tag) { + .div_assign_expr => try p.errStr(.division_by_zero, div.?, "division"), + .mod_assign_expr => try p.errStr(.division_by_zero, mod.?, "remainder"), + else => {}, + } + } + _ = try lhs_copy.adjustTypes(tok, &rhs, p, if (tag == .mod_assign_expr) .integer else .arithmetic); + try lhs.bin(p, tag, rhs); + return lhs; + }, + .sub_assign_expr, + .add_assign_expr, + => { + if (lhs.ty.isPtr() and rhs.ty.isInt()) { + try rhs.ptrCast(p, lhs.ty); + } else { + _ = try lhs_copy.adjustTypes(tok, &rhs, p, .arithmetic); + } + try lhs.bin(p, tag, rhs); + return lhs; + }, + .shl_assign_expr, + .shr_assign_expr, + .bit_and_assign_expr, + .bit_xor_assign_expr, + .bit_or_assign_expr, + => { + _ = try lhs_copy.adjustTypes(tok, &rhs, p, .integer); + try lhs.bin(p, tag, rhs); + return lhs; + }, + else => unreachable, + } + + try rhs.coerce(p, lhs.ty, tok, .assign); + + try lhs.bin(p, tag, rhs); + return lhs; +} + +/// Returns a parse error if the expression is not an integer constant +/// integerConstExpr : constExpr +fn integerConstExpr(p: *Parser, decl_folding: ConstDeclFoldingMode) Error!Result { + const start = p.tok_i; + const res = try p.constExpr(decl_folding); + if (!res.ty.isInt() and res.ty.specifier != .invalid) { + try p.errTok(.expected_integer_constant_expr, start); + return error.ParsingFailed; + } + return res; +} + +/// Caller is responsible for issuing a diagnostic if result is invalid/unavailable +/// constExpr : condExpr +fn constExpr(p: *Parser, decl_folding: ConstDeclFoldingMode) Error!Result { + const const_decl_folding = p.const_decl_folding; + defer p.const_decl_folding = const_decl_folding; + p.const_decl_folding = decl_folding; + + const res = try p.condExpr(); + try res.expect(p); + + if (res.ty.specifier == .invalid or res.val.tag == .unavailable) return res; + + // saveValue sets val to unavailable + var copy = res; + try copy.saveValue(p); + return res; +} + +/// condExpr : lorExpr ('?' expression? ':' condExpr)? +fn condExpr(p: *Parser) Error!Result { + const cond_tok = p.tok_i; + var cond = try p.lorExpr(); + if (cond.empty(p) or p.eatToken(.question_mark) == null) return cond; + try cond.lvalConversion(p); + const saved_eval = p.no_eval; + + if (!cond.ty.isScalar()) { + try p.errStr(.cond_expr_type, cond_tok, try p.typeStr(cond.ty)); + return error.ParsingFailed; + } + + // Prepare for possible binary conditional expression. + var maybe_colon = p.eatToken(.colon); + + // Depending on the value of the condition, avoid evaluating unreachable branches. + var then_expr = blk: { + defer p.no_eval = saved_eval; + if (cond.val.tag != .unavailable and !cond.val.getBool()) p.no_eval = true; + break :blk try p.expr(); + }; + try then_expr.expect(p); + + // If we saw a colon then this is a binary conditional expression. + if (maybe_colon) |colon| { + var cond_then = cond; + cond_then.node = try p.addNode(.{ .tag = .cond_dummy_expr, .ty = cond.ty, .data = .{ .un = cond.node } }); + _ = try cond_then.adjustTypes(colon, &then_expr, p, .conditional); + cond.ty = then_expr.ty; + cond.node = try p.addNode(.{ + .tag = .binary_cond_expr, + .ty = cond.ty, + .data = .{ .if3 = .{ .cond = cond.node, .body = (try p.addList(&.{ cond_then.node, then_expr.node })).start } }, + }); + return cond; + } + + const colon = try p.expectToken(.colon); + var else_expr = blk: { + defer p.no_eval = saved_eval; + if (cond.val.tag != .unavailable and cond.val.getBool()) p.no_eval = true; + break :blk try p.condExpr(); + }; + try else_expr.expect(p); + + _ = try then_expr.adjustTypes(colon, &else_expr, p, .conditional); + + if (cond.val.tag != .unavailable) { + cond.val = if (cond.val.getBool()) then_expr.val else else_expr.val; + } else { + try then_expr.saveValue(p); + try else_expr.saveValue(p); + } + cond.ty = then_expr.ty; + cond.node = try p.addNode(.{ + .tag = .cond_expr, + .ty = cond.ty, + .data = .{ .if3 = .{ .cond = cond.node, .body = (try p.addList(&.{ then_expr.node, else_expr.node })).start } }, + }); + return cond; +} + +/// lorExpr : landExpr ('||' landExpr)* +fn lorExpr(p: *Parser) Error!Result { + var lhs = try p.landExpr(); + if (lhs.empty(p)) return lhs; + const saved_eval = p.no_eval; + defer p.no_eval = saved_eval; + + while (p.eatToken(.pipe_pipe)) |tok| { + if (lhs.val.tag != .unavailable and lhs.val.getBool()) p.no_eval = true; + var rhs = try p.landExpr(); + try rhs.expect(p); + + if (try lhs.adjustTypes(tok, &rhs, p, .boolean_logic)) { + const res = @intFromBool(lhs.val.getBool() or rhs.val.getBool()); + lhs.val = Value.int(res); + } + try lhs.boolRes(p, .bool_or_expr, rhs); + } + return lhs; +} + +/// landExpr : orExpr ('&&' orExpr)* +fn landExpr(p: *Parser) Error!Result { + var lhs = try p.orExpr(); + if (lhs.empty(p)) return lhs; + const saved_eval = p.no_eval; + defer p.no_eval = saved_eval; + + while (p.eatToken(.ampersand_ampersand)) |tok| { + if (lhs.val.tag != .unavailable and !lhs.val.getBool()) p.no_eval = true; + var rhs = try p.orExpr(); + try rhs.expect(p); + + if (try lhs.adjustTypes(tok, &rhs, p, .boolean_logic)) { + const res = @intFromBool(lhs.val.getBool() and rhs.val.getBool()); + lhs.val = Value.int(res); + } + try lhs.boolRes(p, .bool_and_expr, rhs); + } + return lhs; +} + +/// orExpr : xorExpr ('|' xorExpr)* +fn orExpr(p: *Parser) Error!Result { + var lhs = try p.xorExpr(); + if (lhs.empty(p)) return lhs; + while (p.eatToken(.pipe)) |tok| { + var rhs = try p.xorExpr(); + try rhs.expect(p); + + if (try lhs.adjustTypes(tok, &rhs, p, .integer)) { + lhs.val = lhs.val.bitOr(rhs.val, lhs.ty, p.comp); + } + try lhs.bin(p, .bit_or_expr, rhs); + } + return lhs; +} + +/// xorExpr : andExpr ('^' andExpr)* +fn xorExpr(p: *Parser) Error!Result { + var lhs = try p.andExpr(); + if (lhs.empty(p)) return lhs; + while (p.eatToken(.caret)) |tok| { + var rhs = try p.andExpr(); + try rhs.expect(p); + + if (try lhs.adjustTypes(tok, &rhs, p, .integer)) { + lhs.val = lhs.val.bitXor(rhs.val, lhs.ty, p.comp); + } + try lhs.bin(p, .bit_xor_expr, rhs); + } + return lhs; +} + +/// andExpr : eqExpr ('&' eqExpr)* +fn andExpr(p: *Parser) Error!Result { + var lhs = try p.eqExpr(); + if (lhs.empty(p)) return lhs; + while (p.eatToken(.ampersand)) |tok| { + var rhs = try p.eqExpr(); + try rhs.expect(p); + + if (try lhs.adjustTypes(tok, &rhs, p, .integer)) { + lhs.val = lhs.val.bitAnd(rhs.val, lhs.ty, p.comp); + } + try lhs.bin(p, .bit_and_expr, rhs); + } + return lhs; +} + +/// eqExpr : compExpr (('==' | '!=') compExpr)* +fn eqExpr(p: *Parser) Error!Result { + var lhs = try p.compExpr(); + if (lhs.empty(p)) return lhs; + while (true) { + const eq = p.eatToken(.equal_equal); + const ne = eq orelse p.eatToken(.bang_equal); + const tag = p.tokToTag(ne orelse break); + var rhs = try p.compExpr(); + try rhs.expect(p); + + if (try lhs.adjustTypes(ne.?, &rhs, p, .equality)) { + const op: std.math.CompareOperator = if (tag == .equal_expr) .eq else .neq; + const res = lhs.val.compare(op, rhs.val, lhs.ty, p.comp); + lhs.val = Value.int(@intFromBool(res)); + } + try lhs.boolRes(p, tag, rhs); + } + return lhs; +} + +/// compExpr : shiftExpr (('<' | '<=' | '>' | '>=') shiftExpr)* +fn compExpr(p: *Parser) Error!Result { + var lhs = try p.shiftExpr(); + if (lhs.empty(p)) return lhs; + while (true) { + const lt = p.eatToken(.angle_bracket_left); + const le = lt orelse p.eatToken(.angle_bracket_left_equal); + const gt = le orelse p.eatToken(.angle_bracket_right); + const ge = gt orelse p.eatToken(.angle_bracket_right_equal); + const tag = p.tokToTag(ge orelse break); + var rhs = try p.shiftExpr(); + try rhs.expect(p); + + if (try lhs.adjustTypes(ge.?, &rhs, p, .relational)) { + const op: std.math.CompareOperator = switch (tag) { + .less_than_expr => .lt, + .less_than_equal_expr => .lte, + .greater_than_expr => .gt, + .greater_than_equal_expr => .gte, + else => unreachable, + }; + const res = lhs.val.compare(op, rhs.val, lhs.ty, p.comp); + lhs.val = Value.int(@intFromBool(res)); + } + try lhs.boolRes(p, tag, rhs); + } + return lhs; +} + +/// shiftExpr : addExpr (('<<' | '>>') addExpr)* +fn shiftExpr(p: *Parser) Error!Result { + var lhs = try p.addExpr(); + if (lhs.empty(p)) return lhs; + while (true) { + const shl = p.eatToken(.angle_bracket_angle_bracket_left); + const shr = shl orelse p.eatToken(.angle_bracket_angle_bracket_right); + const tag = p.tokToTag(shr orelse break); + var rhs = try p.addExpr(); + try rhs.expect(p); + + if (try lhs.adjustTypes(shr.?, &rhs, p, .integer)) { + if (shl != null) { + lhs.val = lhs.val.shl(rhs.val, lhs.ty, p.comp); + } else { + lhs.val = lhs.val.shr(rhs.val, lhs.ty, p.comp); + } + } + try lhs.bin(p, tag, rhs); + } + return lhs; +} + +/// addExpr : mulExpr (('+' | '-') mulExpr)* +fn addExpr(p: *Parser) Error!Result { + var lhs = try p.mulExpr(); + if (lhs.empty(p)) return lhs; + while (true) { + const plus = p.eatToken(.plus); + const minus = plus orelse p.eatToken(.minus); + const tag = p.tokToTag(minus orelse break); + var rhs = try p.mulExpr(); + try rhs.expect(p); + + const lhs_ty = lhs.ty; + if (try lhs.adjustTypes(minus.?, &rhs, p, if (plus != null) .add else .sub)) { + if (plus != null) { + if (lhs.val.add(lhs.val, rhs.val, lhs.ty, p.comp)) try p.errOverflow(plus.?, lhs); + } else { + if (lhs.val.sub(lhs.val, rhs.val, lhs.ty, p.comp)) try p.errOverflow(minus.?, lhs); + } + } + if (lhs.ty.specifier != .invalid and lhs_ty.isPtr() and !lhs_ty.isVoidStar() and lhs_ty.elemType().hasIncompleteSize()) { + try p.errStr(.ptr_arithmetic_incomplete, minus.?, try p.typeStr(lhs_ty.elemType())); + lhs.ty = Type.invalid; + } + try lhs.bin(p, tag, rhs); + } + return lhs; +} + +/// mulExpr : castExpr (('*' | '/' | '%') castExpr)*´ +fn mulExpr(p: *Parser) Error!Result { + var lhs = try p.castExpr(); + if (lhs.empty(p)) return lhs; + while (true) { + const mul = p.eatToken(.asterisk); + const div = mul orelse p.eatToken(.slash); + const percent = div orelse p.eatToken(.percent); + const tag = p.tokToTag(percent orelse break); + var rhs = try p.castExpr(); + try rhs.expect(p); + + if (rhs.val.isZero() and mul == null and !p.no_eval and lhs.ty.isInt() and rhs.ty.isInt()) { + const err_tag: Diagnostics.Tag = if (p.in_macro) .division_by_zero_macro else .division_by_zero; + lhs.val.tag = .unavailable; + if (div != null) { + try p.errStr(err_tag, div.?, "division"); + } else { + try p.errStr(err_tag, percent.?, "remainder"); + } + if (p.in_macro) return error.ParsingFailed; + } + + if (try lhs.adjustTypes(percent.?, &rhs, p, if (tag == .mod_expr) .integer else .arithmetic)) { + if (mul != null) { + if (lhs.val.mul(lhs.val, rhs.val, lhs.ty, p.comp)) try p.errOverflow(mul.?, lhs); + } else if (div != null) { + lhs.val = Value.div(lhs.val, rhs.val, lhs.ty, p.comp); + } else { + var res = Value.rem(lhs.val, rhs.val, lhs.ty, p.comp); + if (res.tag == .unavailable) { + if (p.in_macro) { + // match clang behavior by defining invalid remainder to be zero in macros + res = Value.int(0); + } else { + try lhs.saveValue(p); + try rhs.saveValue(p); + } + } + lhs.val = res; + } + } + + try lhs.bin(p, tag, rhs); + } + return lhs; +} + +/// This will always be the last message, if present +fn removeUnusedWarningForTok(p: *Parser, last_expr_tok: TokenIndex) void { + if (last_expr_tok == 0) return; + if (p.comp.diag.list.items.len == 0) return; + + const last_expr_loc = p.pp.tokens.items(.loc)[last_expr_tok]; + const last_msg = p.comp.diag.list.items[p.comp.diag.list.items.len - 1]; + + if (last_msg.tag == .unused_value and last_msg.loc.eql(last_expr_loc)) { + p.comp.diag.list.items.len = p.comp.diag.list.items.len - 1; + } +} + +/// castExpr +/// : '(' compoundStmt ')' +/// | '(' typeName ')' castExpr +/// | '(' typeName ')' '{' initializerItems '}' +/// | __builtin_choose_expr '(' integerConstExpr ',' assignExpr ',' assignExpr ')' +/// | __builtin_va_arg '(' assignExpr ',' typeName ')' +/// | __builtin_offsetof '(' typeName ',' offsetofMemberDesignator ')' +/// | __builtin_bitoffsetof '(' typeName ',' offsetofMemberDesignator ')' +/// | unExpr +fn castExpr(p: *Parser) Error!Result { + if (p.eatToken(.l_paren)) |l_paren| cast_expr: { + if (p.tok_ids[p.tok_i] == .l_brace) { + try p.err(.gnu_statement_expression); + if (p.func.ty == null) { + try p.err(.stmt_expr_not_allowed_file_scope); + return error.ParsingFailed; + } + var stmt_expr_state: StmtExprState = .{}; + const body_node = (try p.compoundStmt(false, &stmt_expr_state)).?; // compoundStmt only returns null if .l_brace isn't the first token + p.removeUnusedWarningForTok(stmt_expr_state.last_expr_tok); + + var res = Result{ + .node = body_node, + .ty = stmt_expr_state.last_expr_res.ty, + .val = stmt_expr_state.last_expr_res.val, + }; + try p.expectClosing(l_paren, .r_paren); + try res.un(p, .stmt_expr); + return res; + } + const ty = (try p.typeName()) orelse { + p.tok_i -= 1; + break :cast_expr; + }; + try p.expectClosing(l_paren, .r_paren); + + if (p.tok_ids[p.tok_i] == .l_brace) { + // Compound literal; handled in unExpr + p.tok_i = l_paren; + break :cast_expr; + } + + var operand = try p.castExpr(); + try operand.expect(p); + try operand.lvalConversion(p); + try operand.castType(p, ty, l_paren); + return operand; + } + switch (p.tok_ids[p.tok_i]) { + .builtin_choose_expr => return p.builtinChooseExpr(), + .builtin_va_arg => return p.builtinVaArg(), + .builtin_offsetof => return p.builtinOffsetof(false), + .builtin_bitoffsetof => return p.builtinOffsetof(true), + .builtin_types_compatible_p => return p.typesCompatible(), + // TODO: other special-cased builtins + else => {}, + } + return p.unExpr(); +} + +fn typesCompatible(p: *Parser) Error!Result { + p.tok_i += 1; + const l_paren = try p.expectToken(.l_paren); + + const first = (try p.typeName()) orelse { + try p.err(.expected_type); + p.skipTo(.r_paren); + return error.ParsingFailed; + }; + const lhs = try p.addNode(.{ .tag = .invalid, .ty = first, .data = undefined }); + _ = try p.expectToken(.comma); + + const second = (try p.typeName()) orelse { + try p.err(.expected_type); + p.skipTo(.r_paren); + return error.ParsingFailed; + }; + const rhs = try p.addNode(.{ .tag = .invalid, .ty = second, .data = undefined }); + + try p.expectClosing(l_paren, .r_paren); + + const compatible = first.compatible(second, p.comp); + + var res = Result{ + .val = Value.int(@intFromBool(compatible)), + .node = try p.addNode(.{ .tag = .builtin_types_compatible_p, .ty = Type.int, .data = .{ .bin = .{ + .lhs = lhs, + .rhs = rhs, + } } }), + }; + try p.value_map.put(res.node, res.val); + return res; +} + +fn builtinChooseExpr(p: *Parser) Error!Result { + p.tok_i += 1; + const l_paren = try p.expectToken(.l_paren); + const cond_tok = p.tok_i; + var cond = try p.integerConstExpr(.no_const_decl_folding); + if (cond.val.tag == .unavailable) { + try p.errTok(.builtin_choose_cond, cond_tok); + return error.ParsingFailed; + } + + _ = try p.expectToken(.comma); + + var then_expr = if (cond.val.getBool()) try p.assignExpr() else try p.parseNoEval(assignExpr); + try then_expr.expect(p); + + _ = try p.expectToken(.comma); + + var else_expr = if (!cond.val.getBool()) try p.assignExpr() else try p.parseNoEval(assignExpr); + try else_expr.expect(p); + + try p.expectClosing(l_paren, .r_paren); + + if (cond.val.getBool()) { + cond.val = then_expr.val; + cond.ty = then_expr.ty; + } else { + cond.val = else_expr.val; + cond.ty = else_expr.ty; + } + cond.node = try p.addNode(.{ + .tag = .builtin_choose_expr, + .ty = cond.ty, + .data = .{ .if3 = .{ .cond = cond.node, .body = (try p.addList(&.{ then_expr.node, else_expr.node })).start } }, + }); + return cond; +} + +fn builtinVaArg(p: *Parser) Error!Result { + const builtin_tok = p.tok_i; + p.tok_i += 1; + + const l_paren = try p.expectToken(.l_paren); + const va_list_tok = p.tok_i; + var va_list = try p.assignExpr(); + try va_list.expect(p); + try va_list.lvalConversion(p); + + _ = try p.expectToken(.comma); + + const ty = (try p.typeName()) orelse { + try p.err(.expected_type); + return error.ParsingFailed; + }; + try p.expectClosing(l_paren, .r_paren); + + if (!va_list.ty.eql(p.comp.types.va_list, p.comp, true)) { + try p.errStr(.incompatible_va_arg, va_list_tok, try p.typeStr(va_list.ty)); + return error.ParsingFailed; + } + + return Result{ .ty = ty, .node = try p.addNode(.{ + .tag = .special_builtin_call_one, + .ty = ty, + .data = .{ .decl = .{ .name = builtin_tok, .node = va_list.node } }, + }) }; +} + +fn builtinOffsetof(p: *Parser, want_bits: bool) Error!Result { + const builtin_tok = p.tok_i; + p.tok_i += 1; + + const l_paren = try p.expectToken(.l_paren); + const ty_tok = p.tok_i; + + const ty = (try p.typeName()) orelse { + try p.err(.expected_type); + p.skipTo(.r_paren); + return error.ParsingFailed; + }; + + if (!ty.isRecord()) { + try p.errStr(.offsetof_ty, ty_tok, try p.typeStr(ty)); + p.skipTo(.r_paren); + return error.ParsingFailed; + } else if (ty.hasIncompleteSize()) { + try p.errStr(.offsetof_incomplete, ty_tok, try p.typeStr(ty)); + p.skipTo(.r_paren); + return error.ParsingFailed; + } + + _ = try p.expectToken(.comma); + + const offsetof_expr = try p.offsetofMemberDesignator(ty); + + try p.expectClosing(l_paren, .r_paren); + + return Result{ + .ty = p.comp.types.size, + .val = if (offsetof_expr.val.tag == .int and !want_bits) + Value.int(offsetof_expr.val.data.int / 8) + else + offsetof_expr.val, + .node = try p.addNode(.{ + .tag = .special_builtin_call_one, + .ty = p.comp.types.size, + .data = .{ .decl = .{ .name = builtin_tok, .node = offsetof_expr.node } }, + }), + }; +} + +/// offsetofMemberDesignator: IDENTIFIER ('.' IDENTIFIER | '[' expr ']' )* +fn offsetofMemberDesignator(p: *Parser, base_ty: Type) Error!Result { + errdefer p.skipTo(.r_paren); + const base_field_name_tok = try p.expectIdentifier(); + const base_field_name = try p.comp.intern(p.tokSlice(base_field_name_tok)); + try p.validateFieldAccess(base_ty, base_ty, base_field_name_tok, base_field_name); + const base_node = try p.addNode(.{ .tag = .default_init_expr, .ty = base_ty, .data = undefined }); + + var offset_num: u64 = 0; + const base_record_ty = base_ty.canonicalize(.standard); + var lhs = try p.fieldAccessExtra(base_node, base_record_ty, base_field_name, false, &offset_num); + var bit_offset = Value.int(offset_num); + + while (true) switch (p.tok_ids[p.tok_i]) { + .period => { + p.tok_i += 1; + const field_name_tok = try p.expectIdentifier(); + const field_name = try p.comp.intern(p.tokSlice(field_name_tok)); + + if (!lhs.ty.isRecord()) { + try p.errStr(.offsetof_ty, field_name_tok, try p.typeStr(lhs.ty)); + return error.ParsingFailed; + } + try p.validateFieldAccess(lhs.ty, lhs.ty, field_name_tok, field_name); + const record_ty = lhs.ty.canonicalize(.standard); + lhs = try p.fieldAccessExtra(lhs.node, record_ty, field_name, false, &offset_num); + if (bit_offset.tag != .unavailable) { + bit_offset = Value.int(offset_num + bit_offset.getInt(u64)); + } + }, + .l_bracket => { + const l_bracket_tok = p.tok_i; + p.tok_i += 1; + var index = try p.expr(); + try index.expect(p); + _ = try p.expectClosing(l_bracket_tok, .r_bracket); + + if (!lhs.ty.isArray()) { + try p.errStr(.offsetof_array, l_bracket_tok, try p.typeStr(lhs.ty)); + return error.ParsingFailed; + } + var ptr = lhs; + try ptr.lvalConversion(p); + try index.lvalConversion(p); + + if (!index.ty.isInt()) try p.errTok(.invalid_index, l_bracket_tok); + try p.checkArrayBounds(index, lhs, l_bracket_tok); + + try index.saveValue(p); + try ptr.bin(p, .array_access_expr, index); + lhs = ptr; + }, + else => break, + }; + + return Result{ .ty = base_ty, .val = bit_offset, .node = lhs.node }; +} + +/// unExpr +/// : (compoundLiteral | primaryExpr) suffixExpr* +/// | '&&' IDENTIFIER +/// | ('&' | '*' | '+' | '-' | '~' | '!' | '++' | '--' | keyword_extension | keyword_imag | keyword_real) castExpr +/// | keyword_sizeof unExpr +/// | keyword_sizeof '(' typeName ')' +/// | keyword_alignof '(' typeName ')' +/// | keyword_c23_alignof '(' typeName ')' +fn unExpr(p: *Parser) Error!Result { + const tok = p.tok_i; + switch (p.tok_ids[tok]) { + .ampersand_ampersand => { + const address_tok = p.tok_i; + p.tok_i += 1; + const name_tok = try p.expectIdentifier(); + try p.errTok(.gnu_label_as_value, address_tok); + p.contains_address_of_label = true; + + const str = p.tokSlice(name_tok); + if (p.findLabel(str) == null) { + try p.labels.append(.{ .unresolved_goto = name_tok }); + } + const elem_ty = try p.arena.create(Type); + elem_ty.* = .{ .specifier = .void }; + const result_ty = Type{ .specifier = .pointer, .data = .{ .sub_type = elem_ty } }; + return Result{ + .node = try p.addNode(.{ + .tag = .addr_of_label, + .data = .{ .decl_ref = name_tok }, + .ty = result_ty, + }), + .ty = result_ty, + }; + }, + .ampersand => { + if (p.in_macro) { + try p.err(.invalid_preproc_operator); + return error.ParsingFailed; + } + p.tok_i += 1; + var operand = try p.castExpr(); + try operand.expect(p); + + const slice = p.nodes.slice(); + if (p.getNode(operand.node, .member_access_expr) orelse p.getNode(operand.node, .member_access_ptr_expr)) |member_node| { + if (Tree.isBitfield(slice, member_node)) try p.errTok(.addr_of_bitfield, tok); + } + if (!Tree.isLval(slice, p.data.items, p.value_map, operand.node)) { + try p.errTok(.addr_of_rvalue, tok); + } + if (operand.ty.qual.register) try p.errTok(.addr_of_register, tok); + + const elem_ty = try p.arena.create(Type); + elem_ty.* = operand.ty; + operand.ty = Type{ + .specifier = .pointer, + .data = .{ .sub_type = elem_ty }, + }; + try operand.saveValue(p); + try operand.un(p, .addr_of_expr); + return operand; + }, + .asterisk => { + const asterisk_loc = p.tok_i; + p.tok_i += 1; + var operand = try p.castExpr(); + try operand.expect(p); + + if (operand.ty.isArray() or operand.ty.isPtr() or operand.ty.isFunc()) { + try operand.lvalConversion(p); + operand.ty = operand.ty.elemType(); + } else { + try p.errTok(.indirection_ptr, tok); + } + if (operand.ty.hasIncompleteSize() and !operand.ty.is(.void)) { + try p.errStr(.deref_incomplete_ty_ptr, asterisk_loc, try p.typeStr(operand.ty)); + } + operand.ty.qual = .{}; + try operand.un(p, .deref_expr); + return operand; + }, + .plus => { + p.tok_i += 1; + + var operand = try p.castExpr(); + try operand.expect(p); + try operand.lvalConversion(p); + if (!operand.ty.isInt() and !operand.ty.isFloat()) + try p.errStr(.invalid_argument_un, tok, try p.typeStr(operand.ty)); + + try operand.usualUnaryConversion(p, tok); + + return operand; + }, + .minus => { + p.tok_i += 1; + + var operand = try p.castExpr(); + try operand.expect(p); + try operand.lvalConversion(p); + if (!operand.ty.isInt() and !operand.ty.isFloat()) + try p.errStr(.invalid_argument_un, tok, try p.typeStr(operand.ty)); + + try operand.usualUnaryConversion(p, tok); + if (operand.val.tag == .int or operand.val.tag == .float) { + _ = operand.val.sub(operand.val.zero(), operand.val, operand.ty, p.comp); + } else { + operand.val.tag = .unavailable; + } + try operand.un(p, .negate_expr); + return operand; + }, + .plus_plus => { + p.tok_i += 1; + + var operand = try p.castExpr(); + try operand.expect(p); + if (!operand.ty.isScalar()) + try p.errStr(.invalid_argument_un, tok, try p.typeStr(operand.ty)); + if (operand.ty.isComplex()) + try p.errStr(.complex_prefix_postfix_op, p.tok_i, try p.typeStr(operand.ty)); + + if (!Tree.isLval(p.nodes.slice(), p.data.items, p.value_map, operand.node) or operand.ty.isConst()) { + try p.errTok(.not_assignable, tok); + return error.ParsingFailed; + } + try operand.usualUnaryConversion(p, tok); + + if (operand.val.tag == .int or operand.val.tag == .float) { + if (operand.val.add(operand.val, operand.val.one(), operand.ty, p.comp)) + try p.errOverflow(tok, operand); + } else { + operand.val.tag = .unavailable; + } + + try operand.un(p, .pre_inc_expr); + return operand; + }, + .minus_minus => { + p.tok_i += 1; + + var operand = try p.castExpr(); + try operand.expect(p); + if (!operand.ty.isScalar()) + try p.errStr(.invalid_argument_un, tok, try p.typeStr(operand.ty)); + if (operand.ty.isComplex()) + try p.errStr(.complex_prefix_postfix_op, p.tok_i, try p.typeStr(operand.ty)); + + if (!Tree.isLval(p.nodes.slice(), p.data.items, p.value_map, operand.node) or operand.ty.isConst()) { + try p.errTok(.not_assignable, tok); + return error.ParsingFailed; + } + try operand.usualUnaryConversion(p, tok); + + if (operand.val.tag == .int or operand.val.tag == .float) { + if (operand.val.sub(operand.val, operand.val.one(), operand.ty, p.comp)) + try p.errOverflow(tok, operand); + } else { + operand.val.tag = .unavailable; + } + + try operand.un(p, .pre_dec_expr); + return operand; + }, + .tilde => { + p.tok_i += 1; + + var operand = try p.castExpr(); + try operand.expect(p); + try operand.lvalConversion(p); + try operand.usualUnaryConversion(p, tok); + if (operand.ty.isInt()) { + if (operand.val.tag == .int) { + operand.val = operand.val.bitNot(operand.ty, p.comp); + } + } else { + try p.errStr(.invalid_argument_un, tok, try p.typeStr(operand.ty)); + operand.val.tag = .unavailable; + } + try operand.un(p, .bit_not_expr); + return operand; + }, + .bang => { + p.tok_i += 1; + + var operand = try p.castExpr(); + try operand.expect(p); + try operand.lvalConversion(p); + if (!operand.ty.isScalar()) + try p.errStr(.invalid_argument_un, tok, try p.typeStr(operand.ty)); + + try operand.usualUnaryConversion(p, tok); + if (operand.val.tag == .int) { + const res = Value.int(@intFromBool(!operand.val.getBool())); + operand.val = res; + } else if (operand.val.tag == .nullptr_t) { + operand.val = Value.int(1); + } else { + if (operand.ty.isDecayed()) { + operand.val = Value.int(0); + } else { + operand.val.tag = .unavailable; + } + } + operand.ty = .{ .specifier = .int }; + try operand.un(p, .bool_not_expr); + return operand; + }, + .keyword_sizeof => { + p.tok_i += 1; + const expected_paren = p.tok_i; + var res = Result{}; + if (try p.typeName()) |ty| { + res.ty = ty; + try p.errTok(.expected_parens_around_typename, expected_paren); + } else if (p.eatToken(.l_paren)) |l_paren| { + if (try p.typeName()) |ty| { + res.ty = ty; + try p.expectClosing(l_paren, .r_paren); + } else { + p.tok_i = expected_paren; + res = try p.parseNoEval(unExpr); + } + } else { + res = try p.parseNoEval(unExpr); + } + + if (res.ty.is(.void)) { + try p.errStr(.pointer_arith_void, tok, "sizeof"); + } else if (res.ty.isDecayed()) { + const array_ty = res.ty.originalTypeOfDecayedArray(); + const err_str = try p.typePairStrExtra(res.ty, " instead of ", array_ty); + try p.errStr(.sizeof_array_arg, tok, err_str); + } + if (res.ty.sizeof(p.comp)) |size| { + if (size == 0) { + try p.errTok(.sizeof_returns_zero, tok); + } + res.val = Value.int(size); + res.ty = p.comp.types.size; + } else { + res.val.tag = .unavailable; + if (res.ty.hasIncompleteSize()) { + try p.errStr(.invalid_sizeof, expected_paren - 1, try p.typeStr(res.ty)); + res.ty = Type.invalid; + } else { + res.ty = p.comp.types.size; + } + } + try res.un(p, .sizeof_expr); + return res; + }, + .keyword_alignof, + .keyword_alignof1, + .keyword_alignof2, + .keyword_c23_alignof, + => { + p.tok_i += 1; + const expected_paren = p.tok_i; + var res = Result{}; + if (try p.typeName()) |ty| { + res.ty = ty; + try p.errTok(.expected_parens_around_typename, expected_paren); + } else if (p.eatToken(.l_paren)) |l_paren| { + if (try p.typeName()) |ty| { + res.ty = ty; + try p.expectClosing(l_paren, .r_paren); + } else { + p.tok_i = expected_paren; + res = try p.parseNoEval(unExpr); + try p.errTok(.alignof_expr, expected_paren); + } + } else { + res = try p.parseNoEval(unExpr); + try p.errTok(.alignof_expr, expected_paren); + } + + if (res.ty.is(.void)) { + try p.errStr(.pointer_arith_void, tok, "alignof"); + } + if (res.ty.alignable()) { + res.val = Value.int(res.ty.alignof(p.comp)); + res.ty = p.comp.types.size; + } else { + try p.errStr(.invalid_alignof, expected_paren, try p.typeStr(res.ty)); + res.ty = Type.invalid; + } + try res.un(p, .alignof_expr); + return res; + }, + .keyword_extension => { + p.tok_i += 1; + const saved_extension = p.extension_suppressed; + defer p.extension_suppressed = saved_extension; + p.extension_suppressed = true; + + var child = try p.castExpr(); + try child.expect(p); + return child; + }, + .keyword_imag1, .keyword_imag2 => { + const imag_tok = p.tok_i; + p.tok_i += 1; + + var operand = try p.castExpr(); + try operand.expect(p); + try operand.lvalConversion(p); + if (!operand.ty.isInt() and !operand.ty.isFloat()) { + try p.errStr(.invalid_imag, imag_tok, try p.typeStr(operand.ty)); + } + if (operand.ty.isReal()) { + switch (p.comp.langopts.emulate) { + .msvc => {}, // Doesn't support `_Complex` or `__imag` in the first place + .gcc => { + if (operand.ty.isInt()) { + operand.val = Value.int(0); + } else if (operand.ty.isFloat()) { + operand.val = Value.float(0); + } + }, + .clang => { + if (operand.val.tag == .int) { + operand.val = Value.int(0); + } else { + operand.val.tag = .unavailable; + } + }, + } + } + // convert _Complex T to T + operand.ty = operand.ty.makeReal(); + try operand.un(p, .imag_expr); + return operand; + }, + .keyword_real1, .keyword_real2 => { + const real_tok = p.tok_i; + p.tok_i += 1; + + var operand = try p.castExpr(); + try operand.expect(p); + try operand.lvalConversion(p); + if (!operand.ty.isInt() and !operand.ty.isFloat()) { + try p.errStr(.invalid_real, real_tok, try p.typeStr(operand.ty)); + } + // convert _Complex T to T + operand.ty = operand.ty.makeReal(); + try operand.un(p, .real_expr); + return operand; + }, + else => { + var lhs = try p.compoundLiteral(); + if (lhs.empty(p)) { + lhs = try p.primaryExpr(); + if (lhs.empty(p)) return lhs; + } + while (true) { + const suffix = try p.suffixExpr(lhs); + if (suffix.empty(p)) break; + lhs = suffix; + } + return lhs; + }, + } +} + +/// compoundLiteral +/// : '(' type_name ')' '{' initializer_list '}' +/// | '(' type_name ')' '{' initializer_list ',' '}' +fn compoundLiteral(p: *Parser) Error!Result { + const l_paren = p.eatToken(.l_paren) orelse return Result{}; + const ty = (try p.typeName()) orelse { + p.tok_i = l_paren; + return Result{}; + }; + try p.expectClosing(l_paren, .r_paren); + + if (ty.isFunc()) { + try p.err(.func_init); + } else if (ty.is(.variable_len_array)) { + try p.err(.vla_init); + } else if (ty.hasIncompleteSize() and !ty.is(.incomplete_array)) { + try p.errStr(.variable_incomplete_ty, p.tok_i, try p.typeStr(ty)); + return error.ParsingFailed; + } + var init_list_expr = try p.initializer(ty); + try init_list_expr.un(p, .compound_literal_expr); + return init_list_expr; +} + +/// suffixExpr +/// : '[' expr ']' +/// | '(' argumentExprList? ')' +/// | '.' IDENTIFIER +/// | '->' IDENTIFIER +/// | '++' +/// | '--' +/// argumentExprList : assignExpr (',' assignExpr)* +fn suffixExpr(p: *Parser, lhs: Result) Error!Result { + assert(!lhs.empty(p)); + switch (p.tok_ids[p.tok_i]) { + .l_paren => return p.callExpr(lhs), + .plus_plus => { + defer p.tok_i += 1; + + var operand = lhs; + if (!operand.ty.isScalar()) + try p.errStr(.invalid_argument_un, p.tok_i, try p.typeStr(operand.ty)); + if (operand.ty.isComplex()) + try p.errStr(.complex_prefix_postfix_op, p.tok_i, try p.typeStr(operand.ty)); + + if (!Tree.isLval(p.nodes.slice(), p.data.items, p.value_map, operand.node) or operand.ty.isConst()) { + try p.err(.not_assignable); + return error.ParsingFailed; + } + try operand.usualUnaryConversion(p, p.tok_i); + + try operand.un(p, .post_inc_expr); + return operand; + }, + .minus_minus => { + defer p.tok_i += 1; + + var operand = lhs; + if (!operand.ty.isScalar()) + try p.errStr(.invalid_argument_un, p.tok_i, try p.typeStr(operand.ty)); + if (operand.ty.isComplex()) + try p.errStr(.complex_prefix_postfix_op, p.tok_i, try p.typeStr(operand.ty)); + + if (!Tree.isLval(p.nodes.slice(), p.data.items, p.value_map, operand.node) or operand.ty.isConst()) { + try p.err(.not_assignable); + return error.ParsingFailed; + } + try operand.usualUnaryConversion(p, p.tok_i); + + try operand.un(p, .post_dec_expr); + return operand; + }, + .l_bracket => { + const l_bracket = p.tok_i; + p.tok_i += 1; + var index = try p.expr(); + try index.expect(p); + try p.expectClosing(l_bracket, .r_bracket); + + const array_before_conversion = lhs; + const index_before_conversion = index; + var ptr = lhs; + try ptr.lvalConversion(p); + try index.lvalConversion(p); + if (ptr.ty.isPtr()) { + ptr.ty = ptr.ty.elemType(); + if (!index.ty.isInt()) try p.errTok(.invalid_index, l_bracket); + try p.checkArrayBounds(index_before_conversion, array_before_conversion, l_bracket); + } else if (index.ty.isPtr()) { + index.ty = index.ty.elemType(); + if (!ptr.ty.isInt()) try p.errTok(.invalid_index, l_bracket); + try p.checkArrayBounds(array_before_conversion, index_before_conversion, l_bracket); + std.mem.swap(Result, &ptr, &index); + } else { + try p.errTok(.invalid_subscript, l_bracket); + } + + try ptr.saveValue(p); + try index.saveValue(p); + try ptr.bin(p, .array_access_expr, index); + return ptr; + }, + .period => { + p.tok_i += 1; + const name = try p.expectIdentifier(); + return p.fieldAccess(lhs, name, false); + }, + .arrow => { + p.tok_i += 1; + const name = try p.expectIdentifier(); + if (lhs.ty.isArray()) { + var copy = lhs; + copy.ty.decayArray(); + try copy.implicitCast(p, .array_to_pointer); + return p.fieldAccess(copy, name, true); + } + return p.fieldAccess(lhs, name, true); + }, + else => return Result{}, + } +} + +fn fieldAccess( + p: *Parser, + lhs: Result, + field_name_tok: TokenIndex, + is_arrow: bool, +) !Result { + const expr_ty = lhs.ty; + const is_ptr = expr_ty.isPtr(); + const expr_base_ty = if (is_ptr) expr_ty.elemType() else expr_ty; + const record_ty = expr_base_ty.canonicalize(.standard); + + switch (record_ty.specifier) { + .@"struct", .@"union" => {}, + else => { + try p.errStr(.expected_record_ty, field_name_tok, try p.typeStr(expr_ty)); + return error.ParsingFailed; + }, + } + if (record_ty.hasIncompleteSize()) { + try p.errStr(.deref_incomplete_ty_ptr, field_name_tok - 2, try p.typeStr(expr_base_ty)); + return error.ParsingFailed; + } + if (is_arrow and !is_ptr) try p.errStr(.member_expr_not_ptr, field_name_tok, try p.typeStr(expr_ty)); + if (!is_arrow and is_ptr) try p.errStr(.member_expr_ptr, field_name_tok, try p.typeStr(expr_ty)); + + const field_name = try p.comp.intern(p.tokSlice(field_name_tok)); + try p.validateFieldAccess(record_ty, expr_ty, field_name_tok, field_name); + var discard: u64 = 0; + return p.fieldAccessExtra(lhs.node, record_ty, field_name, is_arrow, &discard); +} + +fn validateFieldAccess(p: *Parser, record_ty: Type, expr_ty: Type, field_name_tok: TokenIndex, field_name: StringId) Error!void { + if (record_ty.hasField(field_name)) return; + + p.strings.items.len = 0; + + try p.strings.writer().print("'{s}' in '", .{p.tokSlice(field_name_tok)}); + const mapper = p.comp.string_interner.getSlowTypeMapper(); + try expr_ty.print(mapper, p.comp.langopts, p.strings.writer()); + try p.strings.append('\''); + + const duped = try p.comp.diag.arena.allocator().dupe(u8, p.strings.items); + try p.errStr(.no_such_member, field_name_tok, duped); + return error.ParsingFailed; +} + +fn fieldAccessExtra(p: *Parser, lhs: NodeIndex, record_ty: Type, field_name: StringId, is_arrow: bool, offset_bits: *u64) Error!Result { + for (record_ty.data.record.fields, 0..) |f, i| { + if (f.isAnonymousRecord()) { + if (!f.ty.hasField(field_name)) continue; + const inner = try p.addNode(.{ + .tag = if (is_arrow) .member_access_ptr_expr else .member_access_expr, + .ty = f.ty, + .data = .{ .member = .{ .lhs = lhs, .index = @intCast(i) } }, + }); + const ret = p.fieldAccessExtra(inner, f.ty, field_name, false, offset_bits); + offset_bits.* += f.layout.offset_bits; + return ret; + } + if (field_name == f.name) { + offset_bits.* = f.layout.offset_bits; + return Result{ + .ty = f.ty, + .node = try p.addNode(.{ + .tag = if (is_arrow) .member_access_ptr_expr else .member_access_expr, + .ty = f.ty, + .data = .{ .member = .{ .lhs = lhs, .index = @intCast(i) } }, + }), + }; + } + } + // We already checked that this container has a field by the name. + unreachable; +} + +fn checkVaStartArg(p: *Parser, builtin_tok: TokenIndex, first_after: TokenIndex, param_tok: TokenIndex, arg: *Result, idx: u32) !void { + assert(idx != 0); + if (idx > 1) { + try p.errTok(.closing_paren, first_after); + return error.ParsingFailed; + } + + var func_ty = p.func.ty orelse { + try p.errTok(.va_start_not_in_func, builtin_tok); + return; + }; + const func_params = func_ty.params(); + if (func_ty.specifier != .var_args_func or func_params.len == 0) { + return p.errTok(.va_start_fixed_args, builtin_tok); + } + const last_param_name = func_params[func_params.len - 1].name; + const decl_ref = p.getNode(arg.node, .decl_ref_expr); + if (decl_ref == null or last_param_name != try p.comp.intern(p.tokSlice(p.nodes.items(.data)[@intFromEnum(decl_ref.?)].decl_ref))) { + try p.errTok(.va_start_not_last_param, param_tok); + } +} + +fn checkComplexArg(p: *Parser, builtin_tok: TokenIndex, first_after: TokenIndex, param_tok: TokenIndex, arg: *Result, idx: u32) !void { + _ = builtin_tok; + _ = first_after; + if (idx <= 1 and !arg.ty.isFloat()) { + try p.errStr(.not_floating_type, param_tok, try p.typeStr(arg.ty)); + } else if (idx == 1) { + const prev_idx = p.list_buf.items[p.list_buf.items.len - 1]; + const prev_ty = p.nodes.items(.ty)[@intFromEnum(prev_idx)]; + if (!prev_ty.eql(arg.ty, p.comp, false)) { + try p.errStr(.argument_types_differ, param_tok, try p.typePairStrExtra(prev_ty, " vs ", arg.ty)); + } + } +} + +fn checkVariableBuiltinArgument(p: *Parser, builtin_tok: TokenIndex, first_after: TokenIndex, param_tok: TokenIndex, arg: *Result, arg_idx: u32, tag: BuiltinFunction.Tag) !void { + switch (tag) { + .__builtin_va_start, .__va_start, .va_start => return p.checkVaStartArg(builtin_tok, first_after, param_tok, arg, arg_idx), + else => {}, + } +} + +fn callExpr(p: *Parser, lhs: Result) Error!Result { + const l_paren = p.tok_i; + p.tok_i += 1; + const ty = lhs.ty.isCallable() orelse { + try p.errStr(.not_callable, l_paren, try p.typeStr(lhs.ty)); + return error.ParsingFailed; + }; + const params = ty.params(); + var func = lhs; + try func.lvalConversion(p); + + const list_buf_top = p.list_buf.items.len; + defer p.list_buf.items.len = list_buf_top; + try p.list_buf.append(func.node); + var arg_count: u32 = 0; + var first_after = l_paren; + + const call_expr = CallExpr.init(p, lhs.node, func.node); + + while (p.eatToken(.r_paren) == null) { + const param_tok = p.tok_i; + if (arg_count == params.len) first_after = p.tok_i; + var arg = try p.assignExpr(); + try arg.expect(p); + + if (call_expr.shouldPerformLvalConversion(arg_count)) { + try arg.lvalConversion(p); + } + if (arg.ty.hasIncompleteSize() and !arg.ty.is(.void)) return error.ParsingFailed; + + if (arg_count >= params.len) { + if (call_expr.shouldPromoteVarArg(arg_count)) { + if (arg.ty.isInt()) try arg.intCast(p, arg.ty.integerPromotion(p.comp), param_tok); + if (arg.ty.is(.float)) try arg.floatCast(p, .{ .specifier = .double }); + } + try call_expr.checkVarArg(p, first_after, param_tok, &arg, arg_count); + try arg.saveValue(p); + try p.list_buf.append(arg.node); + arg_count += 1; + + _ = p.eatToken(.comma) orelse { + try p.expectClosing(l_paren, .r_paren); + break; + }; + continue; + } + const p_ty = params[arg_count].ty; + if (call_expr.shouldCoerceArg(arg_count)) { + try arg.coerce(p, p_ty, param_tok, .{ .arg = params[arg_count].name_tok }); + } + try arg.saveValue(p); + try p.list_buf.append(arg.node); + arg_count += 1; + + _ = p.eatToken(.comma) orelse { + try p.expectClosing(l_paren, .r_paren); + break; + }; + } + + const actual: u32 = @intCast(arg_count); + const extra = Diagnostics.Message.Extra{ .arguments = .{ + .expected = @intCast(params.len), + .actual = actual, + } }; + if (call_expr.paramCountOverride()) |expected| { + if (expected != actual) { + try p.errExtra(.expected_arguments, first_after, .{ .arguments = .{ .expected = expected, .actual = actual } }); + } + } else if (ty.is(.func) and params.len != arg_count) { + try p.errExtra(.expected_arguments, first_after, extra); + } else if (ty.is(.old_style_func) and params.len != arg_count) { + try p.errExtra(.expected_arguments_old, first_after, extra); + } else if (ty.is(.var_args_func) and arg_count < params.len) { + try p.errExtra(.expected_at_least_arguments, first_after, extra); + } + + return call_expr.finish(p, ty, list_buf_top, arg_count); +} + +fn checkArrayBounds(p: *Parser, index: Result, array: Result, tok: TokenIndex) !void { + if (index.val.tag == .unavailable) return; + + const array_len = array.ty.arrayLen() orelse return; + if (array_len == 0) return; + + if (array_len == 1) { + if (p.getNode(array.node, .member_access_expr) orelse p.getNode(array.node, .member_access_ptr_expr)) |node| { + const data = p.nodes.items(.data)[@intFromEnum(node)]; + var lhs = p.nodes.items(.ty)[@intFromEnum(data.member.lhs)]; + if (lhs.get(.pointer)) |ptr| { + lhs = ptr.data.sub_type.*; + } + if (lhs.is(.@"struct")) { + const record = lhs.getRecord().?; + if (data.member.index + 1 == record.fields.len) { + if (!index.val.isZero()) { + try p.errExtra(.old_style_flexible_struct, tok, .{ + .unsigned = index.val.data.int, + }); + } + return; + } + } + } + } + const len = Value.int(array_len); + + if (index.ty.isUnsignedInt(p.comp)) { + if (index.val.compare(.gte, len, p.comp.types.size, p.comp)) + try p.errExtra(.array_after, tok, .{ .unsigned = index.val.data.int }); + } else { + if (index.val.compare(.lt, Value.int(0), index.ty, p.comp)) { + try p.errExtra(.array_before, tok, .{ + .signed = index.val.signExtend(index.ty, p.comp), + }); + } else if (index.val.compare(.gte, len, p.comp.types.size, p.comp)) { + try p.errExtra(.array_after, tok, .{ .unsigned = index.val.data.int }); + } + } +} + +/// primaryExpr +/// : IDENTIFIER +/// | keyword_true +/// | keyword_false +/// | keyword_nullptr +/// | INTEGER_LITERAL +/// | FLOAT_LITERAL +/// | IMAGINARY_LITERAL +/// | CHAR_LITERAL +/// | STRING_LITERAL +/// | '(' expr ')' +/// | genericSelection +fn primaryExpr(p: *Parser) Error!Result { + if (p.eatToken(.l_paren)) |l_paren| { + var e = try p.expr(); + try e.expect(p); + try p.expectClosing(l_paren, .r_paren); + try e.un(p, .paren_expr); + return e; + } + switch (p.tok_ids[p.tok_i]) { + .identifier, .extended_identifier => { + const name_tok = p.expectIdentifier() catch unreachable; + const name = p.tokSlice(name_tok); + const interned_name = try p.comp.intern(name); + if (p.syms.findSymbol(interned_name)) |sym| { + try p.checkDeprecatedUnavailable(sym.ty, name_tok, sym.tok); + if (sym.kind == .constexpr) { + return Result{ + .val = sym.val, + .ty = sym.ty, + .node = try p.addNode(.{ + .tag = .decl_ref_expr, + .ty = sym.ty, + .data = .{ .decl_ref = name_tok }, + }), + }; + } + if (sym.val.tag == .int) { + switch (p.const_decl_folding) { + .gnu_folding_extension => try p.errTok(.const_decl_folded, name_tok), + .gnu_vla_folding_extension => try p.errTok(.const_decl_folded_vla, name_tok), + else => {}, + } + } + return Result{ + .val = if (p.const_decl_folding == .no_const_decl_folding and sym.kind != .enumeration) Value{} else sym.val, + .ty = sym.ty, + .node = try p.addNode(.{ + .tag = if (sym.kind == .enumeration) .enumeration_ref else .decl_ref_expr, + .ty = sym.ty, + .data = .{ .decl_ref = name_tok }, + }), + }; + } + if (try p.comp.builtins.getOrCreate(p.comp, name, p.arena)) |some| { + for (p.tok_ids[p.tok_i..]) |id| switch (id) { + .r_paren => {}, // closing grouped expr + .l_paren => break, // beginning of a call + else => { + try p.errTok(.builtin_must_be_called, name_tok); + return error.ParsingFailed; + }, + }; + if (some.builtin.properties.header != .none) { + try p.errStr(.implicit_builtin, name_tok, name); + try p.errExtra(.implicit_builtin_header_note, name_tok, .{ .builtin_with_header = .{ + .builtin = some.builtin.tag, + .header = some.builtin.properties.header, + } }); + } + + return Result{ + .ty = some.ty, + .node = try p.addNode(.{ + .tag = .builtin_call_expr_one, + .ty = some.ty, + .data = .{ .decl = .{ .name = name_tok, .node = .none } }, + }), + }; + } + if (p.tok_ids[p.tok_i] == .l_paren) { + // allow implicitly declaring functions before C99 like `puts("foo")` + if (mem.startsWith(u8, name, "__builtin_")) + try p.errStr(.unknown_builtin, name_tok, name) + else + try p.errStr(.implicit_func_decl, name_tok, name); + + const func_ty = try p.arena.create(Type.Func); + func_ty.* = .{ .return_type = .{ .specifier = .int }, .params = &.{} }; + const ty: Type = .{ .specifier = .old_style_func, .data = .{ .func = func_ty } }; + const node = try p.addNode(.{ + .ty = ty, + .tag = .fn_proto, + .data = .{ .decl = .{ .name = name_tok } }, + }); + + try p.decl_buf.append(node); + try p.syms.declareSymbol(p, interned_name, ty, name_tok, node); + + return Result{ + .ty = ty, + .node = try p.addNode(.{ + .tag = .decl_ref_expr, + .ty = ty, + .data = .{ .decl_ref = name_tok }, + }), + }; + } + try p.errStr(.undeclared_identifier, name_tok, p.tokSlice(name_tok)); + return error.ParsingFailed; + }, + .keyword_true, .keyword_false => |id| { + p.tok_i += 1; + const numeric_value = @intFromBool(id == .keyword_true); + const res = Result{ + .val = Value.int(numeric_value), + .ty = .{ .specifier = .bool }, + .node = try p.addNode(.{ + .tag = .bool_literal, + .ty = .{ .specifier = .bool }, + .data = .{ .int = numeric_value }, + }), + }; + std.debug.assert(!p.in_macro); // Should have been replaced with .one / .zero + try p.value_map.put(res.node, res.val); + return res; + }, + .keyword_nullptr => { + defer p.tok_i += 1; + try p.errStr(.pre_c2x_compat, p.tok_i, "'nullptr'"); + return Result{ + .val = .{ .tag = .nullptr_t }, + .ty = .{ .specifier = .nullptr_t }, + .node = try p.addNode(.{ + .tag = .nullptr_literal, + .ty = .{ .specifier = .nullptr_t }, + .data = undefined, + }), + }; + }, + .macro_func, .macro_function => { + defer p.tok_i += 1; + var ty: Type = undefined; + var tok = p.tok_i; + if (p.func.ident) |some| { + ty = some.ty; + tok = p.nodes.items(.data)[@intFromEnum(some.node)].decl.name; + } else if (p.func.ty) |_| { + const start: u32 = @intCast(p.retained_strings.items.len); + try p.retained_strings.appendSlice(p.tokSlice(p.func.name)); + try p.retained_strings.append(0); + const predef = try p.makePredefinedIdentifier(start); + ty = predef.ty; + p.func.ident = predef; + } else { + const start: u32 = @intCast(p.retained_strings.items.len); + try p.retained_strings.append(0); + const predef = try p.makePredefinedIdentifier(start); + ty = predef.ty; + p.func.ident = predef; + try p.decl_buf.append(predef.node); + } + if (p.func.ty == null) try p.err(.predefined_top_level); + return Result{ + .ty = ty, + .node = try p.addNode(.{ + .tag = .decl_ref_expr, + .ty = ty, + .data = .{ .decl_ref = tok }, + }), + }; + }, + .macro_pretty_func => { + defer p.tok_i += 1; + var ty: Type = undefined; + if (p.func.pretty_ident) |some| { + ty = some.ty; + } else if (p.func.ty) |func_ty| { + const mapper = p.comp.string_interner.getSlowTypeMapper(); + const start: u32 = @intCast(p.retained_strings.items.len); + try Type.printNamed(func_ty, p.tokSlice(p.func.name), mapper, p.comp.langopts, p.retained_strings.writer()); + try p.retained_strings.append(0); + const predef = try p.makePredefinedIdentifier(start); + ty = predef.ty; + p.func.pretty_ident = predef; + } else { + const start: u32 = @intCast(p.retained_strings.items.len); + try p.retained_strings.appendSlice("top level\x00"); + const predef = try p.makePredefinedIdentifier(start); + ty = predef.ty; + p.func.pretty_ident = predef; + try p.decl_buf.append(predef.node); + } + if (p.func.ty == null) try p.err(.predefined_top_level); + return Result{ + .ty = ty, + .node = try p.addNode(.{ + .tag = .decl_ref_expr, + .ty = ty, + .data = .{ .decl_ref = p.tok_i }, + }), + }; + }, + .string_literal, + .string_literal_utf_16, + .string_literal_utf_8, + .string_literal_utf_32, + .string_literal_wide, + => return p.stringLiteral(), + .char_literal, + .char_literal_utf_8, + .char_literal_utf_16, + .char_literal_utf_32, + .char_literal_wide, + => return p.charLiteral(), + .zero => { + p.tok_i += 1; + var res: Result = .{ .val = Value.int(0), .ty = if (p.in_macro) p.comp.types.intmax else Type.int }; + res.node = try p.addNode(.{ .tag = .int_literal, .ty = res.ty, .data = undefined }); + if (!p.in_macro) try p.value_map.put(res.node, res.val); + return res; + }, + .one => { + p.tok_i += 1; + var res: Result = .{ .val = Value.int(1), .ty = if (p.in_macro) p.comp.types.intmax else Type.int }; + res.node = try p.addNode(.{ .tag = .int_literal, .ty = res.ty, .data = undefined }); + if (!p.in_macro) try p.value_map.put(res.node, res.val); + return res; + }, + .pp_num => return p.ppNum(), + .embed_byte => { + assert(!p.in_macro); + const loc = p.pp.tokens.items(.loc)[p.tok_i]; + p.tok_i += 1; + const buf = p.comp.getSource(.generated).buf[loc.byte_offset..]; + var byte: u8 = buf[0] - '0'; + for (buf[1..]) |c| { + if (!std.ascii.isDigit(c)) break; + byte *= 10; + byte += c - '0'; + } + var res: Result = .{ .val = Value.int(byte) }; + res.node = try p.addNode(.{ .tag = .int_literal, .ty = res.ty, .data = undefined }); + try p.value_map.put(res.node, res.val); + return res; + }, + .keyword_generic => return p.genericSelection(), + else => return Result{}, + } +} + +fn makePredefinedIdentifier(p: *Parser, start: u32) !Result { + const end: u32 = @intCast(p.retained_strings.items.len); + const elem_ty = .{ .specifier = .char, .qual = .{ .@"const" = true } }; + const arr_ty = try p.arena.create(Type.Array); + arr_ty.* = .{ .elem = elem_ty, .len = end - start }; + const ty: Type = .{ .specifier = .array, .data = .{ .array = arr_ty } }; + + const val = Value.bytes(start, end); + const str_lit = try p.addNode(.{ .tag = .string_literal_expr, .ty = ty, .data = undefined }); + if (!p.in_macro) try p.value_map.put(str_lit, val); + + return Result{ .ty = ty, .node = try p.addNode(.{ + .tag = .implicit_static_var, + .ty = ty, + .data = .{ .decl = .{ .name = p.tok_i, .node = str_lit } }, + }) }; +} + +fn stringLiteral(p: *Parser) Error!Result { + var start = p.tok_i; + // use 1 for wchar_t + var width: ?u8 = null; + var is_u8_literal = false; + while (true) { + switch (p.tok_ids[p.tok_i]) { + .string_literal => {}, + .string_literal_utf_16 => if (width) |some| { + if (some != 16) try p.err(.unsupported_str_cat); + } else { + width = 16; + }, + .string_literal_utf_8 => { + is_u8_literal = true; + if (width) |some| { + if (some != 8) try p.err(.unsupported_str_cat); + } else { + width = 8; + } + }, + .string_literal_utf_32 => if (width) |some| { + if (some != 32) try p.err(.unsupported_str_cat); + } else { + width = 32; + }, + .string_literal_wide => if (width) |some| { + if (some != 1) try p.err(.unsupported_str_cat); + } else { + width = 1; + }, + else => break, + } + p.tok_i += 1; + } + if (width == null) width = 8; + if (width.? != 8) return p.todo("unicode string literals"); + + const string_start = p.retained_strings.items.len; + while (start < p.tok_i) : (start += 1) { + var slice = p.tokSlice(start); + slice = slice[0 .. slice.len - 1]; + var i = mem.indexOf(u8, slice, "\"").? + 1; + try p.retained_strings.ensureUnusedCapacity(slice.len); + while (i < slice.len) : (i += 1) { + switch (slice[i]) { + '\\' => { + i += 1; + switch (slice[i]) { + '\n' => i += 1, + '\r' => i += 2, + '\'', '\"', '\\', '?' => |c| p.retained_strings.appendAssumeCapacity(c), + 'n' => p.retained_strings.appendAssumeCapacity('\n'), + 'r' => p.retained_strings.appendAssumeCapacity('\r'), + 't' => p.retained_strings.appendAssumeCapacity('\t'), + 'a' => p.retained_strings.appendAssumeCapacity(0x07), + 'b' => p.retained_strings.appendAssumeCapacity(0x08), + 'e' => { + try p.errExtra(.non_standard_escape_char, start, .{ .unsigned = i - 1 }); + p.retained_strings.appendAssumeCapacity(0x1B); + }, + 'f' => p.retained_strings.appendAssumeCapacity(0x0C), + 'v' => p.retained_strings.appendAssumeCapacity(0x0B), + 'x' => p.retained_strings.appendAssumeCapacity(try p.parseNumberEscape(start, 16, slice, &i)), + '0'...'7' => p.retained_strings.appendAssumeCapacity(try p.parseNumberEscape(start, 8, slice, &i)), + 'u' => try p.parseUnicodeEscape(start, 4, slice, &i), + 'U' => try p.parseUnicodeEscape(start, 8, slice, &i), + else => unreachable, + } + }, + else => |c| p.retained_strings.appendAssumeCapacity(c), + } + } + } + try p.retained_strings.append(0); + const slice = p.retained_strings.items[string_start..]; + + const arr_ty = try p.arena.create(Type.Array); + const specifier: Type.Specifier = if (is_u8_literal and p.comp.langopts.hasChar8_T()) .uchar else .char; + + arr_ty.* = .{ .elem = .{ .specifier = specifier }, .len = slice.len }; + var res: Result = .{ + .ty = .{ + .specifier = .array, + .data = .{ .array = arr_ty }, + }, + .val = Value.bytes(@intCast(string_start), @intCast(p.retained_strings.items.len)), + }; + res.node = try p.addNode(.{ .tag = .string_literal_expr, .ty = res.ty, .data = undefined }); + if (!p.in_macro) try p.value_map.put(res.node, res.val); + return res; +} + +fn parseNumberEscape(p: *Parser, tok: TokenIndex, base: u8, slice: []const u8, i: *usize) !u8 { + if (base == 16) i.* += 1; // skip x + var char: u8 = 0; + var reported = false; + while (i.* < slice.len) : (i.* += 1) { + const val = std.fmt.charToDigit(slice[i.*], base) catch break; // validated by Tokenizer + const product, const overflowed = @mulWithOverflow(char, base); + if (overflowed != 0 and !reported) { + try p.errExtra(.escape_sequence_overflow, tok, .{ .unsigned = i.* }); + reported = true; + } + char = product + val; + } + i.* -= 1; + return char; +} + +fn parseUnicodeEscape(p: *Parser, tok: TokenIndex, count: u8, slice: []const u8, i: *usize) !void { + const c = std.fmt.parseInt(u21, slice[i.* + 1 ..][0..count], 16) catch 0x110000; // count validated by tokenizer + i.* += count + 1; + if (!std.unicode.utf8ValidCodepoint(c) or (c < 0xa0 and c != '$' and c != '@' and c != '`')) { + try p.errExtra(.invalid_universal_character, tok, .{ .unsigned = i.* - count - 2 }); + return; + } + var buf: [4]u8 = undefined; + const to_write = std.unicode.utf8Encode(c, &buf) catch unreachable; // validated above + p.retained_strings.appendSliceAssumeCapacity(buf[0..to_write]); +} + +fn charLiteral(p: *Parser) Error!Result { + defer p.tok_i += 1; + const allow_multibyte = switch (p.tok_ids[p.tok_i]) { + .char_literal => false, + .char_literal_utf_8 => false, + .char_literal_wide => true, + .char_literal_utf_16 => true, + .char_literal_utf_32 => true, + else => unreachable, + }; + const ty: Type = switch (p.tok_ids[p.tok_i]) { + .char_literal => .{ .specifier = .int }, + .char_literal_utf_8 => .{ .specifier = .uchar }, + .char_literal_wide => p.comp.types.wchar, + .char_literal_utf_16 => .{ .specifier = .ushort }, + .char_literal_utf_32 => .{ .specifier = .ulong }, + else => unreachable, + }; + const max: u32 = switch (p.tok_ids[p.tok_i]) { + .char_literal => std.math.maxInt(u8), + .char_literal_wide => @intCast(p.comp.types.wchar.maxInt(p.comp)), + .char_literal_utf_8 => std.math.maxInt(u8), + .char_literal_utf_16 => std.math.maxInt(u16), + .char_literal_utf_32 => std.math.maxInt(u32), + else => unreachable, + }; + var multichar: u8 = switch (p.tok_ids[p.tok_i]) { + .char_literal => 0, + .char_literal_wide => 4, + .char_literal_utf_8 => 2, + .char_literal_utf_16 => 2, + .char_literal_utf_32 => 2, + else => unreachable, + }; + + var val: u32 = 0; + var overflow_reported = false; + var slice = p.tokSlice(p.tok_i); + slice = slice[0 .. slice.len - 1]; + var i = mem.indexOf(u8, slice, "\'").? + 1; + while (i < slice.len) : (i += 1) { + var c: u32 = slice[i]; + var multibyte = false; + switch (c) { + '\\' => { + i += 1; + switch (slice[i]) { + '\n' => i += 1, + '\r' => i += 2, + '\'', '\"', '\\', '?' => c = slice[i], + 'n' => c = '\n', + 'r' => c = '\r', + 't' => c = '\t', + 'a' => c = 0x07, + 'b' => c = 0x08, + 'e' => { + try p.errExtra(.non_standard_escape_char, p.tok_i, .{ .unsigned = i - 1 }); + c = 0x1B; + }, + 'f' => c = 0x0C, + 'v' => c = 0x0B, + 'x' => c = try p.parseNumberEscape(p.tok_i, 16, slice, &i), + '0'...'7' => c = try p.parseNumberEscape(p.tok_i, 8, slice, &i), + 'u', 'U' => return p.todo("unicode escapes in char literals"), + else => unreachable, + } + }, + // These are safe since the source is checked to be valid utf8. + 0b1100_0000...0b1101_1111 => { + c &= 0b00011111; + c <<= 6; + c |= slice[i + 1] & 0b00111111; + i += 1; + multibyte = true; + }, + 0b1110_0000...0b1110_1111 => { + c &= 0b00001111; + c <<= 6; + c |= slice[i + 1] & 0b00111111; + c <<= 6; + c |= slice[i + 2] & 0b00111111; + i += 2; + multibyte = true; + }, + 0b1111_0000...0b1111_0111 => { + c &= 0b00000111; + c <<= 6; + c |= slice[i + 1] & 0b00111111; + c <<= 6; + c |= slice[i + 2] & 0b00111111; + c <<= 6; + c |= slice[i + 3] & 0b00111111; + i += 3; + multibyte = true; + }, + else => {}, + } + if (c > max or (multibyte and !allow_multibyte)) try p.err(.char_too_large); + switch (multichar) { + 0, 2, 4 => multichar += 1, + 1 => { + multichar = 99; + try p.err(.multichar_literal); + }, + 3 => { + try p.err(.unicode_multichar_literal); + return error.ParsingFailed; + }, + 5 => { + try p.err(.wide_multichar_literal); + val = 0; + multichar = 6; + }, + 6 => val = 0, + else => {}, + } + const product, const overflowed = @mulWithOverflow(val, max +% 1); + if (overflowed != 0 and !overflow_reported) { + try p.errExtra(.char_lit_too_wide, p.tok_i, .{ .unsigned = i }); + overflow_reported = true; + } + val = product + c; + } + + // This is the type the literal will have if we're in a macro; macros always operate on intmax_t/uintmax_t values + const macro_ty = if (ty.isUnsignedInt(p.comp) or (p.tok_ids[p.tok_i] == .char_literal and p.comp.getCharSignedness() == .unsigned)) + p.comp.types.intmax.makeIntegerUnsigned() + else + p.comp.types.intmax; + + var res = Result{ + .ty = if (p.in_macro) macro_ty else ty, + .val = Value.int(val), + .node = try p.addNode(.{ .tag = .char_literal, .ty = ty, .data = undefined }), + }; + if (!p.in_macro) try p.value_map.put(res.node, res.val); + return res; +} + +fn parseFloat(p: *Parser, buf: []const u8, suffix: NumberSuffix) !Result { + switch (suffix) { + .L => return p.todo("long double literals"), + .IL => { + try p.err(.gnu_imaginary_constant); + return p.todo("long double imaginary literals"); + }, + .None, .I, .F, .IF, .F16 => { + const ty = Type{ .specifier = switch (suffix) { + .None, .I => .double, + .F, .IF => .float, + .F16 => .float16, + else => unreachable, + } }; + const d_val = std.fmt.parseFloat(f64, buf) catch |er| switch (er) { + error.InvalidCharacter => return p.todo("c2x digit separators in floats"), + else => unreachable, + }; + const tag: Tree.Tag = switch (suffix) { + .None, .I => .double_literal, + .F, .IF => .float_literal, + .F16 => .float16_literal, + else => unreachable, + }; + var res = Result{ + .ty = ty, + .node = try p.addNode(.{ .tag = tag, .ty = ty, .data = undefined }), + .val = Value.float(d_val), + }; + if (suffix.isImaginary()) { + try p.err(.gnu_imaginary_constant); + res.ty = .{ .specifier = switch (suffix) { + .I => .complex_double, + .IF => .complex_float, + else => unreachable, + } }; + res.val.tag = .unavailable; + try res.un(p, .imaginary_literal); + } + return res; + }, + else => unreachable, + } +} + +fn getIntegerPart(p: *Parser, buf: []const u8, prefix: NumberPrefix, tok_i: TokenIndex) ![]const u8 { + if (buf[0] == '.') return ""; + + if (!prefix.digitAllowed(buf[0])) { + switch (prefix) { + .binary => try p.errExtra(.invalid_binary_digit, tok_i, .{ .ascii = @intCast(buf[0]) }), + .octal => try p.errExtra(.invalid_octal_digit, tok_i, .{ .ascii = @intCast(buf[0]) }), + .hex => try p.errStr(.invalid_int_suffix, tok_i, buf), + .decimal => unreachable, + } + return error.ParsingFailed; + } + + for (buf, 0..) |c, idx| { + if (idx == 0) continue; + switch (c) { + '.' => return buf[0..idx], + 'p', 'P' => return if (prefix == .hex) buf[0..idx] else { + try p.errStr(.invalid_int_suffix, tok_i, buf[idx..]); + return error.ParsingFailed; + }, + 'e', 'E' => { + switch (prefix) { + .hex => continue, + .decimal => return buf[0..idx], + .binary => try p.errExtra(.invalid_binary_digit, tok_i, .{ .ascii = @intCast(c) }), + .octal => try p.errExtra(.invalid_octal_digit, tok_i, .{ .ascii = @intCast(c) }), + } + return error.ParsingFailed; + }, + '0'...'9', 'a'...'d', 'A'...'D', 'f', 'F' => { + if (!prefix.digitAllowed(c)) { + switch (prefix) { + .binary => try p.errExtra(.invalid_binary_digit, tok_i, .{ .ascii = @intCast(c) }), + .octal => try p.errExtra(.invalid_octal_digit, tok_i, .{ .ascii = @intCast(c) }), + .decimal, .hex => try p.errStr(.invalid_int_suffix, tok_i, buf[idx..]), + } + return error.ParsingFailed; + } + }, + '\'' => {}, + else => return buf[0..idx], + } + } + return buf; +} + +fn fixedSizeInt(p: *Parser, base: u8, buf: []const u8, suffix: NumberSuffix, tok_i: TokenIndex) !Result { + var val: u64 = 0; + var overflow = false; + for (buf) |c| { + const digit: u64 = switch (c) { + '0'...'9' => c - '0', + 'A'...'Z' => c - 'A' + 10, + 'a'...'z' => c - 'a' + 10, + '\'' => continue, + else => unreachable, + }; + + if (val != 0) { + const product, const overflowed = @mulWithOverflow(val, base); + if (overflowed != 0) { + overflow = true; + } + val = product; + } + const sum, const overflowed = @addWithOverflow(val, digit); + if (overflowed != 0) overflow = true; + val = sum; + } + if (overflow) { + try p.errTok(.int_literal_too_big, tok_i); + var res: Result = .{ .ty = .{ .specifier = .ulong_long }, .val = Value.int(val) }; + res.node = try p.addNode(.{ .tag = .int_literal, .ty = res.ty, .data = undefined }); + if (!p.in_macro) try p.value_map.put(res.node, res.val); + return res; + } + if (suffix.isSignedInteger()) { + if (val > p.comp.types.intmax.maxInt(p.comp)) { + try p.errTok(.implicitly_unsigned_literal, tok_i); + } + } + return if (base == 10) + switch (suffix) { + .None, .I => p.castInt(val, &.{ .int, .long, .long_long }), + .U, .IU => p.castInt(val, &.{ .uint, .ulong, .ulong_long }), + .L, .IL => p.castInt(val, &.{ .long, .long_long }), + .UL, .IUL => p.castInt(val, &.{ .ulong, .ulong_long }), + .LL, .ILL => p.castInt(val, &.{.long_long}), + .ULL, .IULL => p.castInt(val, &.{.ulong_long}), + else => unreachable, + } + else switch (suffix) { + .None, .I => p.castInt(val, &.{ .int, .uint, .long, .ulong, .long_long, .ulong_long }), + .U, .IU => p.castInt(val, &.{ .uint, .ulong, .ulong_long }), + .L, .IL => p.castInt(val, &.{ .long, .ulong, .long_long, .ulong_long }), + .UL, .IUL => p.castInt(val, &.{ .ulong, .ulong_long }), + .LL, .ILL => p.castInt(val, &.{ .long_long, .ulong_long }), + .ULL, .IULL => p.castInt(val, &.{.ulong_long}), + else => unreachable, + }; +} + +fn parseInt(p: *Parser, prefix: NumberPrefix, buf: []const u8, suffix: NumberSuffix, tok_i: TokenIndex) !Result { + if (prefix == .binary) { + try p.errTok(.binary_integer_literal, tok_i); + } + const base = @intFromEnum(prefix); + var res = if (suffix.isBitInt()) + try p.bitInt(base, buf, suffix, tok_i) + else + try p.fixedSizeInt(base, buf, suffix, tok_i); + + if (suffix.isImaginary()) { + try p.errTok(.gnu_imaginary_constant, tok_i); + res.ty = res.ty.makeComplex(); + res.val.tag = .unavailable; + try res.un(p, .imaginary_literal); + } + return res; +} + +fn bitInt(p: *Parser, base: u8, buf: []const u8, suffix: NumberSuffix, tok_i: TokenIndex) Error!Result { + try p.errStr(.pre_c2x_compat, tok_i, "'_BitInt' suffix for literals"); + try p.errTok(.bitint_suffix, tok_i); + + var managed = try big.int.Managed.init(p.comp.gpa); + defer managed.deinit(); + + managed.setString(base, buf) catch |e| switch (e) { + error.InvalidBase => unreachable, // `base` is one of 2, 8, 10, 16 + error.InvalidCharacter => unreachable, // digits validated by Tokenizer + else => |er| return er, + }; + const c = managed.toConst(); + const bits_needed: std.math.IntFittingRange(0, Compilation.bit_int_max_bits) = blk: { + // Literal `0` requires at least 1 bit + const count = @max(1, c.bitCountTwosComp()); + // The wb suffix results in a _BitInt that includes space for the sign bit even if the + // value of the constant is positive or was specified in hexadecimal or octal notation. + const sign_bits = @intFromBool(suffix.isSignedInteger()); + const bits_needed = count + sign_bits; + if (bits_needed > Compilation.bit_int_max_bits) { + const specifier: Type.Builder.Specifier = switch (suffix) { + .WB => .{ .bit_int = 0 }, + .UWB => .{ .ubit_int = 0 }, + .IWB => .{ .complex_bit_int = 0 }, + .IUWB => .{ .complex_ubit_int = 0 }, + else => unreachable, + }; + try p.errStr(.bit_int_too_big, tok_i, specifier.str(p.comp.langopts).?); + return error.ParsingFailed; + } + if (bits_needed > 64) { + return p.todo("_BitInt constants > 64 bits"); + } + break :blk @intCast(bits_needed); + }; + + const val = c.to(u64) catch |e| switch (e) { + error.NegativeIntoUnsigned => unreachable, // unary minus parsed elsewhere; we only see positive integers + error.TargetTooSmall => unreachable, // Validated above but Todo: handle larger _BitInt + }; + + var res: Result = .{ + .val = Value.int(val), + .ty = .{ + .specifier = .bit_int, + .data = .{ .int = .{ .bits = bits_needed, .signedness = suffix.signedness() } }, + }, + }; + res.node = try p.addNode(.{ .tag = .int_literal, .ty = res.ty, .data = .{ .int = val } }); + if (!p.in_macro) try p.value_map.put(res.node, res.val); + return res; +} + +fn getFracPart(p: *Parser, buf: []const u8, prefix: NumberPrefix, tok_i: TokenIndex) ![]const u8 { + if (buf.len == 0 or buf[0] != '.') return ""; + assert(prefix != .octal); + if (prefix == .binary) { + try p.errStr(.invalid_int_suffix, tok_i, buf); + return error.ParsingFailed; + } + for (buf, 0..) |c, idx| { + if (idx == 0) continue; + if (c == '\'') continue; + if (!prefix.digitAllowed(c)) return buf[0..idx]; + } + return buf; +} + +fn getExponent(p: *Parser, buf: []const u8, prefix: NumberPrefix, tok_i: TokenIndex) ![]const u8 { + if (buf.len == 0) return ""; + + switch (buf[0]) { + 'e', 'E' => assert(prefix == .decimal), + 'p', 'P' => if (prefix != .hex) { + try p.errStr(.invalid_float_suffix, tok_i, buf); + return error.ParsingFailed; + }, + else => return "", + } + const end = for (buf, 0..) |c, idx| { + if (idx == 0) continue; + if (idx == 1 and (c == '+' or c == '-')) continue; + switch (c) { + '0'...'9' => {}, + '\'' => continue, + else => break idx, + } + } else buf.len; + const exponent = buf[0..end]; + if (std.mem.indexOfAny(u8, exponent, "0123456789") == null) { + try p.errTok(.exponent_has_no_digits, tok_i); + return error.ParsingFailed; + } + return exponent; +} + +/// Using an explicit `tok_i` parameter instead of `p.tok_i` makes it easier +/// to parse numbers in pragma handlers. +pub fn parseNumberToken(p: *Parser, tok_i: TokenIndex) !Result { + const buf = p.tokSlice(tok_i); + const prefix = NumberPrefix.fromString(buf); + const after_prefix = buf[prefix.stringLen()..]; + + const int_part = try p.getIntegerPart(after_prefix, prefix, tok_i); + + const after_int = after_prefix[int_part.len..]; + + const frac = try p.getFracPart(after_int, prefix, tok_i); + const after_frac = after_int[frac.len..]; + + const exponent = try p.getExponent(after_frac, prefix, tok_i); + const suffix_str = after_frac[exponent.len..]; + const is_float = (exponent.len > 0 or frac.len > 0); + const suffix = NumberSuffix.fromString(suffix_str, if (is_float) .float else .int) orelse { + if (is_float) { + try p.errStr(.invalid_float_suffix, tok_i, suffix_str); + } else { + try p.errStr(.invalid_int_suffix, tok_i, suffix_str); + } + return error.ParsingFailed; + }; + + if (is_float) { + assert(prefix == .hex or prefix == .decimal); + if (prefix == .hex and exponent.len == 0) { + try p.errTok(.hex_floating_constant_requires_exponent, tok_i); + return error.ParsingFailed; + } + const number = buf[0 .. buf.len - suffix_str.len]; + return p.parseFloat(number, suffix); + } else { + return p.parseInt(prefix, int_part, suffix, tok_i); + } +} + +fn ppNum(p: *Parser) Error!Result { + defer p.tok_i += 1; + var res = try p.parseNumberToken(p.tok_i); + if (p.in_macro) { + if (res.ty.isFloat() or !res.ty.isReal()) { + try p.errTok(.float_literal_in_pp_expr, p.tok_i); + return error.ParsingFailed; + } + res.ty = if (res.ty.isUnsignedInt(p.comp)) p.comp.types.intmax.makeIntegerUnsigned() else p.comp.types.intmax; + } else { + try p.value_map.put(res.node, res.val); + } + return res; +} + +fn castInt(p: *Parser, val: u64, specs: []const Type.Specifier) Error!Result { + var res: Result = .{ .val = Value.int(val) }; + for (specs) |spec| { + const ty = Type{ .specifier = spec }; + const unsigned = ty.isUnsignedInt(p.comp); + const size = ty.sizeof(p.comp).?; + res.ty = ty; + + if (unsigned) { + switch (size) { + 2 => if (val <= std.math.maxInt(u16)) break, + 4 => if (val <= std.math.maxInt(u32)) break, + 8 => if (val <= std.math.maxInt(u64)) break, + else => unreachable, + } + } else { + switch (size) { + 2 => if (val <= std.math.maxInt(i16)) break, + 4 => if (val <= std.math.maxInt(i32)) break, + 8 => if (val <= std.math.maxInt(i64)) break, + else => unreachable, + } + } + } else { + res.ty = .{ .specifier = .ulong_long }; + } + res.node = try p.addNode(.{ .tag = .int_literal, .ty = res.ty, .data = .{ .int = val } }); + if (!p.in_macro) try p.value_map.put(res.node, res.val); + return res; +} + +/// Run a parser function but do not evaluate the result +fn parseNoEval(p: *Parser, comptime func: fn (*Parser) Error!Result) Error!Result { + const no_eval = p.no_eval; + defer p.no_eval = no_eval; + p.no_eval = true; + const parsed = try func(p); + try parsed.expect(p); + return parsed; +} + +/// genericSelection : keyword_generic '(' assignExpr ',' genericAssoc (',' genericAssoc)* ')' +/// genericAssoc +/// : typeName ':' assignExpr +/// | keyword_default ':' assignExpr +fn genericSelection(p: *Parser) Error!Result { + p.tok_i += 1; + const l_paren = try p.expectToken(.l_paren); + const controlling_tok = p.tok_i; + const controlling = try p.parseNoEval(assignExpr); + _ = try p.expectToken(.comma); + var controlling_ty = controlling.ty; + if (controlling_ty.isArray()) controlling_ty.decayArray(); + + const list_buf_top = p.list_buf.items.len; + defer p.list_buf.items.len = list_buf_top; + try p.list_buf.append(controlling.node); + + // Use decl_buf to store the token indexes of previous cases + const decl_buf_top = p.decl_buf.items.len; + defer p.decl_buf.items.len = decl_buf_top; + + var default_tok: ?TokenIndex = null; + var default: Result = undefined; + var chosen_tok: TokenIndex = undefined; + var chosen: Result = .{}; + while (true) { + const start = p.tok_i; + if (try p.typeName()) |ty| blk: { + if (ty.isArray()) { + try p.errTok(.generic_array_type, start); + } else if (ty.isFunc()) { + try p.errTok(.generic_func_type, start); + } else if (ty.anyQual()) { + try p.errTok(.generic_qual_type, start); + } + _ = try p.expectToken(.colon); + const node = try p.assignExpr(); + try node.expect(p); + + if (ty.eql(controlling_ty, p.comp, false)) { + if (chosen.node == .none) { + chosen = node; + chosen_tok = start; + break :blk; + } + try p.errStr(.generic_duplicate, start, try p.typeStr(ty)); + try p.errStr(.generic_duplicate_here, chosen_tok, try p.typeStr(ty)); + } + for (p.list_buf.items[list_buf_top + 1 ..], p.decl_buf.items[decl_buf_top..]) |item, prev_tok| { + const prev_ty = p.nodes.items(.ty)[@intFromEnum(item)]; + if (prev_ty.eql(ty, p.comp, true)) { + try p.errStr(.generic_duplicate, start, try p.typeStr(ty)); + try p.errStr(.generic_duplicate_here, @intFromEnum(prev_tok), try p.typeStr(ty)); + } + } + try p.list_buf.append(try p.addNode(.{ + .tag = .generic_association_expr, + .ty = ty, + .data = .{ .un = node.node }, + })); + try p.decl_buf.append(@enumFromInt(start)); + } else if (p.eatToken(.keyword_default)) |tok| { + if (default_tok) |prev| { + try p.errTok(.generic_duplicate_default, tok); + try p.errTok(.previous_case, prev); + } + default_tok = tok; + _ = try p.expectToken(.colon); + default = try p.assignExpr(); + try default.expect(p); + } else { + if (p.list_buf.items.len == list_buf_top + 1) { + try p.err(.expected_type); + return error.ParsingFailed; + } + break; + } + if (p.eatToken(.comma) == null) break; + } + try p.expectClosing(l_paren, .r_paren); + + if (chosen.node == .none) { + if (default_tok != null) { + try p.list_buf.insert(list_buf_top + 1, try p.addNode(.{ + .tag = .generic_default_expr, + .data = .{ .un = default.node }, + })); + chosen = default; + } else { + try p.errStr(.generic_no_match, controlling_tok, try p.typeStr(controlling_ty)); + return error.ParsingFailed; + } + } else { + try p.list_buf.insert(list_buf_top + 1, try p.addNode(.{ + .tag = .generic_association_expr, + .data = .{ .un = chosen.node }, + })); + if (default_tok != null) { + try p.list_buf.append(try p.addNode(.{ + .tag = .generic_default_expr, + .data = .{ .un = chosen.node }, + })); + } + } + + var generic_node: Tree.Node = .{ + .tag = .generic_expr_one, + .ty = chosen.ty, + .data = .{ .bin = .{ .lhs = controlling.node, .rhs = chosen.node } }, + }; + const associations = p.list_buf.items[list_buf_top..]; + if (associations.len > 2) { // associations[0] == controlling.node + generic_node.tag = .generic_expr; + generic_node.data = .{ .range = try p.addList(associations) }; + } + chosen.node = try p.addNode(generic_node); + return chosen; +} diff --git a/deps/aro/Pragma.zig b/deps/aro/Pragma.zig new file mode 100644 index 000000000000..da1c53ed4fce --- /dev/null +++ b/deps/aro/Pragma.zig @@ -0,0 +1,83 @@ +const std = @import("std"); +const Compilation = @import("Compilation.zig"); +const Preprocessor = @import("Preprocessor.zig"); +const Parser = @import("Parser.zig"); +const TokenIndex = @import("Tree.zig").TokenIndex; + +const Pragma = @This(); + +pub const Error = Compilation.Error || error{ UnknownPragma, StopPreprocessing }; + +/// Called during Preprocessor.init +beforePreprocess: ?*const fn (*Pragma, *Compilation) void = null, + +/// Called at the beginning of Parser.parse +beforeParse: ?*const fn (*Pragma, *Compilation) void = null, + +/// Called at the end of Parser.parse if a Tree was successfully parsed +afterParse: ?*const fn (*Pragma, *Compilation) void = null, + +/// Called during Compilation.deinit +deinit: *const fn (*Pragma, *Compilation) void, + +/// Called whenever the preprocessor encounters this pragma. `start_idx` is the index +/// within `pp.tokens` of the pragma name token. The pragma end is indicated by a +/// .nl token (which may be generated if the source ends with a pragma with no newline) +/// As an example, given the following line: +/// #pragma GCC diagnostic error "-Wnewline-eof" \n +/// Then pp.tokens.get(start_idx) will return the `GCC` token. +/// Return error.UnknownPragma to emit an `unknown_pragma` diagnostic +/// Return error.StopPreprocessing to stop preprocessing the current file (see once.zig) +preprocessorHandler: ?*const fn (*Pragma, *Preprocessor, start_idx: TokenIndex) Error!void = null, + +/// Called during token pretty-printing (`-E` option). If this returns true, the pragma will +/// be printed; otherwise it will be omitted. start_idx is the index of the pragma name token +preserveTokens: ?*const fn (*Pragma, *Preprocessor, start_idx: TokenIndex) bool = null, + +/// Same as preprocessorHandler except called during parsing +/// The parser's `p.tok_i` field must not be changed +parserHandler: ?*const fn (*Pragma, *Parser, start_idx: TokenIndex) Compilation.Error!void = null, + +pub fn pasteTokens(pp: *Preprocessor, start_idx: TokenIndex) ![]const u8 { + if (pp.tokens.get(start_idx).id == .nl) return error.ExpectedStringLiteral; + + const char_top = pp.char_buf.items.len; + defer pp.char_buf.items.len = char_top; + var i: usize = 0; + var lparen_count: u32 = 0; + var rparen_count: u32 = 0; + while (true) : (i += 1) { + const tok = pp.tokens.get(start_idx + i); + if (tok.id == .nl) break; + switch (tok.id) { + .l_paren => { + if (lparen_count != i) return error.ExpectedStringLiteral; + lparen_count += 1; + }, + .r_paren => rparen_count += 1, + .string_literal => { + if (rparen_count != 0) return error.ExpectedStringLiteral; + const str = pp.expandedSlice(tok); + try pp.char_buf.appendSlice(str[1 .. str.len - 1]); + }, + else => return error.ExpectedStringLiteral, + } + } + if (lparen_count != rparen_count) return error.ExpectedStringLiteral; + return pp.char_buf.items[char_top..]; +} + +pub fn shouldPreserveTokens(self: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) bool { + if (self.preserveTokens) |func| return func(self, pp, start_idx); + return false; +} + +pub fn preprocessorCB(self: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) Error!void { + if (self.preprocessorHandler) |func| return func(self, pp, start_idx); +} + +pub fn parserCB(self: *Pragma, p: *Parser, start_idx: TokenIndex) Compilation.Error!void { + const tok_index = p.tok_i; + defer std.debug.assert(tok_index == p.tok_i); + if (self.parserHandler) |func| return func(self, p, start_idx); +} diff --git a/deps/aro/Preprocessor.zig b/deps/aro/Preprocessor.zig new file mode 100644 index 000000000000..95758ae3742d --- /dev/null +++ b/deps/aro/Preprocessor.zig @@ -0,0 +1,2691 @@ +const std = @import("std"); +const mem = std.mem; +const Allocator = mem.Allocator; +const assert = std.debug.assert; +const Compilation = @import("Compilation.zig"); +const Error = Compilation.Error; +const Source = @import("Source.zig"); +const Tokenizer = @import("Tokenizer.zig"); +const RawToken = Tokenizer.Token; +const Parser = @import("Parser.zig"); +const Diagnostics = @import("Diagnostics.zig"); +const Token = @import("Tree.zig").Token; +const Attribute = @import("Attribute.zig"); +const features = @import("features.zig"); + +const Preprocessor = @This(); +const DefineMap = std.StringHashMap(Macro); +const RawTokenList = std.ArrayList(RawToken); +const max_include_depth = 200; + +/// Errors that can be returned when expanding a macro. +/// error.UnknownPragma can occur within Preprocessor.pragma() but +/// it is handled there and doesn't escape that function +const MacroError = Error || error{StopPreprocessing}; + +const Macro = struct { + /// Parameters of the function type macro + params: []const []const u8, + + /// Token constituting the macro body + tokens: []const RawToken, + + /// If the function type macro has variable number of arguments + var_args: bool, + + /// Is a function type macro + is_func: bool, + + /// Is a predefined macro + is_builtin: bool = false, + + /// Location of macro in the source + /// `byte_offset` and `line` are used to define the range of tokens included + /// in the macro. + loc: Source.Location, + + fn eql(a: Macro, b: Macro, pp: *Preprocessor) bool { + if (a.tokens.len != b.tokens.len) return false; + if (a.is_builtin != b.is_builtin) return false; + for (a.tokens, b.tokens) |a_tok, b_tok| if (!tokEql(pp, a_tok, b_tok)) return false; + + if (a.is_func and b.is_func) { + if (a.var_args != b.var_args) return false; + if (a.params.len != b.params.len) return false; + for (a.params, b.params) |a_param, b_param| if (!mem.eql(u8, a_param, b_param)) return false; + } + + return true; + } + + fn tokEql(pp: *Preprocessor, a: RawToken, b: RawToken) bool { + return mem.eql(u8, pp.tokSlice(a), pp.tokSlice(b)); + } +}; + +comp: *Compilation, +gpa: mem.Allocator, +arena: std.heap.ArenaAllocator, +defines: DefineMap, +tokens: Token.List = .{}, +token_buf: RawTokenList, +char_buf: std.ArrayList(u8), +/// Counter that is incremented each time preprocess() is called +/// Can be used to distinguish multiple preprocessings of the same file +preprocess_count: u32 = 0, +generated_line: u32 = 1, +add_expansion_nl: u32 = 0, +include_depth: u8 = 0, +counter: u32 = 0, +expansion_source_loc: Source.Location = undefined, +poisoned_identifiers: std.StringHashMap(void), +/// Map from Source.Id to macro name in the `#ifndef` condition which guards the source, if any +include_guards: std.AutoHashMapUnmanaged(Source.Id, []const u8) = .{}, + +/// Memory is retained to avoid allocation on every single token. +top_expansion_buf: ExpandBuf, + +/// Dump current state to stderr. +verbose: bool = false, +preserve_whitespace: bool = false, + +pub fn init(comp: *Compilation) Preprocessor { + const pp = Preprocessor{ + .comp = comp, + .gpa = comp.gpa, + .arena = std.heap.ArenaAllocator.init(comp.gpa), + .defines = DefineMap.init(comp.gpa), + .token_buf = RawTokenList.init(comp.gpa), + .char_buf = std.ArrayList(u8).init(comp.gpa), + .poisoned_identifiers = std.StringHashMap(void).init(comp.gpa), + .top_expansion_buf = ExpandBuf.init(comp.gpa), + }; + comp.pragmaEvent(.before_preprocess); + return pp; +} + +const builtin_macros = struct { + const args = [1][]const u8{"X"}; + + const has_attribute = [1]RawToken{.{ + .id = .macro_param_has_attribute, + .source = .generated, + }}; + const has_warning = [1]RawToken{.{ + .id = .macro_param_has_warning, + .source = .generated, + }}; + const has_feature = [1]RawToken{.{ + .id = .macro_param_has_feature, + .source = .generated, + }}; + const has_extension = [1]RawToken{.{ + .id = .macro_param_has_extension, + .source = .generated, + }}; + const has_builtin = [1]RawToken{.{ + .id = .macro_param_has_builtin, + .source = .generated, + }}; + const has_include = [1]RawToken{.{ + .id = .macro_param_has_include, + .source = .generated, + }}; + const has_include_next = [1]RawToken{.{ + .id = .macro_param_has_include_next, + .source = .generated, + }}; + + const is_identifier = [1]RawToken{.{ + .id = .macro_param_is_identifier, + .source = .generated, + }}; + + const pragma_operator = [1]RawToken{.{ + .id = .macro_param_pragma_operator, + .source = .generated, + }}; + + const file = [1]RawToken{.{ + .id = .macro_file, + .source = .generated, + }}; + const line = [1]RawToken{.{ + .id = .macro_line, + .source = .generated, + }}; + const counter = [1]RawToken{.{ + .id = .macro_counter, + .source = .generated, + }}; +}; + +fn addBuiltinMacro(pp: *Preprocessor, name: []const u8, is_func: bool, tokens: []const RawToken) !void { + try pp.defines.putNoClobber(name, .{ + .params = &builtin_macros.args, + .tokens = tokens, + .var_args = false, + .is_func = is_func, + .loc = .{ .id = .generated }, + .is_builtin = true, + }); +} + +pub fn addBuiltinMacros(pp: *Preprocessor) !void { + try pp.addBuiltinMacro("__has_attribute", true, &builtin_macros.has_attribute); + try pp.addBuiltinMacro("__has_warning", true, &builtin_macros.has_warning); + try pp.addBuiltinMacro("__has_feature", true, &builtin_macros.has_feature); + try pp.addBuiltinMacro("__has_extension", true, &builtin_macros.has_extension); + try pp.addBuiltinMacro("__has_builtin", true, &builtin_macros.has_builtin); + try pp.addBuiltinMacro("__has_include", true, &builtin_macros.has_include); + try pp.addBuiltinMacro("__has_include_next", true, &builtin_macros.has_include_next); + try pp.addBuiltinMacro("__is_identifier", true, &builtin_macros.is_identifier); + try pp.addBuiltinMacro("_Pragma", true, &builtin_macros.pragma_operator); + + try pp.addBuiltinMacro("__FILE__", false, &builtin_macros.file); + try pp.addBuiltinMacro("__LINE__", false, &builtin_macros.line); + try pp.addBuiltinMacro("__COUNTER__", false, &builtin_macros.counter); +} + +pub fn deinit(pp: *Preprocessor) void { + pp.defines.deinit(); + for (pp.tokens.items(.expansion_locs)) |loc| Token.free(loc, pp.gpa); + pp.tokens.deinit(pp.gpa); + pp.arena.deinit(); + pp.token_buf.deinit(); + pp.char_buf.deinit(); + pp.poisoned_identifiers.deinit(); + pp.include_guards.deinit(pp.gpa); + pp.top_expansion_buf.deinit(); +} + +/// Preprocess a source file, returns eof token. +pub fn preprocess(pp: *Preprocessor, source: Source) Error!Token { + return pp.preprocessExtra(source) catch |er| switch (er) { + // This cannot occur in the main file and is handled in `include`. + error.StopPreprocessing => unreachable, + else => |e| return e, + }; +} + +/// Return the name of the #ifndef guard macro that starts a source, if any. +fn findIncludeGuard(pp: *Preprocessor, source: Source) ?[]const u8 { + var tokenizer = Tokenizer{ + .buf = source.buf, + .comp = pp.comp, + .source = source.id, + }; + var hash = tokenizer.nextNoWS(); + while (hash.id == .nl) hash = tokenizer.nextNoWS(); + if (hash.id != .hash) return null; + const ifndef = tokenizer.nextNoWS(); + if (ifndef.id != .keyword_ifndef) return null; + const guard = tokenizer.nextNoWS(); + if (guard.id != .identifier) return null; + return pp.tokSlice(guard); +} + +fn preprocessExtra(pp: *Preprocessor, source: Source) MacroError!Token { + if (pp.comp.invalid_utf8_locs.get(source.id)) |offset| { + try pp.comp.diag.add(.{ + .tag = .invalid_utf8, + // Todo: compute line number + .loc = .{ .id = source.id, .byte_offset = offset }, + }, &.{}); + return error.FatalError; + } + var guard_name = pp.findIncludeGuard(source); + + pp.preprocess_count += 1; + var tokenizer = Tokenizer{ + .buf = source.buf, + .comp = pp.comp, + .source = source.id, + }; + + // Estimate how many new tokens this source will contain. + const estimated_token_count = source.buf.len / 8; + try pp.tokens.ensureTotalCapacity(pp.gpa, pp.tokens.len + estimated_token_count); + + var if_level: u8 = 0; + var if_kind = std.PackedIntArray(u2, 256).init([1]u2{0} ** 256); + const until_else = 0; + const until_endif = 1; + const until_endif_seen_else = 2; + + var start_of_line = true; + while (true) { + var tok = tokenizer.next(); + switch (tok.id) { + .hash => if (!start_of_line) try pp.tokens.append(pp.gpa, tokFromRaw(tok)) else { + const directive = tokenizer.nextNoWS(); + switch (directive.id) { + .keyword_error, .keyword_warning => { + // #error tokens.. + pp.top_expansion_buf.items.len = 0; + const char_top = pp.char_buf.items.len; + defer pp.char_buf.items.len = char_top; + + while (true) { + tok = tokenizer.next(); + if (tok.id == .nl or tok.id == .eof) break; + if (tok.id == .whitespace) tok.id = .macro_ws; + try pp.top_expansion_buf.append(tokFromRaw(tok)); + } + try pp.stringify(pp.top_expansion_buf.items); + const slice = pp.char_buf.items[char_top + 1 .. pp.char_buf.items.len - 2]; + const duped = try pp.comp.diag.arena.allocator().dupe(u8, slice); + + try pp.comp.diag.add(.{ + .tag = if (directive.id == .keyword_error) .error_directive else .warning_directive, + .loc = .{ .id = tok.source, .byte_offset = directive.start, .line = directive.line }, + .extra = .{ .str = duped }, + }, &.{}); + }, + .keyword_if => { + const sum, const overflowed = @addWithOverflow(if_level, 1); + if (overflowed != 0) + return pp.fatal(directive, "too many #if nestings", .{}); + if_level = sum; + + if (try pp.expr(&tokenizer)) { + if_kind.set(if_level, until_endif); + if (pp.verbose) { + pp.verboseLog(directive, "entering then branch of #if", .{}); + } + } else { + if_kind.set(if_level, until_else); + try pp.skip(&tokenizer, .until_else); + if (pp.verbose) { + pp.verboseLog(directive, "entering else branch of #if", .{}); + } + } + }, + .keyword_ifdef => { + const sum, const overflowed = @addWithOverflow(if_level, 1); + if (overflowed != 0) + return pp.fatal(directive, "too many #if nestings", .{}); + if_level = sum; + + const macro_name = (try pp.expectMacroName(&tokenizer)) orelse continue; + try pp.expectNl(&tokenizer); + if (pp.defines.get(macro_name) != null) { + if_kind.set(if_level, until_endif); + if (pp.verbose) { + pp.verboseLog(directive, "entering then branch of #ifdef", .{}); + } + } else { + if_kind.set(if_level, until_else); + try pp.skip(&tokenizer, .until_else); + if (pp.verbose) { + pp.verboseLog(directive, "entering else branch of #ifdef", .{}); + } + } + }, + .keyword_ifndef => { + const sum, const overflowed = @addWithOverflow(if_level, 1); + if (overflowed != 0) + return pp.fatal(directive, "too many #if nestings", .{}); + if_level = sum; + + const macro_name = (try pp.expectMacroName(&tokenizer)) orelse continue; + try pp.expectNl(&tokenizer); + if (pp.defines.get(macro_name) == null) { + if_kind.set(if_level, until_endif); + } else { + if_kind.set(if_level, until_else); + try pp.skip(&tokenizer, .until_else); + } + }, + .keyword_elif => { + if (if_level == 0) { + try pp.err(directive, .elif_without_if); + if_level += 1; + if_kind.set(if_level, until_else); + } else if (if_level == 1) { + guard_name = null; + } + switch (if_kind.get(if_level)) { + until_else => if (try pp.expr(&tokenizer)) { + if_kind.set(if_level, until_endif); + if (pp.verbose) { + pp.verboseLog(directive, "entering then branch of #elif", .{}); + } + } else { + try pp.skip(&tokenizer, .until_else); + if (pp.verbose) { + pp.verboseLog(directive, "entering else branch of #elif", .{}); + } + }, + until_endif => try pp.skip(&tokenizer, .until_endif), + until_endif_seen_else => { + try pp.err(directive, .elif_after_else); + skipToNl(&tokenizer); + }, + else => unreachable, + } + }, + .keyword_elifdef => { + if (if_level == 0) { + try pp.err(directive, .elifdef_without_if); + if_level += 1; + if_kind.set(if_level, until_else); + } else if (if_level == 1) { + guard_name = null; + } + switch (if_kind.get(if_level)) { + until_else => { + const macro_name = try pp.expectMacroName(&tokenizer); + if (macro_name == null) { + if_kind.set(if_level, until_else); + try pp.skip(&tokenizer, .until_else); + if (pp.verbose) { + pp.verboseLog(directive, "entering else branch of #elifdef", .{}); + } + } else { + try pp.expectNl(&tokenizer); + if (pp.defines.get(macro_name.?) != null) { + if_kind.set(if_level, until_endif); + if (pp.verbose) { + pp.verboseLog(directive, "entering then branch of #elifdef", .{}); + } + } else { + if_kind.set(if_level, until_else); + try pp.skip(&tokenizer, .until_else); + if (pp.verbose) { + pp.verboseLog(directive, "entering else branch of #elifdef", .{}); + } + } + } + }, + until_endif => try pp.skip(&tokenizer, .until_endif), + until_endif_seen_else => { + try pp.err(directive, .elifdef_after_else); + skipToNl(&tokenizer); + }, + else => unreachable, + } + }, + .keyword_elifndef => { + if (if_level == 0) { + try pp.err(directive, .elifdef_without_if); + if_level += 1; + if_kind.set(if_level, until_else); + } else if (if_level == 1) { + guard_name = null; + } + switch (if_kind.get(if_level)) { + until_else => { + const macro_name = try pp.expectMacroName(&tokenizer); + if (macro_name == null) { + if_kind.set(if_level, until_else); + try pp.skip(&tokenizer, .until_else); + if (pp.verbose) { + pp.verboseLog(directive, "entering else branch of #elifndef", .{}); + } + } else { + try pp.expectNl(&tokenizer); + if (pp.defines.get(macro_name.?) == null) { + if_kind.set(if_level, until_endif); + if (pp.verbose) { + pp.verboseLog(directive, "entering then branch of #elifndef", .{}); + } + } else { + if_kind.set(if_level, until_else); + try pp.skip(&tokenizer, .until_else); + if (pp.verbose) { + pp.verboseLog(directive, "entering else branch of #elifndef", .{}); + } + } + } + }, + until_endif => try pp.skip(&tokenizer, .until_endif), + until_endif_seen_else => { + try pp.err(directive, .elifdef_after_else); + skipToNl(&tokenizer); + }, + else => unreachable, + } + }, + .keyword_else => { + try pp.expectNl(&tokenizer); + if (if_level == 0) { + try pp.err(directive, .else_without_if); + continue; + } else if (if_level == 1) { + guard_name = null; + } + switch (if_kind.get(if_level)) { + until_else => { + if_kind.set(if_level, until_endif_seen_else); + if (pp.verbose) { + pp.verboseLog(directive, "#else branch here", .{}); + } + }, + until_endif => try pp.skip(&tokenizer, .until_endif_seen_else), + until_endif_seen_else => { + try pp.err(directive, .else_after_else); + skipToNl(&tokenizer); + }, + else => unreachable, + } + }, + .keyword_endif => { + try pp.expectNl(&tokenizer); + if (if_level == 0) { + guard_name = null; + try pp.err(directive, .endif_without_if); + continue; + } else if (if_level == 1) { + const saved_tokenizer = tokenizer; + defer tokenizer = saved_tokenizer; + + var next = tokenizer.nextNoWS(); + while (next.id == .nl) : (next = tokenizer.nextNoWS()) {} + if (next.id != .eof) guard_name = null; + } + if_level -= 1; + }, + .keyword_define => try pp.define(&tokenizer), + .keyword_undef => { + const macro_name = (try pp.expectMacroName(&tokenizer)) orelse continue; + + _ = pp.defines.remove(macro_name); + try pp.expectNl(&tokenizer); + }, + .keyword_include => try pp.include(&tokenizer, .first), + .keyword_include_next => { + try pp.comp.diag.add(.{ + .tag = .include_next, + .loc = .{ .id = tok.source, .byte_offset = directive.start, .line = directive.line }, + }, &.{}); + if (pp.include_depth == 0) { + try pp.comp.diag.add(.{ + .tag = .include_next_outside_header, + .loc = .{ .id = tok.source, .byte_offset = directive.start, .line = directive.line }, + }, &.{}); + try pp.include(&tokenizer, .first); + } else { + try pp.include(&tokenizer, .next); + } + }, + .keyword_embed => try pp.embed(&tokenizer), + .keyword_pragma => try pp.pragma(&tokenizer, directive, null, &.{}), + .keyword_line => { + // #line number "file" + const digits = tokenizer.nextNoWS(); + if (digits.id != .pp_num) try pp.err(digits, .line_simple_digit); + // TODO: validate that the pp_num token is solely digits + + if (digits.id == .eof or digits.id == .nl) continue; + const name = tokenizer.nextNoWS(); + if (name.id == .eof or name.id == .nl) continue; + if (name.id != .string_literal) try pp.err(name, .line_invalid_filename); + try pp.expectNl(&tokenizer); + }, + .pp_num => { + // # number "file" flags + // TODO: validate that the pp_num token is solely digits + // if not, emit `GNU line marker directive requires a simple digit sequence` + const name = tokenizer.nextNoWS(); + if (name.id == .eof or name.id == .nl) continue; + if (name.id != .string_literal) try pp.err(name, .line_invalid_filename); + + const flag_1 = tokenizer.nextNoWS(); + if (flag_1.id == .eof or flag_1.id == .nl) continue; + const flag_2 = tokenizer.nextNoWS(); + if (flag_2.id == .eof or flag_2.id == .nl) continue; + const flag_3 = tokenizer.nextNoWS(); + if (flag_3.id == .eof or flag_3.id == .nl) continue; + const flag_4 = tokenizer.nextNoWS(); + if (flag_4.id == .eof or flag_4.id == .nl) continue; + try pp.expectNl(&tokenizer); + }, + .nl => {}, + .eof => { + if (if_level != 0) try pp.err(tok, .unterminated_conditional_directive); + return tokFromRaw(directive); + }, + else => { + try pp.err(tok, .invalid_preprocessing_directive); + skipToNl(&tokenizer); + }, + } + }, + .whitespace => if (pp.preserve_whitespace) try pp.tokens.append(pp.gpa, tokFromRaw(tok)), + .nl => { + start_of_line = true; + if (pp.preserve_whitespace) try pp.tokens.append(pp.gpa, tokFromRaw(tok)); + }, + .eof => { + if (if_level != 0) try pp.err(tok, .unterminated_conditional_directive); + // The following check needs to occur here and not at the top of the function + // because a pragma may change the level during preprocessing + if (source.buf.len > 0 and source.buf[source.buf.len - 1] != '\n') { + try pp.err(tok, .newline_eof); + } + if (guard_name) |name| { + if (try pp.include_guards.fetchPut(pp.gpa, source.id, name)) |prev| { + assert(mem.eql(u8, name, prev.value)); + } + } + return tokFromRaw(tok); + }, + else => { + if (tok.id.isMacroIdentifier() and pp.poisoned_identifiers.get(pp.tokSlice(tok)) != null) { + try pp.err(tok, .poisoned_identifier); + } + // Add the token to the buffer doing any necessary expansions. + start_of_line = false; + try pp.expandMacro(&tokenizer, tok); + }, + } + } +} + +/// Get raw token source string. +/// Returned slice is invalidated when comp.generated_buf is updated. +pub fn tokSlice(pp: *Preprocessor, token: RawToken) []const u8 { + if (token.id.lexeme()) |some| return some; + const source = pp.comp.getSource(token.source); + return source.buf[token.start..token.end]; +} + +/// Convert a token from the Tokenizer into a token used by the parser. +fn tokFromRaw(raw: RawToken) Token { + return .{ + .id = raw.id, + .loc = .{ + .id = raw.source, + .byte_offset = raw.start, + .line = raw.line, + }, + }; +} + +fn err(pp: *Preprocessor, raw: RawToken, tag: Diagnostics.Tag) !void { + try pp.comp.diag.add(.{ + .tag = tag, + .loc = .{ + .id = raw.source, + .byte_offset = raw.start, + .line = raw.line, + }, + }, &.{}); +} + +fn fatal(pp: *Preprocessor, raw: RawToken, comptime fmt: []const u8, args: anytype) Compilation.Error { + const source = pp.comp.getSource(raw.source); + const line_col = source.lineCol(.{ .id = raw.source, .line = raw.line, .byte_offset = raw.start }); + return pp.comp.diag.fatal(source.path, line_col.line, raw.line, line_col.col, fmt, args); +} + +fn verboseLog(pp: *Preprocessor, raw: RawToken, comptime fmt: []const u8, args: anytype) void { + const source = pp.comp.getSource(raw.source); + const line_col = source.lineCol(.{ .id = raw.source, .line = raw.line, .byte_offset = raw.start }); + + const stderr = std.io.getStdErr().writer(); + var buf_writer = std.io.bufferedWriter(stderr); + const writer = buf_writer.writer(); + defer buf_writer.flush() catch {}; + writer.print("{s}:{d}:{d}: ", .{ source.path, line_col.line_no, line_col.col }) catch return; + writer.print(fmt, args) catch return; + writer.writeByte('\n') catch return; + writer.writeAll(line_col.line) catch return; + writer.writeByte('\n') catch return; +} + +/// Consume next token, error if it is not an identifier. +fn expectMacroName(pp: *Preprocessor, tokenizer: *Tokenizer) Error!?[]const u8 { + const macro_name = tokenizer.nextNoWS(); + if (!macro_name.id.isMacroIdentifier()) { + try pp.err(macro_name, .macro_name_missing); + skipToNl(tokenizer); + return null; + } + return pp.tokSlice(macro_name); +} + +/// Skip until after a newline, error if extra tokens before it. +fn expectNl(pp: *Preprocessor, tokenizer: *Tokenizer) Error!void { + var sent_err = false; + while (true) { + const tok = tokenizer.next(); + if (tok.id == .nl or tok.id == .eof) return; + if (tok.id == .whitespace) continue; + if (!sent_err) { + sent_err = true; + try pp.err(tok, .extra_tokens_directive_end); + } + } +} + +/// Consume all tokens until a newline and parse the result into a boolean. +fn expr(pp: *Preprocessor, tokenizer: *Tokenizer) MacroError!bool { + const start = pp.tokens.len; + defer { + for (pp.top_expansion_buf.items) |tok| Token.free(tok.expansion_locs, pp.gpa); + pp.tokens.len = start; + } + + pp.top_expansion_buf.items.len = 0; + const eof = while (true) { + var tok = tokenizer.next(); + switch (tok.id) { + .nl, .eof => break tok, + .whitespace => if (pp.top_expansion_buf.items.len == 0) continue, + else => {}, + } + try pp.top_expansion_buf.append(tokFromRaw(tok)); + } else unreachable; + if (pp.top_expansion_buf.items.len != 0) { + pp.expansion_source_loc = pp.top_expansion_buf.items[0].loc; + try pp.expandMacroExhaustive(tokenizer, &pp.top_expansion_buf, 0, pp.top_expansion_buf.items.len, false, .expr); + } + for (pp.top_expansion_buf.items) |tok| { + if (tok.id == .macro_ws) continue; + if (!tok.id.validPreprocessorExprStart()) { + try pp.comp.diag.add(.{ + .tag = .invalid_preproc_expr_start, + .loc = tok.loc, + }, tok.expansionSlice()); + return false; + } + break; + } else { + try pp.err(eof, .expected_value_in_expr); + return false; + } + + // validate the tokens in the expression + try pp.tokens.ensureUnusedCapacity(pp.gpa, pp.top_expansion_buf.items.len); + var i: usize = 0; + const items = pp.top_expansion_buf.items; + while (i < items.len) : (i += 1) { + var tok = items[i]; + switch (tok.id) { + .string_literal, + .string_literal_utf_16, + .string_literal_utf_8, + .string_literal_utf_32, + .string_literal_wide, + => { + try pp.comp.diag.add(.{ + .tag = .string_literal_in_pp_expr, + .loc = tok.loc, + }, tok.expansionSlice()); + return false; + }, + .plus_plus, + .minus_minus, + .plus_equal, + .minus_equal, + .asterisk_equal, + .slash_equal, + .percent_equal, + .angle_bracket_angle_bracket_left_equal, + .angle_bracket_angle_bracket_right_equal, + .ampersand_equal, + .caret_equal, + .pipe_equal, + .l_bracket, + .r_bracket, + .l_brace, + .r_brace, + .ellipsis, + .semicolon, + .hash, + .hash_hash, + .equal, + .arrow, + .period, + => { + try pp.comp.diag.add(.{ + .tag = .invalid_preproc_operator, + .loc = tok.loc, + }, tok.expansionSlice()); + return false; + }, + .macro_ws, .whitespace => continue, + .keyword_false => tok.id = .zero, + .keyword_true => tok.id = .one, + else => if (tok.id.isMacroIdentifier()) { + if (tok.id == .keyword_defined) { + const tokens_consumed = try pp.handleKeywordDefined(&tok, items[i + 1 ..], eof); + i += tokens_consumed; + } else { + try pp.comp.diag.add(.{ + .tag = .undefined_macro, + .loc = tok.loc, + .extra = .{ .str = pp.expandedSlice(tok) }, + }, tok.expansionSlice()); + + if (i + 1 < pp.top_expansion_buf.items.len and + pp.top_expansion_buf.items[i + 1].id == .l_paren) + { + try pp.comp.diag.add(.{ + .tag = .fn_macro_undefined, + .loc = tok.loc, + .extra = .{ .str = pp.expandedSlice(tok) }, + }, tok.expansionSlice()); + return false; + } + + tok.id = .zero; // undefined macro + } + }, + } + pp.tokens.appendAssumeCapacity(tok); + } + try pp.tokens.append(pp.gpa, .{ + .id = .eof, + .loc = tokFromRaw(eof).loc, + }); + + // Actually parse it. + var parser = Parser{ + .pp = pp, + .comp = pp.comp, + .gpa = pp.gpa, + .tok_ids = pp.tokens.items(.id), + .tok_i = @intCast(start), + .arena = pp.arena.allocator(), + .in_macro = true, + .data = undefined, + .strings = undefined, + .retained_strings = undefined, + .value_map = undefined, + .labels = undefined, + .decl_buf = undefined, + .list_buf = undefined, + .param_buf = undefined, + .enum_buf = undefined, + .record_buf = undefined, + .attr_buf = undefined, + .field_attr_buf = undefined, + .string_ids = undefined, + }; + return parser.macroExpr(); +} + +/// Turns macro_tok from .keyword_defined into .zero or .one depending on whether the argument is defined +/// Returns the number of tokens consumed +fn handleKeywordDefined(pp: *Preprocessor, macro_tok: *Token, tokens: []const Token, eof: RawToken) !usize { + std.debug.assert(macro_tok.id == .keyword_defined); + var it = TokenIterator.init(tokens); + const first = it.nextNoWS() orelse { + try pp.err(eof, .macro_name_missing); + return it.i; + }; + switch (first.id) { + .l_paren => {}, + else => { + if (!first.id.isMacroIdentifier()) { + try pp.comp.diag.add(.{ + .tag = .macro_name_must_be_identifier, + .loc = first.loc, + .extra = .{ .str = pp.expandedSlice(first) }, + }, first.expansionSlice()); + } + macro_tok.id = if (pp.defines.contains(pp.expandedSlice(first))) .one else .zero; + return it.i; + }, + } + const second = it.nextNoWS() orelse { + try pp.err(eof, .macro_name_missing); + return it.i; + }; + if (!second.id.isMacroIdentifier()) { + try pp.comp.diag.add(.{ + .tag = .macro_name_must_be_identifier, + .loc = second.loc, + }, second.expansionSlice()); + return it.i; + } + macro_tok.id = if (pp.defines.contains(pp.expandedSlice(second))) .one else .zero; + + const last = it.nextNoWS(); + if (last == null or last.?.id != .r_paren) { + const tok = last orelse tokFromRaw(eof); + try pp.comp.diag.add(.{ + .tag = .closing_paren, + .loc = tok.loc, + }, tok.expansionSlice()); + try pp.comp.diag.add(.{ + .tag = .to_match_paren, + .loc = first.loc, + }, first.expansionSlice()); + } + + return it.i; +} + +/// Skip until #else #elif #endif, return last directive token id. +/// Also skips nested #if ... #endifs. +fn skip( + pp: *Preprocessor, + tokenizer: *Tokenizer, + cont: enum { until_else, until_endif, until_endif_seen_else }, +) Error!void { + var ifs_seen: u32 = 0; + var line_start = true; + while (tokenizer.index < tokenizer.buf.len) { + if (line_start) { + const saved_tokenizer = tokenizer.*; + const hash = tokenizer.nextNoWS(); + if (hash.id == .nl) continue; + line_start = false; + if (hash.id != .hash) continue; + const directive = tokenizer.nextNoWS(); + switch (directive.id) { + .keyword_else => { + if (ifs_seen != 0) continue; + if (cont == .until_endif_seen_else) { + try pp.err(directive, .else_after_else); + continue; + } + tokenizer.* = saved_tokenizer; + return; + }, + .keyword_elif => { + if (ifs_seen != 0 or cont == .until_endif) continue; + if (cont == .until_endif_seen_else) { + try pp.err(directive, .elif_after_else); + continue; + } + tokenizer.* = saved_tokenizer; + return; + }, + .keyword_elifdef => { + if (ifs_seen != 0 or cont == .until_endif) continue; + if (cont == .until_endif_seen_else) { + try pp.err(directive, .elifdef_after_else); + continue; + } + tokenizer.* = saved_tokenizer; + return; + }, + .keyword_elifndef => { + if (ifs_seen != 0 or cont == .until_endif) continue; + if (cont == .until_endif_seen_else) { + try pp.err(directive, .elifndef_after_else); + continue; + } + tokenizer.* = saved_tokenizer; + return; + }, + .keyword_endif => { + if (ifs_seen == 0) { + tokenizer.* = saved_tokenizer; + return; + } + ifs_seen -= 1; + }, + .keyword_if, .keyword_ifdef, .keyword_ifndef => ifs_seen += 1, + else => {}, + } + } else if (tokenizer.buf[tokenizer.index] == '\n') { + line_start = true; + tokenizer.index += 1; + tokenizer.line += 1; + } else { + line_start = false; + tokenizer.index += 1; + } + } else { + const eof = tokenizer.next(); + return pp.err(eof, .unterminated_conditional_directive); + } +} + +// Skip until newline, ignore other tokens. +fn skipToNl(tokenizer: *Tokenizer) void { + while (true) { + const tok = tokenizer.next(); + if (tok.id == .nl or tok.id == .eof) return; + } +} + +const ExpandBuf = std.ArrayList(Token); +fn removePlacemarkers(buf: *ExpandBuf) void { + var i: usize = buf.items.len -% 1; + while (i < buf.items.len) : (i -%= 1) { + if (buf.items[i].id == .placemarker) { + const placemarker = buf.orderedRemove(i); + Token.free(placemarker.expansion_locs, buf.allocator); + } + } +} + +const MacroArguments = std.ArrayList([]const Token); +fn deinitMacroArguments(allocator: Allocator, args: *const MacroArguments) void { + for (args.items) |item| { + for (item) |tok| Token.free(tok.expansion_locs, allocator); + allocator.free(item); + } + args.deinit(); +} + +fn expandObjMacro(pp: *Preprocessor, simple_macro: *const Macro) Error!ExpandBuf { + var buf = ExpandBuf.init(pp.gpa); + errdefer buf.deinit(); + try buf.ensureTotalCapacity(simple_macro.tokens.len); + + // Add all of the simple_macros tokens to the new buffer handling any concats. + var i: usize = 0; + while (i < simple_macro.tokens.len) : (i += 1) { + const raw = simple_macro.tokens[i]; + const tok = tokFromRaw(raw); + switch (raw.id) { + .hash_hash => { + var rhs = tokFromRaw(simple_macro.tokens[i + 1]); + i += 1; + while (rhs.id == .whitespace) { + rhs = tokFromRaw(simple_macro.tokens[i + 1]); + i += 1; + } + try pp.pasteTokens(&buf, &.{rhs}); + }, + .whitespace => if (pp.preserve_whitespace) buf.appendAssumeCapacity(tok), + .macro_file => { + const start = pp.comp.generated_buf.items.len; + const source = pp.comp.getSource(pp.expansion_source_loc.id); + try pp.comp.generated_buf.writer().print("\"{s}\"\n", .{source.path}); + + buf.appendAssumeCapacity(try pp.makeGeneratedToken(start, .string_literal, tok)); + }, + .macro_line => { + const start = pp.comp.generated_buf.items.len; + const source = pp.comp.getSource(pp.expansion_source_loc.id); + try pp.comp.generated_buf.writer().print("{d}\n", .{source.physicalLine(pp.expansion_source_loc)}); + + buf.appendAssumeCapacity(try pp.makeGeneratedToken(start, .pp_num, tok)); + }, + .macro_counter => { + defer pp.counter += 1; + const start = pp.comp.generated_buf.items.len; + try pp.comp.generated_buf.writer().print("{d}\n", .{pp.counter}); + + buf.appendAssumeCapacity(try pp.makeGeneratedToken(start, .pp_num, tok)); + }, + else => buf.appendAssumeCapacity(tok), + } + } + + return buf; +} + +/// Join a possibly-parenthesized series of string literal tokens into a single string without +/// leading or trailing quotes. The returned slice is invalidated if pp.char_buf changes. +/// Returns error.ExpectedStringLiteral if parentheses are not balanced, a non-string-literal +/// is encountered, or if no string literals are encountered +/// TODO: destringize (replace all '\\' with a single `\` and all '\"' with a '"') +fn pasteStringsUnsafe(pp: *Preprocessor, toks: []const Token) ![]const u8 { + const char_top = pp.char_buf.items.len; + defer pp.char_buf.items.len = char_top; + var unwrapped = toks; + if (toks.len >= 2 and toks[0].id == .l_paren and toks[toks.len - 1].id == .r_paren) { + unwrapped = toks[1 .. toks.len - 1]; + } + if (unwrapped.len == 0) return error.ExpectedStringLiteral; + + for (unwrapped) |tok| { + if (tok.id == .macro_ws) continue; + if (tok.id != .string_literal) return error.ExpectedStringLiteral; + const str = pp.expandedSlice(tok); + try pp.char_buf.appendSlice(str[1 .. str.len - 1]); + } + return pp.char_buf.items[char_top..]; +} + +/// Handle the _Pragma operator (implemented as a builtin macro) +fn pragmaOperator(pp: *Preprocessor, arg_tok: Token, operator_loc: Source.Location) !void { + const arg_slice = pp.expandedSlice(arg_tok); + const content = arg_slice[1 .. arg_slice.len - 1]; + const directive = "#pragma "; + + pp.char_buf.clearRetainingCapacity(); + const total_len = directive.len + content.len + 1; // destringify can never grow the string, + 1 for newline + try pp.char_buf.ensureUnusedCapacity(total_len); + pp.char_buf.appendSliceAssumeCapacity(directive); + pp.destringify(content); + pp.char_buf.appendAssumeCapacity('\n'); + + const start = pp.comp.generated_buf.items.len; + try pp.comp.generated_buf.appendSlice(pp.char_buf.items); + var tmp_tokenizer = Tokenizer{ + .buf = pp.comp.generated_buf.items, + .comp = pp.comp, + .index = @intCast(start), + .source = .generated, + .line = pp.generated_line, + }; + pp.generated_line += 1; + const hash_tok = tmp_tokenizer.next(); + assert(hash_tok.id == .hash); + const pragma_tok = tmp_tokenizer.next(); + assert(pragma_tok.id == .keyword_pragma); + try pp.pragma(&tmp_tokenizer, pragma_tok, operator_loc, arg_tok.expansionSlice()); +} + +/// Inverts the output of the preprocessor stringify (#) operation +/// (except all whitespace is condensed to a single space) +/// writes output to pp.char_buf; assumes capacity is sufficient +/// backslash backslash -> backslash +/// backslash doublequote -> doublequote +/// All other characters remain the same +fn destringify(pp: *Preprocessor, str: []const u8) void { + var state: enum { start, backslash_seen } = .start; + for (str) |c| { + switch (c) { + '\\' => { + if (state == .backslash_seen) pp.char_buf.appendAssumeCapacity(c); + state = if (state == .start) .backslash_seen else .start; + }, + else => { + if (state == .backslash_seen and c != '"') pp.char_buf.appendAssumeCapacity('\\'); + pp.char_buf.appendAssumeCapacity(c); + state = .start; + }, + } + } +} + +/// Stringify `tokens` into pp.char_buf. +/// See https://gcc.gnu.org/onlinedocs/gcc-11.2.0/cpp/Stringizing.html#Stringizing +fn stringify(pp: *Preprocessor, tokens: []const Token) !void { + try pp.char_buf.append('"'); + var ws_state: enum { start, need, not_needed } = .start; + for (tokens) |tok| { + if (tok.id == .macro_ws) { + if (ws_state == .start) continue; + ws_state = .need; + continue; + } + if (ws_state == .need) try pp.char_buf.append(' '); + ws_state = .not_needed; + + // backslashes not inside strings are not escaped + const is_str = switch (tok.id) { + .string_literal, + .string_literal_utf_16, + .string_literal_utf_8, + .string_literal_utf_32, + .string_literal_wide, + .char_literal, + .char_literal_utf_16, + .char_literal_utf_32, + .char_literal_wide, + => true, + else => false, + }; + + for (pp.expandedSlice(tok)) |c| { + if (c == '"') + try pp.char_buf.appendSlice("\\\"") + else if (c == '\\' and is_str) + try pp.char_buf.appendSlice("\\\\") + else + try pp.char_buf.append(c); + } + } + if (pp.char_buf.items[pp.char_buf.items.len - 1] == '\\') { + const tok = tokens[tokens.len - 1]; + try pp.comp.diag.add(.{ + .tag = .invalid_pp_stringify_escape, + .loc = tok.loc, + }, tok.expansionSlice()); + pp.char_buf.items.len -= 1; + } + try pp.char_buf.appendSlice("\"\n"); +} + +fn reconstructIncludeString(pp: *Preprocessor, param_toks: []const Token) !?[]const u8 { + const char_top = pp.char_buf.items.len; + defer pp.char_buf.items.len = char_top; + + // Trim leading/trailing whitespace + var begin: usize = 0; + var end: usize = param_toks.len; + while (begin < end and param_toks[begin].id == .macro_ws) : (begin += 1) {} + while (end > begin and param_toks[end - 1].id == .macro_ws) : (end -= 1) {} + const params = param_toks[begin..end]; + + if (params.len == 0) { + try pp.comp.diag.add(.{ + .tag = .expected_filename, + .loc = param_toks[0].loc, + }, param_toks[0].expansionSlice()); + return null; + } + // no string pasting + if (params[0].id == .string_literal and params.len > 1) { + try pp.comp.diag.add(.{ + .tag = .closing_paren, + .loc = params[1].loc, + }, params[1].expansionSlice()); + return null; + } + + for (params) |tok| { + const str = pp.expandedSliceExtra(tok, .preserve_macro_ws); + try pp.char_buf.appendSlice(str); + } + + const include_str = pp.char_buf.items[char_top..]; + if (include_str.len < 3) { + try pp.comp.diag.add(.{ + .tag = .empty_filename, + .loc = params[0].loc, + }, params[0].expansionSlice()); + return null; + } + + switch (include_str[0]) { + '<' => { + if (include_str[include_str.len - 1] != '>') { + // Ugly hack to find out where the '>' should go, since we don't have the closing ')' location + const start = params[0].loc; + try pp.comp.diag.add(.{ + .tag = .header_str_closing, + .loc = .{ .id = start.id, .byte_offset = start.byte_offset + @as(u32, @intCast(include_str.len)) + 1, .line = start.line }, + }, params[0].expansionSlice()); + try pp.comp.diag.add(.{ + .tag = .header_str_match, + .loc = params[0].loc, + }, params[0].expansionSlice()); + return null; + } + return include_str; + }, + '"' => return include_str, + else => { + try pp.comp.diag.add(.{ + .tag = .expected_filename, + .loc = params[0].loc, + }, params[0].expansionSlice()); + return null; + }, + } +} + +fn handleBuiltinMacro(pp: *Preprocessor, builtin: RawToken.Id, param_toks: []const Token, src_loc: Source.Location) Error!bool { + switch (builtin) { + .macro_param_has_attribute, + .macro_param_has_feature, + .macro_param_has_extension, + .macro_param_has_builtin, + => { + var invalid: ?Token = null; + var identifier: ?Token = null; + for (param_toks) |tok| { + if (tok.id == .macro_ws) continue; + if (!tok.id.isMacroIdentifier()) { + invalid = tok; + break; + } + if (identifier) |_| invalid = tok else identifier = tok; + } + if (identifier == null and invalid == null) invalid = .{ .id = .eof, .loc = src_loc }; + if (invalid) |some| { + try pp.comp.diag.add( + .{ .tag = .feature_check_requires_identifier, .loc = some.loc }, + some.expansionSlice(), + ); + return false; + } + + const ident_str = pp.expandedSlice(identifier.?); + return switch (builtin) { + .macro_param_has_attribute => Attribute.fromString(.gnu, null, ident_str) != null, + .macro_param_has_feature => features.hasFeature(pp.comp, ident_str), + .macro_param_has_extension => features.hasExtension(pp.comp, ident_str), + .macro_param_has_builtin => pp.comp.hasBuiltin(ident_str), + else => unreachable, + }; + }, + .macro_param_has_warning => { + const actual_param = pp.pasteStringsUnsafe(param_toks) catch |er| switch (er) { + error.ExpectedStringLiteral => { + try pp.comp.diag.add(.{ + .tag = .expected_str_literal_in, + .loc = param_toks[0].loc, + .extra = .{ .str = "__has_warning" }, + }, param_toks[0].expansionSlice()); + return false; + }, + else => |e| return e, + }; + if (!mem.startsWith(u8, actual_param, "-W")) { + try pp.comp.diag.add(.{ + .tag = .malformed_warning_check, + .loc = param_toks[0].loc, + .extra = .{ .str = "__has_warning" }, + }, param_toks[0].expansionSlice()); + return false; + } + const warning_name = actual_param[2..]; + return Diagnostics.warningExists(warning_name); + }, + .macro_param_is_identifier => { + var invalid: ?Token = null; + var identifier: ?Token = null; + for (param_toks) |tok| switch (tok.id) { + .macro_ws => continue, + else => { + if (identifier) |_| invalid = tok else identifier = tok; + }, + }; + if (identifier == null and invalid == null) invalid = .{ .id = .eof, .loc = src_loc }; + if (invalid) |some| { + try pp.comp.diag.add(.{ + .tag = .missing_tok_builtin, + .loc = some.loc, + .extra = .{ .tok_id_expected = .r_paren }, + }, some.expansionSlice()); + return false; + } + + const id = identifier.?.id; + return id == .identifier or id == .extended_identifier; + }, + .macro_param_has_include, .macro_param_has_include_next => { + const include_str = (try pp.reconstructIncludeString(param_toks)) orelse return false; + const include_type: Compilation.IncludeType = switch (include_str[0]) { + '"' => .quotes, + '<' => .angle_brackets, + else => unreachable, + }; + const filename = include_str[1 .. include_str.len - 1]; + if (builtin == .macro_param_has_include or pp.include_depth == 0) { + if (builtin == .macro_param_has_include_next) { + try pp.comp.diag.add(.{ + .tag = .include_next_outside_header, + .loc = src_loc, + }, &.{}); + } + return pp.comp.hasInclude(filename, src_loc.id, include_type, .first); + } + return pp.comp.hasInclude(filename, src_loc.id, include_type, .next); + }, + else => unreachable, + } +} + +fn expandFuncMacro( + pp: *Preprocessor, + loc: Source.Location, + func_macro: *const Macro, + args: *const MacroArguments, + expanded_args: *const MacroArguments, +) MacroError!ExpandBuf { + var buf = ExpandBuf.init(pp.gpa); + try buf.ensureTotalCapacity(func_macro.tokens.len); + errdefer buf.deinit(); + + var expanded_variable_arguments = ExpandBuf.init(pp.gpa); + defer expanded_variable_arguments.deinit(); + var variable_arguments = ExpandBuf.init(pp.gpa); + defer variable_arguments.deinit(); + + if (func_macro.var_args) { + var i: usize = func_macro.params.len; + while (i < expanded_args.items.len) : (i += 1) { + try variable_arguments.appendSlice(args.items[i]); + try expanded_variable_arguments.appendSlice(expanded_args.items[i]); + if (i != expanded_args.items.len - 1) { + const comma = Token{ .id = .comma, .loc = .{ .id = .generated } }; + try variable_arguments.append(comma); + try expanded_variable_arguments.append(comma); + } + } + } + + // token concatenation and expansion phase + var tok_i: usize = 0; + while (tok_i < func_macro.tokens.len) : (tok_i += 1) { + const raw = func_macro.tokens[tok_i]; + switch (raw.id) { + .hash_hash => while (tok_i + 1 < func_macro.tokens.len) { + const raw_next = func_macro.tokens[tok_i + 1]; + tok_i += 1; + + const next = switch (raw_next.id) { + .macro_ws => continue, + .hash_hash => continue, + .macro_param, .macro_param_no_expand => if (args.items[raw_next.end].len > 0) + args.items[raw_next.end] + else + &[1]Token{tokFromRaw(.{ .id = .placemarker, .source = .generated })}, + .keyword_va_args => variable_arguments.items, + else => &[1]Token{tokFromRaw(raw_next)}, + }; + + try pp.pasteTokens(&buf, next); + if (next.len != 0) break; + }, + .macro_param_no_expand => { + const slice = if (args.items[raw.end].len > 0) + args.items[raw.end] + else + &[1]Token{tokFromRaw(.{ .id = .placemarker, .source = .generated })}; + const raw_loc = Source.Location{ .id = raw.source, .byte_offset = raw.start, .line = raw.line }; + try bufCopyTokens(&buf, slice, &.{raw_loc}); + }, + .macro_param => { + const arg = expanded_args.items[raw.end]; + const raw_loc = Source.Location{ .id = raw.source, .byte_offset = raw.start, .line = raw.line }; + try bufCopyTokens(&buf, arg, &.{raw_loc}); + }, + .keyword_va_args => { + const raw_loc = Source.Location{ .id = raw.source, .byte_offset = raw.start, .line = raw.line }; + try bufCopyTokens(&buf, expanded_variable_arguments.items, &.{raw_loc}); + }, + .stringify_param, .stringify_va_args => { + const arg = if (raw.id == .stringify_va_args) + variable_arguments.items + else + args.items[raw.end]; + + pp.char_buf.clearRetainingCapacity(); + try pp.stringify(arg); + + const start = pp.comp.generated_buf.items.len; + try pp.comp.generated_buf.appendSlice(pp.char_buf.items); + + try buf.append(try pp.makeGeneratedToken(start, .string_literal, tokFromRaw(raw))); + }, + .macro_param_has_attribute, + .macro_param_has_warning, + .macro_param_has_feature, + .macro_param_has_extension, + .macro_param_has_builtin, + .macro_param_has_include, + .macro_param_has_include_next, + .macro_param_is_identifier, + => { + const arg = expanded_args.items[0]; + const result = if (arg.len == 0) blk: { + const extra = Diagnostics.Message.Extra{ .arguments = .{ .expected = 1, .actual = 0 } }; + try pp.comp.diag.add(.{ .tag = .expected_arguments, .loc = loc, .extra = extra }, &.{}); + break :blk false; + } else try pp.handleBuiltinMacro(raw.id, arg, loc); + const start = pp.comp.generated_buf.items.len; + try pp.comp.generated_buf.writer().print("{}\n", .{@intFromBool(result)}); + try buf.append(try pp.makeGeneratedToken(start, .pp_num, tokFromRaw(raw))); + }, + .macro_param_pragma_operator => { + const param_toks = expanded_args.items[0]; + // Clang and GCC require exactly one token (so, no parentheses or string pasting) + // even though their error messages indicate otherwise. Ours is slightly more + // descriptive. + var invalid: ?Token = null; + var string: ?Token = null; + for (param_toks) |tok| switch (tok.id) { + .string_literal => { + if (string) |_| invalid = tok else string = tok; + }, + .macro_ws => continue, + else => { + invalid = tok; + break; + }, + }; + if (string == null and invalid == null) invalid = .{ .loc = loc, .id = .eof }; + if (invalid) |some| try pp.comp.diag.add( + .{ .tag = .pragma_operator_string_literal, .loc = some.loc }, + some.expansionSlice(), + ) else try pp.pragmaOperator(string.?, loc); + }, + .comma => { + if (tok_i + 2 < func_macro.tokens.len and func_macro.tokens[tok_i + 1].id == .hash_hash) { + const hash_hash = func_macro.tokens[tok_i + 1]; + var maybe_va_args = func_macro.tokens[tok_i + 2]; + var consumed: usize = 2; + if (maybe_va_args.id == .macro_ws and tok_i + 3 < func_macro.tokens.len) { + consumed = 3; + maybe_va_args = func_macro.tokens[tok_i + 3]; + } + if (maybe_va_args.id == .keyword_va_args) { + // GNU extension: `, ##__VA_ARGS__` deletes the comma if __VA_ARGS__ is empty + tok_i += consumed; + if (func_macro.params.len == expanded_args.items.len) { + // Empty __VA_ARGS__, drop the comma + try pp.err(hash_hash, .comma_deletion_va_args); + } else if (func_macro.params.len == 0 and expanded_args.items.len == 1 and expanded_args.items[0].len == 0) { + // Ambiguous whether this is "empty __VA_ARGS__" or "__VA_ARGS__ omitted" + if (pp.comp.langopts.standard.isGNU()) { + // GNU standard, drop the comma + try pp.err(hash_hash, .comma_deletion_va_args); + } else { + // C standard, retain the comma + try buf.append(tokFromRaw(raw)); + } + } else { + try buf.append(tokFromRaw(raw)); + if (expanded_variable_arguments.items.len > 0 or variable_arguments.items.len == func_macro.params.len) { + try pp.err(hash_hash, .comma_deletion_va_args); + } + const raw_loc = Source.Location{ + .id = maybe_va_args.source, + .byte_offset = maybe_va_args.start, + .line = maybe_va_args.line, + }; + try bufCopyTokens(&buf, expanded_variable_arguments.items, &.{raw_loc}); + } + continue; + } + } + // Regular comma, no token pasting with __VA_ARGS__ + try buf.append(tokFromRaw(raw)); + }, + else => try buf.append(tokFromRaw(raw)), + } + } + removePlacemarkers(&buf); + + return buf; +} + +fn shouldExpand(tok: Token, macro: *Macro) bool { + // macro.loc.line contains the macros end index + if (tok.loc.id == macro.loc.id and + tok.loc.byte_offset >= macro.loc.byte_offset and + tok.loc.byte_offset <= macro.loc.line) + return false; + for (tok.expansionSlice()) |loc| { + if (loc.id == macro.loc.id and + loc.byte_offset >= macro.loc.byte_offset and + loc.byte_offset <= macro.loc.line) + return false; + } + if (tok.flags.expansion_disabled) return false; + + return true; +} + +fn bufCopyTokens(buf: *ExpandBuf, tokens: []const Token, src: []const Source.Location) !void { + try buf.ensureUnusedCapacity(tokens.len); + for (tokens) |tok| { + var copy = try tok.dupe(buf.allocator); + errdefer Token.free(copy.expansion_locs, buf.allocator); + try copy.addExpansionLocation(buf.allocator, src); + buf.appendAssumeCapacity(copy); + } +} + +fn nextBufToken( + pp: *Preprocessor, + tokenizer: *Tokenizer, + buf: *ExpandBuf, + start_idx: *usize, + end_idx: *usize, + extend_buf: bool, +) Error!Token { + start_idx.* += 1; + if (start_idx.* == buf.items.len and start_idx.* >= end_idx.*) { + if (extend_buf) { + const raw_tok = tokenizer.next(); + if (raw_tok.id.isMacroIdentifier() and + pp.poisoned_identifiers.get(pp.tokSlice(raw_tok)) != null) + try pp.err(raw_tok, .poisoned_identifier); + + if (raw_tok.id == .nl) pp.add_expansion_nl += 1; + + const new_tok = tokFromRaw(raw_tok); + end_idx.* += 1; + try buf.append(new_tok); + return new_tok; + } else { + return Token{ .id = .eof, .loc = .{ .id = .generated } }; + } + } else { + return buf.items[start_idx.*]; + } +} + +fn collectMacroFuncArguments( + pp: *Preprocessor, + tokenizer: *Tokenizer, + buf: *ExpandBuf, + start_idx: *usize, + end_idx: *usize, + extend_buf: bool, + is_builtin: bool, +) !MacroArguments { + const name_tok = buf.items[start_idx.*]; + const saved_tokenizer = tokenizer.*; + const old_end = end_idx.*; + + while (true) { + const tok = try nextBufToken(pp, tokenizer, buf, start_idx, end_idx, extend_buf); + switch (tok.id) { + .nl, .whitespace, .macro_ws => {}, + .l_paren => break, + else => { + if (is_builtin) { + try pp.comp.diag.add(.{ + .tag = .missing_lparen_after_builtin, + .loc = name_tok.loc, + .extra = .{ .str = pp.expandedSlice(name_tok) }, + }, tok.expansionSlice()); + } + // Not a macro function call, go over normal identifier, rewind + tokenizer.* = saved_tokenizer; + end_idx.* = old_end; + return error.MissingLParen; + }, + } + } + + // collect the arguments. + var parens: u32 = 0; + var args = MacroArguments.init(pp.gpa); + errdefer deinitMacroArguments(pp.gpa, &args); + var curArgument = std.ArrayList(Token).init(pp.gpa); + defer curArgument.deinit(); + while (true) { + var tok = try nextBufToken(pp, tokenizer, buf, start_idx, end_idx, extend_buf); + tok.flags.is_macro_arg = true; + switch (tok.id) { + .comma => { + if (parens == 0) { + const owned = try curArgument.toOwnedSlice(); + errdefer pp.gpa.free(owned); + try args.append(owned); + } else { + const duped = try tok.dupe(pp.gpa); + errdefer Token.free(duped.expansion_locs, pp.gpa); + try curArgument.append(duped); + } + }, + .l_paren => { + const duped = try tok.dupe(pp.gpa); + errdefer Token.free(duped.expansion_locs, pp.gpa); + try curArgument.append(duped); + parens += 1; + }, + .r_paren => { + if (parens == 0) { + const owned = try curArgument.toOwnedSlice(); + errdefer pp.gpa.free(owned); + try args.append(owned); + break; + } else { + const duped = try tok.dupe(pp.gpa); + errdefer Token.free(duped.expansion_locs, pp.gpa); + try curArgument.append(duped); + parens -= 1; + } + }, + .eof => { + { + const owned = try curArgument.toOwnedSlice(); + errdefer pp.gpa.free(owned); + try args.append(owned); + } + tokenizer.* = saved_tokenizer; + try pp.comp.diag.add( + .{ .tag = .unterminated_macro_arg_list, .loc = name_tok.loc }, + name_tok.expansionSlice(), + ); + return error.Unterminated; + }, + .nl, .whitespace => { + try curArgument.append(.{ .id = .macro_ws, .loc = tok.loc }); + }, + else => { + const duped = try tok.dupe(pp.gpa); + errdefer Token.free(duped.expansion_locs, pp.gpa); + try curArgument.append(duped); + }, + } + } + + return args; +} + +fn removeExpandedTokens(pp: *Preprocessor, buf: *ExpandBuf, start: usize, len: usize, moving_end_idx: *usize) !void { + for (buf.items[start .. start + len]) |tok| Token.free(tok.expansion_locs, pp.gpa); + try buf.replaceRange(start, len, &.{}); + moving_end_idx.* -|= len; +} + +/// The behavior of `defined` depends on whether we are in a preprocessor +/// expression context (#if or #elif) or not. +/// In a non-expression context it's just an identifier. Within a preprocessor +/// expression it is a unary operator or one-argument function. +const EvalContext = enum { + expr, + non_expr, +}; + +/// Helper for safely iterating over a slice of tokens while skipping whitespace +const TokenIterator = struct { + toks: []const Token, + i: usize, + + fn init(toks: []const Token) TokenIterator { + return .{ .toks = toks, .i = 0 }; + } + + fn nextNoWS(self: *TokenIterator) ?Token { + while (self.i < self.toks.len) : (self.i += 1) { + const tok = self.toks[self.i]; + if (tok.id == .whitespace or tok.id == .macro_ws) continue; + + self.i += 1; + return tok; + } + return null; + } +}; + +fn expandMacroExhaustive( + pp: *Preprocessor, + tokenizer: *Tokenizer, + buf: *ExpandBuf, + start_idx: usize, + end_idx: usize, + extend_buf: bool, + eval_ctx: EvalContext, +) MacroError!void { + var moving_end_idx = end_idx; + var advance_index: usize = 0; + // rescan loop + var do_rescan = true; + while (do_rescan) { + do_rescan = false; + // expansion loop + var idx: usize = start_idx + advance_index; + while (idx < moving_end_idx) { + const macro_tok = buf.items[idx]; + if (macro_tok.id == .keyword_defined and eval_ctx == .expr) { + idx += 1; + var it = TokenIterator.init(buf.items[idx..moving_end_idx]); + if (it.nextNoWS()) |tok| { + switch (tok.id) { + .l_paren => { + _ = it.nextNoWS(); // eat (what should be) identifier + _ = it.nextNoWS(); // eat (what should be) r paren + }, + .identifier, .extended_identifier => {}, + else => {}, + } + } + idx += it.i; + continue; + } + const macro_entry = pp.defines.getPtr(pp.expandedSlice(macro_tok)); + if (macro_entry == null or !shouldExpand(buf.items[idx], macro_entry.?)) { + idx += 1; + continue; + } + if (macro_entry) |macro| macro_handler: { + if (macro.is_func) { + var macro_scan_idx = idx; + // to be saved in case this doesn't turn out to be a call + const args = pp.collectMacroFuncArguments( + tokenizer, + buf, + ¯o_scan_idx, + &moving_end_idx, + extend_buf, + macro.is_builtin, + ) catch |er| switch (er) { + error.MissingLParen => { + if (!buf.items[idx].flags.is_macro_arg) buf.items[idx].flags.expansion_disabled = true; + idx += 1; + break :macro_handler; + }, + error.Unterminated => { + if (pp.comp.langopts.emulate == .gcc) idx += 1; + try pp.removeExpandedTokens(buf, idx, macro_scan_idx - idx, &moving_end_idx); + break :macro_handler; + }, + else => |e| return e, + }; + defer { + for (args.items) |item| { + pp.gpa.free(item); + } + args.deinit(); + } + + var args_count: u32 = @intCast(args.items.len); + // if the macro has zero arguments g() args_count is still 1 + // an empty token list g() and a whitespace-only token list g( ) + // counts as zero arguments for the purposes of argument-count validation + if (args_count == 1 and macro.params.len == 0) { + for (args.items[0]) |tok| { + if (tok.id != .macro_ws) break; + } else { + args_count = 0; + } + } + + // Validate argument count. + const extra = Diagnostics.Message.Extra{ + .arguments = .{ .expected = @intCast(macro.params.len), .actual = args_count }, + }; + if (macro.var_args and args_count < macro.params.len) { + try pp.comp.diag.add( + .{ .tag = .expected_at_least_arguments, .loc = buf.items[idx].loc, .extra = extra }, + buf.items[idx].expansionSlice(), + ); + idx += 1; + try pp.removeExpandedTokens(buf, idx, macro_scan_idx - idx + 1, &moving_end_idx); + continue; + } + if (!macro.var_args and args_count != macro.params.len) { + try pp.comp.diag.add( + .{ .tag = .expected_arguments, .loc = buf.items[idx].loc, .extra = extra }, + buf.items[idx].expansionSlice(), + ); + idx += 1; + try pp.removeExpandedTokens(buf, idx, macro_scan_idx - idx + 1, &moving_end_idx); + continue; + } + var expanded_args = MacroArguments.init(pp.gpa); + defer deinitMacroArguments(pp.gpa, &expanded_args); + try expanded_args.ensureTotalCapacity(args.items.len); + for (args.items) |arg| { + var expand_buf = ExpandBuf.init(pp.gpa); + errdefer expand_buf.deinit(); + try expand_buf.appendSlice(arg); + + try pp.expandMacroExhaustive(tokenizer, &expand_buf, 0, expand_buf.items.len, false, eval_ctx); + + expanded_args.appendAssumeCapacity(try expand_buf.toOwnedSlice()); + } + + var res = try pp.expandFuncMacro(macro_tok.loc, macro, &args, &expanded_args); + defer res.deinit(); + const tokens_added = res.items.len; + + const macro_expansion_locs = macro_tok.expansionSlice(); + for (res.items) |*tok| { + try tok.addExpansionLocation(pp.gpa, &.{macro_tok.loc}); + try tok.addExpansionLocation(pp.gpa, macro_expansion_locs); + } + + const tokens_removed = macro_scan_idx - idx + 1; + for (buf.items[idx .. idx + tokens_removed]) |tok| Token.free(tok.expansion_locs, pp.gpa); + try buf.replaceRange(idx, tokens_removed, res.items); + + moving_end_idx += tokens_added; + // Overflow here means that we encountered an unterminated argument list + // while expanding the body of this macro. + moving_end_idx -|= tokens_removed; + idx += tokens_added; + do_rescan = true; + } else { + const res = try pp.expandObjMacro(macro); + defer res.deinit(); + + const macro_expansion_locs = macro_tok.expansionSlice(); + var increment_idx_by = res.items.len; + for (res.items, 0..) |*tok, i| { + tok.flags.is_macro_arg = macro_tok.flags.is_macro_arg; + try tok.addExpansionLocation(pp.gpa, &.{macro_tok.loc}); + try tok.addExpansionLocation(pp.gpa, macro_expansion_locs); + if (tok.id == .keyword_defined and eval_ctx == .expr) { + try pp.comp.diag.add(.{ + .tag = .expansion_to_defined, + .loc = tok.loc, + }, tok.expansionSlice()); + } + + if (i < increment_idx_by and (tok.id == .keyword_defined or pp.defines.contains(pp.expandedSlice(tok.*)))) { + increment_idx_by = i; + } + } + + Token.free(buf.items[idx].expansion_locs, pp.gpa); + try buf.replaceRange(idx, 1, res.items); + idx += increment_idx_by; + moving_end_idx = moving_end_idx + res.items.len - 1; + do_rescan = true; + } + } + if (idx - start_idx == advance_index + 1 and !do_rescan) { + advance_index += 1; + } + } // end of replacement phase + } + // end of scanning phase + + // trim excess buffer + for (buf.items[moving_end_idx..]) |item| { + Token.free(item.expansion_locs, pp.gpa); + } + buf.items.len = moving_end_idx; +} + +/// Try to expand a macro after a possible candidate has been read from the `tokenizer` +/// into the `raw` token passed as argument +fn expandMacro(pp: *Preprocessor, tokenizer: *Tokenizer, raw: RawToken) MacroError!void { + var source_tok = tokFromRaw(raw); + if (!raw.id.isMacroIdentifier()) { + source_tok.id.simplifyMacroKeyword(); + return pp.tokens.append(pp.gpa, source_tok); + } + pp.top_expansion_buf.items.len = 0; + try pp.top_expansion_buf.append(source_tok); + pp.expansion_source_loc = source_tok.loc; + + try pp.expandMacroExhaustive(tokenizer, &pp.top_expansion_buf, 0, 1, true, .non_expr); + try pp.tokens.ensureUnusedCapacity(pp.gpa, pp.top_expansion_buf.items.len); + for (pp.top_expansion_buf.items) |*tok| { + if (tok.id == .macro_ws and !pp.preserve_whitespace) { + Token.free(tok.expansion_locs, pp.gpa); + continue; + } + tok.id.simplifyMacroKeywordExtra(true); + pp.tokens.appendAssumeCapacity(tok.*); + } + if (pp.preserve_whitespace) { + try pp.tokens.ensureUnusedCapacity(pp.gpa, pp.add_expansion_nl); + while (pp.add_expansion_nl > 0) : (pp.add_expansion_nl -= 1) { + pp.tokens.appendAssumeCapacity(.{ .id = .nl, .loc = .{ .id = .generated } }); + } + } +} + +fn expandedSliceExtra(pp: *const Preprocessor, tok: Token, macro_ws_handling: enum { single_macro_ws, preserve_macro_ws }) []const u8 { + if (tok.id.lexeme()) |some| { + if (!tok.id.allowsDigraphs(pp.comp) and !(tok.id == .macro_ws and macro_ws_handling == .preserve_macro_ws)) return some; + } + var tmp_tokenizer = Tokenizer{ + .buf = pp.comp.getSource(tok.loc.id).buf, + .comp = pp.comp, + .index = tok.loc.byte_offset, + .source = .generated, + }; + if (tok.id == .macro_string) { + while (true) : (tmp_tokenizer.index += 1) { + if (tmp_tokenizer.buf[tmp_tokenizer.index] == '>') break; + } + return tmp_tokenizer.buf[tok.loc.byte_offset .. tmp_tokenizer.index + 1]; + } + const res = tmp_tokenizer.next(); + return tmp_tokenizer.buf[res.start..res.end]; +} + +/// Get expanded token source string. +pub fn expandedSlice(pp: *Preprocessor, tok: Token) []const u8 { + return pp.expandedSliceExtra(tok, .single_macro_ws); +} + +/// Concat two tokens and add the result to pp.generated +fn pasteTokens(pp: *Preprocessor, lhs_toks: *ExpandBuf, rhs_toks: []const Token) Error!void { + const lhs = while (lhs_toks.popOrNull()) |lhs| { + if (lhs.id == .macro_ws) + Token.free(lhs.expansion_locs, pp.gpa) + else + break lhs; + } else { + return bufCopyTokens(lhs_toks, rhs_toks, &.{}); + }; + + var rhs_rest: u32 = 1; + const rhs = for (rhs_toks) |rhs| { + if (rhs.id != .macro_ws) break rhs; + rhs_rest += 1; + } else { + return lhs_toks.appendAssumeCapacity(lhs); + }; + defer Token.free(lhs.expansion_locs, pp.gpa); + + const start = pp.comp.generated_buf.items.len; + const end = start + pp.expandedSlice(lhs).len + pp.expandedSlice(rhs).len; + try pp.comp.generated_buf.ensureTotalCapacity(end + 1); // +1 for a newline + // We cannot use the same slices here since they might be invalidated by `ensureCapacity` + pp.comp.generated_buf.appendSliceAssumeCapacity(pp.expandedSlice(lhs)); + pp.comp.generated_buf.appendSliceAssumeCapacity(pp.expandedSlice(rhs)); + pp.comp.generated_buf.appendAssumeCapacity('\n'); + + // Try to tokenize the result. + var tmp_tokenizer = Tokenizer{ + .buf = pp.comp.generated_buf.items, + .comp = pp.comp, + .index = @intCast(start), + .source = .generated, + }; + const pasted_token = tmp_tokenizer.nextNoWS(); + const next = tmp_tokenizer.nextNoWS().id; + if (next != .nl and next != .eof) { + try pp.comp.diag.add(.{ + .tag = .pasting_formed_invalid, + .loc = lhs.loc, + .extra = .{ .str = try pp.comp.diag.arena.allocator().dupe( + u8, + pp.comp.generated_buf.items[start..end], + ) }, + }, lhs.expansionSlice()); + } + + const pasted_id = if (lhs.id == .placemarker and rhs.id == .placemarker) + .placemarker + else + pasted_token.id; + try lhs_toks.append(try pp.makeGeneratedToken(start, pasted_id, lhs)); + try bufCopyTokens(lhs_toks, rhs_toks[rhs_rest..], &.{}); +} + +fn makeGeneratedToken(pp: *Preprocessor, start: usize, id: Token.Id, source: Token) !Token { + var pasted_token = Token{ .id = id, .loc = .{ + .id = .generated, + .byte_offset = @intCast(start), + .line = pp.generated_line, + } }; + pp.generated_line += 1; + try pasted_token.addExpansionLocation(pp.gpa, &.{source.loc}); + try pasted_token.addExpansionLocation(pp.gpa, source.expansionSlice()); + return pasted_token; +} + +/// Defines a new macro and warns if it is a duplicate +fn defineMacro(pp: *Preprocessor, name_tok: RawToken, macro: Macro) Error!void { + const name_str = pp.tokSlice(name_tok); + const gop = try pp.defines.getOrPut(name_str); + if (gop.found_existing and !gop.value_ptr.eql(macro, pp)) { + try pp.comp.diag.add(.{ + .tag = if (gop.value_ptr.is_builtin) .builtin_macro_redefined else .macro_redefined, + .loc = .{ .id = name_tok.source, .byte_offset = name_tok.start, .line = name_tok.line }, + .extra = .{ .str = name_str }, + }, &.{}); + // TODO add a previous definition note + } + if (pp.verbose) { + pp.verboseLog(name_tok, "macro {s} defined", .{name_str}); + } + gop.value_ptr.* = macro; +} + +/// Handle a #define directive. +fn define(pp: *Preprocessor, tokenizer: *Tokenizer) Error!void { + // Get macro name and validate it. + const macro_name = tokenizer.nextNoWS(); + if (macro_name.id == .keyword_defined) { + try pp.err(macro_name, .defined_as_macro_name); + return skipToNl(tokenizer); + } + if (!macro_name.id.isMacroIdentifier()) { + try pp.err(macro_name, .macro_name_must_be_identifier); + return skipToNl(tokenizer); + } + var macro_name_token_id = macro_name.id; + macro_name_token_id.simplifyMacroKeyword(); + switch (macro_name_token_id) { + .identifier, .extended_identifier => {}, + else => if (macro_name_token_id.isMacroIdentifier()) { + try pp.err(macro_name, .keyword_macro); + }, + } + + // Check for function macros and empty defines. + var first = tokenizer.next(); + switch (first.id) { + .nl, .eof => return pp.defineMacro(macro_name, .{ + .params = undefined, + .tokens = undefined, + .var_args = false, + .loc = undefined, + .is_func = false, + }), + .whitespace => first = tokenizer.next(), + .l_paren => return pp.defineFn(tokenizer, macro_name, first), + else => try pp.err(first, .whitespace_after_macro_name), + } + if (first.id == .hash_hash) { + try pp.err(first, .hash_hash_at_start); + return skipToNl(tokenizer); + } + first.id.simplifyMacroKeyword(); + + pp.token_buf.items.len = 0; // Safe to use since we can only be in one directive at a time. + + var need_ws = false; + // Collect the token body and validate any ## found. + var tok = first; + const end_index = while (true) { + tok.id.simplifyMacroKeyword(); + switch (tok.id) { + .hash_hash => { + const next = tokenizer.nextNoWS(); + switch (next.id) { + .nl, .eof => { + try pp.err(tok, .hash_hash_at_end); + return; + }, + .hash_hash => { + try pp.err(next, .hash_hash_at_end); + return; + }, + else => {}, + } + try pp.token_buf.append(tok); + try pp.token_buf.append(next); + }, + .nl, .eof => break tok.start, + .whitespace => need_ws = true, + else => { + if (tok.id != .whitespace and need_ws) { + need_ws = false; + try pp.token_buf.append(.{ .id = .macro_ws, .source = .generated }); + } + try pp.token_buf.append(tok); + }, + } + tok = tokenizer.next(); + } else unreachable; + + const list = try pp.arena.allocator().dupe(RawToken, pp.token_buf.items); + try pp.defineMacro(macro_name, .{ + .loc = .{ + .id = macro_name.source, + .byte_offset = first.start, + .line = end_index, + }, + .tokens = list, + .params = undefined, + .is_func = false, + .var_args = false, + }); +} + +/// Handle a function like #define directive. +fn defineFn(pp: *Preprocessor, tokenizer: *Tokenizer, macro_name: RawToken, l_paren: RawToken) Error!void { + assert(macro_name.id.isMacroIdentifier()); + var params = std.ArrayList([]const u8).init(pp.gpa); + defer params.deinit(); + + // Parse the parameter list. + var gnu_var_args: []const u8 = ""; + var var_args = false; + const start_index = while (true) { + var tok = tokenizer.nextNoWS(); + if (tok.id == .r_paren) break tok.end; + if (tok.id == .eof) return pp.err(tok, .unterminated_macro_param_list); + if (tok.id == .ellipsis) { + var_args = true; + const r_paren = tokenizer.nextNoWS(); + if (r_paren.id != .r_paren) { + try pp.err(r_paren, .missing_paren_param_list); + try pp.err(l_paren, .to_match_paren); + return skipToNl(tokenizer); + } + break r_paren.end; + } + if (!tok.id.isMacroIdentifier()) { + try pp.err(tok, .invalid_token_param_list); + return skipToNl(tokenizer); + } + + try params.append(pp.tokSlice(tok)); + + tok = tokenizer.nextNoWS(); + if (tok.id == .ellipsis) { + try pp.err(tok, .gnu_va_macro); + gnu_var_args = params.pop(); + const r_paren = tokenizer.nextNoWS(); + if (r_paren.id != .r_paren) { + try pp.err(r_paren, .missing_paren_param_list); + try pp.err(l_paren, .to_match_paren); + return skipToNl(tokenizer); + } + break r_paren.end; + } else if (tok.id == .r_paren) { + break tok.end; + } else if (tok.id != .comma) { + try pp.err(tok, .expected_comma_param_list); + return skipToNl(tokenizer); + } + } else unreachable; + + var need_ws = false; + // Collect the body tokens and validate # and ##'s found. + pp.token_buf.items.len = 0; // Safe to use since we can only be in one directive at a time. + const end_index = tok_loop: while (true) { + var tok = tokenizer.next(); + switch (tok.id) { + .nl, .eof => break tok.start, + .whitespace => need_ws = pp.token_buf.items.len != 0, + .hash => { + if (tok.id != .whitespace and need_ws) { + need_ws = false; + try pp.token_buf.append(.{ .id = .macro_ws, .source = .generated }); + } + const param = tokenizer.nextNoWS(); + blk: { + if (var_args and param.id == .keyword_va_args) { + tok.id = .stringify_va_args; + try pp.token_buf.append(tok); + continue :tok_loop; + } + if (!param.id.isMacroIdentifier()) break :blk; + const s = pp.tokSlice(param); + if (mem.eql(u8, s, gnu_var_args)) { + tok.id = .stringify_va_args; + try pp.token_buf.append(tok); + continue :tok_loop; + } + for (params.items, 0..) |p, i| { + if (mem.eql(u8, p, s)) { + tok.id = .stringify_param; + tok.end = @intCast(i); + try pp.token_buf.append(tok); + continue :tok_loop; + } + } + } + try pp.err(param, .hash_not_followed_param); + return skipToNl(tokenizer); + }, + .hash_hash => { + need_ws = false; + // if ## appears at the beginning, the token buf is still empty + // in this case, error out + if (pp.token_buf.items.len == 0) { + try pp.err(tok, .hash_hash_at_start); + return skipToNl(tokenizer); + } + const saved_tokenizer = tokenizer.*; + const next = tokenizer.nextNoWS(); + if (next.id == .nl or next.id == .eof) { + try pp.err(tok, .hash_hash_at_end); + return; + } + tokenizer.* = saved_tokenizer; + // convert the previous token to .macro_param_no_expand if it was .macro_param + if (pp.token_buf.items[pp.token_buf.items.len - 1].id == .macro_param) { + pp.token_buf.items[pp.token_buf.items.len - 1].id = .macro_param_no_expand; + } + try pp.token_buf.append(tok); + }, + else => { + if (tok.id != .whitespace and need_ws) { + need_ws = false; + try pp.token_buf.append(.{ .id = .macro_ws, .source = .generated }); + } + if (var_args and tok.id == .keyword_va_args) { + // do nothing + } else if (tok.id.isMacroIdentifier()) { + tok.id.simplifyMacroKeyword(); + const s = pp.tokSlice(tok); + if (mem.eql(u8, gnu_var_args, s)) { + tok.id = .keyword_va_args; + } else for (params.items, 0..) |param, i| { + if (mem.eql(u8, param, s)) { + // NOTE: it doesn't matter to assign .macro_param_no_expand + // here in case a ## was the previous token, because + // ## processing will eat this token with the same semantics + tok.id = .macro_param; + tok.end = @intCast(i); + break; + } + } + } + try pp.token_buf.append(tok); + }, + } + } else unreachable; + + const param_list = try pp.arena.allocator().dupe([]const u8, params.items); + const token_list = try pp.arena.allocator().dupe(RawToken, pp.token_buf.items); + try pp.defineMacro(macro_name, .{ + .is_func = true, + .params = param_list, + .var_args = var_args or gnu_var_args.len != 0, + .tokens = token_list, + .loc = .{ + .id = macro_name.source, + .byte_offset = start_index, + .line = end_index, + }, + }); +} + +/// Handle an #embed directive +fn embed(pp: *Preprocessor, tokenizer: *Tokenizer) MacroError!void { + const first = tokenizer.nextNoWS(); + const filename_tok = pp.findIncludeFilenameToken(first, tokenizer, .expect_nl_eof) catch |er| switch (er) { + error.InvalidInclude => return, + else => |e| return e, + }; + + // Check for empty filename. + const tok_slice = pp.expandedSlice(filename_tok); + if (tok_slice.len < 3) { + try pp.err(first, .empty_filename); + return; + } + const filename = tok_slice[1 .. tok_slice.len - 1]; + const include_type: Compilation.IncludeType = switch (filename_tok.id) { + .string_literal => .quotes, + .macro_string => .angle_brackets, + else => unreachable, + }; + + const embed_bytes = (try pp.comp.findEmbed(filename, first.source, include_type)) orelse return pp.fatal(first, "'{s}' not found", .{filename}); + defer pp.comp.gpa.free(embed_bytes); + + if (embed_bytes.len == 0) return; + + try pp.tokens.ensureUnusedCapacity(pp.comp.gpa, 2 * embed_bytes.len - 1); // N bytes and N-1 commas + + // TODO: We currently only support systems with CHAR_BIT == 8 + // If the target's CHAR_BIT is not 8, we need to write out correctly-sized embed_bytes + // and correctly account for the target's endianness + const writer = pp.comp.generated_buf.writer(); + + { + const byte = embed_bytes[0]; + const start = pp.comp.generated_buf.items.len; + try writer.print("{d}", .{byte}); + pp.tokens.appendAssumeCapacity(try pp.makeGeneratedToken(start, .embed_byte, filename_tok)); + } + + for (embed_bytes[1..]) |byte| { + const start = pp.comp.generated_buf.items.len; + try writer.print(",{d}", .{byte}); + pp.tokens.appendAssumeCapacity(.{ .id = .comma, .loc = .{ .id = .generated, .byte_offset = @intCast(start) } }); + pp.tokens.appendAssumeCapacity(try pp.makeGeneratedToken(start + 1, .embed_byte, filename_tok)); + } + try pp.comp.generated_buf.append('\n'); +} + +// Handle a #include directive. +fn include(pp: *Preprocessor, tokenizer: *Tokenizer, which: Compilation.WhichInclude) MacroError!void { + const first = tokenizer.nextNoWS(); + const new_source = findIncludeSource(pp, tokenizer, first, which) catch |er| switch (er) { + error.InvalidInclude => return, + else => |e| return e, + }; + + // Prevent stack overflow + pp.include_depth += 1; + defer pp.include_depth -= 1; + if (pp.include_depth > max_include_depth) { + try pp.comp.diag.add(.{ + .tag = .too_many_includes, + .loc = .{ .id = first.source, .byte_offset = first.start, .line = first.line }, + }, &.{}); + return error.StopPreprocessing; + } + + if (pp.include_guards.get(new_source.id)) |guard| { + if (pp.defines.contains(guard)) return; + } + + if (pp.verbose) { + pp.verboseLog(first, "include file {s}", .{new_source.path}); + } + + _ = pp.preprocessExtra(new_source) catch |er| switch (er) { + error.StopPreprocessing => {}, + else => |e| return e, + }; +} + +/// tokens that are part of a pragma directive can happen in 3 ways: +/// 1. directly in the text via `#pragma ...` +/// 2. Via a string literal argument to `_Pragma` +/// 3. Via a stringified macro argument which is used as an argument to `_Pragma` +/// operator_loc: Location of `_Pragma`; null if this is from #pragma +/// arg_locs: expansion locations of the argument to _Pragma. empty if #pragma or a raw string literal was used +fn makePragmaToken(pp: *Preprocessor, raw: RawToken, operator_loc: ?Source.Location, arg_locs: []const Source.Location) !Token { + var tok = tokFromRaw(raw); + if (operator_loc) |loc| { + try tok.addExpansionLocation(pp.gpa, &.{loc}); + } + try tok.addExpansionLocation(pp.gpa, arg_locs); + return tok; +} + +/// Handle a pragma directive +fn pragma(pp: *Preprocessor, tokenizer: *Tokenizer, pragma_tok: RawToken, operator_loc: ?Source.Location, arg_locs: []const Source.Location) !void { + const name_tok = tokenizer.nextNoWS(); + if (name_tok.id == .nl or name_tok.id == .eof) return; + + const name = pp.tokSlice(name_tok); + try pp.tokens.append(pp.gpa, try pp.makePragmaToken(pragma_tok, operator_loc, arg_locs)); + const pragma_start: u32 = @intCast(pp.tokens.len); + + const pragma_name_tok = try pp.makePragmaToken(name_tok, operator_loc, arg_locs); + try pp.tokens.append(pp.gpa, pragma_name_tok); + while (true) { + const next_tok = tokenizer.next(); + if (next_tok.id == .whitespace) continue; + if (next_tok.id == .eof) { + try pp.tokens.append(pp.gpa, .{ + .id = .nl, + .loc = .{ .id = .generated }, + }); + break; + } + try pp.tokens.append(pp.gpa, try pp.makePragmaToken(next_tok, operator_loc, arg_locs)); + if (next_tok.id == .nl) break; + } + if (pp.comp.getPragma(name)) |prag| unknown: { + return prag.preprocessorCB(pp, pragma_start) catch |er| switch (er) { + error.UnknownPragma => break :unknown, + else => |e| return e, + }; + } + return pp.comp.diag.add(.{ + .tag = .unknown_pragma, + .loc = pragma_name_tok.loc, + }, pragma_name_tok.expansionSlice()); +} + +fn findIncludeFilenameToken( + pp: *Preprocessor, + first_token: RawToken, + tokenizer: *Tokenizer, + trailing_token_behavior: enum { ignore_trailing_tokens, expect_nl_eof }, +) !Token { + const start = pp.tokens.len; + defer pp.tokens.len = start; + var first = first_token; + + if (first.id == .angle_bracket_left) to_end: { + // The tokenizer does not handle include strings so do it here. + while (tokenizer.index < tokenizer.buf.len) : (tokenizer.index += 1) { + switch (tokenizer.buf[tokenizer.index]) { + '>' => { + tokenizer.index += 1; + first.end = tokenizer.index; + first.id = .macro_string; + break :to_end; + }, + '\n' => break, + else => {}, + } + } + try pp.comp.diag.add(.{ + .tag = .header_str_closing, + .loc = .{ .id = first.source, .byte_offset = tokenizer.index, .line = first.line }, + }, &.{}); + try pp.err(first, .header_str_match); + } + // Try to expand if the argument is a macro. + try pp.expandMacro(tokenizer, first); + + // Check that we actually got a string. + const filename_tok = pp.tokens.get(start); + switch (filename_tok.id) { + .string_literal, .macro_string => {}, + else => { + try pp.err(first, .expected_filename); + try pp.expectNl(tokenizer); + return error.InvalidInclude; + }, + } + switch (trailing_token_behavior) { + .expect_nl_eof => { + // Error on extra tokens. + const nl = tokenizer.nextNoWS(); + if ((nl.id != .nl and nl.id != .eof) or pp.tokens.len > start + 1) { + skipToNl(tokenizer); + try pp.err(first, .extra_tokens_directive_end); + } + }, + .ignore_trailing_tokens => {}, + } + return filename_tok; +} + +fn findIncludeSource(pp: *Preprocessor, tokenizer: *Tokenizer, first: RawToken, which: Compilation.WhichInclude) !Source { + const filename_tok = try pp.findIncludeFilenameToken(first, tokenizer, .expect_nl_eof); + + // Check for empty filename. + const tok_slice = pp.expandedSlice(filename_tok); + if (tok_slice.len < 3) { + try pp.err(first, .empty_filename); + return error.InvalidInclude; + } + + // Find the file. + const filename = tok_slice[1 .. tok_slice.len - 1]; + const include_type: Compilation.IncludeType = switch (filename_tok.id) { + .string_literal => .quotes, + .macro_string => .angle_brackets, + else => unreachable, + }; + + return (try pp.comp.findInclude(filename, first.source, include_type, which)) orelse + pp.fatal(first, "'{s}' not found", .{filename}); +} + +/// Pretty print tokens and try to preserve whitespace. +pub fn prettyPrintTokens(pp: *Preprocessor, w: anytype) !void { + var i: u32 = 0; + while (true) : (i += 1) { + var cur: Token = pp.tokens.get(i); + switch (cur.id) { + .eof => { + if (pp.tokens.len > 1 and pp.tokens.items(.id)[i - 1] != .nl) try w.writeByte('\n'); + break; + }, + .nl => try w.writeAll("\n"), + .keyword_pragma => { + const pragma_name = pp.expandedSlice(pp.tokens.get(i + 1)); + const end_idx = mem.indexOfScalarPos(Token.Id, pp.tokens.items(.id), i, .nl) orelse i + 1; + const pragma_len = @as(u32, @intCast(end_idx)) - i; + + if (pp.comp.getPragma(pragma_name)) |prag| { + if (!prag.shouldPreserveTokens(pp, i + 1)) { + i += pragma_len; + cur = pp.tokens.get(i); + continue; + } + } + try w.writeAll("#pragma"); + i += 1; + while (true) : (i += 1) { + cur = pp.tokens.get(i); + if (cur.id == .nl) { + try w.writeByte('\n'); + break; + } + try w.writeByte(' '); + const slice = pp.expandedSlice(cur); + try w.writeAll(slice); + } + }, + .whitespace => { + var slice = pp.expandedSlice(cur); + while (mem.indexOfScalar(u8, slice, '\n')) |some| { + try w.writeByte('\n'); + slice = slice[some + 1 ..]; + } + for (slice) |_| try w.writeByte(' '); + }, + else => { + const slice = pp.expandedSlice(cur); + try w.writeAll(slice); + }, + } + } +} + +test "Preserve pragma tokens sometimes" { + const allocator = std.testing.allocator; + const Test = struct { + fn runPreprocessor(source_text: []const u8) ![]const u8 { + var buf = std.ArrayList(u8).init(allocator); + defer buf.deinit(); + + var comp = Compilation.init(allocator); + defer comp.deinit(); + + try comp.addDefaultPragmaHandlers(); + + var pp = Preprocessor.init(&comp); + defer pp.deinit(); + + pp.preserve_whitespace = true; + + const test_runner_macros = try comp.addSourceFromBuffer("", source_text); + const eof = try pp.preprocess(test_runner_macros); + try pp.tokens.append(pp.gpa, eof); + try pp.prettyPrintTokens(buf.writer()); + return allocator.dupe(u8, buf.items); + } + + fn check(source_text: []const u8, expected: []const u8) !void { + const output = try runPreprocessor(source_text); + defer allocator.free(output); + + try std.testing.expectEqualStrings(expected, output); + } + }; + const preserve_gcc_diagnostic = + \\#pragma GCC diagnostic error "-Wnewline-eof" + \\#pragma GCC warning error "-Wnewline-eof" + \\int x; + \\#pragma GCC ignored error "-Wnewline-eof" + \\ + ; + try Test.check(preserve_gcc_diagnostic, preserve_gcc_diagnostic); + + const omit_once = + \\#pragma once + \\int x; + \\#pragma once + \\ + ; + try Test.check(omit_once, "int x;\n"); + + const omit_poison = + \\#pragma GCC poison foobar + \\ + ; + try Test.check(omit_poison, ""); +} + +test "destringify" { + const allocator = std.testing.allocator; + const Test = struct { + fn testDestringify(pp: *Preprocessor, stringified: []const u8, destringified: []const u8) !void { + pp.char_buf.clearRetainingCapacity(); + try pp.char_buf.ensureUnusedCapacity(stringified.len); + pp.destringify(stringified); + try std.testing.expectEqualStrings(destringified, pp.char_buf.items); + } + }; + var comp = Compilation.init(allocator); + defer comp.deinit(); + var pp = Preprocessor.init(&comp); + defer pp.deinit(); + + try Test.testDestringify(&pp, "hello\tworld\n", "hello\tworld\n"); + try Test.testDestringify(&pp, + \\ \"FOO BAR BAZ\" + , + \\ "FOO BAR BAZ" + ); + try Test.testDestringify(&pp, + \\ \\t\\n + \\ + , + \\ \t\n + \\ + ); +} + +test "Include guards" { + const Test = struct { + /// This is here so that when #elifdef / #elifndef are added we don't forget + /// to test that they don't accidentally break include guard detection + fn pairsWithIfndef(tok_id: RawToken.Id) bool { + return switch (tok_id) { + .keyword_elif, + .keyword_elifdef, + .keyword_elifndef, + .keyword_else, + => true, + + .keyword_include, + .keyword_include_next, + .keyword_embed, + .keyword_define, + .keyword_defined, + .keyword_undef, + .keyword_ifdef, + .keyword_ifndef, + .keyword_error, + .keyword_warning, + .keyword_pragma, + .keyword_line, + .keyword_endif, + => false, + else => unreachable, + }; + } + + fn skippable(tok_id: RawToken.Id) bool { + return switch (tok_id) { + .keyword_defined, .keyword_va_args, .keyword_endif => true, + else => false, + }; + } + + fn testIncludeGuard(allocator: std.mem.Allocator, comptime template: []const u8, tok_id: RawToken.Id, expected_guards: u32) !void { + var comp = Compilation.init(allocator); + defer comp.deinit(); + var pp = Preprocessor.init(&comp); + defer pp.deinit(); + + const path = try std.fs.path.join(allocator, &.{ ".", "bar.h" }); + defer allocator.free(path); + + _ = try comp.addSourceFromBuffer(path, "int bar = 5;\n"); + + var buf = std.ArrayList(u8).init(allocator); + defer buf.deinit(); + + var writer = buf.writer(); + switch (tok_id) { + .keyword_include, .keyword_include_next => try writer.print(template, .{ tok_id.lexeme().?, " \"bar.h\"" }), + .keyword_define, .keyword_undef => try writer.print(template, .{ tok_id.lexeme().?, " BAR" }), + .keyword_ifndef, + .keyword_ifdef, + .keyword_elifdef, + .keyword_elifndef, + => try writer.print(template, .{ tok_id.lexeme().?, " BAR\n#endif" }), + else => try writer.print(template, .{ tok_id.lexeme().?, "" }), + } + const source = try comp.addSourceFromBuffer("test.h", buf.items); + _ = try pp.preprocess(source); + + try std.testing.expectEqual(expected_guards, pp.include_guards.count()); + } + }; + const tags = std.meta.tags(RawToken.Id); + for (tags) |tag| { + if (Test.skippable(tag)) continue; + var copy = tag; + copy.simplifyMacroKeyword(); + if (copy != tag or tag == .keyword_else) { + const inside_ifndef_template = + \\//Leading comment (should be ignored) + \\ + \\#ifndef FOO + \\#{s}{s} + \\#endif + ; + const expected_guards: u32 = if (Test.pairsWithIfndef(tag)) 0 else 1; + try Test.testIncludeGuard(std.testing.allocator, inside_ifndef_template, tag, expected_guards); + + const outside_ifndef_template = + \\#ifndef FOO + \\#endif + \\#{s}{s} + ; + try Test.testIncludeGuard(std.testing.allocator, outside_ifndef_template, tag, 0); + } + } +} diff --git a/deps/aro/Source.zig b/deps/aro/Source.zig new file mode 100644 index 000000000000..4c95972aa1fe --- /dev/null +++ b/deps/aro/Source.zig @@ -0,0 +1,125 @@ +const std = @import("std"); +const Source = @This(); + +pub const Id = enum(u32) { + unused = 0, + generated = 1, + _, +}; + +pub const Location = struct { + id: Id = .unused, + byte_offset: u32 = 0, + line: u32 = 0, + + pub fn eql(a: Location, b: Location) bool { + return a.id == b.id and a.byte_offset == b.byte_offset and a.line == b.line; + } +}; + +path: []const u8, +buf: []const u8, +id: Id, +/// each entry represents a byte position within `buf` where a backslash+newline was deleted +/// from the original raw buffer. The same position can appear multiple times if multiple +/// consecutive splices happened. Guaranteed to be non-decreasing +splice_locs: []const u32, + +/// Todo: binary search instead of scanning entire `splice_locs`. +pub fn numSplicesBefore(source: Source, byte_offset: u32) u32 { + for (source.splice_locs, 0..) |splice_offset, i| { + if (splice_offset > byte_offset) return @intCast(i); + } + return @intCast(source.splice_locs.len); +} + +/// Returns the actual line number (before newline splicing) of a Location +/// This corresponds to what the user would actually see in their text editor +pub fn physicalLine(source: Source, loc: Location) u32 { + return loc.line + source.numSplicesBefore(loc.byte_offset); +} + +const LineCol = struct { line: []const u8, line_no: u32, col: u32, width: u32, end_with_splice: bool }; + +pub fn lineCol(source: Source, loc: Location) LineCol { + var start: usize = 0; + // find the start of the line which is either a newline or a splice + if (std.mem.lastIndexOfScalar(u8, source.buf[0..loc.byte_offset], '\n')) |some| start = some + 1; + const splice_index: u32 = for (source.splice_locs, 0..) |splice_offset, i| { + if (splice_offset > start) { + if (splice_offset < loc.byte_offset) { + start = splice_offset; + break @as(u32, @intCast(i)) + 1; + } + break @intCast(i); + } + } else @intCast(source.splice_locs.len); + var i: usize = start; + var col: u32 = 1; + var width: u32 = 0; + + while (i < loc.byte_offset) : (col += 1) { // TODO this is still incorrect, but better + const len = std.unicode.utf8ByteSequenceLength(source.buf[i]) catch unreachable; + const cp = std.unicode.utf8Decode(source.buf[i..][0..len]) catch unreachable; + width += codepointWidth(cp); + i += len; + } + + // find the end of the line which is either a newline, EOF or a splice + var nl = source.buf.len; + var end_with_splice = false; + if (std.mem.indexOfScalar(u8, source.buf[start..], '\n')) |some| nl = some + start; + if (source.splice_locs.len > splice_index and nl > source.splice_locs[splice_index] and source.splice_locs[splice_index] > start) { + end_with_splice = true; + nl = source.splice_locs[splice_index]; + } + return .{ + .line = source.buf[start..nl], + .line_no = loc.line + splice_index, + .col = col, + .width = width, + .end_with_splice = end_with_splice, + }; +} + +fn codepointWidth(cp: u32) u32 { + return switch (cp) { + 0x1100...0x115F, + 0x2329, + 0x232A, + 0x2E80...0x303F, + 0x3040...0x3247, + 0x3250...0x4DBF, + 0x4E00...0xA4C6, + 0xA960...0xA97C, + 0xAC00...0xD7A3, + 0xF900...0xFAFF, + 0xFE10...0xFE19, + 0xFE30...0xFE6B, + 0xFF01...0xFF60, + 0xFFE0...0xFFE6, + 0x1B000...0x1B001, + 0x1F200...0x1F251, + 0x20000...0x3FFFD, + 0x1F300...0x1F5FF, + 0x1F900...0x1F9FF, + => 2, + else => 1, + }; +} + +/// Returns the first offset, if any, in buf where an invalid utf8 sequence +/// is found. Code adapted from std.unicode.utf8ValidateSlice +pub fn offsetOfInvalidUtf8(self: Source) ?u32 { + const buf = self.buf; + std.debug.assert(buf.len <= std.math.maxInt(u32)); + var i: u32 = 0; + while (i < buf.len) { + if (std.unicode.utf8ByteSequenceLength(buf[i])) |cp_len| { + if (i + cp_len > buf.len) return i; + if (std.meta.isError(std.unicode.utf8Decode(buf[i .. i + cp_len]))) return i; + i += cp_len; + } else |_| return i; + } + return null; +} diff --git a/deps/aro/StringInterner.zig b/deps/aro/StringInterner.zig new file mode 100644 index 000000000000..b0ae2b347a31 --- /dev/null +++ b/deps/aro/StringInterner.zig @@ -0,0 +1,78 @@ +const std = @import("std"); +const mem = std.mem; + +const StringInterner = @This(); + +const StringToIdMap = std.StringHashMapUnmanaged(StringId); + +pub const StringId = enum(u32) { + empty, + _, +}; + +pub const TypeMapper = struct { + const LookupSpeed = enum { + fast, + slow, + }; + + data: union(LookupSpeed) { + fast: []const []const u8, + slow: *const StringToIdMap, + }, + + pub fn lookup(self: TypeMapper, string_id: StringInterner.StringId) []const u8 { + if (string_id == .empty) return ""; + switch (self.data) { + .fast => |arr| return arr[@intFromEnum(string_id)], + .slow => |map| { + var it = map.iterator(); + while (it.next()) |entry| { + if (entry.value_ptr.* == string_id) return entry.key_ptr.*; + } + unreachable; + }, + } + } + + pub fn deinit(self: TypeMapper, allocator: mem.Allocator) void { + switch (self.data) { + .slow => {}, + .fast => |arr| allocator.free(arr), + } + } +}; + +string_table: StringToIdMap = .{}, +next_id: StringId = @enumFromInt(@intFromEnum(StringId.empty) + 1), + +pub fn deinit(self: *StringInterner, allocator: mem.Allocator) void { + self.string_table.deinit(allocator); +} + +pub fn intern(self: *StringInterner, allocator: mem.Allocator, str: []const u8) !StringId { + if (str.len == 0) return .empty; + + const gop = try self.string_table.getOrPut(allocator, str); + if (gop.found_existing) return gop.value_ptr.*; + + defer self.next_id = @enumFromInt(@intFromEnum(self.next_id) + 1); + gop.value_ptr.* = self.next_id; + return self.next_id; +} + +/// deinit for the returned TypeMapper is a no-op and does not need to be called +pub fn getSlowTypeMapper(self: *const StringInterner) TypeMapper { + return TypeMapper{ .data = .{ .slow = &self.string_table } }; +} + +/// Caller must call `deinit` on the returned TypeMapper +pub fn getFastTypeMapper(self: *const StringInterner, allocator: mem.Allocator) !TypeMapper { + var strings = try allocator.alloc([]const u8, @intFromEnum(self.next_id)); + var it = self.string_table.iterator(); + strings[0] = ""; + while (it.next()) |entry| { + strings[@intFromEnum(entry.value_ptr.*)] = entry.key_ptr.*; + } + return TypeMapper{ .data = .{ .fast = strings } }; +} diff --git a/deps/aro/SymbolStack.zig b/deps/aro/SymbolStack.zig new file mode 100644 index 000000000000..dc32c14acbc8 --- /dev/null +++ b/deps/aro/SymbolStack.zig @@ -0,0 +1,375 @@ +const std = @import("std"); +const mem = std.mem; +const Allocator = mem.Allocator; +const assert = std.debug.assert; +const Tree = @import("Tree.zig"); +const Token = Tree.Token; +const TokenIndex = Tree.TokenIndex; +const NodeIndex = Tree.NodeIndex; +const Type = @import("Type.zig"); +const Parser = @import("Parser.zig"); +const Value = @import("Value.zig"); +const StringId = @import("StringInterner.zig").StringId; + +const SymbolStack = @This(); + +pub const Symbol = struct { + name: StringId, + ty: Type, + tok: TokenIndex, + node: NodeIndex = .none, + kind: Kind, + val: Value, +}; + +pub const Kind = enum { + typedef, + @"struct", + @"union", + @"enum", + decl, + def, + enumeration, + constexpr, +}; + +syms: std.MultiArrayList(Symbol) = .{}, +scopes: std.ArrayListUnmanaged(u32) = .{}, + +pub fn deinit(s: *SymbolStack, gpa: Allocator) void { + s.syms.deinit(gpa); + s.scopes.deinit(gpa); + s.* = undefined; +} + +pub fn scopeEnd(s: SymbolStack) u32 { + if (s.scopes.items.len == 0) return 0; + return s.scopes.items[s.scopes.items.len - 1]; +} + +pub fn pushScope(s: *SymbolStack, p: *Parser) !void { + try s.scopes.append(p.pp.comp.gpa, @intCast(s.syms.len)); +} + +pub fn popScope(s: *SymbolStack) void { + s.syms.len = s.scopes.pop(); +} + +pub fn findTypedef(s: *SymbolStack, p: *Parser, name: StringId, name_tok: TokenIndex, no_type_yet: bool) !?Symbol { + const kinds = s.syms.items(.kind); + const names = s.syms.items(.name); + var i = s.syms.len; + while (i > 0) { + i -= 1; + switch (kinds[i]) { + .typedef => if (names[i] == name) return s.syms.get(i), + .@"struct" => if (names[i] == name) { + if (no_type_yet) return null; + try p.errStr(.must_use_struct, name_tok, p.tokSlice(name_tok)); + return s.syms.get(i); + }, + .@"union" => if (names[i] == name) { + if (no_type_yet) return null; + try p.errStr(.must_use_union, name_tok, p.tokSlice(name_tok)); + return s.syms.get(i); + }, + .@"enum" => if (names[i] == name) { + if (no_type_yet) return null; + try p.errStr(.must_use_enum, name_tok, p.tokSlice(name_tok)); + return s.syms.get(i); + }, + .def, .decl, .constexpr => if (names[i] == name) return null, + else => {}, + } + } + return null; +} + +pub fn findSymbol(s: *SymbolStack, name: StringId) ?Symbol { + const kinds = s.syms.items(.kind); + const names = s.syms.items(.name); + var i = s.syms.len; + while (i > 0) { + i -= 1; + switch (kinds[i]) { + .def, .decl, .enumeration, .constexpr => if (names[i] == name) return s.syms.get(i), + else => {}, + } + } + return null; +} + +pub fn findTag( + s: *SymbolStack, + p: *Parser, + name: StringId, + kind: Token.Id, + name_tok: TokenIndex, + next_tok_id: Token.Id, +) !?Symbol { + const kinds = s.syms.items(.kind); + const names = s.syms.items(.name); + // `tag Name;` should always result in a new type if in a new scope. + const end = if (next_tok_id == .semicolon) s.scopeEnd() else 0; + var i = s.syms.len; + while (i > end) { + i -= 1; + switch (kinds[i]) { + .@"enum" => if (names[i] == name) { + if (kind == .keyword_enum) return s.syms.get(i); + break; + }, + .@"struct" => if (names[i] == name) { + if (kind == .keyword_struct) return s.syms.get(i); + break; + }, + .@"union" => if (names[i] == name) { + if (kind == .keyword_union) return s.syms.get(i); + break; + }, + else => {}, + } + } else return null; + + if (i < s.scopeEnd()) return null; + try p.errStr(.wrong_tag, name_tok, p.tokSlice(name_tok)); + try p.errTok(.previous_definition, s.syms.items(.tok)[i]); + return null; +} + +pub fn defineTypedef( + s: *SymbolStack, + p: *Parser, + name: StringId, + ty: Type, + tok: TokenIndex, + node: NodeIndex, +) !void { + const kinds = s.syms.items(.kind); + const names = s.syms.items(.name); + const end = s.scopeEnd(); + var i = s.syms.len; + while (i > end) { + i -= 1; + switch (kinds[i]) { + .typedef => if (names[i] == name) { + const prev_ty = s.syms.items(.ty)[i]; + if (ty.eql(prev_ty, p.pp.comp, true)) break; + try p.errStr(.redefinition_of_typedef, tok, try p.typePairStrExtra(ty, " vs ", prev_ty)); + const previous_tok = s.syms.items(.tok)[i]; + if (previous_tok != 0) try p.errTok(.previous_definition, previous_tok); + break; + }, + else => {}, + } + } + try s.syms.append(p.pp.comp.gpa, .{ + .kind = .typedef, + .name = name, + .tok = tok, + .ty = ty, + .node = node, + .val = .{}, + }); +} + +pub fn defineSymbol( + s: *SymbolStack, + p: *Parser, + name: StringId, + ty: Type, + tok: TokenIndex, + node: NodeIndex, + val: Value, + constexpr: bool, +) !void { + const kinds = s.syms.items(.kind); + const names = s.syms.items(.name); + const end = s.scopeEnd(); + var i = s.syms.len; + while (i > end) { + i -= 1; + switch (kinds[i]) { + .enumeration => if (names[i] == name) { + try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); + try p.errTok(.previous_definition, s.syms.items(.tok)[i]); + break; + }, + .decl => if (names[i] == name) { + const prev_ty = s.syms.items(.ty)[i]; + if (!ty.eql(prev_ty, p.pp.comp, true)) { // TODO adjusted equality check + try p.errStr(.redefinition_incompatible, tok, p.tokSlice(tok)); + try p.errTok(.previous_definition, s.syms.items(.tok)[i]); + } + break; + }, + .def, .constexpr => if (names[i] == name) { + try p.errStr(.redefinition, tok, p.tokSlice(tok)); + try p.errTok(.previous_definition, s.syms.items(.tok)[i]); + break; + }, + else => {}, + } + } + try s.syms.append(p.pp.comp.gpa, .{ + .kind = if (constexpr) .constexpr else .def, + .name = name, + .tok = tok, + .ty = ty, + .node = node, + .val = val, + }); +} + +pub fn declareSymbol( + s: *SymbolStack, + p: *Parser, + name: StringId, + ty: Type, + tok: TokenIndex, + node: NodeIndex, +) !void { + const kinds = s.syms.items(.kind); + const names = s.syms.items(.name); + const end = s.scopeEnd(); + var i = s.syms.len; + while (i > end) { + i -= 1; + switch (kinds[i]) { + .enumeration => if (names[i] == name) { + try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); + try p.errTok(.previous_definition, s.syms.items(.tok)[i]); + break; + }, + .decl => if (names[i] == name) { + const prev_ty = s.syms.items(.ty)[i]; + if (!ty.eql(prev_ty, p.pp.comp, true)) { // TODO adjusted equality check + try p.errStr(.redefinition_incompatible, tok, p.tokSlice(tok)); + try p.errTok(.previous_definition, s.syms.items(.tok)[i]); + } + break; + }, + .def, .constexpr => if (names[i] == name) { + const prev_ty = s.syms.items(.ty)[i]; + if (!ty.eql(prev_ty, p.pp.comp, true)) { // TODO adjusted equality check + try p.errStr(.redefinition_incompatible, tok, p.tokSlice(tok)); + try p.errTok(.previous_definition, s.syms.items(.tok)[i]); + break; + } + return; + }, + else => {}, + } + } + try s.syms.append(p.pp.comp.gpa, .{ + .kind = .decl, + .name = name, + .tok = tok, + .ty = ty, + .node = node, + .val = .{}, + }); +} + +pub fn defineParam(s: *SymbolStack, p: *Parser, name: StringId, ty: Type, tok: TokenIndex) !void { + const kinds = s.syms.items(.kind); + const names = s.syms.items(.name); + const end = s.scopeEnd(); + var i = s.syms.len; + while (i > end) { + i -= 1; + switch (kinds[i]) { + .enumeration, .decl, .def, .constexpr => if (names[i] == name) { + try p.errStr(.redefinition_of_parameter, tok, p.tokSlice(tok)); + try p.errTok(.previous_definition, s.syms.items(.tok)[i]); + break; + }, + else => {}, + } + } + if (ty.is(.fp16) and !p.comp.hasHalfPrecisionFloatABI()) { + try p.errStr(.suggest_pointer_for_invalid_fp16, tok, "parameters"); + } + try s.syms.append(p.pp.comp.gpa, .{ + .kind = .def, + .name = name, + .tok = tok, + .ty = ty, + .val = .{}, + }); +} + +pub fn defineTag( + s: *SymbolStack, + p: *Parser, + name: StringId, + kind: Token.Id, + tok: TokenIndex, +) !?Symbol { + const kinds = s.syms.items(.kind); + const names = s.syms.items(.name); + const end = s.scopeEnd(); + var i = s.syms.len; + while (i > end) { + i -= 1; + switch (kinds[i]) { + .@"enum" => if (names[i] == name) { + if (kind == .keyword_enum) return s.syms.get(i); + try p.errStr(.wrong_tag, tok, p.tokSlice(tok)); + try p.errTok(.previous_definition, s.syms.items(.tok)[i]); + return null; + }, + .@"struct" => if (names[i] == name) { + if (kind == .keyword_struct) return s.syms.get(i); + try p.errStr(.wrong_tag, tok, p.tokSlice(tok)); + try p.errTok(.previous_definition, s.syms.items(.tok)[i]); + return null; + }, + .@"union" => if (names[i] == name) { + if (kind == .keyword_union) return s.syms.get(i); + try p.errStr(.wrong_tag, tok, p.tokSlice(tok)); + try p.errTok(.previous_definition, s.syms.items(.tok)[i]); + return null; + }, + else => {}, + } + } + return null; +} + +pub fn defineEnumeration( + s: *SymbolStack, + p: *Parser, + name: StringId, + ty: Type, + tok: TokenIndex, + val: Value, +) !void { + const kinds = s.syms.items(.kind); + const names = s.syms.items(.name); + const end = s.scopeEnd(); + var i = s.syms.len; + while (i > end) { + i -= 1; + switch (kinds[i]) { + .enumeration => if (names[i] == name) { + try p.errStr(.redefinition, tok, p.tokSlice(tok)); + try p.errTok(.previous_definition, s.syms.items(.tok)[i]); + return; + }, + .decl, .def, .constexpr => if (names[i] == name) { + try p.errStr(.redefinition_different_sym, tok, p.tokSlice(tok)); + try p.errTok(.previous_definition, s.syms.items(.tok)[i]); + return; + }, + else => {}, + } + } + try s.syms.append(p.pp.comp.gpa, .{ + .kind = .enumeration, + .name = name, + .tok = tok, + .ty = ty, + .val = val, + }); +} diff --git a/deps/aro/Tokenizer.zig b/deps/aro/Tokenizer.zig new file mode 100644 index 000000000000..28de3c2c5679 --- /dev/null +++ b/deps/aro/Tokenizer.zig @@ -0,0 +1,2140 @@ +const std = @import("std"); +const assert = std.debug.assert; +const Compilation = @import("Compilation.zig"); +const Source = @import("Source.zig"); +const LangOpts = @import("LangOpts.zig"); +const CharInfo = @import("CharInfo.zig"); +const unicode = @import("unicode.zig"); + +const Tokenizer = @This(); + +pub const Token = struct { + id: Id, + source: Source.Id, + start: u32 = 0, + end: u32 = 0, + line: u32 = 0, + + pub const Id = enum(u8) { + invalid, + nl, + whitespace, + eof, + /// identifier containing solely basic character set characters + identifier, + /// identifier with at least one extended character + extended_identifier, + + // string literals with prefixes + string_literal, + string_literal_utf_16, + string_literal_utf_8, + string_literal_utf_32, + string_literal_wide, + + // only generated by preprocessor + macro_string, + + // char literals with prefixes + char_literal, + char_literal_utf_8, + char_literal_utf_16, + char_literal_utf_32, + char_literal_wide, + + /// Integer literal tokens generated by preprocessor. + one, + zero, + + bang, + bang_equal, + pipe, + pipe_pipe, + pipe_equal, + equal, + equal_equal, + l_paren, + r_paren, + l_brace, + r_brace, + l_bracket, + r_bracket, + period, + ellipsis, + caret, + caret_equal, + plus, + plus_plus, + plus_equal, + minus, + minus_minus, + minus_equal, + asterisk, + asterisk_equal, + percent, + percent_equal, + arrow, + colon, + colon_colon, + semicolon, + slash, + slash_equal, + comma, + ampersand, + ampersand_ampersand, + ampersand_equal, + question_mark, + angle_bracket_left, + angle_bracket_left_equal, + angle_bracket_angle_bracket_left, + angle_bracket_angle_bracket_left_equal, + angle_bracket_right, + angle_bracket_right_equal, + angle_bracket_angle_bracket_right, + angle_bracket_angle_bracket_right_equal, + tilde, + hash, + hash_hash, + + /// Special token to speed up preprocessing, `loc.end` will be an index to the param list. + macro_param, + /// Special token to signal that the argument must be replaced without expansion (e.g. in concatenation) + macro_param_no_expand, + /// Special token to speed up preprocessing, `loc.end` will be an index to the param list. + stringify_param, + /// Same as stringify_param, but for var args + stringify_va_args, + /// Special macro whitespace, always equal to a single space + macro_ws, + /// Special token for implementing __has_attribute + macro_param_has_attribute, + /// Special token for implementing __has_warning + macro_param_has_warning, + /// Special token for implementing __has_feature + macro_param_has_feature, + /// Special token for implementing __has_extension + macro_param_has_extension, + /// Special token for implementing __has_builtin + macro_param_has_builtin, + /// Special token for implementing __has_include + macro_param_has_include, + /// Special token for implementing __has_include_next + macro_param_has_include_next, + /// Special token for implementing __is_identifier + macro_param_is_identifier, + /// Special token for implementing __FILE__ + macro_file, + /// Special token for implementing __LINE__ + macro_line, + /// Special token for implementing __COUNTER__ + macro_counter, + /// Special token for implementing _Pragma + macro_param_pragma_operator, + + /// Special identifier for implementing __func__ + macro_func, + /// Special identifier for implementing __FUNCTION__ + macro_function, + /// Special identifier for implementing __PRETTY_FUNCTION__ + macro_pretty_func, + + keyword_auto, + keyword_auto_type, + keyword_break, + keyword_case, + keyword_char, + keyword_const, + keyword_continue, + keyword_default, + keyword_do, + keyword_double, + keyword_else, + keyword_enum, + keyword_extern, + keyword_float, + keyword_for, + keyword_goto, + keyword_if, + keyword_int, + keyword_long, + keyword_register, + keyword_return, + keyword_short, + keyword_signed, + keyword_sizeof, + keyword_static, + keyword_struct, + keyword_switch, + keyword_typedef, + keyword_typeof1, + keyword_typeof2, + keyword_union, + keyword_unsigned, + keyword_void, + keyword_volatile, + keyword_while, + + // ISO C99 + keyword_bool, + keyword_complex, + keyword_imaginary, + keyword_inline, + keyword_restrict, + + // ISO C11 + keyword_alignas, + keyword_alignof, + keyword_atomic, + keyword_generic, + keyword_noreturn, + keyword_static_assert, + keyword_thread_local, + + // ISO C23 + keyword_bit_int, + keyword_c23_alignas, + keyword_c23_alignof, + keyword_c23_bool, + keyword_c23_static_assert, + keyword_c23_thread_local, + keyword_constexpr, + keyword_true, + keyword_false, + keyword_nullptr, + + // Preprocessor directives + keyword_include, + keyword_include_next, + keyword_embed, + keyword_define, + keyword_defined, + keyword_undef, + keyword_ifdef, + keyword_ifndef, + keyword_elif, + keyword_elifdef, + keyword_elifndef, + keyword_endif, + keyword_error, + keyword_warning, + keyword_pragma, + keyword_line, + keyword_va_args, + + // gcc keywords + keyword_const1, + keyword_const2, + keyword_inline1, + keyword_inline2, + keyword_volatile1, + keyword_volatile2, + keyword_restrict1, + keyword_restrict2, + keyword_alignof1, + keyword_alignof2, + keyword_typeof, + keyword_attribute1, + keyword_attribute2, + keyword_extension, + keyword_asm, + keyword_asm1, + keyword_asm2, + keyword_float80, + keyword_float128, + keyword_int128, + keyword_imag1, + keyword_imag2, + keyword_real1, + keyword_real2, + keyword_float16, + + // clang keywords + keyword_fp16, + + // ms keywords + keyword_declspec, + keyword_int64, + keyword_int64_2, + keyword_int32, + keyword_int32_2, + keyword_int16, + keyword_int16_2, + keyword_int8, + keyword_int8_2, + keyword_stdcall, + keyword_stdcall2, + keyword_thiscall, + keyword_thiscall2, + keyword_vectorcall, + keyword_vectorcall2, + + // builtins that require special parsing + builtin_choose_expr, + builtin_va_arg, + builtin_offsetof, + builtin_bitoffsetof, + builtin_types_compatible_p, + + /// Generated by #embed directive + /// Decimal value with no prefix or suffix + embed_byte, + + /// preprocessor number + /// An optional period, followed by a digit 0-9, followed by any number of letters + /// digits, underscores, periods, and exponents (e+, e-, E+, E-, p+, p-, P+, P-) + pp_num, + + /// preprocessor placemarker token + /// generated if `##` is used with a zero-token argument + /// removed after substitution, so the parser should never see this + /// See C99 6.10.3.3.2 + placemarker, + + /// Return true if token is identifier or keyword. + pub fn isMacroIdentifier(id: Id) bool { + switch (id) { + .keyword_include, + .keyword_include_next, + .keyword_embed, + .keyword_define, + .keyword_defined, + .keyword_undef, + .keyword_ifdef, + .keyword_ifndef, + .keyword_elif, + .keyword_elifdef, + .keyword_elifndef, + .keyword_endif, + .keyword_error, + .keyword_warning, + .keyword_pragma, + .keyword_line, + .keyword_va_args, + .macro_func, + .macro_function, + .macro_pretty_func, + .keyword_auto, + .keyword_auto_type, + .keyword_break, + .keyword_case, + .keyword_char, + .keyword_const, + .keyword_continue, + .keyword_default, + .keyword_do, + .keyword_double, + .keyword_else, + .keyword_enum, + .keyword_extern, + .keyword_float, + .keyword_for, + .keyword_goto, + .keyword_if, + .keyword_int, + .keyword_long, + .keyword_register, + .keyword_return, + .keyword_short, + .keyword_signed, + .keyword_sizeof, + .keyword_static, + .keyword_struct, + .keyword_switch, + .keyword_typedef, + .keyword_union, + .keyword_unsigned, + .keyword_void, + .keyword_volatile, + .keyword_while, + .keyword_bool, + .keyword_complex, + .keyword_imaginary, + .keyword_inline, + .keyword_restrict, + .keyword_alignas, + .keyword_alignof, + .keyword_atomic, + .keyword_generic, + .keyword_noreturn, + .keyword_static_assert, + .keyword_thread_local, + .identifier, + .extended_identifier, + .keyword_typeof, + .keyword_typeof1, + .keyword_typeof2, + .keyword_const1, + .keyword_const2, + .keyword_inline1, + .keyword_inline2, + .keyword_volatile1, + .keyword_volatile2, + .keyword_restrict1, + .keyword_restrict2, + .keyword_alignof1, + .keyword_alignof2, + .builtin_choose_expr, + .builtin_va_arg, + .builtin_offsetof, + .builtin_bitoffsetof, + .builtin_types_compatible_p, + .keyword_attribute1, + .keyword_attribute2, + .keyword_extension, + .keyword_asm, + .keyword_asm1, + .keyword_asm2, + .keyword_float80, + .keyword_float128, + .keyword_int128, + .keyword_imag1, + .keyword_imag2, + .keyword_real1, + .keyword_real2, + .keyword_float16, + .keyword_fp16, + .keyword_declspec, + .keyword_int64, + .keyword_int64_2, + .keyword_int32, + .keyword_int32_2, + .keyword_int16, + .keyword_int16_2, + .keyword_int8, + .keyword_int8_2, + .keyword_stdcall, + .keyword_stdcall2, + .keyword_thiscall, + .keyword_thiscall2, + .keyword_vectorcall, + .keyword_vectorcall2, + .keyword_bit_int, + .keyword_c23_alignas, + .keyword_c23_alignof, + .keyword_c23_bool, + .keyword_c23_static_assert, + .keyword_c23_thread_local, + .keyword_constexpr, + .keyword_true, + .keyword_false, + .keyword_nullptr, + => return true, + else => return false, + } + } + + /// Turn macro keywords into identifiers. + /// `keyword_defined` is special since it should only turn into an identifier if + /// we are *not* in an #if or #elif expression + pub fn simplifyMacroKeywordExtra(id: *Id, defined_to_identifier: bool) void { + switch (id.*) { + .keyword_include, + .keyword_include_next, + .keyword_embed, + .keyword_define, + .keyword_undef, + .keyword_ifdef, + .keyword_ifndef, + .keyword_elif, + .keyword_elifdef, + .keyword_elifndef, + .keyword_endif, + .keyword_error, + .keyword_warning, + .keyword_pragma, + .keyword_line, + .keyword_va_args, + => id.* = .identifier, + .keyword_defined => if (defined_to_identifier) { + id.* = .identifier; + }, + else => {}, + } + } + + pub fn simplifyMacroKeyword(id: *Id) void { + simplifyMacroKeywordExtra(id, false); + } + + pub fn lexeme(id: Id) ?[]const u8 { + return switch (id) { + .invalid, + .identifier, + .extended_identifier, + .string_literal, + .string_literal_utf_16, + .string_literal_utf_8, + .string_literal_utf_32, + .string_literal_wide, + .char_literal, + .char_literal_utf_8, + .char_literal_utf_16, + .char_literal_utf_32, + .char_literal_wide, + .macro_string, + .whitespace, + .pp_num, + .embed_byte, + => null, + + .zero => "0", + .one => "1", + + .nl, + .eof, + .macro_param, + .macro_param_no_expand, + .stringify_param, + .stringify_va_args, + .macro_param_has_attribute, + .macro_param_has_warning, + .macro_param_has_feature, + .macro_param_has_extension, + .macro_param_has_builtin, + .macro_param_has_include, + .macro_param_has_include_next, + .macro_param_is_identifier, + .macro_file, + .macro_line, + .macro_counter, + .macro_param_pragma_operator, + .placemarker, + => "", + .macro_ws => " ", + + .macro_func => "__func__", + .macro_function => "__FUNCTION__", + .macro_pretty_func => "__PRETTY_FUNCTION__", + + .bang => "!", + .bang_equal => "!=", + .pipe => "|", + .pipe_pipe => "||", + .pipe_equal => "|=", + .equal => "=", + .equal_equal => "==", + .l_paren => "(", + .r_paren => ")", + .l_brace => "{", + .r_brace => "}", + .l_bracket => "[", + .r_bracket => "]", + .period => ".", + .ellipsis => "...", + .caret => "^", + .caret_equal => "^=", + .plus => "+", + .plus_plus => "++", + .plus_equal => "+=", + .minus => "-", + .minus_minus => "--", + .minus_equal => "-=", + .asterisk => "*", + .asterisk_equal => "*=", + .percent => "%", + .percent_equal => "%=", + .arrow => "->", + .colon => ":", + .colon_colon => "::", + .semicolon => ";", + .slash => "/", + .slash_equal => "/=", + .comma => ",", + .ampersand => "&", + .ampersand_ampersand => "&&", + .ampersand_equal => "&=", + .question_mark => "?", + .angle_bracket_left => "<", + .angle_bracket_left_equal => "<=", + .angle_bracket_angle_bracket_left => "<<", + .angle_bracket_angle_bracket_left_equal => "<<=", + .angle_bracket_right => ">", + .angle_bracket_right_equal => ">=", + .angle_bracket_angle_bracket_right => ">>", + .angle_bracket_angle_bracket_right_equal => ">>=", + .tilde => "~", + .hash => "#", + .hash_hash => "##", + + .keyword_auto => "auto", + .keyword_auto_type => "__auto_type", + .keyword_break => "break", + .keyword_case => "case", + .keyword_char => "char", + .keyword_const => "const", + .keyword_continue => "continue", + .keyword_default => "default", + .keyword_do => "do", + .keyword_double => "double", + .keyword_else => "else", + .keyword_enum => "enum", + .keyword_extern => "extern", + .keyword_float => "float", + .keyword_for => "for", + .keyword_goto => "goto", + .keyword_if => "if", + .keyword_int => "int", + .keyword_long => "long", + .keyword_register => "register", + .keyword_return => "return", + .keyword_short => "short", + .keyword_signed => "signed", + .keyword_sizeof => "sizeof", + .keyword_static => "static", + .keyword_struct => "struct", + .keyword_switch => "switch", + .keyword_typedef => "typedef", + .keyword_typeof => "typeof", + .keyword_union => "union", + .keyword_unsigned => "unsigned", + .keyword_void => "void", + .keyword_volatile => "volatile", + .keyword_while => "while", + .keyword_bool => "_Bool", + .keyword_complex => "_Complex", + .keyword_imaginary => "_Imaginary", + .keyword_inline => "inline", + .keyword_restrict => "restrict", + .keyword_alignas => "_Alignas", + .keyword_alignof => "_Alignof", + .keyword_atomic => "_Atomic", + .keyword_generic => "_Generic", + .keyword_noreturn => "_Noreturn", + .keyword_static_assert => "_Static_assert", + .keyword_thread_local => "_Thread_local", + .keyword_bit_int => "_BitInt", + .keyword_c23_alignas => "alignas", + .keyword_c23_alignof => "alignof", + .keyword_c23_bool => "bool", + .keyword_c23_static_assert => "static_assert", + .keyword_c23_thread_local => "thread_local", + .keyword_constexpr => "constexpr", + .keyword_true => "true", + .keyword_false => "false", + .keyword_nullptr => "nullptr", + .keyword_include => "include", + .keyword_include_next => "include_next", + .keyword_embed => "embed", + .keyword_define => "define", + .keyword_defined => "defined", + .keyword_undef => "undef", + .keyword_ifdef => "ifdef", + .keyword_ifndef => "ifndef", + .keyword_elif => "elif", + .keyword_elifdef => "elifdef", + .keyword_elifndef => "elifndef", + .keyword_endif => "endif", + .keyword_error => "error", + .keyword_warning => "warning", + .keyword_pragma => "pragma", + .keyword_line => "line", + .keyword_va_args => "__VA_ARGS__", + .keyword_const1 => "__const", + .keyword_const2 => "__const__", + .keyword_inline1 => "__inline", + .keyword_inline2 => "__inline__", + .keyword_volatile1 => "__volatile", + .keyword_volatile2 => "__volatile__", + .keyword_restrict1 => "__restrict", + .keyword_restrict2 => "__restrict__", + .keyword_alignof1 => "__alignof", + .keyword_alignof2 => "__alignof__", + .keyword_typeof1 => "__typeof", + .keyword_typeof2 => "__typeof__", + .builtin_choose_expr => "__builtin_choose_expr", + .builtin_va_arg => "__builtin_va_arg", + .builtin_offsetof => "__builtin_offsetof", + .builtin_bitoffsetof => "__builtin_bitoffsetof", + .builtin_types_compatible_p => "__builtin_types_compatible_p", + .keyword_attribute1 => "__attribute", + .keyword_attribute2 => "__attribute__", + .keyword_extension => "__extension__", + .keyword_asm => "asm", + .keyword_asm1 => "__asm", + .keyword_asm2 => "__asm__", + .keyword_float80 => "__float80", + .keyword_float128 => "__float18", + .keyword_int128 => "__int128", + .keyword_imag1 => "__imag", + .keyword_imag2 => "__imag__", + .keyword_real1 => "__real", + .keyword_real2 => "__real__", + .keyword_float16 => "_Float16", + .keyword_fp16 => "__fp16", + .keyword_declspec => "__declspec", + .keyword_int64 => "__int64", + .keyword_int64_2 => "_int64", + .keyword_int32 => "__int32", + .keyword_int32_2 => "_int32", + .keyword_int16 => "__int16", + .keyword_int16_2 => "_int16", + .keyword_int8 => "__int8", + .keyword_int8_2 => "_int8", + .keyword_stdcall => "__stdcall", + .keyword_stdcall2 => "_stdcall", + .keyword_thiscall => "__thiscall", + .keyword_thiscall2 => "_thiscall", + .keyword_vectorcall => "__vectorcall", + .keyword_vectorcall2 => "_vectorcall", + }; + } + + pub fn symbol(id: Id) []const u8 { + return switch (id) { + .macro_string, .invalid => unreachable, + .identifier, + .extended_identifier, + .macro_func, + .macro_function, + .macro_pretty_func, + .builtin_choose_expr, + .builtin_va_arg, + .builtin_offsetof, + .builtin_bitoffsetof, + .builtin_types_compatible_p, + => "an identifier", + .string_literal, + .string_literal_utf_16, + .string_literal_utf_8, + .string_literal_utf_32, + .string_literal_wide, + => "a string literal", + .char_literal, + .char_literal_utf_8, + .char_literal_utf_16, + .char_literal_utf_32, + .char_literal_wide, + => "a character literal", + .pp_num, .embed_byte => "A number", + else => id.lexeme().?, + }; + } + + /// tokens that can start an expression parsed by Preprocessor.expr + /// Note that eof, r_paren, and string literals cannot actually start a + /// preprocessor expression, but we include them here so that a nicer + /// error message can be generated by the parser. + pub fn validPreprocessorExprStart(id: Id) bool { + return switch (id) { + .eof, + .r_paren, + .string_literal, + .string_literal_utf_16, + .string_literal_utf_8, + .string_literal_utf_32, + .string_literal_wide, + + .char_literal, + .char_literal_utf_8, + .char_literal_utf_16, + .char_literal_utf_32, + .char_literal_wide, + .l_paren, + .plus, + .minus, + .tilde, + .bang, + .identifier, + .extended_identifier, + .keyword_defined, + .one, + .zero, + .pp_num, + .keyword_true, + .keyword_false, + => true, + else => false, + }; + } + + pub fn allowsDigraphs(id: Id, comp: *const Compilation) bool { + return switch (id) { + .l_bracket, + .r_bracket, + .l_brace, + .r_brace, + .hash, + .hash_hash, + => comp.langopts.hasDigraphs(), + else => false, + }; + } + + pub fn canOpenGCCAsmStmt(id: Id) bool { + return switch (id) { + .keyword_volatile, .keyword_volatile1, .keyword_volatile2, .keyword_inline, .keyword_inline1, .keyword_inline2, .keyword_goto, .l_paren => true, + else => false, + }; + } + + pub fn isStringLiteral(id: Id) bool { + return switch (id) { + .string_literal, .string_literal_utf_16, .string_literal_utf_8, .string_literal_utf_32, .string_literal_wide => true, + else => false, + }; + } + }; + + /// double underscore and underscore + capital letter identifiers + /// belong to the implementation namespace, so we always convert them + /// to keywords. + pub fn getTokenId(comp: *const Compilation, str: []const u8) Token.Id { + const kw = all_kws.get(str) orelse return .identifier; + const standard = comp.langopts.standard; + return switch (kw) { + .keyword_inline => if (standard.isGNU() or standard.atLeast(.c99)) kw else .identifier, + .keyword_restrict => if (standard.atLeast(.c99)) kw else .identifier, + .keyword_typeof => if (standard.isGNU() or standard.atLeast(.c2x)) kw else .identifier, + .keyword_asm => if (standard.isGNU()) kw else .identifier, + .keyword_declspec => if (comp.langopts.declspec_attrs) kw else .identifier, + + .keyword_c23_alignas, + .keyword_c23_alignof, + .keyword_c23_bool, + .keyword_c23_static_assert, + .keyword_c23_thread_local, + .keyword_constexpr, + .keyword_true, + .keyword_false, + .keyword_nullptr, + .keyword_elifdef, + .keyword_elifndef, + => if (standard.atLeast(.c2x)) kw else .identifier, + + .keyword_int64, + .keyword_int64_2, + .keyword_int32, + .keyword_int32_2, + .keyword_int16, + .keyword_int16_2, + .keyword_int8, + .keyword_int8_2, + .keyword_stdcall2, + .keyword_thiscall2, + .keyword_vectorcall2, + => if (comp.langopts.ms_extensions) kw else .identifier, + else => kw, + }; + } + + /// Check if codepoint may appear in specified context + /// does not check basic character set chars because the tokenizer handles them separately to keep the common + /// case on the fast path + pub fn mayAppearInIdent(comp: *const Compilation, codepoint: u21, where: enum { start, inside }) bool { + if (codepoint == '$') return comp.langopts.dollars_in_identifiers; + if (codepoint <= 0x7F) return false; + return switch (where) { + .start => if (comp.langopts.standard.atLeast(.c11)) + CharInfo.isC11IdChar(codepoint) and !CharInfo.isC11DisallowedInitialIdChar(codepoint) + else + CharInfo.isC99IdChar(codepoint) and !CharInfo.isC99DisallowedInitialIDChar(codepoint), + .inside => if (comp.langopts.standard.atLeast(.c11)) + CharInfo.isC11IdChar(codepoint) + else + CharInfo.isC99IdChar(codepoint), + }; + } + + const all_kws = std.ComptimeStringMap(Id, .{ + .{ "auto", auto: { + @setEvalBranchQuota(3000); + break :auto .keyword_auto; + } }, + .{ "break", .keyword_break }, + .{ "case", .keyword_case }, + .{ "char", .keyword_char }, + .{ "const", .keyword_const }, + .{ "continue", .keyword_continue }, + .{ "default", .keyword_default }, + .{ "do", .keyword_do }, + .{ "double", .keyword_double }, + .{ "else", .keyword_else }, + .{ "enum", .keyword_enum }, + .{ "extern", .keyword_extern }, + .{ "float", .keyword_float }, + .{ "for", .keyword_for }, + .{ "goto", .keyword_goto }, + .{ "if", .keyword_if }, + .{ "int", .keyword_int }, + .{ "long", .keyword_long }, + .{ "register", .keyword_register }, + .{ "return", .keyword_return }, + .{ "short", .keyword_short }, + .{ "signed", .keyword_signed }, + .{ "sizeof", .keyword_sizeof }, + .{ "static", .keyword_static }, + .{ "struct", .keyword_struct }, + .{ "switch", .keyword_switch }, + .{ "typedef", .keyword_typedef }, + .{ "union", .keyword_union }, + .{ "unsigned", .keyword_unsigned }, + .{ "void", .keyword_void }, + .{ "volatile", .keyword_volatile }, + .{ "while", .keyword_while }, + .{ "__typeof__", .keyword_typeof2 }, + .{ "__typeof", .keyword_typeof1 }, + + // ISO C99 + .{ "_Bool", .keyword_bool }, + .{ "_Complex", .keyword_complex }, + .{ "_Imaginary", .keyword_imaginary }, + .{ "inline", .keyword_inline }, + .{ "restrict", .keyword_restrict }, + + // ISO C11 + .{ "_Alignas", .keyword_alignas }, + .{ "_Alignof", .keyword_alignof }, + .{ "_Atomic", .keyword_atomic }, + .{ "_Generic", .keyword_generic }, + .{ "_Noreturn", .keyword_noreturn }, + .{ "_Static_assert", .keyword_static_assert }, + .{ "_Thread_local", .keyword_thread_local }, + + // ISO C23 + .{ "_BitInt", .keyword_bit_int }, + .{ "alignas", .keyword_c23_alignas }, + .{ "alignof", .keyword_c23_alignof }, + .{ "bool", .keyword_c23_bool }, + .{ "static_assert", .keyword_c23_static_assert }, + .{ "thread_local", .keyword_c23_thread_local }, + .{ "constexpr", .keyword_constexpr }, + .{ "true", .keyword_true }, + .{ "false", .keyword_false }, + .{ "nullptr", .keyword_nullptr }, + + // Preprocessor directives + .{ "include", .keyword_include }, + .{ "include_next", .keyword_include_next }, + .{ "embed", .keyword_embed }, + .{ "define", .keyword_define }, + .{ "defined", .keyword_defined }, + .{ "undef", .keyword_undef }, + .{ "ifdef", .keyword_ifdef }, + .{ "ifndef", .keyword_ifndef }, + .{ "elif", .keyword_elif }, + .{ "elifdef", .keyword_elifdef }, + .{ "elifndef", .keyword_elifndef }, + .{ "endif", .keyword_endif }, + .{ "error", .keyword_error }, + .{ "warning", .keyword_warning }, + .{ "pragma", .keyword_pragma }, + .{ "line", .keyword_line }, + .{ "__VA_ARGS__", .keyword_va_args }, + .{ "__func__", .macro_func }, + .{ "__FUNCTION__", .macro_function }, + .{ "__PRETTY_FUNCTION__", .macro_pretty_func }, + + // gcc keywords + .{ "__auto_type", .keyword_auto_type }, + .{ "__const", .keyword_const1 }, + .{ "__const__", .keyword_const2 }, + .{ "__inline", .keyword_inline1 }, + .{ "__inline__", .keyword_inline2 }, + .{ "__volatile", .keyword_volatile1 }, + .{ "__volatile__", .keyword_volatile2 }, + .{ "__restrict", .keyword_restrict1 }, + .{ "__restrict__", .keyword_restrict2 }, + .{ "__alignof", .keyword_alignof1 }, + .{ "__alignof__", .keyword_alignof2 }, + .{ "typeof", .keyword_typeof }, + .{ "__attribute", .keyword_attribute1 }, + .{ "__attribute__", .keyword_attribute2 }, + .{ "__extension__", .keyword_extension }, + .{ "asm", .keyword_asm }, + .{ "__asm", .keyword_asm1 }, + .{ "__asm__", .keyword_asm2 }, + .{ "__float80", .keyword_float80 }, + .{ "__float128", .keyword_float128 }, + .{ "__int128", .keyword_int128 }, + .{ "__imag", .keyword_imag1 }, + .{ "__imag__", .keyword_imag2 }, + .{ "__real", .keyword_real1 }, + .{ "__real__", .keyword_real2 }, + .{ "_Float16", .keyword_float16 }, + + // clang keywords + .{ "__fp16", .keyword_fp16 }, + + // ms keywords + .{ "__declspec", .keyword_declspec }, + .{ "__int64", .keyword_int64 }, + .{ "_int64", .keyword_int64_2 }, + .{ "__int32", .keyword_int32 }, + .{ "_int32", .keyword_int32_2 }, + .{ "__int16", .keyword_int16 }, + .{ "_int16", .keyword_int16_2 }, + .{ "__int8", .keyword_int8 }, + .{ "_int8", .keyword_int8_2 }, + .{ "__stdcall", .keyword_stdcall }, + .{ "_stdcall", .keyword_stdcall2 }, + .{ "__thiscall", .keyword_thiscall }, + .{ "_thiscall", .keyword_thiscall2 }, + .{ "__vectorcall", .keyword_vectorcall }, + .{ "_vectorcall", .keyword_vectorcall2 }, + + // builtins that require special parsing + .{ "__builtin_choose_expr", .builtin_choose_expr }, + .{ "__builtin_va_arg", .builtin_va_arg }, + .{ "__builtin_offsetof", .builtin_offsetof }, + .{ "__builtin_bitoffsetof", .builtin_bitoffsetof }, + .{ "__builtin_types_compatible_p", .builtin_types_compatible_p }, + }); +}; + +buf: []const u8, +index: u32 = 0, +source: Source.Id, +comp: *const Compilation, +line: u32 = 1, + +pub fn next(self: *Tokenizer) Token { + var state: enum { + start, + whitespace, + u, + u8, + U, + L, + string_literal, + char_literal_start, + char_literal, + escape_sequence, + octal_escape, + hex_escape, + unicode_escape, + identifier, + extended_identifier, + equal, + bang, + pipe, + colon, + percent, + asterisk, + plus, + angle_bracket_left, + angle_bracket_angle_bracket_left, + angle_bracket_right, + angle_bracket_angle_bracket_right, + caret, + period, + period2, + minus, + slash, + ampersand, + hash, + hash_digraph, + hash_hash_digraph_partial, + line_comment, + multi_line_comment, + multi_line_comment_asterisk, + multi_line_comment_done, + pp_num, + pp_num_exponent, + pp_num_digit_separator, + } = .start; + + var start = self.index; + var id: Token.Id = .eof; + + var return_state = state; + var counter: u32 = 0; + var codepoint_len: u3 = undefined; + while (self.index < self.buf.len) : (self.index += codepoint_len) { + // Source files get checked for valid utf-8 before being tokenized so it is safe to use + // these versions. + codepoint_len = unicode.utf8ByteSequenceLength_unsafe(self.buf[self.index]); + const c: u21 = switch (codepoint_len) { + 1 => @as(u21, self.buf[self.index]), + 2 => unicode.utf8Decode2_unsafe(self.buf[self.index..]), + 3 => unicode.utf8Decode3_unsafe(self.buf[self.index..]), + 4 => unicode.utf8Decode4_unsafe(self.buf[self.index..]), + else => unreachable, + }; + switch (state) { + .start => switch (c) { + '\n' => { + id = .nl; + self.index += 1; + self.line += 1; + break; + }, + '"' => { + id = .string_literal; + state = .string_literal; + }, + '\'' => { + id = .char_literal; + state = .char_literal_start; + }, + 'u' => state = .u, + 'U' => state = .U, + 'L' => state = .L, + 'a'...'t', 'v'...'z', 'A'...'K', 'M'...'T', 'V'...'Z', '_' => state = .identifier, + '=' => state = .equal, + '!' => state = .bang, + '|' => state = .pipe, + '(' => { + id = .l_paren; + self.index += 1; + break; + }, + ')' => { + id = .r_paren; + self.index += 1; + break; + }, + '[' => { + id = .l_bracket; + self.index += 1; + break; + }, + ']' => { + id = .r_bracket; + self.index += 1; + break; + }, + ';' => { + id = .semicolon; + self.index += 1; + break; + }, + ',' => { + id = .comma; + self.index += 1; + break; + }, + '?' => { + id = .question_mark; + self.index += 1; + break; + }, + ':' => state = .colon, + '%' => state = .percent, + '*' => state = .asterisk, + '+' => state = .plus, + '<' => state = .angle_bracket_left, + '>' => state = .angle_bracket_right, + '^' => state = .caret, + '{' => { + id = .l_brace; + self.index += 1; + break; + }, + '}' => { + id = .r_brace; + self.index += 1; + break; + }, + '~' => { + id = .tilde; + self.index += 1; + break; + }, + '.' => state = .period, + '-' => state = .minus, + '/' => state = .slash, + '&' => state = .ampersand, + '#' => state = .hash, + '0'...'9' => state = .pp_num, + '\t', '\x0B', '\x0C', ' ' => state = .whitespace, + else => if (Token.mayAppearInIdent(self.comp, c, .start)) { + state = .extended_identifier; + } else { + id = .invalid; + self.index += codepoint_len; + break; + }, + }, + .whitespace => switch (c) { + '\t', '\x0B', '\x0C', ' ' => {}, + else => { + id = .whitespace; + break; + }, + }, + .u => switch (c) { + '8' => { + state = .u8; + }, + '\'' => { + id = .char_literal_utf_16; + state = .char_literal_start; + }, + '\"' => { + id = .string_literal_utf_16; + state = .string_literal; + }, + else => { + codepoint_len = 0; + state = .identifier; + }, + }, + .u8 => switch (c) { + '\"' => { + id = .string_literal_utf_8; + state = .string_literal; + }, + '\'' => { + id = .char_literal_utf_8; + state = .char_literal_start; + }, + else => { + codepoint_len = 0; + state = .identifier; + }, + }, + .U => switch (c) { + '\'' => { + id = .char_literal_utf_32; + state = .char_literal_start; + }, + '\"' => { + id = .string_literal_utf_32; + state = .string_literal; + }, + else => { + codepoint_len = 0; + state = .identifier; + }, + }, + .L => switch (c) { + '\'' => { + id = .char_literal_wide; + state = .char_literal_start; + }, + '\"' => { + id = .string_literal_wide; + state = .string_literal; + }, + else => { + codepoint_len = 0; + state = .identifier; + }, + }, + .string_literal => switch (c) { + '\\' => { + return_state = .string_literal; + state = .escape_sequence; + }, + '"' => { + self.index += 1; + break; + }, + '\n' => { + id = .invalid; + break; + }, + '\r' => unreachable, + else => {}, + }, + .char_literal_start => switch (c) { + '\\' => { + return_state = .char_literal; + state = .escape_sequence; + }, + + '\'', '\n' => { + id = .invalid; + break; + }, + else => { + state = .char_literal; + }, + }, + .char_literal => switch (c) { + '\\' => { + return_state = .char_literal; + state = .escape_sequence; + }, + '\'' => { + self.index += 1; + break; + }, + '\n' => { + id = .invalid; + break; + }, + else => {}, + }, + .escape_sequence => switch (c) { + '\'', '"', '?', '\\', 'a', 'b', 'e', 'f', 'n', 'r', 't', 'v' => { + state = return_state; + }, + '\n' => { + state = return_state; + self.line += 1; + }, + '0'...'7' => { + counter = 1; + state = .octal_escape; + }, + 'x' => state = .hex_escape, + 'u' => { + counter = 4; + state = .unicode_escape; + }, + 'U' => { + counter = 8; + state = .unicode_escape; + }, + else => { + id = .invalid; + break; + }, + }, + .octal_escape => switch (c) { + '0'...'7' => { + counter += 1; + if (counter == 3) state = return_state; + }, + else => { + codepoint_len = 0; + state = return_state; + }, + }, + .hex_escape => switch (c) { + '0'...'9', 'a'...'f', 'A'...'F' => {}, + else => { + codepoint_len = 0; + state = return_state; + }, + }, + .unicode_escape => switch (c) { + '0'...'9', 'a'...'f', 'A'...'F' => { + counter -= 1; + if (counter == 0) state = return_state; + }, + else => { + id = .invalid; + break; + }, + }, + .identifier, .extended_identifier => switch (c) { + 'a'...'z', 'A'...'Z', '_', '0'...'9' => {}, + else => { + if (!Token.mayAppearInIdent(self.comp, c, .inside)) { + id = if (state == .identifier) Token.getTokenId(self.comp, self.buf[start..self.index]) else .extended_identifier; + break; + } + state = .extended_identifier; + }, + }, + .equal => switch (c) { + '=' => { + id = .equal_equal; + self.index += 1; + break; + }, + else => { + id = .equal; + break; + }, + }, + .bang => switch (c) { + '=' => { + id = .bang_equal; + self.index += 1; + break; + }, + else => { + id = .bang; + break; + }, + }, + .pipe => switch (c) { + '=' => { + id = .pipe_equal; + self.index += 1; + break; + }, + '|' => { + id = .pipe_pipe; + self.index += 1; + break; + }, + else => { + id = .pipe; + break; + }, + }, + .colon => switch (c) { + '>' => { + if (self.comp.langopts.hasDigraphs()) { + id = .r_bracket; + self.index += 1; + } else { + id = .colon; + } + break; + }, + ':' => { + if (self.comp.langopts.standard.atLeast(.c2x)) { + id = .colon_colon; + self.index += 1; + break; + } else { + id = .colon; + break; + } + }, + else => { + id = .colon; + break; + }, + }, + .percent => switch (c) { + '=' => { + id = .percent_equal; + self.index += 1; + break; + }, + '>' => { + if (self.comp.langopts.hasDigraphs()) { + id = .r_brace; + self.index += 1; + } else { + id = .percent; + } + break; + }, + ':' => { + if (self.comp.langopts.hasDigraphs()) { + state = .hash_digraph; + } else { + id = .percent; + break; + } + }, + else => { + id = .percent; + break; + }, + }, + .asterisk => switch (c) { + '=' => { + id = .asterisk_equal; + self.index += 1; + break; + }, + else => { + id = .asterisk; + break; + }, + }, + .plus => switch (c) { + '=' => { + id = .plus_equal; + self.index += 1; + break; + }, + '+' => { + id = .plus_plus; + self.index += 1; + break; + }, + else => { + id = .plus; + break; + }, + }, + .angle_bracket_left => switch (c) { + '<' => state = .angle_bracket_angle_bracket_left, + '=' => { + id = .angle_bracket_left_equal; + self.index += 1; + break; + }, + ':' => { + if (self.comp.langopts.hasDigraphs()) { + id = .l_bracket; + self.index += 1; + } else { + id = .angle_bracket_left; + } + break; + }, + '%' => { + if (self.comp.langopts.hasDigraphs()) { + id = .l_brace; + self.index += 1; + } else { + id = .angle_bracket_left; + } + break; + }, + else => { + id = .angle_bracket_left; + break; + }, + }, + .angle_bracket_angle_bracket_left => switch (c) { + '=' => { + id = .angle_bracket_angle_bracket_left_equal; + self.index += 1; + break; + }, + else => { + id = .angle_bracket_angle_bracket_left; + break; + }, + }, + .angle_bracket_right => switch (c) { + '>' => state = .angle_bracket_angle_bracket_right, + '=' => { + id = .angle_bracket_right_equal; + self.index += 1; + break; + }, + else => { + id = .angle_bracket_right; + break; + }, + }, + .angle_bracket_angle_bracket_right => switch (c) { + '=' => { + id = .angle_bracket_angle_bracket_right_equal; + self.index += 1; + break; + }, + else => { + id = .angle_bracket_angle_bracket_right; + break; + }, + }, + .caret => switch (c) { + '=' => { + id = .caret_equal; + self.index += 1; + break; + }, + else => { + id = .caret; + break; + }, + }, + .period => switch (c) { + '.' => state = .period2, + '0'...'9' => state = .pp_num, + else => { + id = .period; + break; + }, + }, + .period2 => switch (c) { + '.' => { + id = .ellipsis; + self.index += 1; + break; + }, + else => { + id = .period; + self.index -= 1; + break; + }, + }, + .minus => switch (c) { + '>' => { + id = .arrow; + self.index += 1; + break; + }, + '=' => { + id = .minus_equal; + self.index += 1; + break; + }, + '-' => { + id = .minus_minus; + self.index += 1; + break; + }, + else => { + id = .minus; + break; + }, + }, + .ampersand => switch (c) { + '&' => { + id = .ampersand_ampersand; + self.index += 1; + break; + }, + '=' => { + id = .ampersand_equal; + self.index += 1; + break; + }, + else => { + id = .ampersand; + break; + }, + }, + .hash => switch (c) { + '#' => { + id = .hash_hash; + self.index += 1; + break; + }, + else => { + id = .hash; + break; + }, + }, + .hash_digraph => switch (c) { + '%' => state = .hash_hash_digraph_partial, + else => { + id = .hash; + break; + }, + }, + .hash_hash_digraph_partial => switch (c) { + ':' => { + id = .hash_hash; + self.index += 1; + break; + }, + else => { + id = .hash; + self.index -= 1; // re-tokenize the percent + break; + }, + }, + .slash => switch (c) { + '/' => state = .line_comment, + '*' => state = .multi_line_comment, + '=' => { + id = .slash_equal; + self.index += 1; + break; + }, + else => { + id = .slash; + break; + }, + }, + .line_comment => switch (c) { + '\n' => { + self.index -= 1; + state = .start; + }, + else => {}, + }, + .multi_line_comment => switch (c) { + '*' => state = .multi_line_comment_asterisk, + '\n' => self.line += 1, + else => {}, + }, + .multi_line_comment_asterisk => switch (c) { + '/' => state = .multi_line_comment_done, + '\n' => { + self.line += 1; + state = .multi_line_comment; + }, + '*' => {}, + else => state = .multi_line_comment, + }, + .multi_line_comment_done => switch (c) { + '\n' => { + start = self.index; + id = .nl; + self.index += 1; + self.line += 1; + break; + }, + '\r' => unreachable, + '\t', '\x0B', '\x0C', ' ' => { + start = self.index; + state = .whitespace; + }, + else => { + id = .whitespace; + break; + }, + }, + .pp_num => switch (c) { + 'a'...'d', + 'A'...'D', + 'f'...'o', + 'F'...'O', + 'q'...'z', + 'Q'...'Z', + '0'...'9', + '_', + '.', + => {}, + 'e', 'E', 'p', 'P' => state = .pp_num_exponent, + '\'' => if (self.comp.langopts.standard.atLeast(.c2x)) { + state = .pp_num_digit_separator; + } else { + id = .pp_num; + break; + }, + else => { + id = .pp_num; + break; + }, + }, + .pp_num_digit_separator => switch (c) { + 'a'...'d', + 'A'...'D', + 'f'...'o', + 'F'...'O', + 'q'...'z', + 'Q'...'Z', + '0'...'9', + '_', + => state = .pp_num, + else => { + self.index -= 1; + id = .pp_num; + break; + }, + }, + .pp_num_exponent => switch (c) { + 'a'...'z', + 'A'...'Z', + '0'...'9', + '_', + '.', + '+', + '-', + => state = .pp_num, + else => { + id = .pp_num; + break; + }, + }, + } + } else if (self.index == self.buf.len) { + switch (state) { + .start, .line_comment => {}, + .u, .u8, .U, .L, .identifier => id = Token.getTokenId(self.comp, self.buf[start..self.index]), + .extended_identifier => id = .extended_identifier, + .period2, + .string_literal, + .char_literal_start, + .char_literal, + .escape_sequence, + .octal_escape, + .hex_escape, + .unicode_escape, + .multi_line_comment, + .multi_line_comment_asterisk, + => id = .invalid, + + .whitespace => id = .whitespace, + .multi_line_comment_done => id = .whitespace, + + .equal => id = .equal, + .bang => id = .bang, + .minus => id = .minus, + .slash => id = .slash, + .ampersand => id = .ampersand, + .hash => id = .hash, + .period => id = .period, + .pipe => id = .pipe, + .angle_bracket_angle_bracket_right => id = .angle_bracket_angle_bracket_right, + .angle_bracket_right => id = .angle_bracket_right, + .angle_bracket_angle_bracket_left => id = .angle_bracket_angle_bracket_left, + .angle_bracket_left => id = .angle_bracket_left, + .plus => id = .plus, + .colon => id = .colon, + .percent => id = .percent, + .caret => id = .caret, + .asterisk => id = .asterisk, + .hash_digraph => id = .hash, + .hash_hash_digraph_partial => { + id = .hash; + self.index -= 1; // re-tokenize the percent + }, + .pp_num, .pp_num_exponent, .pp_num_digit_separator => id = .pp_num, + } + } + + return .{ + .id = id, + .start = start, + .end = self.index, + .line = self.line, + .source = self.source, + }; +} + +pub fn nextNoWS(self: *Tokenizer) Token { + var tok = self.next(); + while (tok.id == .whitespace) tok = self.next(); + return tok; +} + +test "operators" { + try expectTokens( + \\ ! != | || |= = == + \\ ( ) { } [ ] . .. ... + \\ ^ ^= + ++ += - -- -= + \\ * *= % %= -> : ; / /= + \\ , & && &= ? < <= << + \\ <<= > >= >> >>= ~ # ## + \\ + , &.{ + .bang, + .bang_equal, + .pipe, + .pipe_pipe, + .pipe_equal, + .equal, + .equal_equal, + .nl, + .l_paren, + .r_paren, + .l_brace, + .r_brace, + .l_bracket, + .r_bracket, + .period, + .period, + .period, + .ellipsis, + .nl, + .caret, + .caret_equal, + .plus, + .plus_plus, + .plus_equal, + .minus, + .minus_minus, + .minus_equal, + .nl, + .asterisk, + .asterisk_equal, + .percent, + .percent_equal, + .arrow, + .colon, + .semicolon, + .slash, + .slash_equal, + .nl, + .comma, + .ampersand, + .ampersand_ampersand, + .ampersand_equal, + .question_mark, + .angle_bracket_left, + .angle_bracket_left_equal, + .angle_bracket_angle_bracket_left, + .nl, + .angle_bracket_angle_bracket_left_equal, + .angle_bracket_right, + .angle_bracket_right_equal, + .angle_bracket_angle_bracket_right, + .angle_bracket_angle_bracket_right_equal, + .tilde, + .hash, + .hash_hash, + .nl, + }); +} + +test "keywords" { + try expectTokens( + \\auto __auto_type break case char const continue default do + \\double else enum extern float for goto if int + \\long register return short signed sizeof static + \\struct switch typedef union unsigned void volatile + \\while _Bool _Complex _Imaginary inline restrict _Alignas + \\_Alignof _Atomic _Generic _Noreturn _Static_assert _Thread_local + \\__attribute __attribute__ + \\ + , &.{ + .keyword_auto, + .keyword_auto_type, + .keyword_break, + .keyword_case, + .keyword_char, + .keyword_const, + .keyword_continue, + .keyword_default, + .keyword_do, + .nl, + .keyword_double, + .keyword_else, + .keyword_enum, + .keyword_extern, + .keyword_float, + .keyword_for, + .keyword_goto, + .keyword_if, + .keyword_int, + .nl, + .keyword_long, + .keyword_register, + .keyword_return, + .keyword_short, + .keyword_signed, + .keyword_sizeof, + .keyword_static, + .nl, + .keyword_struct, + .keyword_switch, + .keyword_typedef, + .keyword_union, + .keyword_unsigned, + .keyword_void, + .keyword_volatile, + .nl, + .keyword_while, + .keyword_bool, + .keyword_complex, + .keyword_imaginary, + .keyword_inline, + .keyword_restrict, + .keyword_alignas, + .nl, + .keyword_alignof, + .keyword_atomic, + .keyword_generic, + .keyword_noreturn, + .keyword_static_assert, + .keyword_thread_local, + .nl, + .keyword_attribute1, + .keyword_attribute2, + .nl, + }); +} + +test "preprocessor keywords" { + try expectTokens( + \\#include + \\#include_next + \\#embed + \\#define + \\#ifdef + \\#ifndef + \\#error + \\#pragma + \\ + , &.{ + .hash, + .keyword_include, + .nl, + .hash, + .keyword_include_next, + .nl, + .hash, + .keyword_embed, + .nl, + .hash, + .keyword_define, + .nl, + .hash, + .keyword_ifdef, + .nl, + .hash, + .keyword_ifndef, + .nl, + .hash, + .keyword_error, + .nl, + .hash, + .keyword_pragma, + .nl, + }); +} + +test "line continuation" { + try expectTokens( + \\#define foo \ + \\ bar + \\"foo\ + \\ bar" + \\#define "foo" + \\ "bar" + \\#define "foo" \ + \\ "bar" + , &.{ + .hash, + .keyword_define, + .identifier, + .identifier, + .nl, + .string_literal, + .nl, + .hash, + .keyword_define, + .string_literal, + .nl, + .string_literal, + .nl, + .hash, + .keyword_define, + .string_literal, + .string_literal, + }); +} + +test "string prefix" { + try expectTokens( + \\"foo" + \\u"foo" + \\u8"foo" + \\U"foo" + \\L"foo" + \\'foo' + \\u8'A' + \\u'foo' + \\U'foo' + \\L'foo' + \\ + , &.{ + .string_literal, + .nl, + .string_literal_utf_16, + .nl, + .string_literal_utf_8, + .nl, + .string_literal_utf_32, + .nl, + .string_literal_wide, + .nl, + .char_literal, + .nl, + .char_literal_utf_8, + .nl, + .char_literal_utf_16, + .nl, + .char_literal_utf_32, + .nl, + .char_literal_wide, + .nl, + }); +} + +test "num suffixes" { + try expectTokens( + \\ 1.0f 1.0L 1.0 .0 1. 0x1p0f 0X1p0 + \\ 0l 0lu 0ll 0llu 0 + \\ 1u 1ul 1ull 1 + \\ 1.0i 1.0I + \\ 1.0if 1.0If 1.0fi 1.0fI + \\ 1.0il 1.0Il 1.0li 1.0lI + \\ + , &.{ + .pp_num, + .pp_num, + .pp_num, + .pp_num, + .pp_num, + .pp_num, + .pp_num, + .nl, + .pp_num, + .pp_num, + .pp_num, + .pp_num, + .pp_num, + .nl, + .pp_num, + .pp_num, + .pp_num, + .pp_num, + .nl, + .pp_num, + .pp_num, + .nl, + .pp_num, + .pp_num, + .pp_num, + .pp_num, + .nl, + .pp_num, + .pp_num, + .pp_num, + .pp_num, + .nl, + }); +} + +test "comments" { + try expectTokens( + \\//foo + \\#foo + , &.{ + .nl, + .hash, + .identifier, + }); +} + +test "extended identifiers" { + try expectTokens("𝓪𝓻𝓸𝓬𝓬", &.{.extended_identifier}); + try expectTokens("u𝓪𝓻𝓸𝓬𝓬", &.{.extended_identifier}); + try expectTokens("u8𝓪𝓻𝓸𝓬𝓬", &.{.extended_identifier}); + try expectTokens("U𝓪𝓻𝓸𝓬𝓬", &.{.extended_identifier}); + try expectTokens("L𝓪𝓻𝓸𝓬𝓬", &.{.extended_identifier}); + try expectTokens("1™", &.{ .pp_num, .extended_identifier }); + try expectTokens("1.™", &.{ .pp_num, .extended_identifier }); + try expectTokens("..™", &.{ .period, .period, .extended_identifier }); + try expectTokens("0™", &.{ .pp_num, .extended_identifier }); + try expectTokens("0b\u{E0000}", &.{ .pp_num, .extended_identifier }); + try expectTokens("0b0\u{E0000}", &.{ .pp_num, .extended_identifier }); + try expectTokens("01\u{E0000}", &.{ .pp_num, .extended_identifier }); + try expectTokens("010\u{E0000}", &.{ .pp_num, .extended_identifier }); + try expectTokens("0x\u{E0000}", &.{ .pp_num, .extended_identifier }); + try expectTokens("0x0\u{E0000}", &.{ .pp_num, .extended_identifier }); + try expectTokens("\"\\0\u{E0000}\"", &.{.string_literal}); + try expectTokens("\"\\x\u{E0000}\"", &.{.string_literal}); + try expectTokens("\"\\u\u{E0000}\"", &.{ .invalid, .extended_identifier, .invalid }); + try expectTokens("1e\u{E0000}", &.{ .pp_num, .extended_identifier }); + try expectTokens("1e1\u{E0000}", &.{ .pp_num, .extended_identifier }); +} + +test "digraphs" { + try expectTokens("%:<::><%%>%:%:", &.{ .hash, .l_bracket, .r_bracket, .l_brace, .r_brace, .hash_hash }); + try expectTokens("\"%:<::><%%>%:%:\"", &.{.string_literal}); + try expectTokens("%:%42 %:%", &.{ .hash, .percent, .pp_num, .hash, .percent }); +} + +test "C23 keywords" { + try expectTokensExtra("true false alignas alignof bool static_assert thread_local nullptr", &.{ + .keyword_true, + .keyword_false, + .keyword_c23_alignas, + .keyword_c23_alignof, + .keyword_c23_bool, + .keyword_c23_static_assert, + .keyword_c23_thread_local, + .keyword_nullptr, + }, .c2x); +} + +fn expectTokensExtra(contents: []const u8, expected_tokens: []const Token.Id, standard: ?LangOpts.Standard) !void { + var comp = Compilation.init(std.testing.allocator); + defer comp.deinit(); + if (standard) |provided| { + comp.langopts.standard = provided; + } + const source = try comp.addSourceFromBuffer("path", contents); + var tokenizer = Tokenizer{ + .buf = source.buf, + .source = source.id, + .comp = &comp, + }; + var i: usize = 0; + while (i < expected_tokens.len) { + const token = tokenizer.next(); + if (token.id == .whitespace) continue; + const expected_token_id = expected_tokens[i]; + i += 1; + if (!std.meta.eql(token.id, expected_token_id)) { + std.debug.print("expected {s}, found {s}\n", .{ @tagName(expected_token_id), @tagName(token.id) }); + return error.TokensDoNotEqual; + } + } + const last_token = tokenizer.next(); + try std.testing.expect(last_token.id == .eof); +} + +fn expectTokens(contents: []const u8, expected_tokens: []const Token.Id) !void { + return expectTokensExtra(contents, expected_tokens, null); +} diff --git a/deps/aro/Toolchain.zig b/deps/aro/Toolchain.zig new file mode 100644 index 000000000000..dcc4a5185944 --- /dev/null +++ b/deps/aro/Toolchain.zig @@ -0,0 +1,493 @@ +const std = @import("std"); +const Driver = @import("Driver.zig"); +const Compilation = @import("Compilation.zig"); +const util = @import("util.zig"); +const mem = std.mem; +const system_defaults = @import("system_defaults"); +const target_util = @import("target.zig"); +const Linux = @import("toolchains/Linux.zig"); +const Multilib = @import("Driver/Multilib.zig"); +const Filesystem = @import("Driver/Filesystem.zig").Filesystem; + +const Toolchain = @This(); + +pub const PathList = std.ArrayListUnmanaged([]const u8); + +pub const RuntimeLibKind = enum { + compiler_rt, + libgcc, +}; + +pub const FileKind = enum { + object, + static, + shared, +}; + +pub const LibGCCKind = enum { + unspecified, + static, + shared, +}; + +pub const UnwindLibKind = enum { + none, + compiler_rt, + libgcc, +}; + +const Inner = union(enum) { + uninitialized, + linux: Linux, + unknown: void, + + fn deinit(self: *Inner, allocator: mem.Allocator) void { + switch (self.*) { + .linux => |*linux| linux.deinit(allocator), + .uninitialized, .unknown => {}, + } + } +}; + +filesystem: Filesystem = .{ .real = {} }, +driver: *Driver, +arena: mem.Allocator, + +/// The list of toolchain specific path prefixes to search for libraries. +library_paths: PathList = .{}, + +/// The list of toolchain specific path prefixes to search for files. +file_paths: PathList = .{}, + +/// The list of toolchain specific path prefixes to search for programs. +program_paths: PathList = .{}, + +selected_multilib: Multilib = .{}, + +inner: Inner = .{ .uninitialized = {} }, + +pub fn getTarget(tc: *const Toolchain) std.Target { + return tc.driver.comp.target; +} + +fn getDefaultLinker(tc: *const Toolchain) []const u8 { + return switch (tc.inner) { + .uninitialized => unreachable, + .linux => |linux| linux.getDefaultLinker(tc.getTarget()), + .unknown => "ld", + }; +} + +/// Call this after driver has finished parsing command line arguments to find the toolchain +pub fn discover(tc: *Toolchain) !void { + if (tc.inner != .uninitialized) return; + + const target = tc.getTarget(); + tc.inner = switch (target.os.tag) { + .elfiamcu, + .linux, + => if (target.cpu.arch == .hexagon) + .{ .unknown = {} } // TODO + else if (target.cpu.arch.isMIPS()) + .{ .unknown = {} } // TODO + else if (target.cpu.arch.isPPC()) + .{ .unknown = {} } // TODO + else if (target.cpu.arch == .ve) + .{ .unknown = {} } // TODO + else + .{ .linux = .{} }, + else => .{ .unknown = {} }, // TODO + }; + return switch (tc.inner) { + .uninitialized => unreachable, + .linux => |*linux| linux.discover(tc), + .unknown => {}, + }; +} + +pub fn deinit(tc: *Toolchain) void { + const gpa = tc.driver.comp.gpa; + tc.inner.deinit(gpa); + + tc.library_paths.deinit(gpa); + tc.file_paths.deinit(gpa); + tc.program_paths.deinit(gpa); +} + +/// Write linker path to `buf` and return a slice of it +pub fn getLinkerPath(tc: *const Toolchain, buf: []u8) ![]const u8 { + // --ld-path= takes precedence over -fuse-ld= and specifies the executable + // name. -B, COMPILER_PATH and PATH are consulted if the value does not + // contain a path component separator. + // -fuse-ld=lld can be used with --ld-path= to indicate that the binary + // that --ld-path= points to is lld. + const use_linker = tc.driver.use_linker orelse system_defaults.linker; + + if (tc.driver.linker_path) |ld_path| { + var path = ld_path; + if (path.len > 0) { + if (std.fs.path.dirname(path) == null) { + path = tc.getProgramPath(path, buf); + } + if (tc.filesystem.canExecute(path)) { + return path; + } + } + return tc.driver.fatal( + "invalid linker name in argument '--ld-path={s}'", + .{path}, + ); + } + + // If we're passed -fuse-ld= with no argument, or with the argument ld, + // then use whatever the default system linker is. + if (use_linker.len == 0 or mem.eql(u8, use_linker, "ld")) { + const default = tc.getDefaultLinker(); + if (std.fs.path.isAbsolute(default)) return default; + return tc.getProgramPath(default, buf); + } + + // Extending -fuse-ld= to an absolute or relative path is unexpected. Checking + // for the linker flavor is brittle. In addition, prepending "ld." or "ld64." + // to a relative path is surprising. This is more complex due to priorities + // among -B, COMPILER_PATH and PATH. --ld-path= should be used instead. + if (mem.indexOfScalar(u8, use_linker, '/') != null) { + try tc.driver.comp.diag.add(.{ .tag = .fuse_ld_path }, &.{}); + } + + if (std.fs.path.isAbsolute(use_linker)) { + if (tc.filesystem.canExecute(use_linker)) { + return use_linker; + } + } else { + var linker_name = try std.ArrayList(u8).initCapacity(tc.driver.comp.gpa, 5 + use_linker.len); // "ld64." ++ use_linker + defer linker_name.deinit(); + if (tc.getTarget().isDarwin()) { + linker_name.appendSliceAssumeCapacity("ld64."); + } else { + linker_name.appendSliceAssumeCapacity("ld."); + } + linker_name.appendSliceAssumeCapacity(use_linker); + const linker_path = tc.getProgramPath(linker_name.items, buf); + if (tc.filesystem.canExecute(linker_path)) { + return linker_path; + } + } + + if (tc.driver.use_linker) |linker| { + return tc.driver.fatal( + "invalid linker name in argument '-fuse-ld={s}'", + .{linker}, + ); + } + const default_linker = tc.getDefaultLinker(); + return tc.getProgramPath(default_linker, buf); +} + +const TargetSpecificToolName = std.BoundedArray(u8, 64); + +/// If an explicit target is provided, also check the prefixed tool-specific name +/// TODO: this isn't exactly right since our target names don't necessarily match up +/// with GCC's. +/// For example the Zig target `arm-freestanding-eabi` would need the `arm-none-eabi` tools +fn possibleProgramNames(raw_triple: ?[]const u8, name: []const u8, target_specific: *TargetSpecificToolName) std.BoundedArray([]const u8, 2) { + var possible_names: std.BoundedArray([]const u8, 2) = .{}; + if (raw_triple) |triple| { + const w = target_specific.writer(); + if (w.print("{s}-{s}", .{ triple, name })) { + possible_names.appendAssumeCapacity(target_specific.constSlice()); + } else |_| {} + } + possible_names.appendAssumeCapacity(name); + + return possible_names; +} + +/// Add toolchain `file_paths` to argv as `-L` arguments +pub fn addFilePathLibArgs(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !void { + try argv.ensureUnusedCapacity(tc.file_paths.items.len); + + var bytes_needed: usize = 0; + for (tc.file_paths.items) |path| { + bytes_needed += path.len + 2; // +2 for `-L` + } + var bytes = try tc.arena.alloc(u8, bytes_needed); + var index: usize = 0; + for (tc.file_paths.items) |path| { + @memcpy(bytes[index..][0..2], "-L"); + @memcpy(bytes[index + 2 ..][0..path.len], path); + argv.appendAssumeCapacity(bytes[index..][0 .. path.len + 2]); + index += path.len + 2; + } +} + +/// Search for an executable called `name` or `{triple}-{name} in program_paths and the $PATH environment variable +/// If not found there, just use `name` +/// Writes the result to `buf` and returns a slice of it +fn getProgramPath(tc: *const Toolchain, name: []const u8, buf: []u8) []const u8 { + var path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + var fib = std.heap.FixedBufferAllocator.init(&path_buf); + + var tool_specific_name: TargetSpecificToolName = .{}; + const possible_names = possibleProgramNames(tc.driver.raw_target_triple, name, &tool_specific_name); + + for (possible_names.constSlice()) |tool_name| { + for (tc.program_paths.items) |program_path| { + defer fib.reset(); + + const candidate = std.fs.path.join(fib.allocator(), &.{ program_path, tool_name }) catch continue; + + if (tc.filesystem.canExecute(candidate) and candidate.len <= buf.len) { + @memcpy(buf[0..candidate.len], candidate); + return buf[0..candidate.len]; + } + } + return tc.filesystem.findProgramByName(tc.driver.comp.gpa, name, tc.driver.comp.environment.path, buf) orelse continue; + } + @memcpy(buf[0..name.len], name); + return buf[0..name.len]; +} + +pub fn getSysroot(tc: *const Toolchain) []const u8 { + return tc.driver.sysroot orelse system_defaults.sysroot; +} + +/// Search for `name` in a variety of places +/// TODO: cache results based on `name` so we're not repeatedly allocating the same strings? +pub fn getFilePath(tc: *const Toolchain, name: []const u8) ![]const u8 { + var path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + var fib = std.heap.FixedBufferAllocator.init(&path_buf); + const allocator = fib.allocator(); + + const sysroot = tc.getSysroot(); + + // todo check resource dir + // todo check compiler RT path + const aro_dir = std.fs.path.dirname(tc.driver.aro_name) orelse ""; + const candidate = try std.fs.path.join(allocator, &.{ aro_dir, "..", name }); + if (tc.filesystem.exists(candidate)) { + return tc.arena.dupe(u8, candidate); + } + + if (tc.searchPaths(&fib, sysroot, tc.library_paths.items, name)) |path| { + return tc.arena.dupe(u8, path); + } + + if (tc.searchPaths(&fib, sysroot, tc.file_paths.items, name)) |path| { + return try tc.arena.dupe(u8, path); + } + + return name; +} + +/// Search a list of `path_prefixes` for the existence `name` +/// Assumes that `fba` is a fixed-buffer allocator, so does not free joined path candidates +fn searchPaths(tc: *const Toolchain, fib: *std.heap.FixedBufferAllocator, sysroot: []const u8, path_prefixes: []const []const u8, name: []const u8) ?[]const u8 { + for (path_prefixes) |path| { + fib.reset(); + if (path.len == 0) continue; + + const candidate = if (path[0] == '=') + std.fs.path.join(fib.allocator(), &.{ sysroot, path[1..], name }) catch continue + else + std.fs.path.join(fib.allocator(), &.{ path, name }) catch continue; + + if (tc.filesystem.exists(candidate)) { + return candidate; + } + } + return null; +} + +const PathKind = enum { + library, + file, + program, +}; + +/// Join `components` into a path. If the path exists, dupe it into the toolchain arena and +/// add it to the specified path list. +pub fn addPathIfExists(tc: *Toolchain, components: []const []const u8, dest_kind: PathKind) !void { + var path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + var fib = std.heap.FixedBufferAllocator.init(&path_buf); + + const candidate = try std.fs.path.join(fib.allocator(), components); + + if (tc.filesystem.exists(candidate)) { + const duped = try tc.arena.dupe(u8, candidate); + const dest = switch (dest_kind) { + .library => &tc.library_paths, + .file => &tc.file_paths, + .program => &tc.program_paths, + }; + try dest.append(tc.driver.comp.gpa, duped); + } +} + +/// Join `components` using the toolchain arena and add the resulting path to `dest_kind`. Does not check +/// whether the path actually exists +pub fn addPathFromComponents(tc: *Toolchain, components: []const []const u8, dest_kind: PathKind) !void { + const full_path = try std.fs.path.join(tc.arena, components); + const dest = switch (dest_kind) { + .library => &tc.library_paths, + .file => &tc.file_paths, + .program => &tc.program_paths, + }; + try dest.append(tc.driver.comp.gpa, full_path); +} + +/// Add linker args to `argv`. Does not add path to linker executable as first item; that must be handled separately +/// Items added to `argv` will be string literals or owned by `tc.arena` so they must not be individually freed +pub fn buildLinkerArgs(tc: *Toolchain, argv: *std.ArrayList([]const u8)) !void { + return switch (tc.inner) { + .uninitialized => unreachable, + .linux => |*linux| linux.buildLinkerArgs(tc, argv), + .unknown => @panic("This toolchain does not support linking yet"), + }; +} + +fn getDefaultRuntimeLibKind(tc: *const Toolchain) RuntimeLibKind { + if (tc.getTarget().isAndroid()) { + return .compiler_rt; + } + return .libgcc; +} + +pub fn getRuntimeLibKind(tc: *const Toolchain) RuntimeLibKind { + const libname = tc.driver.rtlib orelse system_defaults.rtlib; + if (mem.eql(u8, libname, "compiler-rt")) + return .compiler_rt + else if (mem.eql(u8, libname, "libgcc")) + return .libgcc + else + return tc.getDefaultRuntimeLibKind(); +} + +/// TODO +pub fn getCompilerRt(tc: *const Toolchain, component: []const u8, file_kind: FileKind) ![]const u8 { + _ = file_kind; + _ = component; + _ = tc; + return ""; +} + +fn getLibGCCKind(tc: *const Toolchain) LibGCCKind { + const target = tc.getTarget(); + if (tc.driver.static_libgcc or tc.driver.static or tc.driver.static_pie or target.isAndroid()) { + return .static; + } + if (tc.driver.shared_libgcc) { + return .shared; + } + return .unspecified; +} + +fn getUnwindLibKind(tc: *const Toolchain) !UnwindLibKind { + const libname = tc.driver.unwindlib orelse system_defaults.unwindlib; + if (libname.len == 0 or mem.eql(u8, libname, "platform")) { + switch (tc.getRuntimeLibKind()) { + .compiler_rt => { + const target = tc.getTarget(); + if (target.isAndroid() or target.os.tag == .aix) { + return .compiler_rt; + } else { + return .none; + } + }, + .libgcc => return .libgcc, + } + } else if (mem.eql(u8, libname, "none")) { + return .none; + } else if (mem.eql(u8, libname, "libgcc")) { + return .libgcc; + } else if (mem.eql(u8, libname, "libunwind")) { + if (tc.getRuntimeLibKind() == .libgcc) { + try tc.driver.comp.diag.add(.{ .tag = .incompatible_unwindlib }, &.{}); + } + return .compiler_rt; + } else { + unreachable; + } +} + +fn getAsNeededOption(is_solaris: bool, needed: bool) []const u8 { + if (is_solaris) { + return if (needed) "-zignore" else "-zrecord"; + } else { + return if (needed) "--as-needed" else "--no-as-needed"; + } +} + +fn addUnwindLibrary(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !void { + const unw = try tc.getUnwindLibKind(); + const target = tc.getTarget(); + if ((target.isAndroid() and unw == .libgcc) or + target.os.tag == .elfiamcu or + target.ofmt == .wasm or + target_util.isWindowsMSVCEnvironment(target) or + unw == .none) return; + + const lgk = tc.getLibGCCKind(); + const as_needed = lgk == .unspecified and !target.isAndroid() and !target_util.isCygwinMinGW(target) and target.os.tag != .aix; + if (as_needed) { + try argv.append(getAsNeededOption(target.os.tag == .solaris, true)); + } + switch (unw) { + .none => return, + .libgcc => if (lgk == .static) try argv.append("-lgcc_eh") else try argv.append("-lgcc_s"), + .compiler_rt => if (target.os.tag == .aix) { + if (lgk != .static) { + try argv.append("-lunwind"); + } + } else if (lgk == .static) { + try argv.append("-l:libunwind.a"); + } else if (lgk == .shared) { + if (target_util.isCygwinMinGW(target)) { + try argv.append("-l:libunwind.dll.a"); + } else { + try argv.append("-l:libunwind.so"); + } + } else { + try argv.append("-lunwind"); + }, + } + + if (as_needed) { + try argv.append(getAsNeededOption(target.os.tag == .solaris, false)); + } +} + +fn addLibGCC(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !void { + const libgcc_kind = tc.getLibGCCKind(); + if (libgcc_kind == .static or libgcc_kind == .unspecified) { + try argv.append("-lgcc"); + } + try tc.addUnwindLibrary(argv); + if (libgcc_kind == .shared) { + try argv.append("-lgcc"); + } +} + +pub fn addRuntimeLibs(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !void { + const target = tc.getTarget(); + const rlt = tc.getRuntimeLibKind(); + switch (rlt) { + .compiler_rt => { + // TODO + }, + .libgcc => { + if (target_util.isKnownWindowsMSVCEnvironment(target)) { + const rtlib_str = tc.driver.rtlib orelse system_defaults.rtlib; + if (!mem.eql(u8, rtlib_str, "platform")) { + try tc.driver.comp.diag.add(.{ .tag = .unsupported_rtlib_gcc, .extra = .{ .str = "MSVC" } }, &.{}); + } + } else { + try tc.addLibGCC(argv); + } + }, + } + + if (target.isAndroid() and !tc.driver.static and !tc.driver.static_pie) { + try argv.append("-ldl"); + } +} diff --git a/deps/aro/Tree.zig b/deps/aro/Tree.zig new file mode 100644 index 000000000000..b9bda771e5a9 --- /dev/null +++ b/deps/aro/Tree.zig @@ -0,0 +1,1312 @@ +const std = @import("std"); +const Type = @import("Type.zig"); +const Tokenizer = @import("Tokenizer.zig"); +const Compilation = @import("Compilation.zig"); +const Source = @import("Source.zig"); +const Attribute = @import("Attribute.zig"); +const Value = @import("Value.zig"); +const StringInterner = @import("StringInterner.zig"); +const BuiltinFunction = @import("builtins/BuiltinFunction.zig"); + +const Tree = @This(); + +pub const Token = struct { + id: Id, + flags: packed struct { + expansion_disabled: bool = false, + is_macro_arg: bool = false, + } = .{}, + /// This location contains the actual token slice which might be generated. + /// If it is generated then there is guaranteed to be at least one + /// expansion location. + loc: Source.Location, + expansion_locs: ?[*]Source.Location = null, + + pub fn expansionSlice(tok: Token) []const Source.Location { + const locs = tok.expansion_locs orelse return &[0]Source.Location{}; + var i: usize = 0; + while (locs[i].id != .unused) : (i += 1) {} + return locs[0..i]; + } + + pub fn addExpansionLocation(tok: *Token, gpa: std.mem.Allocator, new: []const Source.Location) !void { + if (new.len == 0 or tok.id == .whitespace) return; + var list = std.ArrayList(Source.Location).init(gpa); + defer { + @memset(list.items.ptr[list.items.len..list.capacity], .{}); + // Add a sentinel to indicate the end of the list since + // the ArrayList's capacity isn't guaranteed to be exactly + // what we ask for. + if (list.capacity > 0) { + list.items.ptr[list.capacity - 1].byte_offset = 1; + } + tok.expansion_locs = list.items.ptr; + } + + if (tok.expansion_locs) |locs| { + var i: usize = 0; + while (locs[i].id != .unused) : (i += 1) {} + list.items = locs[0..i]; + while (locs[i].byte_offset != 1) : (i += 1) {} + list.capacity = i + 1; + } + + const min_len = @max(list.items.len + new.len + 1, 4); + const wanted_len = std.math.ceilPowerOfTwo(usize, min_len) catch + return error.OutOfMemory; + try list.ensureTotalCapacity(wanted_len); + + for (new) |new_loc| { + if (new_loc.id == .generated) continue; + list.appendAssumeCapacity(new_loc); + } + } + + pub fn free(expansion_locs: ?[*]Source.Location, gpa: std.mem.Allocator) void { + const locs = expansion_locs orelse return; + var i: usize = 0; + while (locs[i].id != .unused) : (i += 1) {} + while (locs[i].byte_offset != 1) : (i += 1) {} + gpa.free(locs[0 .. i + 1]); + } + + pub fn dupe(tok: Token, gpa: std.mem.Allocator) !Token { + var copy = tok; + copy.expansion_locs = null; + try copy.addExpansionLocation(gpa, tok.expansionSlice()); + return copy; + } + + pub const List = std.MultiArrayList(Token); + pub const Id = Tokenizer.Token.Id; +}; + +pub const TokenIndex = u32; +pub const NodeIndex = enum(u32) { none, _ }; +pub const ValueMap = std.AutoHashMap(NodeIndex, Value); + +comp: *Compilation, +arena: std.heap.ArenaAllocator, +generated: []const u8, +tokens: Token.List.Slice, +nodes: Node.List.Slice, +data: []const NodeIndex, +root_decls: []const NodeIndex, +strings: []const u8, +value_map: ValueMap, + +pub fn deinit(tree: *Tree) void { + tree.comp.gpa.free(tree.root_decls); + tree.comp.gpa.free(tree.data); + tree.comp.gpa.free(tree.strings); + tree.nodes.deinit(tree.comp.gpa); + tree.arena.deinit(); + tree.value_map.deinit(); +} + +pub const GNUAssemblyQualifiers = struct { + @"volatile": bool = false, + @"inline": bool = false, + goto: bool = false, +}; + +pub const Node = struct { + tag: Tag, + ty: Type = .{ .specifier = .void }, + data: Data, + + pub const Range = struct { start: u32, end: u32 }; + + pub const Data = union { + decl: struct { + name: TokenIndex, + node: NodeIndex = .none, + }, + decl_ref: TokenIndex, + range: Range, + if3: struct { + cond: NodeIndex, + body: u32, + }, + un: NodeIndex, + bin: struct { + lhs: NodeIndex, + rhs: NodeIndex, + }, + member: struct { + lhs: NodeIndex, + index: u32, + }, + union_init: struct { + field_index: u32, + node: NodeIndex, + }, + cast: struct { + operand: NodeIndex, + kind: CastKind, + }, + int: u64, + return_zero: bool, + + pub fn forDecl(data: Data, tree: Tree) struct { + decls: []const NodeIndex, + cond: NodeIndex, + incr: NodeIndex, + body: NodeIndex, + } { + const items = tree.data[data.range.start..data.range.end]; + const decls = items[0 .. items.len - 3]; + + return .{ + .decls = decls, + .cond = items[items.len - 3], + .incr = items[items.len - 2], + .body = items[items.len - 1], + }; + } + + pub fn forStmt(data: Data, tree: Tree) struct { + init: NodeIndex, + cond: NodeIndex, + incr: NodeIndex, + body: NodeIndex, + } { + const items = tree.data[data.if3.body..]; + + return .{ + .init = items[0], + .cond = items[1], + .incr = items[2], + .body = data.if3.cond, + }; + } + }; + + pub const List = std.MultiArrayList(Node); +}; + +pub const CastKind = enum(u8) { + /// Does nothing except possibly add qualifiers + no_op, + /// Interpret one bit pattern as another. Used for operands which have the same + /// size and unrelated types, e.g. casting one pointer type to another + bitcast, + /// Convert T[] to T * + array_to_pointer, + /// Converts an lvalue to an rvalue + lval_to_rval, + /// Convert a function type to a pointer to a function + function_to_pointer, + /// Convert a pointer type to a _Bool + pointer_to_bool, + /// Convert a pointer type to an integer type + pointer_to_int, + /// Convert _Bool to an integer type + bool_to_int, + /// Convert _Bool to a floating type + bool_to_float, + /// Convert a _Bool to a pointer; will cause a warning + bool_to_pointer, + /// Convert an integer type to _Bool + int_to_bool, + /// Convert an integer to a floating type + int_to_float, + /// Convert a complex integer to a complex floating type + complex_int_to_complex_float, + /// Convert an integer type to a pointer type + int_to_pointer, + /// Convert a floating type to a _Bool + float_to_bool, + /// Convert a floating type to an integer + float_to_int, + /// Convert a complex floating type to a complex integer + complex_float_to_complex_int, + /// Convert one integer type to another + int_cast, + /// Convert one complex integer type to another + complex_int_cast, + /// Convert real part of complex integer to a integer + complex_int_to_real, + /// Create a complex integer type using operand as the real part + real_to_complex_int, + /// Convert one floating type to another + float_cast, + /// Convert one complex floating type to another + complex_float_cast, + /// Convert real part of complex float to a float + complex_float_to_real, + /// Create a complex floating type using operand as the real part + real_to_complex_float, + /// Convert type to void + to_void, + /// Convert a literal 0 to a null pointer + null_to_pointer, + /// GNU cast-to-union extension + union_cast, + /// Create vector where each value is same as the input scalar. + vector_splat, +}; + +pub const Tag = enum(u8) { + /// Must appear at index 0. Also used as the tag for __builtin_types_compatible_p arguments, since the arguments are types + /// Reaching it is always the result of a bug. + invalid, + + // ====== Decl ====== + + // _Static_assert + static_assert, + + // function prototype + fn_proto, + static_fn_proto, + inline_fn_proto, + inline_static_fn_proto, + + // function definition + fn_def, + static_fn_def, + inline_fn_def, + inline_static_fn_def, + + // variable declaration + @"var", + extern_var, + static_var, + // same as static_var, used for __func__, __FUNCTION__ and __PRETTY_FUNCTION__ + implicit_static_var, + threadlocal_var, + threadlocal_extern_var, + threadlocal_static_var, + + /// __asm__("...") at file scope + file_scope_asm, + + // typedef declaration + typedef, + + // container declarations + /// { lhs; rhs; } + struct_decl_two, + /// { lhs; rhs; } + union_decl_two, + /// { lhs, rhs, } + enum_decl_two, + /// { range } + struct_decl, + /// { range } + union_decl, + /// { range } + enum_decl, + /// struct decl_ref; + struct_forward_decl, + /// union decl_ref; + union_forward_decl, + /// enum decl_ref; + enum_forward_decl, + + /// name = node + enum_field_decl, + /// ty name : node + /// name == 0 means unnamed + record_field_decl, + /// Used when a record has an unnamed record as a field + indirect_record_field_decl, + + // ====== Stmt ====== + + labeled_stmt, + /// { first; second; } first and second may be null + compound_stmt_two, + /// { data } + compound_stmt, + /// if (first) data[second] else data[second+1]; + if_then_else_stmt, + /// if (first) second; second may be null + if_then_stmt, + /// switch (first) second + switch_stmt, + /// case first: second + case_stmt, + /// case data[body]...data[body+1]: cond + case_range_stmt, + /// default: first + default_stmt, + /// while (first) second + while_stmt, + /// do second while(first); + do_while_stmt, + /// for (data[..]; data[len-3]; data[len-2]) data[len-1] + for_decl_stmt, + /// for (;;;) first + forever_stmt, + /// for (data[first]; data[first+1]; data[first+2]) second + for_stmt, + /// goto first; + goto_stmt, + /// goto *un; + computed_goto_stmt, + // continue; first and second unused + continue_stmt, + // break; first and second unused + break_stmt, + // null statement (just a semicolon); first and second unused + null_stmt, + /// return first; first may be null + return_stmt, + /// Assembly statement of the form __asm__("string literal") + gnu_asm_simple, + + // ====== Expr ====== + + /// lhs , rhs + comma_expr, + /// lhs ? data[0] : data[1] + binary_cond_expr, + /// Used as the base for casts of the lhs in `binary_cond_expr`. + cond_dummy_expr, + /// lhs ? data[0] : data[1] + cond_expr, + /// lhs = rhs + assign_expr, + /// lhs *= rhs + mul_assign_expr, + /// lhs /= rhs + div_assign_expr, + /// lhs %= rhs + mod_assign_expr, + /// lhs += rhs + add_assign_expr, + /// lhs -= rhs + sub_assign_expr, + /// lhs <<= rhs + shl_assign_expr, + /// lhs >>= rhs + shr_assign_expr, + /// lhs &= rhs + bit_and_assign_expr, + /// lhs ^= rhs + bit_xor_assign_expr, + /// lhs |= rhs + bit_or_assign_expr, + /// lhs || rhs + bool_or_expr, + /// lhs && rhs + bool_and_expr, + /// lhs | rhs + bit_or_expr, + /// lhs ^ rhs + bit_xor_expr, + /// lhs & rhs + bit_and_expr, + /// lhs == rhs + equal_expr, + /// lhs != rhs + not_equal_expr, + /// lhs < rhs + less_than_expr, + /// lhs <= rhs + less_than_equal_expr, + /// lhs > rhs + greater_than_expr, + /// lhs >= rhs + greater_than_equal_expr, + /// lhs << rhs + shl_expr, + /// lhs >> rhs + shr_expr, + /// lhs + rhs + add_expr, + /// lhs - rhs + sub_expr, + /// lhs * rhs + mul_expr, + /// lhs / rhs + div_expr, + /// lhs % rhs + mod_expr, + /// Explicit: (type) cast + explicit_cast, + /// Implicit: cast + implicit_cast, + /// &un + addr_of_expr, + /// &&decl_ref + addr_of_label, + /// *un + deref_expr, + /// +un + plus_expr, + /// -un + negate_expr, + /// ~un + bit_not_expr, + /// !un + bool_not_expr, + /// ++un + pre_inc_expr, + /// --un + pre_dec_expr, + /// __imag un + imag_expr, + /// __real un + real_expr, + /// lhs[rhs] lhs is pointer/array type, rhs is integer type + array_access_expr, + /// first(second) second may be 0 + call_expr_one, + /// data[0](data[1..]) + call_expr, + /// decl + builtin_call_expr_one, + builtin_call_expr, + /// lhs.member + member_access_expr, + /// lhs->member + member_access_ptr_expr, + /// un++ + post_inc_expr, + /// un-- + post_dec_expr, + /// (un) + paren_expr, + /// decl_ref + decl_ref_expr, + /// decl_ref + enumeration_ref, + /// C23 bool literal `true` / `false` + bool_literal, + /// C23 nullptr literal + nullptr_literal, + /// integer literal, always unsigned + int_literal, + /// Same as int_literal, but originates from a char literal + char_literal, + /// _Float16 literal + float16_literal, + /// f32 literal + float_literal, + /// f64 literal + double_literal, + /// wraps a float or double literal: un + imaginary_literal, + /// tree.str[index..][0..len] + string_literal_expr, + /// sizeof(un?) + sizeof_expr, + /// _Alignof(un?) + alignof_expr, + /// _Generic(controlling lhs, chosen rhs) + generic_expr_one, + /// _Generic(controlling range[0], chosen range[1], rest range[2..]) + generic_expr, + /// ty: un + generic_association_expr, + // default: un + generic_default_expr, + /// __builtin_choose_expr(lhs, data[0], data[1]) + builtin_choose_expr, + /// __builtin_types_compatible_p(lhs, rhs) + builtin_types_compatible_p, + /// decl - special builtins require custom parsing + special_builtin_call_one, + /// ({ un }) + stmt_expr, + + // ====== Initializer expressions ====== + + /// { lhs, rhs } + array_init_expr_two, + /// { range } + array_init_expr, + /// { lhs, rhs } + struct_init_expr_two, + /// { range } + struct_init_expr, + /// { union_init } + union_init_expr, + /// (ty){ un } + compound_literal_expr, + + /// Inserted at the end of a function body if no return stmt is found. + /// ty is the functions return type + /// data is return_zero which is true if the function is called "main" and ty is compatible with int + implicit_return, + + /// Inserted in array_init_expr to represent unspecified elements. + /// data.int contains the amount of elements. + array_filler_expr, + /// Inserted in record and scalar initializers for unspecified elements. + default_init_expr, + + pub fn isImplicit(tag: Tag) bool { + return switch (tag) { + .implicit_cast, + .implicit_return, + .array_filler_expr, + .default_init_expr, + .implicit_static_var, + .cond_dummy_expr, + => true, + else => false, + }; + } +}; + +pub fn isBitfield(nodes: Node.List.Slice, node: NodeIndex) bool { + return bitfieldWidth(nodes, node, false) != null; +} + +/// Returns null if node is not a bitfield. If inspect_lval is true, this function will +/// recurse into implicit lval_to_rval casts (useful for arithmetic conversions) +pub fn bitfieldWidth(nodes: Node.List.Slice, node: NodeIndex, inspect_lval: bool) ?u32 { + if (node == .none) return null; + switch (nodes.items(.tag)[@intFromEnum(node)]) { + .member_access_expr, .member_access_ptr_expr => { + const member = nodes.items(.data)[@intFromEnum(node)].member; + var ty = nodes.items(.ty)[@intFromEnum(member.lhs)]; + if (ty.isPtr()) ty = ty.elemType(); + const record_ty = ty.get(.@"struct") orelse ty.get(.@"union") orelse return null; + const field = record_ty.data.record.fields[member.index]; + return field.bit_width; + }, + .implicit_cast => { + if (!inspect_lval) return null; + + const data = nodes.items(.data)[@intFromEnum(node)]; + return switch (data.cast.kind) { + .lval_to_rval => bitfieldWidth(nodes, data.cast.operand, false), + else => null, + }; + }, + else => return null, + } +} + +pub fn isLval(nodes: Node.List.Slice, extra: []const NodeIndex, value_map: ValueMap, node: NodeIndex) bool { + var is_const: bool = undefined; + return isLvalExtra(nodes, extra, value_map, node, &is_const); +} + +pub fn isLvalExtra(nodes: Node.List.Slice, extra: []const NodeIndex, value_map: ValueMap, node: NodeIndex, is_const: *bool) bool { + is_const.* = false; + switch (nodes.items(.tag)[@intFromEnum(node)]) { + .compound_literal_expr => { + is_const.* = nodes.items(.ty)[@intFromEnum(node)].isConst(); + return true; + }, + .string_literal_expr => return true, + .member_access_ptr_expr => { + const lhs_expr = nodes.items(.data)[@intFromEnum(node)].member.lhs; + const ptr_ty = nodes.items(.ty)[@intFromEnum(lhs_expr)]; + if (ptr_ty.isPtr()) is_const.* = ptr_ty.elemType().isConst(); + return true; + }, + .array_access_expr => { + const lhs_expr = nodes.items(.data)[@intFromEnum(node)].bin.lhs; + if (lhs_expr != .none) { + const array_ty = nodes.items(.ty)[@intFromEnum(lhs_expr)]; + if (array_ty.isPtr() or array_ty.isArray()) is_const.* = array_ty.elemType().isConst(); + } + return true; + }, + .decl_ref_expr => { + const decl_ty = nodes.items(.ty)[@intFromEnum(node)]; + is_const.* = decl_ty.isConst(); + return true; + }, + .deref_expr => { + const data = nodes.items(.data)[@intFromEnum(node)]; + const operand_ty = nodes.items(.ty)[@intFromEnum(data.un)]; + if (operand_ty.isFunc()) return false; + if (operand_ty.isPtr() or operand_ty.isArray()) is_const.* = operand_ty.elemType().isConst(); + return true; + }, + .member_access_expr => { + const data = nodes.items(.data)[@intFromEnum(node)]; + return isLvalExtra(nodes, extra, value_map, data.member.lhs, is_const); + }, + .paren_expr => { + const data = nodes.items(.data)[@intFromEnum(node)]; + return isLvalExtra(nodes, extra, value_map, data.un, is_const); + }, + .builtin_choose_expr => { + const data = nodes.items(.data)[@intFromEnum(node)]; + + if (value_map.get(data.if3.cond)) |val| { + const offset = @intFromBool(val.isZero()); + return isLvalExtra(nodes, extra, value_map, extra[data.if3.body + offset], is_const); + } + return false; + }, + else => return false, + } +} + +pub fn dumpStr(retained_strings: []const u8, range: Value.ByteRange, tag: Tag, writer: anytype) !void { + switch (tag) { + .string_literal_expr => { + const lit_range = range.trim(1); // remove null-terminator + const str = lit_range.slice(retained_strings); + try writer.print("\"{}\"", .{std.zig.fmtEscapes(str)}); + }, + else => unreachable, + } +} + +pub fn tokSlice(tree: Tree, tok_i: TokenIndex) []const u8 { + if (tree.tokens.items(.id)[tok_i].lexeme()) |some| return some; + const loc = tree.tokens.items(.loc)[tok_i]; + var tmp_tokenizer = Tokenizer{ + .buf = tree.comp.getSource(loc.id).buf, + .comp = tree.comp, + .index = loc.byte_offset, + .source = .generated, + }; + const tok = tmp_tokenizer.next(); + return tmp_tokenizer.buf[tok.start..tok.end]; +} + +pub fn dump(tree: Tree, color: bool, writer: anytype) @TypeOf(writer).Error!void { + const mapper = tree.comp.string_interner.getFastTypeMapper(tree.comp.gpa) catch tree.comp.string_interner.getSlowTypeMapper(); + defer mapper.deinit(tree.comp.gpa); + + for (tree.root_decls) |i| { + try tree.dumpNode(i, 0, mapper, color, writer); + try writer.writeByte('\n'); + } +} + +fn dumpFieldAttributes(attributes: []const Attribute, level: u32, strings: []const u8, writer: anytype) !void { + for (attributes) |attr| { + try writer.writeByteNTimes(' ', level); + try writer.print("field attr: {s}", .{@tagName(attr.tag)}); + try dumpAttribute(attr, strings, writer); + } +} + +fn dumpAttribute(attr: Attribute, strings: []const u8, writer: anytype) !void { + switch (attr.tag) { + inline else => |tag| { + const args = @field(attr.args, @tagName(tag)); + if (@TypeOf(args) == void) { + try writer.writeByte('\n'); + return; + } + try writer.writeByte(' '); + inline for (@typeInfo(@TypeOf(args)).Struct.fields, 0..) |f, i| { + if (comptime std.mem.eql(u8, f.name, "__name_tok")) continue; + if (i != 0) { + try writer.writeAll(", "); + } + try writer.writeAll(f.name); + try writer.writeAll(": "); + switch (f.type) { + Value.ByteRange => try writer.print("\"{s}\"", .{@field(args, f.name).slice(strings)}), + ?Value.ByteRange => try writer.print("\"{?s}\"", .{if (@field(args, f.name)) |range| range.slice(strings) else null}), + else => switch (@typeInfo(f.type)) { + .Enum => try writer.writeAll(@tagName(@field(args, f.name))), + else => try writer.print("{any}", .{@field(args, f.name)}), + }, + } + } + try writer.writeByte('\n'); + return; + }, + } +} + +fn dumpNode(tree: Tree, node: NodeIndex, level: u32, mapper: StringInterner.TypeMapper, color: bool, w: anytype) @TypeOf(w).Error!void { + const delta = 2; + const half = delta / 2; + const util = @import("util.zig"); + const TYPE = util.Color.purple; + const TAG = util.Color.cyan; + const IMPLICIT = util.Color.blue; + const NAME = util.Color.red; + const LITERAL = util.Color.green; + const ATTRIBUTE = util.Color.yellow; + std.debug.assert(node != .none); + + const tag = tree.nodes.items(.tag)[@intFromEnum(node)]; + const data = tree.nodes.items(.data)[@intFromEnum(node)]; + const ty = tree.nodes.items(.ty)[@intFromEnum(node)]; + try w.writeByteNTimes(' ', level); + + if (color) util.setColor(if (tag.isImplicit()) IMPLICIT else TAG, w); + try w.print("{s}: ", .{@tagName(tag)}); + if (tag == .implicit_cast or tag == .explicit_cast) { + if (color) util.setColor(.white, w); + try w.print("({s}) ", .{@tagName(data.cast.kind)}); + } + if (color) util.setColor(TYPE, w); + try w.writeByte('\''); + try ty.dump(mapper, tree.comp.langopts, w); + try w.writeByte('\''); + + if (isLval(tree.nodes, tree.data, tree.value_map, node)) { + if (color) util.setColor(ATTRIBUTE, w); + try w.writeAll(" lvalue"); + } + if (isBitfield(tree.nodes, node)) { + if (color) util.setColor(ATTRIBUTE, w); + try w.writeAll(" bitfield"); + } + if (tree.value_map.get(node)) |val| { + if (color) util.setColor(LITERAL, w); + try w.writeAll(" (value: "); + try val.dump(ty, tree.comp, tree.strings, w); + try w.writeByte(')'); + } + if (tag == .implicit_return and data.return_zero) { + if (color) util.setColor(IMPLICIT, w); + try w.writeAll(" (value: 0)"); + if (color) util.setColor(.reset, w); + } + + try w.writeAll("\n"); + if (color) util.setColor(.reset, w); + + if (ty.specifier == .attributed) { + if (color) util.setColor(ATTRIBUTE, w); + for (ty.data.attributed.attributes) |attr| { + try w.writeByteNTimes(' ', level + half); + try w.print("attr: {s}", .{@tagName(attr.tag)}); + try dumpAttribute(attr, tree.strings, w); + } + if (color) util.setColor(.reset, w); + } + + switch (tag) { + .invalid => unreachable, + .file_scope_asm => { + try w.writeByteNTimes(' ', level + 1); + try tree.dumpNode(data.decl.node, level + delta, mapper, color, w); + }, + .gnu_asm_simple => { + try w.writeByteNTimes(' ', level); + try tree.dumpNode(data.un, level, mapper, color, w); + }, + .static_assert => { + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("condition:\n"); + try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w); + if (data.bin.rhs != .none) { + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("diagnostic:\n"); + try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w); + } + }, + .fn_proto, + .static_fn_proto, + .inline_fn_proto, + .inline_static_fn_proto, + => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("name: "); + if (color) util.setColor(NAME, w); + try w.print("{s}\n", .{tree.tokSlice(data.decl.name)}); + if (color) util.setColor(.reset, w); + }, + .fn_def, + .static_fn_def, + .inline_fn_def, + .inline_static_fn_def, + => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("name: "); + if (color) util.setColor(NAME, w); + try w.print("{s}\n", .{tree.tokSlice(data.decl.name)}); + if (color) util.setColor(.reset, w); + try w.writeByteNTimes(' ', level + half); + try w.writeAll("body:\n"); + try tree.dumpNode(data.decl.node, level + delta, mapper, color, w); + }, + .typedef, + .@"var", + .extern_var, + .static_var, + .implicit_static_var, + .threadlocal_var, + .threadlocal_extern_var, + .threadlocal_static_var, + => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("name: "); + if (color) util.setColor(NAME, w); + try w.print("{s}\n", .{tree.tokSlice(data.decl.name)}); + if (color) util.setColor(.reset, w); + if (data.decl.node != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("init:\n"); + try tree.dumpNode(data.decl.node, level + delta, mapper, color, w); + } + }, + .enum_field_decl => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("name: "); + if (color) util.setColor(NAME, w); + try w.print("{s}\n", .{tree.tokSlice(data.decl.name)}); + if (color) util.setColor(.reset, w); + if (data.decl.node != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("value:\n"); + try tree.dumpNode(data.decl.node, level + delta, mapper, color, w); + } + }, + .record_field_decl => { + if (data.decl.name != 0) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("name: "); + if (color) util.setColor(NAME, w); + try w.print("{s}\n", .{tree.tokSlice(data.decl.name)}); + if (color) util.setColor(.reset, w); + } + if (data.decl.node != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("bits:\n"); + try tree.dumpNode(data.decl.node, level + delta, mapper, color, w); + } + }, + .indirect_record_field_decl => {}, + .compound_stmt, + .array_init_expr, + .struct_init_expr, + .enum_decl, + .struct_decl, + .union_decl, + => { + const maybe_field_attributes = if (ty.getRecord()) |record| record.field_attributes else null; + for (tree.data[data.range.start..data.range.end], 0..) |stmt, i| { + if (i != 0) try w.writeByte('\n'); + try tree.dumpNode(stmt, level + delta, mapper, color, w); + if (maybe_field_attributes) |field_attributes| { + if (field_attributes[i].len == 0) continue; + + if (color) util.setColor(ATTRIBUTE, w); + try dumpFieldAttributes(field_attributes[i], level + delta + half, tree.strings, w); + if (color) util.setColor(.reset, w); + } + } + }, + .compound_stmt_two, + .array_init_expr_two, + .struct_init_expr_two, + .enum_decl_two, + .struct_decl_two, + .union_decl_two, + => { + var attr_array = [2][]const Attribute{ &.{}, &.{} }; + const empty: [][]const Attribute = &attr_array; + const field_attributes = if (ty.getRecord()) |record| (record.field_attributes orelse empty.ptr) else empty.ptr; + if (data.bin.lhs != .none) { + try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w); + if (field_attributes[0].len > 0) { + if (color) util.setColor(ATTRIBUTE, w); + try dumpFieldAttributes(field_attributes[0], level + delta + half, tree.strings, w); + if (color) util.setColor(.reset, w); + } + } + if (data.bin.rhs != .none) { + try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w); + if (field_attributes[1].len > 0) { + if (color) util.setColor(ATTRIBUTE, w); + try dumpFieldAttributes(field_attributes[1], level + delta + half, tree.strings, w); + if (color) util.setColor(.reset, w); + } + } + }, + .union_init_expr => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("field index: "); + if (color) util.setColor(LITERAL, w); + try w.print("{d}\n", .{data.union_init.field_index}); + if (color) util.setColor(.reset, w); + if (data.union_init.node != .none) { + try tree.dumpNode(data.union_init.node, level + delta, mapper, color, w); + } + }, + .compound_literal_expr => { + try tree.dumpNode(data.un, level + half, mapper, color, w); + }, + .labeled_stmt => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("label: "); + if (color) util.setColor(LITERAL, w); + try w.print("{s}\n", .{tree.tokSlice(data.decl.name)}); + if (color) util.setColor(.reset, w); + if (data.decl.node != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("stmt:\n"); + try tree.dumpNode(data.decl.node, level + delta, mapper, color, w); + } + }, + .case_stmt => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("value:\n"); + try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w); + if (data.bin.rhs != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("stmt:\n"); + try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w); + } + }, + .case_range_stmt => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("range start:\n"); + try tree.dumpNode(tree.data[data.if3.body], level + delta, mapper, color, w); + + try w.writeByteNTimes(' ', level + half); + try w.writeAll("range end:\n"); + try tree.dumpNode(tree.data[data.if3.body + 1], level + delta, mapper, color, w); + + if (data.if3.cond != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("stmt:\n"); + try tree.dumpNode(data.if3.cond, level + delta, mapper, color, w); + } + }, + .default_stmt => { + if (data.un != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("stmt:\n"); + try tree.dumpNode(data.un, level + delta, mapper, color, w); + } + }, + .binary_cond_expr, .cond_expr, .if_then_else_stmt, .builtin_choose_expr => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("cond:\n"); + try tree.dumpNode(data.if3.cond, level + delta, mapper, color, w); + + try w.writeByteNTimes(' ', level + half); + try w.writeAll("then:\n"); + try tree.dumpNode(tree.data[data.if3.body], level + delta, mapper, color, w); + + try w.writeByteNTimes(' ', level + half); + try w.writeAll("else:\n"); + try tree.dumpNode(tree.data[data.if3.body + 1], level + delta, mapper, color, w); + }, + .builtin_types_compatible_p => { + std.debug.assert(tree.nodes.items(.tag)[@intFromEnum(data.bin.lhs)] == .invalid); + std.debug.assert(tree.nodes.items(.tag)[@intFromEnum(data.bin.rhs)] == .invalid); + + try w.writeByteNTimes(' ', level + half); + try w.writeAll("lhs: "); + + const lhs_ty = tree.nodes.items(.ty)[@intFromEnum(data.bin.lhs)]; + if (color) util.setColor(TYPE, w); + try lhs_ty.dump(mapper, tree.comp.langopts, w); + if (color) util.setColor(.reset, w); + try w.writeByte('\n'); + + try w.writeByteNTimes(' ', level + half); + try w.writeAll("rhs: "); + + const rhs_ty = tree.nodes.items(.ty)[@intFromEnum(data.bin.rhs)]; + if (color) util.setColor(TYPE, w); + try rhs_ty.dump(mapper, tree.comp.langopts, w); + if (color) util.setColor(.reset, w); + try w.writeByte('\n'); + }, + .if_then_stmt => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("cond:\n"); + try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w); + + if (data.bin.rhs != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("then:\n"); + try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w); + } + }, + .switch_stmt, .while_stmt, .do_while_stmt => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("cond:\n"); + try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w); + + if (data.bin.rhs != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("body:\n"); + try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w); + } + }, + .for_decl_stmt => { + const for_decl = data.forDecl(tree); + + try w.writeByteNTimes(' ', level + half); + try w.writeAll("decl:\n"); + for (for_decl.decls) |decl| { + try tree.dumpNode(decl, level + delta, mapper, color, w); + try w.writeByte('\n'); + } + if (for_decl.cond != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("cond:\n"); + try tree.dumpNode(for_decl.cond, level + delta, mapper, color, w); + } + if (for_decl.incr != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("incr:\n"); + try tree.dumpNode(for_decl.incr, level + delta, mapper, color, w); + } + if (for_decl.body != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("body:\n"); + try tree.dumpNode(for_decl.body, level + delta, mapper, color, w); + } + }, + .forever_stmt => { + if (data.un != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("body:\n"); + try tree.dumpNode(data.un, level + delta, mapper, color, w); + } + }, + .for_stmt => { + const for_stmt = data.forStmt(tree); + + if (for_stmt.init != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("init:\n"); + try tree.dumpNode(for_stmt.init, level + delta, mapper, color, w); + } + if (for_stmt.cond != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("cond:\n"); + try tree.dumpNode(for_stmt.cond, level + delta, mapper, color, w); + } + if (for_stmt.incr != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("incr:\n"); + try tree.dumpNode(for_stmt.incr, level + delta, mapper, color, w); + } + if (for_stmt.body != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("body:\n"); + try tree.dumpNode(for_stmt.body, level + delta, mapper, color, w); + } + }, + .goto_stmt, .addr_of_label => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("label: "); + if (color) util.setColor(LITERAL, w); + try w.print("{s}\n", .{tree.tokSlice(data.decl_ref)}); + if (color) util.setColor(.reset, w); + }, + .continue_stmt, .break_stmt, .implicit_return, .null_stmt => {}, + .return_stmt => { + if (data.un != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("expr:\n"); + try tree.dumpNode(data.un, level + delta, mapper, color, w); + } + }, + .call_expr => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("lhs:\n"); + try tree.dumpNode(tree.data[data.range.start], level + delta, mapper, color, w); + + try w.writeByteNTimes(' ', level + half); + try w.writeAll("args:\n"); + for (tree.data[data.range.start + 1 .. data.range.end]) |arg| try tree.dumpNode(arg, level + delta, mapper, color, w); + }, + .call_expr_one => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("lhs:\n"); + try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w); + if (data.bin.rhs != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("arg:\n"); + try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w); + } + }, + .builtin_call_expr => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("name: "); + if (color) util.setColor(NAME, w); + try w.print("{s}\n", .{tree.tokSlice(@intFromEnum(tree.data[data.range.start]))}); + if (color) util.setColor(.reset, w); + + try w.writeByteNTimes(' ', level + half); + try w.writeAll("args:\n"); + for (tree.data[data.range.start + 1 .. data.range.end]) |arg| try tree.dumpNode(arg, level + delta, mapper, color, w); + }, + .builtin_call_expr_one => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("name: "); + if (color) util.setColor(NAME, w); + try w.print("{s}\n", .{tree.tokSlice(data.decl.name)}); + if (color) util.setColor(.reset, w); + if (data.decl.node != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("arg:\n"); + try tree.dumpNode(data.decl.node, level + delta, mapper, color, w); + } + }, + .special_builtin_call_one => { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("name: "); + if (color) util.setColor(NAME, w); + try w.print("{s}\n", .{tree.tokSlice(data.decl.name)}); + if (color) util.setColor(.reset, w); + if (data.decl.node != .none) { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("arg:\n"); + try tree.dumpNode(data.decl.node, level + delta, mapper, color, w); + } + }, + .comma_expr, + .assign_expr, + .mul_assign_expr, + .div_assign_expr, + .mod_assign_expr, + .add_assign_expr, + .sub_assign_expr, + .shl_assign_expr, + .shr_assign_expr, + .bit_and_assign_expr, + .bit_xor_assign_expr, + .bit_or_assign_expr, + .bool_or_expr, + .bool_and_expr, + .bit_or_expr, + .bit_xor_expr, + .bit_and_expr, + .equal_expr, + .not_equal_expr, + .less_than_expr, + .less_than_equal_expr, + .greater_than_expr, + .greater_than_equal_expr, + .shl_expr, + .shr_expr, + .add_expr, + .sub_expr, + .mul_expr, + .div_expr, + .mod_expr, + => { + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("lhs:\n"); + try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w); + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("rhs:\n"); + try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w); + }, + .explicit_cast, .implicit_cast => try tree.dumpNode(data.cast.operand, level + delta, mapper, color, w), + .addr_of_expr, + .computed_goto_stmt, + .deref_expr, + .plus_expr, + .negate_expr, + .bit_not_expr, + .bool_not_expr, + .pre_inc_expr, + .pre_dec_expr, + .imag_expr, + .real_expr, + .post_inc_expr, + .post_dec_expr, + .paren_expr, + => { + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("operand:\n"); + try tree.dumpNode(data.un, level + delta, mapper, color, w); + }, + .decl_ref_expr => { + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("name: "); + if (color) util.setColor(NAME, w); + try w.print("{s}\n", .{tree.tokSlice(data.decl_ref)}); + if (color) util.setColor(.reset, w); + }, + .enumeration_ref => { + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("name: "); + if (color) util.setColor(NAME, w); + try w.print("{s}\n", .{tree.tokSlice(data.decl_ref)}); + if (color) util.setColor(.reset, w); + }, + .bool_literal, + .nullptr_literal, + .int_literal, + .char_literal, + .float16_literal, + .float_literal, + .double_literal, + .string_literal_expr, + => {}, + .member_access_expr, .member_access_ptr_expr => { + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("lhs:\n"); + try tree.dumpNode(data.member.lhs, level + delta, mapper, color, w); + + var lhs_ty = tree.nodes.items(.ty)[@intFromEnum(data.member.lhs)]; + if (lhs_ty.isPtr()) lhs_ty = lhs_ty.elemType(); + lhs_ty = lhs_ty.canonicalize(.standard); + + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("name: "); + if (color) util.setColor(NAME, w); + try w.print("{s}\n", .{mapper.lookup(lhs_ty.data.record.fields[data.member.index].name)}); + if (color) util.setColor(.reset, w); + }, + .array_access_expr => { + if (data.bin.lhs != .none) { + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("lhs:\n"); + try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w); + } + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("index:\n"); + try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w); + }, + .sizeof_expr, .alignof_expr => { + if (data.un != .none) { + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("expr:\n"); + try tree.dumpNode(data.un, level + delta, mapper, color, w); + } + }, + .generic_expr_one => { + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("controlling:\n"); + try tree.dumpNode(data.bin.lhs, level + delta, mapper, color, w); + try w.writeByteNTimes(' ', level + 1); + if (data.bin.rhs != .none) { + try w.writeAll("chosen:\n"); + try tree.dumpNode(data.bin.rhs, level + delta, mapper, color, w); + } + }, + .generic_expr => { + const nodes = tree.data[data.range.start..data.range.end]; + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("controlling:\n"); + try tree.dumpNode(nodes[0], level + delta, mapper, color, w); + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("chosen:\n"); + try tree.dumpNode(nodes[1], level + delta, mapper, color, w); + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("rest:\n"); + for (nodes[2..]) |expr| { + try tree.dumpNode(expr, level + delta, mapper, color, w); + } + }, + .generic_association_expr, .generic_default_expr, .stmt_expr, .imaginary_literal => { + try tree.dumpNode(data.un, level + delta, mapper, color, w); + }, + .array_filler_expr => { + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("count: "); + if (color) util.setColor(LITERAL, w); + try w.print("{d}\n", .{data.int}); + if (color) util.setColor(.reset, w); + }, + .struct_forward_decl, + .union_forward_decl, + .enum_forward_decl, + .default_init_expr, + .cond_dummy_expr, + => {}, + } +} diff --git a/deps/aro/Type.zig b/deps/aro/Type.zig new file mode 100644 index 000000000000..805f6aaa9eaf --- /dev/null +++ b/deps/aro/Type.zig @@ -0,0 +1,2692 @@ +const std = @import("std"); +const Tree = @import("Tree.zig"); +const TokenIndex = Tree.TokenIndex; +const NodeIndex = Tree.NodeIndex; +const Parser = @import("Parser.zig"); +const Compilation = @import("Compilation.zig"); +const Attribute = @import("Attribute.zig"); +const StringInterner = @import("StringInterner.zig"); +const StringId = StringInterner.StringId; +const target_util = @import("target.zig"); +const LangOpts = @import("LangOpts.zig"); +const BuiltinFunction = @import("builtins/BuiltinFunction.zig"); + +const Type = @This(); + +pub const Qualifiers = packed struct { + @"const": bool = false, + atomic: bool = false, + @"volatile": bool = false, + restrict: bool = false, + + // for function parameters only, stored here since it fits in the padding + register: bool = false, + + pub fn any(quals: Qualifiers) bool { + return quals.@"const" or quals.restrict or quals.@"volatile" or quals.atomic; + } + + pub fn dump(quals: Qualifiers, w: anytype) !void { + if (quals.@"const") try w.writeAll("const "); + if (quals.atomic) try w.writeAll("_Atomic "); + if (quals.@"volatile") try w.writeAll("volatile "); + if (quals.restrict) try w.writeAll("restrict "); + if (quals.register) try w.writeAll("register "); + } + + /// Merge the const/volatile qualifiers, used by type resolution + /// of the conditional operator + pub fn mergeCV(a: Qualifiers, b: Qualifiers) Qualifiers { + return .{ + .@"const" = a.@"const" or b.@"const", + .@"volatile" = a.@"volatile" or b.@"volatile", + }; + } + + /// Merge all qualifiers, used by typeof() + fn mergeAll(a: Qualifiers, b: Qualifiers) Qualifiers { + return .{ + .@"const" = a.@"const" or b.@"const", + .atomic = a.atomic or b.atomic, + .@"volatile" = a.@"volatile" or b.@"volatile", + .restrict = a.restrict or b.restrict, + .register = a.register or b.register, + }; + } + + /// Checks if a has all the qualifiers of b + pub fn hasQuals(a: Qualifiers, b: Qualifiers) bool { + if (b.@"const" and !a.@"const") return false; + if (b.@"volatile" and !a.@"volatile") return false; + if (b.atomic and !a.atomic) return false; + return true; + } + + /// register is a storage class and not actually a qualifier + /// so it is not preserved by typeof() + pub fn inheritFromTypeof(quals: Qualifiers) Qualifiers { + var res = quals; + res.register = false; + return res; + } + + pub const Builder = struct { + @"const": ?TokenIndex = null, + atomic: ?TokenIndex = null, + @"volatile": ?TokenIndex = null, + restrict: ?TokenIndex = null, + + pub fn finish(b: Qualifiers.Builder, p: *Parser, ty: *Type) !void { + if (ty.specifier != .pointer and b.restrict != null) { + try p.errStr(.restrict_non_pointer, b.restrict.?, try p.typeStr(ty.*)); + } + if (b.atomic) |some| { + if (ty.isArray()) try p.errStr(.atomic_array, some, try p.typeStr(ty.*)); + if (ty.isFunc()) try p.errStr(.atomic_func, some, try p.typeStr(ty.*)); + if (ty.hasIncompleteSize()) try p.errStr(.atomic_incomplete, some, try p.typeStr(ty.*)); + } + + if (b.@"const" != null) ty.qual.@"const" = true; + if (b.atomic != null) ty.qual.atomic = true; + if (b.@"volatile" != null) ty.qual.@"volatile" = true; + if (b.restrict != null) ty.qual.restrict = true; + } + }; +}; + +// TODO improve memory usage +pub const Func = struct { + return_type: Type, + params: []Param, + + pub const Param = struct { + ty: Type, + name: StringId, + name_tok: TokenIndex, + }; +}; + +pub const Array = struct { + len: u64, + elem: Type, +}; + +pub const Expr = struct { + node: NodeIndex, + ty: Type, +}; + +pub const Attributed = struct { + attributes: []Attribute, + base: Type, + + pub fn create(allocator: std.mem.Allocator, base: Type, existing_attributes: []const Attribute, attributes: []const Attribute) !*Attributed { + var attributed_type = try allocator.create(Attributed); + errdefer allocator.destroy(attributed_type); + + var all_attrs = try allocator.alloc(Attribute, existing_attributes.len + attributes.len); + std.mem.copy(Attribute, all_attrs, existing_attributes); + std.mem.copy(Attribute, all_attrs[existing_attributes.len..], attributes); + + attributed_type.* = .{ + .attributes = all_attrs, + .base = base, + }; + return attributed_type; + } +}; + +// TODO improve memory usage +pub const Enum = struct { + fields: []Field, + tag_ty: Type, + name: StringId, + fixed: bool, + + pub const Field = struct { + ty: Type, + name: StringId, + name_tok: TokenIndex, + node: NodeIndex, + }; + + pub fn isIncomplete(e: Enum) bool { + return e.fields.len == std.math.maxInt(usize); + } + + pub fn create(allocator: std.mem.Allocator, name: StringId, fixed_ty: ?Type) !*Enum { + var e = try allocator.create(Enum); + e.name = name; + e.fields.len = std.math.maxInt(usize); + if (fixed_ty) |some| e.tag_ty = some; + e.fixed = fixed_ty != null; + return e; + } +}; + +// might not need all 4 of these when finished, +// but currently it helps having all 4 when diff-ing +// the rust code. +pub const TypeLayout = struct { + /// The size of the type in bits. + /// + /// This is the value returned by `sizeof` and C and `std::mem::size_of` in Rust + /// (but in bits instead of bytes). This is a multiple of `pointer_alignment_bits`. + size_bits: u64, + /// The alignment of the type, in bits, when used as a field in a record. + /// + /// This is usually the value returned by `_Alignof` in C, but there are some edge + /// cases in GCC where `_Alignof` returns a smaller value. + field_alignment_bits: u32, + /// The alignment, in bits, of valid pointers to this type. + /// + /// This is the value returned by `std::mem::align_of` in Rust + /// (but in bits instead of bytes). `size_bits` is a multiple of this value. + pointer_alignment_bits: u32, + /// The required alignment of the type in bits. + /// + /// This value is only used by MSVC targets. It is 8 on all other + /// targets. On MSVC targets, this value restricts the effects of `#pragma pack` except + /// in some cases involving bit-fields. + required_alignment_bits: u32, +}; + +pub const FieldLayout = struct { + /// `offset_bits` and `size_bits` should both be INVALID if and only if the field + /// is an unnamed bitfield. There is no way to reference an unnamed bitfield in C, so + /// there should be no way to observe these values. If it is used, this value will + /// maximize the chance that a safety-checked overflow will occur. + const INVALID = std.math.maxInt(u64); + + /// The offset of the field, in bits, from the start of the struct. + offset_bits: u64 = INVALID, + /// The size, in bits, of the field. + /// + /// For bit-fields, this is the width of the field. + size_bits: u64 = INVALID, + + pub fn isUnnamed(self: FieldLayout) bool { + return self.offset_bits == INVALID and self.size_bits == INVALID; + } +}; + +// TODO improve memory usage +pub const Record = struct { + fields: []Field, + type_layout: TypeLayout, + /// If this is null, none of the fields have attributes + /// Otherwise, it's a pointer to N items (where N == number of fields) + /// and the item at index i is the attributes for the field at index i + field_attributes: ?[*][]const Attribute, + name: StringId, + + pub const Field = struct { + ty: Type, + name: StringId, + /// zero for anonymous fields + name_tok: TokenIndex = 0, + bit_width: ?u32 = null, + layout: FieldLayout = .{ + .offset_bits = 0, + .size_bits = 0, + }, + + pub fn isNamed(f: *const Field) bool { + return f.name_tok != 0; + } + + pub fn isAnonymousRecord(f: Field) bool { + return !f.isNamed() and f.ty.isRecord(); + } + + /// false for bitfields + pub fn isRegularField(f: *const Field) bool { + return f.bit_width == null; + } + + /// bit width as specified in the C source. Asserts that `f` is a bitfield. + pub fn specifiedBitWidth(f: *const Field) u32 { + return f.bit_width.?; + } + }; + + pub fn isIncomplete(r: Record) bool { + return r.fields.len == std.math.maxInt(usize); + } + + pub fn create(allocator: std.mem.Allocator, name: StringId) !*Record { + var r = try allocator.create(Record); + r.name = name; + r.fields.len = std.math.maxInt(usize); + r.field_attributes = null; + r.type_layout = .{ + .size_bits = 8, + .field_alignment_bits = 8, + .pointer_alignment_bits = 8, + .required_alignment_bits = 8, + }; + return r; + } + + pub fn hasFieldOfType(self: *const Record, ty: Type, comp: *const Compilation) bool { + if (self.isIncomplete()) return false; + for (self.fields) |f| { + if (ty.eql(f.ty, comp, false)) return true; + } + return false; + } +}; + +pub const Specifier = enum { + /// A NaN-like poison value + invalid, + + /// GNU auto type + /// This is a placeholder specifier - it must be replaced by the actual type specifier (determined by the initializer) + auto_type, + + void, + bool, + + // integers + char, + schar, + uchar, + short, + ushort, + int, + uint, + long, + ulong, + long_long, + ulong_long, + int128, + uint128, + complex_char, + complex_schar, + complex_uchar, + complex_short, + complex_ushort, + complex_int, + complex_uint, + complex_long, + complex_ulong, + complex_long_long, + complex_ulong_long, + complex_int128, + complex_uint128, + + // data.int + bit_int, + complex_bit_int, + + // floating point numbers + fp16, + float16, + float, + double, + long_double, + float80, + float128, + complex_float, + complex_double, + complex_long_double, + complex_float80, + complex_float128, + + // data.sub_type + pointer, + unspecified_variable_len_array, + decayed_unspecified_variable_len_array, + // data.func + /// int foo(int bar, char baz) and int (void) + func, + /// int foo(int bar, char baz, ...) + var_args_func, + /// int foo(bar, baz) and int foo() + /// is also var args, but we can give warnings about incorrect amounts of parameters + old_style_func, + + // data.array + array, + decayed_array, + static_array, + decayed_static_array, + incomplete_array, + decayed_incomplete_array, + vector, + // data.expr + variable_len_array, + decayed_variable_len_array, + + // data.record + @"struct", + @"union", + + // data.enum + @"enum", + + /// typeof(type-name) + typeof_type, + /// decayed array created with typeof(type-name) + decayed_typeof_type, + + /// typeof(expression) + typeof_expr, + /// decayed array created with typeof(expression) + decayed_typeof_expr, + + /// data.attributed + attributed, + + /// C23 nullptr_t + nullptr_t, +}; + +/// All fields of Type except data may be mutated +data: union { + sub_type: *Type, + func: *Func, + array: *Array, + expr: *Expr, + @"enum": *Enum, + record: *Record, + attributed: *Attributed, + none: void, + int: struct { + bits: u8, + signedness: std.builtin.Signedness, + }, +} = .{ .none = {} }, +specifier: Specifier, +qual: Qualifiers = .{}, + +pub const int = Type{ .specifier = .int }; +pub const invalid = Type{ .specifier = .invalid }; + +/// Determine if type matches the given specifier, recursing into typeof +/// types if necessary. +pub fn is(ty: Type, specifier: Specifier) bool { + std.debug.assert(specifier != .typeof_type and specifier != .typeof_expr); + return ty.get(specifier) != null; +} + +pub fn withAttributes(self: Type, allocator: std.mem.Allocator, attributes: []const Attribute) !Type { + if (attributes.len == 0) return self; + const attributed_type = try Type.Attributed.create(allocator, self, self.getAttributes(), attributes); + return Type{ .specifier = .attributed, .data = .{ .attributed = attributed_type } }; +} + +pub fn isCallable(ty: Type) ?Type { + return switch (ty.specifier) { + .func, .var_args_func, .old_style_func => ty, + .pointer => if (ty.data.sub_type.isFunc()) ty.data.sub_type.* else null, + .typeof_type => ty.data.sub_type.isCallable(), + .typeof_expr => ty.data.expr.ty.isCallable(), + .attributed => ty.data.attributed.base.isCallable(), + else => null, + }; +} + +pub fn isFunc(ty: Type) bool { + return switch (ty.specifier) { + .func, .var_args_func, .old_style_func => true, + .typeof_type => ty.data.sub_type.isFunc(), + .typeof_expr => ty.data.expr.ty.isFunc(), + .attributed => ty.data.attributed.base.isFunc(), + else => false, + }; +} + +pub fn isArray(ty: Type) bool { + return switch (ty.specifier) { + .array, .static_array, .incomplete_array, .variable_len_array, .unspecified_variable_len_array => true, + .typeof_type => ty.data.sub_type.isArray(), + .typeof_expr => ty.data.expr.ty.isArray(), + .attributed => ty.data.attributed.base.isArray(), + else => false, + }; +} + +pub fn isScalar(ty: Type) bool { + return ty.isInt() or ty.isScalarNonInt(); +} + +/// To avoid calling isInt() twice for allowable loop/if controlling expressions +pub fn isScalarNonInt(ty: Type) bool { + return ty.isFloat() or ty.isPtr() or ty.is(.nullptr_t); +} + +pub fn isDecayed(ty: Type) bool { + const decayed = switch (ty.specifier) { + .decayed_array, + .decayed_static_array, + .decayed_incomplete_array, + .decayed_variable_len_array, + .decayed_unspecified_variable_len_array, + .decayed_typeof_type, + .decayed_typeof_expr, + => true, + else => false, + }; + std.debug.assert(decayed or !std.mem.startsWith(u8, @tagName(ty.specifier), "decayed")); + return decayed; +} + +pub fn isPtr(ty: Type) bool { + return switch (ty.specifier) { + .pointer, + .decayed_array, + .decayed_static_array, + .decayed_incomplete_array, + .decayed_variable_len_array, + .decayed_unspecified_variable_len_array, + .decayed_typeof_type, + .decayed_typeof_expr, + => true, + .typeof_type => ty.data.sub_type.isPtr(), + .typeof_expr => ty.data.expr.ty.isPtr(), + .attributed => ty.data.attributed.base.isPtr(), + else => false, + }; +} + +pub fn isInt(ty: Type) bool { + return switch (ty.specifier) { + // zig fmt: off + .@"enum", .bool, .char, .schar, .uchar, .short, .ushort, .int, .uint, .long, .ulong, + .long_long, .ulong_long, .int128, .uint128, .complex_char, .complex_schar, .complex_uchar, + .complex_short, .complex_ushort, .complex_int, .complex_uint, .complex_long, .complex_ulong, + .complex_long_long, .complex_ulong_long, .complex_int128, .complex_uint128, + .bit_int, .complex_bit_int => true, + // zig fmt: on + .typeof_type => ty.data.sub_type.isInt(), + .typeof_expr => ty.data.expr.ty.isInt(), + .attributed => ty.data.attributed.base.isInt(), + else => false, + }; +} + +pub fn isFloat(ty: Type) bool { + return switch (ty.specifier) { + // zig fmt: off + .float, .double, .long_double, .complex_float, .complex_double, .complex_long_double, + .fp16, .float16, .float80, .float128, .complex_float80, .complex_float128 => true, + // zig fmt: on + .typeof_type => ty.data.sub_type.isFloat(), + .typeof_expr => ty.data.expr.ty.isFloat(), + .attributed => ty.data.attributed.base.isFloat(), + else => false, + }; +} + +pub fn isReal(ty: Type) bool { + return switch (ty.specifier) { + // zig fmt: off + .complex_float, .complex_double, .complex_long_double, .complex_float80, + .complex_float128, .complex_char, .complex_schar, .complex_uchar, .complex_short, + .complex_ushort, .complex_int, .complex_uint, .complex_long, .complex_ulong, + .complex_long_long, .complex_ulong_long, .complex_int128, .complex_uint128, + .complex_bit_int => false, + // zig fmt: on + .typeof_type => ty.data.sub_type.isReal(), + .typeof_expr => ty.data.expr.ty.isReal(), + .attributed => ty.data.attributed.base.isReal(), + else => true, + }; +} + +pub fn isComplex(ty: Type) bool { + return switch (ty.specifier) { + // zig fmt: off + .complex_float, .complex_double, .complex_long_double, .complex_float80, + .complex_float128, .complex_char, .complex_schar, .complex_uchar, .complex_short, + .complex_ushort, .complex_int, .complex_uint, .complex_long, .complex_ulong, + .complex_long_long, .complex_ulong_long, .complex_int128, .complex_uint128, + .complex_bit_int => true, + // zig fmt: on + .typeof_type => ty.data.sub_type.isComplex(), + .typeof_expr => ty.data.expr.ty.isComplex(), + .attributed => ty.data.attributed.base.isComplex(), + else => false, + }; +} + +pub fn isVoidStar(ty: Type) bool { + return switch (ty.specifier) { + .pointer => ty.data.sub_type.specifier == .void, + .typeof_type => ty.data.sub_type.isVoidStar(), + .typeof_expr => ty.data.expr.ty.isVoidStar(), + .attributed => ty.data.attributed.base.isVoidStar(), + else => false, + }; +} + +pub fn isTypeof(ty: Type) bool { + return switch (ty.specifier) { + .typeof_type, .typeof_expr, .decayed_typeof_type, .decayed_typeof_expr => true, + else => false, + }; +} + +pub fn isConst(ty: Type) bool { + return switch (ty.specifier) { + .typeof_type, .decayed_typeof_type => ty.qual.@"const" or ty.data.sub_type.isConst(), + .typeof_expr, .decayed_typeof_expr => ty.qual.@"const" or ty.data.expr.ty.isConst(), + .attributed => ty.data.attributed.base.isConst(), + else => ty.qual.@"const", + }; +} + +pub fn isUnsignedInt(ty: Type, comp: *const Compilation) bool { + return switch (ty.specifier) { + // zig fmt: off + .char, .complex_char => return comp.getCharSignedness() == .unsigned, + .uchar, .ushort, .uint, .ulong, .ulong_long, .bool, .complex_uchar, .complex_ushort, + .complex_uint, .complex_ulong, .complex_ulong_long, .complex_uint128 => true, + // zig fmt: on + .bit_int, .complex_bit_int => return ty.data.int.signedness == .unsigned, + .typeof_type => ty.data.sub_type.isUnsignedInt(comp), + .typeof_expr => ty.data.expr.ty.isUnsignedInt(comp), + .attributed => ty.data.attributed.base.isUnsignedInt(comp), + else => false, + }; +} + +pub fn isEnumOrRecord(ty: Type) bool { + return switch (ty.specifier) { + .@"enum", .@"struct", .@"union" => true, + .typeof_type => ty.data.sub_type.isEnumOrRecord(), + .typeof_expr => ty.data.expr.ty.isEnumOrRecord(), + .attributed => ty.data.attributed.base.isEnumOrRecord(), + else => false, + }; +} + +pub fn isRecord(ty: Type) bool { + return switch (ty.specifier) { + .@"struct", .@"union" => true, + .typeof_type => ty.data.sub_type.isRecord(), + .typeof_expr => ty.data.expr.ty.isRecord(), + .attributed => ty.data.attributed.base.isRecord(), + else => false, + }; +} + +pub fn isAnonymousRecord(ty: Type, comp: *const Compilation) bool { + return switch (ty.specifier) { + // anonymous records can be recognized by their names which are in + // the format "(anonymous TAG at path:line:col)". + .@"struct", .@"union" => { + const mapper = comp.string_interner.getSlowTypeMapper(); + return mapper.lookup(ty.data.record.name)[0] == '('; + }, + .typeof_type => ty.data.sub_type.isAnonymousRecord(comp), + .typeof_expr => ty.data.expr.ty.isAnonymousRecord(comp), + .attributed => ty.data.attributed.base.isAnonymousRecord(comp), + else => false, + }; +} + +pub fn elemType(ty: Type) Type { + return switch (ty.specifier) { + .pointer, .unspecified_variable_len_array, .decayed_unspecified_variable_len_array => ty.data.sub_type.*, + .array, .static_array, .incomplete_array, .decayed_array, .decayed_static_array, .decayed_incomplete_array, .vector => ty.data.array.elem, + .variable_len_array, .decayed_variable_len_array => ty.data.expr.ty, + .typeof_type, .decayed_typeof_type, .typeof_expr, .decayed_typeof_expr => { + const unwrapped = ty.canonicalize(.preserve_quals); + var elem = unwrapped.elemType(); + elem.qual = elem.qual.mergeAll(unwrapped.qual); + return elem; + }, + .attributed => ty.data.attributed.base, + .invalid => Type.invalid, + // zig fmt: off + .complex_float, .complex_double, .complex_long_double, .complex_float80, + .complex_float128, .complex_char, .complex_schar, .complex_uchar, .complex_short, + .complex_ushort, .complex_int, .complex_uint, .complex_long, .complex_ulong, + .complex_long_long, .complex_ulong_long, .complex_int128, .complex_uint128, + .complex_bit_int => ty.makeReal(), + // zig fmt: on + else => unreachable, + }; +} + +pub fn returnType(ty: Type) Type { + return switch (ty.specifier) { + .func, .var_args_func, .old_style_func => ty.data.func.return_type, + .typeof_type, .decayed_typeof_type => ty.data.sub_type.returnType(), + .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.returnType(), + .attributed => ty.data.attributed.base.returnType(), + .invalid => Type.invalid, + else => unreachable, + }; +} + +pub fn params(ty: Type) []Func.Param { + return switch (ty.specifier) { + .func, .var_args_func, .old_style_func => ty.data.func.params, + .typeof_type, .decayed_typeof_type => ty.data.sub_type.params(), + .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.params(), + .attributed => ty.data.attributed.base.params(), + .invalid => &.{}, + else => unreachable, + }; +} + +pub fn arrayLen(ty: Type) ?u64 { + return switch (ty.specifier) { + .array, .static_array, .decayed_array, .decayed_static_array => ty.data.array.len, + .typeof_type, .decayed_typeof_type => ty.data.sub_type.arrayLen(), + .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.arrayLen(), + .attributed => ty.data.attributed.base.arrayLen(), + else => null, + }; +} + +/// Complex numbers are scalars but they can be initialized with a 2-element initList +pub fn expectedInitListSize(ty: Type) ?u64 { + return if (ty.isComplex()) 2 else ty.arrayLen(); +} + +pub fn anyQual(ty: Type) bool { + return switch (ty.specifier) { + .typeof_type => ty.qual.any() or ty.data.sub_type.anyQual(), + .typeof_expr => ty.qual.any() or ty.data.expr.ty.anyQual(), + else => ty.qual.any(), + }; +} + +pub fn getAttributes(ty: Type) []const Attribute { + return switch (ty.specifier) { + .attributed => ty.data.attributed.attributes, + .typeof_type, .decayed_typeof_type => ty.data.sub_type.getAttributes(), + .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.getAttributes(), + else => &.{}, + }; +} + +pub fn getRecord(ty: Type) ?*const Type.Record { + return switch (ty.specifier) { + .attributed => ty.data.attributed.base.getRecord(), + .typeof_type, .decayed_typeof_type => ty.data.sub_type.getRecord(), + .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.getRecord(), + .@"struct", .@"union" => ty.data.record, + else => null, + }; +} + +fn compareIntegerRanks(a: Type, b: Type, comp: *const Compilation) std.math.Order { + std.debug.assert(a.isInt() and b.isInt()); + if (a.eql(b, comp, false)) return .eq; + + const a_unsigned = a.isUnsignedInt(comp); + const b_unsigned = b.isUnsignedInt(comp); + + const a_rank = a.integerRank(comp); + const b_rank = b.integerRank(comp); + if (a_unsigned == b_unsigned) { + return std.math.order(a_rank, b_rank); + } + if (a_unsigned) { + if (a_rank >= b_rank) return .gt; + return .lt; + } + std.debug.assert(b_unsigned); + if (b_rank >= a_rank) return .lt; + return .gt; +} + +fn realIntegerConversion(a: Type, b: Type, comp: *const Compilation) Type { + std.debug.assert(a.isReal() and b.isReal()); + const type_order = a.compareIntegerRanks(b, comp); + const a_signed = !a.isUnsignedInt(comp); + const b_signed = !b.isUnsignedInt(comp); + if (a_signed == b_signed) { + // If both have the same sign, use higher-rank type. + return switch (type_order) { + .lt => b, + .eq, .gt => a, + }; + } else if (type_order != if (a_signed) std.math.Order.gt else std.math.Order.lt) { + // Only one is signed; and the unsigned type has rank >= the signed type + // Use the unsigned type + return if (b_signed) a else b; + } else if (a.bitSizeof(comp).? != b.bitSizeof(comp).?) { + // Signed type is higher rank and sizes are not equal + // Use the signed type + return if (a_signed) a else b; + } else { + // Signed type is higher rank but same size as unsigned type + // e.g. `long` and `unsigned` on x86-linux-gnu + // Use unsigned version of the signed type + return if (a_signed) a.makeIntegerUnsigned() else b.makeIntegerUnsigned(); + } +} + +pub fn makeIntegerUnsigned(ty: Type) Type { + // TODO discards attributed/typeof + var base = ty.canonicalize(.standard); + switch (base.specifier) { + // zig fmt: off + .uchar, .ushort, .uint, .ulong, .ulong_long, .uint128, + .complex_uchar, .complex_ushort, .complex_uint, .complex_ulong, .complex_ulong_long, .complex_uint128, + => return ty, + // zig fmt: on + + .char, .complex_char => { + base.specifier = @enumFromInt(@intFromEnum(base.specifier) + 2); + return base; + }, + + // zig fmt: off + .schar, .short, .int, .long, .long_long, .int128, + .complex_schar, .complex_short, .complex_int, .complex_long, .complex_long_long, .complex_int128 => { + base.specifier = @enumFromInt(@intFromEnum(base.specifier) + 1); + return base; + }, + // zig fmt: on + + .bit_int, .complex_bit_int => { + base.data.int.signedness = .unsigned; + return base; + }, + else => unreachable, + } +} + +/// Find the common type of a and b for binary operations +pub fn integerConversion(a: Type, b: Type, comp: *const Compilation) Type { + const a_real = a.isReal(); + const b_real = b.isReal(); + const target_ty = a.makeReal().realIntegerConversion(b.makeReal(), comp); + return if (a_real and b_real) target_ty else target_ty.makeComplex(); +} + +pub fn integerPromotion(ty: Type, comp: *Compilation) Type { + var specifier = ty.specifier; + switch (specifier) { + .@"enum" => { + if (ty.hasIncompleteSize()) return .{ .specifier = .int }; + specifier = ty.data.@"enum".tag_ty.specifier; + }, + .bit_int, .complex_bit_int => return .{ .specifier = specifier, .data = ty.data }, + else => {}, + } + return switch (specifier) { + else => .{ + .specifier = switch (specifier) { + // zig fmt: off + .bool, .char, .schar, .uchar, .short => .int, + .ushort => if (ty.sizeof(comp).? == sizeof(.{ .specifier = .int }, comp)) Specifier.uint else .int, + .int, .uint, .long, .ulong, .long_long, .ulong_long, .int128, .uint128, .complex_char, + .complex_schar, .complex_uchar, .complex_short, .complex_ushort, .complex_int, + .complex_uint, .complex_long, .complex_ulong, .complex_long_long, .complex_ulong_long, + .complex_int128, .complex_uint128 => specifier, + // zig fmt: on + .typeof_type => return ty.data.sub_type.integerPromotion(comp), + .typeof_expr => return ty.data.expr.ty.integerPromotion(comp), + .attributed => return ty.data.attributed.base.integerPromotion(comp), + .invalid => .invalid, + else => unreachable, // _BitInt, or not an integer type + }, + }, + }; +} + +/// Promote a bitfield. If `int` can hold all the values of the underlying field, +/// promote to int. Otherwise, promote to unsigned int +/// Returns null if no promotion is necessary +pub fn bitfieldPromotion(ty: Type, comp: *Compilation, width: u32) ?Type { + const type_size_bits = ty.bitSizeof(comp).?; + + // Note: GCC and clang will promote `long: 3` to int even though the C standard does not allow this + if (width < type_size_bits) { + return int; + } + + if (width == type_size_bits) { + return if (ty.isUnsignedInt(comp)) .{ .specifier = .uint } else int; + } + + return null; +} + +pub fn hasIncompleteSize(ty: Type) bool { + return switch (ty.specifier) { + .void, .incomplete_array, .invalid => true, + .@"enum" => ty.data.@"enum".isIncomplete() and !ty.data.@"enum".fixed, + .@"struct", .@"union" => ty.data.record.isIncomplete(), + .array, .static_array => ty.data.array.elem.hasIncompleteSize(), + .typeof_type => ty.data.sub_type.hasIncompleteSize(), + .typeof_expr => ty.data.expr.ty.hasIncompleteSize(), + .attributed => ty.data.attributed.base.hasIncompleteSize(), + else => false, + }; +} + +pub fn hasUnboundVLA(ty: Type) bool { + var cur = ty; + while (true) { + switch (cur.specifier) { + .unspecified_variable_len_array, + .decayed_unspecified_variable_len_array, + => return true, + .array, + .static_array, + .incomplete_array, + .variable_len_array, + .decayed_array, + .decayed_static_array, + .decayed_incomplete_array, + .decayed_variable_len_array, + => cur = cur.elemType(), + .typeof_type, .decayed_typeof_type => cur = cur.data.sub_type.*, + .typeof_expr, .decayed_typeof_expr => cur = cur.data.expr.ty, + .attributed => cur = cur.data.attributed.base, + else => return false, + } + } +} + +pub fn hasField(ty: Type, name: StringId) bool { + switch (ty.specifier) { + .@"struct" => { + std.debug.assert(!ty.data.record.isIncomplete()); + for (ty.data.record.fields) |f| { + if (f.isAnonymousRecord() and f.ty.hasField(name)) return true; + if (name == f.name) return true; + } + }, + .@"union" => { + std.debug.assert(!ty.data.record.isIncomplete()); + for (ty.data.record.fields) |f| { + if (f.isAnonymousRecord() and f.ty.hasField(name)) return true; + if (name == f.name) return true; + } + }, + .typeof_type => return ty.data.sub_type.hasField(name), + .typeof_expr => return ty.data.expr.ty.hasField(name), + .attributed => return ty.data.attributed.base.hasField(name), + .invalid => return false, + else => unreachable, + } + return false; +} + +pub fn minInt(ty: Type, comp: *const Compilation) i64 { + std.debug.assert(ty.isInt()); + if (ty.isUnsignedInt(comp)) return 0; + return switch (ty.sizeof(comp).?) { + 1 => std.math.minInt(i8), + 2 => std.math.minInt(i16), + 4 => std.math.minInt(i32), + 8 => std.math.minInt(i64), + else => unreachable, + }; +} + +pub fn maxInt(ty: Type, comp: *const Compilation) u64 { + std.debug.assert(ty.isInt()); + return switch (ty.sizeof(comp).?) { + 1 => if (ty.isUnsignedInt(comp)) @as(u64, std.math.maxInt(u8)) else std.math.maxInt(i8), + 2 => if (ty.isUnsignedInt(comp)) @as(u64, std.math.maxInt(u16)) else std.math.maxInt(i16), + 4 => if (ty.isUnsignedInt(comp)) @as(u64, std.math.maxInt(u32)) else std.math.maxInt(i32), + 8 => if (ty.isUnsignedInt(comp)) @as(u64, std.math.maxInt(u64)) else std.math.maxInt(i64), + else => unreachable, + }; +} + +const TypeSizeOrder = enum { + lt, + gt, + eq, + indeterminate, +}; + +pub fn sizeCompare(a: Type, b: Type, comp: *Compilation) TypeSizeOrder { + const a_size = a.sizeof(comp) orelse return .indeterminate; + const b_size = b.sizeof(comp) orelse return .indeterminate; + return switch (std.math.order(a_size, b_size)) { + .lt => .lt, + .gt => .gt, + .eq => .eq, + }; +} + +/// Size of type as reported by sizeof +pub fn sizeof(ty: Type, comp: *const Compilation) ?u64 { + return switch (ty.specifier) { + .auto_type => unreachable, + .variable_len_array, .unspecified_variable_len_array => return null, + .incomplete_array => return if (comp.langopts.emulate == .msvc) @as(?u64, 0) else null, + .func, .var_args_func, .old_style_func, .void, .bool => 1, + .char, .schar, .uchar => 1, + .short => comp.target.c_type_byte_size(.short), + .ushort => comp.target.c_type_byte_size(.ushort), + .int => comp.target.c_type_byte_size(.int), + .uint => comp.target.c_type_byte_size(.uint), + .long => comp.target.c_type_byte_size(.long), + .ulong => comp.target.c_type_byte_size(.ulong), + .long_long => comp.target.c_type_byte_size(.longlong), + .ulong_long => comp.target.c_type_byte_size(.ulonglong), + .long_double => comp.target.c_type_byte_size(.longdouble), + .int128, .uint128 => 16, + .fp16, .float16 => 2, + .float => comp.target.c_type_byte_size(.float), + .double => comp.target.c_type_byte_size(.double), + .float80 => 16, + .float128 => 16, + .bit_int => { + return std.mem.alignForward(u64, (ty.data.int.bits + 7) / 8, ty.alignof(comp)); + }, + // zig fmt: off + .complex_char, .complex_schar, .complex_uchar, .complex_short, .complex_ushort, .complex_int, + .complex_uint, .complex_long, .complex_ulong, .complex_long_long, .complex_ulong_long, + .complex_int128, .complex_uint128, .complex_float, .complex_double, + .complex_long_double, .complex_float80, .complex_float128, .complex_bit_int, + => return 2 * ty.makeReal().sizeof(comp).?, + // zig fmt: on + .pointer, + .decayed_array, + .decayed_static_array, + .decayed_incomplete_array, + .decayed_variable_len_array, + .decayed_unspecified_variable_len_array, + .decayed_typeof_type, + .decayed_typeof_expr, + .static_array, + .nullptr_t, + => comp.target.ptrBitWidth() / 8, + .array, .vector => { + const size = ty.data.array.elem.sizeof(comp) orelse return null; + const arr_size = size * ty.data.array.len; + if (comp.langopts.emulate == .msvc) { + // msvc ignores array type alignment. + // Since the size might not be a multiple of the field + // alignment, the address of the second element might not be properly aligned + // for the field alignment. A flexible array has size 0. See test case 0018. + return arr_size; + } else { + return std.mem.alignForward(u64, arr_size, ty.alignof(comp)); + } + }, + .@"struct", .@"union" => if (ty.data.record.isIncomplete()) null else @as(u64, ty.data.record.type_layout.size_bits / 8), + .@"enum" => if (ty.data.@"enum".isIncomplete() and !ty.data.@"enum".fixed) null else ty.data.@"enum".tag_ty.sizeof(comp), + .typeof_type => ty.data.sub_type.sizeof(comp), + .typeof_expr => ty.data.expr.ty.sizeof(comp), + .attributed => ty.data.attributed.base.sizeof(comp), + .invalid => return null, + }; +} + +pub fn bitSizeof(ty: Type, comp: *const Compilation) ?u64 { + return switch (ty.specifier) { + .bool => if (comp.langopts.emulate == .msvc) @as(u64, 8) else 1, + .typeof_type, .decayed_typeof_type => ty.data.sub_type.bitSizeof(comp), + .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.bitSizeof(comp), + .attributed => ty.data.attributed.base.bitSizeof(comp), + .bit_int => return ty.data.int.bits, + .long_double => comp.target.c_type_bit_size(.longdouble), + .float80 => return 80, + else => 8 * (ty.sizeof(comp) orelse return null), + }; +} + +pub fn alignable(ty: Type) bool { + return ty.isArray() or !ty.hasIncompleteSize() or ty.is(.void); +} + +/// Get the alignment of a type +pub fn alignof(ty: Type, comp: *const Compilation) u29 { + // don't return the attribute for records + // layout has already accounted for requested alignment + if (ty.requestedAlignment(comp)) |requested| { + // gcc does not respect alignment on enums + if (ty.get(.@"enum")) |ty_enum| { + if (comp.langopts.emulate == .gcc) { + return ty_enum.alignof(comp); + } + } else if (ty.getRecord()) |rec| { + if (ty.hasIncompleteSize()) return 0; + const computed: u29 = @intCast(@divExact(rec.type_layout.field_alignment_bits, 8)); + return @max(requested, computed); + } else if (comp.langopts.emulate == .msvc) { + const type_align = ty.data.attributed.base.alignof(comp); + return @max(requested, type_align); + } + return requested; + } + + return switch (ty.specifier) { + .invalid => unreachable, + .auto_type => unreachable, + + .variable_len_array, + .incomplete_array, + .unspecified_variable_len_array, + .array, + .vector, + => ty.elemType().alignof(comp), + .func, .var_args_func, .old_style_func => target_util.defaultFunctionAlignment(comp.target), + .char, .schar, .uchar, .void, .bool => 1, + + // zig fmt: off + .complex_char, .complex_schar, .complex_uchar, .complex_short, .complex_ushort, .complex_int, + .complex_uint, .complex_long, .complex_ulong, .complex_long_long, .complex_ulong_long, + .complex_int128, .complex_uint128, .complex_float, .complex_double, + .complex_long_double, .complex_float80, .complex_float128, .complex_bit_int, + => return ty.makeReal().alignof(comp), + // zig fmt: on + + .short => comp.target.c_type_alignment(.short), + .ushort => comp.target.c_type_alignment(.ushort), + .int => comp.target.c_type_alignment(.int), + .uint => comp.target.c_type_alignment(.uint), + + .long => comp.target.c_type_alignment(.long), + .ulong => comp.target.c_type_alignment(.ulong), + .long_long => comp.target.c_type_alignment(.longlong), + .ulong_long => comp.target.c_type_alignment(.ulonglong), + + .bit_int => @min( + std.math.ceilPowerOfTwoPromote(u16, (ty.data.int.bits + 7) / 8), + comp.target.maxIntAlignment(), + ), + + .float => comp.target.c_type_alignment(.float), + .double => comp.target.c_type_alignment(.double), + .long_double => comp.target.c_type_alignment(.longdouble), + + .int128, .uint128 => if (comp.target.cpu.arch == .s390x and comp.target.os.tag == .linux and comp.target.isGnu()) 8 else 16, + .fp16, .float16 => 2, + + .float80, .float128 => 16, + .pointer, + .decayed_array, + .decayed_static_array, + .decayed_incomplete_array, + .decayed_variable_len_array, + .decayed_unspecified_variable_len_array, + .static_array, + .nullptr_t, + => switch (comp.target.cpu.arch) { + .avr => 1, + else => comp.target.ptrBitWidth() / 8, + }, + .@"struct", .@"union" => if (ty.data.record.isIncomplete()) 0 else @intCast(ty.data.record.type_layout.field_alignment_bits / 8), + .@"enum" => if (ty.data.@"enum".isIncomplete() and !ty.data.@"enum".fixed) 0 else ty.data.@"enum".tag_ty.alignof(comp), + .typeof_type, .decayed_typeof_type => ty.data.sub_type.alignof(comp), + .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.alignof(comp), + .attributed => ty.data.attributed.base.alignof(comp), + }; +} + +/// Canonicalize a possibly-typeof() type. If the type is not a typeof() type, simply +/// return it. Otherwise, determine the actual qualified type. +/// The `qual_handling` parameter can be used to return the full set of qualifiers +/// added by typeof() operations, which is useful when determining the elemType of +/// arrays and pointers. +pub fn canonicalize(ty: Type, qual_handling: enum { standard, preserve_quals }) Type { + var cur = ty; + if (cur.specifier == .attributed) cur = cur.data.attributed.base; + if (!cur.isTypeof()) return cur; + + var qual = cur.qual; + while (true) { + switch (cur.specifier) { + .typeof_type => cur = cur.data.sub_type.*, + .typeof_expr => cur = cur.data.expr.ty, + .decayed_typeof_type => { + cur = cur.data.sub_type.*; + cur.decayArray(); + }, + .decayed_typeof_expr => { + cur = cur.data.expr.ty; + cur.decayArray(); + }, + else => break, + } + qual = qual.mergeAll(cur.qual); + } + if ((cur.isArray() or cur.isPtr()) and qual_handling == .standard) { + cur.qual = .{}; + } else { + cur.qual = qual; + } + return cur; +} + +pub fn get(ty: *const Type, specifier: Specifier) ?*const Type { + std.debug.assert(specifier != .typeof_type and specifier != .typeof_expr); + return switch (ty.specifier) { + .typeof_type => ty.data.sub_type.get(specifier), + .typeof_expr => ty.data.expr.ty.get(specifier), + .attributed => ty.data.attributed.base.get(specifier), + else => if (ty.specifier == specifier) ty else null, + }; +} + +pub fn requestedAlignment(ty: Type, comp: *const Compilation) ?u29 { + return switch (ty.specifier) { + .typeof_type, .decayed_typeof_type => ty.data.sub_type.requestedAlignment(comp), + .typeof_expr, .decayed_typeof_expr => ty.data.expr.ty.requestedAlignment(comp), + .attributed => annotationAlignment(comp, ty.data.attributed.attributes), + else => null, + }; +} + +pub fn enumIsPacked(ty: Type, comp: *const Compilation) bool { + std.debug.assert(ty.is(.@"enum")); + return comp.langopts.short_enums or target_util.packAllEnums(comp.target) or ty.hasAttribute(.@"packed"); +} + +pub fn annotationAlignment(comp: *const Compilation, attrs: ?[]const Attribute) ?u29 { + const a = attrs orelse return null; + + var max_requested: ?u29 = null; + for (a) |attribute| { + if (attribute.tag != .aligned) continue; + const requested = if (attribute.args.aligned.alignment) |alignment| alignment.requested else target_util.defaultAlignment(comp.target); + if (max_requested == null or max_requested.? < requested) { + max_requested = requested; + } + } + return max_requested; +} + +/// Checks type compatibility for __builtin_types_compatible_p +/// Returns true if the unqualified version of `a_param` and `b_param` are the same +/// Ignores top-level qualifiers (e.g. `int` and `const int` are compatible) but `int *` and `const int *` are not +/// Two types that are typedefed are considered compatible if their underlying types are compatible. +/// An enum type is not considered to be compatible with another enum type even if both are compatible with the same integer type; +/// `A[]` and `A[N]` for a type `A` and integer `N` are compatible +pub fn compatible(a_param: Type, b_param: Type, comp: *const Compilation) bool { + var a_unqual = a_param.canonicalize(.standard); + a_unqual.qual.@"const" = false; + a_unqual.qual.@"volatile" = false; + var b_unqual = b_param.canonicalize(.standard); + b_unqual.qual.@"const" = false; + b_unqual.qual.@"volatile" = false; + + if (a_unqual.eql(b_unqual, comp, true)) return true; + if (!a_unqual.isArray() or !b_unqual.isArray()) return false; + + if (a_unqual.arrayLen() == null or b_unqual.arrayLen() == null) { + // incomplete arrays are compatible with arrays of the same element type + // GCC and clang ignore cv-qualifiers on arrays + return a_unqual.elemType().compatible(b_unqual.elemType(), comp); + } + return false; +} + +pub fn eql(a_param: Type, b_param: Type, comp: *const Compilation, check_qualifiers: bool) bool { + const a = a_param.canonicalize(.standard); + const b = b_param.canonicalize(.standard); + + if (a.specifier == .invalid or b.specifier == .invalid) return false; + if (a.alignof(comp) != b.alignof(comp)) return false; + if (a.isPtr()) { + if (!b.isPtr()) return false; + } else if (a.isFunc()) { + if (!b.isFunc()) return false; + } else if (a.isArray()) { + if (!b.isArray()) return false; + } else if (a.specifier != b.specifier) return false; + + if (a.qual.atomic != b.qual.atomic) return false; + if (check_qualifiers) { + if (a.qual.@"const" != b.qual.@"const") return false; + if (a.qual.@"volatile" != b.qual.@"volatile") return false; + } + + switch (a.specifier) { + .pointer, + .decayed_array, + .decayed_static_array, + .decayed_incomplete_array, + .decayed_variable_len_array, + .decayed_unspecified_variable_len_array, + => if (!a_param.elemType().eql(b_param.elemType(), comp, check_qualifiers)) return false, + + .func, + .var_args_func, + .old_style_func, + => { + // TODO validate this + if (a.data.func.params.len != b.data.func.params.len) return false; + // return type cannot have qualifiers + if (!a.returnType().eql(b.returnType(), comp, false)) return false; + for (a.data.func.params, b.data.func.params) |param, b_qual| { + var a_unqual = param.ty; + a_unqual.qual.@"const" = false; + a_unqual.qual.@"volatile" = false; + var b_unqual = b_qual.ty; + b_unqual.qual.@"const" = false; + b_unqual.qual.@"volatile" = false; + if (!a_unqual.eql(b_unqual, comp, check_qualifiers)) return false; + } + }, + + .array, + .static_array, + .incomplete_array, + .vector, + => { + if (!std.meta.eql(a.arrayLen(), b.arrayLen())) return false; + if (!a.elemType().eql(b.elemType(), comp, check_qualifiers)) return false; + }, + .variable_len_array => if (!a.elemType().eql(b.elemType(), comp, check_qualifiers)) return false, + + .@"struct", .@"union" => if (a.data.record != b.data.record) return false, + .@"enum" => if (a.data.@"enum" != b.data.@"enum") return false, + .bit_int, .complex_bit_int => return a.data.int.bits == b.data.int.bits and a.data.int.signedness == b.data.int.signedness, + + else => {}, + } + return true; +} + +/// Decays an array to a pointer +pub fn decayArray(ty: *Type) void { + // the decayed array type is the current specifier +1 + ty.specifier = @enumFromInt(@intFromEnum(ty.specifier) + 1); +} + +pub fn originalTypeOfDecayedArray(ty: Type) Type { + std.debug.assert(ty.isDecayed()); + var copy = ty; + copy.specifier = @enumFromInt(@intFromEnum(ty.specifier) - 1); + return copy; +} + +/// Rank for floating point conversions, ignoring domain (complex vs real) +/// Asserts that ty is a floating point type +pub fn floatRank(ty: Type) usize { + const real = ty.makeReal(); + return switch (real.specifier) { + // TODO: bfloat16 => 0 + .float16 => 1, + .fp16 => 2, + .float => 3, + .double => 4, + .long_double => 5, + .float128 => 6, + // TODO: ibm128 => 7 + else => unreachable, + }; +} + +/// Rank for integer conversions, ignoring domain (complex vs real) +/// Asserts that ty is an integer type +pub fn integerRank(ty: Type, comp: *const Compilation) usize { + const real = ty.makeReal(); + return @intCast(switch (real.specifier) { + .bit_int => @as(u64, real.data.int.bits) << 3, + + .bool => 1 + (ty.bitSizeof(comp).? << 3), + .char, .schar, .uchar => 2 + (ty.bitSizeof(comp).? << 3), + .short, .ushort => 3 + (ty.bitSizeof(comp).? << 3), + .int, .uint => 4 + (ty.bitSizeof(comp).? << 3), + .long, .ulong => 5 + (ty.bitSizeof(comp).? << 3), + .long_long, .ulong_long => 6 + (ty.bitSizeof(comp).? << 3), + .int128, .uint128 => 7 + (ty.bitSizeof(comp).? << 3), + + else => unreachable, + }); +} + +/// Returns true if `a` and `b` are integer types that differ only in sign +pub fn sameRankDifferentSign(a: Type, b: Type, comp: *const Compilation) bool { + if (!a.isInt() or !b.isInt()) return false; + if (a.integerRank(comp) != b.integerRank(comp)) return false; + return a.isUnsignedInt(comp) != b.isUnsignedInt(comp); +} + +pub fn makeReal(ty: Type) Type { + // TODO discards attributed/typeof + var base = ty.canonicalize(.standard); + switch (base.specifier) { + .complex_float, .complex_double, .complex_long_double, .complex_float80, .complex_float128 => { + base.specifier = @enumFromInt(@intFromEnum(base.specifier) - 5); + return base; + }, + .complex_char, .complex_schar, .complex_uchar, .complex_short, .complex_ushort, .complex_int, .complex_uint, .complex_long, .complex_ulong, .complex_long_long, .complex_ulong_long, .complex_int128, .complex_uint128 => { + base.specifier = @enumFromInt(@intFromEnum(base.specifier) - 13); + return base; + }, + .complex_bit_int => { + base.specifier = .bit_int; + return base; + }, + else => return ty, + } +} + +pub fn makeComplex(ty: Type) Type { + // TODO discards attributed/typeof + var base = ty.canonicalize(.standard); + switch (base.specifier) { + .float, .double, .long_double, .float80, .float128 => { + base.specifier = @enumFromInt(@intFromEnum(base.specifier) + 5); + return base; + }, + .char, .schar, .uchar, .short, .ushort, .int, .uint, .long, .ulong, .long_long, .ulong_long, .int128, .uint128 => { + base.specifier = @enumFromInt(@intFromEnum(base.specifier) + 13); + return base; + }, + .bit_int => { + base.specifier = .complex_bit_int; + return base; + }, + else => return ty, + } +} + +/// Combines types recursively in the order they were parsed, uses `.void` specifier as a sentinel value. +pub fn combine(inner: *Type, outer: Type) Parser.Error!void { + switch (inner.specifier) { + .pointer => return inner.data.sub_type.combine(outer), + .unspecified_variable_len_array => { + try inner.data.sub_type.combine(outer); + }, + .variable_len_array => { + try inner.data.expr.ty.combine(outer); + }, + .array, .static_array, .incomplete_array => { + try inner.data.array.elem.combine(outer); + }, + .func, .var_args_func, .old_style_func => { + try inner.data.func.return_type.combine(outer); + }, + .decayed_array, + .decayed_static_array, + .decayed_incomplete_array, + .decayed_variable_len_array, + .decayed_unspecified_variable_len_array, + .decayed_typeof_type, + .decayed_typeof_expr, + => unreachable, // type should not be able to decay before being combined + .void => inner.* = outer, + else => unreachable, + } +} + +pub fn validateCombinedType(ty: Type, p: *Parser, source_tok: TokenIndex) Parser.Error!void { + switch (ty.specifier) { + .pointer => return ty.data.sub_type.validateCombinedType(p, source_tok), + .unspecified_variable_len_array, + .variable_len_array, + .array, + .static_array, + .incomplete_array, + => { + const elem_ty = ty.elemType(); + if (elem_ty.hasIncompleteSize()) { + try p.errStr(.array_incomplete_elem, source_tok, try p.typeStr(elem_ty)); + return error.ParsingFailed; + } + if (elem_ty.isFunc()) { + try p.errTok(.array_func_elem, source_tok); + return error.ParsingFailed; + } + if (elem_ty.specifier == .static_array and elem_ty.isArray()) { + try p.errTok(.static_non_outermost_array, source_tok); + } + if (elem_ty.anyQual() and elem_ty.isArray()) { + try p.errTok(.qualifier_non_outermost_array, source_tok); + } + }, + .func, .var_args_func, .old_style_func => { + const ret_ty = &ty.data.func.return_type; + if (ret_ty.isArray()) try p.errTok(.func_cannot_return_array, source_tok); + if (ret_ty.isFunc()) try p.errTok(.func_cannot_return_func, source_tok); + if (ret_ty.qual.@"const") { + try p.errStr(.qual_on_ret_type, source_tok, "const"); + ret_ty.qual.@"const" = false; + } + if (ret_ty.qual.@"volatile") { + try p.errStr(.qual_on_ret_type, source_tok, "volatile"); + ret_ty.qual.@"volatile" = false; + } + if (ret_ty.qual.atomic) { + try p.errStr(.qual_on_ret_type, source_tok, "atomic"); + ret_ty.qual.atomic = false; + } + if (ret_ty.is(.fp16) and !p.comp.hasHalfPrecisionFloatABI()) { + try p.errStr(.suggest_pointer_for_invalid_fp16, source_tok, "function return value"); + } + }, + .typeof_type, .decayed_typeof_type => return ty.data.sub_type.validateCombinedType(p, source_tok), + .typeof_expr, .decayed_typeof_expr => return ty.data.expr.ty.validateCombinedType(p, source_tok), + .attributed => return ty.data.attributed.base.validateCombinedType(p, source_tok), + else => {}, + } +} + +/// An unfinished Type +pub const Builder = struct { + complex_tok: ?TokenIndex = null, + bit_int_tok: ?TokenIndex = null, + auto_type_tok: ?TokenIndex = null, + typedef: ?struct { + tok: TokenIndex, + ty: Type, + } = null, + specifier: Builder.Specifier = .none, + qual: Qualifiers.Builder = .{}, + typeof: ?Type = null, + /// When true an error is returned instead of adding a diagnostic message. + /// Used for trying to combine typedef types. + error_on_invalid: bool = false, + + pub const Specifier = union(enum) { + none, + void, + /// GNU __auto_type extension + auto_type, + nullptr_t, + bool, + char, + schar, + uchar, + complex_char, + complex_schar, + complex_uchar, + + unsigned, + signed, + short, + sshort, + ushort, + short_int, + sshort_int, + ushort_int, + int, + sint, + uint, + long, + slong, + ulong, + long_int, + slong_int, + ulong_int, + long_long, + slong_long, + ulong_long, + long_long_int, + slong_long_int, + ulong_long_int, + int128, + sint128, + uint128, + complex_unsigned, + complex_signed, + complex_short, + complex_sshort, + complex_ushort, + complex_short_int, + complex_sshort_int, + complex_ushort_int, + complex_int, + complex_sint, + complex_uint, + complex_long, + complex_slong, + complex_ulong, + complex_long_int, + complex_slong_int, + complex_ulong_int, + complex_long_long, + complex_slong_long, + complex_ulong_long, + complex_long_long_int, + complex_slong_long_int, + complex_ulong_long_int, + complex_int128, + complex_sint128, + complex_uint128, + bit_int: i16, + sbit_int: i16, + ubit_int: i16, + complex_bit_int: i16, + complex_sbit_int: i16, + complex_ubit_int: i16, + + fp16, + float16, + float, + double, + long_double, + float80, + float128, + complex, + complex_float, + complex_double, + complex_long_double, + complex_float80, + complex_float128, + + pointer: *Type, + unspecified_variable_len_array: *Type, + decayed_unspecified_variable_len_array: *Type, + func: *Func, + var_args_func: *Func, + old_style_func: *Func, + array: *Array, + decayed_array: *Array, + static_array: *Array, + decayed_static_array: *Array, + incomplete_array: *Array, + decayed_incomplete_array: *Array, + vector: *Array, + variable_len_array: *Expr, + decayed_variable_len_array: *Expr, + @"struct": *Record, + @"union": *Record, + @"enum": *Enum, + typeof_type: *Type, + decayed_typeof_type: *Type, + typeof_expr: *Expr, + decayed_typeof_expr: *Expr, + + attributed: *Attributed, + + pub fn str(spec: Builder.Specifier, langopts: LangOpts) ?[]const u8 { + return switch (spec) { + .none => unreachable, + .void => "void", + .auto_type => "__auto_type", + .nullptr_t => "nullptr_t", + .bool => if (langopts.standard.atLeast(.c2x)) "bool" else "_Bool", + .char => "char", + .schar => "signed char", + .uchar => "unsigned char", + .unsigned => "unsigned", + .signed => "signed", + .short => "short", + .ushort => "unsigned short", + .sshort => "signed short", + .short_int => "short int", + .sshort_int => "signed short int", + .ushort_int => "unsigned short int", + .int => "int", + .sint => "signed int", + .uint => "unsigned int", + .long => "long", + .slong => "signed long", + .ulong => "unsigned long", + .long_int => "long int", + .slong_int => "signed long int", + .ulong_int => "unsigned long int", + .long_long => "long long", + .slong_long => "signed long long", + .ulong_long => "unsigned long long", + .long_long_int => "long long int", + .slong_long_int => "signed long long int", + .ulong_long_int => "unsigned long long int", + .int128 => "__int128", + .sint128 => "signed __int128", + .uint128 => "unsigned __int128", + .bit_int => "_BitInt", + .sbit_int => "signed _BitInt", + .ubit_int => "unsigned _BitInt", + .complex_char => "_Complex char", + .complex_schar => "_Complex signed char", + .complex_uchar => "_Complex unsigned char", + .complex_unsigned => "_Complex unsigned", + .complex_signed => "_Complex signed", + .complex_short => "_Complex short", + .complex_ushort => "_Complex unsigned short", + .complex_sshort => "_Complex signed short", + .complex_short_int => "_Complex short int", + .complex_sshort_int => "_Complex signed short int", + .complex_ushort_int => "_Complex unsigned short int", + .complex_int => "_Complex int", + .complex_sint => "_Complex signed int", + .complex_uint => "_Complex unsigned int", + .complex_long => "_Complex long", + .complex_slong => "_Complex signed long", + .complex_ulong => "_Complex unsigned long", + .complex_long_int => "_Complex long int", + .complex_slong_int => "_Complex signed long int", + .complex_ulong_int => "_Complex unsigned long int", + .complex_long_long => "_Complex long long", + .complex_slong_long => "_Complex signed long long", + .complex_ulong_long => "_Complex unsigned long long", + .complex_long_long_int => "_Complex long long int", + .complex_slong_long_int => "_Complex signed long long int", + .complex_ulong_long_int => "_Complex unsigned long long int", + .complex_int128 => "_Complex __int128", + .complex_sint128 => "_Complex signed __int128", + .complex_uint128 => "_Complex unsigned __int128", + .complex_bit_int => "_Complex _BitInt", + .complex_sbit_int => "_Complex signed _BitInt", + .complex_ubit_int => "_Complex unsigned _BitInt", + + .fp16 => "__fp16", + .float16 => "_Float16", + .float => "float", + .double => "double", + .long_double => "long double", + .float80 => "__float80", + .float128 => "__float128", + .complex => "_Complex", + .complex_float => "_Complex float", + .complex_double => "_Complex double", + .complex_long_double => "_Complex long double", + .complex_float80 => "_Complex __float80", + .complex_float128 => "_Complex __float128", + + .attributed => |attributed| Builder.fromType(attributed.base).str(langopts), + + else => null, + }; + } + }; + + pub fn finish(b: Builder, p: *Parser) Parser.Error!Type { + var ty: Type = .{ .specifier = undefined }; + if (b.typedef) |typedef| { + ty = typedef.ty; + if (ty.isArray()) { + var elem = ty.elemType(); + try b.qual.finish(p, &elem); + // TODO this really should be easier + switch (ty.specifier) { + .array, .static_array, .incomplete_array => { + var old = ty.data.array; + ty.data.array = try p.arena.create(Array); + ty.data.array.* = .{ + .len = old.len, + .elem = elem, + }; + }, + .variable_len_array, .unspecified_variable_len_array => { + var old = ty.data.expr; + ty.data.expr = try p.arena.create(Expr); + ty.data.expr.* = .{ + .node = old.node, + .ty = elem, + }; + }, + .typeof_type => {}, // TODO handle + .typeof_expr => {}, // TODO handle + .attributed => {}, // TODO handle + else => unreachable, + } + + return ty; + } + try b.qual.finish(p, &ty); + return ty; + } + switch (b.specifier) { + .none => { + if (b.typeof) |typeof| { + ty = typeof; + } else { + ty.specifier = .int; + try p.err(.missing_type_specifier); + } + }, + .void => ty.specifier = .void, + .auto_type => ty.specifier = .auto_type, + .nullptr_t => unreachable, // nullptr_t can only be accessed via typeof(nullptr) + .bool => ty.specifier = .bool, + .char => ty.specifier = .char, + .schar => ty.specifier = .schar, + .uchar => ty.specifier = .uchar, + .complex_char => ty.specifier = .complex_char, + .complex_schar => ty.specifier = .complex_schar, + .complex_uchar => ty.specifier = .complex_uchar, + + .unsigned => ty.specifier = .uint, + .signed => ty.specifier = .int, + .short_int, .sshort_int, .short, .sshort => ty.specifier = .short, + .ushort, .ushort_int => ty.specifier = .ushort, + .int, .sint => ty.specifier = .int, + .uint => ty.specifier = .uint, + .long, .slong, .long_int, .slong_int => ty.specifier = .long, + .ulong, .ulong_int => ty.specifier = .ulong, + .long_long, .slong_long, .long_long_int, .slong_long_int => ty.specifier = .long_long, + .ulong_long, .ulong_long_int => ty.specifier = .ulong_long, + .int128, .sint128 => ty.specifier = .int128, + .uint128 => ty.specifier = .uint128, + .complex_unsigned => ty.specifier = .complex_uint, + .complex_signed => ty.specifier = .complex_int, + .complex_short_int, .complex_sshort_int, .complex_short, .complex_sshort => ty.specifier = .complex_short, + .complex_ushort, .complex_ushort_int => ty.specifier = .complex_ushort, + .complex_int, .complex_sint => ty.specifier = .complex_int, + .complex_uint => ty.specifier = .complex_uint, + .complex_long, .complex_slong, .complex_long_int, .complex_slong_int => ty.specifier = .complex_long, + .complex_ulong, .complex_ulong_int => ty.specifier = .complex_ulong, + .complex_long_long, .complex_slong_long, .complex_long_long_int, .complex_slong_long_int => ty.specifier = .complex_long_long, + .complex_ulong_long, .complex_ulong_long_int => ty.specifier = .complex_ulong_long, + .complex_int128, .complex_sint128 => ty.specifier = .complex_int128, + .complex_uint128 => ty.specifier = .complex_uint128, + .bit_int, .sbit_int, .ubit_int, .complex_bit_int, .complex_ubit_int, .complex_sbit_int => |bits| { + const unsigned = b.specifier == .ubit_int or b.specifier == .complex_ubit_int; + if (unsigned) { + if (bits < 1) { + try p.errStr(.unsigned_bit_int_too_small, b.bit_int_tok.?, b.specifier.str(p.comp.langopts).?); + return error.ParsingFailed; + } + } else { + if (bits < 2) { + try p.errStr(.signed_bit_int_too_small, b.bit_int_tok.?, b.specifier.str(p.comp.langopts).?); + return error.ParsingFailed; + } + } + if (bits > Compilation.bit_int_max_bits) { + try p.errStr(.bit_int_too_big, b.bit_int_tok.?, b.specifier.str(p.comp.langopts).?); + return error.ParsingFailed; + } + ty.specifier = if (b.complex_tok != null) .complex_bit_int else .bit_int; + ty.data = .{ .int = .{ + .signedness = if (unsigned) .unsigned else .signed, + .bits = @intCast(bits), + } }; + }, + + .fp16 => ty.specifier = .fp16, + .float16 => ty.specifier = .float16, + .float => ty.specifier = .float, + .double => ty.specifier = .double, + .long_double => ty.specifier = .long_double, + .float80 => ty.specifier = .float80, + .float128 => ty.specifier = .float128, + .complex_float => ty.specifier = .complex_float, + .complex_double => ty.specifier = .complex_double, + .complex_long_double => ty.specifier = .complex_long_double, + .complex_float80 => ty.specifier = .complex_float80, + .complex_float128 => ty.specifier = .complex_float128, + .complex => { + try p.errTok(.plain_complex, p.tok_i - 1); + ty.specifier = .complex_double; + }, + + .pointer => |data| { + ty.specifier = .pointer; + ty.data = .{ .sub_type = data }; + }, + .unspecified_variable_len_array => |data| { + ty.specifier = .unspecified_variable_len_array; + ty.data = .{ .sub_type = data }; + }, + .decayed_unspecified_variable_len_array => |data| { + ty.specifier = .decayed_unspecified_variable_len_array; + ty.data = .{ .sub_type = data }; + }, + .func => |data| { + ty.specifier = .func; + ty.data = .{ .func = data }; + }, + .var_args_func => |data| { + ty.specifier = .var_args_func; + ty.data = .{ .func = data }; + }, + .old_style_func => |data| { + ty.specifier = .old_style_func; + ty.data = .{ .func = data }; + }, + .array => |data| { + ty.specifier = .array; + ty.data = .{ .array = data }; + }, + .decayed_array => |data| { + ty.specifier = .decayed_array; + ty.data = .{ .array = data }; + }, + .static_array => |data| { + ty.specifier = .static_array; + ty.data = .{ .array = data }; + }, + .decayed_static_array => |data| { + ty.specifier = .decayed_static_array; + ty.data = .{ .array = data }; + }, + .incomplete_array => |data| { + ty.specifier = .incomplete_array; + ty.data = .{ .array = data }; + }, + .decayed_incomplete_array => |data| { + ty.specifier = .decayed_incomplete_array; + ty.data = .{ .array = data }; + }, + .vector => |data| { + ty.specifier = .vector; + ty.data = .{ .array = data }; + }, + .variable_len_array => |data| { + ty.specifier = .variable_len_array; + ty.data = .{ .expr = data }; + }, + .decayed_variable_len_array => |data| { + ty.specifier = .decayed_variable_len_array; + ty.data = .{ .expr = data }; + }, + .@"struct" => |data| { + ty.specifier = .@"struct"; + ty.data = .{ .record = data }; + }, + .@"union" => |data| { + ty.specifier = .@"union"; + ty.data = .{ .record = data }; + }, + .@"enum" => |data| { + ty.specifier = .@"enum"; + ty.data = .{ .@"enum" = data }; + }, + .typeof_type => |data| { + ty.specifier = .typeof_type; + ty.data = .{ .sub_type = data }; + }, + .decayed_typeof_type => |data| { + ty.specifier = .decayed_typeof_type; + ty.data = .{ .sub_type = data }; + }, + .typeof_expr => |data| { + ty.specifier = .typeof_expr; + ty.data = .{ .expr = data }; + }, + .decayed_typeof_expr => |data| { + ty.specifier = .decayed_typeof_expr; + ty.data = .{ .expr = data }; + }, + .attributed => |data| { + ty.specifier = .attributed; + ty.data = .{ .attributed = data }; + }, + } + if (!ty.isReal() and ty.isInt()) { + if (b.complex_tok) |tok| try p.errTok(.complex_int, tok); + } + try b.qual.finish(p, &ty); + return ty; + } + + fn cannotCombine(b: Builder, p: *Parser, source_tok: TokenIndex) !void { + if (b.error_on_invalid) return error.CannotCombine; + const ty_str = b.specifier.str(p.comp.langopts) orelse try p.typeStr(try b.finish(p)); + try p.errExtra(.cannot_combine_spec, source_tok, .{ .str = ty_str }); + if (b.typedef) |some| try p.errStr(.spec_from_typedef, some.tok, try p.typeStr(some.ty)); + } + + fn duplicateSpec(b: *Builder, p: *Parser, source_tok: TokenIndex, spec: []const u8) !void { + if (b.error_on_invalid) return error.CannotCombine; + if (p.comp.langopts.emulate != .clang) return b.cannotCombine(p, source_tok); + try p.errStr(.duplicate_decl_spec, p.tok_i, spec); + } + + pub fn combineFromTypeof(b: *Builder, p: *Parser, new: Type, source_tok: TokenIndex) Compilation.Error!void { + if (b.typeof != null) return p.errStr(.cannot_combine_spec, source_tok, "typeof"); + if (b.specifier != .none) return p.errStr(.invalid_typeof, source_tok, @tagName(b.specifier)); + const inner = switch (new.specifier) { + .typeof_type => new.data.sub_type.*, + .typeof_expr => new.data.expr.ty, + .nullptr_t => new, // typeof(nullptr) is special-cased to be an unwrapped typeof-expr + else => unreachable, + }; + + b.typeof = switch (inner.specifier) { + .attributed => inner.data.attributed.base, + else => new, + }; + } + + /// Try to combine type from typedef, returns true if successful. + pub fn combineTypedef(b: *Builder, p: *Parser, typedef_ty: Type, name_tok: TokenIndex) bool { + b.error_on_invalid = true; + defer b.error_on_invalid = false; + + const new_spec = fromType(typedef_ty); + b.combineExtra(p, new_spec, 0) catch |err| switch (err) { + error.FatalError => unreachable, // we do not add any diagnostics + error.OutOfMemory => unreachable, // we do not add any diagnostics + error.ParsingFailed => unreachable, // we do not add any diagnostics + error.CannotCombine => return false, + }; + b.typedef = .{ .tok = name_tok, .ty = typedef_ty }; + return true; + } + + pub fn combine(b: *Builder, p: *Parser, new: Builder.Specifier, source_tok: TokenIndex) !void { + b.combineExtra(p, new, source_tok) catch |err| switch (err) { + error.CannotCombine => unreachable, + else => |e| return e, + }; + } + + fn combineExtra(b: *Builder, p: *Parser, new: Builder.Specifier, source_tok: TokenIndex) !void { + if (b.typeof != null) { + if (b.error_on_invalid) return error.CannotCombine; + try p.errStr(.invalid_typeof, source_tok, @tagName(new)); + } + + switch (new) { + .complex => b.complex_tok = source_tok, + .bit_int => b.bit_int_tok = source_tok, + .auto_type => b.auto_type_tok = source_tok, + else => {}, + } + + if (new == .int128 and !target_util.hasInt128(p.comp.target)) { + try p.errStr(.type_not_supported_on_target, source_tok, "__int128"); + } + + switch (new) { + else => switch (b.specifier) { + .none => b.specifier = new, + else => return b.cannotCombine(p, source_tok), + }, + .signed => b.specifier = switch (b.specifier) { + .none => .signed, + .char => .schar, + .short => .sshort, + .short_int => .sshort_int, + .int => .sint, + .long => .slong, + .long_int => .slong_int, + .long_long => .slong_long, + .long_long_int => .slong_long_int, + .int128 => .sint128, + .bit_int => |bits| .{ .sbit_int = bits }, + .complex => .complex_signed, + .complex_char => .complex_schar, + .complex_short => .complex_sshort, + .complex_short_int => .complex_sshort_int, + .complex_int => .complex_sint, + .complex_long => .complex_slong, + .complex_long_int => .complex_slong_int, + .complex_long_long => .complex_slong_long, + .complex_long_long_int => .complex_slong_long_int, + .complex_int128 => .complex_sint128, + .complex_bit_int => |bits| .{ .complex_sbit_int = bits }, + .signed, + .sshort, + .sshort_int, + .sint, + .slong, + .slong_int, + .slong_long, + .slong_long_int, + .sint128, + .sbit_int, + .complex_schar, + .complex_signed, + .complex_sshort, + .complex_sshort_int, + .complex_sint, + .complex_slong, + .complex_slong_int, + .complex_slong_long, + .complex_slong_long_int, + .complex_sint128, + .complex_sbit_int, + => return b.duplicateSpec(p, source_tok, "signed"), + else => return b.cannotCombine(p, source_tok), + }, + .unsigned => b.specifier = switch (b.specifier) { + .none => .unsigned, + .char => .uchar, + .short => .ushort, + .short_int => .ushort_int, + .int => .uint, + .long => .ulong, + .long_int => .ulong_int, + .long_long => .ulong_long, + .long_long_int => .ulong_long_int, + .int128 => .uint128, + .bit_int => |bits| .{ .ubit_int = bits }, + .complex => .complex_unsigned, + .complex_char => .complex_uchar, + .complex_short => .complex_ushort, + .complex_short_int => .complex_ushort_int, + .complex_int => .complex_uint, + .complex_long => .complex_ulong, + .complex_long_int => .complex_ulong_int, + .complex_long_long => .complex_ulong_long, + .complex_long_long_int => .complex_ulong_long_int, + .complex_int128 => .complex_uint128, + .complex_bit_int => |bits| .{ .complex_ubit_int = bits }, + .unsigned, + .ushort, + .ushort_int, + .uint, + .ulong, + .ulong_int, + .ulong_long, + .ulong_long_int, + .uint128, + .ubit_int, + .complex_uchar, + .complex_unsigned, + .complex_ushort, + .complex_ushort_int, + .complex_uint, + .complex_ulong, + .complex_ulong_int, + .complex_ulong_long, + .complex_ulong_long_int, + .complex_uint128, + .complex_ubit_int, + => return b.duplicateSpec(p, source_tok, "unsigned"), + else => return b.cannotCombine(p, source_tok), + }, + .char => b.specifier = switch (b.specifier) { + .none => .char, + .unsigned => .uchar, + .signed => .schar, + .complex => .complex_char, + .complex_signed => .complex_schar, + .complex_unsigned => .complex_uchar, + else => return b.cannotCombine(p, source_tok), + }, + .short => b.specifier = switch (b.specifier) { + .none => .short, + .unsigned => .ushort, + .signed => .sshort, + .int => .short_int, + .sint => .sshort_int, + .uint => .ushort_int, + .complex => .complex_short, + .complex_signed => .complex_sshort, + .complex_unsigned => .complex_ushort, + else => return b.cannotCombine(p, source_tok), + }, + .int => b.specifier = switch (b.specifier) { + .none => .int, + .signed => .sint, + .unsigned => .uint, + .short => .short_int, + .sshort => .sshort_int, + .ushort => .ushort_int, + .long => .long_int, + .slong => .slong_int, + .ulong => .ulong_int, + .long_long => .long_long_int, + .slong_long => .slong_long_int, + .ulong_long => .ulong_long_int, + .complex => .complex_int, + .complex_signed => .complex_sint, + .complex_unsigned => .complex_uint, + .complex_short => .complex_short_int, + .complex_sshort => .complex_sshort_int, + .complex_ushort => .complex_ushort_int, + .complex_long => .complex_long_int, + .complex_slong => .complex_slong_int, + .complex_ulong => .complex_ulong_int, + .complex_long_long => .complex_long_long_int, + .complex_slong_long => .complex_slong_long_int, + .complex_ulong_long => .complex_ulong_long_int, + else => return b.cannotCombine(p, source_tok), + }, + .long => b.specifier = switch (b.specifier) { + .none => .long, + .long => .long_long, + .unsigned => .ulong, + .signed => .long, + .int => .long_int, + .sint => .slong_int, + .ulong => .ulong_long, + .complex => .complex_long, + .complex_signed => .complex_slong, + .complex_unsigned => .complex_ulong, + .complex_long => .complex_long_long, + .complex_slong => .complex_slong_long, + .complex_ulong => .complex_ulong_long, + else => return b.cannotCombine(p, source_tok), + }, + .int128 => b.specifier = switch (b.specifier) { + .none => .int128, + .unsigned => .uint128, + .signed => .sint128, + .complex => .complex_int128, + .complex_signed => .complex_sint128, + .complex_unsigned => .complex_uint128, + else => return b.cannotCombine(p, source_tok), + }, + .bit_int => b.specifier = switch (b.specifier) { + .none => .{ .bit_int = new.bit_int }, + .unsigned => .{ .ubit_int = new.bit_int }, + .signed => .{ .sbit_int = new.bit_int }, + .complex => .{ .complex_bit_int = new.bit_int }, + .complex_signed => .{ .complex_sbit_int = new.bit_int }, + .complex_unsigned => .{ .complex_ubit_int = new.bit_int }, + else => return b.cannotCombine(p, source_tok), + }, + .auto_type => b.specifier = switch (b.specifier) { + .none => .auto_type, + else => return b.cannotCombine(p, source_tok), + }, + .fp16 => b.specifier = switch (b.specifier) { + .none => .fp16, + else => return b.cannotCombine(p, source_tok), + }, + .float16 => b.specifier = switch (b.specifier) { + .none => .float16, + else => return b.cannotCombine(p, source_tok), + }, + .float => b.specifier = switch (b.specifier) { + .none => .float, + .complex => .complex_float, + else => return b.cannotCombine(p, source_tok), + }, + .double => b.specifier = switch (b.specifier) { + .none => .double, + .long => .long_double, + .complex_long => .complex_long_double, + .complex => .complex_double, + else => return b.cannotCombine(p, source_tok), + }, + .float80 => b.specifier = switch (b.specifier) { + .none => .float80, + .complex => .complex_float80, + else => return b.cannotCombine(p, source_tok), + }, + .float128 => b.specifier = switch (b.specifier) { + .none => .float128, + .complex => .complex_float128, + else => return b.cannotCombine(p, source_tok), + }, + .complex => b.specifier = switch (b.specifier) { + .none => .complex, + .float => .complex_float, + .double => .complex_double, + .long_double => .complex_long_double, + .float80 => .complex_float80, + .float128 => .complex_float128, + .char => .complex_char, + .schar => .complex_schar, + .uchar => .complex_uchar, + .unsigned => .complex_unsigned, + .signed => .complex_signed, + .short => .complex_short, + .sshort => .complex_sshort, + .ushort => .complex_ushort, + .short_int => .complex_short_int, + .sshort_int => .complex_sshort_int, + .ushort_int => .complex_ushort_int, + .int => .complex_int, + .sint => .complex_sint, + .uint => .complex_uint, + .long => .complex_long, + .slong => .complex_slong, + .ulong => .complex_ulong, + .long_int => .complex_long_int, + .slong_int => .complex_slong_int, + .ulong_int => .complex_ulong_int, + .long_long => .complex_long_long, + .slong_long => .complex_slong_long, + .ulong_long => .complex_ulong_long, + .long_long_int => .complex_long_long_int, + .slong_long_int => .complex_slong_long_int, + .ulong_long_int => .complex_ulong_long_int, + .int128 => .complex_int128, + .sint128 => .complex_sint128, + .uint128 => .complex_uint128, + .bit_int => |bits| .{ .complex_bit_int = bits }, + .sbit_int => |bits| .{ .complex_sbit_int = bits }, + .ubit_int => |bits| .{ .complex_ubit_int = bits }, + .complex, + .complex_float, + .complex_double, + .complex_long_double, + .complex_float80, + .complex_float128, + .complex_char, + .complex_schar, + .complex_uchar, + .complex_unsigned, + .complex_signed, + .complex_short, + .complex_sshort, + .complex_ushort, + .complex_short_int, + .complex_sshort_int, + .complex_ushort_int, + .complex_int, + .complex_sint, + .complex_uint, + .complex_long, + .complex_slong, + .complex_ulong, + .complex_long_int, + .complex_slong_int, + .complex_ulong_int, + .complex_long_long, + .complex_slong_long, + .complex_ulong_long, + .complex_long_long_int, + .complex_slong_long_int, + .complex_ulong_long_int, + .complex_int128, + .complex_sint128, + .complex_uint128, + .complex_bit_int, + .complex_sbit_int, + .complex_ubit_int, + => return b.duplicateSpec(p, source_tok, "_Complex"), + else => return b.cannotCombine(p, source_tok), + }, + } + } + + pub fn fromType(ty: Type) Builder.Specifier { + return switch (ty.specifier) { + .void => .void, + .auto_type => .auto_type, + .nullptr_t => .nullptr_t, + .bool => .bool, + .char => .char, + .schar => .schar, + .uchar => .uchar, + .short => .short, + .ushort => .ushort, + .int => .int, + .uint => .uint, + .long => .long, + .ulong => .ulong, + .long_long => .long_long, + .ulong_long => .ulong_long, + .int128 => .int128, + .uint128 => .uint128, + .bit_int => if (ty.data.int.signedness == .unsigned) { + return .{ .ubit_int = ty.data.int.bits }; + } else { + return .{ .bit_int = ty.data.int.bits }; + }, + .complex_char => .complex_char, + .complex_schar => .complex_schar, + .complex_uchar => .complex_uchar, + .complex_short => .complex_short, + .complex_ushort => .complex_ushort, + .complex_int => .complex_int, + .complex_uint => .complex_uint, + .complex_long => .complex_long, + .complex_ulong => .complex_ulong, + .complex_long_long => .complex_long_long, + .complex_ulong_long => .complex_ulong_long, + .complex_int128 => .complex_int128, + .complex_uint128 => .complex_uint128, + .complex_bit_int => if (ty.data.int.signedness == .unsigned) { + return .{ .complex_ubit_int = ty.data.int.bits }; + } else { + return .{ .complex_bit_int = ty.data.int.bits }; + }, + .fp16 => .fp16, + .float16 => .float16, + .float => .float, + .double => .double, + .float80 => .float80, + .float128 => .float128, + .long_double => .long_double, + .complex_float => .complex_float, + .complex_double => .complex_double, + .complex_long_double => .complex_long_double, + .complex_float80 => .complex_float80, + .complex_float128 => .complex_float128, + + .pointer => .{ .pointer = ty.data.sub_type }, + .unspecified_variable_len_array => .{ .unspecified_variable_len_array = ty.data.sub_type }, + .decayed_unspecified_variable_len_array => .{ .decayed_unspecified_variable_len_array = ty.data.sub_type }, + .func => .{ .func = ty.data.func }, + .var_args_func => .{ .var_args_func = ty.data.func }, + .old_style_func => .{ .old_style_func = ty.data.func }, + .array => .{ .array = ty.data.array }, + .decayed_array => .{ .decayed_array = ty.data.array }, + .static_array => .{ .static_array = ty.data.array }, + .decayed_static_array => .{ .decayed_static_array = ty.data.array }, + .incomplete_array => .{ .incomplete_array = ty.data.array }, + .decayed_incomplete_array => .{ .decayed_incomplete_array = ty.data.array }, + .vector => .{ .vector = ty.data.array }, + .variable_len_array => .{ .variable_len_array = ty.data.expr }, + .decayed_variable_len_array => .{ .decayed_variable_len_array = ty.data.expr }, + .@"struct" => .{ .@"struct" = ty.data.record }, + .@"union" => .{ .@"union" = ty.data.record }, + .@"enum" => .{ .@"enum" = ty.data.@"enum" }, + + .typeof_type => .{ .typeof_type = ty.data.sub_type }, + .decayed_typeof_type => .{ .decayed_typeof_type = ty.data.sub_type }, + .typeof_expr => .{ .typeof_expr = ty.data.expr }, + .decayed_typeof_expr => .{ .decayed_typeof_expr = ty.data.expr }, + + .attributed => .{ .attributed = ty.data.attributed }, + else => unreachable, + }; + } +}; + +pub fn getAttribute(ty: Type, comptime tag: Attribute.Tag) ?Attribute.ArgumentsForTag(tag) { + switch (ty.specifier) { + .typeof_type => return ty.data.sub_type.getAttribute(tag), + .typeof_expr => return ty.data.expr.ty.getAttribute(tag), + .attributed => { + for (ty.data.attributed.attributes) |attribute| { + if (attribute.tag == tag) return @field(attribute.args, @tagName(tag)); + } + return null; + }, + else => return null, + } +} + +pub fn hasAttribute(ty: Type, tag: Attribute.Tag) bool { + for (ty.getAttributes()) |attr| { + if (attr.tag == tag) return true; + } + return false; +} + +/// printf format modifier +pub fn formatModifier(ty: Type) []const u8 { + return switch (ty.specifier) { + .schar, .uchar => "hh", + .short, .ushort => "h", + .int, .uint => "", + .long, .ulong => "l", + .long_long, .ulong_long => "ll", + else => unreachable, + }; +} + +/// Suffix for integer values of this type +pub fn intValueSuffix(ty: Type, comp: *const Compilation) []const u8 { + return switch (ty.specifier) { + .schar, .short, .int => "", + .long => "L", + .long_long => "LL", + .uchar, .char => { + if (ty.specifier == .char and comp.getCharSignedness() == .signed) return ""; + // Only 8-bit char supported currently; + // TODO: handle platforms with 16-bit int + 16-bit char + std.debug.assert(ty.sizeof(comp).? == 1); + return ""; + }, + .ushort => { + if (ty.sizeof(comp).? < int.sizeof(comp).?) { + return ""; + } + return "U"; + }, + .uint => "U", + .ulong => "UL", + .ulong_long => "ULL", + else => unreachable, // not integer + }; +} + +/// Print type in C style +pub fn print(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: anytype) @TypeOf(w).Error!void { + _ = try ty.printPrologue(mapper, langopts, w); + try ty.printEpilogue(mapper, langopts, w); +} + +pub fn printNamed(ty: Type, name: []const u8, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: anytype) @TypeOf(w).Error!void { + const simple = try ty.printPrologue(mapper, langopts, w); + if (simple) try w.writeByte(' '); + try w.writeAll(name); + try ty.printEpilogue(mapper, langopts, w); +} + +const StringGetter = fn (TokenIndex) []const u8; + +/// return true if `ty` is simple +fn printPrologue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: anytype) @TypeOf(w).Error!bool { + if (ty.qual.atomic) { + var non_atomic_ty = ty; + non_atomic_ty.qual.atomic = false; + try w.writeAll("_Atomic("); + try non_atomic_ty.print(mapper, langopts, w); + try w.writeAll(")"); + return true; + } + switch (ty.specifier) { + .pointer, + .decayed_array, + .decayed_static_array, + .decayed_incomplete_array, + .decayed_variable_len_array, + .decayed_unspecified_variable_len_array, + .decayed_typeof_type, + .decayed_typeof_expr, + => { + const elem_ty = ty.elemType(); + const simple = try elem_ty.printPrologue(mapper, langopts, w); + if (simple) try w.writeByte(' '); + if (elem_ty.isFunc() or elem_ty.isArray()) try w.writeByte('('); + try w.writeByte('*'); + try ty.qual.dump(w); + return false; + }, + .func, .var_args_func, .old_style_func => { + const ret_ty = ty.data.func.return_type; + const simple = try ret_ty.printPrologue(mapper, langopts, w); + if (simple) try w.writeByte(' '); + return false; + }, + .array, .static_array, .incomplete_array, .unspecified_variable_len_array, .variable_len_array => { + const elem_ty = ty.elemType(); + const simple = try elem_ty.printPrologue(mapper, langopts, w); + if (simple) try w.writeByte(' '); + return false; + }, + .typeof_type, .typeof_expr => { + const actual = ty.canonicalize(.standard); + return actual.printPrologue(mapper, langopts, w); + }, + .attributed => { + const actual = ty.canonicalize(.standard); + return actual.printPrologue(mapper, langopts, w); + }, + else => {}, + } + try ty.qual.dump(w); + + switch (ty.specifier) { + .@"enum" => if (ty.data.@"enum".fixed) { + try w.print("enum {s}: ", .{mapper.lookup(ty.data.@"enum".name)}); + try ty.data.@"enum".tag_ty.dump(mapper, langopts, w); + } else { + try w.print("enum {s}", .{mapper.lookup(ty.data.@"enum".name)}); + }, + .@"struct" => try w.print("struct {s}", .{mapper.lookup(ty.data.record.name)}), + .@"union" => try w.print("union {s}", .{mapper.lookup(ty.data.record.name)}), + .vector => { + const len = ty.data.array.len; + const elem_ty = ty.data.array.elem; + try w.print("__attribute__((__vector_size__({d} * sizeof(", .{len}); + _ = try elem_ty.printPrologue(mapper, langopts, w); + try w.writeAll(")))) "); + _ = try elem_ty.printPrologue(mapper, langopts, w); + try w.print(" (vector of {d} '", .{len}); + _ = try elem_ty.printPrologue(mapper, langopts, w); + try w.writeAll("' values)"); + }, + else => try w.writeAll(Builder.fromType(ty).str(langopts).?), + } + return true; +} + +fn printEpilogue(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: anytype) @TypeOf(w).Error!void { + if (ty.qual.atomic) return; + switch (ty.specifier) { + .pointer, + .decayed_array, + .decayed_static_array, + .decayed_incomplete_array, + .decayed_variable_len_array, + .decayed_unspecified_variable_len_array, + .decayed_typeof_type, + .decayed_typeof_expr, + => { + const elem_ty = ty.elemType(); + if (elem_ty.isFunc() or elem_ty.isArray()) try w.writeByte(')'); + try elem_ty.printEpilogue(mapper, langopts, w); + }, + .func, .var_args_func, .old_style_func => { + try w.writeByte('('); + for (ty.data.func.params, 0..) |param, i| { + if (i != 0) try w.writeAll(", "); + _ = try param.ty.printPrologue(mapper, langopts, w); + try param.ty.printEpilogue(mapper, langopts, w); + } + if (ty.specifier != .func) { + if (ty.data.func.params.len != 0) try w.writeAll(", "); + try w.writeAll("..."); + } else if (ty.data.func.params.len == 0) { + try w.writeAll("void"); + } + try w.writeByte(')'); + try ty.data.func.return_type.printEpilogue(mapper, langopts, w); + }, + .array, .static_array => { + try w.writeByte('['); + if (ty.specifier == .static_array) try w.writeAll("static "); + try ty.qual.dump(w); + try w.print("{d}]", .{ty.data.array.len}); + try ty.data.array.elem.printEpilogue(mapper, langopts, w); + }, + .incomplete_array => { + try w.writeByte('['); + try ty.qual.dump(w); + try w.writeByte(']'); + try ty.data.array.elem.printEpilogue(mapper, langopts, w); + }, + .unspecified_variable_len_array => { + try w.writeByte('['); + try ty.qual.dump(w); + try w.writeAll("*]"); + try ty.data.sub_type.printEpilogue(mapper, langopts, w); + }, + .variable_len_array => { + try w.writeByte('['); + try ty.qual.dump(w); + try w.writeAll("]"); + try ty.data.expr.ty.printEpilogue(mapper, langopts, w); + }, + .typeof_type, .typeof_expr => { + const actual = ty.canonicalize(.standard); + try actual.printEpilogue(mapper, langopts, w); + }, + .attributed => { + const actual = ty.canonicalize(.standard); + try actual.printEpilogue(mapper, langopts, w); + }, + else => {}, + } +} + +/// Useful for debugging, too noisy to be enabled by default. +const dump_detailed_containers = false; + +// Print as Zig types since those are actually readable +pub fn dump(ty: Type, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: anytype) @TypeOf(w).Error!void { + try ty.qual.dump(w); + switch (ty.specifier) { + .invalid => try w.writeAll("invalid"), + .pointer => { + try w.writeAll("*"); + try ty.data.sub_type.dump(mapper, langopts, w); + }, + .func, .var_args_func, .old_style_func => { + try w.writeAll("fn ("); + for (ty.data.func.params, 0..) |param, i| { + if (i != 0) try w.writeAll(", "); + if (param.name != .empty) try w.print("{s}: ", .{mapper.lookup(param.name)}); + try param.ty.dump(mapper, langopts, w); + } + if (ty.specifier != .func) { + if (ty.data.func.params.len != 0) try w.writeAll(", "); + try w.writeAll("..."); + } + try w.writeAll(") "); + try ty.data.func.return_type.dump(mapper, langopts, w); + }, + .array, .static_array, .decayed_array, .decayed_static_array => { + if (ty.specifier == .decayed_array or ty.specifier == .decayed_static_array) try w.writeByte('d'); + try w.writeByte('['); + if (ty.specifier == .static_array or ty.specifier == .decayed_static_array) try w.writeAll("static "); + try w.print("{d}]", .{ty.data.array.len}); + try ty.data.array.elem.dump(mapper, langopts, w); + }, + .vector => { + try w.print("vector({d}, ", .{ty.data.array.len}); + try ty.data.array.elem.dump(mapper, langopts, w); + try w.writeAll(")"); + }, + .incomplete_array, .decayed_incomplete_array => { + if (ty.specifier == .decayed_incomplete_array) try w.writeByte('d'); + try w.writeAll("[]"); + try ty.data.array.elem.dump(mapper, langopts, w); + }, + .@"enum" => { + const enum_ty = ty.data.@"enum"; + if (enum_ty.isIncomplete() and !enum_ty.fixed) { + try w.print("enum {s}", .{mapper.lookup(enum_ty.name)}); + } else { + try w.print("enum {s}: ", .{mapper.lookup(enum_ty.name)}); + try enum_ty.tag_ty.dump(mapper, langopts, w); + } + if (dump_detailed_containers) try dumpEnum(enum_ty, mapper, w); + }, + .@"struct" => { + try w.print("struct {s}", .{mapper.lookup(ty.data.record.name)}); + if (dump_detailed_containers) try dumpRecord(ty.data.record, mapper, langopts, w); + }, + .@"union" => { + try w.print("union {s}", .{mapper.lookup(ty.data.record.name)}); + if (dump_detailed_containers) try dumpRecord(ty.data.record, mapper, langopts, w); + }, + .unspecified_variable_len_array, .decayed_unspecified_variable_len_array => { + if (ty.specifier == .decayed_unspecified_variable_len_array) try w.writeByte('d'); + try w.writeAll("[*]"); + try ty.data.sub_type.dump(mapper, langopts, w); + }, + .variable_len_array, .decayed_variable_len_array => { + if (ty.specifier == .decayed_variable_len_array) try w.writeByte('d'); + try w.writeAll("[]"); + try ty.data.expr.ty.dump(mapper, langopts, w); + }, + .typeof_type, .decayed_typeof_type => { + try w.writeAll("typeof("); + try ty.data.sub_type.dump(mapper, langopts, w); + try w.writeAll(")"); + }, + .typeof_expr, .decayed_typeof_expr => { + try w.writeAll("typeof(: "); + try ty.data.expr.ty.dump(mapper, langopts, w); + try w.writeAll(")"); + }, + .attributed => { + try w.writeAll("attributed("); + try ty.data.attributed.base.dump(mapper, langopts, w); + try w.writeAll(")"); + }, + else => { + try w.writeAll(Builder.fromType(ty).str(langopts).?); + if (ty.specifier == .bit_int or ty.specifier == .complex_bit_int) { + try w.print("({d})", .{ty.data.int.bits}); + } + }, + } +} + +fn dumpEnum(@"enum": *Enum, mapper: StringInterner.TypeMapper, w: anytype) @TypeOf(w).Error!void { + try w.writeAll(" {"); + for (@"enum".fields) |field| { + try w.print(" {s} = {d},", .{ mapper.lookup(field.name), field.value }); + } + try w.writeAll(" }"); +} + +fn dumpRecord(record: *Record, mapper: StringInterner.TypeMapper, langopts: LangOpts, w: anytype) @TypeOf(w).Error!void { + try w.writeAll(" {"); + for (record.fields) |field| { + try w.writeByte(' '); + try field.ty.dump(mapper, langopts, w); + try w.print(" {s}: {d};", .{ mapper.lookup(field.name), field.bit_width }); + } + try w.writeAll(" }"); +} diff --git a/deps/aro/Value.zig b/deps/aro/Value.zig new file mode 100644 index 000000000000..58a058c33e8c --- /dev/null +++ b/deps/aro/Value.zig @@ -0,0 +1,601 @@ +const std = @import("std"); +const assert = std.debug.assert; +const Compilation = @import("Compilation.zig"); +const Type = @import("Type.zig"); + +const Value = @This(); + +pub const ByteRange = struct { + start: u32, + end: u32, + + pub fn len(self: ByteRange) u32 { + return self.end - self.start; + } + + pub fn trim(self: ByteRange, amount: u32) ByteRange { + std.debug.assert(self.start <= self.end - amount); + return .{ .start = self.start, .end = self.end - amount }; + } + + pub fn slice(self: ByteRange, all_bytes: []const u8) []const u8 { + return all_bytes[self.start..self.end]; + } +}; + +tag: Tag = .unavailable, +data: union { + none: void, + int: u64, + float: f64, + bytes: ByteRange, +} = .{ .none = {} }, + +const Tag = enum { + unavailable, + nullptr_t, + /// int is used to store integer, boolean and pointer values + int, + float, + bytes, +}; + +pub fn zero(v: Value) Value { + return switch (v.tag) { + .int => int(0), + .float => float(0), + else => unreachable, + }; +} + +pub fn one(v: Value) Value { + return switch (v.tag) { + .int => int(1), + .float => float(1), + else => unreachable, + }; +} + +pub fn int(v: anytype) Value { + if (@TypeOf(v) == comptime_int or @typeInfo(@TypeOf(v)).Int.signedness == .unsigned) + return .{ .tag = .int, .data = .{ .int = v } } + else + return .{ .tag = .int, .data = .{ .int = @bitCast(@as(i64, v)) } }; +} + +pub fn float(v: anytype) Value { + return .{ .tag = .float, .data = .{ .float = v } }; +} + +pub fn bytes(start: u32, end: u32) Value { + return .{ .tag = .bytes, .data = .{ .bytes = .{ .start = start, .end = end } } }; +} + +pub fn signExtend(v: Value, old_ty: Type, comp: *Compilation) i64 { + const size = old_ty.sizeof(comp).?; + return switch (size) { + 1 => v.getInt(i8), + 2 => v.getInt(i16), + 4 => v.getInt(i32), + 8 => v.getInt(i64), + else => unreachable, + }; +} + +/// Number of bits needed to hold `v` which is of type `ty`. +/// Asserts that `v` is not negative +pub fn minUnsignedBits(v: Value, ty: Type, comp: *const Compilation) usize { + assert(v.compare(.gte, Value.int(0), ty, comp)); + return switch (ty.sizeof(comp).?) { + 1 => 8 - @clz(v.getInt(u8)), + 2 => 16 - @clz(v.getInt(u16)), + 4 => 32 - @clz(v.getInt(u32)), + 8 => 64 - @clz(v.getInt(u64)), + else => unreachable, + }; +} + +test "minUnsignedBits" { + const Test = struct { + fn checkIntBits(comp: *const Compilation, specifier: Type.Specifier, v: u64, expected: usize) !void { + const val = Value.int(v); + try std.testing.expectEqual(expected, val.minUnsignedBits(.{ .specifier = specifier }, comp)); + } + }; + + var comp = Compilation.init(std.testing.allocator); + defer comp.deinit(); + comp.target = (try std.zig.CrossTarget.parse(.{ .arch_os_abi = "x86_64-linux-gnu" })).toTarget(); + + try Test.checkIntBits(&comp, .int, 0, 0); + try Test.checkIntBits(&comp, .int, 1, 1); + try Test.checkIntBits(&comp, .int, 2, 2); + try Test.checkIntBits(&comp, .int, std.math.maxInt(i8), 7); + try Test.checkIntBits(&comp, .int, std.math.maxInt(u8), 8); + try Test.checkIntBits(&comp, .int, std.math.maxInt(i16), 15); + try Test.checkIntBits(&comp, .int, std.math.maxInt(u16), 16); + try Test.checkIntBits(&comp, .int, std.math.maxInt(i32), 31); + try Test.checkIntBits(&comp, .uint, std.math.maxInt(u32), 32); + try Test.checkIntBits(&comp, .long, std.math.maxInt(i64), 63); + try Test.checkIntBits(&comp, .ulong, std.math.maxInt(u64), 64); + try Test.checkIntBits(&comp, .long_long, std.math.maxInt(i64), 63); + try Test.checkIntBits(&comp, .ulong_long, std.math.maxInt(u64), 64); +} + +/// Minimum number of bits needed to represent `v` in 2's complement notation +/// Asserts that `v` is negative. +pub fn minSignedBits(v: Value, ty: Type, comp: *const Compilation) usize { + assert(v.compare(.lt, Value.int(0), ty, comp)); + return switch (ty.sizeof(comp).?) { + 1 => 8 - @clz(~v.getInt(u8)) + 1, + 2 => 16 - @clz(~v.getInt(u16)) + 1, + 4 => 32 - @clz(~v.getInt(u32)) + 1, + 8 => 64 - @clz(~v.getInt(u64)) + 1, + else => unreachable, + }; +} + +test "minSignedBits" { + const Test = struct { + fn checkIntBits(comp: *const Compilation, specifier: Type.Specifier, v: i64, expected: usize) !void { + const val = Value.int(v); + try std.testing.expectEqual(expected, val.minSignedBits(.{ .specifier = specifier }, comp)); + } + }; + + var comp = Compilation.init(std.testing.allocator); + defer comp.deinit(); + comp.target = (try std.zig.CrossTarget.parse(.{ .arch_os_abi = "x86_64-linux-gnu" })).toTarget(); + + for ([_]Type.Specifier{ .int, .long, .long_long }) |specifier| { + try Test.checkIntBits(&comp, specifier, -1, 1); + try Test.checkIntBits(&comp, specifier, -2, 2); + try Test.checkIntBits(&comp, specifier, -10, 5); + try Test.checkIntBits(&comp, specifier, -101, 8); + + try Test.checkIntBits(&comp, specifier, std.math.minInt(i8), 8); + try Test.checkIntBits(&comp, specifier, std.math.minInt(i16), 16); + try Test.checkIntBits(&comp, specifier, std.math.minInt(i32), 32); + } + + try Test.checkIntBits(&comp, .long, std.math.minInt(i64), 64); + try Test.checkIntBits(&comp, .long_long, std.math.minInt(i64), 64); +} + +pub const FloatToIntChangeKind = enum { + /// value did not change + none, + /// floating point number too small or large for destination integer type + out_of_range, + /// tried to convert a NaN or Infinity + overflow, + /// fractional value was converted to zero + nonzero_to_zero, + /// fractional part truncated + value_changed, +}; + +fn floatToIntExtra(comptime FloatTy: type, int_ty_signedness: std.builtin.Signedness, int_ty_size: u16, v: *Value) FloatToIntChangeKind { + const float_val = v.getFloat(FloatTy); + const was_zero = float_val == 0; + const had_fraction = std.math.modf(float_val).fpart != 0; + + switch (int_ty_signedness) { + inline else => |signedness| switch (int_ty_size) { + inline 1, 2, 4, 8 => |bytecount| { + const IntTy = std.meta.Int(signedness, bytecount * 8); + + const intVal = std.math.lossyCast(IntTy, float_val); + v.* = int(intVal); + if (!was_zero and v.isZero()) return .nonzero_to_zero; + if (float_val <= std.math.minInt(IntTy) or float_val >= std.math.maxInt(IntTy)) return .out_of_range; + if (had_fraction) return .value_changed; + return .none; + }, + else => unreachable, + }, + } +} + +/// Converts the stored value from a float to an integer. +/// `.unavailable` value remains unchanged. +pub fn floatToInt(v: *Value, old_ty: Type, new_ty: Type, comp: *Compilation) FloatToIntChangeKind { + assert(old_ty.isFloat()); + if (v.tag == .unavailable) return .none; + if (new_ty.is(.bool)) { + const was_zero = v.isZero(); + const was_one = v.getFloat(f64) == 1.0; + v.toBool(); + if (was_zero or was_one) return .none; + return .value_changed; + } else if (new_ty.isUnsignedInt(comp) and v.data.float < 0) { + v.* = int(0); + return .out_of_range; + } else if (!std.math.isFinite(v.data.float)) { + v.tag = .unavailable; + return .overflow; + } + const old_size = old_ty.sizeof(comp).?; + const new_size: u16 = @intCast(new_ty.sizeof(comp).?); + if (new_ty.isUnsignedInt(comp)) switch (old_size) { + 1 => unreachable, // promoted to int + 2 => unreachable, // promoted to int + 4 => return floatToIntExtra(f32, .unsigned, new_size, v), + 8 => return floatToIntExtra(f64, .unsigned, new_size, v), + else => unreachable, + } else switch (old_size) { + 1 => unreachable, // promoted to int + 2 => unreachable, // promoted to int + 4 => return floatToIntExtra(f32, .signed, new_size, v), + 8 => return floatToIntExtra(f64, .signed, new_size, v), + else => unreachable, + } +} + +/// Converts the stored value from an integer to a float. +/// `.unavailable` value remains unchanged. +pub fn intToFloat(v: *Value, old_ty: Type, new_ty: Type, comp: *Compilation) void { + assert(old_ty.isInt()); + if (v.tag == .unavailable) return; + if (!new_ty.isReal() or new_ty.sizeof(comp).? > 8) { + v.tag = .unavailable; + } else if (old_ty.isUnsignedInt(comp)) { + v.* = float(@as(f64, @floatFromInt(v.data.int))); + } else { + v.* = float(@as(f64, @floatFromInt(@as(i64, @bitCast(v.data.int))))); + } +} + +/// Truncates or extends bits based on type. +/// old_ty is only used for size. +pub fn intCast(v: *Value, old_ty: Type, new_ty: Type, comp: *Compilation) void { + // assert(old_ty.isInt() and new_ty.isInt()); + if (v.tag == .unavailable) return; + if (new_ty.is(.bool)) return v.toBool(); + if (!old_ty.isUnsignedInt(comp)) { + const size = new_ty.sizeof(comp).?; + switch (size) { + 1 => v.* = int(@as(u8, @truncate(@as(u64, @bitCast(v.signExtend(old_ty, comp)))))), + 2 => v.* = int(@as(u16, @truncate(@as(u64, @bitCast(v.signExtend(old_ty, comp)))))), + 4 => v.* = int(@as(u32, @truncate(@as(u64, @bitCast(v.signExtend(old_ty, comp)))))), + 8 => return, + else => unreachable, + } + } +} + +/// Converts the stored value from an integer to a float. +/// `.unavailable` value remains unchanged. +pub fn floatCast(v: *Value, old_ty: Type, new_ty: Type, comp: *Compilation) void { + assert(old_ty.isFloat() and new_ty.isFloat()); + if (v.tag == .unavailable) return; + const size = new_ty.sizeof(comp).?; + if (!new_ty.isReal() or size > 8) { + v.tag = .unavailable; + } else if (size == 32) { + v.* = float(@as(f32, @floatCast(v.data.float))); + } +} + +/// Truncates data.int to one bit +pub fn toBool(v: *Value) void { + if (v.tag == .unavailable) return; + const res = v.getBool(); + v.* = int(@intFromBool(res)); +} + +pub fn isZero(v: Value) bool { + return switch (v.tag) { + .unavailable => false, + .nullptr_t => false, + .int => v.data.int == 0, + .float => v.data.float == 0, + .bytes => false, + }; +} + +pub fn getBool(v: Value) bool { + return switch (v.tag) { + .unavailable => unreachable, + .nullptr_t => false, + .int => v.data.int != 0, + .float => v.data.float != 0, + .bytes => true, + }; +} + +pub fn getInt(v: Value, comptime T: type) T { + if (T == u64) return v.data.int; + return if (@typeInfo(T).Int.signedness == .unsigned) + @truncate(v.data.int) + else + @truncate(@as(i64, @bitCast(v.data.int))); +} + +pub fn getFloat(v: Value, comptime T: type) T { + if (T == f64) return v.data.float; + return @floatCast(v.data.float); +} + +const bin_overflow = struct { + inline fn addInt(comptime T: type, out: *Value, a: Value, b: Value) bool { + const a_val = a.getInt(T); + const b_val = b.getInt(T); + const sum, const overflowed = @addWithOverflow(a_val, b_val); + out.* = int(sum); + return overflowed != 0; + } + inline fn addFloat(comptime T: type, aa: Value, bb: Value) Value { + const a_val = aa.getFloat(T); + const b_val = bb.getFloat(T); + return float(a_val + b_val); + } + + inline fn subInt(comptime T: type, out: *Value, a: Value, b: Value) bool { + const a_val = a.getInt(T); + const b_val = b.getInt(T); + const difference, const overflowed = @subWithOverflow(a_val, b_val); + out.* = int(difference); + return overflowed != 0; + } + inline fn subFloat(comptime T: type, aa: Value, bb: Value) Value { + const a_val = aa.getFloat(T); + const b_val = bb.getFloat(T); + return float(a_val - b_val); + } + + inline fn mulInt(comptime T: type, out: *Value, a: Value, b: Value) bool { + const a_val = a.getInt(T); + const b_val = b.getInt(T); + const product, const overflowed = @mulWithOverflow(a_val, b_val); + out.* = int(product); + return overflowed != 0; + } + inline fn mulFloat(comptime T: type, aa: Value, bb: Value) Value { + const a_val = aa.getFloat(T); + const b_val = bb.getFloat(T); + return float(a_val * b_val); + } + + const FT = fn (*Value, Value, Value, Type, *Compilation) bool; + fn getOp(comptime intFunc: anytype, comptime floatFunc: anytype) FT { + return struct { + fn op(res: *Value, a: Value, b: Value, ty: Type, comp: *Compilation) bool { + const size = ty.sizeof(comp).?; + if (@TypeOf(floatFunc) != @TypeOf(null) and ty.isFloat()) { + res.* = switch (size) { + 4 => floatFunc(f32, a, b), + 8 => floatFunc(f64, a, b), + else => unreachable, + }; + return false; + } + + if (ty.isUnsignedInt(comp)) switch (size) { + 1 => return intFunc(u8, res, a, b), + 2 => return intFunc(u16, res, a, b), + 4 => return intFunc(u32, res, a, b), + 8 => return intFunc(u64, res, a, b), + else => unreachable, + } else switch (size) { + 1 => return intFunc(u8, res, a, b), + 2 => return intFunc(u16, res, a, b), + 4 => return intFunc(i32, res, a, b), + 8 => return intFunc(i64, res, a, b), + else => unreachable, + } + } + }.op; + } +}; + +pub const add = bin_overflow.getOp(bin_overflow.addInt, bin_overflow.addFloat); +pub const sub = bin_overflow.getOp(bin_overflow.subInt, bin_overflow.subFloat); +pub const mul = bin_overflow.getOp(bin_overflow.mulInt, bin_overflow.mulFloat); + +const bin_ops = struct { + inline fn divInt(comptime T: type, aa: Value, bb: Value) Value { + const a_val = aa.getInt(T); + const b_val = bb.getInt(T); + return int(@divTrunc(a_val, b_val)); + } + inline fn divFloat(comptime T: type, aa: Value, bb: Value) Value { + const a_val = aa.getFloat(T); + const b_val = bb.getFloat(T); + return float(a_val / b_val); + } + + inline fn remInt(comptime T: type, a: Value, b: Value) Value { + const a_val = a.getInt(T); + const b_val = b.getInt(T); + + if (@typeInfo(T).Int.signedness == .signed) { + if (a_val == std.math.minInt(T) and b_val == -1) { + return Value{ .tag = .unavailable, .data = .{ .none = {} } }; + } else { + if (b_val > 0) return int(@rem(a_val, b_val)); + return int(a_val - @divTrunc(a_val, b_val) * b_val); + } + } else { + return int(a_val % b_val); + } + } + + inline fn orInt(comptime T: type, a: Value, b: Value) Value { + const a_val = a.getInt(T); + const b_val = b.getInt(T); + return int(a_val | b_val); + } + inline fn xorInt(comptime T: type, a: Value, b: Value) Value { + const a_val = a.getInt(T); + const b_val = b.getInt(T); + return int(a_val ^ b_val); + } + inline fn andInt(comptime T: type, a: Value, b: Value) Value { + const a_val = a.getInt(T); + const b_val = b.getInt(T); + return int(a_val & b_val); + } + + inline fn shl(comptime T: type, a: Value, b: Value) Value { + const ShiftT = std.math.Log2Int(T); + const info = @typeInfo(T).Int; + const UT = std.meta.Int(.unsigned, info.bits); + const b_val = b.getInt(T); + + if (b_val > std.math.maxInt(ShiftT)) { + return if (info.signedness == .unsigned) + int(@as(UT, std.math.maxInt(UT))) + else + int(@as(T, std.math.minInt(T))); + } + const amt: ShiftT = @truncate(@as(UT, @bitCast(b_val))); + const a_val = a.getInt(T); + return int(a_val << amt); + } + inline fn shr(comptime T: type, a: Value, b: Value) Value { + const ShiftT = std.math.Log2Int(T); + const UT = std.meta.Int(.unsigned, @typeInfo(T).Int.bits); + + const b_val = b.getInt(T); + if (b_val > std.math.maxInt(ShiftT)) return Value.int(0); + + const amt: ShiftT = @truncate(@as(UT, @intCast(b_val))); + const a_val = a.getInt(T); + return int(a_val >> amt); + } + + const FT = fn (Value, Value, Type, *Compilation) Value; + fn getOp(comptime intFunc: anytype, comptime floatFunc: anytype) FT { + return struct { + fn op(a: Value, b: Value, ty: Type, comp: *Compilation) Value { + const size = ty.sizeof(comp).?; + if (@TypeOf(floatFunc) != @TypeOf(null) and ty.isFloat()) { + switch (size) { + 4 => return floatFunc(f32, a, b), + 8 => return floatFunc(f64, a, b), + else => unreachable, + } + } + + if (ty.isUnsignedInt(comp)) switch (size) { + 1 => unreachable, // promoted to int + 2 => unreachable, // promoted to int + 4 => return intFunc(u32, a, b), + 8 => return intFunc(u64, a, b), + else => unreachable, + } else switch (size) { + 1 => unreachable, // promoted to int + 2 => unreachable, // promoted to int + 4 => return intFunc(i32, a, b), + 8 => return intFunc(i64, a, b), + else => unreachable, + } + } + }.op; + } +}; + +/// caller guarantees rhs != 0 +pub const div = bin_ops.getOp(bin_ops.divInt, bin_ops.divFloat); +/// caller guarantees rhs != 0 +/// caller guarantees lhs != std.math.minInt(T) OR rhs != -1 +pub const rem = bin_ops.getOp(bin_ops.remInt, null); + +pub const bitOr = bin_ops.getOp(bin_ops.orInt, null); +pub const bitXor = bin_ops.getOp(bin_ops.xorInt, null); +pub const bitAnd = bin_ops.getOp(bin_ops.andInt, null); + +pub const shl = bin_ops.getOp(bin_ops.shl, null); +pub const shr = bin_ops.getOp(bin_ops.shr, null); + +pub fn bitNot(v: Value, ty: Type, comp: *Compilation) Value { + const size = ty.sizeof(comp).?; + var out: Value = undefined; + if (ty.isUnsignedInt(comp)) switch (size) { + 1 => unreachable, // promoted to int + 2 => unreachable, // promoted to int + 4 => out = int(~v.getInt(u32)), + 8 => out = int(~v.getInt(u64)), + else => unreachable, + } else switch (size) { + 1 => unreachable, // promoted to int + 2 => unreachable, // promoted to int + 4 => out = int(~v.getInt(i32)), + 8 => out = int(~v.getInt(i64)), + else => unreachable, + } + return out; +} + +pub fn compare(a: Value, op: std.math.CompareOperator, b: Value, ty: Type, comp: *const Compilation) bool { + assert(a.tag == b.tag); + if (a.tag == .nullptr_t) { + return switch (op) { + .eq => true, + .neq => false, + else => unreachable, + }; + } + const S = struct { + inline fn doICompare(comptime T: type, aa: Value, opp: std.math.CompareOperator, bb: Value) bool { + const a_val = aa.getInt(T); + const b_val = bb.getInt(T); + return std.math.compare(a_val, opp, b_val); + } + inline fn doFCompare(comptime T: type, aa: Value, opp: std.math.CompareOperator, bb: Value) bool { + const a_val = aa.getFloat(T); + const b_val = bb.getFloat(T); + return std.math.compare(a_val, opp, b_val); + } + }; + const size = ty.sizeof(comp).?; + switch (a.tag) { + .unavailable => return true, + .int => if (ty.isUnsignedInt(comp)) switch (size) { + 1 => return S.doICompare(u8, a, op, b), + 2 => return S.doICompare(u16, a, op, b), + 4 => return S.doICompare(u32, a, op, b), + 8 => return S.doICompare(u64, a, op, b), + else => unreachable, + } else switch (size) { + 1 => return S.doICompare(i8, a, op, b), + 2 => return S.doICompare(i16, a, op, b), + 4 => return S.doICompare(i32, a, op, b), + 8 => return S.doICompare(i64, a, op, b), + else => unreachable, + }, + .float => switch (size) { + 4 => return S.doFCompare(f32, a, op, b), + 8 => return S.doFCompare(f64, a, op, b), + else => unreachable, + }, + else => @panic("TODO"), + } + return false; +} + +pub fn hash(v: Value) u64 { + switch (v.tag) { + .unavailable => unreachable, + .int => return std.hash.Wyhash.hash(0, std.mem.asBytes(&v.data.int)), + else => @panic("TODO"), + } +} + +pub fn dump(v: Value, ty: Type, comp: *Compilation, strings: []const u8, w: anytype) !void { + switch (v.tag) { + .unavailable => try w.writeAll("unavailable"), + .int => if (ty.is(.bool) and comp.langopts.standard.atLeast(.c2x)) { + try w.print("{s}", .{if (v.isZero()) "false" else "true"}); + } else if (ty.isUnsignedInt(comp)) { + try w.print("{d}", .{v.data.int}); + } else { + try w.print("{d}", .{v.signExtend(ty, comp)}); + }, + .bytes => try w.print("\"{s}\"", .{v.data.bytes.slice(strings)}), + // std.fmt does @as instead of @floatCast + .float => try w.print("{d}", .{@as(f64, @floatCast(v.data.float))}), + else => try w.print("({s})", .{@tagName(v.tag)}), + } +} diff --git a/deps/aro/builtins/BuiltinFunction.zig b/deps/aro/builtins/BuiltinFunction.zig new file mode 100644 index 000000000000..53d786c9d5d9 --- /dev/null +++ b/deps/aro/builtins/BuiltinFunction.zig @@ -0,0 +1,35783 @@ +//! Autogenerated by process_builtins.py, do not edit + +const std = @import("std"); +const Properties = @import("Properties.zig"); +const TypeDescription = @import("TypeDescription.zig"); +const Attributes = Properties.Attributes; +const TargetSet = Properties.TargetSet; + +pub const Tag = blk: { + @setEvalBranchQuota(10000); + break :blk std.meta.DeclEnum(functions); +}; + +tag: Tag, +param_str: []const u8, +properties: Properties, + +pub fn fromTag(builtin: Tag) @This() { + @setEvalBranchQuota(10000); + switch (builtin) { + inline else => |tag| { + const desc = @field(functions, @tagName(tag)); + return .{ + .tag = tag, + .param_str = desc.param_str, + .properties = .{ + .language = if (@hasDecl(desc, "language")) @field(desc, "language") else .all_languages, + .header = if (@hasDecl(desc, "header")) @field(desc, "header") else .none, + .attributes = if (@hasDecl(desc, "attributes")) @field(desc, "attributes") else Attributes{}, + .target_set = if (@hasDecl(desc, "target_set")) @field(desc, "target_set") else TargetSet.init(.{ .basic = true }), + }, + }; + }, + } +} + +pub fn isVarArgs(self: @This()) bool { + return self.param_str[self.param_str.len - 1] == '.'; +} + +const functions = struct { + pub const _Block_object_assign = struct { + const param_str = "vv*vC*iC"; + const header = .blocks; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const _Block_object_dispose = struct { + const param_str = "vvC*iC"; + const header = .blocks; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const _Exit = struct { + const param_str = "vi"; + const header = .stdlib; + const attributes = Attributes{ + .noreturn = true, + .lib_function_without_prefix = true, + }; + }; + + pub const _InterlockedAnd = struct { + const param_str = "NiNiD*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedAnd16 = struct { + const param_str = "ssD*s"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedAnd8 = struct { + const param_str = "ccD*c"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedCompareExchange = struct { + const param_str = "NiNiD*NiNi"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedCompareExchange16 = struct { + const param_str = "ssD*ss"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedCompareExchange64 = struct { + const param_str = "LLiLLiD*LLiLLi"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedCompareExchange8 = struct { + const param_str = "ccD*cc"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedCompareExchangePointer = struct { + const param_str = "v*v*D*v*v*"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedCompareExchangePointer_nf = struct { + const param_str = "v*v*D*v*v*"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedDecrement = struct { + const param_str = "NiNiD*"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedDecrement16 = struct { + const param_str = "ssD*"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedExchange = struct { + const param_str = "NiNiD*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedExchange16 = struct { + const param_str = "ssD*s"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedExchange8 = struct { + const param_str = "ccD*c"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedExchangeAdd = struct { + const param_str = "NiNiD*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedExchangeAdd16 = struct { + const param_str = "ssD*s"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedExchangeAdd8 = struct { + const param_str = "ccD*c"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedExchangePointer = struct { + const param_str = "v*v*D*v*"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedExchangeSub = struct { + const param_str = "NiNiD*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedExchangeSub16 = struct { + const param_str = "ssD*s"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedExchangeSub8 = struct { + const param_str = "ccD*c"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedIncrement = struct { + const param_str = "NiNiD*"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedIncrement16 = struct { + const param_str = "ssD*"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedOr = struct { + const param_str = "NiNiD*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedOr16 = struct { + const param_str = "ssD*s"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedOr8 = struct { + const param_str = "ccD*c"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedXor = struct { + const param_str = "NiNiD*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedXor16 = struct { + const param_str = "ssD*s"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _InterlockedXor8 = struct { + const param_str = "ccD*c"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _MoveFromCoprocessor = struct { + const param_str = "UiIUiIUiIUiIUiIUi"; + const language = .all_ms_languages; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const _MoveFromCoprocessor2 = struct { + const param_str = "UiIUiIUiIUiIUiIUi"; + const language = .all_ms_languages; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const _MoveToCoprocessor = struct { + const param_str = "vUiIUiIUiIUiIUiIUi"; + const language = .all_ms_languages; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const _MoveToCoprocessor2 = struct { + const param_str = "vUiIUiIUiIUiIUiIUi"; + const language = .all_ms_languages; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const _ReturnAddress = struct { + const param_str = "v*"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const __GetExceptionInfo = struct { + const param_str = "v*."; + const language = .all_ms_languages; + const attributes = Attributes{ + .custom_typecheck = true, + .eval_args = false, + }; + }; + + pub const __abnormal_termination = struct { + const param_str = "i"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const __annotation = struct { + const param_str = "wC*."; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const __arithmetic_fence = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + .const_evaluable = true, + }; + }; + + pub const __assume = struct { + const param_str = "vb"; + const language = .all_ms_languages; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __atomic_always_lock_free = struct { + const param_str = "bzvCD*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __atomic_clear = struct { + const param_str = "vvD*i"; + const attributes = Attributes{}; + }; + + pub const __atomic_is_lock_free = struct { + const param_str = "bzvCD*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __atomic_signal_fence = struct { + const param_str = "vi"; + const attributes = Attributes{}; + }; + + pub const __atomic_test_and_set = struct { + const param_str = "bvD*i"; + const attributes = Attributes{}; + }; + + pub const __atomic_thread_fence = struct { + const param_str = "vi"; + const attributes = Attributes{}; + }; + + pub const __builtin___CFStringMakeConstantString = struct { + const param_str = "FC*cC*"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin___NSStringMakeConstantString = struct { + const param_str = "FC*cC*"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin___clear_cache = struct { + const param_str = "vc*c*"; + const attributes = Attributes{}; + }; + + pub const __builtin___fprintf_chk = struct { + const param_str = "iP*icC*."; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .format_kind = .printf, + .format_string_position = 2, + }; + }; + + pub const __builtin___get_unsafe_stack_bottom = struct { + const param_str = "v*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___get_unsafe_stack_ptr = struct { + const param_str = "v*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___get_unsafe_stack_start = struct { + const param_str = "v*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___get_unsafe_stack_top = struct { + const param_str = "v*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___memccpy_chk = struct { + const param_str = "v*v*vC*izz"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___memcpy_chk = struct { + const param_str = "v*v*vC*zz"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___memmove_chk = struct { + const param_str = "v*v*vC*zz"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___mempcpy_chk = struct { + const param_str = "v*v*vC*zz"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___memset_chk = struct { + const param_str = "v*v*izz"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___printf_chk = struct { + const param_str = "iicC*."; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .format_kind = .printf, + .format_string_position = 1, + }; + }; + + pub const __builtin___snprintf_chk = struct { + const param_str = "ic*zizcC*."; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .format_kind = .printf, + .format_string_position = 4, + }; + }; + + pub const __builtin___sprintf_chk = struct { + const param_str = "ic*izcC*."; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .format_kind = .printf, + .format_string_position = 3, + }; + }; + + pub const __builtin___stpcpy_chk = struct { + const param_str = "c*c*cC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___stpncpy_chk = struct { + const param_str = "c*c*cC*zz"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___strcat_chk = struct { + const param_str = "c*c*cC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___strcpy_chk = struct { + const param_str = "c*c*cC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___strlcat_chk = struct { + const param_str = "zc*cC*zz"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___strlcpy_chk = struct { + const param_str = "zc*cC*zz"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___strncat_chk = struct { + const param_str = "c*c*cC*zz"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___strncpy_chk = struct { + const param_str = "c*c*cC*zz"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin___vfprintf_chk = struct { + const param_str = "iP*icC*a"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .format_kind = .vprintf, + .format_string_position = 2, + }; + }; + + pub const __builtin___vprintf_chk = struct { + const param_str = "iicC*a"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .format_kind = .vprintf, + .format_string_position = 1, + }; + }; + + pub const __builtin___vsnprintf_chk = struct { + const param_str = "ic*zizcC*a"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .format_kind = .vprintf, + .format_string_position = 4, + }; + }; + + pub const __builtin___vsprintf_chk = struct { + const param_str = "ic*izcC*a"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .format_kind = .vprintf, + .format_string_position = 3, + }; + }; + + pub const __builtin_abort = struct { + const param_str = "v"; + const attributes = Attributes{ + .noreturn = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_abs = struct { + const param_str = "ii"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_acos = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_acosf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_acosf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_acosh = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_acoshf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_acoshf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_acoshl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_acosl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_add_overflow = struct { + const param_str = "b."; + const attributes = Attributes{ + .custom_typecheck = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_addc = struct { + const param_str = "UiUiCUiCUiCUi*"; + const attributes = Attributes{}; + }; + + pub const __builtin_addcb = struct { + const param_str = "UcUcCUcCUcCUc*"; + const attributes = Attributes{}; + }; + + pub const __builtin_addcl = struct { + const param_str = "ULiULiCULiCULiCULi*"; + const attributes = Attributes{}; + }; + + pub const __builtin_addcll = struct { + const param_str = "ULLiULLiCULLiCULLiCULLi*"; + const attributes = Attributes{}; + }; + + pub const __builtin_addcs = struct { + const param_str = "UsUsCUsCUsCUs*"; + const attributes = Attributes{}; + }; + + pub const __builtin_addf128_round_to_odd = struct { + const param_str = "LLdLLdLLd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_align_down = struct { + const param_str = "v*vC*z"; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_align_up = struct { + const param_str = "v*vC*z"; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_alloca = struct { + const param_str = "v*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_alloca_uninitialized = struct { + const param_str = "v*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_alloca_with_align = struct { + const param_str = "v*zIz"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_alloca_with_align_uninitialized = struct { + const param_str = "v*zIz"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_altivec_crypto_vcipher = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_crypto_vcipherlast = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_crypto_vncipher = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_crypto_vncipherlast = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_crypto_vpermxor = struct { + const param_str = "V16UcV16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_crypto_vpermxor_be = struct { + const param_str = "V16UcV16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_crypto_vpmsumb = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_crypto_vpmsumd = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_crypto_vpmsumh = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_crypto_vpmsumw = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_crypto_vsbox = struct { + const param_str = "V16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_crypto_vshasigmad = struct { + const param_str = "V2ULLiV2ULLiIiIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_crypto_vshasigmaw = struct { + const param_str = "V4UiV4UiIiIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_dss = struct { + const param_str = "vUIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_dssall = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_dst = struct { + const param_str = "vvC*iUIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_dstst = struct { + const param_str = "vvC*iUIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_dststt = struct { + const param_str = "vvC*iUIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_dstt = struct { + const param_str = "vvC*iUIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_lvebx = struct { + const param_str = "V16cLivC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_lvehx = struct { + const param_str = "V8sLivC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_lvewx = struct { + const param_str = "V4iLivC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_lvsl = struct { + const param_str = "V16cUcvC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_lvsr = struct { + const param_str = "V16cUcvC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_lvx = struct { + const param_str = "V4iLivC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_lvxl = struct { + const param_str = "V4iLivC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_mfvscr = struct { + const param_str = "V8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_mtvscr = struct { + const param_str = "vV4i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_mtvsrbm = struct { + const param_str = "V16UcULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_mtvsrdm = struct { + const param_str = "V2ULLiULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_mtvsrhm = struct { + const param_str = "V8UsULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_mtvsrqm = struct { + const param_str = "V1ULLLiULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_mtvsrwm = struct { + const param_str = "V4UiULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_stvebx = struct { + const param_str = "vV16cLiv*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_stvehx = struct { + const param_str = "vV8sLiv*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_stvewx = struct { + const param_str = "vV4iLiv*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_stvx = struct { + const param_str = "vV4iLiv*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_stvxl = struct { + const param_str = "vV4iLiv*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vabsdub = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vabsduh = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vabsduw = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vaddcuq = struct { + const param_str = "V1ULLLiV1ULLLiV1ULLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vaddcuq_c = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vaddcuw = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vaddecuq = struct { + const param_str = "V1ULLLiV1ULLLiV1ULLLiV1ULLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vaddecuq_c = struct { + const param_str = "V16UcV16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vaddeuqm = struct { + const param_str = "V1ULLLiV1ULLLiV1ULLLiV1ULLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vaddeuqm_c = struct { + const param_str = "V16UcV16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vaddsbs = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vaddshs = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vaddsws = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vaddubs = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vadduhs = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vadduqm = struct { + const param_str = "V1ULLLiV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vadduws = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vavgsb = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vavgsh = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vavgsw = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vavgub = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vavguh = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vavguw = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vbpermd = struct { + const param_str = "V2ULLiV2ULLiV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vbpermq = struct { + const param_str = "V2ULLiV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcfsx = struct { + const param_str = "V4fV4SiIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcfuged = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcfux = struct { + const param_str = "V4fV4UiIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vclrlb = struct { + const param_str = "V16UcV16UcUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vclrrb = struct { + const param_str = "V16UcV16UcUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vclzb = struct { + const param_str = "V16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vclzd = struct { + const param_str = "V2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vclzdm = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vclzh = struct { + const param_str = "V8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vclzlsbb = struct { + const param_str = "SiV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vclzw = struct { + const param_str = "V4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpbfp = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpbfp_p = struct { + const param_str = "iiV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpeqfp = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpeqfp_p = struct { + const param_str = "iiV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpequb = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpequb_p = struct { + const param_str = "iiV16cV16c"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpequd = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpequd_p = struct { + const param_str = "iiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpequh = struct { + const param_str = "V8sV8sV8s"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpequh_p = struct { + const param_str = "iiV8sV8s"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpequq = struct { + const param_str = "V1LLLiV1ULLLiV1ULLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpequq_p = struct { + const param_str = "iiV1ULLLiV1LLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpequw = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpequw_p = struct { + const param_str = "iiV4iV4i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgefp = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgefp_p = struct { + const param_str = "iiV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtfp = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtfp_p = struct { + const param_str = "iiV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtsb = struct { + const param_str = "V16cV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtsb_p = struct { + const param_str = "iiV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtsd = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtsd_p = struct { + const param_str = "iiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtsh = struct { + const param_str = "V8sV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtsh_p = struct { + const param_str = "iiV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtsq = struct { + const param_str = "V1LLLiV1SLLLiV1SLLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtsq_p = struct { + const param_str = "iiV1SLLLiV1SLLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtsw = struct { + const param_str = "V4iV4SiV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtsw_p = struct { + const param_str = "iiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtub = struct { + const param_str = "V16cV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtub_p = struct { + const param_str = "iiV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtud = struct { + const param_str = "V2LLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtud_p = struct { + const param_str = "iiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtuh = struct { + const param_str = "V8sV8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtuh_p = struct { + const param_str = "iiV8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtuq = struct { + const param_str = "V1LLLiV1ULLLiV1ULLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtuq_p = struct { + const param_str = "iiV1ULLLiV1ULLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtuw = struct { + const param_str = "V4iV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpgtuw_p = struct { + const param_str = "iiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpneb = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpneb_p = struct { + const param_str = "iiV16cV16c"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpned_p = struct { + const param_str = "iiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpneh = struct { + const param_str = "V8sV8sV8s"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpneh_p = struct { + const param_str = "iiV8sV8s"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpnew = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpnew_p = struct { + const param_str = "iiV4iV4i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpnezb = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpnezh = struct { + const param_str = "V8sV8sV8s"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcmpnezw = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcntmbb = struct { + const param_str = "ULLiV16UcUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcntmbd = struct { + const param_str = "ULLiV2ULLiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcntmbh = struct { + const param_str = "ULLiV8UsUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vcntmbw = struct { + const param_str = "ULLiV4UiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vctsxs = struct { + const param_str = "V4SiV4fIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vctuxs = struct { + const param_str = "V4UiV4fIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vctzb = struct { + const param_str = "V16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vctzd = struct { + const param_str = "V2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vctzdm = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vctzh = struct { + const param_str = "V8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vctzlsbb = struct { + const param_str = "SiV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vctzw = struct { + const param_str = "V4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vdivesd = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vdivesq = struct { + const param_str = "V1SLLLiV1SLLLiV1SLLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vdivesw = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vdiveud = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vdiveuq = struct { + const param_str = "V1ULLLiV1ULLLiV1ULLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vdiveuw = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vexpandbm = struct { + const param_str = "V16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vexpanddm = struct { + const param_str = "V2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vexpandhm = struct { + const param_str = "V8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vexpandqm = struct { + const param_str = "V1ULLLiV1ULLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vexpandwm = struct { + const param_str = "V4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vexptefp = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextddvlx = struct { + const param_str = "V2ULLiV2ULLiV2ULLiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextddvrx = struct { + const param_str = "V2ULLiV2ULLiV2ULLiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextdubvlx = struct { + const param_str = "V2ULLiV16UcV16UcUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextdubvrx = struct { + const param_str = "V2ULLiV16UcV16UcUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextduhvlx = struct { + const param_str = "V2ULLiV8UsV8UsUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextduhvrx = struct { + const param_str = "V2ULLiV8UsV8UsUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextduwvlx = struct { + const param_str = "V2ULLiV4UiV4UiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextduwvrx = struct { + const param_str = "V2ULLiV4UiV4UiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextractbm = struct { + const param_str = "UiV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextractdm = struct { + const param_str = "UiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextracthm = struct { + const param_str = "UiV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextractqm = struct { + const param_str = "UiV1ULLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextractwm = struct { + const param_str = "UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextsb2d = struct { + const param_str = "V2SLLiV16Sc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextsb2w = struct { + const param_str = "V4SiV16Sc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextsd2q = struct { + const param_str = "V1SLLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextsh2d = struct { + const param_str = "V2SLLiV8Ss"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextsh2w = struct { + const param_str = "V4SiV8Ss"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vextsw2d = struct { + const param_str = "V2SLLiV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vgbbd = struct { + const param_str = "V16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vgnb = struct { + const param_str = "ULLiV1ULLLiIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinsblx = struct { + const param_str = "V16UcV16UcUiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinsbrx = struct { + const param_str = "V16UcV16UcUiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinsbvlx = struct { + const param_str = "V16UcV16UcUiV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinsbvrx = struct { + const param_str = "V16UcV16UcUiV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinsd = struct { + const param_str = "V16UcV16UcULLiIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinsd_elt = struct { + const param_str = "V16UcV16UcULLiiC"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinsdlx = struct { + const param_str = "V2ULLiV2ULLiULLiULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinsdrx = struct { + const param_str = "V2ULLiV2ULLiULLiULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinshlx = struct { + const param_str = "V8UsV8UsUiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinshrx = struct { + const param_str = "V8UsV8UsUiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinshvlx = struct { + const param_str = "V8UsV8UsUiV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinshvrx = struct { + const param_str = "V8UsV8UsUiV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinsw = struct { + const param_str = "V16UcV16UcUiIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinsw_elt = struct { + const param_str = "V16UcV16UcUiiC"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinswlx = struct { + const param_str = "V4UiV4UiUiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinswrx = struct { + const param_str = "V4UiV4UiUiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinswvlx = struct { + const param_str = "V4UiV4UiUiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vinswvrx = struct { + const param_str = "V4UiV4UiUiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vlogefp = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmaddfp = struct { + const param_str = "V4fV4fV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmaxfp = struct { + const param_str = "V4fV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmaxsb = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmaxsd = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmaxsh = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmaxsw = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmaxub = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmaxud = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmaxuh = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmaxuw = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmhaddshs = struct { + const param_str = "V8sV8sV8sV8s"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmhraddshs = struct { + const param_str = "V8sV8sV8sV8s"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vminfp = struct { + const param_str = "V4fV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vminsb = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vminsd = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vminsh = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vminsw = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vminub = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vminud = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vminuh = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vminuw = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmsumcud = struct { + const param_str = "V1ULLLiV2ULLiV2ULLiV1ULLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmsummbm = struct { + const param_str = "V4SiV16ScV16UcV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmsumshm = struct { + const param_str = "V4SiV8SsV8SsV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmsumshs = struct { + const param_str = "V4SiV8SsV8SsV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmsumubm = struct { + const param_str = "V4UiV16UcV16UcV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmsumuhm = struct { + const param_str = "V4UiV8UsV8UsV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmsumuhs = struct { + const param_str = "V4UiV8UsV8UsV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmulesb = struct { + const param_str = "V8SsV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmulesd = struct { + const param_str = "V1SLLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmulesh = struct { + const param_str = "V4SiV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmulesw = struct { + const param_str = "V2SLLiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmuleub = struct { + const param_str = "V8UsV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmuleud = struct { + const param_str = "V1ULLLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmuleuh = struct { + const param_str = "V4UiV8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmuleuw = struct { + const param_str = "V2ULLiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmulhsd = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmulhsw = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmulhud = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmulhuw = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmulosb = struct { + const param_str = "V8SsV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmulosd = struct { + const param_str = "V1SLLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmulosh = struct { + const param_str = "V4SiV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmulosw = struct { + const param_str = "V2SLLiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmuloub = struct { + const param_str = "V8UsV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmuloud = struct { + const param_str = "V1ULLLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmulouh = struct { + const param_str = "V4UiV8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vmulouw = struct { + const param_str = "V2ULLiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vnmsubfp = struct { + const param_str = "V4fV4fV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpdepd = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vperm_4si = struct { + const param_str = "V4iV4iV4iV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpextd = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpkpx = struct { + const param_str = "V8sV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpksdss = struct { + const param_str = "V4SiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpksdus = struct { + const param_str = "V4UiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpkshss = struct { + const param_str = "V16ScV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpkshus = struct { + const param_str = "V16UcV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpkswss = struct { + const param_str = "V8SsV4SiV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpkswus = struct { + const param_str = "V8UsV4SiV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpkudum = struct { + const param_str = "V4UiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpkudus = struct { + const param_str = "V4UiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpkuhus = struct { + const param_str = "V16UcV8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpkuwus = struct { + const param_str = "V8UsV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpopcntb = struct { + const param_str = "V16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpopcntd = struct { + const param_str = "V2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpopcnth = struct { + const param_str = "V8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vpopcntw = struct { + const param_str = "V4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vprtybd = struct { + const param_str = "V2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vprtybq = struct { + const param_str = "V1ULLLiV1ULLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vprtybw = struct { + const param_str = "V4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vrefp = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vrfim = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vrfin = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vrfip = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vrfiz = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vrlb = struct { + const param_str = "V16cV16cV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vrld = struct { + const param_str = "V2LLiV2LLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vrldmi = struct { + const param_str = "V2ULLiV2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vrldnm = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vrlh = struct { + const param_str = "V8sV8sV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vrlqmi = struct { + const param_str = "V1ULLLiV1ULLLiV1ULLLiV1ULLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vrlqnm = struct { + const param_str = "V1ULLLiV1ULLLiV1ULLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vrlw = struct { + const param_str = "V4iV4iV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vrlwmi = struct { + const param_str = "V4UiV4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vrlwnm = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vrsqrtefp = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsel_4si = struct { + const param_str = "V4iV4iV4iV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsl = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsldbi = struct { + const param_str = "V16UcV16UcV16UcIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vslo = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vslv = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsr = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsrab = struct { + const param_str = "V16cV16cV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsrah = struct { + const param_str = "V8sV8sV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsraw = struct { + const param_str = "V4iV4iV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsrdbi = struct { + const param_str = "V16UcV16UcV16UcIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsro = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsrv = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vstribl = struct { + const param_str = "V16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vstribl_p = struct { + const param_str = "iiV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vstribr = struct { + const param_str = "V16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vstribr_p = struct { + const param_str = "iiV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vstrihl = struct { + const param_str = "V8sV8s"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vstrihl_p = struct { + const param_str = "iiV8s"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vstrihr = struct { + const param_str = "V8sV8s"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vstrihr_p = struct { + const param_str = "iiV8s"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsubcuq = struct { + const param_str = "V1ULLLiV1ULLLiV1ULLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsubcuq_c = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsubcuw = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsubecuq = struct { + const param_str = "V1ULLLiV1ULLLiV1ULLLiV1ULLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsubecuq_c = struct { + const param_str = "V16UcV16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsubeuqm = struct { + const param_str = "V1ULLLiV1ULLLiV1ULLLiV1ULLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsubeuqm_c = struct { + const param_str = "V16UcV16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsubsbs = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsubshs = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsubsws = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsububs = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsubuhs = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsubuqm = struct { + const param_str = "V1ULLLiV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsubuws = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsum2sws = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsum4sbs = struct { + const param_str = "V4SiV16ScV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsum4shs = struct { + const param_str = "V4SiV8SsV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsum4ubs = struct { + const param_str = "V4UiV16UcV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vsumsws = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vupkhpx = struct { + const param_str = "V4UiV8s"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vupkhsb = struct { + const param_str = "V8sV16c"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vupkhsh = struct { + const param_str = "V4iV8s"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vupkhsw = struct { + const param_str = "V2LLiV4i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vupklpx = struct { + const param_str = "V4UiV8s"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vupklsb = struct { + const param_str = "V8sV16c"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vupklsh = struct { + const param_str = "V4iV8s"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_altivec_vupklsw = struct { + const param_str = "V2LLiV4i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_amdgcn_alignbit = struct { + const param_str = "UiUiUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_alignbyte = struct { + const param_str = "UiUiUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_atomic_dec32 = struct { + const param_str = "UZiUZiD*UZiUicC*"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_atomic_dec64 = struct { + const param_str = "UWiUWiD*UWiUicC*"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_atomic_inc32 = struct { + const param_str = "UZiUZiD*UZiUicC*"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_atomic_inc64 = struct { + const param_str = "UWiUWiD*UWiUicC*"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_buffer_wbinvl1 = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_class = struct { + const param_str = "bdi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_classf = struct { + const param_str = "bfi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_cosf = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_cubeid = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_cubema = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_cubesc = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_cubetc = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_cvt_pk_i16 = struct { + const param_str = "E2sii"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_cvt_pk_u16 = struct { + const param_str = "E2UsUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_cvt_pk_u8_f32 = struct { + const param_str = "UifUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_cvt_pknorm_i16 = struct { + const param_str = "E2sff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_cvt_pknorm_u16 = struct { + const param_str = "E2Usff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_cvt_pkrtz = struct { + const param_str = "E2hff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_dispatch_ptr = struct { + const param_str = "v*4"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_div_fixup = struct { + const param_str = "dddd"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_div_fixupf = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_div_fmas = struct { + const param_str = "ddddb"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_div_fmasf = struct { + const param_str = "ffffb"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_div_scale = struct { + const param_str = "dddbb*"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_div_scalef = struct { + const param_str = "fffbb*"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_ds_append = struct { + const param_str = "ii*3"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_ds_bpermute = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_ds_consume = struct { + const param_str = "ii*3"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_ds_faddf = struct { + const param_str = "ff*3fIiIiIb"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_ds_fmaxf = struct { + const param_str = "ff*3fIiIiIb"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_ds_fminf = struct { + const param_str = "ff*3fIiIiIb"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_ds_gws_barrier = struct { + const param_str = "vUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_ds_gws_init = struct { + const param_str = "vUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_ds_gws_sema_br = struct { + const param_str = "vUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_ds_gws_sema_p = struct { + const param_str = "vUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_ds_gws_sema_v = struct { + const param_str = "vUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_ds_permute = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_ds_swizzle = struct { + const param_str = "iiIi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_endpgm = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .noreturn = true, + }; + }; + + pub const __builtin_amdgcn_fcmp = struct { + const param_str = "WUiddIi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_fcmpf = struct { + const param_str = "WUiffIi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_fence = struct { + const param_str = "vUicC*"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_fmed3f = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_fract = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_fractf = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_frexp_exp = struct { + const param_str = "id"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_frexp_expf = struct { + const param_str = "if"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_frexp_mant = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_frexp_mantf = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_grid_size_x = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_grid_size_y = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_grid_size_z = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_groupstaticsize = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_iglp_opt = struct { + const param_str = "vIi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_implicitarg_ptr = struct { + const param_str = "v*4"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_interp_mov = struct { + const param_str = "fUiUiUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_interp_p1 = struct { + const param_str = "ffUiUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_interp_p1_f16 = struct { + const param_str = "ffUiUibUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_interp_p2 = struct { + const param_str = "fffUiUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_interp_p2_f16 = struct { + const param_str = "hffUiUibUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_is_private = struct { + const param_str = "bvC*0"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_is_shared = struct { + const param_str = "bvC*0"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_kernarg_segment_ptr = struct { + const param_str = "v*4"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_ldexp = struct { + const param_str = "ddi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_ldexpf = struct { + const param_str = "ffi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_lerp = struct { + const param_str = "UiUiUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_log_clampf = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_mbcnt_hi = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_mbcnt_lo = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_mqsad_pk_u16_u8 = struct { + const param_str = "WUiWUiUiWUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_mqsad_u32_u8 = struct { + const param_str = "V4UiWUiUiV4Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_msad_u8 = struct { + const param_str = "UiUiUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_qsad_pk_u16_u8 = struct { + const param_str = "WUiWUiUiWUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_queue_ptr = struct { + const param_str = "v*4"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_rcp = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_rcpf = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_read_exec = struct { + const param_str = "WUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_read_exec_hi = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_read_exec_lo = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_readfirstlane = struct { + const param_str = "ii"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_readlane = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_rsq = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_rsq_clamp = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_rsq_clampf = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_rsqf = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_s_barrier = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_s_dcache_inv = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_s_decperflevel = struct { + const param_str = "vIi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_s_getpc = struct { + const param_str = "WUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_s_getreg = struct { + const param_str = "UiIi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_s_incperflevel = struct { + const param_str = "vIi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_s_sendmsg = struct { + const param_str = "vIiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_s_sendmsghalt = struct { + const param_str = "vIiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_s_setprio = struct { + const param_str = "vIs"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_s_setreg = struct { + const param_str = "vIiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_s_sleep = struct { + const param_str = "vIi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_s_waitcnt = struct { + const param_str = "vIi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_sad_hi_u8 = struct { + const param_str = "UiUiUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_sad_u16 = struct { + const param_str = "UiUiUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_sad_u8 = struct { + const param_str = "UiUiUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_sbfe = struct { + const param_str = "UiUiUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_sched_barrier = struct { + const param_str = "vIi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_sched_group_barrier = struct { + const param_str = "vIiIiIi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_sicmp = struct { + const param_str = "WUiiiIi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_sicmpl = struct { + const param_str = "WUiWiWiIi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_sinf = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_sqrt = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_sqrtf = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_trig_preop = struct { + const param_str = "ddi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_trig_preopf = struct { + const param_str = "ffi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_ubfe = struct { + const param_str = "UiUiUiUi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_uicmp = struct { + const param_str = "WUiUiUiIi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_uicmpl = struct { + const param_str = "WUiWUiWUiIi"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_wave_barrier = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_amdgcn_workgroup_id_x = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_workgroup_id_y = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_workgroup_id_z = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_workgroup_size_x = struct { + const param_str = "Us"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_workgroup_size_y = struct { + const param_str = "Us"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_workgroup_size_z = struct { + const param_str = "Us"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_workitem_id_x = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_workitem_id_y = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_amdgcn_workitem_id_z = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_annotation = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_arm_cdp = struct { + const param_str = "vUIiUIiUIiUIiUIiUIi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_cdp2 = struct { + const param_str = "vUIiUIiUIiUIiUIiUIi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_clrex = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + }; + + pub const __builtin_arm_cls = struct { + const param_str = "UiZUi"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_cls64 = struct { + const param_str = "UiWUi"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_cmse_TT = struct { + const param_str = "Uiv*"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_arm_cmse_TTA = struct { + const param_str = "Uiv*"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_arm_cmse_TTAT = struct { + const param_str = "Uiv*"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_arm_cmse_TTT = struct { + const param_str = "Uiv*"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_arm_dbg = struct { + const param_str = "vUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_dmb = struct { + const param_str = "vUi"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_dsb = struct { + const param_str = "vUi"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_get_fpscr = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_isb = struct { + const param_str = "vUi"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_ldaex = struct { + const param_str = "v."; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_arm_ldc = struct { + const param_str = "vUIiUIivC*"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_ldc2 = struct { + const param_str = "vUIiUIivC*"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_ldc2l = struct { + const param_str = "vUIiUIivC*"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_ldcl = struct { + const param_str = "vUIiUIivC*"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_ldrex = struct { + const param_str = "v."; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_arm_ldrexd = struct { + const param_str = "LLUiv*"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_mcr = struct { + const param_str = "vUIiUIiUiUIiUIiUIi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_mcr2 = struct { + const param_str = "vUIiUIiUiUIiUIiUIi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_mcrr = struct { + const param_str = "vUIiUIiLLUiUIi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_mcrr2 = struct { + const param_str = "vUIiUIiLLUiUIi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_mrc = struct { + const param_str = "UiUIiUIiUIiUIiUIi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_mrc2 = struct { + const param_str = "UiUIiUIiUIiUIiUIi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_mrrc = struct { + const param_str = "LLUiUIiUIiUIi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_mrrc2 = struct { + const param_str = "LLUiUIiUIiUIi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_nop = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + }; + + pub const __builtin_arm_prefetch = struct { + const param_str = "!"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_qadd = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_qadd16 = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_qadd8 = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_qasx = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_qdbl = struct { + const param_str = "ii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_qsax = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_qsub = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_qsub16 = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_qsub8 = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_rbit = struct { + const param_str = "UiUi"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_rbit64 = struct { + const param_str = "WUiWUi"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_rsr = struct { + const param_str = "UicC*"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_rsr128 = struct { + const param_str = "LLLUicC*"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_rsr64 = struct { + const param_str = "!"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_rsrp = struct { + const param_str = "v*cC*"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_sadd16 = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_sadd8 = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_sasx = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_sel = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_set_fpscr = struct { + const param_str = "vUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_sev = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + }; + + pub const __builtin_arm_sevl = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + }; + + pub const __builtin_arm_shadd16 = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_shadd8 = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_shasx = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_shsax = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_shsub16 = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_shsub8 = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smlabb = struct { + const param_str = "iiii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smlabt = struct { + const param_str = "iiii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smlad = struct { + const param_str = "iiii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smladx = struct { + const param_str = "iiii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smlald = struct { + const param_str = "LLiiiLLi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smlaldx = struct { + const param_str = "LLiiiLLi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smlatb = struct { + const param_str = "iiii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smlatt = struct { + const param_str = "iiii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smlawb = struct { + const param_str = "iiii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smlawt = struct { + const param_str = "iiii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smlsd = struct { + const param_str = "iiii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smlsdx = struct { + const param_str = "iiii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smlsld = struct { + const param_str = "LLiiiLLi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smlsldx = struct { + const param_str = "LLiiiLLi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smuad = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smuadx = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smulbb = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smulbt = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smultb = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smultt = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smulwb = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smulwt = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smusd = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_smusdx = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_ssat = struct { + const param_str = "iiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_ssat16 = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_ssax = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_ssub16 = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_ssub8 = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_stc = struct { + const param_str = "vUIiUIiv*"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_stc2 = struct { + const param_str = "vUIiUIiv*"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_stc2l = struct { + const param_str = "vUIiUIiv*"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_stcl = struct { + const param_str = "vUIiUIiv*"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_stlex = struct { + const param_str = "i."; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_arm_strex = struct { + const param_str = "i."; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_arm_strexd = struct { + const param_str = "iLLUiv*"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __builtin_arm_sxtab16 = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_sxtb16 = struct { + const param_str = "ii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_tcancel = struct { + const param_str = "vWUIi"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_arm_tcommit = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_arm_tstart = struct { + const param_str = "WUi"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + }); + const attributes = Attributes{ + .returns_twice = true, + }; + }; + + pub const __builtin_arm_ttest = struct { + const param_str = "WUi"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uadd16 = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uadd8 = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uasx = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uhadd16 = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uhadd8 = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uhasx = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uhsax = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uhsub16 = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uhsub8 = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uqadd16 = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uqadd8 = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uqasx = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uqsax = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uqsub16 = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uqsub8 = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_usad8 = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_usada8 = struct { + const param_str = "UiUiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_usat = struct { + const param_str = "UiiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_usat16 = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_usax = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_usub16 = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_usub8 = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uxtab16 = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_uxtb16 = struct { + const param_str = "ii"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_vcvtr_d = struct { + const param_str = "fdi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_vcvtr_f = struct { + const param_str = "ffi"; + const target_set = TargetSet.init(.{ + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_wfe = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + }; + + pub const __builtin_arm_wfi = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + }; + + pub const __builtin_arm_wsr = struct { + const param_str = "vcC*Ui"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_wsr128 = struct { + const param_str = "vcC*LLLUi"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_wsr64 = struct { + const param_str = "!"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_wsrp = struct { + const param_str = "vcC*vC*"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_arm_yield = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + }; + + pub const __builtin_asin = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_asinf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_asinf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_asinh = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_asinhf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_asinhf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_asinhl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_asinl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_assume = struct { + const param_str = "vb"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_assume_aligned = struct { + const param_str = "v*vC*z."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_atan = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_atan2 = struct { + const param_str = "ddd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_atan2f = struct { + const param_str = "fff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_atan2f128 = struct { + const param_str = "LLdLLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_atan2l = struct { + const param_str = "LdLdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_atanf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_atanf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_atanh = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_atanhf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_atanhf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_atanhl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_atanl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_bcmp = struct { + const param_str = "ivC*vC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_bcopy = struct { + const param_str = "vv*v*z"; + const attributes = Attributes{}; + }; + + pub const __builtin_bitrev = struct { + const param_str = "UiUi"; + const target_set = TargetSet.init(.{ + .xcore = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_bitreverse16 = struct { + const param_str = "UsUs"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_bitreverse32 = struct { + const param_str = "UZiUZi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_bitreverse64 = struct { + const param_str = "UWiUWi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_bitreverse8 = struct { + const param_str = "UcUc"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_bpermd = struct { + const param_str = "SLLiSLLiSLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_bswap16 = struct { + const param_str = "UsUs"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_bswap32 = struct { + const param_str = "UZiUZi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_bswap64 = struct { + const param_str = "UWiUWi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_bzero = struct { + const param_str = "vv*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_cabs = struct { + const param_str = "dXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cabsf = struct { + const param_str = "fXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cabsl = struct { + const param_str = "LdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cacos = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cacosf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cacosh = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cacoshf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cacoshl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cacosl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_call_with_static_chain = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_calloc = struct { + const param_str = "v*zz"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_canonicalize = struct { + const param_str = "dd"; + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_canonicalizef = struct { + const param_str = "ff"; + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_canonicalizef16 = struct { + const param_str = "hh"; + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_canonicalizel = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_carg = struct { + const param_str = "dXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cargf = struct { + const param_str = "fXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cargl = struct { + const param_str = "LdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_casin = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_casinf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_casinh = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_casinhf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_casinhl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_casinl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_catan = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_catanf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_catanh = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_catanhf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_catanhl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_catanl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cbrt = struct { + const param_str = "dd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_cbrtf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_cbrtf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_cbrtl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_ccos = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ccosf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ccosh = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ccoshf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ccoshl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ccosl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ceil = struct { + const param_str = "dd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_ceilf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_ceilf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_ceilf16 = struct { + const param_str = "hh"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_ceill = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_cexp = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cexpf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cexpl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cfuged = struct { + const param_str = "ULLiULLiULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_char_memchr = struct { + const param_str = "c*cC*iz"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_cimag = struct { + const param_str = "dXd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_cimagf = struct { + const param_str = "fXf"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_cimagl = struct { + const param_str = "LdXLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_classify_type = struct { + const param_str = "i."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .eval_args = false, + .const_evaluable = true, + }; + }; + + pub const __builtin_clog = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_clogf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_clogl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_clrsb = struct { + const param_str = "ii"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_clrsbl = struct { + const param_str = "iLi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_clrsbll = struct { + const param_str = "iLLi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_clz = struct { + const param_str = "iUi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_clzl = struct { + const param_str = "iULi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_clzll = struct { + const param_str = "iULLi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_clzs = struct { + const param_str = "iUs"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_cntlzdm = struct { + const param_str = "ULLiULLiULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_cnttzdm = struct { + const param_str = "ULLiULLiULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_complex = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_conj = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_conjf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_conjl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_constant_p = struct { + const param_str = "i."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .eval_args = false, + .const_evaluable = true, + }; + }; + + pub const __builtin_convertvector = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_copysign = struct { + const param_str = "ddd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_copysignf = struct { + const param_str = "fff"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_copysignf128 = struct { + const param_str = "LLdLLdLLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_copysignf16 = struct { + const param_str = "hhh"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_copysignl = struct { + const param_str = "LdLdLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_cos = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cosf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cosf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cosf16 = struct { + const param_str = "hh"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cosh = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_coshf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_coshf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_coshl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cosl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cpow = struct { + const param_str = "XdXdXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cpowf = struct { + const param_str = "XfXfXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cpowl = struct { + const param_str = "XLdXLdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_cproj = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_cprojf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_cprojl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_cpu_init = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .x86 = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_cpu_is = struct { + const param_str = "bcC*"; + const target_set = TargetSet.init(.{ + .x86 = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_cpu_supports = struct { + const param_str = "bcC*"; + const target_set = TargetSet.init(.{ + .x86 = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_creal = struct { + const param_str = "dXd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_crealf = struct { + const param_str = "fXf"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_creall = struct { + const param_str = "LdXLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_csin = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_csinf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_csinh = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_csinhf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_csinhl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_csinl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_csqrt = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_csqrtf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_csqrtl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ctan = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ctanf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ctanh = struct { + const param_str = "XdXd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ctanhf = struct { + const param_str = "XfXf"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ctanhl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ctanl = struct { + const param_str = "XLdXLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ctz = struct { + const param_str = "iUi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_ctzl = struct { + const param_str = "iULi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_ctzll = struct { + const param_str = "iULLi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_ctzs = struct { + const param_str = "iUs"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_darn = struct { + const param_str = "LLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_darn_32 = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_darn_raw = struct { + const param_str = "LLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_dcbf = struct { + const param_str = "vvC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_debugtrap = struct { + const param_str = "v"; + const attributes = Attributes{}; + }; + + pub const __builtin_divde = struct { + const param_str = "SLLiSLLiSLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_divdeu = struct { + const param_str = "ULLiULLiULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_divf128_round_to_odd = struct { + const param_str = "LLdLLdLLd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_divwe = struct { + const param_str = "SiSiSi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_divweu = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_dump_struct = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_dwarf_cfa = struct { + const param_str = "v*"; + const attributes = Attributes{}; + }; + + pub const __builtin_dwarf_sp_column = struct { + const param_str = "Ui"; + const attributes = Attributes{}; + }; + + pub const __builtin_dynamic_object_size = struct { + const param_str = "zvC*i"; + const attributes = Attributes{ + .eval_args = false, + .const_evaluable = true, + }; + }; + + pub const __builtin_eh_return = struct { + const param_str = "vzv*"; + const attributes = Attributes{ + .noreturn = true, + }; + }; + + pub const __builtin_eh_return_data_regno = struct { + const param_str = "iIi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_elementwise_abs = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_elementwise_add_sat = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_elementwise_canonicalize = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_elementwise_ceil = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_elementwise_copysign = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_elementwise_cos = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_elementwise_floor = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_elementwise_max = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_elementwise_min = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_elementwise_roundeven = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_elementwise_sin = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_elementwise_sub_sat = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_elementwise_trunc = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_erf = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_erfc = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_erfcf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_erfcf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_erfcl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_erff = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_erff128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_erfl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_exp = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_exp2 = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_exp2f = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_exp2f128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_exp2f16 = struct { + const param_str = "hh"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_exp2l = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_expect = struct { + const param_str = "LiLiLi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_expect_with_probability = struct { + const param_str = "LiLiLid"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_expf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_expf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_expf16 = struct { + const param_str = "hh"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_expl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_expm1 = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_expm1f = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_expm1f128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_expm1l = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_extend_pointer = struct { + const param_str = "ULLiv*"; + const attributes = Attributes{}; + }; + + pub const __builtin_extract_return_addr = struct { + const param_str = "v*v*"; + const attributes = Attributes{}; + }; + + pub const __builtin_fabs = struct { + const param_str = "dd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_fabsf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_fabsf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_fabsf16 = struct { + const param_str = "hh"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_fabsl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_fdim = struct { + const param_str = "ddd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_fdimf = struct { + const param_str = "fff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_fdimf128 = struct { + const param_str = "LLdLLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_fdiml = struct { + const param_str = "LdLdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ffs = struct { + const param_str = "ii"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_ffsl = struct { + const param_str = "iLi"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_ffsll = struct { + const param_str = "iLLi"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_floor = struct { + const param_str = "dd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_floorf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_floorf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_floorf16 = struct { + const param_str = "hh"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_floorl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_flt_rounds = struct { + const param_str = "i"; + const attributes = Attributes{}; + }; + + pub const __builtin_fma = struct { + const param_str = "dddd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_fmaf = struct { + const param_str = "ffff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_fmaf128 = struct { + const param_str = "LLdLLdLLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_fmaf128_round_to_odd = struct { + const param_str = "LLdLLdLLdLLd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_fmaf16 = struct { + const param_str = "hhhh"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_fmal = struct { + const param_str = "LdLdLdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_fmax = struct { + const param_str = "ddd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_fmaxf = struct { + const param_str = "fff"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_fmaxf128 = struct { + const param_str = "LLdLLdLLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_fmaxf16 = struct { + const param_str = "hhh"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_fmaxl = struct { + const param_str = "LdLdLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_fmin = struct { + const param_str = "ddd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_fminf = struct { + const param_str = "fff"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_fminf128 = struct { + const param_str = "LLdLLdLLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_fminf16 = struct { + const param_str = "hhh"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_fminl = struct { + const param_str = "LdLdLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_fmod = struct { + const param_str = "ddd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_fmodf = struct { + const param_str = "fff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_fmodf128 = struct { + const param_str = "LLdLLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_fmodf16 = struct { + const param_str = "hhh"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_fmodl = struct { + const param_str = "LdLdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_fpclassify = struct { + const param_str = "iiiiii."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_fprintf = struct { + const param_str = "iP*cC*."; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .format_kind = .printf, + .format_string_position = 1, + }; + }; + + pub const __builtin_frame_address = struct { + const param_str = "v*IUi"; + const attributes = Attributes{}; + }; + + pub const __builtin_free = struct { + const param_str = "vv*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_frexp = struct { + const param_str = "ddi*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_frexpf = struct { + const param_str = "ffi*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_frexpf128 = struct { + const param_str = "LLdLLdi*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_frexpl = struct { + const param_str = "LdLdi*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_frob_return_addr = struct { + const param_str = "v*v*"; + const attributes = Attributes{}; + }; + + pub const __builtin_get_texasr = struct { + const param_str = "LUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_get_texasru = struct { + const param_str = "LUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_get_tfhar = struct { + const param_str = "LUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_get_tfiar = struct { + const param_str = "LUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_getid = struct { + const param_str = "Si"; + const target_set = TargetSet.init(.{ + .xcore = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_getps = struct { + const param_str = "UiUi"; + const target_set = TargetSet.init(.{ + .xcore = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_huge_val = struct { + const param_str = "d"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_huge_valf = struct { + const param_str = "f"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_huge_valf128 = struct { + const param_str = "LLd"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_huge_valf16 = struct { + const param_str = "x"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_huge_vall = struct { + const param_str = "Ld"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_hypot = struct { + const param_str = "ddd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_hypotf = struct { + const param_str = "fff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_hypotf128 = struct { + const param_str = "LLdLLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_hypotl = struct { + const param_str = "LdLdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ia32_rdpmc = struct { + const param_str = "UOii"; + const target_set = TargetSet.init(.{ + .x86 = true, + }); + }; + + pub const __builtin_ia32_rdtsc = struct { + const param_str = "UOi"; + const target_set = TargetSet.init(.{ + .x86 = true, + }); + }; + + pub const __builtin_ia32_rdtscp = struct { + const param_str = "UOiUi*"; + const target_set = TargetSet.init(.{ + .x86 = true, + }); + }; + + pub const __builtin_ilogb = struct { + const param_str = "id"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ilogbf = struct { + const param_str = "if"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ilogbf128 = struct { + const param_str = "iLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ilogbl = struct { + const param_str = "iLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_index = struct { + const param_str = "c*cC*i"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_inf = struct { + const param_str = "d"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_inff = struct { + const param_str = "f"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_inff128 = struct { + const param_str = "LLd"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_inff16 = struct { + const param_str = "x"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_infl = struct { + const param_str = "Ld"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_init_dwarf_reg_size_table = struct { + const param_str = "vv*"; + const attributes = Attributes{}; + }; + + pub const __builtin_is_aligned = struct { + const param_str = "bvC*z"; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_isfinite = struct { + const param_str = "i."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_isgreater = struct { + const param_str = "i."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_isgreaterequal = struct { + const param_str = "i."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_isinf = struct { + const param_str = "i."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_isinf_sign = struct { + const param_str = "i."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_isless = struct { + const param_str = "i."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_islessequal = struct { + const param_str = "i."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_islessgreater = struct { + const param_str = "i."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_isnan = struct { + const param_str = "i."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_isnormal = struct { + const param_str = "i."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_isunordered = struct { + const param_str = "i."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_labs = struct { + const param_str = "LiLi"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_launder = struct { + const param_str = "v*v*"; + const attributes = Attributes{ + .custom_typecheck = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_ldexp = struct { + const param_str = "ddi"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ldexpf = struct { + const param_str = "ffi"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ldexpf128 = struct { + const param_str = "LLdLLdi"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ldexpl = struct { + const param_str = "LdLdi"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_lgamma = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_lgammaf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_lgammaf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_lgammal = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_llabs = struct { + const param_str = "LLiLLi"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_llrint = struct { + const param_str = "LLid"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_llrintf = struct { + const param_str = "LLif"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_llrintf128 = struct { + const param_str = "LLiLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_llrintl = struct { + const param_str = "LLiLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_llround = struct { + const param_str = "LLid"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_llroundf = struct { + const param_str = "LLif"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_llroundf128 = struct { + const param_str = "LLiLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_llroundl = struct { + const param_str = "LLiLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_log = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_log10 = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_log10f = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_log10f128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_log10f16 = struct { + const param_str = "hh"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_log10l = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_log1p = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_log1pf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_log1pf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_log1pl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_log2 = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_log2f = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_log2f128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_log2f16 = struct { + const param_str = "hh"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_log2l = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_logb = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_logbf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_logbf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_logbl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_logf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_logf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_logf16 = struct { + const param_str = "hh"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_logl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_longjmp = struct { + const param_str = "vv**i"; + const attributes = Attributes{ + .noreturn = true, + }; + }; + + pub const __builtin_lrint = struct { + const param_str = "Lid"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_lrintf = struct { + const param_str = "Lif"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_lrintf128 = struct { + const param_str = "LiLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_lrintl = struct { + const param_str = "LiLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_lround = struct { + const param_str = "Lid"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_lroundf = struct { + const param_str = "Lif"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_lroundf128 = struct { + const param_str = "LiLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_lroundl = struct { + const param_str = "LiLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_malloc = struct { + const param_str = "v*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_matrix_column_major_load = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_matrix_column_major_store = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_matrix_transpose = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_memchr = struct { + const param_str = "v*vC*iz"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_memcmp = struct { + const param_str = "ivC*vC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_memcpy = struct { + const param_str = "v*v*vC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_memcpy_inline = struct { + const param_str = "vv*vC*Iz"; + const attributes = Attributes{}; + }; + + pub const __builtin_memmove = struct { + const param_str = "v*v*vC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_mempcpy = struct { + const param_str = "v*v*vC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_memset = struct { + const param_str = "v*v*iz"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_memset_inline = struct { + const param_str = "vv*iIz"; + const attributes = Attributes{}; + }; + + pub const __builtin_mips_absq_s_ph = struct { + const param_str = "V2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_absq_s_qb = struct { + const param_str = "V4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_absq_s_w = struct { + const param_str = "ii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_addq_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_addq_s_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_addq_s_w = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_addqh_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_addqh_r_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_addqh_r_w = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_addqh_w = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_addsc = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_addu_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_addu_qb = struct { + const param_str = "V4ScV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_addu_s_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_addu_s_qb = struct { + const param_str = "V4ScV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_adduh_qb = struct { + const param_str = "V4ScV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_adduh_r_qb = struct { + const param_str = "V4ScV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_addwc = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_append = struct { + const param_str = "iiiIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_balign = struct { + const param_str = "iiiIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_bitrev = struct { + const param_str = "ii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_bposge32 = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_cmp_eq_ph = struct { + const param_str = "vV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_cmp_le_ph = struct { + const param_str = "vV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_cmp_lt_ph = struct { + const param_str = "vV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_cmpgdu_eq_qb = struct { + const param_str = "iV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_cmpgdu_le_qb = struct { + const param_str = "iV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_cmpgdu_lt_qb = struct { + const param_str = "iV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_cmpgu_eq_qb = struct { + const param_str = "iV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_cmpgu_le_qb = struct { + const param_str = "iV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_cmpgu_lt_qb = struct { + const param_str = "iV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_cmpu_eq_qb = struct { + const param_str = "vV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_cmpu_le_qb = struct { + const param_str = "vV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_cmpu_lt_qb = struct { + const param_str = "vV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_dpa_w_ph = struct { + const param_str = "LLiLLiV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_dpaq_s_w_ph = struct { + const param_str = "LLiLLiV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_dpaq_sa_l_w = struct { + const param_str = "LLiLLiii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_dpaqx_s_w_ph = struct { + const param_str = "LLiLLiV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_dpaqx_sa_w_ph = struct { + const param_str = "LLiLLiV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_dpau_h_qbl = struct { + const param_str = "LLiLLiV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_dpau_h_qbr = struct { + const param_str = "LLiLLiV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_dpax_w_ph = struct { + const param_str = "LLiLLiV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_dps_w_ph = struct { + const param_str = "LLiLLiV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_dpsq_s_w_ph = struct { + const param_str = "LLiLLiV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_dpsq_sa_l_w = struct { + const param_str = "LLiLLiii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_dpsqx_s_w_ph = struct { + const param_str = "LLiLLiV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_dpsqx_sa_w_ph = struct { + const param_str = "LLiLLiV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_dpsu_h_qbl = struct { + const param_str = "LLiLLiV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_dpsu_h_qbr = struct { + const param_str = "LLiLLiV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_dpsx_w_ph = struct { + const param_str = "LLiLLiV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_extp = struct { + const param_str = "iLLii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_extpdp = struct { + const param_str = "iLLii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_extr_r_w = struct { + const param_str = "iLLii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_extr_rs_w = struct { + const param_str = "iLLii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_extr_s_h = struct { + const param_str = "iLLii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_extr_w = struct { + const param_str = "iLLii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_insv = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_lbux = struct { + const param_str = "iv*i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_lhx = struct { + const param_str = "iv*i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_lwx = struct { + const param_str = "iv*i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_madd = struct { + const param_str = "LLiLLiii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_maddu = struct { + const param_str = "LLiLLiUiUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_maq_s_w_phl = struct { + const param_str = "LLiLLiV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_maq_s_w_phr = struct { + const param_str = "LLiLLiV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_maq_sa_w_phl = struct { + const param_str = "LLiLLiV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_maq_sa_w_phr = struct { + const param_str = "LLiLLiV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_modsub = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_msub = struct { + const param_str = "LLiLLiii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_msubu = struct { + const param_str = "LLiLLiUiUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_mthlip = struct { + const param_str = "LLiLLii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_mul_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_mul_s_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_muleq_s_w_phl = struct { + const param_str = "iV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_muleq_s_w_phr = struct { + const param_str = "iV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_muleu_s_ph_qbl = struct { + const param_str = "V2sV4ScV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_muleu_s_ph_qbr = struct { + const param_str = "V2sV4ScV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_mulq_rs_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_mulq_rs_w = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_mulq_s_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_mulq_s_w = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_mulsa_w_ph = struct { + const param_str = "LLiLLiV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_mulsaq_s_w_ph = struct { + const param_str = "LLiLLiV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_mult = struct { + const param_str = "LLiii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_multu = struct { + const param_str = "LLiUiUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_packrl_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_pick_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_pick_qb = struct { + const param_str = "V4ScV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_preceq_w_phl = struct { + const param_str = "iV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_preceq_w_phr = struct { + const param_str = "iV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_precequ_ph_qbl = struct { + const param_str = "V2sV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_precequ_ph_qbla = struct { + const param_str = "V2sV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_precequ_ph_qbr = struct { + const param_str = "V2sV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_precequ_ph_qbra = struct { + const param_str = "V2sV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_preceu_ph_qbl = struct { + const param_str = "V2sV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_preceu_ph_qbla = struct { + const param_str = "V2sV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_preceu_ph_qbr = struct { + const param_str = "V2sV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_preceu_ph_qbra = struct { + const param_str = "V2sV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_precr_qb_ph = struct { + const param_str = "V4ScV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_precr_sra_ph_w = struct { + const param_str = "V2siiIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_precr_sra_r_ph_w = struct { + const param_str = "V2siiIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_precrq_ph_w = struct { + const param_str = "V2sii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_precrq_qb_ph = struct { + const param_str = "V4ScV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_precrq_rs_ph_w = struct { + const param_str = "V2sii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_precrqu_s_qb_ph = struct { + const param_str = "V4ScV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_prepend = struct { + const param_str = "iiiIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_raddu_w_qb = struct { + const param_str = "iV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_rddsp = struct { + const param_str = "iIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_repl_ph = struct { + const param_str = "V2si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_repl_qb = struct { + const param_str = "V4Sci"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_shilo = struct { + const param_str = "LLiLLii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_shll_ph = struct { + const param_str = "V2sV2si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_shll_qb = struct { + const param_str = "V4ScV4Sci"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_shll_s_ph = struct { + const param_str = "V2sV2si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_shll_s_w = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_shra_ph = struct { + const param_str = "V2sV2si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_shra_qb = struct { + const param_str = "V4ScV4Sci"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_shra_r_ph = struct { + const param_str = "V2sV2si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_shra_r_qb = struct { + const param_str = "V4ScV4Sci"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_shra_r_w = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_shrl_ph = struct { + const param_str = "V2sV2si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_shrl_qb = struct { + const param_str = "V4ScV4Sci"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_subq_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_subq_s_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_subq_s_w = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_subqh_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_subqh_r_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_subqh_r_w = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_subqh_w = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_subu_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_subu_qb = struct { + const param_str = "V4ScV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_subu_s_ph = struct { + const param_str = "V2sV2sV2s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_subu_s_qb = struct { + const param_str = "V4ScV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_mips_subuh_qb = struct { + const param_str = "V4ScV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_subuh_r_qb = struct { + const param_str = "V4ScV4ScV4Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mips_wrdsp = struct { + const param_str = "viIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_modf = struct { + const param_str = "ddd*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_modff = struct { + const param_str = "fff*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_modff128 = struct { + const param_str = "LLdLLdLLd*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_modfl = struct { + const param_str = "LdLdLd*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_msa_add_a_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_add_a_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_add_a_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_add_a_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_adds_a_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_adds_a_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_adds_a_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_adds_a_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_adds_s_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_adds_s_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_adds_s_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_adds_s_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_adds_u_b = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_adds_u_d = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_adds_u_h = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_adds_u_w = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_addv_b = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_addv_d = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_addv_h = struct { + const param_str = "V8sV8sV8s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_addv_w = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_addvi_b = struct { + const param_str = "V16cV16cIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_addvi_d = struct { + const param_str = "V2LLiV2LLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_addvi_h = struct { + const param_str = "V8sV8sIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_addvi_w = struct { + const param_str = "V4iV4iIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_and_v = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_andi_b = struct { + const param_str = "V16UcV16UcIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_asub_s_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_asub_s_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_asub_s_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_asub_s_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_asub_u_b = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_asub_u_d = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_asub_u_h = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_asub_u_w = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ave_s_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ave_s_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ave_s_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ave_s_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ave_u_b = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ave_u_d = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ave_u_h = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ave_u_w = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_aver_s_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_aver_s_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_aver_s_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_aver_s_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_aver_u_b = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_aver_u_d = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_aver_u_h = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_aver_u_w = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bclr_b = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bclr_d = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bclr_h = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bclr_w = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bclri_b = struct { + const param_str = "V16UcV16UcIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bclri_d = struct { + const param_str = "V2ULLiV2ULLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bclri_h = struct { + const param_str = "V8UsV8UsIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bclri_w = struct { + const param_str = "V4UiV4UiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_binsl_b = struct { + const param_str = "V16UcV16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_binsl_d = struct { + const param_str = "V2ULLiV2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_binsl_h = struct { + const param_str = "V8UsV8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_binsl_w = struct { + const param_str = "V4UiV4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_binsli_b = struct { + const param_str = "V16UcV16UcV16UcIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_binsli_d = struct { + const param_str = "V2ULLiV2ULLiV2ULLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_binsli_h = struct { + const param_str = "V8UsV8UsV8UsIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_binsli_w = struct { + const param_str = "V4UiV4UiV4UiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_binsr_b = struct { + const param_str = "V16UcV16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_binsr_d = struct { + const param_str = "V2ULLiV2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_binsr_h = struct { + const param_str = "V8UsV8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_binsr_w = struct { + const param_str = "V4UiV4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_binsri_b = struct { + const param_str = "V16UcV16UcV16UcIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_binsri_d = struct { + const param_str = "V2ULLiV2ULLiV2ULLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_binsri_h = struct { + const param_str = "V8UsV8UsV8UsIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_binsri_w = struct { + const param_str = "V4UiV4UiV4UiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bmnz_v = struct { + const param_str = "V16UcV16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bmnzi_b = struct { + const param_str = "V16UcV16UcV16UcIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bmz_v = struct { + const param_str = "V16UcV16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bmzi_b = struct { + const param_str = "V16UcV16UcV16UcIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bneg_b = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bneg_d = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bneg_h = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bneg_w = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bnegi_b = struct { + const param_str = "V16UcV16UcIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bnegi_d = struct { + const param_str = "V2ULLiV2ULLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bnegi_h = struct { + const param_str = "V8UsV8UsIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bnegi_w = struct { + const param_str = "V4UiV4UiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bnz_b = struct { + const param_str = "iV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bnz_d = struct { + const param_str = "iV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bnz_h = struct { + const param_str = "iV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bnz_v = struct { + const param_str = "iV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bnz_w = struct { + const param_str = "iV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bsel_v = struct { + const param_str = "V16UcV16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bseli_b = struct { + const param_str = "V16UcV16UcV16UcIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bset_b = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bset_d = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bset_h = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bset_w = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bseti_b = struct { + const param_str = "V16UcV16UcIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bseti_d = struct { + const param_str = "V2ULLiV2ULLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bseti_h = struct { + const param_str = "V8UsV8UsIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bseti_w = struct { + const param_str = "V4UiV4UiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bz_b = struct { + const param_str = "iV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bz_d = struct { + const param_str = "iV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bz_h = struct { + const param_str = "iV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bz_v = struct { + const param_str = "iV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_bz_w = struct { + const param_str = "iV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ceq_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ceq_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ceq_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ceq_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ceqi_b = struct { + const param_str = "V16ScV16ScISi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ceqi_d = struct { + const param_str = "V2SLLiV2SLLiISi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ceqi_h = struct { + const param_str = "V8SsV8SsISi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ceqi_w = struct { + const param_str = "V4SiV4SiISi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_cfcmsa = struct { + const param_str = "iIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_msa_cle_s_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_cle_s_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_cle_s_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_cle_s_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_cle_u_b = struct { + const param_str = "V16ScV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_cle_u_d = struct { + const param_str = "V2SLLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_cle_u_h = struct { + const param_str = "V8SsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_cle_u_w = struct { + const param_str = "V4SiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clei_s_b = struct { + const param_str = "V16ScV16ScISi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clei_s_d = struct { + const param_str = "V2SLLiV2SLLiISi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clei_s_h = struct { + const param_str = "V8SsV8SsISi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clei_s_w = struct { + const param_str = "V4SiV4SiISi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clei_u_b = struct { + const param_str = "V16ScV16UcIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clei_u_d = struct { + const param_str = "V2SLLiV2ULLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clei_u_h = struct { + const param_str = "V8SsV8UsIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clei_u_w = struct { + const param_str = "V4SiV4UiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clt_s_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clt_s_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clt_s_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clt_s_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clt_u_b = struct { + const param_str = "V16ScV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clt_u_d = struct { + const param_str = "V2SLLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clt_u_h = struct { + const param_str = "V8SsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clt_u_w = struct { + const param_str = "V4SiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clti_s_b = struct { + const param_str = "V16ScV16ScISi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clti_s_d = struct { + const param_str = "V2SLLiV2SLLiISi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clti_s_h = struct { + const param_str = "V8SsV8SsISi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clti_s_w = struct { + const param_str = "V4SiV4SiISi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clti_u_b = struct { + const param_str = "V16ScV16UcIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clti_u_d = struct { + const param_str = "V2SLLiV2ULLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clti_u_h = struct { + const param_str = "V8SsV8UsIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_clti_u_w = struct { + const param_str = "V4SiV4UiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_copy_s_b = struct { + const param_str = "iV16ScIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_copy_s_d = struct { + const param_str = "LLiV2SLLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_copy_s_h = struct { + const param_str = "iV8SsIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_copy_s_w = struct { + const param_str = "iV4SiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_copy_u_b = struct { + const param_str = "iV16UcIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_copy_u_d = struct { + const param_str = "LLiV2ULLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_copy_u_h = struct { + const param_str = "iV8UsIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_copy_u_w = struct { + const param_str = "iV4UiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ctcmsa = struct { + const param_str = "vIii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_msa_div_s_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_div_s_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_div_s_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_div_s_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_div_u_b = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_div_u_d = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_div_u_h = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_div_u_w = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dotp_s_d = struct { + const param_str = "V2SLLiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dotp_s_h = struct { + const param_str = "V8SsV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dotp_s_w = struct { + const param_str = "V4SiV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dotp_u_d = struct { + const param_str = "V2ULLiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dotp_u_h = struct { + const param_str = "V8UsV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dotp_u_w = struct { + const param_str = "V4UiV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dpadd_s_d = struct { + const param_str = "V2SLLiV2SLLiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dpadd_s_h = struct { + const param_str = "V8SsV8SsV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dpadd_s_w = struct { + const param_str = "V4SiV4SiV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dpadd_u_d = struct { + const param_str = "V2ULLiV2ULLiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dpadd_u_h = struct { + const param_str = "V8UsV8UsV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dpadd_u_w = struct { + const param_str = "V4UiV4UiV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dpsub_s_d = struct { + const param_str = "V2SLLiV2SLLiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dpsub_s_h = struct { + const param_str = "V8SsV8SsV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dpsub_s_w = struct { + const param_str = "V4SiV4SiV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dpsub_u_d = struct { + const param_str = "V2ULLiV2ULLiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dpsub_u_h = struct { + const param_str = "V8UsV8UsV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_dpsub_u_w = struct { + const param_str = "V4UiV4UiV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fadd_d = struct { + const param_str = "V2dV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fadd_w = struct { + const param_str = "V4fV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcaf_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcaf_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fceq_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fceq_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fclass_d = struct { + const param_str = "V2LLiV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fclass_w = struct { + const param_str = "V4iV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcle_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcle_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fclt_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fclt_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcne_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcne_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcor_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcor_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcueq_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcueq_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcule_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcule_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcult_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcult_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcun_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcun_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcune_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fcune_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fdiv_d = struct { + const param_str = "V2dV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fdiv_w = struct { + const param_str = "V4fV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fexdo_h = struct { + const param_str = "V8hV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fexdo_w = struct { + const param_str = "V4fV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fexp2_d = struct { + const param_str = "V2dV2dV2LLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fexp2_w = struct { + const param_str = "V4fV4fV4i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fexupl_d = struct { + const param_str = "V2dV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fexupl_w = struct { + const param_str = "V4fV8h"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fexupr_d = struct { + const param_str = "V2dV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fexupr_w = struct { + const param_str = "V4fV8h"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ffint_s_d = struct { + const param_str = "V2dV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ffint_s_w = struct { + const param_str = "V4fV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ffint_u_d = struct { + const param_str = "V2dV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ffint_u_w = struct { + const param_str = "V4fV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ffql_d = struct { + const param_str = "V2dV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ffql_w = struct { + const param_str = "V4fV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ffqr_d = struct { + const param_str = "V2dV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ffqr_w = struct { + const param_str = "V4fV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fill_b = struct { + const param_str = "V16Sci"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fill_d = struct { + const param_str = "V2SLLiLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fill_h = struct { + const param_str = "V8Ssi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fill_w = struct { + const param_str = "V4Sii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_flog2_d = struct { + const param_str = "V2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_flog2_w = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fmadd_d = struct { + const param_str = "V2dV2dV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fmadd_w = struct { + const param_str = "V4fV4fV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fmax_a_d = struct { + const param_str = "V2dV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fmax_a_w = struct { + const param_str = "V4fV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fmax_d = struct { + const param_str = "V2dV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fmax_w = struct { + const param_str = "V4fV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fmin_a_d = struct { + const param_str = "V2dV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fmin_a_w = struct { + const param_str = "V4fV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fmin_d = struct { + const param_str = "V2dV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fmin_w = struct { + const param_str = "V4fV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fmsub_d = struct { + const param_str = "V2dV2dV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fmsub_w = struct { + const param_str = "V4fV4fV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fmul_d = struct { + const param_str = "V2dV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fmul_w = struct { + const param_str = "V4fV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_frcp_d = struct { + const param_str = "V2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_frcp_w = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_frint_d = struct { + const param_str = "V2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_frint_w = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_frsqrt_d = struct { + const param_str = "V2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_frsqrt_w = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsaf_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsaf_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fseq_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fseq_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsle_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsle_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fslt_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fslt_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsne_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsne_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsor_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsor_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsqrt_d = struct { + const param_str = "V2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsqrt_w = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsub_d = struct { + const param_str = "V2dV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsub_w = struct { + const param_str = "V4fV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsueq_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsueq_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsule_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsule_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsult_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsult_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsun_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsun_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsune_d = struct { + const param_str = "V2LLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_fsune_w = struct { + const param_str = "V4iV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ftint_s_d = struct { + const param_str = "V2SLLiV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ftint_s_w = struct { + const param_str = "V4SiV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ftint_u_d = struct { + const param_str = "V2ULLiV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ftint_u_w = struct { + const param_str = "V4UiV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ftq_h = struct { + const param_str = "V4UiV4fV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ftq_w = struct { + const param_str = "V2ULLiV2dV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ftrunc_s_d = struct { + const param_str = "V2SLLiV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ftrunc_s_w = struct { + const param_str = "V4SiV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ftrunc_u_d = struct { + const param_str = "V2ULLiV2d"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ftrunc_u_w = struct { + const param_str = "V4UiV4f"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_hadd_s_d = struct { + const param_str = "V2SLLiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_hadd_s_h = struct { + const param_str = "V8SsV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_hadd_s_w = struct { + const param_str = "V4SiV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_hadd_u_d = struct { + const param_str = "V2ULLiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_hadd_u_h = struct { + const param_str = "V8UsV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_hadd_u_w = struct { + const param_str = "V4UiV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_hsub_s_d = struct { + const param_str = "V2SLLiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_hsub_s_h = struct { + const param_str = "V8SsV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_hsub_s_w = struct { + const param_str = "V4SiV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_hsub_u_d = struct { + const param_str = "V2ULLiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_hsub_u_h = struct { + const param_str = "V8UsV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_hsub_u_w = struct { + const param_str = "V4UiV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ilvev_b = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ilvev_d = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ilvev_h = struct { + const param_str = "V8sV8sV8s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ilvev_w = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ilvl_b = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ilvl_d = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ilvl_h = struct { + const param_str = "V8sV8sV8s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ilvl_w = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ilvod_b = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ilvod_d = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ilvod_h = struct { + const param_str = "V8sV8sV8s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ilvod_w = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ilvr_b = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ilvr_d = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ilvr_h = struct { + const param_str = "V8sV8sV8s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ilvr_w = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_insert_b = struct { + const param_str = "V16ScV16ScIUii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_insert_d = struct { + const param_str = "V2SLLiV2SLLiIUiLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_insert_h = struct { + const param_str = "V8SsV8SsIUii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_insert_w = struct { + const param_str = "V4SiV4SiIUii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_insve_b = struct { + const param_str = "V16ScV16ScIUiV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_insve_d = struct { + const param_str = "V2SLLiV2SLLiIUiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_insve_h = struct { + const param_str = "V8SsV8SsIUiV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_insve_w = struct { + const param_str = "V4SiV4SiIUiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ld_b = struct { + const param_str = "V16Scv*Ii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ld_d = struct { + const param_str = "V2SLLiv*Ii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ld_h = struct { + const param_str = "V8Ssv*Ii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ld_w = struct { + const param_str = "V4Siv*Ii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ldi_b = struct { + const param_str = "V16cIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ldi_d = struct { + const param_str = "V2LLiIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ldi_h = struct { + const param_str = "V8sIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ldi_w = struct { + const param_str = "V4iIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ldr_d = struct { + const param_str = "V2SLLiv*Ii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ldr_w = struct { + const param_str = "V4Siv*Ii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_madd_q_h = struct { + const param_str = "V8SsV8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_madd_q_w = struct { + const param_str = "V4SiV4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_maddr_q_h = struct { + const param_str = "V8SsV8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_maddr_q_w = struct { + const param_str = "V4SiV4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_maddv_b = struct { + const param_str = "V16ScV16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_maddv_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_maddv_h = struct { + const param_str = "V8SsV8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_maddv_w = struct { + const param_str = "V4SiV4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_max_a_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_max_a_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_max_a_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_max_a_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_max_s_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_max_s_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_max_s_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_max_s_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_max_u_b = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_max_u_d = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_max_u_h = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_max_u_w = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_maxi_s_b = struct { + const param_str = "V16ScV16ScIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_maxi_s_d = struct { + const param_str = "V2SLLiV2SLLiIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_maxi_s_h = struct { + const param_str = "V8SsV8SsIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_maxi_s_w = struct { + const param_str = "V4SiV4SiIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_maxi_u_b = struct { + const param_str = "V16UcV16UcIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_maxi_u_d = struct { + const param_str = "V2ULLiV2ULLiIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_maxi_u_h = struct { + const param_str = "V8UsV8UsIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_maxi_u_w = struct { + const param_str = "V4UiV4UiIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_min_a_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_min_a_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_min_a_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_min_a_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_min_s_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_min_s_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_min_s_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_min_s_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_min_u_b = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_min_u_d = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_min_u_h = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_min_u_w = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mini_s_b = struct { + const param_str = "V16ScV16ScIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mini_s_d = struct { + const param_str = "V2SLLiV2SLLiIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mini_s_h = struct { + const param_str = "V8SsV8SsIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mini_s_w = struct { + const param_str = "V4SiV4SiIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mini_u_b = struct { + const param_str = "V16UcV16UcIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mini_u_d = struct { + const param_str = "V2ULLiV2ULLiIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mini_u_h = struct { + const param_str = "V8UsV8UsIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mini_u_w = struct { + const param_str = "V4UiV4UiIi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mod_s_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mod_s_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mod_s_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mod_s_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mod_u_b = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mod_u_d = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mod_u_h = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mod_u_w = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_move_v = struct { + const param_str = "V16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_msub_q_h = struct { + const param_str = "V8SsV8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_msub_q_w = struct { + const param_str = "V4SiV4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_msubr_q_h = struct { + const param_str = "V8SsV8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_msubr_q_w = struct { + const param_str = "V4SiV4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_msubv_b = struct { + const param_str = "V16ScV16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_msubv_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_msubv_h = struct { + const param_str = "V8SsV8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_msubv_w = struct { + const param_str = "V4SiV4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mul_q_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mul_q_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mulr_q_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mulr_q_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mulv_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mulv_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mulv_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_mulv_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_nloc_b = struct { + const param_str = "V16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_nloc_d = struct { + const param_str = "V2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_nloc_h = struct { + const param_str = "V8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_nloc_w = struct { + const param_str = "V4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_nlzc_b = struct { + const param_str = "V16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_nlzc_d = struct { + const param_str = "V2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_nlzc_h = struct { + const param_str = "V8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_nlzc_w = struct { + const param_str = "V4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_nor_v = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_nori_b = struct { + const param_str = "V16UcV16cIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_or_v = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_ori_b = struct { + const param_str = "V16UcV16UcIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_pckev_b = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_pckev_d = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_pckev_h = struct { + const param_str = "V8sV8sV8s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_pckev_w = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_pckod_b = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_pckod_d = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_pckod_h = struct { + const param_str = "V8sV8sV8s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_pckod_w = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_pcnt_b = struct { + const param_str = "V16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_pcnt_d = struct { + const param_str = "V2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_pcnt_h = struct { + const param_str = "V8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_pcnt_w = struct { + const param_str = "V4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sat_s_b = struct { + const param_str = "V16ScV16ScIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sat_s_d = struct { + const param_str = "V2SLLiV2SLLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sat_s_h = struct { + const param_str = "V8SsV8SsIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sat_s_w = struct { + const param_str = "V4SiV4SiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sat_u_b = struct { + const param_str = "V16UcV16UcIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sat_u_d = struct { + const param_str = "V2ULLiV2ULLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sat_u_h = struct { + const param_str = "V8UsV8UsIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sat_u_w = struct { + const param_str = "V4UiV4UiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_shf_b = struct { + const param_str = "V16cV16cIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_shf_h = struct { + const param_str = "V8sV8sIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_shf_w = struct { + const param_str = "V4iV4iIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sld_b = struct { + const param_str = "V16cV16cV16cUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sld_d = struct { + const param_str = "V2LLiV2LLiV2LLiUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sld_h = struct { + const param_str = "V8sV8sV8sUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sld_w = struct { + const param_str = "V4iV4iV4iUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sldi_b = struct { + const param_str = "V16cV16cV16cIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sldi_d = struct { + const param_str = "V2LLiV2LLiV2LLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sldi_h = struct { + const param_str = "V8sV8sV8sIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sldi_w = struct { + const param_str = "V4iV4iV4iIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sll_b = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sll_d = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sll_h = struct { + const param_str = "V8sV8sV8s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sll_w = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_slli_b = struct { + const param_str = "V16cV16cIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_slli_d = struct { + const param_str = "V2LLiV2LLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_slli_h = struct { + const param_str = "V8sV8sIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_slli_w = struct { + const param_str = "V4iV4iIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_splat_b = struct { + const param_str = "V16cV16cUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_splat_d = struct { + const param_str = "V2LLiV2LLiUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_splat_h = struct { + const param_str = "V8sV8sUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_splat_w = struct { + const param_str = "V4iV4iUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_splati_b = struct { + const param_str = "V16cV16cIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_splati_d = struct { + const param_str = "V2LLiV2LLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_splati_h = struct { + const param_str = "V8sV8sIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_splati_w = struct { + const param_str = "V4iV4iIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sra_b = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sra_d = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sra_h = struct { + const param_str = "V8sV8sV8s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_sra_w = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srai_b = struct { + const param_str = "V16cV16cIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srai_d = struct { + const param_str = "V2LLiV2LLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srai_h = struct { + const param_str = "V8sV8sIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srai_w = struct { + const param_str = "V4iV4iIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srar_b = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srar_d = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srar_h = struct { + const param_str = "V8sV8sV8s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srar_w = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srari_b = struct { + const param_str = "V16cV16cIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srari_d = struct { + const param_str = "V2LLiV2LLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srari_h = struct { + const param_str = "V8sV8sIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srari_w = struct { + const param_str = "V4iV4iIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srl_b = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srl_d = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srl_h = struct { + const param_str = "V8sV8sV8s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srl_w = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srli_b = struct { + const param_str = "V16cV16cIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srli_d = struct { + const param_str = "V2LLiV2LLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srli_h = struct { + const param_str = "V8sV8sIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srli_w = struct { + const param_str = "V4iV4iIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srlr_b = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srlr_d = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srlr_h = struct { + const param_str = "V8sV8sV8s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srlr_w = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srlri_b = struct { + const param_str = "V16cV16cIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srlri_d = struct { + const param_str = "V2LLiV2LLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srlri_h = struct { + const param_str = "V8sV8sIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_srlri_w = struct { + const param_str = "V4iV4iIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_st_b = struct { + const param_str = "vV16Scv*Ii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_st_d = struct { + const param_str = "vV2SLLiv*Ii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_st_h = struct { + const param_str = "vV8Ssv*Ii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_st_w = struct { + const param_str = "vV4Siv*Ii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_str_d = struct { + const param_str = "vV2SLLiv*Ii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_str_w = struct { + const param_str = "vV4Siv*Ii"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subs_s_b = struct { + const param_str = "V16ScV16ScV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subs_s_d = struct { + const param_str = "V2SLLiV2SLLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subs_s_h = struct { + const param_str = "V8SsV8SsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subs_s_w = struct { + const param_str = "V4SiV4SiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subs_u_b = struct { + const param_str = "V16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subs_u_d = struct { + const param_str = "V2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subs_u_h = struct { + const param_str = "V8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subs_u_w = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subsus_u_b = struct { + const param_str = "V16UcV16UcV16Sc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subsus_u_d = struct { + const param_str = "V2ULLiV2ULLiV2SLLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subsus_u_h = struct { + const param_str = "V8UsV8UsV8Ss"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subsus_u_w = struct { + const param_str = "V4UiV4UiV4Si"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subsuu_s_b = struct { + const param_str = "V16ScV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subsuu_s_d = struct { + const param_str = "V2SLLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subsuu_s_h = struct { + const param_str = "V8SsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subsuu_s_w = struct { + const param_str = "V4SiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subv_b = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subv_d = struct { + const param_str = "V2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subv_h = struct { + const param_str = "V8sV8sV8s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subv_w = struct { + const param_str = "V4iV4iV4i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subvi_b = struct { + const param_str = "V16cV16cIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subvi_d = struct { + const param_str = "V2LLiV2LLiIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subvi_h = struct { + const param_str = "V8sV8sIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_subvi_w = struct { + const param_str = "V4iV4iIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_vshf_b = struct { + const param_str = "V16cV16cV16cV16c"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_vshf_d = struct { + const param_str = "V2LLiV2LLiV2LLiV2LLi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_vshf_h = struct { + const param_str = "V8sV8sV8sV8s"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_vshf_w = struct { + const param_str = "V4iV4iV4iV4i"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_xor_v = struct { + const param_str = "V16cV16cV16c"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_msa_xori_b = struct { + const param_str = "V16cV16cIUi"; + const target_set = TargetSet.init(.{ + .mips = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_mul_overflow = struct { + const param_str = "b."; + const attributes = Attributes{ + .custom_typecheck = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_mulf128_round_to_odd = struct { + const param_str = "LLdLLdLLd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_nan = struct { + const param_str = "dcC*"; + const attributes = Attributes{ + .pure = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_nanf = struct { + const param_str = "fcC*"; + const attributes = Attributes{ + .pure = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_nanf128 = struct { + const param_str = "LLdcC*"; + const attributes = Attributes{ + .pure = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_nanf16 = struct { + const param_str = "xcC*"; + const attributes = Attributes{ + .pure = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_nanl = struct { + const param_str = "LdcC*"; + const attributes = Attributes{ + .pure = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_nans = struct { + const param_str = "dcC*"; + const attributes = Attributes{ + .pure = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_nansf = struct { + const param_str = "fcC*"; + const attributes = Attributes{ + .pure = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_nansf128 = struct { + const param_str = "LLdcC*"; + const attributes = Attributes{ + .pure = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_nansf16 = struct { + const param_str = "xcC*"; + const attributes = Attributes{ + .pure = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_nansl = struct { + const param_str = "LdcC*"; + const attributes = Attributes{ + .pure = true, + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_nearbyint = struct { + const param_str = "dd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_nearbyintf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_nearbyintf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_nearbyintl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_nextafter = struct { + const param_str = "ddd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_nextafterf = struct { + const param_str = "fff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_nextafterf128 = struct { + const param_str = "LLdLLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_nextafterl = struct { + const param_str = "LdLdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_nexttoward = struct { + const param_str = "ddLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_nexttowardf = struct { + const param_str = "ffLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_nexttowardf128 = struct { + const param_str = "LLdLLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_nexttowardl = struct { + const param_str = "LdLdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_nontemporal_load = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_nontemporal_store = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_objc_memmove_collectable = struct { + const param_str = "v*v*vC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_object_size = struct { + const param_str = "zvC*i"; + const attributes = Attributes{ + .eval_args = false, + .const_evaluable = true, + }; + }; + + pub const __builtin_operator_delete = struct { + const param_str = "vv*"; + const attributes = Attributes{ + .custom_typecheck = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_operator_new = struct { + const param_str = "v*z"; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_os_log_format = struct { + const param_str = "v*v*cC*."; + const attributes = Attributes{ + .custom_typecheck = true, + .format_kind = .printf, + .format_string_position = 0, + }; + }; + + pub const __builtin_os_log_format_buffer_size = struct { + const param_str = "zcC*."; + const attributes = Attributes{ + .custom_typecheck = true, + .eval_args = false, + .const_evaluable = true, + .format_kind = .printf, + .format_string_position = 0, + }; + }; + + pub const __builtin_pack_longdouble = struct { + const param_str = "Lddd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_pack_vector_int128 = struct { + const param_str = "V1LLLiULLiULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_parity = struct { + const param_str = "iUi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_parityl = struct { + const param_str = "iULi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_parityll = struct { + const param_str = "iULLi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_pdepd = struct { + const param_str = "ULLiULLiULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_pextd = struct { + const param_str = "ULLiULLiULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_popcount = struct { + const param_str = "iUi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_popcountl = struct { + const param_str = "iULi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_popcountll = struct { + const param_str = "iULLi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_pow = struct { + const param_str = "ddd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_powf = struct { + const param_str = "fff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_powf128 = struct { + const param_str = "LLdLLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_powf16 = struct { + const param_str = "hhh"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_powi = struct { + const param_str = "ddi"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_powif = struct { + const param_str = "ffi"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_powil = struct { + const param_str = "LdLdi"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_powl = struct { + const param_str = "LdLdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ppc_addex = struct { + const param_str = "LLiLLiLLiCIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_alignx = struct { + const param_str = "vIivC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_ppc_bcdadd = struct { + const param_str = "V16UcV16UcV16UcIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_bcdadd_p = struct { + const param_str = "iiV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_bcdsub = struct { + const param_str = "V16UcV16UcV16UcIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_bcdsub_p = struct { + const param_str = "iiV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_cmpb = struct { + const param_str = "LLiLLiLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_cmpeqb = struct { + const param_str = "LLiLLiLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_cmprb = struct { + const param_str = "iCIiii"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_compare_and_swap = struct { + const param_str = "iiD*i*i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_compare_and_swaplp = struct { + const param_str = "iLiD*Li*Li"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_compare_exp_eq = struct { + const param_str = "idd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_compare_exp_gt = struct { + const param_str = "idd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_compare_exp_lt = struct { + const param_str = "idd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_compare_exp_uo = struct { + const param_str = "idd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_dcbfl = struct { + const param_str = "vvC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_dcbflp = struct { + const param_str = "vvC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_dcbst = struct { + const param_str = "vvC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_dcbt = struct { + const param_str = "vv*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_dcbtst = struct { + const param_str = "vv*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_dcbtstt = struct { + const param_str = "vv*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_dcbtt = struct { + const param_str = "vv*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_dcbz = struct { + const param_str = "vv*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_eieio = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_extract_exp = struct { + const param_str = "Uid"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_extract_sig = struct { + const param_str = "ULLid"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fcfid = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fcfud = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fctid = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fctidz = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fctiw = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fctiwz = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fctudz = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fctuwz = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fetch_and_add = struct { + const param_str = "iiD*i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fetch_and_addlp = struct { + const param_str = "LiLiD*Li"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fetch_and_and = struct { + const param_str = "UiUiD*Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fetch_and_andlp = struct { + const param_str = "ULiULiD*ULi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fetch_and_or = struct { + const param_str = "UiUiD*Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fetch_and_orlp = struct { + const param_str = "ULiULiD*ULi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fetch_and_swap = struct { + const param_str = "UiUiD*Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fetch_and_swaplp = struct { + const param_str = "ULiULiD*ULi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fmsub = struct { + const param_str = "dddd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fmsubs = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fnabs = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fnabss = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fnmadd = struct { + const param_str = "dddd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fnmadds = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fnmsub = struct { + const param_str = "dddd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fnmsubs = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fre = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fres = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fric = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_frim = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_frims = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_frin = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_frins = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_frip = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_frips = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_friz = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_frizs = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_frsqrte = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_frsqrtes = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fsel = struct { + const param_str = "dddd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fsels = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fsqrt = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_fsqrts = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_get_timebase = struct { + const param_str = "ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ppc_icbt = struct { + const param_str = "vv*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_insert_exp = struct { + const param_str = "ddULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_iospace_eieio = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_iospace_lwsync = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_iospace_sync = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_isync = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_lbarx = struct { + const param_str = "ccD*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_ldarx = struct { + const param_str = "LiLiD*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_lharx = struct { + const param_str = "ssD*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_load2r = struct { + const param_str = "UsUs*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_load4r = struct { + const param_str = "UiUi*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_load8r = struct { + const param_str = "ULLiULLi*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_lwarx = struct { + const param_str = "iiD*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_lwsync = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_maddhd = struct { + const param_str = "LLiLLiLLiLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_maddhdu = struct { + const param_str = "ULLiULLiULLiULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_maddld = struct { + const param_str = "LLiLLiLLiLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_maxfe = struct { + const param_str = "LdLdLdLd."; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_ppc_maxfl = struct { + const param_str = "dddd."; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_ppc_maxfs = struct { + const param_str = "ffff."; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_ppc_mfmsr = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_mfspr = struct { + const param_str = "ULiIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_mftbu = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_minfe = struct { + const param_str = "LdLdLdLd."; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_ppc_minfl = struct { + const param_str = "dddd."; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_ppc_minfs = struct { + const param_str = "ffff."; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_ppc_mtfsb0 = struct { + const param_str = "vUIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_mtfsb1 = struct { + const param_str = "vUIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_mtfsf = struct { + const param_str = "vUIiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_mtfsfi = struct { + const param_str = "vUIiUIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_mtmsr = struct { + const param_str = "vUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_mtspr = struct { + const param_str = "vIiULi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_mulhd = struct { + const param_str = "LLiLiLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_mulhdu = struct { + const param_str = "ULLiULiULi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_mulhw = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_mulhwu = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_popcntb = struct { + const param_str = "ULiULi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_poppar4 = struct { + const param_str = "iUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_poppar8 = struct { + const param_str = "iULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_rdlam = struct { + const param_str = "UWiUWiUWiUWIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_ppc_recipdivd = struct { + const param_str = "V2dV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_recipdivf = struct { + const param_str = "V4fV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_rldimi = struct { + const param_str = "ULLiULLiULLiIUiIULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_rlwimi = struct { + const param_str = "UiUiUiIUiIUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_rlwnm = struct { + const param_str = "UiUiUiIUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_rsqrtd = struct { + const param_str = "V2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_rsqrtf = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_setb = struct { + const param_str = "LLiLLiLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_stbcx = struct { + const param_str = "icD*i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_stdcx = struct { + const param_str = "iLiD*Li"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_stfiw = struct { + const param_str = "viC*d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_sthcx = struct { + const param_str = "isD*s"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_store2r = struct { + const param_str = "vUiUs*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_store4r = struct { + const param_str = "vUiUi*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_store8r = struct { + const param_str = "vULLiULLi*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_stwcx = struct { + const param_str = "iiD*i"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_swdiv = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_swdiv_nochk = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_swdivs = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_swdivs_nochk = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_sync = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_tdw = struct { + const param_str = "vLLiLLiIUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_test_data_class = struct { + const param_str = "idIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_ppc_trap = struct { + const param_str = "vi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_trapd = struct { + const param_str = "vLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ppc_tw = struct { + const param_str = "viiIUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_prefetch = struct { + const param_str = "vvC*."; + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_preserve_access_index = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_printf = struct { + const param_str = "icC*."; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .format_kind = .printf, + .format_string_position = 0, + }; + }; + + pub const __builtin_ptx_get_image_channel_data_typei_ = struct { + const param_str = "ii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __builtin_ptx_get_image_channel_orderi_ = struct { + const param_str = "ii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __builtin_ptx_get_image_depthi_ = struct { + const param_str = "ii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __builtin_ptx_get_image_heighti_ = struct { + const param_str = "ii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __builtin_ptx_get_image_widthi_ = struct { + const param_str = "ii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __builtin_ptx_read_image2Dff_ = struct { + const param_str = "V4fiiff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __builtin_ptx_read_image2Dfi_ = struct { + const param_str = "V4fiiii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __builtin_ptx_read_image2Dif_ = struct { + const param_str = "V4iiiff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __builtin_ptx_read_image2Dii_ = struct { + const param_str = "V4iiiii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __builtin_ptx_read_image3Dff_ = struct { + const param_str = "V4fiiffff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __builtin_ptx_read_image3Dfi_ = struct { + const param_str = "V4fiiiiii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __builtin_ptx_read_image3Dif_ = struct { + const param_str = "V4iiiffff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __builtin_ptx_read_image3Dii_ = struct { + const param_str = "V4iiiiiii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __builtin_ptx_write_image2Df_ = struct { + const param_str = "viiiffff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __builtin_ptx_write_image2Di_ = struct { + const param_str = "viiiiiii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __builtin_ptx_write_image2Dui_ = struct { + const param_str = "viiiUiUiUiUi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __builtin_r600_implicitarg_ptr = struct { + const param_str = "Uc*7"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_r600_read_tgid_x = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_r600_read_tgid_y = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_r600_read_tgid_z = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_r600_read_tidig_x = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_r600_read_tidig_y = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_r600_read_tidig_z = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_r600_recipsqrt_ieee = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_r600_recipsqrt_ieeef = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .amdgpu = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_readcyclecounter = struct { + const param_str = "ULLi"; + const attributes = Attributes{}; + }; + + pub const __builtin_readflm = struct { + const param_str = "d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_realloc = struct { + const param_str = "v*v*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_reduce_add = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_reduce_and = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_reduce_max = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_reduce_min = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_reduce_mul = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_reduce_or = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_reduce_xor = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_remainder = struct { + const param_str = "ddd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_remainderf = struct { + const param_str = "fff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_remainderf128 = struct { + const param_str = "LLdLLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_remainderl = struct { + const param_str = "LdLdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_remquo = struct { + const param_str = "dddi*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_remquof = struct { + const param_str = "fffi*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_remquof128 = struct { + const param_str = "LLdLLdLLdi*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_remquol = struct { + const param_str = "LdLdLdi*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_return_address = struct { + const param_str = "v*IUi"; + const attributes = Attributes{}; + }; + + pub const __builtin_rindex = struct { + const param_str = "c*cC*i"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_rint = struct { + const param_str = "dd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_rintf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_rintf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_rintf16 = struct { + const param_str = "hh"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_rintl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_rotateleft16 = struct { + const param_str = "UsUsUs"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_rotateleft32 = struct { + const param_str = "UZiUZiUZi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_rotateleft64 = struct { + const param_str = "UWiUWiUWi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_rotateleft8 = struct { + const param_str = "UcUcUc"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_rotateright16 = struct { + const param_str = "UsUsUs"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_rotateright32 = struct { + const param_str = "UZiUZiUZi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_rotateright64 = struct { + const param_str = "UWiUWiUWi"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_rotateright8 = struct { + const param_str = "UcUcUc"; + const attributes = Attributes{ + .@"const" = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_round = struct { + const param_str = "dd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_roundf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_roundf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_roundf16 = struct { + const param_str = "hh"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_roundl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_sadd_overflow = struct { + const param_str = "bSiCSiCSi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_saddl_overflow = struct { + const param_str = "bSLiCSLiCSLi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_saddll_overflow = struct { + const param_str = "bSLLiCSLLiCSLLi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_scalbln = struct { + const param_str = "ddLi"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_scalblnf = struct { + const param_str = "ffLi"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_scalblnf128 = struct { + const param_str = "LLdLLdLi"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_scalblnl = struct { + const param_str = "LdLdLi"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_scalbn = struct { + const param_str = "ddi"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_scalbnf = struct { + const param_str = "ffi"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_scalbnf128 = struct { + const param_str = "LLdLLdi"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_scalbnl = struct { + const param_str = "LdLdi"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_set_texasr = struct { + const param_str = "vLUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_set_texasru = struct { + const param_str = "vLUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_set_tfhar = struct { + const param_str = "vLUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_set_tfiar = struct { + const param_str = "vLUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_setflm = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_setjmp = struct { + const param_str = "iv**"; + const attributes = Attributes{ + .returns_twice = true, + }; + }; + + pub const __builtin_setps = struct { + const param_str = "vUiUi"; + const target_set = TargetSet.init(.{ + .xcore = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_setrnd = struct { + const param_str = "di"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_shufflevector = struct { + const param_str = "v."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + }; + }; + + pub const __builtin_signbit = struct { + const param_str = "i."; + const attributes = Attributes{ + .@"const" = true, + .custom_typecheck = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_signbitf = struct { + const param_str = "if"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_signbitl = struct { + const param_str = "iLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_sin = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_sinf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_sinf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_sinf16 = struct { + const param_str = "hh"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_sinh = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_sinhf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_sinhf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_sinhl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_sinl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_smul_overflow = struct { + const param_str = "bSiCSiCSi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_smull_overflow = struct { + const param_str = "bSLiCSLiCSLi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_smulll_overflow = struct { + const param_str = "bSLLiCSLLiCSLLi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_snprintf = struct { + const param_str = "ic*zcC*."; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .format_kind = .printf, + .format_string_position = 2, + }; + }; + + pub const __builtin_sponentry = struct { + const param_str = "v*"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_sprintf = struct { + const param_str = "ic*cC*."; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .format_kind = .vprintf, + .format_string_position = 1, + }; + }; + + pub const __builtin_sqrt = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_sqrtf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_sqrtf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_sqrtf128_round_to_odd = struct { + const param_str = "LLdLLd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_sqrtf16 = struct { + const param_str = "hh"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_sqrtl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_ssub_overflow = struct { + const param_str = "bSiCSiCSi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_ssubl_overflow = struct { + const param_str = "bSLiCSLiCSLi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_ssubll_overflow = struct { + const param_str = "bSLLiCSLLiCSLLi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_stdarg_start = struct { + const param_str = "vA."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_stpcpy = struct { + const param_str = "c*c*cC*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_stpncpy = struct { + const param_str = "c*c*cC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_strcasecmp = struct { + const param_str = "icC*cC*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_strcat = struct { + const param_str = "c*c*cC*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_strchr = struct { + const param_str = "c*cC*i"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_strcmp = struct { + const param_str = "icC*cC*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_strcpy = struct { + const param_str = "c*c*cC*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_strcspn = struct { + const param_str = "zcC*cC*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_strdup = struct { + const param_str = "c*cC*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_strlen = struct { + const param_str = "zcC*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_strncasecmp = struct { + const param_str = "icC*cC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_strncat = struct { + const param_str = "c*c*cC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_strncmp = struct { + const param_str = "icC*cC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_strncpy = struct { + const param_str = "c*c*cC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_strndup = struct { + const param_str = "c*cC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_strpbrk = struct { + const param_str = "c*cC*cC*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_strrchr = struct { + const param_str = "c*cC*i"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_strspn = struct { + const param_str = "zcC*cC*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_strstr = struct { + const param_str = "c*cC*cC*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_sub_overflow = struct { + const param_str = "b."; + const attributes = Attributes{ + .custom_typecheck = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_subc = struct { + const param_str = "UiUiCUiCUiCUi*"; + const attributes = Attributes{}; + }; + + pub const __builtin_subcb = struct { + const param_str = "UcUcCUcCUcCUc*"; + const attributes = Attributes{}; + }; + + pub const __builtin_subcl = struct { + const param_str = "ULiULiCULiCULiCULi*"; + const attributes = Attributes{}; + }; + + pub const __builtin_subcll = struct { + const param_str = "ULLiULLiCULLiCULLiCULLi*"; + const attributes = Attributes{}; + }; + + pub const __builtin_subcs = struct { + const param_str = "UsUsCUsCUsCUs*"; + const attributes = Attributes{}; + }; + + pub const __builtin_subf128_round_to_odd = struct { + const param_str = "LLdLLdLLd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_tabort = struct { + const param_str = "UiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_tabortdc = struct { + const param_str = "UiUiUiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_tabortdci = struct { + const param_str = "UiUiUii"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_tabortwc = struct { + const param_str = "UiUiUiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_tabortwci = struct { + const param_str = "UiUiUii"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_tan = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_tanf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_tanf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_tanh = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_tanhf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_tanhf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_tanhl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_tanl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_tbegin = struct { + const param_str = "UiUIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_tcheck = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_tend = struct { + const param_str = "UiUIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_tendall = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_tgamma = struct { + const param_str = "dd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_tgammaf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_tgammaf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_tgammal = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __builtin_thread_pointer = struct { + const param_str = "v*"; + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_trap = struct { + const param_str = "v"; + const attributes = Attributes{ + .noreturn = true, + }; + }; + + pub const __builtin_trechkpt = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_treclaim = struct { + const param_str = "UiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_tresume = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_trunc = struct { + const param_str = "dd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_truncf = struct { + const param_str = "ff"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_truncf128 = struct { + const param_str = "LLdLLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_truncf128_round_to_odd = struct { + const param_str = "dLLd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_truncf16 = struct { + const param_str = "hh"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_truncl = struct { + const param_str = "LdLd"; + const attributes = Attributes{ + .@"const" = true, + .lib_function_with_builtin_prefix = true, + }; + }; + + pub const __builtin_tsr = struct { + const param_str = "UiUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_tsuspend = struct { + const param_str = "Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_ttest = struct { + const param_str = "LUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_uadd_overflow = struct { + const param_str = "bUiCUiCUi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_uaddl_overflow = struct { + const param_str = "bULiCULiCULi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_uaddll_overflow = struct { + const param_str = "bULLiCULLiCULLi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_umul_overflow = struct { + const param_str = "bUiCUiCUi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_umull_overflow = struct { + const param_str = "bULiCULiCULi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_umulll_overflow = struct { + const param_str = "bULLiCULLiCULLi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_unpack_longdouble = struct { + const param_str = "dLdIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_unpack_vector_int128 = struct { + const param_str = "ULLiV1LLLii"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_unpredictable = struct { + const param_str = "LiLi"; + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_unreachable = struct { + const param_str = "v"; + const attributes = Attributes{ + .noreturn = true, + }; + }; + + pub const __builtin_unwind_init = struct { + const param_str = "v"; + }; + + pub const __builtin_usub_overflow = struct { + const param_str = "bUiCUiCUi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_usubl_overflow = struct { + const param_str = "bULiCULiCULi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_usubll_overflow = struct { + const param_str = "bULLiCULLiCULLi*"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __builtin_va_copy = struct { + const param_str = "vAA"; + const attributes = Attributes{}; + }; + + pub const __builtin_va_end = struct { + const param_str = "vA"; + const attributes = Attributes{}; + }; + + pub const __builtin_va_start = struct { + const param_str = "vA."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_ve_vl_andm_MMM = struct { + const param_str = "V512bV512bV512b"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_andm_mmm = struct { + const param_str = "V256bV256bV256b"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_eqvm_MMM = struct { + const param_str = "V512bV512bV512b"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_eqvm_mmm = struct { + const param_str = "V256bV256bV256b"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_extract_vm512l = struct { + const param_str = "V256bV512b"; + const target_set = TargetSet.init(.{ + .ve = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_extract_vm512u = struct { + const param_str = "V256bV512b"; + const target_set = TargetSet.init(.{ + .ve = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_fencec_s = struct { + const param_str = "vUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_fencei = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_fencem_s = struct { + const param_str = "vUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_fidcr_sss = struct { + const param_str = "LUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_insert_vm512l = struct { + const param_str = "V512bV512bV256b"; + const target_set = TargetSet.init(.{ + .ve = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_insert_vm512u = struct { + const param_str = "V512bV512bV256b"; + const target_set = TargetSet.init(.{ + .ve = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_lcr_sss = struct { + const param_str = "LUiLUiLUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_lsv_vvss = struct { + const param_str = "V256dV256dUiLUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_lvm_MMss = struct { + const param_str = "V512bV512bLUiLUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_lvm_mmss = struct { + const param_str = "V256bV256bLUiLUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_lvsd_svs = struct { + const param_str = "dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_lvsl_svs = struct { + const param_str = "LUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_lvss_svs = struct { + const param_str = "fV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_lzvm_sml = struct { + const param_str = "LUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_negm_MM = struct { + const param_str = "V512bV512b"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_negm_mm = struct { + const param_str = "V256bV256b"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_nndm_MMM = struct { + const param_str = "V512bV512bV512b"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_nndm_mmm = struct { + const param_str = "V256bV256bV256b"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_orm_MMM = struct { + const param_str = "V512bV512bV512b"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_orm_mmm = struct { + const param_str = "V256bV256bV256b"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pack_f32a = struct { + const param_str = "ULifC*"; + const target_set = TargetSet.init(.{ + .ve = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pack_f32p = struct { + const param_str = "ULifC*fC*"; + const target_set = TargetSet.init(.{ + .ve = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pcvm_sml = struct { + const param_str = "LUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pfchv_ssl = struct { + const param_str = "vLivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pfchvnc_ssl = struct { + const param_str = "vLivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvadds_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvadds_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvadds_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvadds_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvadds_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvadds_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvaddu_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvaddu_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvaddu_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvaddu_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvaddu_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvaddu_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvand_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvand_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvand_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvand_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvand_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvand_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvbrd_vsMvl = struct { + const param_str = "V256dLUiV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvbrd_vsl = struct { + const param_str = "V256dLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvbrd_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvbrv_vvMvl = struct { + const param_str = "V256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvbrv_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvbrv_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvbrvlo_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvbrvlo_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvbrvlo_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvbrvup_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvbrvup_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvbrvup_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcmps_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcmps_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcmps_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcmps_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcmps_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcmps_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcmpu_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcmpu_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcmpu_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcmpu_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcmpu_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcmpu_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcvtsw_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcvtsw_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcvtws_vvMvl = struct { + const param_str = "V256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcvtws_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcvtws_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcvtwsrz_vvMvl = struct { + const param_str = "V256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcvtwsrz_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvcvtwsrz_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pveqv_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pveqv_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pveqv_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pveqv_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pveqv_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pveqv_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfadd_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfadd_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfadd_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfadd_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfadd_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfadd_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfcmp_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfcmp_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfcmp_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfcmp_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfcmp_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfcmp_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmad_vsvvMvl = struct { + const param_str = "V256dLUiV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmad_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmad_vsvvvl = struct { + const param_str = "V256dLUiV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmad_vvsvMvl = struct { + const param_str = "V256dV256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmad_vvsvl = struct { + const param_str = "V256dV256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmad_vvsvvl = struct { + const param_str = "V256dV256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmad_vvvvMvl = struct { + const param_str = "V256dV256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmad_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmad_vvvvvl = struct { + const param_str = "V256dV256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmax_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmax_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmax_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmax_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmax_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmax_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmin_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmin_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmin_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmin_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmin_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmin_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkaf_Ml = struct { + const param_str = "V512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkat_Ml = struct { + const param_str = "V512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkseq_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkseq_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkseqnan_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkseqnan_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksge_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksge_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksgenan_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksgenan_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksgt_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksgt_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksgtnan_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksgtnan_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksle_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksle_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslenan_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslenan_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksloeq_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksloeq_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksloeqnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksloeqnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksloge_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksloge_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslogenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslogenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslogt_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslogt_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslogtnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslogtnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslole_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslole_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslolenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslolenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslolt_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslolt_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksloltnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksloltnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslonan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslonan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslone_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslone_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslonenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslonenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslonum_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslonum_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslt_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkslt_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksltnan_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksltnan_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksnan_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksnan_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksne_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksne_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksnenan_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksnenan_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksnum_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksnum_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupeq_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupeq_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupeqnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupeqnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupge_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupge_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupgenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupgenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupgt_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupgt_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupgtnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupgtnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksuple_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksuple_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksuplenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksuplenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksuplt_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksuplt_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupltnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupltnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupne_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupne_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupnenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupnenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupnum_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmksupnum_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkweq_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkweq_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkweqnan_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkweqnan_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwge_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwge_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwgenan_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwgenan_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwgt_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwgt_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwgtnan_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwgtnan_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwle_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwle_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlenan_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlenan_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwloeq_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwloeq_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwloeqnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwloeqnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwloge_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwloge_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlogenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlogenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlogt_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlogt_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlogtnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlogtnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlole_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlole_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlolenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlolenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlolt_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlolt_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwloltnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwloltnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlonan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlonan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlone_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlone_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlonenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlonenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlonum_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlonum_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlt_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwlt_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwltnan_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwltnan_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwnan_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwnan_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwne_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwne_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwnenan_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwnenan_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwnum_MvMl = struct { + const param_str = "V512bV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwnum_Mvl = struct { + const param_str = "V512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupeq_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupeq_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupeqnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupeqnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupge_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupge_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupgenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupgenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupgt_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupgt_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupgtnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupgtnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwuple_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwuple_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwuplenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwuplenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwuplt_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwuplt_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupltnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupltnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupne_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupne_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupnenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupnenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupnum_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmkwupnum_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmsb_vsvvMvl = struct { + const param_str = "V256dLUiV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmsb_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmsb_vsvvvl = struct { + const param_str = "V256dLUiV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmsb_vvsvMvl = struct { + const param_str = "V256dV256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmsb_vvsvl = struct { + const param_str = "V256dV256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmsb_vvsvvl = struct { + const param_str = "V256dV256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmsb_vvvvMvl = struct { + const param_str = "V256dV256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmsb_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmsb_vvvvvl = struct { + const param_str = "V256dV256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmul_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmul_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmul_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmul_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmul_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfmul_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmad_vsvvMvl = struct { + const param_str = "V256dLUiV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmad_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmad_vsvvvl = struct { + const param_str = "V256dLUiV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmad_vvsvMvl = struct { + const param_str = "V256dV256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmad_vvsvl = struct { + const param_str = "V256dV256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmad_vvsvvl = struct { + const param_str = "V256dV256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmad_vvvvMvl = struct { + const param_str = "V256dV256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmad_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmad_vvvvvl = struct { + const param_str = "V256dV256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmsb_vsvvMvl = struct { + const param_str = "V256dLUiV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmsb_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmsb_vsvvvl = struct { + const param_str = "V256dLUiV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmsb_vvsvMvl = struct { + const param_str = "V256dV256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmsb_vvsvl = struct { + const param_str = "V256dV256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmsb_vvsvvl = struct { + const param_str = "V256dV256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmsb_vvvvMvl = struct { + const param_str = "V256dV256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmsb_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfnmsb_vvvvvl = struct { + const param_str = "V256dV256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfsub_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfsub_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfsub_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfsub_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfsub_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvfsub_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvldz_vvMvl = struct { + const param_str = "V256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvldz_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvldz_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvldzlo_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvldzlo_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvldzlo_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvldzup_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvldzup_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvldzup_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvmaxs_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvmaxs_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvmaxs_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvmaxs_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvmaxs_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvmaxs_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvmins_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvmins_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvmins_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvmins_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvmins_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvmins_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvor_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvor_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvor_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvor_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvor_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvor_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvpcnt_vvMvl = struct { + const param_str = "V256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvpcnt_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvpcnt_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvpcntlo_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvpcntlo_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvpcntlo_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvpcntup_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvpcntup_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvpcntup_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvrcp_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvrcp_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvrsqrt_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvrsqrt_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvrsqrtnex_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvrsqrtnex_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvseq_vl = struct { + const param_str = "V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvseq_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvseqlo_vl = struct { + const param_str = "V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvseqlo_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsequp_vl = struct { + const param_str = "V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsequp_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsla_vvsMvl = struct { + const param_str = "V256dV256dLUiV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsla_vvsl = struct { + const param_str = "V256dV256dLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsla_vvsvl = struct { + const param_str = "V256dV256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsla_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsla_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsla_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsll_vvsMvl = struct { + const param_str = "V256dV256dLUiV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsll_vvsl = struct { + const param_str = "V256dV256dLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsll_vvsvl = struct { + const param_str = "V256dV256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsll_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsll_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsll_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsra_vvsMvl = struct { + const param_str = "V256dV256dLUiV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsra_vvsl = struct { + const param_str = "V256dV256dLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsra_vvsvl = struct { + const param_str = "V256dV256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsra_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsra_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsra_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsrl_vvsMvl = struct { + const param_str = "V256dV256dLUiV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsrl_vvsl = struct { + const param_str = "V256dV256dLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsrl_vvsvl = struct { + const param_str = "V256dV256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsrl_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsrl_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsrl_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsubs_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsubs_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsubs_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsubs_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsubs_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsubs_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsubu_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsubu_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsubu_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsubu_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsubu_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvsubu_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvxor_vsvMvl = struct { + const param_str = "V256dLUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvxor_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvxor_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvxor_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvxor_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_pvxor_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_scr_sss = struct { + const param_str = "vLUiLUiLUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_svm_sMs = struct { + const param_str = "LUiV512bLUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_svm_sms = struct { + const param_str = "LUiV256bLUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_svob = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_tovm_sml = struct { + const param_str = "LUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_tscr_ssss = struct { + const param_str = "LUiLUiLUiLUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddsl_vsvl = struct { + const param_str = "V256dLiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddsl_vsvmvl = struct { + const param_str = "V256dLiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddsl_vsvvl = struct { + const param_str = "V256dLiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddsl_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddsl_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddsl_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddswsx_vsvl = struct { + const param_str = "V256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddswsx_vsvmvl = struct { + const param_str = "V256diV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddswsx_vsvvl = struct { + const param_str = "V256diV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddswsx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddswsx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddswsx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddswzx_vsvl = struct { + const param_str = "V256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddswzx_vsvmvl = struct { + const param_str = "V256diV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddswzx_vsvvl = struct { + const param_str = "V256diV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddswzx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddswzx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddswzx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddul_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddul_vsvmvl = struct { + const param_str = "V256dLUiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddul_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddul_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddul_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vaddul_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vadduw_vsvl = struct { + const param_str = "V256dUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vadduw_vsvmvl = struct { + const param_str = "V256dUiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vadduw_vsvvl = struct { + const param_str = "V256dUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vadduw_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vadduw_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vadduw_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vand_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vand_vsvmvl = struct { + const param_str = "V256dLUiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vand_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vand_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vand_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vand_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vbrdd_vsl = struct { + const param_str = "V256ddUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vbrdd_vsmvl = struct { + const param_str = "V256ddV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vbrdd_vsvl = struct { + const param_str = "V256ddV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vbrdl_vsl = struct { + const param_str = "V256dLiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vbrdl_vsmvl = struct { + const param_str = "V256dLiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vbrdl_vsvl = struct { + const param_str = "V256dLiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vbrds_vsl = struct { + const param_str = "V256dfUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vbrds_vsmvl = struct { + const param_str = "V256dfV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vbrds_vsvl = struct { + const param_str = "V256dfV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vbrdw_vsl = struct { + const param_str = "V256diUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vbrdw_vsmvl = struct { + const param_str = "V256diV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vbrdw_vsvl = struct { + const param_str = "V256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vbrv_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vbrv_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vbrv_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpsl_vsvl = struct { + const param_str = "V256dLiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpsl_vsvmvl = struct { + const param_str = "V256dLiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpsl_vsvvl = struct { + const param_str = "V256dLiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpsl_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpsl_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpsl_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpswsx_vsvl = struct { + const param_str = "V256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpswsx_vsvmvl = struct { + const param_str = "V256diV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpswsx_vsvvl = struct { + const param_str = "V256diV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpswsx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpswsx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpswsx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpswzx_vsvl = struct { + const param_str = "V256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpswzx_vsvmvl = struct { + const param_str = "V256diV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpswzx_vsvvl = struct { + const param_str = "V256diV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpswzx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpswzx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpswzx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpul_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpul_vsvmvl = struct { + const param_str = "V256dLUiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpul_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpul_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpul_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpul_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpuw_vsvl = struct { + const param_str = "V256dUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpuw_vsvmvl = struct { + const param_str = "V256dUiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpuw_vsvvl = struct { + const param_str = "V256dUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpuw_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpuw_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcmpuw_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcp_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtdl_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtdl_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtds_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtds_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtdw_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtdw_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtld_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtld_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtld_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtldrz_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtldrz_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtldrz_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtsd_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtsd_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtsw_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtsw_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwdsx_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwdsx_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwdsx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwdsxrz_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwdsxrz_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwdsxrz_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwdzx_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwdzx_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwdzx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwdzxrz_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwdzxrz_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwdzxrz_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwssx_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwssx_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwssx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwssxrz_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwssxrz_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwssxrz_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwszx_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwszx_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwszx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwszxrz_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwszxrz_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vcvtwszxrz_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivsl_vsvl = struct { + const param_str = "V256dLiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivsl_vsvmvl = struct { + const param_str = "V256dLiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivsl_vsvvl = struct { + const param_str = "V256dLiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivsl_vvsl = struct { + const param_str = "V256dV256dLiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivsl_vvsmvl = struct { + const param_str = "V256dV256dLiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivsl_vvsvl = struct { + const param_str = "V256dV256dLiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivsl_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivsl_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivsl_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswsx_vsvl = struct { + const param_str = "V256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswsx_vsvmvl = struct { + const param_str = "V256diV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswsx_vsvvl = struct { + const param_str = "V256diV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswsx_vvsl = struct { + const param_str = "V256dV256diUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswsx_vvsmvl = struct { + const param_str = "V256dV256diV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswsx_vvsvl = struct { + const param_str = "V256dV256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswsx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswsx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswsx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswzx_vsvl = struct { + const param_str = "V256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswzx_vsvmvl = struct { + const param_str = "V256diV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswzx_vsvvl = struct { + const param_str = "V256diV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswzx_vvsl = struct { + const param_str = "V256dV256diUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswzx_vvsmvl = struct { + const param_str = "V256dV256diV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswzx_vvsvl = struct { + const param_str = "V256dV256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswzx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswzx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivswzx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivul_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivul_vsvmvl = struct { + const param_str = "V256dLUiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivul_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivul_vvsl = struct { + const param_str = "V256dV256dLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivul_vvsmvl = struct { + const param_str = "V256dV256dLUiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivul_vvsvl = struct { + const param_str = "V256dV256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivul_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivul_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivul_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivuw_vsvl = struct { + const param_str = "V256dUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivuw_vsvmvl = struct { + const param_str = "V256dUiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivuw_vsvvl = struct { + const param_str = "V256dUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivuw_vvsl = struct { + const param_str = "V256dV256dUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivuw_vvsmvl = struct { + const param_str = "V256dV256dUiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivuw_vvsvl = struct { + const param_str = "V256dV256dUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivuw_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivuw_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vdivuw_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_veqv_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_veqv_vsvmvl = struct { + const param_str = "V256dLUiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_veqv_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_veqv_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_veqv_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_veqv_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vex_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfaddd_vsvl = struct { + const param_str = "V256ddV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfaddd_vsvmvl = struct { + const param_str = "V256ddV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfaddd_vsvvl = struct { + const param_str = "V256ddV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfaddd_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfaddd_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfaddd_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfadds_vsvl = struct { + const param_str = "V256dfV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfadds_vsvmvl = struct { + const param_str = "V256dfV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfadds_vsvvl = struct { + const param_str = "V256dfV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfadds_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfadds_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfadds_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfcmpd_vsvl = struct { + const param_str = "V256ddV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfcmpd_vsvmvl = struct { + const param_str = "V256ddV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfcmpd_vsvvl = struct { + const param_str = "V256ddV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfcmpd_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfcmpd_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfcmpd_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfcmps_vsvl = struct { + const param_str = "V256dfV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfcmps_vsvmvl = struct { + const param_str = "V256dfV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfcmps_vsvvl = struct { + const param_str = "V256dfV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfcmps_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfcmps_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfcmps_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfdivd_vsvl = struct { + const param_str = "V256ddV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfdivd_vsvmvl = struct { + const param_str = "V256ddV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfdivd_vsvvl = struct { + const param_str = "V256ddV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfdivd_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfdivd_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfdivd_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfdivs_vsvl = struct { + const param_str = "V256dfV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfdivs_vsvmvl = struct { + const param_str = "V256dfV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfdivs_vsvvl = struct { + const param_str = "V256dfV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfdivs_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfdivs_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfdivs_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmadd_vsvvl = struct { + const param_str = "V256ddV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmadd_vsvvmvl = struct { + const param_str = "V256ddV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmadd_vsvvvl = struct { + const param_str = "V256ddV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmadd_vvsvl = struct { + const param_str = "V256dV256ddV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmadd_vvsvmvl = struct { + const param_str = "V256dV256ddV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmadd_vvsvvl = struct { + const param_str = "V256dV256ddV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmadd_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmadd_vvvvmvl = struct { + const param_str = "V256dV256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmadd_vvvvvl = struct { + const param_str = "V256dV256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmads_vsvvl = struct { + const param_str = "V256dfV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmads_vsvvmvl = struct { + const param_str = "V256dfV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmads_vsvvvl = struct { + const param_str = "V256dfV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmads_vvsvl = struct { + const param_str = "V256dV256dfV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmads_vvsvmvl = struct { + const param_str = "V256dV256dfV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmads_vvsvvl = struct { + const param_str = "V256dV256dfV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmads_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmads_vvvvmvl = struct { + const param_str = "V256dV256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmads_vvvvvl = struct { + const param_str = "V256dV256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmaxd_vsvl = struct { + const param_str = "V256ddV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmaxd_vsvmvl = struct { + const param_str = "V256ddV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmaxd_vsvvl = struct { + const param_str = "V256ddV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmaxd_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmaxd_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmaxd_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmaxs_vsvl = struct { + const param_str = "V256dfV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmaxs_vsvmvl = struct { + const param_str = "V256dfV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmaxs_vsvvl = struct { + const param_str = "V256dfV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmaxs_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmaxs_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmaxs_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmind_vsvl = struct { + const param_str = "V256ddV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmind_vsvmvl = struct { + const param_str = "V256ddV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmind_vsvvl = struct { + const param_str = "V256ddV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmind_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmind_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmind_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmins_vsvl = struct { + const param_str = "V256dfV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmins_vsvmvl = struct { + const param_str = "V256dfV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmins_vsvvl = struct { + const param_str = "V256dfV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmins_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmins_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmins_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdeq_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdeq_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdeqnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdeqnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdge_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdge_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdgenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdgenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdgt_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdgt_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdgtnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdgtnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdle_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdle_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdlenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdlenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdlt_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdlt_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdltnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdltnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdne_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdne_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdnenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdnenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdnum_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkdnum_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklaf_ml = struct { + const param_str = "V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklat_ml = struct { + const param_str = "V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkleq_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkleq_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkleqnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkleqnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklge_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklge_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklgenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklgenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklgt_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklgt_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklgtnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklgtnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklle_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklle_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkllenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkllenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkllt_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkllt_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklltnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklltnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklne_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklne_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklnenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklnenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklnum_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmklnum_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkseq_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkseq_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkseqnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkseqnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksge_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksge_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksgenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksgenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksgt_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksgt_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksgtnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksgtnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksle_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksle_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkslenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkslenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkslt_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkslt_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksltnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksltnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksne_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksne_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksnenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksnenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksnum_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmksnum_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkweq_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkweq_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkweqnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkweqnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwge_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwge_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwgenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwgenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwgt_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwgt_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwgtnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwgtnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwle_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwle_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwlenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwlenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwlt_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwlt_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwltnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwltnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwnan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwnan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwne_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwne_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwnenan_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwnenan_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwnum_mvl = struct { + const param_str = "V256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmkwnum_mvml = struct { + const param_str = "V256bV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbd_vsvvl = struct { + const param_str = "V256ddV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbd_vsvvmvl = struct { + const param_str = "V256ddV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbd_vsvvvl = struct { + const param_str = "V256ddV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbd_vvsvl = struct { + const param_str = "V256dV256ddV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbd_vvsvmvl = struct { + const param_str = "V256dV256ddV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbd_vvsvvl = struct { + const param_str = "V256dV256ddV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbd_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbd_vvvvmvl = struct { + const param_str = "V256dV256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbd_vvvvvl = struct { + const param_str = "V256dV256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbs_vsvvl = struct { + const param_str = "V256dfV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbs_vsvvmvl = struct { + const param_str = "V256dfV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbs_vsvvvl = struct { + const param_str = "V256dfV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbs_vvsvl = struct { + const param_str = "V256dV256dfV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbs_vvsvmvl = struct { + const param_str = "V256dV256dfV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbs_vvsvvl = struct { + const param_str = "V256dV256dfV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbs_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbs_vvvvmvl = struct { + const param_str = "V256dV256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmsbs_vvvvvl = struct { + const param_str = "V256dV256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmuld_vsvl = struct { + const param_str = "V256ddV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmuld_vsvmvl = struct { + const param_str = "V256ddV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmuld_vsvvl = struct { + const param_str = "V256ddV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmuld_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmuld_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmuld_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmuls_vsvl = struct { + const param_str = "V256dfV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmuls_vsvmvl = struct { + const param_str = "V256dfV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmuls_vsvvl = struct { + const param_str = "V256dfV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmuls_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmuls_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfmuls_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmadd_vsvvl = struct { + const param_str = "V256ddV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmadd_vsvvmvl = struct { + const param_str = "V256ddV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmadd_vsvvvl = struct { + const param_str = "V256ddV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmadd_vvsvl = struct { + const param_str = "V256dV256ddV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmadd_vvsvmvl = struct { + const param_str = "V256dV256ddV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmadd_vvsvvl = struct { + const param_str = "V256dV256ddV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmadd_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmadd_vvvvmvl = struct { + const param_str = "V256dV256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmadd_vvvvvl = struct { + const param_str = "V256dV256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmads_vsvvl = struct { + const param_str = "V256dfV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmads_vsvvmvl = struct { + const param_str = "V256dfV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmads_vsvvvl = struct { + const param_str = "V256dfV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmads_vvsvl = struct { + const param_str = "V256dV256dfV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmads_vvsvmvl = struct { + const param_str = "V256dV256dfV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmads_vvsvvl = struct { + const param_str = "V256dV256dfV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmads_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmads_vvvvmvl = struct { + const param_str = "V256dV256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmads_vvvvvl = struct { + const param_str = "V256dV256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbd_vsvvl = struct { + const param_str = "V256ddV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbd_vsvvmvl = struct { + const param_str = "V256ddV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbd_vsvvvl = struct { + const param_str = "V256ddV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbd_vvsvl = struct { + const param_str = "V256dV256ddV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbd_vvsvmvl = struct { + const param_str = "V256dV256ddV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbd_vvsvvl = struct { + const param_str = "V256dV256ddV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbd_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbd_vvvvmvl = struct { + const param_str = "V256dV256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbd_vvvvvl = struct { + const param_str = "V256dV256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbs_vsvvl = struct { + const param_str = "V256dfV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbs_vsvvmvl = struct { + const param_str = "V256dfV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbs_vsvvvl = struct { + const param_str = "V256dfV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbs_vvsvl = struct { + const param_str = "V256dV256dfV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbs_vvsvmvl = struct { + const param_str = "V256dV256dfV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbs_vvsvvl = struct { + const param_str = "V256dV256dfV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbs_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbs_vvvvmvl = struct { + const param_str = "V256dV256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfnmsbs_vvvvvl = struct { + const param_str = "V256dV256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfrmaxdfst_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfrmaxdfst_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfrmaxdlst_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfrmaxdlst_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfrmaxsfst_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfrmaxsfst_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfrmaxslst_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfrmaxslst_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfrmindfst_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfrmindfst_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfrmindlst_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfrmindlst_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfrminsfst_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfrminsfst_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfrminslst_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfrminslst_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsqrtd_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsqrtd_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsqrts_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsqrts_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsubd_vsvl = struct { + const param_str = "V256ddV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsubd_vsvmvl = struct { + const param_str = "V256ddV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsubd_vsvvl = struct { + const param_str = "V256ddV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsubd_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsubd_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsubd_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsubs_vsvl = struct { + const param_str = "V256dfV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsubs_vsvmvl = struct { + const param_str = "V256dfV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsubs_vsvvl = struct { + const param_str = "V256dfV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsubs_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsubs_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsubs_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsumd_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsumd_vvml = struct { + const param_str = "V256dV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsums_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vfsums_vvml = struct { + const param_str = "V256dV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgt_vvssl = struct { + const param_str = "V256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgt_vvssml = struct { + const param_str = "V256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgt_vvssmvl = struct { + const param_str = "V256dV256dLUiLUiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgt_vvssvl = struct { + const param_str = "V256dV256dLUiLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtlsx_vvssl = struct { + const param_str = "V256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtlsx_vvssml = struct { + const param_str = "V256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtlsx_vvssmvl = struct { + const param_str = "V256dV256dLUiLUiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtlsx_vvssvl = struct { + const param_str = "V256dV256dLUiLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtlsxnc_vvssl = struct { + const param_str = "V256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtlsxnc_vvssml = struct { + const param_str = "V256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtlsxnc_vvssmvl = struct { + const param_str = "V256dV256dLUiLUiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtlsxnc_vvssvl = struct { + const param_str = "V256dV256dLUiLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtlzx_vvssl = struct { + const param_str = "V256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtlzx_vvssml = struct { + const param_str = "V256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtlzx_vvssmvl = struct { + const param_str = "V256dV256dLUiLUiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtlzx_vvssvl = struct { + const param_str = "V256dV256dLUiLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtlzxnc_vvssl = struct { + const param_str = "V256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtlzxnc_vvssml = struct { + const param_str = "V256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtlzxnc_vvssmvl = struct { + const param_str = "V256dV256dLUiLUiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtlzxnc_vvssvl = struct { + const param_str = "V256dV256dLUiLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtnc_vvssl = struct { + const param_str = "V256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtnc_vvssml = struct { + const param_str = "V256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtnc_vvssmvl = struct { + const param_str = "V256dV256dLUiLUiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtnc_vvssvl = struct { + const param_str = "V256dV256dLUiLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtu_vvssl = struct { + const param_str = "V256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtu_vvssml = struct { + const param_str = "V256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtu_vvssmvl = struct { + const param_str = "V256dV256dLUiLUiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtu_vvssvl = struct { + const param_str = "V256dV256dLUiLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtunc_vvssl = struct { + const param_str = "V256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtunc_vvssml = struct { + const param_str = "V256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtunc_vvssmvl = struct { + const param_str = "V256dV256dLUiLUiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vgtunc_vvssvl = struct { + const param_str = "V256dV256dLUiLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vld2d_vssl = struct { + const param_str = "V256dLUivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vld2d_vssvl = struct { + const param_str = "V256dLUivC*V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vld2dnc_vssl = struct { + const param_str = "V256dLUivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vld2dnc_vssvl = struct { + const param_str = "V256dLUivC*V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vld_vssl = struct { + const param_str = "V256dLUivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vld_vssvl = struct { + const param_str = "V256dLUivC*V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldl2dsx_vssl = struct { + const param_str = "V256dLUivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldl2dsx_vssvl = struct { + const param_str = "V256dLUivC*V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldl2dsxnc_vssl = struct { + const param_str = "V256dLUivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldl2dsxnc_vssvl = struct { + const param_str = "V256dLUivC*V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldl2dzx_vssl = struct { + const param_str = "V256dLUivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldl2dzx_vssvl = struct { + const param_str = "V256dLUivC*V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldl2dzxnc_vssl = struct { + const param_str = "V256dLUivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldl2dzxnc_vssvl = struct { + const param_str = "V256dLUivC*V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldlsx_vssl = struct { + const param_str = "V256dLUivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldlsx_vssvl = struct { + const param_str = "V256dLUivC*V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldlsxnc_vssl = struct { + const param_str = "V256dLUivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldlsxnc_vssvl = struct { + const param_str = "V256dLUivC*V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldlzx_vssl = struct { + const param_str = "V256dLUivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldlzx_vssvl = struct { + const param_str = "V256dLUivC*V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldlzxnc_vssl = struct { + const param_str = "V256dLUivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldlzxnc_vssvl = struct { + const param_str = "V256dLUivC*V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldnc_vssl = struct { + const param_str = "V256dLUivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldnc_vssvl = struct { + const param_str = "V256dLUivC*V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldu2d_vssl = struct { + const param_str = "V256dLUivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldu2d_vssvl = struct { + const param_str = "V256dLUivC*V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldu2dnc_vssl = struct { + const param_str = "V256dLUivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldu2dnc_vssvl = struct { + const param_str = "V256dLUivC*V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldu_vssl = struct { + const param_str = "V256dLUivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldu_vssvl = struct { + const param_str = "V256dLUivC*V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldunc_vssl = struct { + const param_str = "V256dLUivC*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldunc_vssvl = struct { + const param_str = "V256dLUivC*V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldz_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldz_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vldz_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxsl_vsvl = struct { + const param_str = "V256dLiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxsl_vsvmvl = struct { + const param_str = "V256dLiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxsl_vsvvl = struct { + const param_str = "V256dLiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxsl_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxsl_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxsl_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxswsx_vsvl = struct { + const param_str = "V256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxswsx_vsvmvl = struct { + const param_str = "V256diV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxswsx_vsvvl = struct { + const param_str = "V256diV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxswsx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxswsx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxswsx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxswzx_vsvl = struct { + const param_str = "V256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxswzx_vsvmvl = struct { + const param_str = "V256diV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxswzx_vsvvl = struct { + const param_str = "V256diV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxswzx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxswzx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmaxswzx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminsl_vsvl = struct { + const param_str = "V256dLiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminsl_vsvmvl = struct { + const param_str = "V256dLiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminsl_vsvvl = struct { + const param_str = "V256dLiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminsl_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminsl_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminsl_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminswsx_vsvl = struct { + const param_str = "V256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminswsx_vsvmvl = struct { + const param_str = "V256diV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminswsx_vsvvl = struct { + const param_str = "V256diV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminswsx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminswsx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminswsx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminswzx_vsvl = struct { + const param_str = "V256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminswzx_vsvmvl = struct { + const param_str = "V256diV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminswzx_vsvvl = struct { + const param_str = "V256diV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminswzx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminswzx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vminswzx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmrg_vsvml = struct { + const param_str = "V256dLUiV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmrg_vsvmvl = struct { + const param_str = "V256dLUiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmrg_vvvml = struct { + const param_str = "V256dV256dV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmrg_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmrgw_vsvMl = struct { + const param_str = "V256dUiV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmrgw_vsvMvl = struct { + const param_str = "V256dUiV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmrgw_vvvMl = struct { + const param_str = "V256dV256dV256dV512bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmrgw_vvvMvl = struct { + const param_str = "V256dV256dV256dV512bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulsl_vsvl = struct { + const param_str = "V256dLiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulsl_vsvmvl = struct { + const param_str = "V256dLiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulsl_vsvvl = struct { + const param_str = "V256dLiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulsl_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulsl_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulsl_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulslw_vsvl = struct { + const param_str = "V256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulslw_vsvvl = struct { + const param_str = "V256diV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulslw_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulslw_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulswsx_vsvl = struct { + const param_str = "V256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulswsx_vsvmvl = struct { + const param_str = "V256diV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulswsx_vsvvl = struct { + const param_str = "V256diV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulswsx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulswsx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulswsx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulswzx_vsvl = struct { + const param_str = "V256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulswzx_vsvmvl = struct { + const param_str = "V256diV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulswzx_vsvvl = struct { + const param_str = "V256diV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulswzx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulswzx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulswzx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulul_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulul_vsvmvl = struct { + const param_str = "V256dLUiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulul_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulul_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulul_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmulul_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmuluw_vsvl = struct { + const param_str = "V256dUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmuluw_vsvmvl = struct { + const param_str = "V256dUiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmuluw_vsvvl = struct { + const param_str = "V256dUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmuluw_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmuluw_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmuluw_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmv_vsvl = struct { + const param_str = "V256dUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmv_vsvmvl = struct { + const param_str = "V256dUiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vmv_vsvvl = struct { + const param_str = "V256dUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vor_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vor_vsvmvl = struct { + const param_str = "V256dLUiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vor_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vor_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vor_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vor_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vpcnt_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vpcnt_vvmvl = struct { + const param_str = "V256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vpcnt_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrand_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrand_vvml = struct { + const param_str = "V256dV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrcpd_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrcpd_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrcps_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrcps_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrmaxslfst_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrmaxslfst_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrmaxsllst_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrmaxsllst_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrmaxswfstsx_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrmaxswfstsx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrmaxswfstzx_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrmaxswfstzx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrmaxswlstsx_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrmaxswlstsx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrmaxswlstzx_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrmaxswlstzx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrminslfst_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrminslfst_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrminsllst_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrminsllst_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrminswfstsx_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrminswfstsx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrminswfstzx_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrminswfstzx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrminswlstsx_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrminswlstsx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrminswlstzx_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrminswlstzx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vror_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vror_vvml = struct { + const param_str = "V256dV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrsqrtd_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrsqrtd_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrsqrtdnex_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrsqrtdnex_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrsqrts_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrsqrts_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrsqrtsnex_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrsqrtsnex_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrxor_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vrxor_vvml = struct { + const param_str = "V256dV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsc_vvssl = struct { + const param_str = "vV256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsc_vvssml = struct { + const param_str = "vV256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vscl_vvssl = struct { + const param_str = "vV256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vscl_vvssml = struct { + const param_str = "vV256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsclnc_vvssl = struct { + const param_str = "vV256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsclnc_vvssml = struct { + const param_str = "vV256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsclncot_vvssl = struct { + const param_str = "vV256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsclncot_vvssml = struct { + const param_str = "vV256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsclot_vvssl = struct { + const param_str = "vV256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsclot_vvssml = struct { + const param_str = "vV256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vscnc_vvssl = struct { + const param_str = "vV256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vscnc_vvssml = struct { + const param_str = "vV256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vscncot_vvssl = struct { + const param_str = "vV256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vscncot_vvssml = struct { + const param_str = "vV256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vscot_vvssl = struct { + const param_str = "vV256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vscot_vvssml = struct { + const param_str = "vV256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vscu_vvssl = struct { + const param_str = "vV256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vscu_vvssml = struct { + const param_str = "vV256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vscunc_vvssl = struct { + const param_str = "vV256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vscunc_vvssml = struct { + const param_str = "vV256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vscuncot_vvssl = struct { + const param_str = "vV256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vscuncot_vvssml = struct { + const param_str = "vV256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vscuot_vvssl = struct { + const param_str = "vV256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vscuot_vvssml = struct { + const param_str = "vV256dV256dLUiLUiV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vseq_vl = struct { + const param_str = "V256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vseq_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsfa_vvssl = struct { + const param_str = "V256dV256dLUiLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsfa_vvssmvl = struct { + const param_str = "V256dV256dLUiLUiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsfa_vvssvl = struct { + const param_str = "V256dV256dLUiLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vshf_vvvsl = struct { + const param_str = "V256dV256dV256dLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vshf_vvvsvl = struct { + const param_str = "V256dV256dV256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslal_vvsl = struct { + const param_str = "V256dV256dLiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslal_vvsmvl = struct { + const param_str = "V256dV256dLiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslal_vvsvl = struct { + const param_str = "V256dV256dLiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslal_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslal_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslal_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslawsx_vvsl = struct { + const param_str = "V256dV256diUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslawsx_vvsmvl = struct { + const param_str = "V256dV256diV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslawsx_vvsvl = struct { + const param_str = "V256dV256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslawsx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslawsx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslawsx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslawzx_vvsl = struct { + const param_str = "V256dV256diUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslawzx_vvsmvl = struct { + const param_str = "V256dV256diV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslawzx_vvsvl = struct { + const param_str = "V256dV256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslawzx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslawzx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vslawzx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsll_vvsl = struct { + const param_str = "V256dV256dLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsll_vvsmvl = struct { + const param_str = "V256dV256dLUiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsll_vvsvl = struct { + const param_str = "V256dV256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsll_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsll_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsll_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsral_vvsl = struct { + const param_str = "V256dV256dLiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsral_vvsmvl = struct { + const param_str = "V256dV256dLiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsral_vvsvl = struct { + const param_str = "V256dV256dLiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsral_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsral_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsral_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrawsx_vvsl = struct { + const param_str = "V256dV256diUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrawsx_vvsmvl = struct { + const param_str = "V256dV256diV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrawsx_vvsvl = struct { + const param_str = "V256dV256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrawsx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrawsx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrawsx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrawzx_vvsl = struct { + const param_str = "V256dV256diUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrawzx_vvsmvl = struct { + const param_str = "V256dV256diV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrawzx_vvsvl = struct { + const param_str = "V256dV256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrawzx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrawzx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrawzx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrl_vvsl = struct { + const param_str = "V256dV256dLUiUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrl_vvsmvl = struct { + const param_str = "V256dV256dLUiV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrl_vvsvl = struct { + const param_str = "V256dV256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrl_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrl_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsrl_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vst2d_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vst2d_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vst2dnc_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vst2dnc_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vst2dncot_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vst2dncot_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vst2dot_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vst2dot_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vst_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vst_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstl2d_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstl2d_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstl2dnc_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstl2dnc_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstl2dncot_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstl2dncot_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstl2dot_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstl2dot_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstl_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstl_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstlnc_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstlnc_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstlncot_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstlncot_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstlot_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstlot_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstnc_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstnc_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstncot_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstncot_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstot_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstot_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstu2d_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstu2d_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstu2dnc_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstu2dnc_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstu2dncot_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstu2dncot_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstu2dot_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstu2dot_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstu_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstu_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstunc_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstunc_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstuncot_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstuncot_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstuot_vssl = struct { + const param_str = "vV256dLUiv*Ui"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vstuot_vssml = struct { + const param_str = "vV256dLUiv*V256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubsl_vsvl = struct { + const param_str = "V256dLiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubsl_vsvmvl = struct { + const param_str = "V256dLiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubsl_vsvvl = struct { + const param_str = "V256dLiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubsl_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubsl_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubsl_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubswsx_vsvl = struct { + const param_str = "V256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubswsx_vsvmvl = struct { + const param_str = "V256diV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubswsx_vsvvl = struct { + const param_str = "V256diV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubswsx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubswsx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubswsx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubswzx_vsvl = struct { + const param_str = "V256diV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubswzx_vsvmvl = struct { + const param_str = "V256diV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubswzx_vsvvl = struct { + const param_str = "V256diV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubswzx_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubswzx_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubswzx_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubul_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubul_vsvmvl = struct { + const param_str = "V256dLUiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubul_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubul_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubul_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubul_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubuw_vsvl = struct { + const param_str = "V256dUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubuw_vsvmvl = struct { + const param_str = "V256dUiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubuw_vsvvl = struct { + const param_str = "V256dUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubuw_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubuw_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsubuw_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsuml_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsuml_vvml = struct { + const param_str = "V256dV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsumwsx_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsumwsx_vvml = struct { + const param_str = "V256dV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsumwzx_vvl = struct { + const param_str = "V256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vsumwzx_vvml = struct { + const param_str = "V256dV256dV256bUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vxor_vsvl = struct { + const param_str = "V256dLUiV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vxor_vsvmvl = struct { + const param_str = "V256dLUiV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vxor_vsvvl = struct { + const param_str = "V256dLUiV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vxor_vvvl = struct { + const param_str = "V256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vxor_vvvmvl = struct { + const param_str = "V256dV256dV256dV256bV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_vxor_vvvvl = struct { + const param_str = "V256dV256dV256dV256dUi"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_xorm_MMM = struct { + const param_str = "V512bV512bV512b"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_ve_vl_xorm_mmm = struct { + const param_str = "V256bV256bV256b"; + const target_set = TargetSet.init(.{ + .vevl_gen = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_vsnprintf = struct { + const param_str = "ic*zcC*a"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .format_kind = .vprintf, + .format_string_position = 2, + }; + }; + + pub const __builtin_vsprintf = struct { + const param_str = "ic*cC*a"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .format_kind = .vprintf, + .format_string_position = 1, + }; + }; + + pub const __builtin_vsx_extractuword = struct { + const param_str = "V2ULLiV16UcIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_insertword = struct { + const param_str = "V16UcV4UiV16UcIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_ldrmb = struct { + const param_str = "V16UcCc*Ii"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_lxvd2x = struct { + const param_str = "V2dLivC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_lxvd2x_be = struct { + const param_str = "V2dSLLivC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_lxvl = struct { + const param_str = "V4ivC*ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_lxvll = struct { + const param_str = "V4ivC*ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_lxvw4x = struct { + const param_str = "V4iLivC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_lxvw4x_be = struct { + const param_str = "V4iSLLivC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_scalar_extract_expq = struct { + const param_str = "ULLiLLd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_scalar_insert_exp_qp = struct { + const param_str = "LLdLLdULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_strmb = struct { + const param_str = "vCc*IiV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_stxvd2x = struct { + const param_str = "vV2dLiv*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_stxvd2x_be = struct { + const param_str = "vV2dSLLivC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_stxvl = struct { + const param_str = "vV4iv*ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_stxvll = struct { + const param_str = "vV4iv*ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_stxvw4x = struct { + const param_str = "vV4iLiv*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_stxvw4x_be = struct { + const param_str = "vV4iSLLivC*"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xsmaxdp = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xsmindp = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvabsdp = struct { + const param_str = "V2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvabssp = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcmpeqdp = struct { + const param_str = "V2ULLiV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcmpeqdp_p = struct { + const param_str = "iiV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcmpeqsp = struct { + const param_str = "V4UiV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcmpeqsp_p = struct { + const param_str = "iiV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcmpgedp = struct { + const param_str = "V2ULLiV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcmpgedp_p = struct { + const param_str = "iiV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcmpgesp = struct { + const param_str = "V4UiV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcmpgesp_p = struct { + const param_str = "iiV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcmpgtdp = struct { + const param_str = "V2ULLiV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcmpgtdp_p = struct { + const param_str = "iiV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcmpgtsp = struct { + const param_str = "V4UiV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcmpgtsp_p = struct { + const param_str = "iiV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcpsgndp = struct { + const param_str = "V2dV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcpsgnsp = struct { + const param_str = "V4fV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcvbf16spn = struct { + const param_str = "V16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcvdpsp = struct { + const param_str = "V4fV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcvdpsxws = struct { + const param_str = "V4SiV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcvdpuxws = struct { + const param_str = "V4UiV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcvhpsp = struct { + const param_str = "V4fV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcvspbf16 = struct { + const param_str = "V16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcvspdp = struct { + const param_str = "V2dV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcvsphp = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcvspsxds = struct { + const param_str = "V2SLLiV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcvspuxds = struct { + const param_str = "V2ULLiV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcvsxdsp = struct { + const param_str = "V4fV2SLLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcvsxwdp = struct { + const param_str = "V2dV4Si"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcvuxdsp = struct { + const param_str = "V4fV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvcvuxwdp = struct { + const param_str = "V2dV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvdivdp = struct { + const param_str = "V2dV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvdivsp = struct { + const param_str = "V4fV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xviexpdp = struct { + const param_str = "V2dV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xviexpsp = struct { + const param_str = "V4fV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvmaddadp = struct { + const param_str = "V2dV2dV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvmaddasp = struct { + const param_str = "V4fV4fV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvmaxdp = struct { + const param_str = "V2dV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvmaxsp = struct { + const param_str = "V4fV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvmindp = struct { + const param_str = "V2dV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvminsp = struct { + const param_str = "V4fV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvmsubadp = struct { + const param_str = "V2dV2dV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvmsubasp = struct { + const param_str = "V4fV4fV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvmuldp = struct { + const param_str = "V2dV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvmulsp = struct { + const param_str = "V4fV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvnmaddadp = struct { + const param_str = "V2dV2dV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvnmaddasp = struct { + const param_str = "V4fV4fV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvnmsubadp = struct { + const param_str = "V2dV2dV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvnmsubasp = struct { + const param_str = "V4fV4fV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvrdpi = struct { + const param_str = "V2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvrdpic = struct { + const param_str = "V2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvrdpim = struct { + const param_str = "V2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvrdpip = struct { + const param_str = "V2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvrdpiz = struct { + const param_str = "V2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvredp = struct { + const param_str = "V2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvresp = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvrspi = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvrspic = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvrspim = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvrspip = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvrspiz = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvrsqrtedp = struct { + const param_str = "V2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvrsqrtesp = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvsqrtdp = struct { + const param_str = "V2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvsqrtsp = struct { + const param_str = "V4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvtdivdp = struct { + const param_str = "iV2dV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvtdivsp = struct { + const param_str = "iV4fV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvtlsbb = struct { + const param_str = "iV16UcUi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvtsqrtdp = struct { + const param_str = "iV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvtsqrtsp = struct { + const param_str = "iV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvtstdcdp = struct { + const param_str = "V2ULLiV2dIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvtstdcsp = struct { + const param_str = "V4UiV4fIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvxexpdp = struct { + const param_str = "V2ULLiV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvxexpsp = struct { + const param_str = "V4UiV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvxsigdp = struct { + const param_str = "V2ULLiV2d"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xvxsigsp = struct { + const param_str = "V4UiV4f"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xxblendvb = struct { + const param_str = "V16UcV16UcV16UcV16Uc"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xxblendvd = struct { + const param_str = "V2ULLiV2ULLiV2ULLiV2ULLi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xxblendvh = struct { + const param_str = "V8UsV8UsV8UsV8Us"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xxblendvw = struct { + const param_str = "V4UiV4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xxeval = struct { + const param_str = "V2ULLiV2ULLiV2ULLiV2ULLiIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xxgenpcvbm = struct { + const param_str = "V16UcV16Uci"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xxgenpcvdm = struct { + const param_str = "V2ULLiV2ULLii"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xxgenpcvhm = struct { + const param_str = "V8UsV8Usi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xxgenpcvwm = struct { + const param_str = "V4UiV4Uii"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xxleqv = struct { + const param_str = "V4UiV4UiV4Ui"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xxpermdi = struct { + const param_str = "v."; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_vsx_xxpermx = struct { + const param_str = "V16UcV16UcV16UcV16UcIi"; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + }; + + pub const __builtin_vsx_xxsldwi = struct { + const param_str = "v."; + const target_set = TargetSet.init(.{ + .ppc = true, + }); + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __builtin_wasm_max_f32 = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .webassembly = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_wasm_max_f64 = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .webassembly = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_wasm_memory_grow = struct { + const param_str = "zIiz"; + const target_set = TargetSet.init(.{ + .webassembly = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_wasm_memory_size = struct { + const param_str = "zIi"; + const target_set = TargetSet.init(.{ + .webassembly = true, + }); + const attributes = Attributes{}; + }; + + pub const __builtin_wasm_min_f32 = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .webassembly = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_wasm_min_f64 = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .webassembly = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_wasm_trunc_s_i32_f32 = struct { + const param_str = "if"; + const target_set = TargetSet.init(.{ + .webassembly = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_wasm_trunc_s_i32_f64 = struct { + const param_str = "id"; + const target_set = TargetSet.init(.{ + .webassembly = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_wasm_trunc_s_i64_f32 = struct { + const param_str = "LLif"; + const target_set = TargetSet.init(.{ + .webassembly = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_wasm_trunc_s_i64_f64 = struct { + const param_str = "LLid"; + const target_set = TargetSet.init(.{ + .webassembly = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_wasm_trunc_u_i32_f32 = struct { + const param_str = "if"; + const target_set = TargetSet.init(.{ + .webassembly = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_wasm_trunc_u_i32_f64 = struct { + const param_str = "id"; + const target_set = TargetSet.init(.{ + .webassembly = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_wasm_trunc_u_i64_f32 = struct { + const param_str = "LLif"; + const target_set = TargetSet.init(.{ + .webassembly = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_wasm_trunc_u_i64_f64 = struct { + const param_str = "LLid"; + const target_set = TargetSet.init(.{ + .webassembly = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __builtin_wcschr = struct { + const param_str = "w*wC*w"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_wcscmp = struct { + const param_str = "iwC*wC*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_wcslen = struct { + const param_str = "zwC*"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_wcsncmp = struct { + const param_str = "iwC*wC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_wmemchr = struct { + const param_str = "w*wC*wz"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_wmemcmp = struct { + const param_str = "iwC*wC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_wmemcpy = struct { + const param_str = "w*w*wC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __builtin_wmemmove = struct { + const param_str = "w*w*wC*z"; + const attributes = Attributes{ + .lib_function_with_builtin_prefix = true, + .const_evaluable = true, + }; + }; + + pub const __c11_atomic_is_lock_free = struct { + const param_str = "bz"; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const __c11_atomic_signal_fence = struct { + const param_str = "vi"; + const attributes = Attributes{}; + }; + + pub const __c11_atomic_thread_fence = struct { + const param_str = "vi"; + const attributes = Attributes{}; + }; + + pub const __clear_cache = struct { + const param_str = "vv*v*"; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{}; + }; + + pub const __cospi = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __cospif = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __debugbreak = struct { + const param_str = "v"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const __dmb = struct { + const param_str = "vUi"; + const language = .all_ms_languages; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __dsb = struct { + const param_str = "vUi"; + const language = .all_ms_languages; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __emit = struct { + const param_str = "vIUiC"; + const language = .all_ms_languages; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __exception_code = struct { + const param_str = "UNi"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const __exception_info = struct { + const param_str = "v*"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const __exp10 = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __exp10f = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __fastfail = struct { + const param_str = "vUi"; + const language = .all_ms_languages; + const attributes = Attributes{ + .noreturn = true, + }; + }; + + pub const __finite = struct { + const param_str = "id"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const __finitef = struct { + const param_str = "if"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const __finitel = struct { + const param_str = "iLd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const __isb = struct { + const param_str = "vUi"; + const language = .all_ms_languages; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __iso_volatile_load16 = struct { + const param_str = "ssCD*"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const __iso_volatile_load32 = struct { + const param_str = "iiCD*"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const __iso_volatile_load64 = struct { + const param_str = "LLiLLiCD*"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const __iso_volatile_load8 = struct { + const param_str = "ccCD*"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const __iso_volatile_store16 = struct { + const param_str = "vsD*s"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const __iso_volatile_store32 = struct { + const param_str = "viD*i"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const __iso_volatile_store64 = struct { + const param_str = "vLLiD*LLi"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const __iso_volatile_store8 = struct { + const param_str = "vcD*c"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const __ldrexd = struct { + const param_str = "WiWiCD*"; + const language = .all_ms_languages; + const target_set = TargetSet.init(.{ + .arm = true, + }); + }; + + pub const __lzcnt = struct { + const param_str = "UiUi"; + const language = .all_ms_languages; + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __lzcnt16 = struct { + const param_str = "UsUs"; + const language = .all_ms_languages; + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __lzcnt64 = struct { + const param_str = "UWiUWi"; + const language = .all_ms_languages; + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __noop = struct { + const param_str = "i."; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const __nvvm_add_rm_d = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_add_rm_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_add_rm_ftz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_add_rn_d = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_add_rn_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_add_rn_ftz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_add_rp_d = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_add_rp_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_add_rp_ftz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_add_rz_d = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_add_rz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_add_rz_ftz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_atom_add_gen_f = struct { + const param_str = "ffD*f"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_add_gen_i = struct { + const param_str = "iiD*i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_add_gen_l = struct { + const param_str = "LiLiD*Li"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_add_gen_ll = struct { + const param_str = "LLiLLiD*LLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_and_gen_i = struct { + const param_str = "iiD*i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_and_gen_l = struct { + const param_str = "LiLiD*Li"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_and_gen_ll = struct { + const param_str = "LLiLLiD*LLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_cas_gen_i = struct { + const param_str = "iiD*ii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_cas_gen_l = struct { + const param_str = "LiLiD*LiLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_cas_gen_ll = struct { + const param_str = "LLiLLiD*LLiLLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_dec_gen_ui = struct { + const param_str = "UiUiD*Ui"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_inc_gen_ui = struct { + const param_str = "UiUiD*Ui"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_max_gen_i = struct { + const param_str = "iiD*i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_max_gen_l = struct { + const param_str = "LiLiD*Li"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_max_gen_ll = struct { + const param_str = "LLiLLiD*LLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_max_gen_ui = struct { + const param_str = "UiUiD*Ui"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_max_gen_ul = struct { + const param_str = "ULiULiD*ULi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_max_gen_ull = struct { + const param_str = "ULLiULLiD*ULLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_min_gen_i = struct { + const param_str = "iiD*i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_min_gen_l = struct { + const param_str = "LiLiD*Li"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_min_gen_ll = struct { + const param_str = "LLiLLiD*LLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_min_gen_ui = struct { + const param_str = "UiUiD*Ui"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_min_gen_ul = struct { + const param_str = "ULiULiD*ULi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_min_gen_ull = struct { + const param_str = "ULLiULLiD*ULLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_or_gen_i = struct { + const param_str = "iiD*i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_or_gen_l = struct { + const param_str = "LiLiD*Li"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_or_gen_ll = struct { + const param_str = "LLiLLiD*LLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_sub_gen_i = struct { + const param_str = "iiD*i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_sub_gen_l = struct { + const param_str = "LiLiD*Li"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_sub_gen_ll = struct { + const param_str = "LLiLLiD*LLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_xchg_gen_i = struct { + const param_str = "iiD*i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_xchg_gen_l = struct { + const param_str = "LiLiD*Li"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_xchg_gen_ll = struct { + const param_str = "LLiLLiD*LLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_xor_gen_i = struct { + const param_str = "iiD*i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_xor_gen_l = struct { + const param_str = "LiLiD*Li"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_atom_xor_gen_ll = struct { + const param_str = "LLiLLiD*LLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_bar0_and = struct { + const param_str = "ii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_bar0_or = struct { + const param_str = "ii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_bar0_popc = struct { + const param_str = "ii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_bar_sync = struct { + const param_str = "vi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_bitcast_d2ll = struct { + const param_str = "LLid"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_bitcast_f2i = struct { + const param_str = "if"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_bitcast_i2f = struct { + const param_str = "fi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_bitcast_ll2d = struct { + const param_str = "dLLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ceil_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ceil_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ceil_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_compiler_error = struct { + const param_str = "vcC*4"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_compiler_warn = struct { + const param_str = "vcC*4"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_cos_approx_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_cos_approx_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2f_rm = struct { + const param_str = "fd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2f_rm_ftz = struct { + const param_str = "fd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2f_rn = struct { + const param_str = "fd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2f_rn_ftz = struct { + const param_str = "fd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2f_rp = struct { + const param_str = "fd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2f_rp_ftz = struct { + const param_str = "fd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2f_rz = struct { + const param_str = "fd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2f_rz_ftz = struct { + const param_str = "fd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2i_hi = struct { + const param_str = "id"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2i_lo = struct { + const param_str = "id"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2i_rm = struct { + const param_str = "id"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2i_rn = struct { + const param_str = "id"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2i_rp = struct { + const param_str = "id"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2i_rz = struct { + const param_str = "id"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2ll_rm = struct { + const param_str = "LLid"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2ll_rn = struct { + const param_str = "LLid"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2ll_rp = struct { + const param_str = "LLid"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2ll_rz = struct { + const param_str = "LLid"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2ui_rm = struct { + const param_str = "Uid"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2ui_rn = struct { + const param_str = "Uid"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2ui_rp = struct { + const param_str = "Uid"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2ui_rz = struct { + const param_str = "Uid"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2ull_rm = struct { + const param_str = "ULLid"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2ull_rn = struct { + const param_str = "ULLid"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2ull_rp = struct { + const param_str = "ULLid"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_d2ull_rz = struct { + const param_str = "ULLid"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_div_approx_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_div_approx_ftz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_div_rm_d = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_div_rm_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_div_rm_ftz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_div_rn_d = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_div_rn_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_div_rn_ftz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_div_rp_d = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_div_rp_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_div_rp_ftz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_div_rz_d = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_div_rz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_div_rz_ftz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ex2_approx_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ex2_approx_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ex2_approx_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2h_rn = struct { + const param_str = "Usf"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2h_rn_ftz = struct { + const param_str = "Usf"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2i_rm = struct { + const param_str = "if"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2i_rm_ftz = struct { + const param_str = "if"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2i_rn = struct { + const param_str = "if"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2i_rn_ftz = struct { + const param_str = "if"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2i_rp = struct { + const param_str = "if"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2i_rp_ftz = struct { + const param_str = "if"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2i_rz = struct { + const param_str = "if"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2i_rz_ftz = struct { + const param_str = "if"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ll_rm = struct { + const param_str = "LLif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ll_rm_ftz = struct { + const param_str = "LLif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ll_rn = struct { + const param_str = "LLif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ll_rn_ftz = struct { + const param_str = "LLif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ll_rp = struct { + const param_str = "LLif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ll_rp_ftz = struct { + const param_str = "LLif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ll_rz = struct { + const param_str = "LLif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ll_rz_ftz = struct { + const param_str = "LLif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ui_rm = struct { + const param_str = "Uif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ui_rm_ftz = struct { + const param_str = "Uif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ui_rn = struct { + const param_str = "Uif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ui_rn_ftz = struct { + const param_str = "Uif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ui_rp = struct { + const param_str = "Uif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ui_rp_ftz = struct { + const param_str = "Uif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ui_rz = struct { + const param_str = "Uif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ui_rz_ftz = struct { + const param_str = "Uif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ull_rm = struct { + const param_str = "ULLif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ull_rm_ftz = struct { + const param_str = "ULLif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ull_rn = struct { + const param_str = "ULLif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ull_rn_ftz = struct { + const param_str = "ULLif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ull_rp = struct { + const param_str = "ULLif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ull_rp_ftz = struct { + const param_str = "ULLif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ull_rz = struct { + const param_str = "ULLif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_f2ull_rz_ftz = struct { + const param_str = "ULLif"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fabs_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fabs_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fabs_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_floor_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_floor_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_floor_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fma_rm_d = struct { + const param_str = "dddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fma_rm_f = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fma_rm_ftz_f = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fma_rn_d = struct { + const param_str = "dddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fma_rn_f = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fma_rn_ftz_f = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fma_rp_d = struct { + const param_str = "dddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fma_rp_f = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fma_rp_ftz_f = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fma_rz_d = struct { + const param_str = "dddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fma_rz_f = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fma_rz_ftz_f = struct { + const param_str = "ffff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fmax_d = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fmax_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fmax_ftz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fmin_d = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fmin_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_fmin_ftz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_i2d_rm = struct { + const param_str = "di"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_i2d_rn = struct { + const param_str = "di"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_i2d_rp = struct { + const param_str = "di"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_i2d_rz = struct { + const param_str = "di"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_i2f_rm = struct { + const param_str = "fi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_i2f_rn = struct { + const param_str = "fi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_i2f_rp = struct { + const param_str = "fi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_i2f_rz = struct { + const param_str = "fi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_isspacep_const = struct { + const param_str = "bvC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_isspacep_global = struct { + const param_str = "bvC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_isspacep_local = struct { + const param_str = "bvC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_isspacep_shared = struct { + const param_str = "bvC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_ldg_c = struct { + const param_str = "ccC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_c2 = struct { + const param_str = "E2cE2cC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_c4 = struct { + const param_str = "E4cE4cC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_d = struct { + const param_str = "ddC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_d2 = struct { + const param_str = "E2dE2dC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_f = struct { + const param_str = "ffC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_f2 = struct { + const param_str = "E2fE2fC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_f4 = struct { + const param_str = "E4fE4fC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_i = struct { + const param_str = "iiC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_i2 = struct { + const param_str = "E2iE2iC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_i4 = struct { + const param_str = "E4iE4iC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_l = struct { + const param_str = "LiLiC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_ll = struct { + const param_str = "LLiLLiC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_ll2 = struct { + const param_str = "E2LLiE2LLiC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_s = struct { + const param_str = "ssC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_s2 = struct { + const param_str = "E2sE2sC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_s4 = struct { + const param_str = "E4sE4sC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_uc = struct { + const param_str = "UcUcC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_uc2 = struct { + const param_str = "E2UcE2UcC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_uc4 = struct { + const param_str = "E4UcE4UcC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_ui = struct { + const param_str = "UiUiC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_ui2 = struct { + const param_str = "E2UiE2UiC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_ui4 = struct { + const param_str = "E4UiE4UiC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_ul = struct { + const param_str = "ULiULiC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_ull = struct { + const param_str = "ULLiULLiC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_ull2 = struct { + const param_str = "E2ULLiE2ULLiC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_us = struct { + const param_str = "UsUsC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_us2 = struct { + const param_str = "E2UsE2UsC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ldg_us4 = struct { + const param_str = "E4UsE4UsC*"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_lg2_approx_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_lg2_approx_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_lg2_approx_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ll2d_rm = struct { + const param_str = "dLLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ll2d_rn = struct { + const param_str = "dLLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ll2d_rp = struct { + const param_str = "dLLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ll2d_rz = struct { + const param_str = "dLLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ll2f_rm = struct { + const param_str = "fLLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ll2f_rn = struct { + const param_str = "fLLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ll2f_rp = struct { + const param_str = "fLLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ll2f_rz = struct { + const param_str = "fLLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_lohi_i2d = struct { + const param_str = "dii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_membar_cta = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_membar_gl = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_membar_sys = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_memcpy = struct { + const param_str = "vUc*Uc*zi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_memset = struct { + const param_str = "vUc*Uczi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mul24_i = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mul24_ui = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mul_rm_d = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mul_rm_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mul_rm_ftz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mul_rn_d = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mul_rn_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mul_rn_ftz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mul_rp_d = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mul_rp_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mul_rp_ftz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mul_rz_d = struct { + const param_str = "ddd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mul_rz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mul_rz_ftz_f = struct { + const param_str = "fff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mulhi_i = struct { + const param_str = "iii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mulhi_ll = struct { + const param_str = "LLiLLiLLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mulhi_ui = struct { + const param_str = "UiUiUi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_mulhi_ull = struct { + const param_str = "ULLiULLiULLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_prmt = struct { + const param_str = "UiUiUiUi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rcp_approx_ftz_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rcp_approx_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rcp_rm_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rcp_rm_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rcp_rm_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rcp_rn_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rcp_rn_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rcp_rn_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rcp_rp_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rcp_rp_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rcp_rp_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rcp_rz_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rcp_rz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rcp_rz_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_read_ptx_sreg_clock = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_read_ptx_sreg_clock64 = struct { + const param_str = "LLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_read_ptx_sreg_ctaid_w = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_ctaid_x = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_ctaid_y = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_ctaid_z = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_gridid = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_laneid = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_lanemask_eq = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_lanemask_ge = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_lanemask_gt = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_lanemask_le = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_lanemask_lt = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_nctaid_w = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_nctaid_x = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_nctaid_y = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_nctaid_z = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_nsmid = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_ntid_w = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_ntid_x = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_ntid_y = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_ntid_z = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_nwarpid = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_pm0 = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_read_ptx_sreg_pm1 = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_read_ptx_sreg_pm2 = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_read_ptx_sreg_pm3 = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{}; + }; + + pub const __nvvm_read_ptx_sreg_smid = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_tid_w = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_tid_x = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_tid_y = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_tid_z = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_read_ptx_sreg_warpid = struct { + const param_str = "i"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __nvvm_round_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_round_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_round_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rsqrt_approx_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rsqrt_approx_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_rsqrt_approx_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sad_i = struct { + const param_str = "iiii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sad_ui = struct { + const param_str = "UiUiUiUi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_saturate_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_saturate_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_saturate_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_shfl_bfly_f32 = struct { + const param_str = "ffii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_shfl_bfly_i32 = struct { + const param_str = "iiii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_shfl_down_f32 = struct { + const param_str = "ffii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_shfl_down_i32 = struct { + const param_str = "iiii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_shfl_idx_f32 = struct { + const param_str = "ffii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_shfl_idx_i32 = struct { + const param_str = "iiii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_shfl_up_f32 = struct { + const param_str = "ffii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_shfl_up_i32 = struct { + const param_str = "iiii"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sin_approx_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sin_approx_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sqrt_approx_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sqrt_approx_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sqrt_rm_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sqrt_rm_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sqrt_rm_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sqrt_rn_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sqrt_rn_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sqrt_rn_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sqrt_rp_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sqrt_rp_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sqrt_rp_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sqrt_rz_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sqrt_rz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_sqrt_rz_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_trunc_d = struct { + const param_str = "dd"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_trunc_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_trunc_ftz_f = struct { + const param_str = "ff"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ui2d_rm = struct { + const param_str = "dUi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ui2d_rn = struct { + const param_str = "dUi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ui2d_rp = struct { + const param_str = "dUi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ui2d_rz = struct { + const param_str = "dUi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ui2f_rm = struct { + const param_str = "fUi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ui2f_rn = struct { + const param_str = "fUi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ui2f_rp = struct { + const param_str = "fUi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ui2f_rz = struct { + const param_str = "fUi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ull2d_rm = struct { + const param_str = "dULLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ull2d_rn = struct { + const param_str = "dULLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ull2d_rp = struct { + const param_str = "dULLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ull2d_rz = struct { + const param_str = "dULLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ull2f_rm = struct { + const param_str = "fULLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ull2f_rn = struct { + const param_str = "fULLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ull2f_rp = struct { + const param_str = "fULLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_ull2f_rz = struct { + const param_str = "fULLi"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_vote_all = struct { + const param_str = "bb"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_vote_any = struct { + const param_str = "bb"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_vote_ballot = struct { + const param_str = "Uib"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __nvvm_vote_uni = struct { + const param_str = "bb"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __popcnt = struct { + const param_str = "UiUi"; + const language = .all_ms_languages; + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __popcnt16 = struct { + const param_str = "UsUs"; + const language = .all_ms_languages; + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __popcnt64 = struct { + const param_str = "UWiUWi"; + const language = .all_ms_languages; + const attributes = Attributes{ + .@"const" = true, + }; + }; + + pub const __rdtsc = struct { + const param_str = "UOi"; + const target_set = TargetSet.init(.{ + .x86 = true, + }); + }; + + pub const __sev = struct { + const param_str = "v"; + const language = .all_ms_languages; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + }; + + pub const __sevl = struct { + const param_str = "v"; + const language = .all_ms_languages; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + }; + + pub const __sigsetjmp = struct { + const param_str = "iSJi"; + const header = .setjmp; + const attributes = Attributes{ + .allow_type_mismatch = true, + .lib_function_without_prefix = true, + .returns_twice = true, + }; + }; + + pub const __sinpi = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __sinpif = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __sync_add_and_fetch = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_add_and_fetch_1 = struct { + const param_str = "ccD*c."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_add_and_fetch_16 = struct { + const param_str = "LLLiLLLiD*LLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_add_and_fetch_2 = struct { + const param_str = "ssD*s."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_add_and_fetch_4 = struct { + const param_str = "iiD*i."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_add_and_fetch_8 = struct { + const param_str = "LLiLLiD*LLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_and_and_fetch = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_and_and_fetch_1 = struct { + const param_str = "ccD*c."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_and_and_fetch_16 = struct { + const param_str = "LLLiLLLiD*LLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_and_and_fetch_2 = struct { + const param_str = "ssD*s."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_and_and_fetch_4 = struct { + const param_str = "iiD*i."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_and_and_fetch_8 = struct { + const param_str = "LLiLLiD*LLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_bool_compare_and_swap = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_bool_compare_and_swap_1 = struct { + const param_str = "bcD*cc."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_bool_compare_and_swap_16 = struct { + const param_str = "bLLLiD*LLLiLLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_bool_compare_and_swap_2 = struct { + const param_str = "bsD*ss."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_bool_compare_and_swap_4 = struct { + const param_str = "biD*ii."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_bool_compare_and_swap_8 = struct { + const param_str = "bLLiD*LLiLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_add = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_add_1 = struct { + const param_str = "ccD*c."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_add_16 = struct { + const param_str = "LLLiLLLiD*LLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_add_2 = struct { + const param_str = "ssD*s."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_add_4 = struct { + const param_str = "iiD*i."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_add_8 = struct { + const param_str = "LLiLLiD*LLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_and = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_and_1 = struct { + const param_str = "ccD*c."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_and_16 = struct { + const param_str = "LLLiLLLiD*LLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_and_2 = struct { + const param_str = "ssD*s."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_and_4 = struct { + const param_str = "iiD*i."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_and_8 = struct { + const param_str = "LLiLLiD*LLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_max = struct { + const param_str = "iiD*i"; + const attributes = Attributes{}; + }; + + pub const __sync_fetch_and_min = struct { + const param_str = "iiD*i"; + const attributes = Attributes{}; + }; + + pub const __sync_fetch_and_nand = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_nand_1 = struct { + const param_str = "ccD*c."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_nand_16 = struct { + const param_str = "LLLiLLLiD*LLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_nand_2 = struct { + const param_str = "ssD*s."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_nand_4 = struct { + const param_str = "iiD*i."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_nand_8 = struct { + const param_str = "LLiLLiD*LLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_or = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_or_1 = struct { + const param_str = "ccD*c."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_or_16 = struct { + const param_str = "LLLiLLLiD*LLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_or_2 = struct { + const param_str = "ssD*s."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_or_4 = struct { + const param_str = "iiD*i."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_or_8 = struct { + const param_str = "LLiLLiD*LLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_sub = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_sub_1 = struct { + const param_str = "ccD*c."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_sub_16 = struct { + const param_str = "LLLiLLLiD*LLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_sub_2 = struct { + const param_str = "ssD*s."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_sub_4 = struct { + const param_str = "iiD*i."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_sub_8 = struct { + const param_str = "LLiLLiD*LLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_umax = struct { + const param_str = "UiUiD*Ui"; + const attributes = Attributes{}; + }; + + pub const __sync_fetch_and_umin = struct { + const param_str = "UiUiD*Ui"; + const attributes = Attributes{}; + }; + + pub const __sync_fetch_and_xor = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_xor_1 = struct { + const param_str = "ccD*c."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_xor_16 = struct { + const param_str = "LLLiLLLiD*LLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_xor_2 = struct { + const param_str = "ssD*s."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_xor_4 = struct { + const param_str = "iiD*i."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_fetch_and_xor_8 = struct { + const param_str = "LLiLLiD*LLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_lock_release = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_lock_release_1 = struct { + const param_str = "vcD*."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_lock_release_16 = struct { + const param_str = "vLLLiD*."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_lock_release_2 = struct { + const param_str = "vsD*."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_lock_release_4 = struct { + const param_str = "viD*."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_lock_release_8 = struct { + const param_str = "vLLiD*."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_lock_test_and_set = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_lock_test_and_set_1 = struct { + const param_str = "ccD*c."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_lock_test_and_set_16 = struct { + const param_str = "LLLiLLLiD*LLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_lock_test_and_set_2 = struct { + const param_str = "ssD*s."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_lock_test_and_set_4 = struct { + const param_str = "iiD*i."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_lock_test_and_set_8 = struct { + const param_str = "LLiLLiD*LLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_nand_and_fetch = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_nand_and_fetch_1 = struct { + const param_str = "ccD*c."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_nand_and_fetch_16 = struct { + const param_str = "LLLiLLLiD*LLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_nand_and_fetch_2 = struct { + const param_str = "ssD*s."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_nand_and_fetch_4 = struct { + const param_str = "iiD*i."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_nand_and_fetch_8 = struct { + const param_str = "LLiLLiD*LLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_or_and_fetch = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_or_and_fetch_1 = struct { + const param_str = "ccD*c."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_or_and_fetch_16 = struct { + const param_str = "LLLiLLLiD*LLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_or_and_fetch_2 = struct { + const param_str = "ssD*s."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_or_and_fetch_4 = struct { + const param_str = "iiD*i."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_or_and_fetch_8 = struct { + const param_str = "LLiLLiD*LLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_sub_and_fetch = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_sub_and_fetch_1 = struct { + const param_str = "ccD*c."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_sub_and_fetch_16 = struct { + const param_str = "LLLiLLLiD*LLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_sub_and_fetch_2 = struct { + const param_str = "ssD*s."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_sub_and_fetch_4 = struct { + const param_str = "iiD*i."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_sub_and_fetch_8 = struct { + const param_str = "LLiLLiD*LLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_swap = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_swap_1 = struct { + const param_str = "ccD*c."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_swap_16 = struct { + const param_str = "LLLiLLLiD*LLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_swap_2 = struct { + const param_str = "ssD*s."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_swap_4 = struct { + const param_str = "iiD*i."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_swap_8 = struct { + const param_str = "LLiLLiD*LLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_synchronize = struct { + const param_str = "v"; + const attributes = Attributes{}; + }; + + pub const __sync_val_compare_and_swap = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_val_compare_and_swap_1 = struct { + const param_str = "ccD*cc."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_val_compare_and_swap_16 = struct { + const param_str = "LLLiLLLiD*LLLiLLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_val_compare_and_swap_2 = struct { + const param_str = "ssD*ss."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_val_compare_and_swap_4 = struct { + const param_str = "iiD*ii."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_val_compare_and_swap_8 = struct { + const param_str = "LLiLLiD*LLiLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_xor_and_fetch = struct { + const param_str = "v."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_xor_and_fetch_1 = struct { + const param_str = "ccD*c."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_xor_and_fetch_16 = struct { + const param_str = "LLLiLLLiD*LLLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_xor_and_fetch_2 = struct { + const param_str = "ssD*s."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_xor_and_fetch_4 = struct { + const param_str = "iiD*i."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __sync_xor_and_fetch_8 = struct { + const param_str = "LLiLLiD*LLi."; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __syncthreads = struct { + const param_str = "v"; + const target_set = TargetSet.init(.{ + .nvptx = true, + }); + }; + + pub const __tanpi = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __tanpif = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const __va_start = struct { + const param_str = "vc**."; + const language = .all_ms_languages; + const attributes = Attributes{ + .custom_typecheck = true, + }; + }; + + pub const __warn_memset_zero_len = struct { + const param_str = "v"; + const attributes = Attributes{ + .pure = true, + }; + }; + + pub const __wfe = struct { + const param_str = "v"; + const language = .all_ms_languages; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + }; + + pub const __wfi = struct { + const param_str = "v"; + const language = .all_ms_languages; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + }; + + pub const __xray_customevent = struct { + const param_str = "vcC*z"; + }; + + pub const __xray_typedevent = struct { + const param_str = "vzcC*z"; + }; + + pub const __yield = struct { + const param_str = "v"; + const language = .all_ms_languages; + const target_set = TargetSet.init(.{ + .aarch64 = true, + .arm = true, + }); + }; + + pub const _abnormal_termination = struct { + const param_str = "i"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _alloca = struct { + const param_str = "v*z"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _bittest = struct { + const param_str = "UcNiC*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _bittest64 = struct { + const param_str = "UcWiC*Wi"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _bittestandcomplement = struct { + const param_str = "UcNi*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _bittestandcomplement64 = struct { + const param_str = "UcWi*Wi"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _bittestandreset = struct { + const param_str = "UcNi*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _bittestandreset64 = struct { + const param_str = "UcWi*Wi"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _bittestandset = struct { + const param_str = "UcNi*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _bittestandset64 = struct { + const param_str = "UcWi*Wi"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _byteswap_uint64 = struct { + const param_str = "ULLiULLi"; + const language = .all_ms_languages; + const header = .stdlib; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const _byteswap_ulong = struct { + const param_str = "UNiUNi"; + const language = .all_ms_languages; + const header = .stdlib; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const _byteswap_ushort = struct { + const param_str = "UsUs"; + const language = .all_ms_languages; + const header = .stdlib; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const _exception_code = struct { + const param_str = "UNi"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _exception_info = struct { + const param_str = "v*"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _exit = struct { + const param_str = "vi"; + const language = .all_gnu_languages; + const header = .unistd; + const attributes = Attributes{ + .noreturn = true, + .lib_function_without_prefix = true, + }; + }; + + pub const _interlockedbittestandreset = struct { + const param_str = "UcNiD*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _interlockedbittestandreset64 = struct { + const param_str = "UcWiD*Wi"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _interlockedbittestandreset_acq = struct { + const param_str = "UcNiD*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _interlockedbittestandreset_nf = struct { + const param_str = "UcNiD*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _interlockedbittestandreset_rel = struct { + const param_str = "UcNiD*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _interlockedbittestandset = struct { + const param_str = "UcNiD*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _interlockedbittestandset64 = struct { + const param_str = "UcWiD*Wi"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _interlockedbittestandset_acq = struct { + const param_str = "UcNiD*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _interlockedbittestandset_nf = struct { + const param_str = "UcNiD*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _interlockedbittestandset_rel = struct { + const param_str = "UcNiD*Ni"; + const language = .all_ms_languages; + const attributes = Attributes{}; + }; + + pub const _longjmp = struct { + const param_str = "vJi"; + const language = .all_gnu_languages; + const header = .setjmp; + const attributes = Attributes{ + .noreturn = true, + .allow_type_mismatch = true, + .lib_function_without_prefix = true, + }; + }; + + pub const _lrotl = struct { + const param_str = "ULiULii"; + const language = .all_ms_languages; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const _lrotr = struct { + const param_str = "ULiULii"; + const language = .all_ms_languages; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const _rotl = struct { + const param_str = "UiUii"; + const language = .all_ms_languages; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const _rotl16 = struct { + const param_str = "UsUsUc"; + const language = .all_ms_languages; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const _rotl64 = struct { + const param_str = "UWiUWii"; + const language = .all_ms_languages; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const _rotl8 = struct { + const param_str = "UcUcUc"; + const language = .all_ms_languages; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const _rotr = struct { + const param_str = "UiUii"; + const language = .all_ms_languages; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const _rotr16 = struct { + const param_str = "UsUsUc"; + const language = .all_ms_languages; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const _rotr64 = struct { + const param_str = "UWiUWii"; + const language = .all_ms_languages; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const _rotr8 = struct { + const param_str = "UcUcUc"; + const language = .all_ms_languages; + const attributes = Attributes{ + .const_evaluable = true, + }; + }; + + pub const _setjmp = struct { + const param_str = "iJ"; + const header = .setjmp; + const attributes = Attributes{ + .allow_type_mismatch = true, + .lib_function_without_prefix = true, + .returns_twice = true, + }; + }; + + pub const _setjmpex = struct { + const param_str = "iJ"; + const language = .all_ms_languages; + const header = .setjmpex; + const attributes = Attributes{ + .allow_type_mismatch = true, + .lib_function_without_prefix = true, + .returns_twice = true, + }; + }; + + pub const abort = struct { + const param_str = "v"; + const header = .stdlib; + const attributes = Attributes{ + .noreturn = true, + .lib_function_without_prefix = true, + }; + }; + + pub const abs = struct { + const param_str = "ii"; + const header = .stdlib; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const acos = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const acosf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const acosh = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const acoshf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const acoshl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const acosl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const aligned_alloc = struct { + const param_str = "v*zz"; + const header = .stdlib; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const alloca = struct { + const param_str = "v*z"; + const language = .all_gnu_languages; + const header = .stdlib; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const asin = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const asinf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const asinh = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const asinhf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const asinhl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const asinl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const atan = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const atan2 = struct { + const param_str = "ddd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const atan2f = struct { + const param_str = "fff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const atan2l = struct { + const param_str = "LdLdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const atanf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const atanh = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const atanhf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const atanhl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const atanl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const bcmp = struct { + const param_str = "ivC*vC*z"; + const language = .all_gnu_languages; + const header = .strings; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; + + pub const bzero = struct { + const param_str = "vv*z"; + const language = .all_gnu_languages; + const header = .strings; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const cabs = struct { + const param_str = "dXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cabsf = struct { + const param_str = "fXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cabsl = struct { + const param_str = "LdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cacos = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cacosf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cacosh = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cacoshf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cacoshl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cacosl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const calloc = struct { + const param_str = "v*zz"; + const header = .stdlib; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const carg = struct { + const param_str = "dXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cargf = struct { + const param_str = "fXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cargl = struct { + const param_str = "LdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const casin = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const casinf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const casinh = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const casinhf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const casinhl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const casinl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const catan = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const catanf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const catanh = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const catanhf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const catanhl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const catanl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cbrt = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const cbrtf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const cbrtl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const ccos = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ccosf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ccosh = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ccoshf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ccoshl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ccosl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ceil = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const ceilf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const ceill = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const cexp = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cexpf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cexpl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cimag = struct { + const param_str = "dXd"; + const header = .complex; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const cimagf = struct { + const param_str = "fXf"; + const header = .complex; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const cimagl = struct { + const param_str = "LdXLd"; + const header = .complex; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const clog = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const clogf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const clogl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const conj = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const conjf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const conjl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const copysign = struct { + const param_str = "ddd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const copysignf = struct { + const param_str = "fff"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const copysignl = struct { + const param_str = "LdLdLd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const cos = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cosf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cosh = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const coshf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const coshl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cosl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cpow = struct { + const param_str = "XdXdXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cpowf = struct { + const param_str = "XfXfXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cpowl = struct { + const param_str = "XLdXLdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const cproj = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const cprojf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const cprojl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const creal = struct { + const param_str = "dXd"; + const header = .complex; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const crealf = struct { + const param_str = "fXf"; + const header = .complex; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const creall = struct { + const param_str = "LdXLd"; + const header = .complex; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const csin = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const csinf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const csinh = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const csinhf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const csinhl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const csinl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const csqrt = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const csqrtf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const csqrtl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ctan = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ctanf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ctanh = struct { + const param_str = "XdXd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ctanhf = struct { + const param_str = "XfXf"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ctanhl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ctanl = struct { + const param_str = "XLdXLd"; + const header = .complex; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const erf = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const erfc = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const erfcf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const erfcl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const erff = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const erfl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const exit = struct { + const param_str = "vi"; + const header = .stdlib; + const attributes = Attributes{ + .noreturn = true, + .lib_function_without_prefix = true, + }; + }; + + pub const exp = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const exp2 = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const exp2f = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const exp2l = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const expf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const expl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const expm1 = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const expm1f = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const expm1l = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const fabs = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const fabsf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const fabsl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const fdim = struct { + const param_str = "ddd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const fdimf = struct { + const param_str = "fff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const fdiml = struct { + const param_str = "LdLdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const finite = struct { + const param_str = "id"; + const language = .gnu_lang; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const finitef = struct { + const param_str = "if"; + const language = .gnu_lang; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const finitel = struct { + const param_str = "iLd"; + const language = .gnu_lang; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const floor = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const floorf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const floorl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const fma = struct { + const param_str = "dddd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const fmaf = struct { + const param_str = "ffff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const fmal = struct { + const param_str = "LdLdLdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const fmax = struct { + const param_str = "ddd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const fmaxf = struct { + const param_str = "fff"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const fmaxl = struct { + const param_str = "LdLdLd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const fmin = struct { + const param_str = "ddd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const fminf = struct { + const param_str = "fff"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const fminl = struct { + const param_str = "LdLdLd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const fmod = struct { + const param_str = "ddd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const fmodf = struct { + const param_str = "fff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const fmodl = struct { + const param_str = "LdLdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const fopen = struct { + const param_str = "P*cC*cC*"; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const fprintf = struct { + const param_str = "iP*cC*."; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .format_kind = .printf, + .format_string_position = 1, + }; + }; + + pub const fread = struct { + const param_str = "zv*zzP*"; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const free = struct { + const param_str = "vv*"; + const header = .stdlib; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const frexp = struct { + const param_str = "ddi*"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const frexpf = struct { + const param_str = "ffi*"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const frexpl = struct { + const param_str = "LdLdi*"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const fscanf = struct { + const param_str = "iP*RcC*R."; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .format_kind = .scanf, + .format_string_position = 1, + }; + }; + + pub const fwrite = struct { + const param_str = "zvC*zzP*"; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const getcontext = struct { + const param_str = "iK*"; + const header = .setjmp; + const attributes = Attributes{ + .allow_type_mismatch = true, + .lib_function_without_prefix = true, + .returns_twice = true, + }; + }; + + pub const hypot = struct { + const param_str = "ddd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const hypotf = struct { + const param_str = "fff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const hypotl = struct { + const param_str = "LdLdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ilogb = struct { + const param_str = "id"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ilogbf = struct { + const param_str = "if"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ilogbl = struct { + const param_str = "iLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const index = struct { + const param_str = "c*cC*i"; + const language = .all_gnu_languages; + const header = .strings; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const isalnum = struct { + const param_str = "ii"; + const header = .ctype; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const isalpha = struct { + const param_str = "ii"; + const header = .ctype; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const isblank = struct { + const param_str = "ii"; + const header = .ctype; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const iscntrl = struct { + const param_str = "ii"; + const header = .ctype; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const isdigit = struct { + const param_str = "ii"; + const header = .ctype; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const isgraph = struct { + const param_str = "ii"; + const header = .ctype; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const islower = struct { + const param_str = "ii"; + const header = .ctype; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const isprint = struct { + const param_str = "ii"; + const header = .ctype; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const ispunct = struct { + const param_str = "ii"; + const header = .ctype; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const isspace = struct { + const param_str = "ii"; + const header = .ctype; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const isupper = struct { + const param_str = "ii"; + const header = .ctype; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const isxdigit = struct { + const param_str = "ii"; + const header = .ctype; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const labs = struct { + const param_str = "LiLi"; + const header = .stdlib; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const ldexp = struct { + const param_str = "ddi"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ldexpf = struct { + const param_str = "ffi"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const ldexpl = struct { + const param_str = "LdLdi"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const lgamma = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const lgammaf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const lgammal = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const llabs = struct { + const param_str = "LLiLLi"; + const header = .stdlib; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const llrint = struct { + const param_str = "LLid"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const llrintf = struct { + const param_str = "LLif"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const llrintl = struct { + const param_str = "LLiLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const llround = struct { + const param_str = "LLid"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const llroundf = struct { + const param_str = "LLif"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const llroundl = struct { + const param_str = "LLiLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const log = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const log10 = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const log10f = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const log10l = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const log1p = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const log1pf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const log1pl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const log2 = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const log2f = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const log2l = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const logb = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const logbf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const logbl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const logf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const logl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const longjmp = struct { + const param_str = "vJi"; + const header = .setjmp; + const attributes = Attributes{ + .noreturn = true, + .allow_type_mismatch = true, + .lib_function_without_prefix = true, + }; + }; + + pub const lrint = struct { + const param_str = "Lid"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const lrintf = struct { + const param_str = "Lif"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const lrintl = struct { + const param_str = "LiLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const lround = struct { + const param_str = "Lid"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const lroundf = struct { + const param_str = "Lif"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const lroundl = struct { + const param_str = "LiLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const malloc = struct { + const param_str = "v*z"; + const header = .stdlib; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const memalign = struct { + const param_str = "v*zz"; + const language = .all_gnu_languages; + const header = .malloc; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const memccpy = struct { + const param_str = "v*v*vC*iz"; + const language = .all_gnu_languages; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const memchr = struct { + const param_str = "v*vC*iz"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; + + pub const memcmp = struct { + const param_str = "ivC*vC*z"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; + + pub const memcpy = struct { + const param_str = "v*v*vC*z"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; + + pub const memmove = struct { + const param_str = "v*v*vC*z"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; + + pub const mempcpy = struct { + const param_str = "v*v*vC*z"; + const language = .all_gnu_languages; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const memset = struct { + const param_str = "v*v*iz"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const modf = struct { + const param_str = "ddd*"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const modff = struct { + const param_str = "fff*"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const modfl = struct { + const param_str = "LdLdLd*"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const nan = struct { + const param_str = "dcC*"; + const header = .math; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const nanf = struct { + const param_str = "fcC*"; + const header = .math; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const nanl = struct { + const param_str = "LdcC*"; + const header = .math; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const nearbyint = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const nearbyintf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const nearbyintl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const nextafter = struct { + const param_str = "ddd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const nextafterf = struct { + const param_str = "fff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const nextafterl = struct { + const param_str = "LdLdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const nexttoward = struct { + const param_str = "ddLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const nexttowardf = struct { + const param_str = "ffLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const nexttowardl = struct { + const param_str = "LdLdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const pow = struct { + const param_str = "ddd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const powf = struct { + const param_str = "fff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const powl = struct { + const param_str = "LdLdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const printf = struct { + const param_str = "icC*."; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .format_kind = .printf, + .format_string_position = 0, + }; + }; + + pub const realloc = struct { + const param_str = "v*v*z"; + const header = .stdlib; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const remainder = struct { + const param_str = "ddd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const remainderf = struct { + const param_str = "fff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const remainderl = struct { + const param_str = "LdLdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const remquo = struct { + const param_str = "dddi*"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const remquof = struct { + const param_str = "fffi*"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const remquol = struct { + const param_str = "LdLdLdi*"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const rindex = struct { + const param_str = "c*cC*i"; + const language = .all_gnu_languages; + const header = .strings; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const rint = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_fp_exceptions = true, + }; + }; + + pub const rintf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_fp_exceptions = true, + }; + }; + + pub const rintl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_fp_exceptions = true, + }; + }; + + pub const round = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const roundf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const roundl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const savectx = struct { + const param_str = "iJ"; + const header = .setjmp; + const attributes = Attributes{ + .allow_type_mismatch = true, + .lib_function_without_prefix = true, + .returns_twice = true, + }; + }; + + pub const scalbln = struct { + const param_str = "ddLi"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const scalblnf = struct { + const param_str = "ffLi"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const scalblnl = struct { + const param_str = "LdLdLi"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const scalbn = struct { + const param_str = "ddi"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const scalbnf = struct { + const param_str = "ffi"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const scalbnl = struct { + const param_str = "LdLdi"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const scanf = struct { + const param_str = "icC*R."; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .format_kind = .scanf, + .format_string_position = 0, + }; + }; + + pub const setjmp = struct { + const param_str = "iJ"; + const header = .setjmp; + const attributes = Attributes{ + .allow_type_mismatch = true, + .lib_function_without_prefix = true, + .returns_twice = true, + }; + }; + + pub const siglongjmp = struct { + const param_str = "vSJi"; + const language = .all_gnu_languages; + const header = .setjmp; + const attributes = Attributes{ + .noreturn = true, + .allow_type_mismatch = true, + .lib_function_without_prefix = true, + }; + }; + + pub const sigsetjmp = struct { + const param_str = "iSJi"; + const header = .setjmp; + const attributes = Attributes{ + .allow_type_mismatch = true, + .lib_function_without_prefix = true, + .returns_twice = true, + }; + }; + + pub const sin = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const sinf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const sinh = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const sinhf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const sinhl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const sinl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const snprintf = struct { + const param_str = "ic*zcC*."; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .format_kind = .printf, + .format_string_position = 2, + }; + }; + + pub const sprintf = struct { + const param_str = "ic*cC*."; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .format_kind = .printf, + .format_string_position = 1, + }; + }; + + pub const sqrt = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const sqrtf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const sqrtl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const sscanf = struct { + const param_str = "icC*RcC*R."; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .format_kind = .scanf, + .format_string_position = 1, + }; + }; + + pub const stpcpy = struct { + const param_str = "c*c*cC*"; + const language = .all_gnu_languages; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const stpncpy = struct { + const param_str = "c*c*cC*z"; + const language = .all_gnu_languages; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strcasecmp = struct { + const param_str = "icC*cC*"; + const language = .all_gnu_languages; + const header = .strings; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strcat = struct { + const param_str = "c*c*cC*"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strchr = struct { + const param_str = "c*cC*i"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; + + pub const strcmp = struct { + const param_str = "icC*cC*"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; + + pub const strcpy = struct { + const param_str = "c*c*cC*"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strcspn = struct { + const param_str = "zcC*cC*"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strdup = struct { + const param_str = "c*cC*"; + const language = .all_gnu_languages; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strerror = struct { + const param_str = "c*i"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strlcat = struct { + const param_str = "zc*cC*z"; + const language = .all_gnu_languages; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strlcpy = struct { + const param_str = "zc*cC*z"; + const language = .all_gnu_languages; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strlen = struct { + const param_str = "zcC*"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; + + pub const strncasecmp = struct { + const param_str = "icC*cC*z"; + const language = .all_gnu_languages; + const header = .strings; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strncat = struct { + const param_str = "c*c*cC*z"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strncmp = struct { + const param_str = "icC*cC*z"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; + + pub const strncpy = struct { + const param_str = "c*c*cC*z"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strndup = struct { + const param_str = "c*cC*z"; + const language = .all_gnu_languages; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strpbrk = struct { + const param_str = "c*cC*cC*"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strrchr = struct { + const param_str = "c*cC*i"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strspn = struct { + const param_str = "zcC*cC*"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strstr = struct { + const param_str = "c*cC*cC*"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strtod = struct { + const param_str = "dcC*c**"; + const header = .stdlib; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strtof = struct { + const param_str = "fcC*c**"; + const header = .stdlib; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strtok = struct { + const param_str = "c*c*cC*"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strtol = struct { + const param_str = "LicC*c**i"; + const header = .stdlib; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strtold = struct { + const param_str = "LdcC*c**"; + const header = .stdlib; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strtoll = struct { + const param_str = "LLicC*c**i"; + const header = .stdlib; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strtoul = struct { + const param_str = "ULicC*c**i"; + const header = .stdlib; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strtoull = struct { + const param_str = "ULLicC*c**i"; + const header = .stdlib; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const strxfrm = struct { + const param_str = "zc*cC*z"; + const header = .string; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const tan = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const tanf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const tanh = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const tanhf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const tanhl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const tanl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const tgamma = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const tgammaf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const tgammal = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_without_errno_and_fp_exceptions = true, + }; + }; + + pub const tolower = struct { + const param_str = "ii"; + const header = .ctype; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const toupper = struct { + const param_str = "ii"; + const header = .ctype; + const attributes = Attributes{ + .pure = true, + .lib_function_without_prefix = true, + }; + }; + + pub const trunc = struct { + const param_str = "dd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const truncf = struct { + const param_str = "ff"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const truncl = struct { + const param_str = "LdLd"; + const header = .math; + const attributes = Attributes{ + .@"const" = true, + .lib_function_without_prefix = true, + }; + }; + + pub const va_copy = struct { + const param_str = "vAA"; + const header = .stdarg; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const va_end = struct { + const param_str = "vA"; + const header = .stdarg; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const va_start = struct { + const param_str = "vA."; + const header = .stdarg; + const attributes = Attributes{ + .lib_function_without_prefix = true, + }; + }; + + pub const vfork = struct { + const param_str = "p"; + const header = .unistd; + const attributes = Attributes{ + .allow_type_mismatch = true, + .lib_function_without_prefix = true, + .returns_twice = true, + }; + }; + + pub const vfprintf = struct { + const param_str = "iP*cC*a"; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .format_kind = .vprintf, + .format_string_position = 1, + }; + }; + + pub const vfscanf = struct { + const param_str = "iP*RcC*Ra"; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .format_kind = .vscanf, + .format_string_position = 1, + }; + }; + + pub const vprintf = struct { + const param_str = "icC*a"; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .format_kind = .vprintf, + .format_string_position = 0, + }; + }; + + pub const vscanf = struct { + const param_str = "icC*Ra"; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .format_kind = .vscanf, + .format_string_position = 0, + }; + }; + + pub const vsnprintf = struct { + const param_str = "ic*zcC*a"; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .format_kind = .vprintf, + .format_string_position = 2, + }; + }; + + pub const vsprintf = struct { + const param_str = "ic*cC*a"; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .format_kind = .vprintf, + .format_string_position = 1, + }; + }; + + pub const vsscanf = struct { + const param_str = "icC*RcC*Ra"; + const header = .stdio; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .format_kind = .vscanf, + .format_string_position = 1, + }; + }; + + pub const wcschr = struct { + const param_str = "w*wC*w"; + const header = .wchar; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; + + pub const wcscmp = struct { + const param_str = "iwC*wC*"; + const header = .wchar; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; + + pub const wcslen = struct { + const param_str = "zwC*"; + const header = .wchar; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; + + pub const wcsncmp = struct { + const param_str = "iwC*wC*z"; + const header = .wchar; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; + + pub const wmemchr = struct { + const param_str = "w*wC*wz"; + const header = .wchar; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; + + pub const wmemcmp = struct { + const param_str = "iwC*wC*z"; + const header = .wchar; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; + + pub const wmemcpy = struct { + const param_str = "w*w*wC*z"; + const header = .wchar; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; + + pub const wmemmove = struct { + const param_str = "w*w*wC*z"; + const header = .wchar; + const attributes = Attributes{ + .lib_function_without_prefix = true, + .const_evaluable = true, + }; + }; +}; +pub const MaxParamCount = 12; diff --git a/deps/aro/builtins/Properties.zig b/deps/aro/builtins/Properties.zig new file mode 100644 index 000000000000..b564c0e2b209 --- /dev/null +++ b/deps/aro/builtins/Properties.zig @@ -0,0 +1,138 @@ +const std = @import("std"); + +const Properties = @This(); + +language: Language, +attributes: Attributes, +header: Header, +target_set: TargetSet, + +/// Header which must be included for a builtin to be available +pub const Header = enum { + none, + /// stdio.h + stdio, + /// stdlib.h + stdlib, + /// setjmpex.h + setjmpex, + /// stdarg.h + stdarg, + /// string.h + string, + /// ctype.h + ctype, + /// wchar.h + wchar, + /// setjmp.h + setjmp, + /// malloc.h + malloc, + /// strings.h + strings, + /// unistd.h + unistd, + /// pthread.h + pthread, + /// math.h + math, + /// complex.h + complex, + /// Blocks.h + blocks, +}; + +/// Languages in which a builtin is available +pub const Language = enum { + all_languages, + all_ms_languages, + all_gnu_languages, + gnu_lang, +}; + +pub const Attributes = packed struct { + /// Function does not return + noreturn: bool = false, + + /// Function has no side effects + pure: bool = false, + + /// Function has no side effects and does not read memory + @"const": bool = false, + + /// Signature is meaningless; use custom typecheck + custom_typecheck: bool = false, + + /// A declaration of this builtin should be recognized even if the type doesn't match the specified signature. + allow_type_mismatch: bool = false, + + /// this is a libc/libm function with a '__builtin_' prefix added. + lib_function_with_builtin_prefix: bool = false, + + /// this is a libc/libm function without a '__builtin_' prefix. This builtin is disableable by '-fno-builtin-foo' + lib_function_without_prefix: bool = false, + + /// Function returns twice (e.g. setjmp) + returns_twice: bool = false, + + /// Nature of the format string passed to this function + format_kind: enum(u3) { + /// Does not take a format string + none, + /// this is a printf-like function whose Nth argument is the format string + printf, + /// function is like vprintf in that it accepts its arguments as a va_list rather than through an ellipsis + vprintf, + /// this is a scanf-like function whose Nth argument is the format string + scanf, + /// the function is like vscanf in that it accepts its arguments as a va_list rather than through an ellipsis + vscanf, + } = .none, + + /// Position of format string argument. Only meaningful if format_kind is not .none + format_string_position: u5 = 0, + + /// if false, arguments are not evaluated + eval_args: bool = true, + + /// no side effects and does not read memory, but only when -fno-math-errno and FP exceptions are ignored + const_without_errno_and_fp_exceptions: bool = false, + + /// no side effects and does not read memory, but only when FP exceptions are ignored + const_without_fp_exceptions: bool = false, + + /// this function can be constant evaluated by the frontend + const_evaluable: bool = false, +}; + +pub const Target = enum { + /// Supported on all targets + basic, + aarch64, + aarch64_neon_sve_bridge, + aarch64_neon_sve_bridge_cg, + amdgpu, + arm, + bpf, + hexagon, + hexagon_dep, + hexagon_map_custom_dep, + loong_arch, + mips, + neon, + nvptx, + ppc, + riscv, + riscv_vector, + sve, + systemz, + ve, + vevl_gen, + webassembly, + x86, + x86_64, + xcore, +}; + +/// Targets for which a builtin is enabled +pub const TargetSet = std.enums.EnumSet(Target); diff --git a/deps/aro/builtins/TypeDescription.zig b/deps/aro/builtins/TypeDescription.zig new file mode 100644 index 000000000000..59832cffc1b3 --- /dev/null +++ b/deps/aro/builtins/TypeDescription.zig @@ -0,0 +1,277 @@ +const std = @import("std"); + +const TypeDescription = @This(); + +prefix: []const Prefix, +spec: Spec, +suffix: []const Suffix, + +pub const Component = union(enum) { + prefix: Prefix, + spec: Spec, + suffix: Suffix, +}; + +pub const ComponentIterator = struct { + str: []const u8, + idx: usize, + + pub fn init(str: []const u8) ComponentIterator { + return .{ + .str = str, + .idx = 0, + }; + } + + pub fn peek(self: *ComponentIterator) ?Component { + const idx = self.idx; + defer self.idx = idx; + return self.next(); + } + + pub fn next(self: *ComponentIterator) ?Component { + if (self.idx == self.str.len) return null; + const c = self.str[self.idx]; + self.idx += 1; + switch (c) { + 'L' => { + if (self.str[self.idx] != 'L') return .{ .prefix = .L }; + self.idx += 1; + if (self.str[self.idx] != 'L') return .{ .prefix = .LL }; + self.idx += 1; + return .{ .prefix = .LLL }; + }, + 'Z' => return .{ .prefix = .Z }, + 'W' => return .{ .prefix = .W }, + 'N' => return .{ .prefix = .N }, + 'O' => return .{ .prefix = .O }, + 'S' => { + if (self.str[self.idx] == 'J') { + self.idx += 1; + return .{ .spec = .SJ }; + } + return .{ .prefix = .S }; + }, + 'U' => return .{ .prefix = .U }, + 'I' => return .{ .prefix = .I }, + + 'v' => return .{ .spec = .v }, + 'b' => return .{ .spec = .b }, + 'c' => return .{ .spec = .c }, + 's' => return .{ .spec = .s }, + 'i' => return .{ .spec = .i }, + 'h' => return .{ .spec = .h }, + 'x' => return .{ .spec = .x }, + 'y' => return .{ .spec = .y }, + 'f' => return .{ .spec = .f }, + 'd' => return .{ .spec = .d }, + 'z' => return .{ .spec = .z }, + 'w' => return .{ .spec = .w }, + 'F' => return .{ .spec = .F }, + 'a' => return .{ .spec = .a }, + 'A' => return .{ .spec = .A }, + 'V', 'q', 'E' => { + const start = self.idx; + while (std.ascii.isDigit(self.str[self.idx])) : (self.idx += 1) {} + const count = std.fmt.parseUnsigned(u32, self.str[start..self.idx], 10) catch unreachable; + return switch (c) { + 'V' => .{ .spec = .{ .V = count } }, + 'q' => .{ .spec = .{ .q = count } }, + 'E' => .{ .spec = .{ .E = count } }, + else => unreachable, + }; + }, + 'X' => { + defer self.idx += 1; + switch (self.str[self.idx]) { + 'f' => return .{ .spec = .{ .X = .float } }, + 'd' => return .{ .spec = .{ .X = .double } }, + 'L' => { + self.idx += 1; + return .{ .spec = .{ .X = .longdouble } }; + }, + else => unreachable, + } + }, + 'Y' => return .{ .spec = .Y }, + 'P' => return .{ .spec = .P }, + 'J' => return .{ .spec = .J }, + 'K' => return .{ .spec = .K }, + 'p' => return .{ .spec = .p }, + '.' => { + // can only appear at end of param string; indicates varargs function + std.debug.assert(self.idx == self.str.len); + return null; + }, + '!' => { + std.debug.assert(self.str.len == 1); + return .{ .spec = .@"!" }; + }, + + '*' => { + if (self.idx < self.str.len and std.ascii.isDigit(self.str[self.idx])) { + defer self.idx += 1; + const addr_space = self.str[self.idx] - '0'; + return .{ .suffix = .{ .@"*" = addr_space } }; + } else { + return .{ .suffix = .{ .@"*" = null } }; + } + }, + 'C' => return .{ .suffix = .C }, + 'D' => return .{ .suffix = .D }, + 'R' => return .{ .suffix = .R }, + else => unreachable, + } + return null; + } +}; + +pub const TypeIterator = struct { + param_str: []const u8, + prefix: [4]Prefix, + spec: Spec, + suffix: [4]Suffix, + idx: usize, + + pub fn init(param_str: []const u8) TypeIterator { + return .{ + .param_str = param_str, + .prefix = undefined, + .spec = undefined, + .suffix = undefined, + .idx = 0, + }; + } + + /// Returned `TypeDescription` contains fields which are slices into the underlying `TypeIterator` + /// The returned value is invalidated when `.next()` is called again or the TypeIterator goes out + // of scope. + pub fn next(self: *TypeIterator) ?TypeDescription { + var it = ComponentIterator.init(self.param_str[self.idx..]); + defer self.idx += it.idx; + + var prefix_count: usize = 0; + var maybe_spec: ?Spec = null; + var suffix_count: usize = 0; + while (it.peek()) |component| { + switch (component) { + .prefix => |prefix| { + if (maybe_spec != null) break; + self.prefix[prefix_count] = prefix; + prefix_count += 1; + }, + .spec => |spec| { + if (maybe_spec != null) break; + maybe_spec = spec; + }, + .suffix => |suffix| { + std.debug.assert(maybe_spec != null); + self.suffix[suffix_count] = suffix; + suffix_count += 1; + }, + } + _ = it.next(); + } + if (maybe_spec) |spec| { + return TypeDescription{ + .prefix = self.prefix[0..prefix_count], + .spec = spec, + .suffix = self.suffix[0..suffix_count], + }; + } + return null; + } +}; + +const Prefix = enum { + /// long (e.g. Li for 'long int', Ld for 'long double') + L, + /// long long (e.g. LLi for 'long long int', LLd for __float128) + LL, + /// __int128_t (e.g. LLLi) + LLL, + /// int32_t (require a native 32-bit integer type on the target) + Z, + /// int64_t (require a native 64-bit integer type on the target) + W, + /// 'int' size if target is LP64, 'L' otherwise. + N, + /// long for OpenCL targets, long long otherwise. + O, + /// signed + S, + /// unsigned + U, + /// Required to constant fold to an integer constant expression. + I, +}; + +const Spec = union(enum) { + /// void + v, + /// boolean + b, + /// char + c, + /// short + s, + /// int + i, + /// half (__fp16, OpenCL) + h, + /// half (_Float16) + x, + /// half (__bf16) + y, + /// float + f, + /// double + d, + /// size_t + z, + /// wchar_t + w, + /// constant CFString + F, + /// __builtin_va_list + a, + /// "reference" to __builtin_va_list + A, + /// Vector, followed by the number of elements and the base type. + V: u32, + /// Scalable vector, followed by the number of elements and the base type. + q: u32, + /// ext_vector, followed by the number of elements and the base type. + E: u32, + /// _Complex, followed by the base type. + X: enum { + float, + double, + longdouble, + }, + /// ptrdiff_t + Y, + /// FILE + P, + /// jmp_buf + J, + /// sigjmp_buf + SJ, + /// ucontext_t + K, + /// pid_t + p, + /// Used to indicate a builtin with target-dependent param types. Must appear by itself + @"!", +}; + +const Suffix = union(enum) { + /// pointer (optionally followed by an address space number,if no address space is specified than any address space will be accepted) + @"*": ?u8, + /// const + C, + /// volatile + D, + /// restrict + R, +}; diff --git a/deps/aro/codegen/x86_64.zig b/deps/aro/codegen/x86_64.zig new file mode 100644 index 000000000000..bc8b43dff1d3 --- /dev/null +++ b/deps/aro/codegen/x86_64.zig @@ -0,0 +1,221 @@ +const std = @import("std"); +const Codegen = @import("../Codegen_legacy.zig"); +const Tree = @import("../Tree.zig"); +const NodeIndex = Tree.NodeIndex; +const x86_64 = @import("zig").codegen.x86_64; +const Register = x86_64.Register; +const RegisterManager = @import("zig").RegisterManager; + +const Fn = @This(); + +const Value = union(enum) { + symbol: []const u8, + immediate: i64, + register: Register, + none, +}; + +register_manager: RegisterManager(Fn, Register, &x86_64.callee_preserved_regs) = .{}, +data: *std.ArrayList(u8), +c: *Codegen, + +pub fn deinit(func: *Fn) void { + func.* = undefined; +} + +pub fn genFn(c: *Codegen, decl: NodeIndex, data: *std.ArrayList(u8)) Codegen.Error!void { + var func = Fn{ .data = data, .c = c }; + defer func.deinit(); + + // function prologue + try func.data.appendSlice(&.{ + 0x55, // push rbp + 0x48, 0x89, 0xe5, // mov rbp,rsp + }); + _ = try func.genNode(c.node_data[@intFromEnum(decl)].decl.node); + // all functions are guaranteed to end in a return statement so no extra work required here +} + +pub fn spillInst(f: *Fn, reg: Register, inst: u32) !void { + _ = inst; + _ = reg; + _ = f; +} + +fn setReg(func: *Fn, val: Value, reg: Register) !void { + switch (val) { + .none => unreachable, + .symbol => |sym| { + // lea address with 0 and add relocation + const encoder = try x86_64.Encoder.init(func.data, 8); + encoder.rex(.{ .w = true }); + encoder.opcode_1byte(0x8D); + encoder.modRm_RIPDisp32(reg.low_id()); + + const offset = func.data.items.len; + encoder.imm32(0); + + try func.c.obj.addRelocation(sym, .func, offset, -4); + }, + .immediate => |x| if (x == 0) { + // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit + // register is the fastest way to zero a register. + // The encoding for `xor r32, r32` is `0x31 /r`. + const encoder = try x86_64.Encoder.init(func.data, 3); + + // If we're accessing e.g. r8d, we need to use a REX prefix before the actual operation. Since + // this is a 32-bit operation, the W flag is set to zero. X is also zero, as we're not using a SIB. + // Both R and B are set, as we're extending, in effect, the register bits *and* the operand. + encoder.rex(.{ .r = reg.isExtended(), .b = reg.isExtended() }); + encoder.opcode_1byte(0x31); + // Section 3.1.1.1 of the Intel x64 Manual states that "/r indicates that the + // ModR/M byte of the instruction contains a register operand and an r/m operand." + encoder.modRm_direct(reg.low_id(), reg.low_id()); + } else if (x <= std.math.maxInt(i32)) { + // Next best case: if we set the lower four bytes, the upper four will be zeroed. + // + // The encoding for `mov IMM32 -> REG` is (0xB8 + R) IMM. + + const encoder = try x86_64.Encoder.init(func.data, 6); + // Just as with XORing, we need a REX prefix. This time though, we only + // need the B bit set, as we're extending the opcode's register field, + // and there is no Mod R/M byte. + encoder.rex(.{ .b = reg.isExtended() }); + encoder.opcode_withReg(0xB8, reg.low_id()); + + // no ModR/M byte + + // IMM + encoder.imm32(@intCast(x)); + } else { + // Worst case: we need to load the 64-bit register with the IMM. GNU's assemblers calls + // this `movabs`, though this is officially just a different variant of the plain `mov` + // instruction. + // + // This encoding is, in fact, the *same* as the one used for 32-bit loads. The only + // difference is that we set REX.W before the instruction, which extends the load to + // 64-bit and uses the full bit-width of the register. + { + const encoder = try x86_64.Encoder.init(func.data, 10); + encoder.rex(.{ .w = true, .b = reg.isExtended() }); + encoder.opcode_withReg(0xB8, reg.low_id()); + encoder.imm64(@bitCast(x)); + } + }, + .register => |src_reg| { + // If the registers are the same, nothing to do. + if (src_reg.id() == reg.id()) + return; + + // This is a variant of 8B /r. + const encoder = try x86_64.Encoder.init(func.data, 3); + encoder.rex(.{ + .w = true, + .r = reg.isExtended(), + .b = src_reg.isExtended(), + }); + encoder.opcode_1byte(0x8B); + encoder.modRm_direct(reg.low_id(), src_reg.low_id()); + }, + } +} + +fn genNode(func: *Fn, node: NodeIndex) Codegen.Error!Value { + if (func.c.tree.value_map.get(node)) |some| { + if (some.tag == .int) + return Value{ .immediate = @bitCast(some.data.int) }; + } + + const data = func.c.node_data[@intFromEnum(node)]; + switch (func.c.node_tag[@intFromEnum(node)]) { + .static_assert => return Value{ .none = {} }, + .compound_stmt_two => { + if (data.bin.lhs != .none) _ = try func.genNode(data.bin.lhs); + if (data.bin.rhs != .none) _ = try func.genNode(data.bin.rhs); + return Value{ .none = {} }; + }, + .compound_stmt => { + for (func.c.tree.data[data.range.start..data.range.end]) |stmt| { + _ = try func.genNode(stmt); + } + return Value{ .none = {} }; + }, + .call_expr_one => if (data.bin.rhs != .none) + return func.genCall(data.bin.lhs, &.{data.bin.rhs}) + else + return func.genCall(data.bin.lhs, &.{}), + .call_expr => return func.genCall(func.c.tree.data[data.range.start], func.c.tree.data[data.range.start + 1 .. data.range.end]), + .explicit_cast, .implicit_cast => { + switch (data.cast.kind) { + .function_to_pointer, + .array_to_pointer, + => return func.genNode(data.cast.operand), // no-op + else => return func.c.comp.diag.fatalNoSrc("TODO x86_64 genNode for cast {s}\n", .{@tagName(data.cast.kind)}), + } + }, + .decl_ref_expr => { + // TODO locals and arguments + return Value{ .symbol = func.c.tree.tokSlice(data.decl_ref) }; + }, + .return_stmt => { + const value = try func.genNode(data.un); + try func.setReg(value, x86_64.c_abi_int_return_regs[0]); + try func.data.appendSlice(&.{ + 0x5d, // pop rbp + 0xc3, // ret + }); + return Value{ .none = {} }; + }, + .implicit_return => { + try func.setReg(.{ .immediate = 0 }, x86_64.c_abi_int_return_regs[0]); + try func.data.appendSlice(&.{ + 0x5d, // pop rbp + 0xc3, // ret + }); + return Value{ .none = {} }; + }, + .int_literal => return Value{ .immediate = @bitCast(data.int) }, + .string_literal_expr => { + const range = func.c.tree.value_map.get(node).?.data.bytes; + const str_bytes = range.slice(func.c.tree.strings); + const section = try func.c.obj.getSection(.strings); + const start = section.items.len; + try section.appendSlice(str_bytes); + const symbol_name = try func.c.obj.declareSymbol(.strings, null, .Internal, .variable, start, str_bytes.len); + return Value{ .symbol = symbol_name }; + }, + else => return func.c.comp.diag.fatalNoSrc("TODO x86_64 genNode {}\n", .{func.c.node_tag[@intFromEnum(node)]}), + } +} + +fn genCall(func: *Fn, lhs: NodeIndex, args: []const NodeIndex) Codegen.Error!Value { + if (args.len > x86_64.c_abi_int_param_regs.len) + return func.c.comp.diag.fatalNoSrc("TODO more than args {d}\n", .{x86_64.c_abi_int_param_regs.len}); + + const func_value = try func.genNode(lhs); + for (args, 0..) |arg, i| { + const value = try func.genNode(arg); + try func.setReg(value, x86_64.c_abi_int_param_regs[i]); + } + + switch (func_value) { + .none => unreachable, + .symbol => |sym| { + const encoder = try x86_64.Encoder.init(func.data, 5); + encoder.opcode_1byte(0xe8); + + const offset = func.data.items.len; + encoder.imm32(0); + + try func.c.obj.addRelocation(sym, .func, offset, -4); + }, + .immediate => return func.c.comp.diag.fatalNoSrc("TODO call immediate\n", .{}), + .register => return func.c.comp.diag.fatalNoSrc("TODO call reg\n", .{}), + } + return Value{ .register = x86_64.c_abi_int_return_regs[0] }; +} + +pub fn genVar(c: *Codegen, decl: NodeIndex) Codegen.Error!void { + _ = c; + _ = decl; +} diff --git a/deps/aro/features.zig b/deps/aro/features.zig new file mode 100644 index 000000000000..d66ba7cabc81 --- /dev/null +++ b/deps/aro/features.zig @@ -0,0 +1,76 @@ +const std = @import("std"); +const Compilation = @import("Compilation.zig"); +const target_util = @import("target.zig"); + +/// Used to implement the __has_feature macro. +pub fn hasFeature(comp: *Compilation, ext: []const u8) bool { + const list = .{ + .assume_nonnull = true, + .attribute_analyzer_noreturn = true, + .attribute_availability = true, + .attribute_availability_with_message = true, + .attribute_availability_app_extension = true, + .attribute_availability_with_version_underscores = true, + .attribute_availability_tvos = true, + .attribute_availability_watchos = true, + .attribute_availability_with_strict = true, + .attribute_availability_with_replacement = true, + .attribute_availability_in_templates = true, + .attribute_availability_swift = true, + .attribute_cf_returns_not_retained = true, + .attribute_cf_returns_retained = true, + .attribute_cf_returns_on_parameters = true, + .attribute_deprecated_with_message = true, + .attribute_deprecated_with_replacement = true, + .attribute_ext_vector_type = true, + .attribute_ns_returns_not_retained = true, + .attribute_ns_returns_retained = true, + .attribute_ns_consumes_self = true, + .attribute_ns_consumed = true, + .attribute_cf_consumed = true, + .attribute_overloadable = true, + .attribute_unavailable_with_message = true, + .attribute_unused_on_fields = true, + .attribute_diagnose_if_objc = true, + .blocks = false, // TODO + .c_thread_safety_attributes = true, + .enumerator_attributes = true, + .nullability = true, + .nullability_on_arrays = true, + .nullability_nullable_result = true, + .c_alignas = comp.langopts.standard.atLeast(.c11), + .c_alignof = comp.langopts.standard.atLeast(.c11), + .c_atomic = comp.langopts.standard.atLeast(.c11), + .c_generic_selections = comp.langopts.standard.atLeast(.c11), + .c_static_assert = comp.langopts.standard.atLeast(.c11), + .c_thread_local = comp.langopts.standard.atLeast(.c11) and target_util.isTlsSupported(comp.target), + }; + inline for (std.meta.fields(@TypeOf(list))) |f| { + if (std.mem.eql(u8, f.name, ext)) return @field(list, f.name); + } + return false; +} + +/// Used to implement the __has_extension macro. +pub fn hasExtension(comp: *Compilation, ext: []const u8) bool { + const list = .{ + // C11 features + .c_alignas = true, + .c_alignof = true, + .c_atomic = false, // TODO + .c_generic_selections = true, + .c_static_assert = true, + .c_thread_local = target_util.isTlsSupported(comp.target), + // misc + .overloadable_unmarked = false, // TODO + .statement_attributes_with_gnu_syntax = false, // TODO + .gnu_asm = true, + .gnu_asm_goto_with_outputs = true, + .matrix_types = false, // TODO + .matrix_types_scalar_division = false, // TODO + }; + inline for (std.meta.fields(@TypeOf(list))) |f| { + if (std.mem.eql(u8, f.name, ext)) return @field(list, f.name); + } + return false; +} diff --git a/deps/aro/lib.zig b/deps/aro/lib.zig new file mode 100644 index 000000000000..e19becb73568 --- /dev/null +++ b/deps/aro/lib.zig @@ -0,0 +1,27 @@ +/// Deprecated +pub const Codegen = @import("Codegen_legacy.zig"); +pub const CodeGen = @import("CodeGen.zig"); +pub const Compilation = @import("Compilation.zig"); +pub const Diagnostics = @import("Diagnostics.zig"); +pub const Driver = @import("Driver.zig"); +pub const Interner = @import("Interner.zig"); +pub const Ir = @import("Ir.zig"); +pub const Object = @import("Object.zig"); +pub const Parser = @import("Parser.zig"); +pub const Preprocessor = @import("Preprocessor.zig"); +pub const Source = @import("Source.zig"); +pub const Tokenizer = @import("Tokenizer.zig"); +pub const Tree = @import("Tree.zig"); +pub const Type = @import("Type.zig"); +pub const TypeMapper = @import("StringInterner.zig").TypeMapper; +pub const target_util = @import("target.zig"); + +pub const version_str = "0.0.0-dev"; +pub const version = @import("std").SemanticVersion.parse(version_str) catch unreachable; + +pub const CallingConvention = enum { + C, + stdcall, + thiscall, + vectorcall, +}; diff --git a/deps/aro/number_affixes.zig b/deps/aro/number_affixes.zig new file mode 100644 index 000000000000..e987934bd214 --- /dev/null +++ b/deps/aro/number_affixes.zig @@ -0,0 +1,169 @@ +const std = @import("std"); +const mem = std.mem; + +pub const Prefix = enum(u8) { + binary = 2, + octal = 8, + decimal = 10, + hex = 16, + + pub fn digitAllowed(prefix: Prefix, c: u8) bool { + return switch (c) { + '0', '1' => true, + '2'...'7' => prefix != .binary, + '8'...'9' => prefix == .decimal or prefix == .hex, + 'a'...'f', 'A'...'F' => prefix == .hex, + else => false, + }; + } + + pub fn fromString(buf: []const u8) Prefix { + if (buf.len == 1) return .decimal; + // tokenizer enforces that first byte is a decimal digit or period + switch (buf[0]) { + '.', '1'...'9' => return .decimal, + '0' => {}, + else => unreachable, + } + switch (buf[1]) { + 'x', 'X' => return if (buf.len == 2) .decimal else .hex, + 'b', 'B' => return if (buf.len == 2) .decimal else .binary, + else => { + if (mem.indexOfAny(u8, buf, "eE.")) |_| { + // This is a decimal floating point number that happens to start with zero + return .decimal; + } else if (Suffix.fromString(buf[1..], .int)) |_| { + // This is `0` with a valid suffix + return .decimal; + } else { + return .octal; + } + }, + } + } + + /// Length of this prefix as a string + pub fn stringLen(prefix: Prefix) usize { + return switch (prefix) { + .binary => 2, + .octal => 1, + .decimal => 0, + .hex => 2, + }; + } +}; + +pub const Suffix = enum { + // zig fmt: off + + // int and imaginary int + None, I, + + // unsigned real integers + U, UL, ULL, + + // unsigned imaginary integers + IU, IUL, IULL, + + // long or long double, real and imaginary + L, IL, + + // long long and imaginary long long + LL, ILL, + + // float and imaginary float + F, IF, + + // _Float16 + F16, + + // Imaginary _Bitint + IWB, IUWB, + + // _Bitint + WB, UWB, + + // zig fmt: on + + const Tuple = struct { Suffix, []const []const u8 }; + + const IntSuffixes = &[_]Tuple{ + .{ .U, &.{"U"} }, + .{ .L, &.{"L"} }, + .{ .WB, &.{"WB"} }, + .{ .UL, &.{ "U", "L" } }, + .{ .UWB, &.{ "U", "WB" } }, + .{ .LL, &.{"LL"} }, + .{ .ULL, &.{ "U", "LL" } }, + + .{ .I, &.{"I"} }, + + .{ .IWB, &.{ "I", "WB" } }, + .{ .IU, &.{ "I", "U" } }, + .{ .IL, &.{ "I", "L" } }, + .{ .IUL, &.{ "I", "U", "L" } }, + .{ .IUWB, &.{ "I", "U", "WB" } }, + .{ .ILL, &.{ "I", "LL" } }, + .{ .IULL, &.{ "I", "U", "LL" } }, + }; + + const FloatSuffixes = &[_]Tuple{ + .{ .F16, &.{"F16"} }, + .{ .F, &.{"F"} }, + .{ .L, &.{"L"} }, + + .{ .I, &.{"I"} }, + .{ .IL, &.{ "I", "L" } }, + .{ .IF, &.{ "I", "F" } }, + }; + + pub fn fromString(buf: []const u8, suffix_kind: enum { int, float }) ?Suffix { + if (buf.len == 0) return .None; + + const suffixes = switch (suffix_kind) { + .float => FloatSuffixes, + .int => IntSuffixes, + }; + var scratch: [3]u8 = undefined; + top: for (suffixes) |candidate| { + const tag = candidate[0]; + const parts = candidate[1]; + var len: usize = 0; + for (parts) |part| len += part.len; + if (len != buf.len) continue; + + for (parts) |part| { + const lower = std.ascii.lowerString(&scratch, part); + if (mem.indexOf(u8, buf, part) == null and mem.indexOf(u8, buf, lower) == null) continue :top; + } + return tag; + } + return null; + } + + pub fn isImaginary(suffix: Suffix) bool { + return switch (suffix) { + .I, .IL, .IF, .IU, .IUL, .ILL, .IULL, .IWB, .IUWB => true, + .None, .L, .F16, .F, .U, .UL, .LL, .ULL, .WB, .UWB => false, + }; + } + + pub fn isSignedInteger(suffix: Suffix) bool { + return switch (suffix) { + .None, .L, .LL, .I, .IL, .ILL, .WB, .IWB => true, + .U, .UL, .ULL, .IU, .IUL, .IULL, .UWB, .IUWB => false, + .F, .IF, .F16 => unreachable, + }; + } + + pub fn signedness(suffix: Suffix) std.builtin.Signedness { + return if (suffix.isSignedInteger()) .signed else .unsigned; + } + + pub fn isBitInt(suffix: Suffix) bool { + return switch (suffix) { + .WB, .UWB, .IWB, .IUWB => true, + else => false, + }; + } +}; diff --git a/deps/aro/object/Elf.zig b/deps/aro/object/Elf.zig new file mode 100644 index 000000000000..6493e5dc25a8 --- /dev/null +++ b/deps/aro/object/Elf.zig @@ -0,0 +1,377 @@ +const std = @import("std"); +const Compilation = @import("../Compilation.zig"); +const Object = @import("../Object.zig"); + +const Elf = @This(); + +const Section = struct { + data: std.ArrayList(u8), + relocations: std.ArrayListUnmanaged(Relocation) = .{}, + flags: u64, + type: u32, + index: u16 = undefined, +}; + +const Symbol = struct { + section: ?*Section, + size: u64, + offset: u64, + index: u16 = undefined, + info: u8, +}; + +const Relocation = packed struct { + symbol: *Symbol, + addend: i64, + offset: u48, + type: u8, +}; + +const additional_sections = 3; // null section, strtab, symtab +const strtab_index = 1; +const symtab_index = 2; +const strtab_default = "\x00.strtab\x00.symtab\x00"; +const strtab_name = 1; +const symtab_name = "\x00.strtab\x00".len; + +obj: Object, +/// The keys are owned by the Codegen.tree +sections: std.StringHashMapUnmanaged(*Section) = .{}, +local_symbols: std.StringHashMapUnmanaged(*Symbol) = .{}, +global_symbols: std.StringHashMapUnmanaged(*Symbol) = .{}, +unnamed_symbol_mangle: u32 = 0, +strtab_len: u64 = strtab_default.len, +arena: std.heap.ArenaAllocator, + +pub fn create(comp: *Compilation) !*Object { + const elf = try comp.gpa.create(Elf); + elf.* = .{ + .obj = .{ .format = .elf, .comp = comp }, + .arena = std.heap.ArenaAllocator.init(comp.gpa), + }; + return &elf.obj; +} + +pub fn deinit(elf: *Elf) void { + const gpa = elf.arena.child_allocator; + { + var it = elf.sections.valueIterator(); + while (it.next()) |sect| { + sect.*.data.deinit(); + sect.*.relocations.deinit(gpa); + } + } + elf.sections.deinit(gpa); + elf.local_symbols.deinit(gpa); + elf.global_symbols.deinit(gpa); + elf.arena.deinit(); + gpa.destroy(elf); +} + +fn sectionString(sec: Object.Section) []const u8 { + return switch (sec) { + .undefined => unreachable, + .data => "data", + .read_only_data => "rodata", + .func => "text", + .strings => "rodata.str", + .custom => |name| name, + }; +} + +pub fn getSection(elf: *Elf, section_kind: Object.Section) !*std.ArrayList(u8) { + const section_name = sectionString(section_kind); + const section = elf.sections.get(section_name) orelse blk: { + const section = try elf.arena.allocator().create(Section); + section.* = .{ + .data = std.ArrayList(u8).init(elf.arena.child_allocator), + .type = std.elf.SHT_PROGBITS, + .flags = switch (section_kind) { + .func, .custom => std.elf.SHF_ALLOC + std.elf.SHF_EXECINSTR, + .strings => std.elf.SHF_ALLOC + std.elf.SHF_MERGE + std.elf.SHF_STRINGS, + .read_only_data => std.elf.SHF_ALLOC, + .data => std.elf.SHF_ALLOC + std.elf.SHF_WRITE, + .undefined => unreachable, + }, + }; + try elf.sections.putNoClobber(elf.arena.child_allocator, section_name, section); + elf.strtab_len += section_name.len + ".\x00".len; + break :blk section; + }; + return §ion.data; +} + +pub fn declareSymbol( + elf: *Elf, + section_kind: Object.Section, + maybe_name: ?[]const u8, + linkage: std.builtin.GlobalLinkage, + @"type": Object.SymbolType, + offset: u64, + size: u64, +) ![]const u8 { + const section = blk: { + if (section_kind == .undefined) break :blk null; + const section_name = sectionString(section_kind); + break :blk elf.sections.get(section_name); + }; + const binding: u8 = switch (linkage) { + .Internal => std.elf.STB_LOCAL, + .Strong => std.elf.STB_GLOBAL, + .Weak => std.elf.STB_WEAK, + .LinkOnce => unreachable, + }; + const sym_type: u8 = switch (@"type") { + .func => std.elf.STT_FUNC, + .variable => std.elf.STT_OBJECT, + .external => std.elf.STT_NOTYPE, + }; + const name = if (maybe_name) |some| some else blk: { + defer elf.unnamed_symbol_mangle += 1; + break :blk try std.fmt.allocPrint(elf.arena.allocator(), ".L.{d}", .{elf.unnamed_symbol_mangle}); + }; + + const gop = if (linkage == .Internal) + try elf.local_symbols.getOrPut(elf.arena.child_allocator, name) + else + try elf.global_symbols.getOrPut(elf.arena.child_allocator, name); + + if (!gop.found_existing) { + gop.value_ptr.* = try elf.arena.allocator().create(Symbol); + elf.strtab_len += name.len + 1; // +1 for null byte + } + gop.value_ptr.*.* = .{ + .section = section, + .size = size, + .offset = offset, + .info = (binding << 4) + sym_type, + }; + return name; +} + +pub fn addRelocation(elf: *Elf, name: []const u8, section_kind: Object.Section, address: u64, addend: i64) !void { + const section_name = sectionString(section_kind); + const symbol = elf.local_symbols.get(name) orelse elf.global_symbols.get(name).?; // reference to undeclared symbol + const section = elf.sections.get(section_name).?; + if (section.relocations.items.len == 0) elf.strtab_len += ".rela".len; + + try section.relocations.append(elf.arena.child_allocator, .{ + .symbol = symbol, + .offset = @intCast(address), + .addend = addend, + .type = if (symbol.section == null) 4 else 2, // TODO + }); +} + +/// elf header +/// sections contents +/// symbols +/// relocations +/// strtab +/// section headers +pub fn finish(elf: *Elf, file: std.fs.File) !void { + var buf_writer = std.io.bufferedWriter(file.writer()); + const w = buf_writer.writer(); + + var num_sections: std.elf.Elf64_Half = additional_sections; + var relocations_len: std.elf.Elf64_Off = 0; + var sections_len: std.elf.Elf64_Off = 0; + { + var it = elf.sections.valueIterator(); + while (it.next()) |sect| { + sections_len += sect.*.data.items.len; + relocations_len += sect.*.relocations.items.len * @sizeOf(std.elf.Elf64_Rela); + sect.*.index = num_sections; + num_sections += 1; + num_sections += @intFromBool(sect.*.relocations.items.len != 0); + } + } + const symtab_len = (elf.local_symbols.count() + elf.global_symbols.count() + 1) * @sizeOf(std.elf.Elf64_Sym); + + const symtab_offset = @sizeOf(std.elf.Elf64_Ehdr) + sections_len; + const symtab_offset_aligned = std.mem.alignForward(u64, symtab_offset, 8); + const rela_offset = symtab_offset_aligned + symtab_len; + const strtab_offset = rela_offset + relocations_len; + const sh_offset = strtab_offset + elf.strtab_len; + const sh_offset_aligned = std.mem.alignForward(u64, sh_offset, 16); + + var elf_header = std.elf.Elf64_Ehdr{ + .e_ident = .{ 0x7F, 'E', 'L', 'F', 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + .e_type = std.elf.ET.REL, // we only produce relocatables + .e_machine = elf.obj.comp.target.cpu.arch.toElfMachine(), + .e_version = 1, + .e_entry = 0, // linker will handle this + .e_phoff = 0, // no program header + .e_shoff = sh_offset_aligned, // section headers offset + .e_flags = 0, // no flags + .e_ehsize = @sizeOf(std.elf.Elf64_Ehdr), + .e_phentsize = 0, // no program header + .e_phnum = 0, // no program header + .e_shentsize = @sizeOf(std.elf.Elf64_Shdr), + .e_shnum = num_sections, + .e_shstrndx = strtab_index, + }; + try w.writeStruct(elf_header); + + // write contents of sections + { + var it = elf.sections.valueIterator(); + while (it.next()) |sect| try w.writeAll(sect.*.data.items); + } + + // pad to 8 bytes + try w.writeByteNTimes(0, @intCast(symtab_offset_aligned - symtab_offset)); + + var name_offset: u32 = strtab_default.len; + // write symbols + { + // first symbol must be null + try w.writeStruct(std.mem.zeroes(std.elf.Elf64_Sym)); + + var sym_index: u16 = 1; + var it = elf.local_symbols.iterator(); + while (it.next()) |entry| { + const sym = entry.value_ptr.*; + try w.writeStruct(std.elf.Elf64_Sym{ + .st_name = name_offset, + .st_info = sym.info, + .st_other = 0, + .st_shndx = if (sym.section) |some| some.index else 0, + .st_value = sym.offset, + .st_size = sym.size, + }); + sym.index = sym_index; + sym_index += 1; + name_offset += @intCast(entry.key_ptr.len + 1); // +1 for null byte + } + it = elf.global_symbols.iterator(); + while (it.next()) |entry| { + const sym = entry.value_ptr.*; + try w.writeStruct(std.elf.Elf64_Sym{ + .st_name = name_offset, + .st_info = sym.info, + .st_other = 0, + .st_shndx = if (sym.section) |some| some.index else 0, + .st_value = sym.offset, + .st_size = sym.size, + }); + sym.index = sym_index; + sym_index += 1; + name_offset += @intCast(entry.key_ptr.len + 1); // +1 for null byte + } + } + + // write relocations + { + var it = elf.sections.valueIterator(); + while (it.next()) |sect| { + for (sect.*.relocations.items) |rela| { + try w.writeStruct(std.elf.Elf64_Rela{ + .r_offset = rela.offset, + .r_addend = rela.addend, + .r_info = (@as(u64, rela.symbol.index) << 32) | rela.type, + }); + } + } + } + + // write strtab + try w.writeAll(strtab_default); + { + var it = elf.local_symbols.keyIterator(); + while (it.next()) |key| try w.print("{s}\x00", .{key.*}); + it = elf.global_symbols.keyIterator(); + while (it.next()) |key| try w.print("{s}\x00", .{key.*}); + } + { + var it = elf.sections.iterator(); + while (it.next()) |entry| { + if (entry.value_ptr.*.relocations.items.len != 0) try w.writeAll(".rela"); + try w.print(".{s}\x00", .{entry.key_ptr.*}); + } + } + + // pad to 16 bytes + try w.writeByteNTimes(0, @intCast(sh_offset_aligned - sh_offset)); + // mandatory null header + try w.writeStruct(std.mem.zeroes(std.elf.Elf64_Shdr)); + + // write strtab section header + { + var sect_header = std.elf.Elf64_Shdr{ + .sh_name = strtab_name, + .sh_type = std.elf.SHT_STRTAB, + .sh_flags = 0, + .sh_addr = 0, + .sh_offset = strtab_offset, + .sh_size = elf.strtab_len, + .sh_link = 0, + .sh_info = 0, + .sh_addralign = 1, + .sh_entsize = 0, + }; + try w.writeStruct(sect_header); + } + + // write symtab section header + { + var sect_header = std.elf.Elf64_Shdr{ + .sh_name = symtab_name, + .sh_type = std.elf.SHT_SYMTAB, + .sh_flags = 0, + .sh_addr = 0, + .sh_offset = symtab_offset_aligned, + .sh_size = symtab_len, + .sh_link = strtab_index, + .sh_info = elf.local_symbols.size + 1, + .sh_addralign = 8, + .sh_entsize = @sizeOf(std.elf.Elf64_Sym), + }; + try w.writeStruct(sect_header); + } + + // remaining section headers + { + var sect_offset: u64 = @sizeOf(std.elf.Elf64_Ehdr); + var rela_sect_offset: u64 = rela_offset; + var it = elf.sections.iterator(); + while (it.next()) |entry| { + const sect = entry.value_ptr.*; + const rela_count = sect.relocations.items.len; + const rela_name_offset: u32 = if (rela_count != 0) @truncate(".rela".len) else 0; + try w.writeStruct(std.elf.Elf64_Shdr{ + .sh_name = rela_name_offset + name_offset, + .sh_type = sect.type, + .sh_flags = sect.flags, + .sh_addr = 0, + .sh_offset = sect_offset, + .sh_size = sect.data.items.len, + .sh_link = 0, + .sh_info = 0, + .sh_addralign = if (sect.flags & std.elf.SHF_EXECINSTR != 0) 16 else 1, + .sh_entsize = 0, + }); + + if (rela_count != 0) { + const size = rela_count * @sizeOf(std.elf.Elf64_Rela); + try w.writeStruct(std.elf.Elf64_Shdr{ + .sh_name = name_offset, + .sh_type = std.elf.SHT_RELA, + .sh_flags = 0, + .sh_addr = 0, + .sh_offset = rela_sect_offset, + .sh_size = rela_count * @sizeOf(std.elf.Elf64_Rela), + .sh_link = symtab_index, + .sh_info = sect.index, + .sh_addralign = 8, + .sh_entsize = @sizeOf(std.elf.Elf64_Rela), + }); + rela_sect_offset += size; + } + + sect_offset += sect.data.items.len; + name_offset += @as(u32, @intCast(entry.key_ptr.len + ".\x00".len)) + rela_name_offset; + } + } + try buf_writer.flush(); +} diff --git a/deps/aro/pragmas/gcc.zig b/deps/aro/pragmas/gcc.zig new file mode 100644 index 000000000000..22bef7cfb447 --- /dev/null +++ b/deps/aro/pragmas/gcc.zig @@ -0,0 +1,199 @@ +const std = @import("std"); +const mem = std.mem; +const Compilation = @import("../Compilation.zig"); +const Pragma = @import("../Pragma.zig"); +const Diagnostics = @import("../Diagnostics.zig"); +const Preprocessor = @import("../Preprocessor.zig"); +const Parser = @import("../Parser.zig"); +const TokenIndex = @import("../Tree.zig").TokenIndex; + +const GCC = @This(); + +pragma: Pragma = .{ + .beforeParse = beforeParse, + .beforePreprocess = beforePreprocess, + .afterParse = afterParse, + .deinit = deinit, + .preprocessorHandler = preprocessorHandler, + .parserHandler = parserHandler, + .preserveTokens = preserveTokens, +}, +original_options: Diagnostics.Options = .{}, +options_stack: std.ArrayListUnmanaged(Diagnostics.Options) = .{}, + +const Directive = enum { + warning, + @"error", + diagnostic, + poison, + const Diagnostics = enum { + ignored, + warning, + @"error", + fatal, + push, + pop, + }; +}; + +fn beforePreprocess(pragma: *Pragma, comp: *Compilation) void { + var self = @fieldParentPtr(GCC, "pragma", pragma); + self.original_options = comp.diag.options; +} + +fn beforeParse(pragma: *Pragma, comp: *Compilation) void { + var self = @fieldParentPtr(GCC, "pragma", pragma); + comp.diag.options = self.original_options; + self.options_stack.items.len = 0; +} + +fn afterParse(pragma: *Pragma, comp: *Compilation) void { + var self = @fieldParentPtr(GCC, "pragma", pragma); + comp.diag.options = self.original_options; + self.options_stack.items.len = 0; +} + +pub fn init(allocator: mem.Allocator) !*Pragma { + var gcc = try allocator.create(GCC); + gcc.* = .{}; + return &gcc.pragma; +} + +fn deinit(pragma: *Pragma, comp: *Compilation) void { + var self = @fieldParentPtr(GCC, "pragma", pragma); + self.options_stack.deinit(comp.gpa); + comp.gpa.destroy(self); +} + +fn diagnosticHandler(self: *GCC, pp: *Preprocessor, start_idx: TokenIndex) Pragma.Error!void { + const diagnostic_tok = pp.tokens.get(start_idx); + if (diagnostic_tok.id == .nl) return; + + const diagnostic = std.meta.stringToEnum(Directive.Diagnostics, pp.expandedSlice(diagnostic_tok)) orelse + return error.UnknownPragma; + + switch (diagnostic) { + .ignored, .warning, .@"error", .fatal => { + const str = Pragma.pasteTokens(pp, start_idx + 1) catch |err| switch (err) { + error.ExpectedStringLiteral => { + return pp.comp.diag.add(.{ + .tag = .pragma_requires_string_literal, + .loc = diagnostic_tok.loc, + .extra = .{ .str = "GCC diagnostic" }, + }, diagnostic_tok.expansionSlice()); + }, + else => |e| return e, + }; + if (!mem.startsWith(u8, str, "-W")) { + const next = pp.tokens.get(start_idx + 1); + return pp.comp.diag.add(.{ + .tag = .malformed_warning_check, + .loc = next.loc, + .extra = .{ .str = "GCC diagnostic" }, + }, next.expansionSlice()); + } + const new_kind = switch (diagnostic) { + .ignored => Diagnostics.Kind.off, + .warning => Diagnostics.Kind.warning, + .@"error" => Diagnostics.Kind.@"error", + .fatal => Diagnostics.Kind.@"fatal error", + else => unreachable, + }; + + try pp.comp.diag.set(str[2..], new_kind); + }, + .push => try self.options_stack.append(pp.comp.gpa, pp.comp.diag.options), + .pop => pp.comp.diag.options = self.options_stack.popOrNull() orelse self.original_options, + } +} + +fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) Pragma.Error!void { + var self = @fieldParentPtr(GCC, "pragma", pragma); + const directive_tok = pp.tokens.get(start_idx + 1); + if (directive_tok.id == .nl) return; + + const gcc_pragma = std.meta.stringToEnum(Directive, pp.expandedSlice(directive_tok)) orelse + return pp.comp.diag.add(.{ + .tag = .unknown_gcc_pragma, + .loc = directive_tok.loc, + }, directive_tok.expansionSlice()); + + switch (gcc_pragma) { + .warning, .@"error" => { + const text = Pragma.pasteTokens(pp, start_idx + 2) catch |err| switch (err) { + error.ExpectedStringLiteral => { + return pp.comp.diag.add(.{ + .tag = .pragma_requires_string_literal, + .loc = directive_tok.loc, + .extra = .{ .str = @tagName(gcc_pragma) }, + }, directive_tok.expansionSlice()); + }, + else => |e| return e, + }; + const extra = Diagnostics.Message.Extra{ .str = try pp.comp.diag.arena.allocator().dupe(u8, text) }; + const diagnostic_tag: Diagnostics.Tag = if (gcc_pragma == .warning) .pragma_warning_message else .pragma_error_message; + return pp.comp.diag.add( + .{ .tag = diagnostic_tag, .loc = directive_tok.loc, .extra = extra }, + directive_tok.expansionSlice(), + ); + }, + .diagnostic => return self.diagnosticHandler(pp, start_idx + 2) catch |err| switch (err) { + error.UnknownPragma => { + const tok = pp.tokens.get(start_idx + 2); + return pp.comp.diag.add(.{ + .tag = .unknown_gcc_pragma_directive, + .loc = tok.loc, + }, tok.expansionSlice()); + }, + else => |e| return e, + }, + .poison => { + var i: usize = 2; + while (true) : (i += 1) { + const tok = pp.tokens.get(start_idx + i); + if (tok.id == .nl) break; + + if (!tok.id.isMacroIdentifier()) { + return pp.comp.diag.add(.{ + .tag = .pragma_poison_identifier, + .loc = tok.loc, + }, tok.expansionSlice()); + } + const str = pp.expandedSlice(tok); + if (pp.defines.get(str) != null) { + try pp.comp.diag.add(.{ + .tag = .pragma_poison_macro, + .loc = tok.loc, + }, tok.expansionSlice()); + } + try pp.poisoned_identifiers.put(str, {}); + } + return; + }, + } +} + +fn parserHandler(pragma: *Pragma, p: *Parser, start_idx: TokenIndex) Compilation.Error!void { + var self = @fieldParentPtr(GCC, "pragma", pragma); + const directive_tok = p.pp.tokens.get(start_idx + 1); + if (directive_tok.id == .nl) return; + const name = p.pp.expandedSlice(directive_tok); + if (mem.eql(u8, name, "diagnostic")) { + return self.diagnosticHandler(p.pp, start_idx + 2) catch |err| switch (err) { + error.UnknownPragma => {}, // handled during preprocessing + error.StopPreprocessing => unreachable, // Only used by #pragma once + else => |e| return e, + }; + } +} + +fn preserveTokens(_: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) bool { + const next = pp.tokens.get(start_idx + 1); + if (next.id != .nl) { + const name = pp.expandedSlice(next); + if (mem.eql(u8, name, "poison")) { + return false; + } + } + return true; +} diff --git a/deps/aro/pragmas/message.zig b/deps/aro/pragmas/message.zig new file mode 100644 index 000000000000..42752516c3c5 --- /dev/null +++ b/deps/aro/pragmas/message.zig @@ -0,0 +1,50 @@ +const std = @import("std"); +const mem = std.mem; +const Compilation = @import("../Compilation.zig"); +const Pragma = @import("../Pragma.zig"); +const Diagnostics = @import("../Diagnostics.zig"); +const Preprocessor = @import("../Preprocessor.zig"); +const Parser = @import("../Parser.zig"); +const TokenIndex = @import("../Tree.zig").TokenIndex; +const Source = @import("../Source.zig"); + +const Message = @This(); + +pragma: Pragma = .{ + .deinit = deinit, + .preprocessorHandler = preprocessorHandler, +}, + +pub fn init(allocator: mem.Allocator) !*Pragma { + var once = try allocator.create(Message); + once.* = .{}; + return &once.pragma; +} + +fn deinit(pragma: *Pragma, comp: *Compilation) void { + var self = @fieldParentPtr(Message, "pragma", pragma); + comp.gpa.destroy(self); +} + +fn preprocessorHandler(_: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) Pragma.Error!void { + const message_tok = pp.tokens.get(start_idx); + const message_expansion_locs = message_tok.expansionSlice(); + + const str = Pragma.pasteTokens(pp, start_idx + 1) catch |err| switch (err) { + error.ExpectedStringLiteral => { + return pp.comp.diag.add(.{ + .tag = .pragma_requires_string_literal, + .loc = message_tok.loc, + .extra = .{ .str = "message" }, + }, message_expansion_locs); + }, + else => |e| return e, + }; + + const loc = if (message_expansion_locs.len != 0) + message_expansion_locs[message_expansion_locs.len - 1] + else + message_tok.loc; + const extra = Diagnostics.Message.Extra{ .str = try pp.comp.diag.arena.allocator().dupe(u8, str) }; + return pp.comp.diag.add(.{ .tag = .pragma_message, .loc = loc, .extra = extra }, &.{}); +} diff --git a/deps/aro/pragmas/once.zig b/deps/aro/pragmas/once.zig new file mode 100644 index 000000000000..c2de2efc1da3 --- /dev/null +++ b/deps/aro/pragmas/once.zig @@ -0,0 +1,56 @@ +const std = @import("std"); +const mem = std.mem; +const Compilation = @import("../Compilation.zig"); +const Pragma = @import("../Pragma.zig"); +const Diagnostics = @import("../Diagnostics.zig"); +const Preprocessor = @import("../Preprocessor.zig"); +const Parser = @import("../Parser.zig"); +const TokenIndex = @import("../Tree.zig").TokenIndex; +const Source = @import("../Source.zig"); + +const Once = @This(); + +pragma: Pragma = .{ + .afterParse = afterParse, + .deinit = deinit, + .preprocessorHandler = preprocessorHandler, +}, +pragma_once: std.AutoHashMap(Source.Id, void), +preprocess_count: u32 = 0, + +pub fn init(allocator: mem.Allocator) !*Pragma { + var once = try allocator.create(Once); + once.* = .{ + .pragma_once = std.AutoHashMap(Source.Id, void).init(allocator), + }; + return &once.pragma; +} + +fn afterParse(pragma: *Pragma, _: *Compilation) void { + var self = @fieldParentPtr(Once, "pragma", pragma); + self.pragma_once.clearRetainingCapacity(); +} + +fn deinit(pragma: *Pragma, comp: *Compilation) void { + var self = @fieldParentPtr(Once, "pragma", pragma); + self.pragma_once.deinit(); + comp.gpa.destroy(self); +} + +fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) Pragma.Error!void { + var self = @fieldParentPtr(Once, "pragma", pragma); + const name_tok = pp.tokens.get(start_idx); + const next = pp.tokens.get(start_idx + 1); + if (next.id != .nl) { + try pp.comp.diag.add(.{ + .tag = .extra_tokens_directive_end, + .loc = name_tok.loc, + }, next.expansionSlice()); + } + const seen = self.preprocess_count == pp.preprocess_count; + const prev = try self.pragma_once.fetchPut(name_tok.loc.id, {}); + if (prev != null and !seen) { + return error.StopPreprocessing; + } + self.preprocess_count = pp.preprocess_count; +} diff --git a/deps/aro/pragmas/pack.zig b/deps/aro/pragmas/pack.zig new file mode 100644 index 000000000000..20ec25eb2960 --- /dev/null +++ b/deps/aro/pragmas/pack.zig @@ -0,0 +1,164 @@ +const std = @import("std"); +const mem = std.mem; +const Compilation = @import("../Compilation.zig"); +const Pragma = @import("../Pragma.zig"); +const Diagnostics = @import("../Diagnostics.zig"); +const Preprocessor = @import("../Preprocessor.zig"); +const Parser = @import("../Parser.zig"); +const Tree = @import("../Tree.zig"); +const TokenIndex = Tree.TokenIndex; + +const Pack = @This(); + +pragma: Pragma = .{ + .deinit = deinit, + .parserHandler = parserHandler, + .preserveTokens = preserveTokens, +}, +stack: std.ArrayListUnmanaged(struct { label: []const u8, val: u8 }) = .{}, + +pub fn init(allocator: mem.Allocator) !*Pragma { + var pack = try allocator.create(Pack); + pack.* = .{}; + return &pack.pragma; +} + +fn deinit(pragma: *Pragma, comp: *Compilation) void { + var self = @fieldParentPtr(Pack, "pragma", pragma); + self.stack.deinit(comp.gpa); + comp.gpa.destroy(self); +} + +fn parserHandler(pragma: *Pragma, p: *Parser, start_idx: TokenIndex) Compilation.Error!void { + var pack = @fieldParentPtr(Pack, "pragma", pragma); + var idx = start_idx + 1; + const l_paren = p.pp.tokens.get(idx); + if (l_paren.id != .l_paren) { + return p.pp.comp.diag.add(.{ + .tag = .pragma_pack_lparen, + .loc = l_paren.loc, + }, l_paren.expansionSlice()); + } + idx += 1; + + // TODO -fapple-pragma-pack -fxl-pragma-pack + const apple_or_xl = false; + const tok_ids = p.pp.tokens.items(.id); + const arg = idx; + switch (tok_ids[arg]) { + .identifier => { + idx += 1; + const Action = enum { + show, + push, + pop, + }; + const action = std.meta.stringToEnum(Action, p.tokSlice(arg)) orelse { + return p.errTok(.pragma_pack_unknown_action, arg); + }; + switch (action) { + .show => { + try p.errExtra(.pragma_pack_show, arg, .{ .unsigned = p.pragma_pack orelse 8 }); + }, + .push, .pop => { + var new_val: ?u8 = null; + var label: ?[]const u8 = null; + if (tok_ids[idx] == .comma) { + idx += 1; + const next = idx; + idx += 1; + switch (tok_ids[next]) { + .pp_num => new_val = (try packInt(p, next)) orelse return, + .identifier => { + label = p.tokSlice(next); + if (tok_ids[idx] == .comma) { + idx += 1; + const int = idx; + idx += 1; + if (tok_ids[int] != .pp_num) return p.errTok(.pragma_pack_int_ident, int); + new_val = (try packInt(p, int)) orelse return; + } + }, + else => return p.errTok(.pragma_pack_int_ident, next), + } + } + if (action == .push) { + try pack.stack.append(p.pp.comp.gpa, .{ .label = label orelse "", .val = p.pragma_pack orelse 8 }); + } else { + pack.pop(p, label); + if (new_val != null) { + try p.errTok(.pragma_pack_undefined_pop, arg); + } else if (pack.stack.items.len == 0) { + try p.errTok(.pragma_pack_empty_stack, arg); + } + } + if (new_val) |some| { + p.pragma_pack = some; + } + }, + } + }, + .r_paren => if (apple_or_xl) { + pack.pop(p, null); + } else { + p.pragma_pack = null; + }, + .pp_num => { + const new_val = (try packInt(p, arg)) orelse return; + idx += 1; + if (apple_or_xl) { + try pack.stack.append(p.pp.comp.gpa, .{ .label = "", .val = p.pragma_pack }); + } + p.pragma_pack = new_val; + }, + else => {}, + } + + if (tok_ids[idx] != .r_paren) { + return p.errTok(.pragma_pack_rparen, idx); + } +} + +fn packInt(p: *Parser, tok_i: TokenIndex) Compilation.Error!?u8 { + const res = p.parseNumberToken(tok_i) catch |err| switch (err) { + error.ParsingFailed => { + try p.errTok(.pragma_pack_int, tok_i); + return null; + }, + else => |e| return e, + }; + const int = if (res.val.tag == .int) res.val.getInt(u64) else 99; + switch (int) { + 1, 2, 4, 8, 16 => return @intCast(int), + else => { + try p.errTok(.pragma_pack_int, tok_i); + return null; + }, + } +} + +fn pop(pack: *Pack, p: *Parser, maybe_label: ?[]const u8) void { + if (maybe_label) |label| { + var i = pack.stack.items.len; + while (i > 0) { + i -= 1; + if (std.mem.eql(u8, pack.stack.items[i].label, label)) { + const prev = pack.stack.orderedRemove(i); + p.pragma_pack = prev.val; + return; + } + } + } else { + const prev = pack.stack.popOrNull() orelse { + p.pragma_pack = 2; + return; + }; + p.pragma_pack = prev.val; + } +} + +fn preserveTokens(_: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) bool { + _ = pp; + _ = start_idx; + return true; +} diff --git a/deps/aro/record_layout.zig b/deps/aro/record_layout.zig new file mode 100644 index 000000000000..c24cfd9d469f --- /dev/null +++ b/deps/aro/record_layout.zig @@ -0,0 +1,669 @@ +//! Record layout code adapted from https://github.com/mahkoh/repr-c +//! Licensed under MIT license: https://github.com/mahkoh/repr-c/tree/master/repc/facade + +const std = @import("std"); +const Type = @import("Type.zig"); +const Attribute = @import("Attribute.zig"); +const Compilation = @import("Compilation.zig"); +const Parser = @import("Parser.zig"); +const Record = Type.Record; +const Field = Record.Field; +const TypeLayout = Type.TypeLayout; +const FieldLayout = Type.FieldLayout; +const target_util = @import("target.zig"); + +const BITS_PER_BYTE = 8; + +const OngoingBitfield = struct { + size_bits: u64, + unused_size_bits: u64, +}; + +const SysVContext = struct { + /// Does the record have an __attribute__((packed)) annotation. + attr_packed: bool, + /// The value of #pragma pack(N) at the type level if any. + max_field_align_bits: ?u64, + /// The alignment of this record. + aligned_bits: u32, + is_union: bool, + /// The size of the record. This might not be a multiple of 8 if the record contains bit-fields. + /// For structs, this is also the offset of the first bit after the last field. + size_bits: u64, + /// non-null if the previous field was a non-zero-sized bit-field. Only used by MinGW. + ongoing_bitfield: ?OngoingBitfield, + + comp: *const Compilation, + + fn init(ty: Type, comp: *const Compilation, pragma_pack: ?u8) SysVContext { + var pack_value: ?u64 = null; + if (pragma_pack) |pak| { + pack_value = pak * BITS_PER_BYTE; + } + var req_align: u29 = BITS_PER_BYTE; + if (ty.requestedAlignment(comp)) |aln| { + req_align = aln * BITS_PER_BYTE; + } + return SysVContext{ + .attr_packed = ty.hasAttribute(.@"packed"), + .max_field_align_bits = pack_value, + .aligned_bits = req_align, + .is_union = ty.is(.@"union"), + .size_bits = 0, + .comp = comp, + .ongoing_bitfield = null, + }; + } + + fn layoutFields(self: *SysVContext, rec: *const Record) void { + for (rec.fields, 0..) |*fld, fld_indx| { + const type_layout = computeLayout(fld.ty, self.comp); + + var field_attrs: ?[]const Attribute = null; + if (rec.field_attributes) |attrs| { + field_attrs = attrs[fld_indx]; + } + if (self.comp.target.isMinGW()) { + fld.layout = self.layoutMinGWField(fld, field_attrs, type_layout); + } else { + if (fld.isRegularField()) { + fld.layout = self.layoutRegularField(field_attrs, type_layout); + } else { + fld.layout = self.layoutBitField(field_attrs, type_layout, fld.isNamed(), fld.specifiedBitWidth()); + } + } + } + } + + /// On MinGW the alignment of the field is calculated in the usual way except that the alignment of + /// the underlying type is ignored in three cases + /// - the field is packed + /// - the field is a bit-field and the previous field was a non-zero-sized bit-field with the same type size + /// - the field is a zero-sized bit-field and the previous field was not a non-zero-sized bit-field + /// See test case 0068. + fn ignoreTypeAlignment(is_attr_packed: bool, bit_width: ?u32, ongoing_bitfield: ?OngoingBitfield, fld_layout: TypeLayout) bool { + if (is_attr_packed) return true; + if (bit_width) |width| { + if (ongoing_bitfield) |ongoing| { + if (ongoing.size_bits == fld_layout.size_bits) return true; + } else { + if (width == 0) return true; + } + } + return false; + } + + fn layoutMinGWField( + self: *SysVContext, + field: *const Field, + field_attrs: ?[]const Attribute, + field_layout: TypeLayout, + ) FieldLayout { + const annotation_alignment_bits = BITS_PER_BYTE * (Type.annotationAlignment(self.comp, field_attrs) orelse 1); + const is_attr_packed = self.attr_packed or isPacked(field_attrs); + const ignore_type_alignment = ignoreTypeAlignment(is_attr_packed, field.bit_width, self.ongoing_bitfield, field_layout); + + var field_alignment_bits: u64 = field_layout.field_alignment_bits; + if (ignore_type_alignment) { + field_alignment_bits = BITS_PER_BYTE; + } + field_alignment_bits = @max(field_alignment_bits, annotation_alignment_bits); + if (self.max_field_align_bits) |bits| { + field_alignment_bits = @min(field_alignment_bits, bits); + } + + // The field affects the record alignment in one of three cases + // - the field is a regular field + // - the field is a zero-width bit-field following a non-zero-width bit-field + // - the field is a non-zero-width bit-field and not packed. + // See test case 0069. + const update_record_alignment = + field.isRegularField() or + (field.specifiedBitWidth() == 0 and self.ongoing_bitfield != null) or + (field.specifiedBitWidth() != 0 and !is_attr_packed); + + // If a field affects the alignment of a record, the alignment is calculated in the + // usual way except that __attribute__((packed)) is ignored on a zero-width bit-field. + // See test case 0068. + if (update_record_alignment) { + var ty_alignment_bits = field_layout.field_alignment_bits; + if (is_attr_packed and (field.isRegularField() or field.specifiedBitWidth() != 0)) { + ty_alignment_bits = BITS_PER_BYTE; + } + ty_alignment_bits = @max(ty_alignment_bits, annotation_alignment_bits); + if (self.max_field_align_bits) |bits| { + ty_alignment_bits = @intCast(@min(ty_alignment_bits, bits)); + } + self.aligned_bits = @max(self.aligned_bits, ty_alignment_bits); + } + + // NOTE: ty_alignment_bits and field_alignment_bits are different in the following case: + // Y = { size: 64, alignment: 64 }struct { + // { offset: 0, size: 1 }c { size: 8, alignment: 8 }char:1, + // @attr_packed _ { size: 64, alignment: 64 }long long:0, + // { offset: 8, size: 8 }d { size: 8, alignment: 8 }char, + // } + if (field.isRegularField()) { + return self.layoutRegularFieldMinGW(field_layout.size_bits, field_alignment_bits); + } else { + return self.layoutBitFieldMinGW(field_layout.size_bits, field_alignment_bits, field.isNamed(), field.specifiedBitWidth()); + } + } + + fn layoutBitFieldMinGW( + self: *SysVContext, + ty_size_bits: u64, + field_alignment_bits: u64, + is_named: bool, + width: u64, + ) FieldLayout { + std.debug.assert(width <= ty_size_bits); // validated in parser + + // In a union, the size of the underlying type does not affect the size of the union. + // See test case 0070. + if (self.is_union) { + self.size_bits = @max(self.size_bits, width); + if (!is_named) return .{}; + return .{ + .offset_bits = 0, + .size_bits = width, + }; + } + if (width == 0) { + self.ongoing_bitfield = null; + } else { + // If there is an ongoing bit-field in a struct whose underlying type has the same size and + // if there is enough space left to place this bit-field, then this bit-field is placed in + // the ongoing bit-field and the size of the struct is not affected by this + // bit-field. See test case 0037. + if (self.ongoing_bitfield) |*ongoing| { + if (ongoing.size_bits == ty_size_bits and ongoing.unused_size_bits >= width) { + const offset_bits = self.size_bits - ongoing.unused_size_bits; + ongoing.unused_size_bits -= width; + if (!is_named) return .{}; + return .{ + .offset_bits = offset_bits, + .size_bits = width, + }; + } + } + // Otherwise this field is part of a new ongoing bit-field. + self.ongoing_bitfield = .{ + .size_bits = ty_size_bits, + .unused_size_bits = ty_size_bits - width, + }; + } + const offset_bits = std.mem.alignForward(u64, self.size_bits, field_alignment_bits); + self.size_bits = if (width == 0) offset_bits else offset_bits + ty_size_bits; + if (!is_named) return .{}; + return .{ + .offset_bits = offset_bits, + .size_bits = width, + }; + } + + fn layoutRegularFieldMinGW( + self: *SysVContext, + ty_size_bits: u64, + field_alignment_bits: u64, + ) FieldLayout { + self.ongoing_bitfield = null; + // A struct field starts at the next offset in the struct that is properly + // aligned with respect to the start of the struct. See test case 0033. + // A union field always starts at offset 0. + const offset_bits = if (self.is_union) 0 else std.mem.alignForward(u64, self.size_bits, field_alignment_bits); + + // Set the size of the record to the maximum of the current size and the end of + // the field. See test case 0034. + self.size_bits = @max(self.size_bits, offset_bits + ty_size_bits); + + return .{ + .offset_bits = offset_bits, + .size_bits = ty_size_bits, + }; + } + + fn layoutRegularField( + self: *SysVContext, + fld_attrs: ?[]const Attribute, + fld_layout: TypeLayout, + ) FieldLayout { + var fld_align_bits = fld_layout.field_alignment_bits; + + // If the struct or the field is packed, then the alignment of the underlying type is + // ignored. See test case 0084. + if (self.attr_packed or isPacked(fld_attrs)) { + fld_align_bits = BITS_PER_BYTE; + } + + // The field alignment can be increased by __attribute__((aligned)) annotations on the + // field. See test case 0085. + if (Type.annotationAlignment(self.comp, fld_attrs)) |anno| { + fld_align_bits = @max(fld_align_bits, anno * BITS_PER_BYTE); + } + + // #pragma pack takes precedence over all other attributes. See test cases 0084 and + // 0085. + if (self.max_field_align_bits) |req_bits| { + fld_align_bits = @intCast(@min(fld_align_bits, req_bits)); + } + + // A struct field starts at the next offset in the struct that is properly + // aligned with respect to the start of the struct. + const offset_bits = if (self.is_union) 0 else std.mem.alignForward(u64, self.size_bits, fld_align_bits); + const size_bits = fld_layout.size_bits; + + // The alignment of a record is the maximum of its field alignments. See test cases + // 0084, 0085, 0086. + self.size_bits = @max(self.size_bits, offset_bits + size_bits); + self.aligned_bits = @max(self.aligned_bits, fld_align_bits); + + return .{ + .offset_bits = offset_bits, + .size_bits = size_bits, + }; + } + + fn layoutBitField( + self: *SysVContext, + fld_attrs: ?[]const Attribute, + fld_layout: TypeLayout, + is_named: bool, + bit_width: u64, + ) FieldLayout { + const ty_size_bits = fld_layout.size_bits; + var ty_fld_algn_bits: u32 = fld_layout.field_alignment_bits; + + if (bit_width > 0) { + std.debug.assert(bit_width <= ty_size_bits); // Checked in parser + // Some targets ignore the alignment of the underlying type when laying out + // non-zero-sized bit-fields. See test case 0072. On such targets, bit-fields never + // cross a storage boundary. See test case 0081. + if (target_util.ignoreNonZeroSizedBitfieldTypeAlignment(self.comp.target)) { + ty_fld_algn_bits = 1; + } + } else { + // Some targets ignore the alignment of the underlying type when laying out + // zero-sized bit-fields. See test case 0073. + if (target_util.ignoreZeroSizedBitfieldTypeAlignment(self.comp.target)) { + ty_fld_algn_bits = 1; + } + // Some targets have a minimum alignment of zero-sized bit-fields. See test case + // 0074. + if (target_util.minZeroWidthBitfieldAlignment(self.comp.target)) |target_align| { + ty_fld_algn_bits = @max(ty_fld_algn_bits, target_align); + } + } + + // __attribute__((packed)) on the record is identical to __attribute__((packed)) on each + // field. See test case 0067. + const attr_packed = self.attr_packed or isPacked(fld_attrs); + const has_packing_annotation = attr_packed or self.max_field_align_bits != null; + + const annotation_alignment: u32 = if (Type.annotationAlignment(self.comp, fld_attrs)) |anno| anno * BITS_PER_BYTE else 1; + + const first_unused_bit: u64 = if (self.is_union) 0 else self.size_bits; + var field_align_bits: u64 = 1; + + if (bit_width == 0) { + field_align_bits = @max(ty_fld_algn_bits, annotation_alignment); + } else if (self.comp.langopts.emulate == .gcc) { + // On GCC, the field alignment is at least the alignment requested by annotations + // except as restricted by #pragma pack. See test case 0083. + field_align_bits = annotation_alignment; + if (self.max_field_align_bits) |max_bits| { + field_align_bits = @min(annotation_alignment, max_bits); + } + + // On GCC, if there are no packing annotations and + // - the field would otherwise start at an offset such that it would cross a + // storage boundary or + // - the alignment of the type is larger than its size, + // then it is aligned to the type's field alignment. See test case 0083. + if (!has_packing_annotation) { + const start_bit = std.mem.alignForward(u64, first_unused_bit, field_align_bits); + + const does_field_cross_boundary = start_bit % ty_fld_algn_bits + bit_width > ty_size_bits; + + if (ty_fld_algn_bits > ty_size_bits or does_field_cross_boundary) { + field_align_bits = @max(field_align_bits, ty_fld_algn_bits); + } + } + } else { + std.debug.assert(self.comp.langopts.emulate == .clang); + + // On Clang, the alignment requested by annotations is not respected if it is + // larger than the value of #pragma pack. See test case 0083. + if (annotation_alignment <= self.max_field_align_bits orelse std.math.maxInt(u29)) { + field_align_bits = @max(field_align_bits, annotation_alignment); + } + // On Clang, if there are no packing annotations and the field would cross a + // storage boundary if it were positioned at the first unused bit in the record, + // it is aligned to the type's field alignment. See test case 0083. + if (!has_packing_annotation) { + const does_field_cross_boundary = first_unused_bit % ty_fld_algn_bits + bit_width > ty_size_bits; + + if (does_field_cross_boundary) + field_align_bits = @max(field_align_bits, ty_fld_algn_bits); + } + } + + const offset_bits = std.mem.alignForward(u64, first_unused_bit, field_align_bits); + self.size_bits = @max(self.size_bits, offset_bits + bit_width); + + // Unnamed fields do not contribute to the record alignment except on a few targets. + // See test case 0079. + if (is_named or target_util.unnamedFieldAffectsAlignment(self.comp.target)) { + var inherited_align_bits: u32 = undefined; + + if (bit_width == 0) { + // If the width is 0, #pragma pack and __attribute__((packed)) are ignored. + // See test case 0075. + inherited_align_bits = @max(ty_fld_algn_bits, annotation_alignment); + } else if (self.max_field_align_bits) |max_align_bits| { + // Otherwise, if a #pragma pack is in effect, __attribute__((packed)) on the field or + // record is ignored. See test case 0076. + inherited_align_bits = @max(ty_fld_algn_bits, annotation_alignment); + inherited_align_bits = @intCast(@min(inherited_align_bits, max_align_bits)); + } else if (attr_packed) { + // Otherwise, if the field or the record is packed, the field alignment is 1 bit unless + // it is explicitly increased with __attribute__((aligned)). See test case 0077. + inherited_align_bits = annotation_alignment; + } else { + // Otherwise, the field alignment is the field alignment of the underlying type unless + // it is explicitly increased with __attribute__((aligned)). See test case 0078. + inherited_align_bits = @max(ty_fld_algn_bits, annotation_alignment); + } + self.aligned_bits = @max(self.aligned_bits, inherited_align_bits); + } + + if (!is_named) return .{}; + return .{ + .size_bits = bit_width, + .offset_bits = offset_bits, + }; + } +}; + +const MsvcContext = struct { + req_align_bits: u32, + max_field_align_bits: ?u32, + /// The alignment of pointers that point to an object of this type. This is greater than or equal + /// to the required alignment. Once all fields have been laid out, the size of the record will be + /// rounded up to this value. + pointer_align_bits: u32, + /// The alignment of this type when it is used as a record field. This is greater than or equal to + /// the pointer alignment. + field_align_bits: u32, + size_bits: u64, + ongoing_bitfield: ?OngoingBitfield, + contains_non_bitfield: bool, + is_union: bool, + comp: *const Compilation, + + fn init(ty: Type, comp: *const Compilation, pragma_pack: ?u8) MsvcContext { + var pack_value: ?u32 = null; + if (ty.hasAttribute(.@"packed")) { + // __attribute__((packed)) behaves like #pragma pack(1) in clang. See test case 0056. + pack_value = BITS_PER_BYTE; + } + if (pack_value == null) { + if (pragma_pack) |pack| { + pack_value = pack * BITS_PER_BYTE; + } + } + if (pack_value) |pack| { + pack_value = msvcPragmaPack(comp, pack); + } + + // The required alignment can be increased by adding a __declspec(align) + // annotation. See test case 0023. + var must_align: u29 = BITS_PER_BYTE; + if (ty.requestedAlignment(comp)) |req_align| { + must_align = req_align * BITS_PER_BYTE; + } + return MsvcContext{ + .req_align_bits = must_align, + .pointer_align_bits = must_align, + .field_align_bits = must_align, + .size_bits = 0, + .max_field_align_bits = pack_value, + .ongoing_bitfield = null, + .contains_non_bitfield = false, + .is_union = ty.is(.@"union"), + .comp = comp, + }; + } + + fn layoutField(self: *MsvcContext, fld: *const Field, fld_attrs: ?[]const Attribute) FieldLayout { + const type_layout = computeLayout(fld.ty, self.comp); + + // The required alignment of the field is the maximum of the required alignment of the + // underlying type and the __declspec(align) annotation on the field itself. + // See test case 0028. + var req_align = type_layout.required_alignment_bits; + if (Type.annotationAlignment(self.comp, fld_attrs)) |anno| { + req_align = @max(anno * BITS_PER_BYTE, req_align); + } + + // The required alignment of a record is the maximum of the required alignments of its + // fields except that the required alignment of bitfields is ignored. + // See test case 0029. + if (fld.isRegularField()) { + self.req_align_bits = @max(self.req_align_bits, req_align); + } + + // The offset of the field is based on the field alignment of the underlying type. + // See test case 0027. + var fld_align_bits = type_layout.field_alignment_bits; + if (self.max_field_align_bits) |max_align| { + fld_align_bits = @min(fld_align_bits, max_align); + } + // check the requested alignment of the field type. + if (fld.ty.requestedAlignment(self.comp)) |type_req_align| { + fld_align_bits = @max(fld_align_bits, type_req_align * 8); + } + + if (isPacked(fld_attrs)) { + // __attribute__((packed)) on a field is a clang extension. It behaves as if #pragma + // pack(1) had been applied only to this field. See test case 0057. + fld_align_bits = BITS_PER_BYTE; + } + // __attribute__((packed)) on a field is a clang extension. It behaves as if #pragma + // pack(1) had been applied only to this field. See test case 0057. + fld_align_bits = @max(fld_align_bits, req_align); + if (fld.isRegularField()) { + return self.layoutRegularField(type_layout.size_bits, fld_align_bits); + } else { + return self.layoutBitField(type_layout.size_bits, fld_align_bits, fld.specifiedBitWidth()); + } + } + + fn layoutBitField(self: *MsvcContext, ty_size_bits: u64, field_align: u32, bit_width: u32) FieldLayout { + if (bit_width == 0) { + // A zero-sized bit-field that does not follow a non-zero-sized bit-field does not affect + // the overall layout of the record. Even in a union where the order would otherwise + // not matter. See test case 0035. + if (self.ongoing_bitfield) |_| { + self.ongoing_bitfield = null; + } else { + // this field takes 0 space. + return .{ .offset_bits = self.size_bits, .size_bits = bit_width }; + } + } else { + std.debug.assert(bit_width <= ty_size_bits); + // If there is an ongoing bit-field in a struct whose underlying type has the same size and + // if there is enough space left to place this bit-field, then this bit-field is placed in + // the ongoing bit-field and the overall layout of the struct is not affected by this + // bit-field. See test case 0037. + if (!self.is_union) { + if (self.ongoing_bitfield) |*p| { + if (p.size_bits == ty_size_bits and p.unused_size_bits >= bit_width) { + const offset_bits = self.size_bits - p.unused_size_bits; + p.unused_size_bits -= bit_width; + return .{ .offset_bits = offset_bits, .size_bits = bit_width }; + } + } + } + // Otherwise this field is part of a new ongoing bit-field. + self.ongoing_bitfield = .{ .size_bits = ty_size_bits, .unused_size_bits = ty_size_bits - bit_width }; + } + const offset_bits = if (!self.is_union) bits: { + // This is the one place in the layout of a record where the pointer alignment might + // get assigned a smaller value than the field alignment. This can only happen if + // the field or the type of the field has a required alignment. Otherwise the value + // of field_alignment_bits is already bound by max_field_alignment_bits. + // See test case 0038. + const p_align = if (self.max_field_align_bits) |max_fld_align| + @min(max_fld_align, field_align) + else + field_align; + self.pointer_align_bits = @max(self.pointer_align_bits, p_align); + self.field_align_bits = @max(self.field_align_bits, field_align); + + const offset_bits = std.mem.alignForward(u64, self.size_bits, field_align); + self.size_bits = if (bit_width == 0) offset_bits else offset_bits + ty_size_bits; + + break :bits offset_bits; + } else bits: { + // Bit-fields do not affect the alignment of a union. See test case 0041. + self.size_bits = @max(self.size_bits, ty_size_bits); + break :bits 0; + }; + return .{ .offset_bits = offset_bits, .size_bits = bit_width }; + } + + fn layoutRegularField(self: *MsvcContext, size_bits: u64, field_align: u32) FieldLayout { + self.contains_non_bitfield = true; + self.ongoing_bitfield = null; + // The alignment of the field affects both the pointer alignment and the field + // alignment of the record. See test case 0032. + self.pointer_align_bits = @max(self.pointer_align_bits, field_align); + self.field_align_bits = @max(self.field_align_bits, field_align); + const offset_bits = switch (self.is_union) { + true => 0, + false => std.mem.alignForward(u64, self.size_bits, field_align), + }; + self.size_bits = @max(self.size_bits, offset_bits + size_bits); + return .{ .offset_bits = offset_bits, .size_bits = size_bits }; + } + fn handleZeroSizedRecord(self: *MsvcContext) void { + if (self.is_union) { + // MSVC does not allow unions without fields. + // If all fields in a union have size 0, the size of the union is set to + // - its field alignment if it contains at least one non-bitfield + // - 4 bytes if it contains only bitfields + // See test case 0025. + if (self.contains_non_bitfield) { + self.size_bits = self.field_align_bits; + } else { + self.size_bits = 4 * BITS_PER_BYTE; + } + } else { + // If all fields in a struct have size 0, its size is set to its required alignment + // but at least to 4 bytes. See test case 0026. + self.size_bits = @max(self.req_align_bits, 4 * BITS_PER_BYTE); + self.pointer_align_bits = @intCast(@min(self.pointer_align_bits, self.size_bits)); + } + } +}; + +pub fn compute(rec: *Type.Record, ty: Type, comp: *const Compilation, pragma_pack: ?u8) void { + switch (comp.langopts.emulate) { + .gcc, .clang => { + var context = SysVContext.init(ty, comp, pragma_pack); + + context.layoutFields(rec); + + context.size_bits = std.mem.alignForward(u64, context.size_bits, context.aligned_bits); + + rec.type_layout = .{ + .size_bits = context.size_bits, + .field_alignment_bits = context.aligned_bits, + .pointer_alignment_bits = context.aligned_bits, + .required_alignment_bits = BITS_PER_BYTE, + }; + }, + .msvc => { + var context = MsvcContext.init(ty, comp, pragma_pack); + for (rec.fields, 0..) |*fld, fld_indx| { + var field_attrs: ?[]const Attribute = null; + if (rec.field_attributes) |attrs| { + field_attrs = attrs[fld_indx]; + } + + fld.layout = context.layoutField(fld, field_attrs); + } + if (context.size_bits == 0) { + // As an extension, MSVC allows records that only contain zero-sized bitfields and empty + // arrays. Such records would be zero-sized but this case is handled here separately to + // ensure that there are no zero-sized records. + context.handleZeroSizedRecord(); + } + context.size_bits = std.mem.alignForward(u64, context.size_bits, context.pointer_align_bits); + rec.type_layout = .{ + .size_bits = context.size_bits, + .field_alignment_bits = context.field_align_bits, + .pointer_alignment_bits = context.pointer_align_bits, + .required_alignment_bits = context.req_align_bits, + }; + }, + } +} + +fn computeLayout(ty: Type, comp: *const Compilation) TypeLayout { + if (ty.getRecord()) |rec| { + const requested = BITS_PER_BYTE * (ty.requestedAlignment(comp) orelse 0); + return .{ + .size_bits = rec.type_layout.size_bits, + .pointer_alignment_bits = @max(requested, rec.type_layout.pointer_alignment_bits), + .field_alignment_bits = @max(requested, rec.type_layout.field_alignment_bits), + .required_alignment_bits = rec.type_layout.required_alignment_bits, + }; + } else { + const type_align = ty.alignof(comp) * BITS_PER_BYTE; + return .{ + .size_bits = ty.bitSizeof(comp) orelse 0, + .pointer_alignment_bits = type_align, + .field_alignment_bits = type_align, + .required_alignment_bits = BITS_PER_BYTE, + }; + } +} + +fn isPacked(attrs: ?[]const Attribute) bool { + const a = attrs orelse return false; + + for (a) |attribute| { + if (attribute.tag != .@"packed") continue; + return true; + } + return false; +} + +// The effect of #pragma pack(N) depends on the target. +// +// x86: By default, there is no maximum field alignment. N={1,2,4} set the maximum field +// alignment to that value. All other N activate the default. +// x64: By default, there is no maximum field alignment. N={1,2,4,8} set the maximum field +// alignment to that value. All other N activate the default. +// arm: By default, the maximum field alignment is 8. N={1,2,4,8,16} set the maximum field +// alignment to that value. All other N activate the default. +// arm64: By default, the maximum field alignment is 8. N={1,2,4,8} set the maximum field +// alignment to that value. N=16 disables the maximum field alignment. All other N +// activate the default. +// +// See test case 0020. +pub fn msvcPragmaPack(comp: *const Compilation, pack: u32) ?u32 { + return switch (pack) { + 8, 16, 32 => pack, + 64 => if (comp.target.cpu.arch == .x86) null else pack, + 128 => if (comp.target.cpu.arch == .thumb) pack else null, + else => { + return switch (comp.target.cpu.arch) { + .thumb, .aarch64 => 64, + else => null, + }; + }, + }; +} diff --git a/deps/aro/target.zig b/deps/aro/target.zig new file mode 100644 index 000000000000..d3612a772b4d --- /dev/null +++ b/deps/aro/target.zig @@ -0,0 +1,810 @@ +const std = @import("std"); +const LangOpts = @import("LangOpts.zig"); +const Type = @import("Type.zig"); +const llvm = @import("zig").codegen.llvm; +const TargetSet = @import("builtins/Properties.zig").TargetSet; + +/// intmax_t for this target +pub fn intMaxType(target: std.Target) Type { + switch (target.cpu.arch) { + .aarch64, + .aarch64_be, + .sparc64, + => if (target.os.tag != .openbsd) return .{ .specifier = .long }, + + .bpfel, + .bpfeb, + .loongarch64, + .riscv64, + .powerpc64, + .powerpc64le, + .tce, + .tcele, + .ve, + => return .{ .specifier = .long }, + + .x86_64 => switch (target.os.tag) { + .windows, .openbsd => {}, + else => switch (target.abi) { + .gnux32, .muslx32 => {}, + else => return .{ .specifier = .long }, + }, + }, + + else => {}, + } + return .{ .specifier = .long_long }; +} + +/// intptr_t for this target +pub fn intPtrType(target: std.Target) Type { + switch (target.os.tag) { + .haiku => return .{ .specifier = .long }, + .nacl => return .{ .specifier = .int }, + else => {}, + } + + switch (target.cpu.arch) { + .aarch64, .aarch64_be => switch (target.os.tag) { + .windows => return .{ .specifier = .long_long }, + else => {}, + }, + + .msp430, + .csky, + .loongarch32, + .riscv32, + .xcore, + .hexagon, + .tce, + .tcele, + .m68k, + .spir, + .spirv32, + .arc, + .avr, + => return .{ .specifier = .int }, + + .sparc, .sparcel => switch (target.os.tag) { + .netbsd, .openbsd => {}, + else => return .{ .specifier = .int }, + }, + + .powerpc, .powerpcle => switch (target.os.tag) { + .linux, .freebsd, .netbsd => return .{ .specifier = .int }, + else => {}, + }, + + // 32-bit x86 Darwin, OpenBSD, and RTEMS use long (the default); others use int + .x86 => switch (target.os.tag) { + .openbsd, .rtems => {}, + else => if (!target.os.tag.isDarwin()) return .{ .specifier = .int }, + }, + + .x86_64 => switch (target.os.tag) { + .windows => return .{ .specifier = .long_long }, + else => switch (target.abi) { + .gnux32, .muslx32 => return .{ .specifier = .int }, + else => {}, + }, + }, + + else => {}, + } + + return .{ .specifier = .long }; +} + +/// int16_t for this target +pub fn int16Type(target: std.Target) Type { + return switch (target.cpu.arch) { + .avr => .{ .specifier = .int }, + else => .{ .specifier = .short }, + }; +} + +/// int64_t for this target +pub fn int64Type(target: std.Target) Type { + switch (target.cpu.arch) { + .loongarch64, + .ve, + .riscv64, + .powerpc64, + .powerpc64le, + .bpfel, + .bpfeb, + => return .{ .specifier = .long }, + + .sparc64 => return intMaxType(target), + + .x86, .x86_64 => if (!target.isDarwin()) return intMaxType(target), + .aarch64, .aarch64_be => if (!target.isDarwin() and target.os.tag != .openbsd and target.os.tag != .windows) return .{ .specifier = .long }, + else => {}, + } + return .{ .specifier = .long_long }; +} + +/// This function returns 1 if function alignment is not observable or settable. +pub fn defaultFunctionAlignment(target: std.Target) u8 { + return switch (target.cpu.arch) { + .arm, .armeb => 4, + .aarch64, .aarch64_32, .aarch64_be => 4, + .sparc, .sparcel, .sparc64 => 4, + .riscv64 => 2, + else => 1, + }; +} + +pub fn isTlsSupported(target: std.Target) bool { + if (target.isDarwin()) { + var supported = false; + switch (target.os.tag) { + .macos => supported = !(target.os.isAtLeast(.macos, .{ .major = 10, .minor = 7, .patch = 0 }) orelse false), + else => {}, + } + return supported; + } + return switch (target.cpu.arch) { + .tce, .tcele, .bpfel, .bpfeb, .msp430, .nvptx, .nvptx64, .x86, .arm, .armeb, .thumb, .thumbeb => false, + else => true, + }; +} + +pub fn ignoreNonZeroSizedBitfieldTypeAlignment(target: std.Target) bool { + switch (target.cpu.arch) { + .avr => return true, + .arm => { + if (std.Target.arm.featureSetHas(target.cpu.features, .has_v7)) { + switch (target.os.tag) { + .ios => return true, + else => return false, + } + } + }, + else => return false, + } + return false; +} + +pub fn ignoreZeroSizedBitfieldTypeAlignment(target: std.Target) bool { + switch (target.cpu.arch) { + .avr => return true, + else => return false, + } +} + +pub fn minZeroWidthBitfieldAlignment(target: std.Target) ?u29 { + switch (target.cpu.arch) { + .avr => return 8, + .arm => { + if (std.Target.arm.featureSetHas(target.cpu.features, .has_v7)) { + switch (target.os.tag) { + .ios => return 32, + else => return null, + } + } else return null; + }, + else => return null, + } +} + +pub fn unnamedFieldAffectsAlignment(target: std.Target) bool { + switch (target.cpu.arch) { + .aarch64 => { + if (target.isDarwin() or target.os.tag == .windows) return false; + return true; + }, + .armeb => { + if (std.Target.arm.featureSetHas(target.cpu.features, .has_v7)) { + if (std.Target.Abi.default(target.cpu.arch, target.os) == .eabi) return true; + } + }, + .arm => return true, + .avr => return true, + .thumb => { + if (target.os.tag == .windows) return false; + return true; + }, + else => return false, + } + return false; +} + +pub fn packAllEnums(target: std.Target) bool { + return switch (target.cpu.arch) { + .hexagon => true, + else => false, + }; +} + +/// Default alignment (in bytes) for __attribute__((aligned)) when no alignment is specified +pub fn defaultAlignment(target: std.Target) u29 { + switch (target.cpu.arch) { + .avr => return 1, + .arm => if (target.isAndroid() or target.os.tag == .ios) return 16 else return 8, + .sparc => if (std.Target.sparc.featureSetHas(target.cpu.features, .v9)) return 16 else return 8, + .mips, .mipsel => switch (target.abi) { + .none, .gnuabi64 => return 16, + else => return 8, + }, + .s390x, .armeb, .thumbeb, .thumb => return 8, + else => return 16, + } +} +pub fn systemCompiler(target: std.Target) LangOpts.Compiler { + // Android is linux but not gcc, so these checks go first + // the rest for documentation as fn returns .clang + if (target.isDarwin() or + target.isAndroid() or + target.isBSD() or + target.os.tag == .fuchsia or + target.os.tag == .solaris or + target.os.tag == .haiku or + target.cpu.arch == .hexagon) + { + return .clang; + } + if (target.os.tag == .uefi) return .msvc; + // this is before windows to grab WindowsGnu + if (target.abi.isGnu() or + target.os.tag == .linux) + { + return .gcc; + } + if (target.os.tag == .windows) { + return .msvc; + } + if (target.cpu.arch == .avr) return .gcc; + return .clang; +} + +pub fn hasInt128(target: std.Target) bool { + if (target.cpu.arch == .wasm32) return true; + if (target.cpu.arch == .x86_64) return true; + return target.ptrBitWidth() >= 64; +} + +pub fn hasHalfPrecisionFloatABI(target: std.Target) bool { + return switch (target.cpu.arch) { + .thumb, .thumbeb, .arm, .aarch64 => true, + else => false, + }; +} + +pub const FPSemantics = enum { + None, + IEEEHalf, + BFloat, + IEEESingle, + IEEEDouble, + IEEEQuad, + /// Minifloat 5-bit exponent 2-bit mantissa + E5M2, + /// Minifloat 4-bit exponent 3-bit mantissa + E4M3, + x87ExtendedDouble, + IBMExtendedDouble, + + /// Only intended for generating float.h macros for the preprocessor + pub fn forType(ty: std.Target.CType, target: std.Target) FPSemantics { + std.debug.assert(ty == .float or ty == .double or ty == .longdouble); + return switch (target.c_type_bit_size(ty)) { + 32 => .IEEESingle, + 64 => .IEEEDouble, + 80 => .x87ExtendedDouble, + 128 => switch (target.cpu.arch) { + .powerpc, .powerpcle, .powerpc64, .powerpc64le => .IBMExtendedDouble, + else => .IEEEQuad, + }, + else => unreachable, + }; + } + + pub fn halfPrecisionType(target: std.Target) ?FPSemantics { + switch (target.cpu.arch) { + .aarch64, + .aarch64_32, + .aarch64_be, + .arm, + .armeb, + .hexagon, + .riscv32, + .riscv64, + .spirv32, + .spirv64, + => return .IEEEHalf, + .x86, .x86_64 => if (std.Target.x86.featureSetHas(target.cpu.features, .sse2)) return .IEEEHalf, + else => {}, + } + return null; + } + + pub fn chooseValue(self: FPSemantics, comptime T: type, values: [6]T) T { + return switch (self) { + .IEEEHalf => values[0], + .IEEESingle => values[1], + .IEEEDouble => values[2], + .x87ExtendedDouble => values[3], + .IBMExtendedDouble => values[4], + .IEEEQuad => values[5], + else => unreachable, + }; + } +}; + +pub fn isLP64(target: std.Target) bool { + return target.c_type_bit_size(.int) == 32 and target.ptrBitWidth() == 64; +} + +pub fn isKnownWindowsMSVCEnvironment(target: std.Target) bool { + return target.os.tag == .windows and target.abi == .msvc; +} + +pub fn isWindowsMSVCEnvironment(target: std.Target) bool { + return target.os.tag == .windows and (target.abi == .msvc or target.abi == .none); +} + +pub fn isCygwinMinGW(target: std.Target) bool { + return target.os.tag == .windows and (target.abi == .gnu or target.abi == .cygnus); +} + +pub fn builtinEnabled(target: std.Target, enabled_for: TargetSet) bool { + var copy = enabled_for; + var it = copy.iterator(); + while (it.next()) |val| { + switch (val) { + .basic => return true, + .x86_64 => if (target.cpu.arch == .x86_64) return true, + .aarch64 => if (target.cpu.arch == .aarch64) return true, + .arm => if (target.cpu.arch == .arm) return true, + .ppc => switch (target.cpu.arch) { + .powerpc, .powerpc64, .powerpc64le => return true, + else => {}, + }, + else => { + // Todo: handle other target predicates + }, + } + } + return false; +} + +pub fn defaultFpEvalMethod(target: std.Target) LangOpts.FPEvalMethod { + if (target.os.tag == .aix) return .double; + switch (target.cpu.arch) { + .x86, .x86_64 => { + if (target.ptrBitWidth() == 32 and target.os.tag == .netbsd) { + if (target.os.version_range.semver.min.order(.{ .major = 6, .minor = 99, .patch = 26 }) != .gt) { + // NETBSD <= 6.99.26 on 32-bit x86 defaults to double + return .double; + } + } + if (std.Target.x86.featureSetHas(target.cpu.features, .sse)) { + return .source; + } + return .extended; + }, + else => {}, + } + return .source; +} + +/// Value of the `-m` flag for `ld` for this target +pub fn ldEmulationOption(target: std.Target, arm_endianness: ?std.builtin.Endian) ?[]const u8 { + return switch (target.cpu.arch) { + .x86 => if (target.os.tag == .elfiamcu) "elf_iamcu" else "elf_i386", + .arm, + .armeb, + .thumb, + .thumbeb, + => switch (arm_endianness orelse target.cpu.arch.endian()) { + .Little => "armelf_linux_eabi", + .Big => "armelfb_linux_eabi", + }, + .aarch64 => "aarch64linux", + .aarch64_be => "aarch64linuxb", + .m68k => "m68kelf", + .powerpc => if (target.os.tag == .linux) "elf32ppclinux" else "elf32ppc", + .powerpcle => if (target.os.tag == .linux) "elf32lppclinux" else "elf32lppc", + .powerpc64 => "elf64ppc", + .powerpc64le => "elf64lppc", + .riscv32 => "elf32lriscv", + .riscv64 => "elf64lriscv", + .sparc, .sparcel => "elf32_sparc", + .sparc64 => "elf64_sparc", + .loongarch32 => "elf32loongarch", + .loongarch64 => "elf64loongarch", + .mips => "elf32btsmip", + .mipsel => "elf32ltsmip", + .mips64 => if (target.abi == .gnuabin32) "elf32btsmipn32" else "elf64btsmip", + .mips64el => if (target.abi == .gnuabin32) "elf32ltsmipn32" else "elf64ltsmip", + .x86_64 => if (target.abi == .gnux32 or target.abi == .muslx32) "elf32_x86_64" else "elf_x86_64", + .ve => "elf64ve", + .csky => "cskyelf_linux", + else => null, + }; +} + +pub fn get32BitArchVariant(target: std.Target) ?std.Target { + var copy = target; + switch (target.cpu.arch) { + .amdgcn, + .avr, + .msp430, + .spu_2, + .ve, + .bpfel, + .bpfeb, + .s390x, + => return null, + + .arc, + .arm, + .armeb, + .csky, + .hexagon, + .m68k, + .le32, + .mips, + .mipsel, + .powerpc, + .powerpcle, + .r600, + .riscv32, + .sparc, + .sparcel, + .tce, + .tcele, + .thumb, + .thumbeb, + .x86, + .xcore, + .nvptx, + .amdil, + .hsail, + .spir, + .kalimba, + .shave, + .lanai, + .wasm32, + .renderscript32, + .aarch64_32, + .spirv32, + .loongarch32, + .dxil, + .xtensa, + => {}, // Already 32 bit + + .aarch64 => copy.cpu.arch = .arm, + .aarch64_be => copy.cpu.arch = .armeb, + .le64 => copy.cpu.arch = .le32, + .amdil64 => copy.cpu.arch = .amdil, + .nvptx64 => copy.cpu.arch = .nvptx, + .wasm64 => copy.cpu.arch = .wasm32, + .hsail64 => copy.cpu.arch = .hsail, + .spir64 => copy.cpu.arch = .spir, + .spirv64 => copy.cpu.arch = .spirv32, + .renderscript64 => copy.cpu.arch = .renderscript32, + .loongarch64 => copy.cpu.arch = .loongarch32, + .mips64 => copy.cpu.arch = .mips, + .mips64el => copy.cpu.arch = .mipsel, + .powerpc64 => copy.cpu.arch = .powerpc, + .powerpc64le => copy.cpu.arch = .powerpcle, + .riscv64 => copy.cpu.arch = .riscv32, + .sparc64 => copy.cpu.arch = .sparc, + .x86_64 => copy.cpu.arch = .x86, + } + return copy; +} + +pub fn get64BitArchVariant(target: std.Target) ?std.Target { + var copy = target; + switch (target.cpu.arch) { + .arc, + .avr, + .csky, + .dxil, + .hexagon, + .kalimba, + .lanai, + .m68k, + .msp430, + .r600, + .shave, + .sparcel, + .spu_2, + .tce, + .tcele, + .xcore, + .xtensa, + => return null, + + .aarch64, + .aarch64_be, + .amdgcn, + .bpfeb, + .bpfel, + .le64, + .amdil64, + .nvptx64, + .wasm64, + .hsail64, + .spir64, + .spirv64, + .renderscript64, + .loongarch64, + .mips64, + .mips64el, + .powerpc64, + .powerpc64le, + .riscv64, + .s390x, + .sparc64, + .ve, + .x86_64, + => {}, // Already 64 bit + + .aarch64_32 => copy.cpu.arch = .aarch64, + .amdil => copy.cpu.arch = .amdil64, + .arm => copy.cpu.arch = .aarch64, + .armeb => copy.cpu.arch = .aarch64_be, + .hsail => copy.cpu.arch = .hsail64, + .le32 => copy.cpu.arch = .le64, + .loongarch32 => copy.cpu.arch = .loongarch64, + .mips => copy.cpu.arch = .mips64, + .mipsel => copy.cpu.arch = .mips64el, + .nvptx => copy.cpu.arch = .nvptx64, + .powerpc => copy.cpu.arch = .powerpc64, + .powerpcle => copy.cpu.arch = .powerpc64le, + .renderscript32 => copy.cpu.arch = .renderscript64, + .riscv32 => copy.cpu.arch = .riscv64, + .sparc => copy.cpu.arch = .sparc64, + .spir => copy.cpu.arch = .spir64, + .spirv32 => copy.cpu.arch = .spirv64, + .thumb => copy.cpu.arch = .aarch64, + .thumbeb => copy.cpu.arch = .aarch64_be, + .wasm32 => copy.cpu.arch = .wasm64, + .x86 => copy.cpu.arch = .x86_64, + } + return copy; +} + +/// Adapted from Zig's src/codegen/llvm.zig +pub fn toLLVMTriple(target: std.Target, buf: []u8) []const u8 { + // 64 bytes is assumed to be large enough to hold any target triple; increase if necessary + std.debug.assert(buf.len >= 64); + + var stream = std.io.fixedBufferStream(buf); + const writer = stream.writer(); + + const llvm_arch = switch (target.cpu.arch) { + .arm => "arm", + .armeb => "armeb", + .aarch64 => "aarch64", + .aarch64_be => "aarch64_be", + .aarch64_32 => "aarch64_32", + .arc => "arc", + .avr => "avr", + .bpfel => "bpfel", + .bpfeb => "bpfeb", + .csky => "csky", + .dxil => "dxil", + .hexagon => "hexagon", + .loongarch32 => "loongarch32", + .loongarch64 => "loongarch64", + .m68k => "m68k", + .mips => "mips", + .mipsel => "mipsel", + .mips64 => "mips64", + .mips64el => "mips64el", + .msp430 => "msp430", + .powerpc => "powerpc", + .powerpcle => "powerpcle", + .powerpc64 => "powerpc64", + .powerpc64le => "powerpc64le", + .r600 => "r600", + .amdgcn => "amdgcn", + .riscv32 => "riscv32", + .riscv64 => "riscv64", + .sparc => "sparc", + .sparc64 => "sparc64", + .sparcel => "sparcel", + .s390x => "s390x", + .tce => "tce", + .tcele => "tcele", + .thumb => "thumb", + .thumbeb => "thumbeb", + .x86 => "i386", + .x86_64 => "x86_64", + .xcore => "xcore", + .xtensa => "xtensa", + .nvptx => "nvptx", + .nvptx64 => "nvptx64", + .le32 => "le32", + .le64 => "le64", + .amdil => "amdil", + .amdil64 => "amdil64", + .hsail => "hsail", + .hsail64 => "hsail64", + .spir => "spir", + .spir64 => "spir64", + .spirv32 => "spirv32", + .spirv64 => "spirv64", + .kalimba => "kalimba", + .shave => "shave", + .lanai => "lanai", + .wasm32 => "wasm32", + .wasm64 => "wasm64", + .renderscript32 => "renderscript32", + .renderscript64 => "renderscript64", + .ve => "ve", + // Note: spu_2 is not supported in LLVM; this is the Zig arch name + .spu_2 => "spu_2", + }; + writer.writeAll(llvm_arch) catch unreachable; + writer.writeByte('-') catch unreachable; + + const llvm_os = switch (target.os.tag) { + .freestanding => "unknown", + .ananas => "ananas", + .cloudabi => "cloudabi", + .dragonfly => "dragonfly", + .freebsd => "freebsd", + .fuchsia => "fuchsia", + .kfreebsd => "kfreebsd", + .linux => "linux", + .lv2 => "lv2", + .netbsd => "netbsd", + .openbsd => "openbsd", + .solaris => "solaris", + .windows => "windows", + .zos => "zos", + .haiku => "haiku", + .minix => "minix", + .rtems => "rtems", + .nacl => "nacl", + .aix => "aix", + .cuda => "cuda", + .nvcl => "nvcl", + .amdhsa => "amdhsa", + .ps4 => "ps4", + .ps5 => "ps5", + .elfiamcu => "elfiamcu", + .mesa3d => "mesa3d", + .contiki => "contiki", + .amdpal => "amdpal", + .hermit => "hermit", + .hurd => "hurd", + .wasi => "wasi", + .emscripten => "emscripten", + .uefi => "windows", + .macos => "macosx", + .ios => "ios", + .tvos => "tvos", + .watchos => "watchos", + .driverkit => "driverkit", + .shadermodel => "shadermodel", + .opencl, + .glsl450, + .vulkan, + .plan9, + .other, + => "unknown", + }; + writer.writeAll(llvm_os) catch unreachable; + + if (target.os.tag.isDarwin()) { + const min_version = target.os.version_range.semver.min; + writer.print("{d}.{d}.{d}", .{ + min_version.major, + min_version.minor, + min_version.patch, + }) catch unreachable; + } + writer.writeByte('-') catch unreachable; + + const llvm_abi = switch (target.abi) { + .none => "unknown", + .gnu => "gnu", + .gnuabin32 => "gnuabin32", + .gnuabi64 => "gnuabi64", + .gnueabi => "gnueabi", + .gnueabihf => "gnueabihf", + .gnuf32 => "gnuf32", + .gnuf64 => "gnuf64", + .gnusf => "gnusf", + .gnux32 => "gnux32", + .gnuilp32 => "gnuilp32", + .code16 => "code16", + .eabi => "eabi", + .eabihf => "eabihf", + .android => "android", + .musl => "musl", + .musleabi => "musleabi", + .musleabihf => "musleabihf", + .muslx32 => "muslx32", + .msvc => "msvc", + .itanium => "itanium", + .cygnus => "cygnus", + .coreclr => "coreclr", + .simulator => "simulator", + .macabi => "macabi", + .pixel => "pixel", + .vertex => "vertex", + .geometry => "geometry", + .hull => "hull", + .domain => "domain", + .compute => "compute", + .library => "library", + .raygeneration => "raygeneration", + .intersection => "intersection", + .anyhit => "anyhit", + .closesthit => "closesthit", + .miss => "miss", + .callable => "callable", + .mesh => "mesh", + .amplification => "amplification", + }; + writer.writeAll(llvm_abi) catch unreachable; + return stream.getWritten(); +} + +test "alignment functions - smoke test" { + var target: std.Target = undefined; + const x86 = std.Target.Cpu.Arch.x86_64; + target.cpu = std.Target.Cpu.baseline(x86); + target.os = std.Target.Os.Tag.defaultVersionRange(.linux, x86); + target.abi = std.Target.Abi.default(x86, target.os); + + try std.testing.expect(isTlsSupported(target)); + try std.testing.expect(!ignoreNonZeroSizedBitfieldTypeAlignment(target)); + try std.testing.expect(minZeroWidthBitfieldAlignment(target) == null); + try std.testing.expect(!unnamedFieldAffectsAlignment(target)); + try std.testing.expect(defaultAlignment(target) == 16); + try std.testing.expect(!packAllEnums(target)); + try std.testing.expect(systemCompiler(target) == .gcc); + + const arm = std.Target.Cpu.Arch.arm; + target.cpu = std.Target.Cpu.baseline(arm); + target.os = std.Target.Os.Tag.defaultVersionRange(.ios, arm); + target.abi = std.Target.Abi.default(arm, target.os); + + try std.testing.expect(!isTlsSupported(target)); + try std.testing.expect(ignoreNonZeroSizedBitfieldTypeAlignment(target)); + try std.testing.expectEqual(@as(?u29, 32), minZeroWidthBitfieldAlignment(target)); + try std.testing.expect(unnamedFieldAffectsAlignment(target)); + try std.testing.expect(defaultAlignment(target) == 16); + try std.testing.expect(!packAllEnums(target)); + try std.testing.expect(systemCompiler(target) == .clang); +} + +test "target size/align tests" { + var comp: @import("Compilation.zig") = undefined; + + const x86 = std.Target.Cpu.Arch.x86; + comp.target.cpu.arch = x86; + comp.target.cpu.model = &std.Target.x86.cpu.i586; + comp.target.os = std.Target.Os.Tag.defaultVersionRange(.linux, x86); + comp.target.abi = std.Target.Abi.gnu; + + const tt: Type = .{ + .specifier = .long_long, + }; + + try std.testing.expectEqual(@as(u64, 8), tt.sizeof(&comp).?); + try std.testing.expectEqual(@as(u64, 4), tt.alignof(&comp)); + + const arm = std.Target.Cpu.Arch.arm; + comp.target.cpu = std.Target.Cpu.Model.toCpu(&std.Target.arm.cpu.cortex_r4, arm); + comp.target.os = std.Target.Os.Tag.defaultVersionRange(.ios, arm); + comp.target.abi = std.Target.Abi.none; + + const ct: Type = .{ + .specifier = .char, + }; + + try std.testing.expectEqual(true, std.Target.arm.featureSetHas(comp.target.cpu.features, .has_v7)); + try std.testing.expectEqual(@as(u64, 1), ct.sizeof(&comp).?); + try std.testing.expectEqual(@as(u64, 1), ct.alignof(&comp)); + try std.testing.expectEqual(true, ignoreNonZeroSizedBitfieldTypeAlignment(comp.target)); +} diff --git a/deps/aro/toolchains/Linux.zig b/deps/aro/toolchains/Linux.zig new file mode 100644 index 000000000000..7ec73204a763 --- /dev/null +++ b/deps/aro/toolchains/Linux.zig @@ -0,0 +1,482 @@ +const std = @import("std"); +const mem = std.mem; +const Compilation = @import("../Compilation.zig"); +const GCCDetector = @import("../Driver/GCCDetector.zig"); +const Toolchain = @import("../Toolchain.zig"); +const Driver = @import("../Driver.zig"); +const Distro = @import("../Driver/Distro.zig"); +const target_util = @import("../target.zig"); +const system_defaults = @import("system_defaults"); + +const Linux = @This(); + +distro: Distro.Tag = .unknown, +extra_opts: std.ArrayListUnmanaged([]const u8) = .{}, +gcc_detector: GCCDetector = .{}, + +pub fn discover(self: *Linux, tc: *Toolchain) !void { + self.distro = Distro.detect(tc.getTarget(), tc.filesystem); + try self.gcc_detector.discover(tc); + tc.selected_multilib = self.gcc_detector.selected; + + try self.gcc_detector.appendToolPath(tc); + try self.buildExtraOpts(tc); + try self.findPaths(tc); +} + +fn buildExtraOpts(self: *Linux, tc: *const Toolchain) !void { + const gpa = tc.driver.comp.gpa; + const target = tc.getTarget(); + const is_android = target.isAndroid(); + if (self.distro.isAlpine() or is_android) { + try self.extra_opts.ensureUnusedCapacity(gpa, 2); + self.extra_opts.appendAssumeCapacity("-z"); + self.extra_opts.appendAssumeCapacity("now"); + } + + if (self.distro.isOpenSUSE() or self.distro.isUbuntu() or self.distro.isAlpine() or is_android) { + try self.extra_opts.ensureUnusedCapacity(gpa, 2); + self.extra_opts.appendAssumeCapacity("-z"); + self.extra_opts.appendAssumeCapacity("relro"); + } + + if (target.cpu.arch.isARM() or target.cpu.arch.isAARCH64() or is_android) { + try self.extra_opts.ensureUnusedCapacity(gpa, 2); + self.extra_opts.appendAssumeCapacity("-z"); + self.extra_opts.appendAssumeCapacity("max-page-size=4096"); + } + + if (target.cpu.arch == .arm or target.cpu.arch == .thumb) { + try self.extra_opts.append(gpa, "-X"); + } + + if (!target.cpu.arch.isMIPS() and target.cpu.arch != .hexagon) { + const hash_style = if (is_android) .both else self.distro.getHashStyle(); + try self.extra_opts.append(gpa, switch (hash_style) { + inline else => |tag| "--hash-style=" ++ @tagName(tag), + }); + } + + if (system_defaults.enable_linker_build_id) { + try self.extra_opts.append(gpa, "--build-id"); + } +} + +fn addMultiLibPaths(self: *Linux, tc: *Toolchain, sysroot: []const u8, os_lib_dir: []const u8) !void { + if (!self.gcc_detector.is_valid) return; + const gcc_triple = self.gcc_detector.gcc_triple; + const lib_path = self.gcc_detector.parent_lib_path; + + // Add lib/gcc/$triple/$version, with an optional /multilib suffix. + try tc.addPathIfExists(&.{ self.gcc_detector.install_path, tc.selected_multilib.gcc_suffix }, .file); + + // Add lib/gcc/$triple/$libdir + // For GCC built with --enable-version-specific-runtime-libs. + try tc.addPathIfExists(&.{ self.gcc_detector.install_path, "..", os_lib_dir }, .file); + + try tc.addPathIfExists(&.{ lib_path, "..", gcc_triple, "lib", "..", os_lib_dir, tc.selected_multilib.os_suffix }, .file); + + // If the GCC installation we found is inside of the sysroot, we want to + // prefer libraries installed in the parent prefix of the GCC installation. + // It is important to *not* use these paths when the GCC installation is + // outside of the system root as that can pick up unintended libraries. + // This usually happens when there is an external cross compiler on the + // host system, and a more minimal sysroot available that is the target of + // the cross. Note that GCC does include some of these directories in some + // configurations but this seems somewhere between questionable and simply + // a bug. + if (mem.startsWith(u8, lib_path, sysroot)) { + try tc.addPathIfExists(&.{ lib_path, "..", os_lib_dir }, .file); + } +} + +fn addMultiArchPaths(self: *Linux, tc: *Toolchain) !void { + if (!self.gcc_detector.is_valid) return; + const lib_path = self.gcc_detector.parent_lib_path; + const gcc_triple = self.gcc_detector.gcc_triple; + const multilib = self.gcc_detector.selected; + try tc.addPathIfExists(&.{ lib_path, "..", gcc_triple, "lib", multilib.os_suffix }, .file); +} + +/// TODO: Very incomplete +fn findPaths(self: *Linux, tc: *Toolchain) !void { + const target = tc.getTarget(); + const sysroot = tc.getSysroot(); + + var output: [64]u8 = undefined; + + const os_lib_dir = getOSLibDir(target); + const multiarch_triple = getMultiarchTriple(target) orelse target_util.toLLVMTriple(target, &output); + + try self.addMultiLibPaths(tc, sysroot, os_lib_dir); + + try tc.addPathIfExists(&.{ sysroot, "/lib", multiarch_triple }, .file); + try tc.addPathIfExists(&.{ sysroot, "/lib", "..", os_lib_dir }, .file); + + if (target.isAndroid()) { + // TODO + } + try tc.addPathIfExists(&.{ sysroot, "/usr", "lib", multiarch_triple }, .file); + try tc.addPathIfExists(&.{ sysroot, "/usr", "lib", "..", os_lib_dir }, .file); + + try self.addMultiArchPaths(tc); + + try tc.addPathIfExists(&.{ sysroot, "/lib" }, .file); + try tc.addPathIfExists(&.{ sysroot, "/usr", "lib" }, .file); +} + +pub fn deinit(self: *Linux, allocator: std.mem.Allocator) void { + self.extra_opts.deinit(allocator); +} + +fn isPIEDefault(self: *const Linux) bool { + _ = self; + return false; +} + +fn getPIE(self: *const Linux, d: *const Driver) bool { + if (d.shared or d.static or d.relocatable or d.static_pie) { + return false; + } + return d.pie orelse self.isPIEDefault(); +} + +fn getStaticPIE(self: *const Linux, d: *Driver) !bool { + _ = self; + if (d.static_pie and d.pie != null) { + try d.err("cannot specify 'nopie' along with 'static-pie'"); + } + return d.static_pie; +} + +fn getStatic(self: *const Linux, d: *const Driver) bool { + _ = self; + return d.static and !d.static_pie; +} + +pub fn getDefaultLinker(self: *const Linux, target: std.Target) []const u8 { + _ = self; + if (target.isAndroid()) { + return "ld.lld"; + } + return "ld"; +} + +pub fn buildLinkerArgs(self: *const Linux, tc: *const Toolchain, argv: *std.ArrayList([]const u8)) Compilation.Error!void { + const d = tc.driver; + const target = tc.getTarget(); + + const is_pie = self.getPIE(d); + const is_static_pie = try self.getStaticPIE(d); + const is_static = self.getStatic(d); + const is_android = target.isAndroid(); + const is_iamcu = target.os.tag == .elfiamcu; + const is_ve = target.cpu.arch == .ve; + const has_crt_begin_end_files = target.abi != .none; // TODO: clang checks for MIPS vendor + + if (is_pie) { + try argv.append("-pie"); + } + if (is_static_pie) { + try argv.appendSlice(&.{ "-static", "-pie", "--no-dynamic-linker", "-z", "text" }); + } + + if (d.rdynamic) { + try argv.append("-export-dynamic"); + } + + if (d.strip) { + try argv.append("-s"); + } + + try argv.appendSlice(self.extra_opts.items); + try argv.append("--eh-frame-hdr"); + + // Todo: Driver should parse `-EL`/`-EB` for arm to set endianness for arm targets + if (target_util.ldEmulationOption(d.comp.target, null)) |emulation| { + try argv.appendSlice(&.{ "-m", emulation }); + } else { + try d.err("Unknown target triple"); + return; + } + if (d.comp.target.cpu.arch.isRISCV()) { + try argv.append("-X"); + } + if (d.shared) { + try argv.append("-shared"); + } + if (is_static) { + try argv.append("-static"); + } else { + if (d.rdynamic) { + try argv.append("-export-dynamic"); + } + if (!d.shared and !is_static_pie and !d.relocatable) { + const dynamic_linker = d.comp.target.standardDynamicLinkerPath(); + // todo: check for --dyld-prefix + if (dynamic_linker.get()) |path| { + try argv.appendSlice(&.{ "-dynamic-linker", try tc.arena.dupe(u8, path) }); + } else { + try d.err("Could not find dynamic linker path"); + } + } + } + + try argv.appendSlice(&.{ "-o", d.output_name orelse "a.out" }); + + if (!d.nostdlib and !d.nostartfiles and !d.relocatable) { + if (!is_android and !is_iamcu) { + if (!d.shared) { + const crt1 = if (is_pie) + "Scrt1.o" + else if (is_static_pie) + "rcrt1.o" + else + "crt1.o"; + try argv.append(try tc.getFilePath(crt1)); + } + try argv.append(try tc.getFilePath("crti.o")); + } + if (is_ve) { + try argv.appendSlice(&.{ "-z", "max-page-size=0x4000000" }); + } + + if (is_iamcu) { + try argv.append(try tc.getFilePath("crt0.o")); + } else if (has_crt_begin_end_files) { + var path: []const u8 = ""; + if (tc.getRuntimeLibKind() == .compiler_rt and !is_android) { + const crt_begin = try tc.getCompilerRt("crtbegin", .object); + if (tc.filesystem.exists(crt_begin)) { + path = crt_begin; + } + } + if (path.len == 0) { + const crt_begin = if (tc.driver.shared) + if (is_android) "crtbegin_so.o" else "crtbeginS.o" + else if (is_static) + if (is_android) "crtbegin_static.o" else "crtbeginT.o" + else if (is_pie or is_static_pie) + if (is_android) "crtbegin_dynamic.o" else "crtbeginS.o" + else if (is_android) "crtbegin_dynamic.o" else "crtbegin.o"; + path = try tc.getFilePath(crt_begin); + } + try argv.append(path); + } + } + + // TODO add -L opts + // TODO add -u opts + + try tc.addFilePathLibArgs(argv); + + // TODO handle LTO + + try argv.appendSlice(d.link_objects.items); + + if (!d.nostdlib and !d.relocatable) { + if (!d.nodefaultlibs) { + if (is_static or is_static_pie) { + try argv.append("--start-group"); + } + try tc.addRuntimeLibs(argv); + + // TODO: add pthread if needed + if (!d.nolibc) { + try argv.append("-lc"); + } + if (is_iamcu) { + try argv.append("-lgloss"); + } + if (is_static or is_static_pie) { + try argv.append("--end-group"); + } else { + try tc.addRuntimeLibs(argv); + } + if (is_iamcu) { + try argv.appendSlice(&.{ "--as-needed", "-lsoftfp", "--no-as-needed" }); + } + } + if (!d.nostartfiles and !is_iamcu) { + if (has_crt_begin_end_files) { + var path: []const u8 = ""; + if (tc.getRuntimeLibKind() == .compiler_rt and !is_android) { + const crt_end = try tc.getCompilerRt("crtend", .object); + if (tc.filesystem.exists(crt_end)) { + path = crt_end; + } + } + if (path.len == 0) { + const crt_end = if (d.shared) + if (is_android) "crtend_so.o" else "crtendS.o" + else if (is_pie or is_static_pie) + if (is_android) "crtend_android.o" else "crtendS.o" + else if (is_android) "crtend_android.o" else "crtend.o"; + path = try tc.getFilePath(crt_end); + } + try argv.append(path); + } + if (!is_android) { + try argv.append(try tc.getFilePath("crtn.o")); + } + } + } + + // TODO add -T args +} + +fn getMultiarchTriple(target: std.Target) ?[]const u8 { + const is_android = target.isAndroid(); + const is_mips_r6 = std.Target.mips.featureSetHas(target.cpu.features, .mips32r6); + return switch (target.cpu.arch) { + .arm, .thumb => if (is_android) "arm-linux-androideabi" else if (target.abi == .gnueabihf) "arm-linux-gnueabihf" else "arm-linux-gnueabi", + .armeb, .thumbeb => if (target.abi == .gnueabihf) "armeb-linux-gnueabihf" else "armeb-linux-gnueabi", + .aarch64 => if (is_android) "aarch64-linux-android" else "aarch64-linux-gnu", + .aarch64_be => "aarch64_be-linux-gnu", + .x86 => if (is_android) "i686-linux-android" else "i386-linux-gnu", + .x86_64 => if (is_android) "x86_64-linux-android" else if (target.abi == .gnux32) "x86_64-linux-gnux32" else "x86_64-linux-gnu", + .m68k => "m68k-linux-gnu", + .mips => if (is_mips_r6) "mipsisa32r6-linux-gnu" else "mips-linux-gnu", + .mipsel => if (is_android) "mipsel-linux-android" else if (is_mips_r6) "mipsisa32r6el-linux-gnu" else "mipsel-linux-gnu", + .powerpcle => "powerpcle-linux-gnu", + .powerpc64 => "powerpc64-linux-gnu", + .powerpc64le => "powerpc64le-linux-gnu", + .riscv64 => "riscv64-linux-gnu", + .sparc => "sparc-linux-gnu", + .sparc64 => "sparc64-linux-gnu", + .s390x => "s390x-linux-gnu", + + // TODO: expand this + else => null, + }; +} + +fn getOSLibDir(target: std.Target) []const u8 { + switch (target.cpu.arch) { + .x86, + .powerpc, + .powerpcle, + .sparc, + .sparcel, + => return "lib32", + else => {}, + } + if (target.cpu.arch == .x86_64 and (target.abi == .gnux32 or target.abi == .muslx32)) { + return "libx32"; + } + if (target.cpu.arch == .riscv32) { + return "lib32"; + } + if (target.ptrBitWidth() == 32) { + return "lib"; + } + return "lib64"; +} + +test Linux { + if (@import("builtin").os.tag == .windows) return error.SkipZigTest; + + var arena_instance = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena_instance.deinit(); + const arena = arena_instance.allocator(); + + var comp = Compilation.init(std.testing.allocator); + defer comp.deinit(); + comp.environment = .{ + .path = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + }; + + const raw_triple = "x86_64-linux-gnu"; + const cross = std.zig.CrossTarget.parse(.{ .arch_os_abi = raw_triple }) catch unreachable; + comp.target = cross.toTarget(); // TODO deprecated + comp.langopts.setEmulatedCompiler(.gcc); + + var driver: Driver = .{ .comp = &comp }; + defer driver.deinit(); + driver.raw_target_triple = raw_triple; + + const link_obj = try driver.comp.gpa.dupe(u8, "/tmp/foo.o"); + try driver.link_objects.append(driver.comp.gpa, link_obj); + driver.temp_file_count += 1; + + var toolchain: Toolchain = .{ .driver = &driver, .arena = arena, .filesystem = .{ .fake = &.{ + .{ .path = "/tmp" }, + .{ .path = "/usr" }, + .{ .path = "/usr/lib64" }, + .{ .path = "/usr/bin" }, + .{ .path = "/usr/bin/ld", .executable = true }, + .{ .path = "/lib" }, + .{ .path = "/lib/x86_64-linux-gnu" }, + .{ .path = "/lib/x86_64-linux-gnu/crt1.o" }, + .{ .path = "/lib/x86_64-linux-gnu/crti.o" }, + .{ .path = "/lib/x86_64-linux-gnu/crtn.o" }, + .{ .path = "/lib64" }, + .{ .path = "/usr/lib" }, + .{ .path = "/usr/lib/gcc" }, + .{ .path = "/usr/lib/gcc/x86_64-linux-gnu" }, + .{ .path = "/usr/lib/gcc/x86_64-linux-gnu/9" }, + .{ .path = "/usr/lib/gcc/x86_64-linux-gnu/9/crtbegin.o" }, + .{ .path = "/usr/lib/gcc/x86_64-linux-gnu/9/crtend.o" }, + .{ .path = "/usr/lib/x86_64-linux-gnu" }, + .{ .path = "/etc/lsb-release", .contents = + \\DISTRIB_ID=Ubuntu + \\DISTRIB_RELEASE=20.04 + \\DISTRIB_CODENAME=focal + \\DISTRIB_DESCRIPTION="Ubuntu 20.04.6 LTS" + \\ + }, + } } }; + defer toolchain.deinit(); + + try toolchain.discover(); + + var argv = std.ArrayList([]const u8).init(driver.comp.gpa); + defer argv.deinit(); + + var linker_path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + const linker_path = try toolchain.getLinkerPath(&linker_path_buf); + try argv.append(linker_path); + + try toolchain.buildLinkerArgs(&argv); + + const expected = [_][]const u8{ + "/usr/bin/ld", + "-z", + "relro", + "--hash-style=gnu", + "--eh-frame-hdr", + "-m", + "elf_x86_64", + "-dynamic-linker", + "/lib64/ld-linux-x86-64.so.2", + "-o", + "a.out", + "/lib/x86_64-linux-gnu/crt1.o", + "/lib/x86_64-linux-gnu/crti.o", + "/usr/lib/gcc/x86_64-linux-gnu/9/crtbegin.o", + "-L/usr/lib/gcc/x86_64-linux-gnu/9", + "-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib64", + "-L/lib/x86_64-linux-gnu", + "-L/lib/../lib64", + "-L/usr/lib/x86_64-linux-gnu", + "-L/usr/lib/../lib64", + "-L/lib", + "-L/usr/lib", + link_obj, + "-lgcc", + "--as-needed", + "-lgcc_s", + "--no-as-needed", + "-lc", + "-lgcc", + "--as-needed", + "-lgcc_s", + "--no-as-needed", + "/usr/lib/gcc/x86_64-linux-gnu/9/crtend.o", + "/lib/x86_64-linux-gnu/crtn.o", + }; + try std.testing.expectEqual(expected.len, argv.items.len); + for (expected, argv.items) |expected_item, actual_item| { + try std.testing.expectEqualStrings(expected_item, actual_item); + } +} diff --git a/deps/aro/unicode.zig b/deps/aro/unicode.zig new file mode 100644 index 000000000000..3b467f2a8807 --- /dev/null +++ b/deps/aro/unicode.zig @@ -0,0 +1,41 @@ +//! Copied from https://github.com/ziglang/zig/blob/6f0807f50f4e946bb850e746beaa5d6556cf7750/lib/std/unicode.zig +//! with all safety checks removed. These functions must only be called with known-good buffers that have already +//! been validated as being legitimate UTF8-encoded data, otherwise undefined behavior will occur. + +pub fn utf8ByteSequenceLength_unsafe(first_byte: u8) u3 { + return switch (first_byte) { + 0b0000_0000...0b0111_1111 => 1, + 0b1100_0000...0b1101_1111 => 2, + 0b1110_0000...0b1110_1111 => 3, + 0b1111_0000...0b1111_0111 => 4, + else => unreachable, + }; +} + +pub fn utf8Decode2_unsafe(bytes: []const u8) u21 { + var value: u21 = bytes[0] & 0b00011111; + value <<= 6; + return value | (bytes[1] & 0b00111111); +} + +pub fn utf8Decode3_unsafe(bytes: []const u8) u21 { + var value: u21 = bytes[0] & 0b00001111; + + value <<= 6; + value |= bytes[1] & 0b00111111; + + value <<= 6; + return value | (bytes[2] & 0b00111111); +} + +pub fn utf8Decode4_unsafe(bytes: []const u8) u21 { + var value: u21 = bytes[0] & 0b00000111; + value <<= 6; + value |= bytes[1] & 0b00111111; + + value <<= 6; + value |= bytes[2] & 0b00111111; + + value <<= 6; + return value | (bytes[3] & 0b00111111); +} diff --git a/deps/aro/util.zig b/deps/aro/util.zig new file mode 100644 index 000000000000..3f92f36a72bd --- /dev/null +++ b/deps/aro/util.zig @@ -0,0 +1,83 @@ +const std = @import("std"); +const mem = std.mem; +const builtin = @import("builtin"); +const is_windows = builtin.os.tag == .windows; + +pub const Color = enum { + reset, + red, + green, + blue, + cyan, + purple, + yellow, + white, +}; + +pub fn fileSupportsColor(file: std.fs.File) bool { + return file.supportsAnsiEscapeCodes() or (is_windows and file.isTty()); +} + +pub fn setColor(color: Color, w: anytype) void { + if (is_windows) { + const stderr_file = std.io.getStdErr(); + if (!stderr_file.isTty()) return; + const windows = std.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; + _ = windows.kernel32.GetConsoleScreenBufferInfo(stderr_file.handle, &info); + S.attrs = info.wAttributes; + _ = windows.kernel32.SetConsoleOutputCP(65001); + } + + // need to flush bufferedWriter + const T = if (@typeInfo(@TypeOf(w.context)) == .Pointer) @TypeOf(w.context.*) else @TypeOf(w.context); + if (T != void and @hasDecl(T, "flush")) w.context.flush() catch {}; + + switch (color) { + .reset => _ = windows.SetConsoleTextAttribute(stderr_file.handle, S.attrs) catch {}, + .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 {}, + .blue => _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {}, + .cyan => _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {}, + .purple => _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {}, + .yellow => _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY) catch {}, + .white => _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {}, + } + } else switch (color) { + .reset => w.writeAll("\x1b[0m") catch {}, + .red => w.writeAll("\x1b[31;1m") catch {}, + .green => w.writeAll("\x1b[32;1m") catch {}, + .blue => w.writeAll("\x1b[34;1m") catch {}, + .cyan => w.writeAll("\x1b[36;1m") catch {}, + .purple => w.writeAll("\x1b[35;1m") catch {}, + .yellow => w.writeAll("\x1b[93;1m") catch {}, + .white => w.writeAll("\x1b[0m\x1b[1m") catch {}, + } +} + +pub fn errorDescription(err: anyerror) []const u8 { + return switch (err) { + error.OutOfMemory => "ran out of memory", + error.FileNotFound => "file not found", + error.IsDir => "is a directory", + error.NotDir => "is not a directory", + error.NotOpenForReading => "file is not open for reading", + error.NotOpenForWriting => "file is not open for writing", + error.InvalidUtf8 => "input is not valid UTF-8", + error.FileBusy => "file is busy", + error.NameTooLong => "file name is too long", + error.AccessDenied => "access denied", + error.FileTooBig => "file is too big", + error.ProcessFdQuotaExceeded, error.SystemFdQuotaExceeded => "ran out of file descriptors", + error.SystemResources => "ran out of system resources", + error.FatalError => "a fatal error occurred", + error.Unexpected => "an unexpected error occurred", + else => @errorName(err), + }; +} diff --git a/src/Compilation.zig b/src/Compilation.zig index 71dff4a442ce..e2a1b9cb66b6 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -32,7 +32,6 @@ const Module = @import("Module.zig"); const InternPool = @import("InternPool.zig"); const BuildId = std.Build.CompileStep.BuildId; const Cache = std.Build.Cache; -const translate_c = @import("translate_c.zig"); const c_codegen = @import("codegen/c.zig"); const libtsan = @import("libtsan.zig"); const Zir = @import("Zir.zig"); @@ -88,7 +87,7 @@ failed_win32_resources: if (build_options.only_core_functionality) void else std misc_failures: std.AutoArrayHashMapUnmanaged(MiscTask, MiscError) = .{}, keep_source_files_loaded: bool, -use_clang: bool, +c_frontend: CFrontend, sanitize_c: bool, /// When this is `true` it means invoking clang as a sub-process is expected to inherit /// stdin, stdout, stderr, and if it returns non success, to forward the exit code. @@ -515,6 +514,8 @@ pub const cache_helpers = struct { } }; +pub const CFrontend = enum { clang, aro }; + pub const ClangPreprocessorMode = enum { no, /// This means we are doing `zig cc -E -o `. @@ -1046,14 +1047,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { break :pic explicit; } else pie or must_pic; - // Make a decision on whether to use Clang for translate-c and compiling C files. - const use_clang = if (options.use_clang) |explicit| explicit else blk: { - if (build_options.have_llvm) { - // Can't use it if we don't have it! - break :blk false; - } - // It's not planned to do our own translate-c or C compilation. - break :blk true; + // Make a decision on whether to use Clang or Aro for translate-c and compiling C files. + const c_frontend: CFrontend = blk: { + if (!build_options.have_llvm) break :blk .aro; + if (options.use_clang) |explicit| if (explicit) break :blk .clang; + break :blk .clang; }; const is_safe_mode = switch (options.optimize_mode) { @@ -1677,7 +1675,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .astgen_work_queue = std.fifo.LinearFifo(*Module.File, .Dynamic).init(gpa), .embed_file_work_queue = std.fifo.LinearFifo(*Module.EmbedFile, .Dynamic).init(gpa), .keep_source_files_loaded = options.keep_source_files_loaded, - .use_clang = use_clang, + .c_frontend = c_frontend, .clang_argv = options.clang_argv, .c_source_files = options.c_source_files, .rc_source_files = options.rc_source_files, @@ -3918,9 +3916,7 @@ pub const CImportResult = struct { /// This API is currently coupled pretty tightly to stage1's needs; it will need to be reworked /// a bit when we want to start using it from self-hosted. pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { - if (!build_options.have_llvm) - return error.ZigCompilerNotBuiltWithLLVMExtensions; - + if (build_options.only_c) unreachable; // @cImport is not needed for bootstrapping const tracy_trace = trace(@src()); defer tracy_trace.end(); @@ -3967,7 +3963,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { var argv = std.ArrayList([]const u8).init(comp.gpa); defer argv.deinit(); - try argv.append(""); // argv[0] is program name, actual args start at [1] + try argv.append(@tagName(comp.c_frontend)); // argv[0] is program name, actual args start at [1] try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path); try argv.append(out_h_path); @@ -3975,31 +3971,44 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { if (comp.verbose_cc) { dump_argv(argv.items); } + var tree = switch (comp.c_frontend) { + .aro => tree: { + if (builtin.zig_backend == .stage2_c) @panic("the CBE cannot compile Aro yet!"); + const translate_c = @import("aro_translate_c.zig"); + _ = translate_c; + if (true) @panic("TODO"); + break :tree undefined; + }, + .clang => tree: { + if (!build_options.have_llvm) unreachable; + const translate_c = @import("translate_c.zig"); + + // Convert to null terminated args. + const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, argv.items.len + 1); + new_argv_with_sentinel[argv.items.len] = null; + const new_argv = new_argv_with_sentinel[0..argv.items.len :null]; + for (argv.items, 0..) |arg, i| { + new_argv[i] = try arena.dupeZ(u8, arg); + } - // Convert to null terminated args. - const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, argv.items.len + 1); - new_argv_with_sentinel[argv.items.len] = null; - const new_argv = new_argv_with_sentinel[0..argv.items.len :null]; - for (argv.items, 0..) |arg, i| { - new_argv[i] = try arena.dupeZ(u8, arg); - } - - const c_headers_dir_path_z = try comp.zig_lib_directory.joinZ(arena, &[_][]const u8{"include"}); - var errors = std.zig.ErrorBundle.empty; - errdefer errors.deinit(comp.gpa); - var tree = translate_c.translate( - comp.gpa, - new_argv.ptr, - new_argv.ptr + new_argv.len, - &errors, - c_headers_dir_path_z, - ) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - error.SemanticAnalyzeFail => { - return CImportResult{ - .out_zig_path = "", - .cache_hit = actual_hit, - .errors = errors, + const c_headers_dir_path_z = try comp.zig_lib_directory.joinZ(arena, &[_][]const u8{"include"}); + var errors = std.zig.ErrorBundle.empty; + errdefer errors.deinit(comp.gpa); + break :tree translate_c.translate( + comp.gpa, + new_argv.ptr, + new_argv.ptr + new_argv.len, + &errors, + c_headers_dir_path_z, + ) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.SemanticAnalyzeFail => { + return CImportResult{ + .out_zig_path = "", + .cache_hit = actual_hit, + .errors = errors, + }; + }, }; }, }; @@ -4249,6 +4258,9 @@ fn reportRetryableEmbedFileError( } fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.Progress.Node) !void { + if (comp.c_frontend == .aro) { + return comp.failCObj(c_object, "aro does not support compiling C objects yet", .{}); + } if (!build_options.have_llvm) { return comp.failCObj(c_object, "clang not available: compiler built without LLVM extensions", .{}); } diff --git a/src/aro_translate_c.zig b/src/aro_translate_c.zig new file mode 100644 index 000000000000..5686c848bfdb --- /dev/null +++ b/src/aro_translate_c.zig @@ -0,0 +1,444 @@ +const std = @import("std"); +const mem = std.mem; +const assert = std.debug.assert; +const translate_c = @import("translate_c.zig"); +const aro = @import("aro"); +const Tree = aro.Tree; +const NodeIndex = Tree.NodeIndex; +const TokenIndex = Tree.TokenIndex; +const Type = aro.Type; +const ast = @import("translate_c/ast.zig"); +const ZigNode = ast.Node; +const ZigTag = ZigNode.Tag; +const common = @import("translate_c/common.zig"); +const Error = common.Error; +const MacroProcessingError = common.MacroProcessingError; +const TypeError = common.TypeError; +const TransError = common.TransError; +const SymbolTable = common.SymbolTable; +const AliasList = common.AliasList; +const ResultUsed = common.ResultUsed; +const Scope = common.ScopeExtra(Context, Type); + +pub const Compilation = aro.Compilation; + +const Context = struct { + gpa: mem.Allocator, + arena: mem.Allocator, + decl_table: std.AutoArrayHashMapUnmanaged(usize, []const u8) = .{}, + alias_list: AliasList, + global_scope: *Scope.Root, + mangle_count: u32 = 0, + /// Table of record decls that have been demoted to opaques. + opaque_demotes: std.AutoHashMapUnmanaged(usize, void) = .{}, + /// Table of unnamed enums and records that are child types of typedefs. + unnamed_typedefs: std.AutoHashMapUnmanaged(usize, []const u8) = .{}, + /// Needed to decide if we are parsing a typename + typedefs: std.StringArrayHashMapUnmanaged(void) = .{}, + + /// This one is different than the root scope's name table. This contains + /// a list of names that we found by visiting all the top level decls without + /// translating them. The other maps are updated as we translate; this one is updated + /// up front in a pre-processing step. + global_names: std.StringArrayHashMapUnmanaged(void) = .{}, + + /// This is similar to `global_names`, but contains names which we would + /// *like* to use, but do not strictly *have* to if they are unavailable. + /// These are relevant to types, which ideally we would name like + /// 'struct_foo' with an alias 'foo', but if either of those names is taken, + /// may be mangled. + /// This is distinct from `global_names` so we can detect at a type + /// declaration whether or not the name is available. + weak_global_names: std.StringArrayHashMapUnmanaged(void) = .{}, + + pattern_list: translate_c.PatternList, + tree: Tree, + comp: *Compilation, + mapper: aro.TypeMapper, + + fn getMangle(c: *Context) u32 { + c.mangle_count += 1; + return c.mangle_count; + } + + /// Convert a clang source location to a file:line:column string + fn locStr(c: *Context, loc: TokenIndex) ![]const u8 { + _ = c; + _ = loc; + // const spelling_loc = c.source_manager.getSpellingLoc(loc); + // const filename_c = c.source_manager.getFilename(spelling_loc); + // const filename = if (filename_c) |s| try c.str(s) else @as([]const u8, "(no file)"); + + // const line = c.source_manager.getSpellingLineNumber(spelling_loc); + // const column = c.source_manager.getSpellingColumnNumber(spelling_loc); + // return std.fmt.allocPrint(c.arena, "{s}:{d}:{d}", .{ filename, line, column }); + return "somewhere"; + } +}; + +fn maybeSuppressResult(c: *Context, used: ResultUsed, result: ZigNode) TransError!ZigNode { + if (used == .used) return result; + return ZigTag.discard.create(c.arena, .{ .should_skip = false, .value = result }); +} + +fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: ZigNode) !void { + const gop = try c.global_scope.sym_table.getOrPut(name); + if (!gop.found_existing) { + gop.value_ptr.* = decl_node; + try c.global_scope.nodes.append(decl_node); + } +} + +fn failDecl(c: *Context, loc: TokenIndex, name: []const u8, comptime format: []const u8, args: anytype) Error!void { + // location + // pub const name = @compileError(msg); + const fail_msg = try std.fmt.allocPrint(c.arena, format, args); + try addTopLevelDecl(c, name, try ZigTag.fail_decl.create(c.arena, .{ .actual = name, .mangled = fail_msg })); + const str = try c.locStr(loc); + const location_comment = try std.fmt.allocPrint(c.arena, "// {s}", .{str}); + try c.global_scope.nodes.append(try ZigTag.warning.create(c.arena, location_comment)); +} + +pub fn translate( + gpa: mem.Allocator, + comp: *Compilation, + args: []const []const u8, +) !std.zig.Ast { + try comp.addDefaultPragmaHandlers(); + comp.langopts.setEmulatedCompiler(aro.target_util.systemCompiler(comp.target)); + + var driver: aro.Driver = .{ .comp = comp }; + defer driver.deinit(); + + var macro_buf = std.ArrayList(u8).init(gpa); + defer macro_buf.deinit(); + + assert(!try driver.parseArgs(std.io.null_writer, macro_buf.writer(), args)); + assert(driver.inputs.items.len == 1); + const source = driver.inputs.items[0]; + + const builtin = try comp.generateBuiltinMacros(); + const user_macros = try comp.addSourceFromBuffer("", macro_buf.items); + + var pp = aro.Preprocessor.init(comp); + defer pp.deinit(); + + try pp.addBuiltinMacros(); + + _ = try pp.preprocess(builtin); + _ = try pp.preprocess(user_macros); + const eof = try pp.preprocess(source); + try pp.tokens.append(pp.comp.gpa, eof); + + var tree = try aro.Parser.parse(&pp); + defer tree.deinit(); + + if (driver.comp.diag.errors != 0) { + return error.SemanticAnalyzeFail; + } + + const mapper = tree.comp.string_interner.getFastTypeMapper(tree.comp.gpa) catch tree.comp.string_interner.getSlowTypeMapper(); + defer mapper.deinit(tree.comp.gpa); + + var arena_allocator = std.heap.ArenaAllocator.init(gpa); + errdefer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); + + var context = Context{ + .gpa = gpa, + .arena = arena, + .alias_list = AliasList.init(gpa), + .global_scope = try arena.create(Scope.Root), + .pattern_list = try translate_c.PatternList.init(gpa), + .comp = comp, + .mapper = mapper, + .tree = tree, + }; + context.global_scope.* = Scope.Root.init(&context); + defer { + context.decl_table.deinit(gpa); + context.alias_list.deinit(); + context.global_names.deinit(gpa); + context.opaque_demotes.deinit(gpa); + context.unnamed_typedefs.deinit(gpa); + context.typedefs.deinit(gpa); + context.global_scope.deinit(); + context.pattern_list.deinit(gpa); + } + + inline for (@typeInfo(std.zig.c_builtins).Struct.decls) |decl| { + const builtin_fn = try ZigTag.pub_var_simple.create(arena, .{ + .name = decl.name, + .init = try ZigTag.import_c_builtin.create(arena, decl.name), + }); + try addTopLevelDecl(&context, decl.name, builtin_fn); + } + + try prepopulateGlobalNameTable(&context); + try transTopLevelDecls(&context); + + for (context.alias_list.items) |alias| { + if (!context.global_scope.sym_table.contains(alias.alias)) { + const node = try ZigTag.alias.create(arena, .{ .actual = alias.alias, .mangled = alias.name }); + try addTopLevelDecl(&context, alias.alias, node); + } + } + + return ast.render(gpa, context.global_scope.nodes.items); +} + +fn prepopulateGlobalNameTable(c: *Context) !void { + const node_tags = c.tree.nodes.items(.tag); + const node_types = c.tree.nodes.items(.ty); + const node_data = c.tree.nodes.items(.data); + for (c.tree.root_decls) |node| { + const data = node_data[@intFromEnum(node)]; + const decl_name = switch (node_tags[@intFromEnum(node)]) { + .typedef => @panic("TODO"), + + .static_assert, + .struct_decl_two, + .union_decl_two, + .struct_decl, + .union_decl, + => blk: { + const ty = node_types[@intFromEnum(node)]; + const name_id = ty.data.record.name; + break :blk c.mapper.lookup(name_id); + }, + + .enum_decl_two, + .enum_decl, + => blk: { + const ty = node_types[@intFromEnum(node)]; + const name_id = ty.data.@"enum".name; + break :blk c.mapper.lookup(name_id); + }, + + .fn_proto, + .static_fn_proto, + .inline_fn_proto, + .inline_static_fn_proto, + .fn_def, + .static_fn_def, + .inline_fn_def, + .inline_static_fn_def, + .@"var", + .static_var, + .threadlocal_var, + .threadlocal_static_var, + .extern_var, + .threadlocal_extern_var, + => c.tree.tokSlice(data.decl.name), + else => unreachable, + }; + try c.global_names.put(c.gpa, decl_name, {}); + } +} + +fn transTopLevelDecls(c: *Context) !void { + const node_tags = c.tree.nodes.items(.tag); + const node_data = c.tree.nodes.items(.data); + for (c.tree.root_decls) |node| { + const data = node_data[@intFromEnum(node)]; + switch (node_tags[@intFromEnum(node)]) { + .typedef => { + try transTypeDef(c, &c.global_scope.base, node); + }, + + .static_assert, + .struct_decl_two, + .union_decl_two, + .struct_decl, + .union_decl, + => { + try transRecordDecl(c, &c.global_scope.base, node); + }, + + .enum_decl_two => { + var fields = [2]NodeIndex{ data.bin.lhs, data.bin.rhs }; + var field_count: u8 = 0; + if (fields[0] != .none) field_count += 1; + if (fields[1] != .none) field_count += 1; + try transEnumDecl(c, &c.global_scope.base, node, fields[0..field_count]); + }, + .enum_decl => { + const fields = c.tree.data[data.range.start..data.range.end]; + try transEnumDecl(c, &c.global_scope.base, node, fields); + }, + + .fn_proto, + .static_fn_proto, + .inline_fn_proto, + .inline_static_fn_proto, + .fn_def, + .static_fn_def, + .inline_fn_def, + .inline_static_fn_def, + => { + try transFnDecl(c, node); + }, + + .@"var", + .static_var, + .threadlocal_var, + .threadlocal_static_var, + .extern_var, + .threadlocal_extern_var, + => { + try transVarDecl(c, node, null); + }, + else => unreachable, + } + } +} + +fn transTypeDef(_: *Context, _: *Scope, _: NodeIndex) Error!void { + @panic("TODO"); +} +fn transRecordDecl(_: *Context, _: *Scope, _: NodeIndex) Error!void { + @panic("TODO"); +} +fn transFnDecl(_: *Context, _: NodeIndex) Error!void { + @panic("TODO"); +} +fn transVarDecl(_: *Context, _: NodeIndex, _: ?usize) Error!void { + @panic("TODO"); +} +fn transEnumDecl(c: *Context, scope: *Scope, enum_decl: NodeIndex, field_nodes: []const NodeIndex) Error!void { + const node_types = c.tree.nodes.items(.ty); + const ty = node_types[@intFromEnum(enum_decl)]; + const node_data = c.tree.nodes.items(.data); + if (c.decl_table.get(@intFromPtr(ty.data.@"enum"))) |_| + return; // Avoid processing this decl twice + const toplevel = scope.id == .root; + const bs: *Scope.Block = if (!toplevel) try scope.findBlockScope(c) else undefined; + + var is_unnamed = false; + var bare_name: []const u8 = c.mapper.lookup(ty.data.@"enum".name); + var name = bare_name; + if (c.unnamed_typedefs.get(@intFromPtr(ty.data.@"enum"))) |typedef_name| { + bare_name = typedef_name; + name = typedef_name; + } else { + if (bare_name.len == 0) { + bare_name = try std.fmt.allocPrint(c.arena, "unnamed_{d}", .{c.getMangle()}); + is_unnamed = true; + } + name = try std.fmt.allocPrint(c.arena, "enum_{s}", .{bare_name}); + } + if (!toplevel) name = try bs.makeMangledName(c, name); + try c.decl_table.putNoClobber(c.gpa, @intFromPtr(ty.data.@"enum"), name); + + const enum_type_node = if (!ty.data.@"enum".isIncomplete()) blk: { + for (ty.data.@"enum".fields, field_nodes) |field, field_node| { + var enum_val_name: []const u8 = c.mapper.lookup(field.name); + if (!toplevel) { + enum_val_name = try bs.makeMangledName(c, enum_val_name); + } + + const enum_const_type_node: ?ZigNode = transType(c, scope, field.ty, field.name_tok) catch |err| switch (err) { + error.UnsupportedType => null, + else => |e| return e, + }; + + const enum_const_def = try ZigTag.enum_constant.create(c.arena, .{ + .name = enum_val_name, + .is_public = toplevel, + .type = enum_const_type_node, + .value = transExpr(c, node_data[@intFromEnum(field_node)].decl.node, .used) catch @panic("TODO"), + }); + if (toplevel) + try addTopLevelDecl(c, enum_val_name, enum_const_def) + else { + try scope.appendNode(enum_const_def); + try bs.discardVariable(c, enum_val_name); + } + } + + break :blk transType(c, scope, ty.data.@"enum".tag_ty, 0) catch |err| switch (err) { + error.UnsupportedType => { + return failDecl(c, 0, name, "unable to translate enum integer type", .{}); + }, + else => |e| return e, + }; + } else blk: { + try c.opaque_demotes.put(c.gpa, @intFromPtr(ty.data.@"enum"), {}); + break :blk ZigTag.opaque_literal.init(); + }; + + const is_pub = toplevel and !is_unnamed; + const payload = try c.arena.create(ast.Payload.SimpleVarDecl); + payload.* = .{ + .base = .{ .tag = ([2]ZigTag{ .var_simple, .pub_var_simple })[@intFromBool(is_pub)] }, + .data = .{ + .init = enum_type_node, + .name = name, + }, + }; + const node = ZigNode.initPayload(&payload.base); + if (toplevel) { + try addTopLevelDecl(c, name, node); + if (!is_unnamed) + try c.alias_list.append(.{ .alias = bare_name, .name = name }); + } else { + try scope.appendNode(node); + if (node.tag() != .pub_var_simple) { + try bs.discardVariable(c, name); + } + } +} + +fn transType(c: *Context, scope: *Scope, raw_ty: Type, source_loc: TokenIndex) TypeError!ZigNode { + _ = source_loc; + _ = scope; + const ty = raw_ty.canonicalize(.standard); + switch (ty.specifier) { + .void => return ZigTag.type.create(c.arena, "anyopaque"), + .bool => return ZigTag.type.create(c.arena, "bool"), + .char => return ZigTag.type.create(c.arena, "c_char"), + .schar => return ZigTag.type.create(c.arena, "i8"), + .uchar => return ZigTag.type.create(c.arena, "u8"), + .short => return ZigTag.type.create(c.arena, "c_short"), + .ushort => return ZigTag.type.create(c.arena, "c_ushort"), + .int => return ZigTag.type.create(c.arena, "c_int"), + .uint => return ZigTag.type.create(c.arena, "c_uint"), + .long => return ZigTag.type.create(c.arena, "c_long"), + .ulong => return ZigTag.type.create(c.arena, "c_ulong"), + .long_long => return ZigTag.type.create(c.arena, "c_longlong"), + .ulong_long => return ZigTag.type.create(c.arena, "c_ulonglong"), + .int128 => return ZigTag.type.create(c.arena, "i128"), + .uint128 => return ZigTag.type.create(c.arena, "u128"), + .fp16, .float16 => return ZigTag.type.create(c.arena, "f16"), + .float => return ZigTag.type.create(c.arena, "f32"), + .double => return ZigTag.type.create(c.arena, "f64"), + .long_double => return ZigTag.type.create(c.arena, "c_longdouble"), + .float80 => return ZigTag.type.create(c.arena, "f80"), + .float128 => return ZigTag.type.create(c.arena, "f128"), + else => @panic("TODO"), + } +} + +fn transStmt(c: *Context, node: NodeIndex) TransError!void { + _ = try c.transExpr(node, .unused); +} + +fn transExpr(c: *Context, node: NodeIndex, result_used: ResultUsed) TransError!ZigNode { + std.debug.assert(node != .none); + const ty = c.tree.nodes.items(.ty)[@intFromEnum(node)]; + if (c.tree.value_map.get(node)) |val| { + // TODO handle other values + const str = try std.fmt.allocPrint(c.arena, "{d}", .{val.data.int}); + const int = try ZigTag.integer_literal.create(c.arena, str); + const as_node = try ZigTag.as.create(c.arena, .{ + .lhs = try transType(c, undefined, ty, undefined), + .rhs = int, + }); + return maybeSuppressResult(c, result_used, as_node); + } + const node_tags = c.tree.nodes.items(.tag); + switch (node_tags[@intFromEnum(node)]) { + else => unreachable, // Not an expression. + } + return .none; +} diff --git a/src/main.zig b/src/main.zig index 04ae483a6e02..26b08a9d47ab 100644 --- a/src/main.zig +++ b/src/main.zig @@ -20,7 +20,6 @@ const build_options = @import("build_options"); const introspect = @import("introspect.zig"); const LibCInstallation = @import("libc_installation.zig").LibCInstallation; const wasi_libc = @import("wasi_libc.zig"); -const translate_c = @import("translate_c.zig"); const BuildId = std.Build.CompileStep.BuildId; const Cache = std.Build.Cache; const target_util = @import("target.zig"); @@ -4204,9 +4203,7 @@ fn updateModule(comp: *Compilation) !void { } fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilation.CImportResult) !void { - if (!build_options.have_llvm) - fatal("cannot translate-c: compiler built without LLVM extensions", .{}); - + if (build_options.only_c) unreachable; // translate-c is not needed for bootstrapping assert(comp.c_source_files.len == 1); const c_source_file = comp.c_source_files[0]; @@ -4225,14 +4222,14 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati const digest = if (try man.hit()) man.final() else digest: { if (fancy_output) |p| p.cache_hit = false; var argv = std.ArrayList([]const u8).init(arena); - try argv.append(""); // argv[0] is program name, actual args start at [1] + try argv.append(@tagName(comp.c_frontend)); // argv[0] is program name, actual args start at [1] var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{}); defer zig_cache_tmp_dir.close(); const ext = Compilation.classifyFileExt(c_source_file.src_path); const out_dep_path: ?[]const u8 = blk: { - if (comp.disable_c_depfile or !ext.clangSupportsDepFile()) + if (comp.c_frontend == .aro or comp.disable_c_depfile or !ext.clangSupportsDepFile()) break :blk null; const c_src_basename = fs.path.basename(c_source_file.src_path); @@ -4241,44 +4238,67 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati break :blk out_dep_path; }; - try comp.addTranslateCCArgs(arena, &argv, ext, out_dep_path); + // TODO + if (comp.c_frontend != .aro) try comp.addTranslateCCArgs(arena, &argv, ext, out_dep_path); try argv.append(c_source_file.src_path); if (comp.verbose_cc) { - std.debug.print("clang ", .{}); Compilation.dump_argv(argv.items); } - // Convert to null terminated args. - const clang_args_len = argv.items.len + c_source_file.extra_flags.len; - const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, clang_args_len + 1); - new_argv_with_sentinel[clang_args_len] = null; - const new_argv = new_argv_with_sentinel[0..clang_args_len :null]; - for (argv.items, 0..) |arg, i| { - new_argv[i] = try arena.dupeZ(u8, arg); - } - for (c_source_file.extra_flags, 0..) |arg, i| { - new_argv[argv.items.len + i] = try arena.dupeZ(u8, arg); - } - - const c_headers_dir_path_z = try comp.zig_lib_directory.joinZ(arena, &[_][]const u8{"include"}); - var errors = std.zig.ErrorBundle.empty; - var tree = translate_c.translate( - comp.gpa, - new_argv.ptr, - new_argv.ptr + new_argv.len, - &errors, - c_headers_dir_path_z, - ) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - error.SemanticAnalyzeFail => { - if (fancy_output) |p| { - p.errors = errors; - return; - } else { - errors.renderToStdErr(renderOptions(comp.color)); - process.exit(1); + var tree = switch (comp.c_frontend) { + .aro => tree: { + if (builtin.zig_backend == .stage2_c) @panic("the CBE cannot compile Aro yet!"); + const translate_c = @import("aro_translate_c.zig"); + var aro_comp = translate_c.Compilation.init(comp.gpa); + defer aro_comp.deinit(); + + break :tree translate_c.translate(comp.gpa, &aro_comp, argv.items) catch |err| switch (err) { + error.SemanticAnalyzeFail, error.FatalError => { + // TODO convert these to zig errors + aro_comp.renderErrors(); + process.exit(1); + }, + error.OutOfMemory => return error.OutOfMemory, + error.StreamTooLong => fatal("StreamTooLong?", .{}), + }; + }, + .clang => tree: { + if (!build_options.have_llvm) unreachable; + const translate_c = @import("translate_c.zig"); + + // Convert to null terminated args. + const clang_args_len = argv.items.len + c_source_file.extra_flags.len; + const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, clang_args_len + 1); + new_argv_with_sentinel[clang_args_len] = null; + const new_argv = new_argv_with_sentinel[0..clang_args_len :null]; + for (argv.items, 0..) |arg, i| { + new_argv[i] = try arena.dupeZ(u8, arg); } + for (c_source_file.extra_flags, 0..) |arg, i| { + new_argv[argv.items.len + i] = try arena.dupeZ(u8, arg); + } + + const c_headers_dir_path_z = try comp.zig_lib_directory.joinZ(arena, &[_][]const u8{"include"}); + var errors = std.zig.ErrorBundle.empty; + break :tree translate_c.translate( + comp.gpa, + new_argv.ptr, + new_argv.ptr + new_argv.len, + &errors, + c_headers_dir_path_z, + ) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.SemanticAnalyzeFail => { + if (fancy_output) |p| { + p.errors = errors; + return; + } else { + errors.renderToStdErr(renderOptions(comp.color)); + process.exit(1); + } + }, + }; }, }; defer tree.deinit(comp.gpa); diff --git a/src/translate_c.zig b/src/translate_c.zig index 75576b35bb48..4da2e8b1e614 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -7,312 +7,24 @@ const CToken = std.c.Token; const mem = std.mem; const math = std.math; const meta = std.meta; +const CallingConvention = std.builtin.CallingConvention; const ast = @import("translate_c/ast.zig"); const Node = ast.Node; const Tag = Node.Tag; - -const CallingConvention = std.builtin.CallingConvention; - -pub const Error = std.mem.Allocator.Error; -const MacroProcessingError = Error || error{UnexpectedMacroToken}; -const TypeError = Error || error{UnsupportedType}; -const TransError = TypeError || error{UnsupportedTranslation}; - -const SymbolTable = std.StringArrayHashMap(Node); -const AliasList = std.ArrayList(struct { - alias: []const u8, - name: []const u8, -}); +const common = @import("translate_c/common.zig"); +const Error = common.Error; +const MacroProcessingError = common.MacroProcessingError; +const TypeError = common.TypeError; +const TransError = common.TransError; +const SymbolTable = common.SymbolTable; +const AliasList = common.AliasList; +const ResultUsed = common.ResultUsed; +const Scope = common.ScopeExtra(Context, clang.QualType); // Maps macro parameter names to token position, for determining if different // identifiers refer to the same positional argument in different macros. const ArgsPositionMap = std.StringArrayHashMapUnmanaged(usize); -const Scope = struct { - id: Id, - parent: ?*Scope, - - const Id = enum { - block, - root, - condition, - loop, - do_loop, - }; - - /// Used for the scope of condition expressions, for example `if (cond)`. - /// The block is lazily initialised because it is only needed for rare - /// cases of comma operators being used. - const Condition = struct { - base: Scope, - block: ?Block = null, - - fn getBlockScope(self: *Condition, c: *Context) !*Block { - if (self.block) |*b| return b; - self.block = try Block.init(c, &self.base, true); - return &self.block.?; - } - - fn deinit(self: *Condition) void { - if (self.block) |*b| b.deinit(); - } - }; - - /// Represents an in-progress Node.Block. This struct is stack-allocated. - /// When it is deinitialized, it produces an Node.Block which is allocated - /// into the main arena. - const Block = struct { - base: Scope, - statements: std.ArrayList(Node), - variables: AliasList, - mangle_count: u32 = 0, - label: ?[]const u8 = null, - - /// By default all variables are discarded, since we do not know in advance if they - /// will be used. This maps the variable's name to the Discard payload, so that if - /// the variable is subsequently referenced we can indicate that the discard should - /// be skipped during the intermediate AST -> Zig AST render step. - variable_discards: std.StringArrayHashMap(*ast.Payload.Discard), - - /// When the block corresponds to a function, keep track of the return type - /// so that the return expression can be cast, if necessary - return_type: ?clang.QualType = null, - - /// C static local variables are wrapped in a block-local struct. The struct - /// is named after the (mangled) variable name, the Zig variable within the - /// struct itself is given this name. - const StaticInnerName = "static"; - - fn init(c: *Context, parent: *Scope, labeled: bool) !Block { - var blk = Block{ - .base = .{ - .id = .block, - .parent = parent, - }, - .statements = std.ArrayList(Node).init(c.gpa), - .variables = AliasList.init(c.gpa), - .variable_discards = std.StringArrayHashMap(*ast.Payload.Discard).init(c.gpa), - }; - if (labeled) { - blk.label = try blk.makeMangledName(c, "blk"); - } - return blk; - } - - fn deinit(self: *Block) void { - self.statements.deinit(); - self.variables.deinit(); - self.variable_discards.deinit(); - self.* = undefined; - } - - fn complete(self: *Block, c: *Context) !Node { - if (self.base.parent.?.id == .do_loop) { - // We reserve 1 extra statement if the parent is a do_loop. This is in case of - // do while, we want to put `if (cond) break;` at the end. - const alloc_len = self.statements.items.len + @intFromBool(self.base.parent.?.id == .do_loop); - var stmts = try c.arena.alloc(Node, alloc_len); - stmts.len = self.statements.items.len; - @memcpy(stmts[0..self.statements.items.len], self.statements.items); - return Tag.block.create(c.arena, .{ - .label = self.label, - .stmts = stmts, - }); - } - if (self.statements.items.len == 0) return Tag.empty_block.init(); - return Tag.block.create(c.arena, .{ - .label = self.label, - .stmts = try c.arena.dupe(Node, self.statements.items), - }); - } - - /// Given the desired name, return a name that does not shadow anything from outer scopes. - /// Inserts the returned name into the scope. - /// The name will not be visible to callers of getAlias. - fn reserveMangledName(scope: *Block, c: *Context, name: []const u8) ![]const u8 { - return scope.createMangledName(c, name, true); - } - - /// Same as reserveMangledName, but enables the alias immediately. - fn makeMangledName(scope: *Block, c: *Context, name: []const u8) ![]const u8 { - return scope.createMangledName(c, name, false); - } - - fn createMangledName(scope: *Block, c: *Context, name: []const u8, reservation: bool) ![]const u8 { - const name_copy = try c.arena.dupe(u8, name); - var proposed_name = name_copy; - while (scope.contains(proposed_name)) { - scope.mangle_count += 1; - proposed_name = try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ name, scope.mangle_count }); - } - const new_mangle = try scope.variables.addOne(); - if (reservation) { - new_mangle.* = .{ .name = name_copy, .alias = name_copy }; - } else { - new_mangle.* = .{ .name = name_copy, .alias = proposed_name }; - } - return proposed_name; - } - - fn getAlias(scope: *Block, name: []const u8) []const u8 { - for (scope.variables.items) |p| { - if (mem.eql(u8, p.name, name)) - return p.alias; - } - return scope.base.parent.?.getAlias(name); - } - - fn localContains(scope: *Block, name: []const u8) bool { - for (scope.variables.items) |p| { - if (mem.eql(u8, p.alias, name)) - return true; - } - return false; - } - - fn contains(scope: *Block, name: []const u8) bool { - if (scope.localContains(name)) - return true; - return scope.base.parent.?.contains(name); - } - - fn discardVariable(scope: *Block, c: *Context, name: []const u8) Error!void { - const name_node = try Tag.identifier.create(c.arena, name); - const discard = try Tag.discard.create(c.arena, .{ .should_skip = false, .value = name_node }); - try scope.statements.append(discard); - try scope.variable_discards.putNoClobber(name, discard.castTag(.discard).?); - } - }; - - const Root = struct { - base: Scope, - sym_table: SymbolTable, - macro_table: SymbolTable, - context: *Context, - nodes: std.ArrayList(Node), - - fn init(c: *Context) Root { - return .{ - .base = .{ - .id = .root, - .parent = null, - }, - .sym_table = SymbolTable.init(c.gpa), - .macro_table = SymbolTable.init(c.gpa), - .context = c, - .nodes = std.ArrayList(Node).init(c.gpa), - }; - } - - fn deinit(scope: *Root) void { - scope.sym_table.deinit(); - scope.macro_table.deinit(); - scope.nodes.deinit(); - } - - /// Check if the global scope contains this name, without looking into the "future", e.g. - /// ignore the preprocessed decl and macro names. - fn containsNow(scope: *Root, name: []const u8) bool { - return scope.sym_table.contains(name) or scope.macro_table.contains(name); - } - - /// Check if the global scope contains the name, includes all decls that haven't been translated yet. - fn contains(scope: *Root, name: []const u8) bool { - return scope.containsNow(name) or scope.context.global_names.contains(name) or scope.context.weak_global_names.contains(name); - } - }; - - fn findBlockScope(inner: *Scope, c: *Context) !*Scope.Block { - var scope = inner; - while (true) { - switch (scope.id) { - .root => unreachable, - .block => return @fieldParentPtr(Block, "base", scope), - .condition => return @fieldParentPtr(Condition, "base", scope).getBlockScope(c), - else => scope = scope.parent.?, - } - } - } - - fn findBlockReturnType(inner: *Scope) clang.QualType { - var scope = inner; - while (true) { - switch (scope.id) { - .root => unreachable, - .block => { - const block = @fieldParentPtr(Block, "base", scope); - if (block.return_type) |qt| return qt; - scope = scope.parent.?; - }, - else => scope = scope.parent.?, - } - } - } - - fn getAlias(scope: *Scope, name: []const u8) []const u8 { - return switch (scope.id) { - .root => return name, - .block => @fieldParentPtr(Block, "base", scope).getAlias(name), - .loop, .do_loop, .condition => scope.parent.?.getAlias(name), - }; - } - - fn contains(scope: *Scope, name: []const u8) bool { - return switch (scope.id) { - .root => @fieldParentPtr(Root, "base", scope).contains(name), - .block => @fieldParentPtr(Block, "base", scope).contains(name), - .loop, .do_loop, .condition => scope.parent.?.contains(name), - }; - } - - fn getBreakableScope(inner: *Scope) *Scope { - var scope = inner; - while (true) { - switch (scope.id) { - .root => unreachable, - .loop, .do_loop => return scope, - else => scope = scope.parent.?, - } - } - } - - /// Appends a node to the first block scope if inside a function, or to the root tree if not. - fn appendNode(inner: *Scope, node: Node) !void { - var scope = inner; - while (true) { - switch (scope.id) { - .root => { - const root = @fieldParentPtr(Root, "base", scope); - return root.nodes.append(node); - }, - .block => { - const block = @fieldParentPtr(Block, "base", scope); - return block.statements.append(node); - }, - else => scope = scope.parent.?, - } - } - } - - fn skipVariableDiscard(inner: *Scope, name: []const u8) void { - var scope = inner; - while (true) { - switch (scope.id) { - .root => return, - .block => { - const block = @fieldParentPtr(Block, "base", scope); - if (block.variable_discards.get(name)) |discard| { - discard.data.should_skip = true; - return; - } - }, - else => {}, - } - scope = scope.parent.?; - } - } -}; - pub const Context = struct { gpa: mem.Allocator, arena: mem.Allocator, @@ -829,7 +541,7 @@ fn transQualTypeMaybeInitialized(c: *Context, scope: *Scope, qt: clang.QualType, /// var static = S.*; /// }).static; fn stringLiteralToCharStar(c: *Context, str: Node) Error!Node { - const var_name = Scope.Block.StaticInnerName; + const var_name = Scope.Block.static_inner_name; const variables = try c.arena.alloc(Node, 1); variables[0] = try Tag.mut_str.create(c.arena, .{ .name = var_name, .init = str }); @@ -1423,11 +1135,6 @@ fn transEnumDecl(c: *Context, scope: *Scope, enum_decl: *const clang.EnumDecl) E } } -const ResultUsed = enum { - used, - unused, -}; - fn transStmt( c: *Context, scope: *Scope, @@ -2070,7 +1777,7 @@ fn transDeclStmtOne( init_node = try removeCVQualifiers(c, dst_type_node, init_node); } - const var_name: []const u8 = if (is_static_local) Scope.Block.StaticInnerName else mangled_name; + const var_name: []const u8 = if (is_static_local) Scope.Block.static_inner_name else mangled_name; var node = try Tag.var_decl.create(c.arena, .{ .is_pub = false, .is_const = is_const, @@ -2153,7 +1860,7 @@ fn transDeclRefExpr( if (var_decl.isStaticLocal()) { ref_expr = try Tag.field_access.create(c.arena, .{ .lhs = ref_expr, - .field_name = Scope.Block.StaticInnerName, + .field_name = Scope.Block.static_inner_name, }); } } @@ -5322,7 +5029,7 @@ pub fn failDecl(c: *Context, loc: clang.SourceLocation, name: []const u8, compti try c.global_scope.nodes.append(try Tag.warning.create(c.arena, location_comment)); } -const PatternList = struct { +pub const PatternList = struct { patterns: []Pattern, /// Templates must be function-like macros @@ -5455,7 +5162,7 @@ const PatternList = struct { /// macro. Please review this logic carefully if changing that assumption. Two /// function-like macros are considered equivalent if and only if they contain the same /// list of tokens, modulo parameter names. - fn isEquivalent(self: Pattern, ms: MacroSlicer, args_hash: ArgsPositionMap) bool { + pub fn isEquivalent(self: Pattern, ms: MacroSlicer, args_hash: ArgsPositionMap) bool { if (self.tokens.len != ms.tokens.len) return false; if (args_hash.count() != self.args_hash.count()) return false; @@ -5496,7 +5203,7 @@ const PatternList = struct { } }; - fn init(allocator: mem.Allocator) Error!PatternList { + pub fn init(allocator: mem.Allocator) Error!PatternList { const patterns = try allocator.alloc(Pattern, templates.len); for (templates, 0..) |template, i| { try patterns[i].init(allocator, template); @@ -5504,12 +5211,12 @@ const PatternList = struct { return PatternList{ .patterns = patterns }; } - fn deinit(self: *PatternList, allocator: mem.Allocator) void { + pub fn deinit(self: *PatternList, allocator: mem.Allocator) void { for (self.patterns) |*pattern| pattern.deinit(allocator); allocator.free(self.patterns); } - fn match(self: PatternList, allocator: mem.Allocator, ms: MacroSlicer) Error!?Pattern { + pub fn match(self: PatternList, allocator: mem.Allocator, ms: MacroSlicer) Error!?Pattern { var args_hash: ArgsPositionMap = .{}; defer args_hash.deinit(allocator); diff --git a/src/translate_c/common.zig b/src/translate_c/common.zig new file mode 100644 index 000000000000..c26ab2798ba2 --- /dev/null +++ b/src/translate_c/common.zig @@ -0,0 +1,311 @@ +const std = @import("std"); +const ast = @import("ast.zig"); +const Node = ast.Node; +const Tag = Node.Tag; + +const CallingConvention = std.builtin.CallingConvention; + +pub const Error = std.mem.Allocator.Error; +pub const MacroProcessingError = Error || error{UnexpectedMacroToken}; +pub const TypeError = Error || error{UnsupportedType}; +pub const TransError = TypeError || error{UnsupportedTranslation}; + +pub const SymbolTable = std.StringArrayHashMap(Node); +pub const AliasList = std.ArrayList(struct { + alias: []const u8, + name: []const u8, +}); + +pub const ResultUsed = enum { + used, + unused, +}; + +pub fn ScopeExtra(comptime Context: type, comptime Type: type) type { + return struct { + id: Id, + parent: ?*Scope, + + const Scope = @This(); + + pub const Id = enum { + block, + root, + condition, + loop, + do_loop, + }; + + /// Used for the scope of condition expressions, for example `if (cond)`. + /// The block is lazily initialised because it is only needed for rare + /// cases of comma operators being used. + pub const Condition = struct { + base: Scope, + block: ?Block = null, + + pub fn getBlockScope(self: *Condition, c: *Context) !*Block { + if (self.block) |*b| return b; + self.block = try Block.init(c, &self.base, true); + return &self.block.?; + } + + pub fn deinit(self: *Condition) void { + if (self.block) |*b| b.deinit(); + } + }; + + /// Represents an in-progress Node.Block. This struct is stack-allocated. + /// When it is deinitialized, it produces an Node.Block which is allocated + /// into the main arena. + pub const Block = struct { + base: Scope, + statements: std.ArrayList(Node), + variables: AliasList, + mangle_count: u32 = 0, + label: ?[]const u8 = null, + + /// By default all variables are discarded, since we do not know in advance if they + /// will be used. This maps the variable's name to the Discard payload, so that if + /// the variable is subsequently referenced we can indicate that the discard should + /// be skipped during the intermediate AST -> Zig AST render step. + variable_discards: std.StringArrayHashMap(*ast.Payload.Discard), + + /// When the block corresponds to a function, keep track of the return type + /// so that the return expression can be cast, if necessary + return_type: ?Type = null, + + /// C static local variables are wrapped in a block-local struct. The struct + /// is named after the (mangled) variable name, the Zig variable within the + /// struct itself is given this name. + pub const static_inner_name = "static"; + + pub fn init(c: *Context, parent: *Scope, labeled: bool) !Block { + var blk = Block{ + .base = .{ + .id = .block, + .parent = parent, + }, + .statements = std.ArrayList(Node).init(c.gpa), + .variables = AliasList.init(c.gpa), + .variable_discards = std.StringArrayHashMap(*ast.Payload.Discard).init(c.gpa), + }; + if (labeled) { + blk.label = try blk.makeMangledName(c, "blk"); + } + return blk; + } + + pub fn deinit(self: *Block) void { + self.statements.deinit(); + self.variables.deinit(); + self.variable_discards.deinit(); + self.* = undefined; + } + + pub fn complete(self: *Block, c: *Context) !Node { + if (self.base.parent.?.id == .do_loop) { + // We reserve 1 extra statement if the parent is a do_loop. This is in case of + // do while, we want to put `if (cond) break;` at the end. + const alloc_len = self.statements.items.len + @intFromBool(self.base.parent.?.id == .do_loop); + var stmts = try c.arena.alloc(Node, alloc_len); + stmts.len = self.statements.items.len; + @memcpy(stmts[0..self.statements.items.len], self.statements.items); + return Tag.block.create(c.arena, .{ + .label = self.label, + .stmts = stmts, + }); + } + if (self.statements.items.len == 0) return Tag.empty_block.init(); + return Tag.block.create(c.arena, .{ + .label = self.label, + .stmts = try c.arena.dupe(Node, self.statements.items), + }); + } + + /// Given the desired name, return a name that does not shadow anything from outer scopes. + /// Inserts the returned name into the scope. + /// The name will not be visible to callers of getAlias. + pub fn reserveMangledName(scope: *Block, c: *Context, name: []const u8) ![]const u8 { + return scope.createMangledName(c, name, true); + } + + /// Same as reserveMangledName, but enables the alias immediately. + pub fn makeMangledName(scope: *Block, c: *Context, name: []const u8) ![]const u8 { + return scope.createMangledName(c, name, false); + } + + pub fn createMangledName(scope: *Block, c: *Context, name: []const u8, reservation: bool) ![]const u8 { + const name_copy = try c.arena.dupe(u8, name); + var proposed_name = name_copy; + while (scope.contains(proposed_name)) { + scope.mangle_count += 1; + proposed_name = try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ name, scope.mangle_count }); + } + const new_mangle = try scope.variables.addOne(); + if (reservation) { + new_mangle.* = .{ .name = name_copy, .alias = name_copy }; + } else { + new_mangle.* = .{ .name = name_copy, .alias = proposed_name }; + } + return proposed_name; + } + + pub fn getAlias(scope: *Block, name: []const u8) []const u8 { + for (scope.variables.items) |p| { + if (std.mem.eql(u8, p.name, name)) + return p.alias; + } + return scope.base.parent.?.getAlias(name); + } + + pub fn localContains(scope: *Block, name: []const u8) bool { + for (scope.variables.items) |p| { + if (std.mem.eql(u8, p.alias, name)) + return true; + } + return false; + } + + pub fn contains(scope: *Block, name: []const u8) bool { + if (scope.localContains(name)) + return true; + return scope.base.parent.?.contains(name); + } + + pub fn discardVariable(scope: *Block, c: *Context, name: []const u8) Error!void { + const name_node = try Tag.identifier.create(c.arena, name); + const discard = try Tag.discard.create(c.arena, .{ .should_skip = false, .value = name_node }); + try scope.statements.append(discard); + try scope.variable_discards.putNoClobber(name, discard.castTag(.discard).?); + } + }; + + pub const Root = struct { + base: Scope, + sym_table: SymbolTable, + macro_table: SymbolTable, + context: *Context, + nodes: std.ArrayList(Node), + + pub fn init(c: *Context) Root { + return .{ + .base = .{ + .id = .root, + .parent = null, + }, + .sym_table = SymbolTable.init(c.gpa), + .macro_table = SymbolTable.init(c.gpa), + .context = c, + .nodes = std.ArrayList(Node).init(c.gpa), + }; + } + + pub fn deinit(scope: *Root) void { + scope.sym_table.deinit(); + scope.macro_table.deinit(); + scope.nodes.deinit(); + } + + /// Check if the global scope contains this name, without looking into the "future", e.g. + /// ignore the preprocessed decl and macro names. + pub fn containsNow(scope: *Root, name: []const u8) bool { + return scope.sym_table.contains(name) or scope.macro_table.contains(name); + } + + /// Check if the global scope contains the name, includes all decls that haven't been translated yet. + pub fn contains(scope: *Root, name: []const u8) bool { + return scope.containsNow(name) or scope.context.global_names.contains(name) or scope.context.weak_global_names.contains(name); + } + }; + + pub fn findBlockScope(inner: *Scope, c: *Context) !*Scope.Block { + var scope = inner; + while (true) { + switch (scope.id) { + .root => unreachable, + .block => return @fieldParentPtr(Block, "base", scope), + .condition => return @fieldParentPtr(Condition, "base", scope).getBlockScope(c), + else => scope = scope.parent.?, + } + } + } + + pub fn findBlockReturnType(inner: *Scope) Type { + var scope = inner; + while (true) { + switch (scope.id) { + .root => unreachable, + .block => { + const block = @fieldParentPtr(Block, "base", scope); + if (block.return_type) |ty| return ty; + scope = scope.parent.?; + }, + else => scope = scope.parent.?, + } + } + } + + pub fn getAlias(scope: *Scope, name: []const u8) []const u8 { + return switch (scope.id) { + .root => return name, + .block => @fieldParentPtr(Block, "base", scope).getAlias(name), + .loop, .do_loop, .condition => scope.parent.?.getAlias(name), + }; + } + + pub fn contains(scope: *Scope, name: []const u8) bool { + return switch (scope.id) { + .root => @fieldParentPtr(Root, "base", scope).contains(name), + .block => @fieldParentPtr(Block, "base", scope).contains(name), + .loop, .do_loop, .condition => scope.parent.?.contains(name), + }; + } + + pub fn getBreakableScope(inner: *Scope) *Scope { + var scope = inner; + while (true) { + switch (scope.id) { + .root => unreachable, + .loop, .do_loop => return scope, + else => scope = scope.parent.?, + } + } + } + + /// Appends a node to the first block scope if inside a function, or to the root tree if not. + pub fn appendNode(inner: *Scope, node: Node) !void { + var scope = inner; + while (true) { + switch (scope.id) { + .root => { + const root = @fieldParentPtr(Root, "base", scope); + return root.nodes.append(node); + }, + .block => { + const block = @fieldParentPtr(Block, "base", scope); + return block.statements.append(node); + }, + else => scope = scope.parent.?, + } + } + } + + pub fn skipVariableDiscard(inner: *Scope, name: []const u8) void { + var scope = inner; + while (true) { + switch (scope.id) { + .root => return, + .block => { + const block = @fieldParentPtr(Block, "base", scope); + if (block.variable_discards.get(name)) |discard| { + discard.data.should_skip = true; + return; + } + }, + else => {}, + } + scope = scope.parent.?; + } + } + }; +}