diff --git a/internal/backends/compiler_wat/wir/wat/function.go b/internal/backends/compiler_wat/wir/wat/function.go index ca8e24e..2dde905 100644 --- a/internal/backends/compiler_wat/wir/wat/function.go +++ b/internal/backends/compiler_wat/wir/wat/function.go @@ -2,47 +2,68 @@ package wat -func (f *Function) Format(indent string) string { - s := indent + "(func $" + f.InternalName +import "strings" + +func (f *Function) Format(sb *strings.Builder) { + sb.WriteString("(func $") + sb.WriteString(f.InternalName) + if len(f.ExternalName) > 0 { - s += " (export \"" + f.ExternalName + "\")" + sb.WriteString(" (export \"") + sb.WriteString(f.ExternalName) + sb.WriteString("\")") } for _, param := range f.Params { - s += " (param $" + param.Name() + " " + param.Type().Name() + ")" + sb.WriteString(" (param $") + sb.WriteString(param.Name()) + sb.WriteByte(' ') + sb.WriteString(param.Type().Name()) + sb.WriteByte(')') } if len(f.Results) > 0 { - s += " (result" + sb.WriteString(" (result") for _, r := range f.Results { - s += " " + r.Name() + sb.WriteByte(' ') + sb.WriteString(r.Name()) } - s += ")" + sb.WriteByte(')') } - s += "\n" + sb.WriteByte('\n') for _, local := range f.Locals { - s += indent - s += " (local $" + local.Name() + " " + local.Type().Name() + ")" - s += "\n" + sb.WriteString(" (local $") + sb.WriteString(local.Name()) + sb.WriteByte(' ') + sb.WriteString(local.Type().Name()) + sb.WriteByte(')') + sb.WriteByte('\n') } + indent_t := " " for _, inst := range f.Insts { - s += inst.Format(indent+" ") + "\n" + inst.Format(indent_t, sb) + sb.WriteByte('\n') } - s += indent + ") ;;" + f.InternalName - return s + sb.WriteString(") ;;") + sb.WriteString(f.InternalName) } func (sig *FuncSig) String() string { - str := "" + var sb strings.Builder + for _, param := range sig.Params { - str += " (param " + param.Name() + ")" + sb.WriteString(" (param ") + sb.WriteString(param.Name()) + sb.WriteByte(')') } for _, ret := range sig.Results { - str += " (result " + ret.Name() + ")" + sb.WriteString(" (result ") + sb.WriteString(ret.Name()) + sb.WriteByte(')') } - return str + return sb.String() } diff --git a/internal/backends/compiler_wat/wir/wat/import.go b/internal/backends/compiler_wat/wir/wat/import.go index a546886..071e06e 100644 --- a/internal/backends/compiler_wat/wir/wat/import.go +++ b/internal/backends/compiler_wat/wir/wat/import.go @@ -2,6 +2,8 @@ package wat +import "strings" + /************************************** ImpObj: **************************************/ @@ -27,5 +29,15 @@ func NewImpFunc(moduleName string, objName string, funcName string, sig FuncSig) } func (o *ImpFunc) Type() ObjType { return ObjTypeFunc } func (o *ImpFunc) Format(indent string) string { - return indent + "(import \"" + o.moduleName + "\" \"" + o.objName + "\" (func $" + o.funcName + o.sig.String() + "))" + var sb strings.Builder + sb.WriteString(indent) + sb.WriteString("(import \"") + sb.WriteString(o.moduleName) + sb.WriteString("\" \"") + sb.WriteString(o.objName) + sb.WriteString("\" (func $") + sb.WriteString(o.funcName) + sb.WriteString(o.sig.String()) + sb.WriteString("))") + return sb.String() } diff --git a/internal/backends/compiler_wat/wir/wat/instruction_arith.go b/internal/backends/compiler_wat/wir/wat/instruction_arith.go index 2aac624..4745093 100644 --- a/internal/backends/compiler_wat/wir/wat/instruction_arith.go +++ b/internal/backends/compiler_wat/wir/wat/instruction_arith.go @@ -3,6 +3,8 @@ package wat import ( + "strings" + "wa-lang.org/wa/internal/logger" ) @@ -19,8 +21,12 @@ type instAdd struct { typ ValueType } -func NewInstAdd(t ValueType) *instAdd { return &instAdd{typ: t} } -func (i *instAdd) Format(indent string) string { return indent + i.typ.Name() + ".add" } +func NewInstAdd(t ValueType) *instAdd { return &instAdd{typ: t} } +func (i *instAdd) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".add") +} /************************************** instSub: @@ -30,8 +36,12 @@ type instSub struct { typ ValueType } -func NewInstSub(t ValueType) *instSub { return &instSub{typ: t} } -func (i *instSub) Format(indent string) string { return indent + i.typ.Name() + ".sub" } +func NewInstSub(t ValueType) *instSub { return &instSub{typ: t} } +func (i *instSub) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".sub") +} /************************************** instMul: @@ -41,8 +51,12 @@ type instMul struct { typ ValueType } -func NewInstMul(t ValueType) *instMul { return &instMul{typ: t} } -func (i *instMul) Format(indent string) string { return indent + i.typ.Name() + ".mul" } +func NewInstMul(t ValueType) *instMul { return &instMul{typ: t} } +func (i *instMul) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".mul") +} /************************************** instDiv: @@ -53,29 +67,35 @@ type instDiv struct { } func NewInstDiv(t ValueType) *instDiv { return &instDiv{typ: t} } -func (i *instDiv) Format(indent string) string { +func (i *instDiv) Format(indent string, sb *strings.Builder) { switch i.typ.(type) { case I32: - return indent + "i32.div_s" + sb.WriteString(indent) + sb.WriteString("i32.div_s") case U32: - return indent + "i32.div_u" + sb.WriteString(indent) + sb.WriteString("i32.div_u") case I64: - return indent + "i64.div_s" + sb.WriteString(indent) + sb.WriteString("i64.div_s") case U64: - return indent + "i64.div_u" + sb.WriteString(indent) + sb.WriteString("i64.div_u") case F32: - return indent + "f32.div" + sb.WriteString(indent) + sb.WriteString("f32.div") case F64: - return indent + "f64.div" + sb.WriteString(indent) + sb.WriteString("f64.div") + default: + logger.Fatal("Todo") } - logger.Fatal("Todo") - return "" } /************************************** @@ -87,20 +107,25 @@ type instRem struct { } func NewInstRem(t ValueType) *instRem { return &instRem{typ: t} } -func (i *instRem) Format(indent string) string { +func (i *instRem) Format(indent string, sb *strings.Builder) { switch i.typ.(type) { case I32: - return indent + "i32.rem_s" + sb.WriteString(indent) + sb.WriteString("i32.rem_s") case U32: - return indent + "i32.rem_u" + sb.WriteString(indent) + sb.WriteString("i32.rem_u") case I64: - return indent + "i64.rem_s" + sb.WriteString(indent) + sb.WriteString("i64.rem_s") case U64: - return indent + "i64.rem_u" + sb.WriteString(indent) + sb.WriteString("i64.rem_u") + + default: + logger.Fatal("Todo") } - logger.Fatal("Todo") - return "" } diff --git a/internal/backends/compiler_wat/wir/wat/instruction_bit.go b/internal/backends/compiler_wat/wir/wat/instruction_bit.go index 5160c17..7814ba8 100644 --- a/internal/backends/compiler_wat/wir/wat/instruction_bit.go +++ b/internal/backends/compiler_wat/wir/wat/instruction_bit.go @@ -2,7 +2,11 @@ package wat -import "wa-lang.org/wa/internal/logger" +import ( + "strings" + + "wa-lang.org/wa/internal/logger" +) /************************************** instAnd: @@ -12,8 +16,12 @@ type instAnd struct { typ ValueType } -func NewInstAnd(t ValueType) *instAnd { return &instAnd{typ: t} } -func (i *instAnd) Format(indent string) string { return indent + i.typ.Name() + ".and" } +func NewInstAnd(t ValueType) *instAnd { return &instAnd{typ: t} } +func (i *instAnd) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".and") +} /************************************** instOr: @@ -23,8 +31,12 @@ type instOr struct { typ ValueType } -func NewInstOr(t ValueType) *instOr { return &instOr{typ: t} } -func (i *instOr) Format(indent string) string { return indent + i.typ.Name() + ".or" } +func NewInstOr(t ValueType) *instOr { return &instOr{typ: t} } +func (i *instOr) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".or") +} /************************************** instXor: @@ -34,8 +46,12 @@ type instXor struct { typ ValueType } -func NewInstXor(t ValueType) *instXor { return &instXor{typ: t} } -func (i *instXor) Format(indent string) string { return indent + i.typ.Name() + ".xor" } +func NewInstXor(t ValueType) *instXor { return &instXor{typ: t} } +func (i *instXor) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".xor") +} /************************************** instShl: @@ -45,8 +61,12 @@ type instShl struct { typ ValueType } -func NewInstShl(t ValueType) *instShl { return &instShl{typ: t} } -func (i *instShl) Format(indent string) string { return indent + i.typ.Name() + ".shl" } +func NewInstShl(t ValueType) *instShl { return &instShl{typ: t} } +func (i *instShl) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".shl") +} /************************************** instShr: @@ -57,14 +77,19 @@ type instShr struct { } func NewInstShr(t ValueType) *instShr { return &instShr{typ: t} } -func (i *instShr) Format(indent string) string { +func (i *instShr) Format(indent string, sb *strings.Builder) { switch i.typ.(type) { case I32, I64: - return indent + i.typ.Name() + ".shr_s" + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".shr_s") case U32, U64: - return indent + i.typ.Name() + ".shr_u" + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".shr_u") + + default: + logger.Fatal("Todo") } - logger.Fatal("Todo") - return "" } diff --git a/internal/backends/compiler_wat/wir/wat/instruction_comp.go b/internal/backends/compiler_wat/wir/wat/instruction_comp.go index de51c17..b4ce40c 100644 --- a/internal/backends/compiler_wat/wir/wat/instruction_comp.go +++ b/internal/backends/compiler_wat/wir/wat/instruction_comp.go @@ -2,7 +2,11 @@ package wat -import "wa-lang.org/wa/internal/logger" +import ( + "strings" + + "wa-lang.org/wa/internal/logger" +) /************************************** instEqz: @@ -12,8 +16,12 @@ type instEqz struct { typ ValueType } -func NewInstEqz(t ValueType) *instEqz { return &instEqz{typ: t} } -func (i *instEqz) Format(indent string) string { return indent + i.typ.Name() + ".eqz" } +func NewInstEqz(t ValueType) *instEqz { return &instEqz{typ: t} } +func (i *instEqz) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".eqz") +} /************************************** instEq: @@ -23,8 +31,12 @@ type instEq struct { typ ValueType } -func NewInstEq(t ValueType) *instEq { return &instEq{typ: t} } -func (i *instEq) Format(indent string) string { return indent + i.typ.Name() + ".eq" } +func NewInstEq(t ValueType) *instEq { return &instEq{typ: t} } +func (i *instEq) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".eq") +} /************************************** instNe: @@ -34,8 +46,12 @@ type instNe struct { typ ValueType } -func NewInstNe(t ValueType) *instNe { return &instNe{typ: t} } -func (i *instNe) Format(indent string) string { return indent + i.typ.Name() + ".ne" } +func NewInstNe(t ValueType) *instNe { return &instNe{typ: t} } +func (i *instNe) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".ne") +} /************************************** instLt: @@ -46,28 +62,35 @@ type instLt struct { } func NewInstLt(t ValueType) *instLt { return &instLt{typ: t} } -func (i *instLt) Format(indent string) string { +func (i *instLt) Format(indent string, sb *strings.Builder) { switch i.typ.(type) { case I32: - return indent + "i32.lt_s" + sb.WriteString(indent) + sb.WriteString("i32.lt_s") case U32: - return indent + "i32.lt_u" + sb.WriteString(indent) + sb.WriteString("i32.lt_u") case I64: - return indent + "i64.lt_s" + sb.WriteString(indent) + sb.WriteString("i64.lt_s") case U64: - return indent + "i64.lt_u" + sb.WriteString(indent) + sb.WriteString("i64.lt_u") case F32: - return indent + "f32.lt" + sb.WriteString(indent) + sb.WriteString("f32.lt") case F64: - return indent + "f64.lt" + sb.WriteString(indent) + sb.WriteString("f64.lt") + + default: + logger.Fatal("Todo") } - logger.Fatal("Todo") - return "" } /************************************** @@ -79,28 +102,35 @@ type instGt struct { } func NewInstGt(t ValueType) *instGt { return &instGt{typ: t} } -func (i *instGt) Format(indent string) string { +func (i *instGt) Format(indent string, sb *strings.Builder) { switch i.typ.(type) { case I32: - return indent + "i32.gt_s" + sb.WriteString(indent) + sb.WriteString("i32.gt_s") case U32: - return indent + "i32.gt_u" + sb.WriteString(indent) + sb.WriteString("i32.gt_u") case I64: - return indent + "i64.gt_s" + sb.WriteString(indent) + sb.WriteString("i64.gt_s") case U64: - return indent + "i64.gt_u" + sb.WriteString(indent) + sb.WriteString("i64.gt_u") case F32: - return indent + "f32.gt" + sb.WriteString(indent) + sb.WriteString("f32.gt") case F64: - return indent + "f64.gt" + sb.WriteString(indent) + sb.WriteString("f64.gt") + + default: + logger.Fatal("Todo") } - logger.Fatal("Todo") - return "" } /************************************** @@ -112,28 +142,35 @@ type instLe struct { } func NewInstLe(t ValueType) *instLe { return &instLe{typ: t} } -func (i *instLe) Format(indent string) string { +func (i *instLe) Format(indent string, sb *strings.Builder) { switch i.typ.(type) { case I32: - return indent + "i32.le_s" + sb.WriteString(indent) + sb.WriteString("i32.le_s") case U32: - return indent + "i32.le_u" + sb.WriteString(indent) + sb.WriteString("i32.le_u") case I64: - return indent + "i64.le_s" + sb.WriteString(indent) + sb.WriteString("i64.le_s") case U64: - return indent + "i64.le_u" + sb.WriteString(indent) + sb.WriteString("i64.le_u") case F32: - return indent + "f32.le" + sb.WriteString(indent) + sb.WriteString("f32.le") case F64: - return indent + "f64.le" + sb.WriteString(indent) + sb.WriteString("f64.le") + + default: + logger.Fatal("Todo") } - logger.Fatal("Todo") - return "" } /************************************** @@ -145,17 +182,24 @@ type instGe struct { } func NewInstGe(t ValueType) *instGe { return &instGe{typ: t} } -func (i *instGe) Format(indent string) string { +func (i *instGe) Format(indent string, sb *strings.Builder) { switch i.typ.(type) { case I32, I64: - return indent + i.typ.Name() + ".ge_s" + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".ge_s") case U32, U64: - return indent + i.typ.Name() + ".ge_u" + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".ge_u") case F32, F64: - return indent + i.typ.Name() + ".ge" + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".ge") + + default: + logger.Fatal("Todo") } - logger.Fatal("Todo") - return "" } diff --git a/internal/backends/compiler_wat/wir/wat/instruction_const.go b/internal/backends/compiler_wat/wir/wat/instruction_const.go index 48236cf..cc5b1b7 100644 --- a/internal/backends/compiler_wat/wir/wat/instruction_const.go +++ b/internal/backends/compiler_wat/wir/wat/instruction_const.go @@ -2,6 +2,8 @@ package wat +import "strings" + /************************************** instConst: **************************************/ @@ -14,6 +16,9 @@ type instConst struct { func NewInstConst(typ ValueType, literal string) *instConst { return &instConst{typ: typ, literal: literal} } -func (i *instConst) Format(indent string) string { - return indent + i.typ.Name() + ".const " + i.literal +func (i *instConst) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".const ") + sb.WriteString(i.literal) } diff --git a/internal/backends/compiler_wat/wir/wat/instruction_convert.go b/internal/backends/compiler_wat/wir/wat/instruction_convert.go index 24bf764..294a7cc 100644 --- a/internal/backends/compiler_wat/wir/wat/instruction_convert.go +++ b/internal/backends/compiler_wat/wir/wat/instruction_convert.go @@ -1,5 +1,7 @@ package wat +import "strings" + /************************************** instConvert_i32_wrap_i64: **************************************/ @@ -7,8 +9,11 @@ type instConvert_i32_wrap_i64 struct { anInstruction } -func NewInstConvert_i32_wrap_i64() *instConvert_i32_wrap_i64 { return &instConvert_i32_wrap_i64{} } -func (i *instConvert_i32_wrap_i64) Format(indent string) string { return indent + "i32.wrap_i64" } +func NewInstConvert_i32_wrap_i64() *instConvert_i32_wrap_i64 { return &instConvert_i32_wrap_i64{} } +func (i *instConvert_i32_wrap_i64) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("i32.wrap_i64") +} /************************************** instConvert_i32_trunc_f32_s: @@ -20,7 +25,10 @@ type instConvert_i32_trunc_f32_s struct { func NewInstConvert_i32_trunc_f32_s() *instConvert_i32_trunc_f32_s { return &instConvert_i32_trunc_f32_s{} } -func (i *instConvert_i32_trunc_f32_s) Format(indent string) string { return indent + "i32.trunc_f32_s" } +func (i *instConvert_i32_trunc_f32_s) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("i32.trunc_f32_s") +} /************************************** instConvert_i32_trunc_f64_s: @@ -32,7 +40,10 @@ type instConvert_i32_trunc_f64_s struct { func NewInstConvert_i32_trunc_f64_s() *instConvert_i32_trunc_f64_s { return &instConvert_i32_trunc_f64_s{} } -func (i *instConvert_i32_trunc_f64_s) Format(indent string) string { return indent + "i32.trunc_f64_s" } +func (i *instConvert_i32_trunc_f64_s) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("i32.trunc_f64_s") +} /************************************** instConvert_i64_extend_i32_s: @@ -44,8 +55,9 @@ type instConvert_i64_extend_i32_s struct { func NewInstConvert_i64_extend_i32_s() *instConvert_i64_extend_i32_s { return &instConvert_i64_extend_i32_s{} } -func (i *instConvert_i64_extend_i32_s) Format(indent string) string { - return indent + "i64.extend_i32_s" +func (i *instConvert_i64_extend_i32_s) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("i64.extend_i32_s") } /************************************** @@ -58,8 +70,9 @@ type instConvert_i64_extend_i32_u struct { func NewInstConvert_i64_extend_i32_u() *instConvert_i64_extend_i32_u { return &instConvert_i64_extend_i32_u{} } -func (i *instConvert_i64_extend_i32_u) Format(indent string) string { - return indent + "i64.extend_i32_u" +func (i *instConvert_i64_extend_i32_u) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("i64.extend_i32_u") } /************************************** @@ -72,7 +85,10 @@ type instConvert_i64_trunc_f32_s struct { func NewInstConvert_i64_trunc_f32_s() *instConvert_i64_trunc_f32_s { return &instConvert_i64_trunc_f32_s{} } -func (i *instConvert_i64_trunc_f32_s) Format(indent string) string { return indent + "i64.trunc_f32_s" } +func (i *instConvert_i64_trunc_f32_s) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("i64.trunc_f32_s") +} /************************************** instConvert_i64_trunc_f64_s: @@ -84,7 +100,10 @@ type instConvert_i64_trunc_f64_s struct { func NewInstConvert_i64_trunc_f64_s() *instConvert_i64_trunc_f64_s { return &instConvert_i64_trunc_f64_s{} } -func (i *instConvert_i64_trunc_f64_s) Format(indent string) string { return indent + "i64.trunc_f64_s" } +func (i *instConvert_i64_trunc_f64_s) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("i64.trunc_f64_s") +} /************************************** instConvert_f32_convert_i32_s: @@ -96,8 +115,9 @@ type instConvert_f32_convert_i32_s struct { func NewInstConvert_f32_convert_i32_s() *instConvert_f32_convert_i32_s { return &instConvert_f32_convert_i32_s{} } -func (i *instConvert_f32_convert_i32_s) Format(indent string) string { - return indent + "f32.convert_i32_s" +func (i *instConvert_f32_convert_i32_s) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("f32.convert_i32_s") } /************************************** @@ -110,8 +130,9 @@ type instConvert_f32_convert_i32_u struct { func NewInstConvert_f32_convert_i32_u() *instConvert_f32_convert_i32_u { return &instConvert_f32_convert_i32_u{} } -func (i *instConvert_f32_convert_i32_u) Format(indent string) string { - return indent + "f32.convert_i32_u" +func (i *instConvert_f32_convert_i32_u) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("f32.convert_i32_u") } /************************************** @@ -124,8 +145,9 @@ type instConvert_f32_convert_i64_s struct { func NewInstConvert_f32_convert_i64_s() *instConvert_f32_convert_i64_s { return &instConvert_f32_convert_i64_s{} } -func (i *instConvert_f32_convert_i64_s) Format(indent string) string { - return indent + "f32.convert_i64_s" +func (i *instConvert_f32_convert_i64_s) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("f32.convert_i64_s") } /************************************** @@ -138,8 +160,9 @@ type instConvert_f32_convert_i64_u struct { func NewInstConvert_f32_convert_i64_u() *instConvert_f32_convert_i64_u { return &instConvert_f32_convert_i64_u{} } -func (i *instConvert_f32_convert_i64_u) Format(indent string) string { - return indent + "f32.convert_i64_u" +func (i *instConvert_f32_convert_i64_u) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("f32.convert_i64_u") } /************************************** @@ -152,8 +175,9 @@ type instConvert_f32_demote_f64 struct { func NewInstConvert_f32_demote_f64() *instConvert_f32_demote_f64 { return &instConvert_f32_demote_f64{} } -func (i *instConvert_f32_demote_f64) Format(indent string) string { - return indent + "f32.demote_f64" +func (i *instConvert_f32_demote_f64) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("f32.demote_f64") } /************************************** @@ -166,8 +190,9 @@ type instConvert_f64_convert_i32_s struct { func NewInstConvert_f64_convert_i32_s() *instConvert_f64_convert_i32_s { return &instConvert_f64_convert_i32_s{} } -func (i *instConvert_f64_convert_i32_s) Format(indent string) string { - return indent + "f64.convert_i32_s" +func (i *instConvert_f64_convert_i32_s) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("f64.convert_i32_s") } /************************************** @@ -180,8 +205,9 @@ type instConvert_f64_convert_i32_u struct { func NewInstConvert_f64_convert_i32_u() *instConvert_f64_convert_i32_u { return &instConvert_f64_convert_i32_u{} } -func (i *instConvert_f64_convert_i32_u) Format(indent string) string { - return indent + "f64.convert_i32_u" +func (i *instConvert_f64_convert_i32_u) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("f64.convert_i32_u") } /************************************** @@ -194,8 +220,9 @@ type instConvert_f64_convert_i64_s struct { func NewInstConvert_f64_convert_i64_s() *instConvert_f64_convert_i64_s { return &instConvert_f64_convert_i64_s{} } -func (i *instConvert_f64_convert_i64_s) Format(indent string) string { - return indent + "f64.convert_i64_s" +func (i *instConvert_f64_convert_i64_s) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("f64.convert_i64_s") } /************************************** @@ -208,8 +235,9 @@ type instConvert_f64_convert_i64_u struct { func NewInstConvert_f64_convert_i64_u() *instConvert_f64_convert_i64_u { return &instConvert_f64_convert_i64_u{} } -func (i *instConvert_f64_convert_i64_u) Format(indent string) string { - return indent + "f64.convert_i64_u" +func (i *instConvert_f64_convert_i64_u) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("f64.convert_i64_u") } /************************************** @@ -222,6 +250,7 @@ type instConvert_f64_promote_f32 struct { func NewInstConvert_f64_promote_f32() *instConvert_f64_promote_f32 { return &instConvert_f64_promote_f32{} } -func (i *instConvert_f64_promote_f32) Format(indent string) string { - return indent + "f64.promote_f32" +func (i *instConvert_f64_promote_f32) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("f64.promote_f32") } diff --git a/internal/backends/compiler_wat/wir/wat/instruction_ctl.go b/internal/backends/compiler_wat/wir/wat/instruction_ctl.go index 530dec0..9739773 100644 --- a/internal/backends/compiler_wat/wir/wat/instruction_ctl.go +++ b/internal/backends/compiler_wat/wir/wat/instruction_ctl.go @@ -2,7 +2,10 @@ package wat -import "strconv" +import ( + "strconv" + "strings" +) /************************************** instCall: @@ -12,8 +15,12 @@ type instCall struct { name string } -func NewInstCall(name string) *instCall { return &instCall{name: name} } -func (i *instCall) Format(indent string) string { return indent + "call $" + i.name } +func NewInstCall(name string) *instCall { return &instCall{name: name} } +func (i *instCall) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("call $") + sb.WriteString(i.name) +} /************************************** instCallIndirect: @@ -26,8 +33,11 @@ type instCallIndirect struct { func NewInstCallIndirect(func_type string) *instCallIndirect { return &instCallIndirect{func_type: func_type} } -func (i *instCallIndirect) Format(indent string) string { - return indent + "call_indirect (type $" + i.func_type + ")" +func (i *instCallIndirect) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("call_indirect (type $") + sb.WriteString(i.func_type) + sb.WriteString(")") } /************************************** @@ -40,14 +50,22 @@ type instBlock struct { } func NewInstBlock(name string) *instBlock { return &instBlock{name: name} } -func (i *instBlock) Format(indent string) string { - s := indent + "(block $" - s += i.name + "\n" +func (i *instBlock) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("(block $") + + sb.WriteString(i.name) + sb.WriteString("\n") + + indent_t := indent + " " for _, v := range i.Insts { - s += v.Format(indent+" ") + "\n" + v.Format(indent_t, sb) + sb.WriteString("\n") } - s += indent + ") ;;" + i.name - return s + + sb.WriteString(indent) + sb.WriteString(") ;;") + sb.WriteString(i.name) } /************************************** @@ -60,14 +78,22 @@ type instLoop struct { } func NewInstLoop(name string) *instLoop { return &instLoop{name: name} } -func (i *instLoop) Format(indent string) string { - s := indent + "(loop $" - s += i.name + "\n" +func (i *instLoop) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("(loop $") + + sb.WriteString(i.name) + sb.WriteString("\n") + + indent_t := indent + " " for _, v := range i.Insts { - s += v.Format(indent+" ") + "\n" + v.Format(indent_t, sb) + sb.WriteString("\n") } - s += indent + ") ;;" + i.name - return s + + sb.WriteString(indent) + sb.WriteString(") ;;") + sb.WriteString(i.name) } /************************************** @@ -78,8 +104,12 @@ type instBr struct { Name string } -func NewInstBr(name string) *instBr { return &instBr{Name: name} } -func (i *instBr) Format(indent string) string { return indent + "br $" + i.Name } +func NewInstBr(name string) *instBr { return &instBr{Name: name} } +func (i *instBr) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("br $") + sb.WriteString(i.Name) +} /************************************** instBrTable: @@ -90,12 +120,13 @@ type instBrTable struct { } func NewInstBrTable(t []int) *instBrTable { return &instBrTable{Table: t} } -func (i *instBrTable) Format(indent string) string { - s := indent + "br_table" +func (i *instBrTable) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("br_table") for _, v := range i.Table { - s += " " + strconv.Itoa(v) + sb.WriteString(" ") + sb.WriteString(strconv.Itoa(v)) } - return s } /************************************** @@ -111,26 +142,34 @@ type instIf struct { func NewInstIf(instsTrue, instsFalse []Inst, ret []ValueType) *instIf { return &instIf{True: instsTrue, False: instsFalse, Ret: ret} } -func (i *instIf) Format(indent string) string { - s := indent + "if" - if len(i.Ret) > 0 { - s += " (result" - for _, r := range i.Ret { - s += " " + r.Name() - } - s += ")" - } - s += "\n" +func (i *instIf) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("if") + if len(i.Ret) > 0 { + sb.WriteString(" (result") + for _, r := range i.Ret { + sb.WriteString(" ") + sb.WriteString(r.Name()) + } + sb.WriteString(")") + } + sb.WriteString("\n") + + indent_t := indent + " " for _, v := range i.True { - s += v.Format(indent+" ") + "\n" + v.Format(indent_t, sb) + sb.WriteString("\n") } - s += indent + "else\n" + sb.WriteString(indent) + sb.WriteString("else\n") for _, v := range i.False { - s += v.Format(indent+" ") + "\n" + v.Format(indent_t, sb) + sb.WriteString("\n") } - s += indent + "end" - return s + + sb.WriteString(indent) + sb.WriteString("end") } /************************************** @@ -140,5 +179,8 @@ type instReturn struct { anInstruction } -func NewInstReturn() *instReturn { return &instReturn{} } -func (i *instReturn) Format(indent string) string { return indent + "return" } +func NewInstReturn() *instReturn { return &instReturn{} } +func (i *instReturn) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("return") +} diff --git a/internal/backends/compiler_wat/wir/wat/instruction_mem.go b/internal/backends/compiler_wat/wir/wat/instruction_mem.go index 7fbfd76..289c68d 100644 --- a/internal/backends/compiler_wat/wir/wat/instruction_mem.go +++ b/internal/backends/compiler_wat/wir/wat/instruction_mem.go @@ -2,7 +2,10 @@ package wat -import "strconv" +import ( + "strconv" + "strings" +) /************************************** instLoad: @@ -16,8 +19,13 @@ type instLoad struct { func NewInstLoad(typ ValueType, offset int, align int) *instLoad { return &instLoad{typ: typ, offset: offset, align: align} } -func (i *instLoad) Format(indent string) string { - return indent + i.typ.Name() + ".load offset=" + strconv.Itoa(i.offset) + " align=" + strconv.Itoa(i.align) +func (i *instLoad) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".load offset=") + sb.WriteString(strconv.Itoa(i.offset)) + sb.WriteString(" align=") + sb.WriteString(strconv.Itoa(i.align)) } /************************************** @@ -31,8 +39,12 @@ type instLoad8s struct { func NewInstLoad8s(offset int, align int) *instLoad8s { return &instLoad8s{offset: offset, align: align} } -func (i *instLoad8s) Format(indent string) string { - return indent + "i32.load8_s offset=" + strconv.Itoa(i.offset) + " align=" + strconv.Itoa(i.align) +func (i *instLoad8s) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("i32.load8_s offset=") + sb.WriteString(strconv.Itoa(i.offset)) + sb.WriteString(" align=") + sb.WriteString(strconv.Itoa(i.align)) } /************************************** @@ -46,8 +58,12 @@ type instLoad8u struct { func NewInstLoad8u(offset int, align int) *instLoad8u { return &instLoad8u{offset: offset, align: align} } -func (i *instLoad8u) Format(indent string) string { - return indent + "i32.load8_u offset=" + strconv.Itoa(i.offset) + " align=" + strconv.Itoa(i.align) +func (i *instLoad8u) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("i32.load8_u offset=") + sb.WriteString(strconv.Itoa(i.offset)) + sb.WriteString(" align=") + sb.WriteString(strconv.Itoa(i.align)) } /************************************** @@ -61,8 +77,12 @@ type instLoad16s struct { func NewInstLoad16s(offset int, align int) *instLoad16s { return &instLoad16s{offset: offset, align: align} } -func (i *instLoad16s) Format(indent string) string { - return indent + "i32.load16_s offset=" + strconv.Itoa(i.offset) + " align=" + strconv.Itoa(i.align) +func (i *instLoad16s) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("i32.load16_s offset=") + sb.WriteString(strconv.Itoa(i.offset)) + sb.WriteString(" align=") + sb.WriteString(strconv.Itoa(i.align)) } /************************************** @@ -76,8 +96,12 @@ type instLoad16u struct { func NewInstLoad16u(offset int, align int) *instLoad16u { return &instLoad16u{offset: offset, align: align} } -func (i *instLoad16u) Format(indent string) string { - return indent + "i32.load16_u offset=" + strconv.Itoa(i.offset) + " align=" + strconv.Itoa(i.align) +func (i *instLoad16u) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("i32.load16_u offset=") + sb.WriteString(strconv.Itoa(i.offset)) + sb.WriteString(" align=") + sb.WriteString(strconv.Itoa(i.align)) } /************************************** @@ -92,8 +116,13 @@ type instStore struct { func NewInstStore(typ ValueType, offset int, align int) *instStore { return &instStore{typ: typ, offset: offset, align: align} } -func (i *instStore) Format(indent string) string { - return indent + i.typ.Name() + ".store offset=" + strconv.Itoa(i.offset) + " align=" + strconv.Itoa(i.align) +func (i *instStore) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString(i.typ.Name()) + sb.WriteString(".store offset=") + sb.WriteString(strconv.Itoa(i.offset)) + sb.WriteString(" align=") + sb.WriteString(strconv.Itoa(i.align)) } /************************************** @@ -107,8 +136,12 @@ type instStore8 struct { func NewInstStore8(offset int, align int) *instStore8 { return &instStore8{offset: offset, align: align} } -func (i *instStore8) Format(indent string) string { - return indent + "i32.store8 offset=" + strconv.Itoa(i.offset) + " align=" + strconv.Itoa(i.align) +func (i *instStore8) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("i32.store8 offset=") + sb.WriteString(strconv.Itoa(i.offset)) + sb.WriteString(" align=") + sb.WriteString(strconv.Itoa(i.align)) } /************************************** @@ -122,6 +155,10 @@ type instStore16 struct { func NewInstStore16(offset int, align int) *instStore16 { return &instStore16{offset: offset, align: align} } -func (i *instStore16) Format(indent string) string { - return indent + "i32.store16 offset=" + strconv.Itoa(i.offset) + " align=" + strconv.Itoa(i.align) +func (i *instStore16) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("i32.store16 offset=") + sb.WriteString(strconv.Itoa(i.offset)) + sb.WriteString(" align=") + sb.WriteString(strconv.Itoa(i.align)) } diff --git a/internal/backends/compiler_wat/wir/wat/instruction_misc.go b/internal/backends/compiler_wat/wir/wat/instruction_misc.go index 250c01d..d308bd7 100644 --- a/internal/backends/compiler_wat/wir/wat/instruction_misc.go +++ b/internal/backends/compiler_wat/wir/wat/instruction_misc.go @@ -1,5 +1,7 @@ package wat +import "strings" + /************************************** instDrop: **************************************/ @@ -7,8 +9,11 @@ type instDrop struct { anInstruction } -func NewInstDrop() *instDrop { return &instDrop{} } -func (i *instDrop) Format(indent string) string { return indent + "drop" } +func NewInstDrop() *instDrop { return &instDrop{} } +func (i *instDrop) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("drop") +} /************************************** comment: @@ -18,8 +23,12 @@ type comment struct { name string } -func NewComment(name string) *comment { return &comment{name: name} } -func (i *comment) Format(indent string) string { return indent + ";;" + i.name } +func NewComment(name string) *comment { return &comment{name: name} } +func (i *comment) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString(";;") + sb.WriteString(i.name) +} /************************************** blank: @@ -28,8 +37,8 @@ type blank struct { anInstruction } -func NewBlank() *blank { return &blank{} } -func (i *blank) Format(indent string) string { return "" } +func NewBlank() *blank { return &blank{} } +func (i *blank) Format(indent string, sb *strings.Builder) {} /************************************** instUnreachable: @@ -38,5 +47,8 @@ type instUnreachable struct { anInstruction } -func NewInstUnreachable() *instUnreachable { return &instUnreachable{} } -func (i *instUnreachable) Format(indent string) string { return indent + "unreachable" } +func NewInstUnreachable() *instUnreachable { return &instUnreachable{} } +func (i *instUnreachable) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("unreachable") +} diff --git a/internal/backends/compiler_wat/wir/wat/instruction_var.go b/internal/backends/compiler_wat/wir/wat/instruction_var.go index ae25c52..04d6bdd 100644 --- a/internal/backends/compiler_wat/wir/wat/instruction_var.go +++ b/internal/backends/compiler_wat/wir/wat/instruction_var.go @@ -2,6 +2,8 @@ package wat +import "strings" + /************************************** instGetLocal: **************************************/ @@ -10,8 +12,12 @@ type instGetLocal struct { name string } -func NewInstGetLocal(name string) *instGetLocal { return &instGetLocal{name: name} } -func (i *instGetLocal) Format(indent string) string { return indent + "local.get $" + i.name } +func NewInstGetLocal(name string) *instGetLocal { return &instGetLocal{name: name} } +func (i *instGetLocal) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("local.get $") + sb.WriteString(i.name) +} /************************************** instSetLocal: @@ -21,8 +27,12 @@ type instSetLocal struct { name string } -func NewInstSetLocal(name string) *instSetLocal { return &instSetLocal{name: name} } -func (i *instSetLocal) Format(indent string) string { return indent + "local.set $" + i.name } +func NewInstSetLocal(name string) *instSetLocal { return &instSetLocal{name: name} } +func (i *instSetLocal) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("local.set $") + sb.WriteString(i.name) +} /************************************** instGetGlobal: @@ -32,8 +42,12 @@ type instGetGlobal struct { name string } -func NewInstGetGlobal(name string) *instGetGlobal { return &instGetGlobal{name: name} } -func (i *instGetGlobal) Format(indent string) string { return indent + "global.get $" + i.name } +func NewInstGetGlobal(name string) *instGetGlobal { return &instGetGlobal{name: name} } +func (i *instGetGlobal) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("global.get $") + sb.WriteString(i.name) +} /************************************** instSetGlobal: @@ -43,5 +57,9 @@ type instSetGlobal struct { name string } -func NewInstSetGlobal(name string) *instSetGlobal { return &instSetGlobal{name: name} } -func (i *instSetGlobal) Format(indent string) string { return indent + "global.set $" + i.name } +func NewInstSetGlobal(name string) *instSetGlobal { return &instSetGlobal{name: name} } +func (i *instSetGlobal) Format(indent string, sb *strings.Builder) { + sb.WriteString(indent) + sb.WriteString("global.set $") + sb.WriteString(i.name) +} diff --git a/internal/backends/compiler_wat/wir/wat/module.go b/internal/backends/compiler_wat/wir/wat/module.go index 2193120..beff1d5 100644 --- a/internal/backends/compiler_wat/wir/wat/module.go +++ b/internal/backends/compiler_wat/wir/wat/module.go @@ -4,6 +4,7 @@ package wat import ( "strconv" + "strings" ) // 模块对象 @@ -21,55 +22,70 @@ type Module struct { } func (m *Module) String() string { - s := "(module $__walang__\n" + var sb strings.Builder + + sb.WriteString("(module $__walang__\n") for _, i := range m.Imports { - s += i.Format(" ") + "\n" + sb.WriteString(i.Format(" ")) + sb.WriteByte('\n') } - s += m.BaseWat + sb.WriteString(m.BaseWat) if len(m.DataSeg.data) > 0 { - s += "(data (i32.const " + strconv.Itoa(m.DataSeg.start) + ") \"" + sb.WriteString("(data (i32.const ") + sb.WriteString(strconv.Itoa(m.DataSeg.start)) + sb.WriteString(") \"") for _, d := range m.DataSeg.data { - s += "\\" + sb.WriteByte('\\') i := strconv.FormatInt(int64(d), 16) if len(i) < 2 { i = "0" + i } - s += i + sb.WriteString(i) } - s += "\")\n" + sb.WriteString("\")\n") } - s += m.Tables.String() + sb.WriteString(m.Tables.String()) for _, ft := range m.FuncTypes { - s += ft.String() + sb.WriteString(ft.String()) } for _, g := range m.Globals { - s += "(global $" - s += g.V.Name() + sb.WriteString("(global $") + sb.WriteString(g.V.Name()) if g.IsMut { - s += " (mut " + g.V.Type().Name() + ")" + sb.WriteString(" (mut ") + sb.WriteString(g.V.Type().Name()) + sb.WriteByte(')') } else { - s += " " + g.V.Type().Name() + sb.WriteByte(' ') + sb.WriteString(g.V.Type().Name()) } // if len(g.InitValue) > 0 { - s += " (" + g.V.Type().Name() + ".const " + g.InitValue + ")" + sb.WriteString(" (") + sb.WriteString(g.V.Type().Name()) + sb.WriteString(".const ") + sb.WriteString(g.InitValue) + sb.WriteByte(')') } else { - s += " (" + g.V.Type().Name() + ".const 0)" + sb.WriteString(" (") + sb.WriteString(g.V.Type().Name()) + sb.WriteString(".const 0)") } - s += ")\n" + sb.WriteString(")\n") } for _, f := range m.Funcs { - s += "\n\n" + f.Format("") + sb.WriteString("\n\n") + f.Format(&sb) } - s += "\n) ;;module" - return s + sb.WriteString("\n) ;;module") + return sb.String() } func (t Table) String() string { diff --git a/internal/backends/compiler_wat/wir/wat/wat.go b/internal/backends/compiler_wat/wir/wat/wat.go index 1fe6917..d38512b 100644 --- a/internal/backends/compiler_wat/wir/wat/wat.go +++ b/internal/backends/compiler_wat/wir/wat/wat.go @@ -2,6 +2,8 @@ package wat +import "strings" + /************************************** Import: **************************************/ @@ -52,7 +54,7 @@ type FuncSig struct { Inst: **************************************/ type Inst interface { - Format(indent string) string + Format(indent string, sb *strings.Builder) isInstruction() }