lib/choir/src/backends/artifact/serialization/linkage.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const std = @import("std");
  2 const artifact = @import("../root.zig");
  3 const format = @import("root.zig").format;
  4 
  5 const Signature = artifact.Signature;
  6 
  7 pub fn write(writer: *format.Writer, value: artifact.Linkage) format.WriteError!void {
  8     try writer.writeCount(value.required_symbols.items.len);
  9     for (value.required_symbols.items) |symbol| try writeSymbol(writer, symbol);
 10     try writer.writeCount(value.provided_symbols.items.len);
 11     for (value.provided_symbols.items) |symbol| try writeSymbol(writer, symbol);
 12     try writer.writeCount(value.relocations.items.len);
 13     for (value.relocations.items) |relocation| {
 14         try writer.writeInt(u64, relocation.offset);
 15         try writer.writeString(relocation.symbol);
 16         try writer.writeTag(relocation.kind);
 17         try writer.writeInt(i64, relocation.addend);
 18         try writer.writeOptionalU16(relocation.width_bits);
 19     }
 20 }
 21 
 22 pub fn readInto(reader: *format.Reader, value: *artifact.Linkage) (format.Error || std.mem.Allocator.Error)!void {
 23     const required_count = try reader.readCount();
 24     for (0..required_count) |_| try value.addRequired(try readSymbol(reader));
 25     const provided_count = try reader.readCount();
 26     for (0..provided_count) |_| try value.addProvided(try readSymbol(reader));
 27     const relocation_count = try reader.readCount();
 28     for (0..relocation_count) |_| {
 29         try value.addRelocation(.{
 30             .offset = try reader.readInt(u64),
 31             .symbol = try reader.readString(),
 32             .kind = try reader.readTag(artifact.RelocationKind),
 33             .addend = try reader.readInt(i64),
 34             .width_bits = try reader.readOptionalU16(),
 35         });
 36     }
 37 }
 38 
 39 fn writeSymbol(writer: *format.Writer, symbol: artifact.Symbol) format.WriteError!void {
 40     try writer.writeString(symbol.name);
 41     try writer.writeTag(symbol.kind);
 42     try writer.writeTag(symbol.binding);
 43     try writer.writeBool(symbol.signature != null);
 44     if (symbol.signature) |*signature| try writeSignature(writer, signature);
 45 }
 46 
 47 fn readSymbol(reader: *format.Reader) format.Error!artifact.Symbol {
 48     const name = try reader.readString();
 49     const kind = try reader.readTag(artifact.SymbolKind);
 50     const binding = try reader.readTag(artifact.SymbolBinding);
 51     const signature: ?Signature = if (try reader.readBool()) try readSignature(reader) else null;
 52     return .{ .name = name, .kind = kind, .binding = binding, .signature = signature };
 53 }
 54 
 55 fn writeSignature(writer: *format.Writer, signature: *const Signature) format.WriteError!void {
 56     std.debug.assert(signature.isValid());
 57     try writer.writeInt(u8, signature.parameter_count);
 58     try writer.writeInt(u8, signature.result_count);
 59     for (signature.parameters()) |value_type| try writeValueType(writer, value_type);
 60     for (signature.results()) |value_type| try writeValueType(writer, value_type);
 61 }
 62 
 63 fn readSignature(reader: *format.Reader) format.Error!Signature {
 64     const parameter_count = try reader.readInt(u8);
 65     const result_count = try reader.readInt(u8);
 66     if (parameter_count > Signature.max_parameters) return error.LimitExceeded;
 67     if (result_count > Signature.max_results) return error.LimitExceeded;
 68     var parameters: [Signature.max_parameters]artifact.ValueType = undefined;
 69     for (parameters[0..parameter_count]) |*value_type| value_type.* = try readValueType(reader);
 70     var results: [Signature.max_results]artifact.ValueType = undefined;
 71     for (results[0..result_count]) |*value_type| value_type.* = try readValueType(reader);
 72     const signature = Signature.init(
 73         parameters[0..parameter_count],
 74         results[0..result_count],
 75     ) catch |err| switch (err) {
 76         error.TooManyParameters, error.TooManyResults => unreachable,
 77         error.InvalidValueType => return error.InvalidValue,
 78     };
 79     std.debug.assert(signature.parameter_count == parameter_count);
 80     std.debug.assert(signature.result_count == result_count);
 81     return signature;
 82 }
 83 
 84 fn writeValueType(writer: *format.Writer, value_type: artifact.ValueType) format.WriteError!void {
 85     try writer.writeTag(std.meta.activeTag(value_type));
 86     switch (value_type) {
 87         .scalar => |scalar| try writer.writeTag(scalar),
 88         .memref => {},
 89         .vector => |vector| {
 90             try writer.writeTag(vector.element);
 91             try writer.writeInt(u8, vector.lanes);
 92         },
 93     }
 94 }
 95 
 96 fn readValueType(reader: *format.Reader) format.Error!artifact.ValueType {
 97     return switch (try reader.readTag(artifact.ValueKind)) {
 98         .scalar => .{ .scalar = try reader.readTag(artifact.ScalarType) },
 99         .memref => .memref,
100         .vector => .{ .vector = .{
101             .element = try reader.readTag(artifact.ScalarType),
102             .lanes = try reader.readInt(u8),
103         } },
104     };
105 }