lib/choir/src/backends/wasm/emission/function/instruction/writer.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const std = @import("std");
  2 const wasm = @import("../../../root.zig");
  3 const ir = @import("../../../../../core/root.zig");
  4 const dialects = @import("../../../../../dialects/root.zig");
  5 const emission = @import("../../root.zig");
  6 const instruction = @import("root.zig");
  7 
  8 const ArithDialect = dialects.ArithDialect;
  9 const FuncDialect = dialects.FuncDialect;
 10 const MemrefDialect = dialects.MemrefDialect;
 11 
 12 pub fn Writer(comptime Out: type) type {
 13     return struct {
 14         out: Out,
 15         plan: *const emission.Plan,
 16         function_ordinal: usize,
 17 
 18         const Self = @This();
 19 
 20         pub fn writeOperation(self: *Self, operation: *ir.Operation) emission.Error!void {
 21             const name = operation.name.name;
 22             if (std.mem.eql(u8, name, ArithDialect.ConstantOp.operation_name)) {
 23                 return instruction.arithmetic.lowering.writeConstant(Out, self, operation);
 24             }
 25             if (std.mem.eql(u8, name, ArithDialect.AddOp.operation_name)) {
 26                 return instruction.arithmetic.lowering.writeBinary(Out, self, operation, .add);
 27             }
 28             if (std.mem.eql(u8, name, ArithDialect.SubOp.operation_name)) {
 29                 return instruction.arithmetic.lowering.writeBinary(Out, self, operation, .sub);
 30             }
 31             if (std.mem.eql(u8, name, ArithDialect.MulOp.operation_name)) {
 32                 return instruction.arithmetic.lowering.writeBinary(Out, self, operation, .mul);
 33             }
 34             if (std.mem.eql(u8, name, ArithDialect.DivOp.operation_name)) {
 35                 return instruction.arithmetic.lowering.writeBinary(Out, self, operation, .div);
 36             }
 37             if (std.mem.eql(u8, name, ArithDialect.RemOp.operation_name)) {
 38                 return instruction.arithmetic.lowering.writeBinary(Out, self, operation, .rem);
 39             }
 40             if (std.mem.eql(u8, name, ArithDialect.AndOp.operation_name)) {
 41                 return instruction.arithmetic.lowering.writeBinary(Out, self, operation, .band);
 42             }
 43             if (std.mem.eql(u8, name, ArithDialect.OrOp.operation_name)) {
 44                 return instruction.arithmetic.lowering.writeBinary(Out, self, operation, .bor);
 45             }
 46             if (std.mem.eql(u8, name, ArithDialect.XorOp.operation_name)) {
 47                 return instruction.arithmetic.lowering.writeBinary(Out, self, operation, .bxor);
 48             }
 49             if (std.mem.eql(u8, name, ArithDialect.ShlOp.operation_name)) {
 50                 return instruction.arithmetic.lowering.writeBinary(Out, self, operation, .shl);
 51             }
 52             if (std.mem.eql(u8, name, ArithDialect.ShrOp.operation_name)) {
 53                 return instruction.arithmetic.lowering.writeBinary(Out, self, operation, .shr);
 54             }
 55             if (std.mem.eql(u8, name, ArithDialect.UshrOp.operation_name)) {
 56                 return instruction.arithmetic.lowering.writeBinary(Out, self, operation, .ushr);
 57             }
 58             if (std.mem.eql(u8, name, ArithDialect.CmpOp.operation_name)) {
 59                 return instruction.arithmetic.lowering.writeCmp(Out, self, operation);
 60             }
 61             if (std.mem.eql(u8, name, ArithDialect.SelectOp.operation_name)) {
 62                 return instruction.arithmetic.lowering.writeSelect(Out, self, operation);
 63             }
 64             if (std.mem.eql(u8, name, ArithDialect.NegOp.operation_name)) {
 65                 return instruction.arithmetic.lowering.writeNeg(Out, self, operation);
 66             }
 67             if (std.mem.eql(u8, name, ArithDialect.AbsOp.operation_name)) {
 68                 return instruction.arithmetic.lowering.writeAbs(Out, self, operation);
 69             }
 70             if (std.mem.eql(u8, name, ArithDialect.SqrtOp.operation_name)) {
 71                 return instruction.arithmetic.lowering.writeSqrt(Out, self, operation);
 72             }
 73             if (std.mem.eql(u8, name, ArithDialect.BitcastOp.operation_name)) {
 74                 return instruction.cast.write(Out, self, operation, true);
 75             }
 76             if (std.mem.eql(u8, name, ArithDialect.CastOp.operation_name)) {
 77                 return instruction.cast.write(Out, self, operation, false);
 78             }
 79             if (std.mem.eql(u8, name, FuncDialect.CallOp.operation_name)) {
 80                 return instruction.call.write(Out, self, operation);
 81             }
 82             if (std.mem.eql(u8, name, MemrefDialect.LoadOp.operation_name)) {
 83                 return instruction.memory.writeLoad(Out, self, operation);
 84             }
 85             if (std.mem.eql(u8, name, MemrefDialect.StoreOp.operation_name)) {
 86                 return instruction.memory.writeStore(Out, self, operation);
 87             }
 88             inline for (.{ ArithDialect.AddoOp, ArithDialect.SuboOp, ArithDialect.MuloOp }) |Op| {
 89                 if (std.mem.eql(u8, name, Op.operation_name)) return error.UnsupportedOperation;
 90             }
 91             return error.CodeGenFailed;
 92         }
 93 
 94         pub fn writeValue(self: *Self, value: *ir.Value) emission.Error!void {
 95             try self.writeLocalGet(try self.localFor(value));
 96         }
 97 
 98         pub fn writeLocalGet(self: *Self, local: u32) emission.Error!void {
 99             try self.out.writeByte(0x20);
100             try wasm.binary.writeUleb(self.out, local);
101         }
102 
103         pub fn writeLocalSet(self: *Self, local: u32) emission.Error!void {
104             try self.out.writeByte(0x21);
105             try wasm.binary.writeUleb(self.out, local);
106         }
107 
108         pub fn localFor(self: *const Self, value: *ir.Value) emission.Error!u32 {
109             return self.plan.localFor(self.function_ordinal, value) orelse
110                 error.CodeGenFailed;
111         }
112     };
113 }