tiny.choir.ir.dialects.opSpec
Defined in ir.dialects.
API (7)
Actions
Public operations.
Types and contracts
Public types and contracts.
Source
Source: lib/choir/src/core/dialects/spec.zig:926
zig
pub const opSpec = struct { pub const Options = struct { traits: interfaces.OperationTraits = .{}, attrs: []const []const u8 = &.{}, required_attrs: []const []const u8 = &.{}, attribute_specs: []const AttributeSpec = &.{}, operand_segments: ?interfaces.OperationSegmentSpec = null, result_segments: ?interfaces.OperationSegmentSpec = null, operand_types: []const interfaces.OperationTypeConstraint = &.{}, result_types: []const interfaces.OperationTypeConstraint = &.{}, properties: ?interfaces.OperationPropertiesModel = null, interfaces: []const interfaces.InterfaceEntry = &.{}, dynamic_traits: []const OperationTraitSpec = &.{}, }; pub fn dialect(comptime Target: type) type { const Names = namesFor(Target); return struct { pub fn name(comptime mnemonic: []const u8) []const u8 { return Names.name(mnemonic); } pub fn state(comptime OpType: type, loc: Location) Operation.State { return Names.state(OpType, loc); } pub fn define(comptime spec: anytype) OperationSpec { comptime validateDecl(@TypeOf(spec), "mnemonic"); return shapedWithLayout(Names.name(@field(spec, "mnemonic")), shapeFromDecl(spec), layoutFromDecl(spec), optionsFromDecl(spec)); } pub fn leaf(comptime spec: anytype) OperationSpec { comptime validateDecl(@TypeOf(spec), "mnemonic"); return shapedWithLayout(Names.name(@field(spec, "mnemonic")), leafShapeFromDecl(spec), layoutFromDecl(spec), optionsFromDecl(spec)); } pub fn terminator(comptime spec: anytype) OperationSpec { comptime validateDecl(@TypeOf(spec), "mnemonic"); return shapedWithLayout(Names.name(@field(spec, "mnemonic")), terminatorShapeFromDecl(spec), layoutFromDecl(spec), terminatorOptionsFromDecl(spec)); } }; } pub fn define(comptime spec: anytype) OperationSpec { comptime validateDecl(@TypeOf(spec), "name"); return shapedWithLayout(@field(spec, "name"), shapeFromDecl(spec), layoutFromDecl(spec), optionsFromDecl(spec)); } pub fn terminator(comptime spec: anytype) OperationSpec { comptime validateDecl(@TypeOf(spec), "name"); return shapedWithLayout(@field(spec, "name"), terminatorShapeFromDecl(spec), layoutFromDecl(spec), terminatorOptionsFromDecl(spec)); } pub fn shaped(comptime full_name: []const u8, comptime op_shape: interfaces.OperationShape, comptime options: Options) OperationSpec { return shapedWithLayout(full_name, op_shape, .{}, options); } pub fn dynamicTraits(comptime values: anytype) []const OperationTraitSpec { return asSlice(OperationTraitSpec, values, "dynamic_traits"); } pub fn verifier(comptime verify_fn: *const fn (op_ptr: *const anyopaque) anyerror!void) interfaces.InterfaceEntry { return VerifyOpInterface.entryFor(verify_fn); } fn shapedWithLayout(comptime full_name: []const u8, comptime op_shape: interfaces.OperationShape, comptime op_layout: OperationLayout, comptime options: Options) OperationSpec { if (full_name.len == 0) @compileError("operation name cannot be empty"); validateLayout(op_shape, op_layout); return .{ .name = full_name, .shape = op_shape, .operand_names = op_layout.operands, .result_names = op_layout.results, .region_names = op_layout.regions, .successor_names = op_layout.successors, .traits = options.traits, .inherent_attribute_names = attributeNamesWithRequired(options.attrs, options.required_attrs), .required_attribute_names = options.required_attrs, .attribute_specs = attributeSpecsWithNames(options.attribute_specs, attributeNamesWithRequired(options.attrs, options.required_attrs)), .operand_segments = options.operand_segments, .result_segments = options.result_segments, .operand_type_constraints = options.operand_types, .result_type_constraints = options.result_types, .properties_model = options.properties, .interfaces = options.interfaces, .dynamic_traits = options.dynamic_traits, }; } fn layoutFromDecl(comptime spec: anytype) OperationLayout { return .{ .operands = layoutField(spec, "operands", "operand_names"), .results = layoutField(spec, "results", "result_names"), .regions = layoutField(spec, "regions", "region_names"), .successors = layoutField(spec, "successors", "successor_names"), }; } fn shapeFromDecl(comptime spec: anytype) interfaces.OperationShape { const Spec = @TypeOf(spec); if (comptime @hasField(Spec, "shape")) { if (@hasField(Spec, "operands")) @compileError("operation declaration cannot specify both shape and operands"); if (@hasField(Spec, "results")) @compileError("operation declaration cannot specify both shape and results"); if (@hasField(Spec, "regions")) @compileError("operation declaration cannot specify both shape and regions"); if (@hasField(Spec, "successors")) @compileError("operation declaration cannot specify both shape and successors"); return shapeFromValue(@field(spec, "shape")); } return .{ .operands = shapeField(spec, "operands"), .results = shapeField(spec, "results"), .regions = shapeField(spec, "regions"), .successors = shapeField(spec, "successors"), }; } fn terminatorShapeFromDecl(comptime spec: anytype) interfaces.OperationShape { const Spec = @TypeOf(spec); if (@hasField(Spec, "shape")) @compileError("terminator operation declaration cannot specify shape"); return .{ .operands = shapeField(spec, "operands"), .results = shapeFieldOrExact(spec, "results", 0), .regions = shapeFieldOrExact(spec, "regions", 0), .successors = shapeFieldOrExact(spec, "successors", 0), }; } fn shapeFromValue(comptime value: anytype) interfaces.OperationShape { const Value = @TypeOf(value); if (Value == interfaces.OperationShape) return value; return shape.of(value); } fn leafShapeFromDecl(comptime spec: anytype) interfaces.OperationShape { const Spec = @TypeOf(spec); if (@hasField(Spec, "shape")) @compileError("leaf operation declaration cannot specify shape"); if (@hasField(Spec, "regions")) @compileError("leaf operation declaration cannot specify regions"); if (@hasField(Spec, "successors")) @compileError("leaf operation declaration cannot specify successors"); return .{ .operands = shapeField(spec, "operands"), .results = shapeField(spec, "results"), .regions = interfaces.CountRange.exactly(0), .successors = interfaces.CountRange.exactly(0), }; } fn shapeField(comptime spec: anytype, comptime name: []const u8) interfaces.CountRange { if (comptime @hasField(@TypeOf(spec), name)) return shape.rangeFrom(@field(spec, name)); return .{}; } fn layoutField(comptime spec: anytype, comptime shape_name: []const u8, comptime names_name: []const u8) []const []const u8 { const inferred = if (comptime @hasField(@TypeOf(spec), shape_name)) componentNamesFromValue(@field(spec, shape_name), shape_name) else &.{}; if (comptime @hasField(@TypeOf(spec), names_name)) { const explicit = componentNamesFromValue(@field(spec, names_name), names_name); if (inferred.len != 0) { @compileError("operation declaration cannot specify both named " ++ shape_name ++ " and " ++ names_name); } return explicit; } return inferred; } fn validateLayout(comptime op_shape: interfaces.OperationShape, comptime op_layout: OperationLayout) void { validateLayoutRange(op_shape.operands, op_layout.operands, "operand"); validateLayoutRange(op_shape.results, op_layout.results, "result"); validateLayoutRange(op_shape.regions, op_layout.regions, "region"); validateLayoutRange(op_shape.successors, op_layout.successors, "successor"); } fn validateLayoutRange(comptime range: interfaces.CountRange, comptime names: []const []const u8, comptime kind: []const u8) void { if (range.max) |max| { if (names.len > max) { @compileError("operation " ++ kind ++ " names cannot exceed the operation shape maximum"); } } } fn shapeFieldOrExact(comptime spec: anytype, comptime name: []const u8, comptime count: usize) interfaces.CountRange { if (comptime @hasField(@TypeOf(spec), name)) return shape.rangeFrom(@field(spec, name)); return interfaces.CountRange.exactly(count); } fn optionsFromDecl(comptime spec: anytype) Options { const attr_specs = attributeSpecsFromDecl(spec, "attrs"); const required_attr_specs = attributeSpecsFromDecl(spec, "required_attrs"); return .{ .traits = declField(spec, "traits", interfaces.OperationTraits{}), .attrs = attributeNamesFromSpecs(attr_specs), .required_attrs = attributeNamesFromSpecs(required_attr_specs), .attribute_specs = attributeSpecsWithRequired(attr_specs, required_attr_specs), .operand_segments = segmentDecl(spec, "operand_segments"), .result_segments = segmentDecl(spec, "result_segments"), .operand_types = declSlice(interfaces.OperationTypeConstraint, spec, "operand_types"), .result_types = declSlice(interfaces.OperationTypeConstraint, spec, "result_types"), .properties = declField(spec, "properties", @as(?interfaces.OperationPropertiesModel, null)), .interfaces = declSlice(interfaces.InterfaceEntry, spec, "interfaces"), .dynamic_traits = if (comptime @hasField(@TypeOf(spec), "dynamic_traits")) dynamicTraits(@field(spec, "dynamic_traits")) else &.{}, }; } fn terminatorOptionsFromDecl(comptime spec: anytype) Options { return optionsWithDynamicTrait(optionsFromDecl(spec), trait(core_traits.Terminator)); } fn declField(comptime spec: anytype, comptime name: []const u8, comptime default: anytype) @TypeOf(default) { if (comptime @hasField(@TypeOf(spec), name)) return @field(spec, name); return default; } fn declSlice(comptime Element: type, comptime spec: anytype, comptime name: []const u8) []const Element { if (comptime !@hasField(@TypeOf(spec), name)) return &.{}; return asSlice(Element, @field(spec, name), name); } fn segmentDecl(comptime spec: anytype, comptime name: []const u8) ?interfaces.OperationSegmentSpec { if (comptime !@hasField(@TypeOf(spec), name)) return null; const value = @field(spec, name); if (@TypeOf(value) != interfaces.OperationSegmentSpec) { @compileError("operation declaration field " ++ name ++ " must be an OperationSegmentSpec"); } return value; } fn asSlice(comptime Element: type, comptime values: anytype, comptime name: []const u8) []const Element { const Values = @TypeOf(values); if (Values == []const Element) return values; switch (@typeInfo(Values)) { .pointer => |pointer_info| { switch (pointer_info.size) { .one => switch (@typeInfo(pointer_info.child)) { .array => |array_info| { const typed = comptime blk: { var out: [array_info.len]Element = undefined; for (values.*, 0..) |value, index| { out[index] = asElement(Element, value); } break :blk out; }; return &typed; }, .@"struct" => |struct_info| { if (!struct_info.is_tuple) @compileError("operation declaration field " ++ name ++ " must be a comptime slice, array, or tuple"); const typed = comptime blk: { var out: [struct_info.field_names.len]Element = undefined; for (struct_info.field_names, 0..) |field_name, index| { out[index] = asElement(Element, @field(values.*, field_name)); } break :blk out; }; return &typed; }, else => @compileError("operation declaration field " ++ name ++ " must be a comptime slice or array pointer"), }, .slice => { const typed = comptime blk: { var out: [values.len]Element = undefined; for (values, 0..) |value, index| { out[index] = asElement(Element, value); } break :blk out; }; return &typed; }, else => @compileError("operation declaration field " ++ name ++ " must be a comptime slice or array pointer"), } }, .array => |array_info| { const typed = comptime blk: { var out: [array_info.len]Element = undefined; for (values, 0..) |value, index| { out[index] = asElement(Element, value); } break :blk out; }; return &typed; }, .@"struct" => |struct_info| { if (!struct_info.is_tuple) @compileError("operation declaration field " ++ name ++ " must be a comptime slice, array, or tuple"); const typed = comptime blk: { var out: [struct_info.field_names.len]Element = undefined; for (struct_info.field_names, 0..) |field_name, index| { out[index] = asElement(Element, @field(values, field_name)); } break :blk out; }; return &typed; }, else => @compileError("operation declaration field " ++ name ++ " must be a comptime slice or array pointer"), } } fn asElement(comptime Element: type, comptime value: anytype) Element { const Value = @TypeOf(value); if (Element == OperationTraitSpec and Value == type) return trait(value); if (Value == Element) return value; return switch (@typeInfo(Element)) { .@"struct" => |element_info| blk: { var out: Element = undefined; for (element_info.field_names) |field_name| { @field(out, field_name) = @field(value, field_name); } break :blk out; }, else => value, }; } fn optionsWithDynamicTrait(comptime options: Options, comptime trait_spec: OperationTraitSpec) Options { return .{ .traits = options.traits.merge(trait_spec.traits), .attrs = options.attrs, .required_attrs = options.required_attrs, .attribute_specs = options.attribute_specs, .operand_segments = options.operand_segments, .result_segments = options.result_segments, .operand_types = options.operand_types, .result_types = options.result_types, .properties = options.properties, .interfaces = options.interfaces, .dynamic_traits = dynamicTraitsWith(options.dynamic_traits, trait_spec), }; } fn dynamicTraitsWith(comptime dynamic_traits: []const OperationTraitSpec, comptime trait_spec: OperationTraitSpec) []const OperationTraitSpec { for (dynamic_traits) |existing| { if (existing.id == trait_spec.id) @compileError("operation dynamic trait is duplicated"); } const values = comptime blk: { var out: [dynamic_traits.len + 1]OperationTraitSpec = undefined; for (dynamic_traits, 0..) |existing, index| { out[index] = existing; } out[dynamic_traits.len] = trait_spec; break :blk out; }; return &values; } fn validateDecl(comptime Spec: type, comptime name_field: []const u8) void { switch (@typeInfo(Spec)) { .@"struct" => |struct_info| { if (!@hasField(Spec, name_field)) @compileError("operation declaration must declare " ++ name_field); inline for (struct_info.field_names) |field_name| { if (!isDeclField(field_name, name_field)) { @compileError("unknown operation declaration field: " ++ field_name); } } }, else => @compileError("operation declaration must be a struct literal"), } } fn isDeclField(comptime field_name: []const u8, comptime name_field: []const u8) bool { return std.mem.eql(u8, field_name, name_field) or std.mem.eql(u8, field_name, "shape") or std.mem.eql(u8, field_name, "operands") or std.mem.eql(u8, field_name, "operand_names") or std.mem.eql(u8, field_name, "results") or std.mem.eql(u8, field_name, "result_names") or std.mem.eql(u8, field_name, "regions") or std.mem.eql(u8, field_name, "region_names") or std.mem.eql(u8, field_name, "successors") or std.mem.eql(u8, field_name, "successor_names") or std.mem.eql(u8, field_name, "traits") or std.mem.eql(u8, field_name, "attrs") or std.mem.eql(u8, field_name, "required_attrs") or std.mem.eql(u8, field_name, "operand_segments") or std.mem.eql(u8, field_name, "result_segments") or std.mem.eql(u8, field_name, "operand_types") or std.mem.eql(u8, field_name, "result_types") or std.mem.eql(u8, field_name, "properties") or std.mem.eql(u8, field_name, "interfaces") or std.mem.eql(u8, field_name, "dynamic_traits"); } fn namesFor(comptime Target: type) type { if (comptime isDialectType(Target)) return operationNames(Target); if (comptime isOperationNamesType(Target)) return Target; @compileError("opSpec.dialect expects a dialect type or operationNames result"); } fn isDialectType(comptime Target: type) bool { if (!@hasDecl(Target, "name")) return false; return switch (@typeInfo(@TypeOf(@field(Target, "name")))) { .pointer => true, else => false, }; } fn isOperationNamesType(comptime Target: type) bool { if (!@hasDecl(Target, "name")) return false; if (!@hasDecl(Target, "state")) return false; return switch (@typeInfo(@TypeOf(@field(Target, "name")))) { .@"fn" => true, else => false, }; }};Source: lib/choir/src/core/dialects/root.zig:48
zig
pub const opSpec = spec.opSpec;Also reachable as
backends.wasm.emission.module_encoding.common.ir.dialects.opSpec.
Complete caller list for ir.dialects.opSpec.dialect
10 direct callers.
tiny.choir.ir.dialects.operationTemplate.explicit[function] atlib/choir/src/core/dialects/spec.zig:1758tiny.choir.ir.dialects.operationTemplate.explicitLeaf[function] atlib/choir/src/core/dialects/spec.zig:1682tiny.choir.ir.dialects.operationTemplate.explicitTerminator[function] atlib/choir/src/core/dialects/spec.zig:1847lib.choir.src.core.dialects.spec.test_DialectSpec_derives_verifier_and_CSE_interfaces_from_operation_declarations[function] — test source atlib/choir/src/core/dialects/spec.zig:4408in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.test_DialectSpec_registers_operations,_interfaces,_traits,_types,_and_dialect_interfaces[function] — test source atlib/choir/src/core/dialects/spec.zig:4260in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.test_operation_descriptor_DSL_builds_dialect_operation_sets[function] — test source atlib/choir/src/core/dialects/spec.zig:3414in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.test_operation_descriptor_DSL_exports_compact_operation_metadata[function] — test source atlib/choir/src/core/dialects/spec.zig:3097in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.test_operation_descriptor_required_attrs_are_inherent_attrs[function] — test source atlib/choir/src/core/dialects/spec.zig:3261in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.test_operation_segment_helpers_set_attributes_and_read_named_segments[function] — test source atlib/choir/src/core/dialects/spec.zig:3201in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.test_operations_derives_operation_specs_from_descriptors[function] — test source atlib/choir/src/core/dialects/spec.zig:3077in nearest public ownerlib.choir.src.core.dialects.spec
Complete call list for ir.dialects.opSpec.dialect
9 direct calls.
lib.choir.src.core.dialects.spec.opSpec.layoutFromDecl[function] — private source atlib/choir/src/core/dialects/spec.zig:1015in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.opSpec.leafShapeFromDecl[function] — private source atlib/choir/src/core/dialects/spec.zig:1058in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.opSpec.namesFor[function] — private source atlib/choir/src/core/dialects/spec.zig:1304in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.opSpec.optionsFromDecl[function] — private source atlib/choir/src/core/dialects/spec.zig:1111in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.opSpec.shapeFromDecl[function] — private source atlib/choir/src/core/dialects/spec.zig:1024in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.opSpec.shapedWithLayout[function] — private source atlib/choir/src/core/dialects/spec.zig:991in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.opSpec.terminatorOptionsFromDecl[function] — private source atlib/choir/src/core/dialects/spec.zig:1129in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.opSpec.terminatorShapeFromDecl[function] — private source atlib/choir/src/core/dialects/spec.zig:1041in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.opSpec.validateDecl[function] — private source atlib/choir/src/core/dialects/spec.zig:1267in nearest public ownerlib.choir.src.core.dialects.spec
Complete caller list for ir.dialects.opSpec.shaped
9 direct callers.
lib.choir.src.core.dialects.spec.operationTemplate.binaryFixedResultImpl[function] — private source atlib/choir/src/core/dialects/spec.zig:1975in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.operationTemplate.binarySameTypeImpl[function] — private source atlib/choir/src/core/dialects/spec.zig:1908in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.operationTemplate.selectSameTypeImpl[function] — private source atlib/choir/src/core/dialects/spec.zig:2302in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.operationTemplate.ternarySameTypeImpl[function] — private source atlib/choir/src/core/dialects/spec.zig:2227in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.operationTemplate.unaryExplicitTypeImpl[function] — private source atlib/choir/src/core/dialects/spec.zig:2142in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.operationTemplate.unaryFixedResultImpl[function] — private source atlib/choir/src/core/dialects/spec.zig:2070in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.operationTemplate.unaryNoResultImpl[function] — private source atlib/choir/src/core/dialects/spec.zig:2201in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.operationTemplate.unarySameTypeImpl[function] — private source atlib/choir/src/core/dialects/spec.zig:2011in nearest public ownerlib.choir.src.core.dialects.speclib.choir.src.core.dialects.spec.operationTemplate.unarySameTypeStringAttrImpl[function] — private source atlib/choir/src/core/dialects/spec.zig:2102in nearest public ownerlib.choir.src.core.dialects.spec
Audit
| Definitions | 8 |
|---|---|
| Public names | 16 |
| Members | 11 |
| Version | 26.7.0 |
| Revision | daab053ee433 |