wa-lang.org/wazero@v1.0.2/internal/wazeroir/format.go (about)

     1  package wazeroir
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"strings"
     8  )
     9  
    10  const EntrypointLabel = ".entrypoint"
    11  
    12  func Format(ops []Operation) string {
    13  	buf := bytes.NewBuffer(nil)
    14  
    15  	_, _ = buf.WriteString(EntrypointLabel + "\n")
    16  	for _, op := range ops {
    17  		formatOperation(buf, op)
    18  	}
    19  
    20  	return buf.String()
    21  }
    22  
    23  func formatOperation(w io.StringWriter, b Operation) {
    24  	var str string
    25  	var isLabel bool
    26  	switch o := b.(type) {
    27  	case *OperationUnreachable:
    28  		str = "unreachable"
    29  	case *OperationLabel:
    30  		isLabel = true
    31  		str = fmt.Sprintf("%s:", o.Label.asBranchTarget())
    32  	case *OperationBr:
    33  		str = fmt.Sprintf("br %s", o.Target.String())
    34  	case *OperationBrIf:
    35  		str = fmt.Sprintf("br_if %s, %s", o.Then, o.Else)
    36  	case *OperationBrTable:
    37  		targets := make([]string, len(o.Targets))
    38  		for i, t := range o.Targets {
    39  			targets[i] = t.String()
    40  		}
    41  		str = fmt.Sprintf("br_table [%s] %s", strings.Join(targets, ","), o.Default)
    42  	case *OperationCall:
    43  		str = fmt.Sprintf("call %d", o.FunctionIndex)
    44  	case *OperationCallIndirect:
    45  		str = fmt.Sprintf("call_indirect: type=%d, table=%d", o.TypeIndex, o.TableIndex)
    46  	case *OperationDrop:
    47  		str = fmt.Sprintf("drop %d..%d", o.Depth.Start, o.Depth.End)
    48  	case *OperationSelect:
    49  		str = "select"
    50  	case *OperationPick:
    51  		str = fmt.Sprintf("pick %d (is_vector=%v)", o.Depth, o.IsTargetVector)
    52  	case *OperationSet:
    53  		str = fmt.Sprintf("swap %d (is_vector=%v)", o.Depth, o.IsTargetVector)
    54  	case *OperationGlobalGet:
    55  		str = fmt.Sprintf("global.get %d", o.Index)
    56  	case *OperationGlobalSet:
    57  		str = fmt.Sprintf("global.set %d", o.Index)
    58  	case *OperationLoad:
    59  		str = fmt.Sprintf("%s.load (align=%d, offset=%d)", o.Type, o.Arg.Alignment, o.Arg.Offset)
    60  	case *OperationLoad8:
    61  		str = fmt.Sprintf("%s.load8 (align=%d, offset=%d)", o.Type, o.Arg.Alignment, o.Arg.Offset)
    62  	case *OperationLoad16:
    63  		str = fmt.Sprintf("%s.load16 (align=%d, offset=%d)", o.Type, o.Arg.Alignment, o.Arg.Offset)
    64  	case *OperationLoad32:
    65  		var t string
    66  		if o.Signed {
    67  			t = "i64"
    68  		} else {
    69  			t = "u64"
    70  		}
    71  		str = fmt.Sprintf("%s.load32 (align=%d, offset=%d)", t, o.Arg.Alignment, o.Arg.Offset)
    72  	case *OperationStore:
    73  		str = fmt.Sprintf("%s.store (align=%d, offset=%d)", o.Type, o.Arg.Alignment, o.Arg.Offset)
    74  	case *OperationStore8:
    75  		str = fmt.Sprintf("store8 (align=%d, offset=%d)", o.Arg.Alignment, o.Arg.Offset)
    76  	case *OperationStore16:
    77  		str = fmt.Sprintf("store16 (align=%d, offset=%d)", o.Arg.Alignment, o.Arg.Offset)
    78  	case *OperationStore32:
    79  		str = fmt.Sprintf("i64.store32 (align=%d, offset=%d)", o.Arg.Alignment, o.Arg.Offset)
    80  	case *OperationMemorySize:
    81  		str = "memory.size"
    82  	case *OperationMemoryGrow:
    83  		str = "memory.grow"
    84  	case *OperationConstI32:
    85  		str = fmt.Sprintf("i32.const %d", o.Value)
    86  	case *OperationConstI64:
    87  		str = fmt.Sprintf("i64.const %d", o.Value)
    88  	case *OperationConstF32:
    89  		str = fmt.Sprintf("f32.const %f", o.Value)
    90  	case *OperationConstF64:
    91  		str = fmt.Sprintf("f64.const %f", o.Value)
    92  	case *OperationEq:
    93  		str = fmt.Sprintf("%s.eq", o.Type)
    94  	case *OperationNe:
    95  		str = fmt.Sprintf("%s.ne", o.Type)
    96  	case *OperationEqz:
    97  		str = fmt.Sprintf("%s.eqz", o.Type)
    98  	case *OperationLt:
    99  		str = fmt.Sprintf("%s.lt", o.Type)
   100  	case *OperationGt:
   101  		str = fmt.Sprintf("%s.gt", o.Type)
   102  	case *OperationLe:
   103  		str = fmt.Sprintf("%s.le", o.Type)
   104  	case *OperationGe:
   105  		str = fmt.Sprintf("%s.ge", o.Type)
   106  	case *OperationAdd:
   107  		str = fmt.Sprintf("%s.add", o.Type)
   108  	case *OperationSub:
   109  		str = fmt.Sprintf("%s.sub", o.Type)
   110  	case *OperationMul:
   111  		str = fmt.Sprintf("%s.mul", o.Type)
   112  	case *OperationClz:
   113  		str = fmt.Sprintf("%s.clz", o.Type)
   114  	case *OperationCtz:
   115  		str = fmt.Sprintf("%s.ctz", o.Type)
   116  	case *OperationPopcnt:
   117  		str = fmt.Sprintf("%s.popcnt", o.Type)
   118  	case *OperationDiv:
   119  		str = fmt.Sprintf("%s.div", o.Type)
   120  	case *OperationRem:
   121  		str = fmt.Sprintf("%s.rem", o.Type)
   122  	case *OperationAnd:
   123  		str = fmt.Sprintf("%s.and", o.Type)
   124  	case *OperationOr:
   125  		str = fmt.Sprintf("%s.or", o.Type)
   126  	case *OperationXor:
   127  		str = fmt.Sprintf("%s.xor", o.Type)
   128  	case *OperationShl:
   129  		str = fmt.Sprintf("%s.shl", o.Type)
   130  	case *OperationShr:
   131  		str = fmt.Sprintf("%s.shr", o.Type)
   132  	case *OperationRotl:
   133  		str = fmt.Sprintf("%s.rotl", o.Type)
   134  	case *OperationRotr:
   135  		str = fmt.Sprintf("%s.rotr", o.Type)
   136  	case *OperationAbs:
   137  		str = fmt.Sprintf("%s.abs", o.Type)
   138  	case *OperationNeg:
   139  		str = fmt.Sprintf("%s.neg", o.Type)
   140  	case *OperationCeil:
   141  		str = fmt.Sprintf("%s.ceil", o.Type)
   142  	case *OperationFloor:
   143  		str = fmt.Sprintf("%s.floor", o.Type)
   144  	case *OperationTrunc:
   145  		str = fmt.Sprintf("%s.trunc", o.Type)
   146  	case *OperationNearest:
   147  		str = fmt.Sprintf("%s.nearest", o.Type)
   148  	case *OperationSqrt:
   149  		str = fmt.Sprintf("%s.sqrt", o.Type)
   150  	case *OperationMin:
   151  		str = fmt.Sprintf("%s.min", o.Type)
   152  	case *OperationMax:
   153  		str = fmt.Sprintf("%s.max", o.Type)
   154  	case *OperationCopysign:
   155  		str = fmt.Sprintf("%s.copysign", o.Type)
   156  	case *OperationI32WrapFromI64:
   157  		str = "i32.wrap_from.i64"
   158  	case *OperationITruncFromF:
   159  		str = fmt.Sprintf("%s.truncate_from.%s", o.OutputType, o.InputType)
   160  	case *OperationFConvertFromI:
   161  		str = fmt.Sprintf("%s.convert_from.%s", o.OutputType, o.InputType)
   162  	case *OperationF32DemoteFromF64:
   163  		str = "f32.demote_from.f64"
   164  	case *OperationF64PromoteFromF32:
   165  		str = "f64.promote_from.f32"
   166  	case *OperationI32ReinterpretFromF32:
   167  		str = "i32.reinterpret_from.f32"
   168  	case *OperationI64ReinterpretFromF64:
   169  		str = "i64.reinterpret_from.f64"
   170  	case *OperationF32ReinterpretFromI32:
   171  		str = "f32.reinterpret_from.i32"
   172  	case *OperationF64ReinterpretFromI64:
   173  		str = "f64.reinterpret_from.i64"
   174  	case *OperationExtend:
   175  		var in, out string
   176  		if o.Signed {
   177  			in = "i32"
   178  			out = "i64"
   179  		} else {
   180  			in = "u32"
   181  			out = "u64"
   182  		}
   183  		str = fmt.Sprintf("%s.extend_from.%s", out, in)
   184  	case *OperationV128Const:
   185  		str = fmt.Sprintf("v128.const [%#x, %#x]", o.Lo, o.Hi)
   186  	case *OperationV128Add:
   187  		str = fmt.Sprintf("v128.add (shape=%s)", shapeName(o.Shape))
   188  	case *OperationV128ITruncSatFromF:
   189  		if o.Signed {
   190  			str = fmt.Sprintf("v128.ITruncSatFrom%sS", shapeName(o.OriginShape))
   191  		} else {
   192  			str = fmt.Sprintf("v128.ITruncSatFrom%sU", shapeName(o.OriginShape))
   193  		}
   194  	default:
   195  		panic("unreachable: a bug in wazeroir implementation")
   196  	}
   197  
   198  	if !isLabel {
   199  		const indent = "\t"
   200  		str = indent + str
   201  	}
   202  
   203  	_, _ = w.WriteString(str + "\n")
   204  }