Appearance
Add a custom instruction
A custom instruction starts as an ordinary function import. Wago replaces calls to that import while compiling the guest.
Pick the guest ABI
This WAT import carries two four-bit values through normal i32 parameters:
wat
(import "wago:instr/example.int" "i4.add"
(func $i4.add (param i32 i32) (result i32)))Any language that can emit the same import can use it.
Request the module
Request compiler.instruction.define with wago:instr/example.int in Scope.Modules.
Define its meaning
Get Registrar.CompilerInstructions, then define the logical widths and portable handler:
go
Input: []int32{4, 4},
Output: []int32{4},
Handler: func(_ wago.InstructionContext, in []wago.Bits) ([]wago.Bits, error) {
value, err := wago.BitsFromUint32(4, in[0].Uint32()+in[1].Uint32())
return []wago.Bits{value}, err
},The handler is the fallback and the executable definition of the operation.
Add a scalar lowering
go
Lower: func(ctx wago.LoweringContext) error {
ctx.Output(0, ctx.Add(ctx.Input(0), ctx.Input(1)))
return nil
},Wago can inline this recipe on supported backends. The portable handler remains available elsewhere.
Use target-specific code generation only when the scalar recipe cannot express the operation. Raw AMD64 or ARM64 emission is trusted backend code and needs architecture-tagged files.
Run examples/18-custom-instruction for the complete plugin and WAT guest.
