diff --git a/internal/backends/compiler_wat/compile_type.go b/internal/backends/compiler_wat/compile_type.go index b3d43d2ceb09257183a72eaa1cb93bf142d52e6a..75ae1aa6e7495f533c3b3ed2e1bd1b0ad0056cc7 100644 --- a/internal/backends/compiler_wat/compile_type.go +++ b/internal/backends/compiler_wat/compile_type.go @@ -131,13 +131,16 @@ func (tLib *typeLib) compile(from types.Type) wir.ValueType { } newType = tStruct - uncommanFlag = true + //uncommanFlag = true case *types.Interface: if ut.NumMethods() == 0 { return tLib.compile(ut) } - pkg_name, _ := wir.GetPkgMangleName(t.Obj().Pkg().Path()) + pkg_name := "" + if t.Obj().Pkg() != nil { + pkg_name, _ = wir.GetPkgMangleName(t.Obj().Pkg().Path()) + } obj_name := wir.GenSymbolName(t.Obj().Name()) newType = tLib.module.GenValueType_Interface(pkg_name + "." + obj_name) @@ -145,17 +148,17 @@ func (tLib *typeLib) compile(from types.Type) wir.ValueType { for i := 0; i < ut.NumMethods(); i++ { var method wir.Method method.Sig = tLib.GenFnSig(ut.Method(i).Type().(*types.Signature)) + method.Name = ut.Method(i).Name() - method.FullFnName = pkg_name + "." + obj_name + "." + method.Name - newType.AddMethod(method) + var fnSig wir.FnSig + fnSig.Params = append(fnSig.Params, tLib.module.GenValueType_Ref(tLib.module.VOID)) + fnSig.Params = append(fnSig.Params, method.Sig.Params...) + fnSig.Results = method.Sig.Results + + method.FullFnName = tLib.module.AddFnSig(&fnSig) - var fntype wir.FnType - fntype.FnSig.Params = append(fntype.FnSig.Params, tLib.module.GenValueType_Ref(tLib.module.VOID)) - fntype.FnSig.Params = append(fntype.FnSig.Params, method.Sig.Params...) - fntype.FnSig.Results = method.Sig.Results - fntype.Name = method.FullFnName - tLib.module.AddFnType(&fntype) + newType.AddMethod(method) } case *types.Signature: diff --git a/internal/backends/compiler_wat/wir/module.go b/internal/backends/compiler_wat/wir/module.go index 1dfc462743f84d3194845df1b64b39c2029f4aa0..3dc1272963c2f88bc3feb1ccd01fa47af068febb 100644 --- a/internal/backends/compiler_wat/wir/module.go +++ b/internal/backends/compiler_wat/wir/module.go @@ -2,17 +2,23 @@ package wir import ( "strconv" + "strings" "wa-lang.org/wa/internal/backends/compiler_wat/wir/wat" "wa-lang.org/wa/internal/logger" "wa-lang.org/wa/internal/ssa" ) +type fnSigWrap struct { + name string + typeAddr int +} + /************************************** Module: **************************************/ type Module struct { - VOID, RUNE, I8, U8, I16, U16, I32, U32, I64, U64, F32, F64, STRING ValueType + VOID, RUNE, I8, U8, I16, U16, I32, U32, UPTR, I64, U64, F32, F64, STRING ValueType types_map map[string]ValueType usedConcreteTypes []ValueType @@ -20,8 +26,8 @@ type Module struct { imports []wat.Import - fn_types []*FnType - fn_types_map map[string]int + fnSigs []*FnSig + fnSigsName map[string]fnSigWrap funcs []*Function funcs_map map[string]*Function @@ -54,6 +60,7 @@ func NewModule() *Module { m.U16 = &tU16{} m.I32 = &tI32{} m.U32 = &tU32{} + m.UPTR = m.U32 m.I64 = &tI64{} m.U64 = &tU64{} m.F32 = &tF32{} @@ -75,13 +82,7 @@ func NewModule() *Module { m.STRING = m.GenValueType_String() - m.fn_types_map = make(map[string]int) - { - var free_type FnType - free_type.Name = "$onFree" - free_type.Params = []ValueType{m.I32} - m.AddFnType(&free_type) - } + m.fnSigsName = make(map[string]fnSigWrap) m.funcs_map = make(map[string]*Function) @@ -110,21 +111,23 @@ func (m *Module) AddImportFunc(moduleName string, objName string, funcName strin m.imports = append(m.imports, wat.NewImpFunc(moduleName, objName, funcName, wat_sig)) } -func (m *Module) findFnType(name string) int { - if i, ok := m.fn_types_map[name]; ok { - return i +func (m *Module) FindFnSig(sig *FnSig) string { + if s, ok := m.fnSigsName[sig.String()]; ok { + return s.name } - return 0 + return "" } -func (m *Module) AddFnType(typ *FnType) int { - if i := m.findFnType(typ.Name); i != 0 { - return i +func (m *Module) AddFnSig(sig *FnSig) string { + if s, ok := m.fnSigsName[sig.String()]; ok { + return s.name } - i := len(m.fn_types) - m.fn_types = append(m.fn_types, typ) - m.fn_types_map[typ.Name] = i - return i + + m.fnSigs = append(m.fnSigs, sig) + s := "$$fnSig" + strconv.Itoa(len(m.fnSigs)) + + m.fnSigsName[sig.String()] = fnSigWrap{name: s} + return s } func (m *Module) findTableElem(elem string) int { @@ -229,14 +232,21 @@ func (m *Module) genGlobalAlloc() *Function { func (m *Module) ToWatModule() *wat.Module { m.buildItab() + m.buildTypesInfo() var wat_module wat.Module wat_module.Imports = m.imports wat_module.BaseWat = m.BaseWat - for _, t := range m.fn_types { + { + var onfree_type wat.FuncType + onfree_type.Name = "$onFree" + onfree_type.Params = m.I32.Raw() + wat_module.FuncTypes = append(wat_module.FuncTypes, onfree_type) + } + for _, t := range m.fnSigs { var fn_type wat.FuncType - fn_type.Name = t.Name + fn_type.Name = m.fnSigsName[t.String()].name for _, i := range t.Params { fn_type.Params = append(fn_type.Params, i.Raw()...) } @@ -335,15 +345,15 @@ func (m *Module) buildItab() { var addr int if fits { - var itab []byte + var itab_bin []byte header := NewConst("0", t_itab) - itab = append(itab, header.Bin()...) + itab_bin = append(itab_bin, header.Bin()...) for _, v := range vtable { fnid := NewConst(strconv.Itoa(v), m.U32) - itab = append(itab, fnid.Bin()...) + itab_bin = append(itab_bin, fnid.Bin()...) } - addr = m.DataSeg.Append(itab, 8) + addr = m.DataSeg.Append(itab_bin, 8) } itabs = append(itabs, NewConst(strconv.Itoa(addr), m.U32).Bin()...) @@ -355,3 +365,195 @@ func (m *Module) buildItab() { m.SetGlobalInitValue("$wa.RT._interfaceCount", strconv.Itoa(len(m.usedInterfaces))) m.SetGlobalInitValue("$wa.RT._concretTypeCount", strconv.Itoa(len(m.usedConcreteTypes))) } + +func (m *Module) buildTypesInfo() { + for name, t := range m.types_map { + if strings.HasPrefix(name, "runtime.") { + continue + } + m.buildTypeInfo(t) + } +} + +func (m *Module) buildTypeInfo(t ValueType) int { + if t.typeInfoAddr() != 0 { + return t.typeInfoAddr() + } + + _type := NewConst("0", m.types_map["runtime._type"]).(*aStruct) + _type.setFieldConstValue("size", NewConst(strconv.Itoa(t.Size()), m.U32)) + _type.setFieldConstValue("hash", NewConst(strconv.Itoa(t.Hash()), m.I32)) + _type.setFieldConstValue("kind", NewConst(strconv.Itoa(int(t.Kind())), m.U8)) + _type.setFieldConstValue("align", NewConst(strconv.Itoa(t.align()), m.U8)) + _type.setFieldConstValue("flag", NewConst("0", m.U16)) + _type.setFieldConstValue("name", NewConst(t.Name(), m.STRING)) + + switch typ := t.(type) { + case *tVoid: + typ.addr = m.DataSeg.Append(_type.Bin(), 8) + return typ.addr + + case *tI8: + typ.addr = m.DataSeg.Append(_type.Bin(), 8) + return typ.addr + + case *tU8: + typ.addr = m.DataSeg.Append(_type.Bin(), 8) + return typ.addr + + case *tI16: + typ.addr = m.DataSeg.Append(_type.Bin(), 8) + return typ.addr + + case *tU16: + typ.addr = m.DataSeg.Append(_type.Bin(), 8) + return typ.addr + + case *tI32: + typ.addr = m.DataSeg.Append(_type.Bin(), 8) + return typ.addr + + case *tU32: + typ.addr = m.DataSeg.Append(_type.Bin(), 8) + return typ.addr + + case *tI64: + typ.addr = m.DataSeg.Append(_type.Bin(), 8) + return typ.addr + + case *tU64: + typ.addr = m.DataSeg.Append(_type.Bin(), 8) + return typ.addr + + case *tF32: + typ.addr = m.DataSeg.Append(_type.Bin(), 8) + return typ.addr + + case *tF64: + typ.addr = m.DataSeg.Append(_type.Bin(), 8) + return typ.addr + + case *tRune: + typ.addr = m.DataSeg.Append(_type.Bin(), 8) + return typ.addr + + case *String: + typ.addr = m.DataSeg.Append(_type.Bin(), 8) + return typ.addr + + case *Ptr: + typ.addr = m.DataSeg.Append(_type.Bin(), 8) + return typ.addr + + case *Block: + typ.addr = m.DataSeg.Append(_type.Bin(), 8) + return typ.addr + + case *Array: + _array := NewConst("0", m.types_map["runtime._arrayType"]).(*aStruct) + _array.setFieldConstValue("$_type", _type) + _array.setFieldConstValue("elemType", NewConst(strconv.Itoa(m.buildTypeInfo(typ.Base)), m.UPTR)) + _array.setFieldConstValue("cap", NewConst(strconv.Itoa(typ.Capacity), m.UPTR)) + typ.addr = m.DataSeg.Append(_array.Bin(), 8) + return typ.addr + + case *Slice: + _slice := NewConst("0", m.types_map["runtime._arrayType"]).(*aStruct) + _slice.setFieldConstValue("$_type", _type) + _slice.setFieldConstValue("elemType", NewConst(strconv.Itoa(m.buildTypeInfo(typ.Base)), m.UPTR)) + typ.addr = m.DataSeg.Append(_slice.Bin(), 8) + return typ.addr + + case *Ref: + _ref := NewConst("0", m.types_map["runtime._refType"]).(*aStruct) + typ.addr = m.DataSeg.Alloc(len(_ref.Bin()), 8) + + _ref.setFieldConstValue("$_type", _type) + _ref.setFieldConstValue("elemType", NewConst(strconv.Itoa(m.buildTypeInfo(typ.Base)), m.UPTR)) + if len(typ.methods) > 0 { + _uncommon := NewConst("0", m.types_map["runtime._uncommonType"]).(*aStruct) + _uncommon.setFieldConstValue("methodCount", NewConst(strconv.Itoa(len(typ.methods)), m.U32)) + _uncommon_bin := _uncommon.Bin() + for _, method := range typ.methods { + _method := NewConst("0", m.types_map["runtime._method"]).(*aStruct) + _method.setFieldConstValue("name", NewConst(method.Name, m.STRING)) + _method.setFieldConstValue("fnType", NewConst(strconv.Itoa(m.buildFnTypeInfo(&method.Sig)), m.UPTR)) + _method.setFieldConstValue("fnID", NewConst(strconv.Itoa(m.AddTableElem(method.FullFnName)), m.U32)) + _uncommon_bin = append(_uncommon_bin, _method.Bin()...) + } + _ref.setFieldConstValue("uncommon", NewConst(strconv.Itoa(m.DataSeg.Append(_uncommon_bin, 8)), m.UPTR)) + } + + m.DataSeg.Set(_ref.Bin(), typ.addr) + return typ.addr + + case *Closure: + typ.addr = m.DataSeg.Append(_type.Bin(), 8) + return typ.addr + + case *Struct: + _struct := NewConst("0", m.types_map["runtime._structType"]).(*aStruct) + _structField := NewConst("0", m.types_map["runtime._structField"]).(*aStruct) + typ.addr = m.DataSeg.Alloc(len(_struct.Bin())+len(_structField.Bin())*len(typ.fields), 8) + + _struct.setFieldConstValue("$_type", _type) + _struct.setFieldConstValue("fieldCount", NewConst(strconv.Itoa(len(typ.fields)), m.U32)) + _struct_bin := _struct.Bin() + for _, f := range typ.fields { + _structField.setFieldConstValue("name", NewConst(f.Name(), m.STRING)) + _structField.setFieldConstValue("typ", NewConst(strconv.Itoa(m.buildTypeInfo(f.Type())), m.UPTR)) + _struct_bin = append(_struct_bin, _structField.Bin()...) + } + + m.DataSeg.Set(_struct_bin, typ.addr) + return typ.addr + + case *Interface: + _interface := NewConst("0", m.types_map["runtime._interfaceType"]).(*aStruct) + _imethod := NewConst("0", m.types_map["runtime._imethod"]).(*aStruct) + typ.addr = m.DataSeg.Alloc(len(_interface.Bin())+len(_imethod.Bin())*typ.NumMethods(), 8) + + _interface.setFieldConstValue("methodCount", NewConst(strconv.Itoa(typ.NumMethods()), m.U32)) + _interface_bin := _interface.Bin() + for _, method := range typ.methods { + _imethod.setFieldConstValue("name", NewConst(method.Name, m.STRING)) + _imethod.setFieldConstValue("fnType", NewConst(strconv.Itoa(m.buildFnTypeInfo(&method.Sig)), m.UPTR)) + _interface_bin = append(_interface_bin, _imethod.Bin()...) + } + + m.DataSeg.Set(_interface_bin, typ.addr) + return typ.addr + + default: + logger.Fatalf("Todo: %t", t) + return 0 + } +} + +func (m *Module) buildFnTypeInfo(sig *FnSig) int { + s, ok := m.fnSigsName[sig.String()] + if ok && s.typeAddr != 0 { + return s.typeAddr + } + + _fnType := NewConst("0", m.types_map["runtime._fnType"]).(*aStruct) + _fnType.setFieldConstValue("paramCount", NewConst(strconv.Itoa(len(sig.Params)), m.U32)) + _fnType.setFieldConstValue("resultCount", NewConst(strconv.Itoa(len(sig.Results)), m.U32)) + _fnType_bin := _fnType.Bin() + + for _, p := range sig.Params { + typaddr := m.buildTypeInfo(p) + typaddr_bin := NewConst(strconv.Itoa(typaddr), m.UPTR).Bin() + _fnType_bin = append(_fnType_bin, typaddr_bin...) + } + + for _, p := range sig.Results { + typaddr := m.buildTypeInfo(p) + typaddr_bin := NewConst(strconv.Itoa(typaddr), m.UPTR).Bin() + _fnType_bin = append(_fnType_bin, typaddr_bin...) + } + + s.typeAddr = m.DataSeg.Append(_fnType_bin, 8) + m.fnSigsName[sig.String()] = s + return s.typeAddr +} diff --git a/internal/backends/compiler_wat/wir/value_array.go b/internal/backends/compiler_wat/wir/value_array.go index b132bb24ac392901f42afc9d67f4b26e52568729..b67099f14ffa767a22c5f542b6cea5226696c07d 100644 --- a/internal/backends/compiler_wat/wir/value_array.go +++ b/internal/backends/compiler_wat/wir/value_array.go @@ -26,12 +26,7 @@ func (m *Module) GenValueType_Array(base ValueType, capacity int) *Array { return t.(*Array) } - var found bool - arr_t.underlying, found = m.GenValueType_Struct(arr_t.Name() + ".underlying") - if found { - logger.Fatalf("Type: %s already registered.", arr_t.Name()+".underlying") - } - + arr_t.underlying = m.genInternalStruct(arr_t.Name() + ".underlying") for i := 0; i < capacity; i++ { field := m.NewStructField("m"+strconv.Itoa(i), base) arr_t.underlying.AppendField(field) @@ -45,6 +40,7 @@ func (m *Module) GenValueType_Array(base ValueType, capacity int) *Array { func (t *Array) Name() string { return t.Base.Name() + ".$array" + strconv.Itoa(t.Capacity) } func (t *Array) Size() int { return t.underlying.Size() } func (t *Array) align() int { return t.underlying.align() } +func (t *Array) Kind() TypeKind { return kArray } func (t *Array) Raw() []wat.ValueType { return t.underlying.Raw() } func (t *Array) onFree() int { return t.underlying.onFree() } diff --git a/internal/backends/compiler_wat/wir/value_block.go b/internal/backends/compiler_wat/wir/value_block.go index 8644c3195d352c8ffda5903863906931b6f4caa6..96be634aaae8bdd1b1ad5319d4e061f53508f461 100644 --- a/internal/backends/compiler_wat/wir/value_block.go +++ b/internal/backends/compiler_wat/wir/value_block.go @@ -21,27 +21,35 @@ type Block struct { func (m *Module) GenValueType_Block(base ValueType) *Block { block_t := Block{Base: base} - t, ok := m.findValueType(block_t.Name()) - if ok { - return t.(*Block) - } + //t, ok := m.findValueType(block_t.Name()) + //if ok { + // return t.(*Block) + //} + //m.addValueType(&block_t) block_t._i32 = m.I32 block_t._u32 = m.U32 - m.addValueType(&block_t) return &block_t } func (t *Block) Name() string { return t.Base.Name() + ".$$block" } func (t *Block) Size() int { return 4 } func (t *Block) align() int { return 4 } +func (t *Block) Kind() TypeKind { return kBlock } func (t *Block) Raw() []wat.ValueType { return []wat.ValueType{wat.U32{}} } + +func (t *Block) typeInfoAddr() int { + logger.Fatalf("Internal type: %s shouldn't have typeInfo.", t.Name()) + return 0 +} + func (t *Block) Equal(u ValueType) bool { if ut, ok := u.(*Block); ok { return t.Base.Equal(ut.Base) } return false } + func (t *Block) onFree() int { var f Function f.InternalName = "$" + GenSymbolName(t.Name()) + ".$$onFree" diff --git a/internal/backends/compiler_wat/wir/value_closure.go b/internal/backends/compiler_wat/wir/value_closure.go index 1efffa126b67f060923f9c426fecd4df738d0d75..73b6a08175919136169c7fc5135e86adc9142b52 100644 --- a/internal/backends/compiler_wat/wir/value_closure.go +++ b/internal/backends/compiler_wat/wir/value_closure.go @@ -52,44 +52,29 @@ func (s *FnSig) String() string { return n } -/************************************** -FnType: -**************************************/ -type FnType struct { - Name string - FnSig -} - /************************************** Closure: **************************************/ type Closure struct { tCommon - underlying *Struct - _fn_type FnType - _u32 ValueType + underlying *Struct + _fnSig FnSig + _fnTypeName string + _u32 ValueType } -var _closure_id int - func (m *Module) GenValueType_Closure(sig FnSig) *Closure { var closure_t Closure - closure_t._fn_type.FnSig = sig + closure_t._fnSig = sig t, ok := m.findValueType(closure_t.Name()) if ok { return t.(*Closure) } closure_t._u32 = m.U32 - closure_t._fn_type.Name = "closure$" + strconv.Itoa(_closure_id) - _closure_id++ - m.AddFnType(&closure_t._fn_type) - - var found bool - closure_t.underlying, found = m.GenValueType_Struct(closure_t.Name() + ".underlying") - if found { - logger.Fatalf("Type: %s already registered.", closure_t.Name()+".underlying") - } + closure_t._fnTypeName = m.AddFnSig(&sig) + + closure_t.underlying = m.genInternalStruct(closure_t.Name() + ".underlying") closure_t.underlying.AppendField(m.NewStructField("fn_index", m.U32)) closure_t.underlying.AppendField(m.NewStructField("data", m.GenValueType_Ref(m.VOID))) closure_t.underlying.Finish() @@ -98,15 +83,16 @@ func (m *Module) GenValueType_Closure(sig FnSig) *Closure { return &closure_t } -func (t *Closure) Name() string { return t._fn_type.String() } +func (t *Closure) Name() string { return t._fnSig.String() } func (t *Closure) Size() int { return t.underlying.Size() } func (t *Closure) align() int { return t.underlying.align() } +func (t *Closure) Kind() TypeKind { return kStruct } func (t *Closure) onFree() int { return t.underlying.onFree() } func (t *Closure) Raw() []wat.ValueType { return t.underlying.Raw() } func (t *Closure) Equal(u ValueType) bool { if ut, ok := u.(*Closure); ok { - return t._fn_type.FnSig.Equal(&ut._fn_type.FnSig) + return t._fnSig.Equal(&ut._fnSig) } return false } @@ -157,6 +143,6 @@ func EmitCallClosure(c Value, params []Value) (insts []wat.Inst) { insts = append(insts, closure.Extract("data").EmitPush()...) insts = append(insts, currentModule.FindGlobalByName("$wa.RT.closure_data").EmitPop()...) - insts = append(insts, wat.NewInstCallIndirect(closure.typ._fn_type.Name)) + insts = append(insts, wat.NewInstCallIndirect(closure.typ._fnTypeName)) return } diff --git a/internal/backends/compiler_wat/wir/value_interface.go b/internal/backends/compiler_wat/wir/value_interface.go index de1d01172e9dde94ab18117b6023614aae867562..b7124fda464b71551eeaef0c39899d06c8b98077 100644 --- a/internal/backends/compiler_wat/wir/value_interface.go +++ b/internal/backends/compiler_wat/wir/value_interface.go @@ -6,7 +6,6 @@ import ( "strconv" "wa-lang.org/wa/internal/backends/compiler_wat/wir/wat" - "wa-lang.org/wa/internal/logger" ) /************************************** @@ -27,12 +26,7 @@ func (m *Module) GenValueType_Interface(name string) *Interface { var interface_t Interface interface_t.name = name - var found bool - interface_t.underlying, found = m.GenValueType_Struct(interface_t.Name() + ".underlying") - if found { - logger.Fatalf("Type: %s already registered.", interface_t.Name()+".underlying") - } - + interface_t.underlying = m.genInternalStruct(interface_t.Name() + ".underlying") interface_t.underlying.AppendField(m.NewStructField("data", m.GenValueType_Ref(m.GenValueType_Ref(m.VOID)))) interface_t.underlying.AppendField(m.NewStructField("itab", m.U32)) interface_t.underlying.Finish() @@ -44,6 +38,7 @@ func (m *Module) GenValueType_Interface(name string) *Interface { func (t *Interface) Name() string { return t.name } func (t *Interface) Size() int { return t.underlying.Size() } func (t *Interface) align() int { return t.underlying.align() } +func (t *Interface) Kind() TypeKind { return kInterface } func (t *Interface) onFree() int { return t.underlying.onFree() } func (t *Interface) Raw() []wat.ValueType { return t.underlying.Raw() } func (t *Interface) Equal(u ValueType) bool { diff --git a/internal/backends/compiler_wat/wir/value_pointer.go b/internal/backends/compiler_wat/wir/value_pointer.go index f67ac68b75afd5181a90419f2083bb49309ca6b8..8951d5c0ae0b50964dd671604f647d06117c1d26 100644 --- a/internal/backends/compiler_wat/wir/value_pointer.go +++ b/internal/backends/compiler_wat/wir/value_pointer.go @@ -17,26 +17,33 @@ type Ptr struct { func (m *Module) GenValueType_Ptr(base ValueType) *Ptr { ptr_t := Ptr{Base: base} - t, ok := m.findValueType(ptr_t.Name()) - if ok { - return t.(*Ptr) - } - - m.addValueType(&ptr_t) + //t, ok := m.findValueType(ptr_t.Name()) + //if ok { + // return t.(*Ptr) + //} + //m.addValueType(&ptr_t) return &ptr_t } func (t *Ptr) Name() string { return t.Base.Name() + ".$$ptr" } func (t *Ptr) Size() int { return 4 } func (t *Ptr) align() int { return 4 } +func (t *Ptr) Kind() TypeKind { return kPtr } func (t *Ptr) onFree() int { return 0 } func (t *Ptr) Raw() []wat.ValueType { return []wat.ValueType{toWatType(t)} } + +func (t *Ptr) typeInfoAddr() int { + logger.Fatalf("Internal type: %s shouldn't have typeInfo.", t.Name()) + return 0 +} + func (t *Ptr) Equal(u ValueType) bool { if ut, ok := u.(*Ptr); ok { return t.Base.Equal(ut.Base) } return false } + func (t *Ptr) EmitLoadFromAddr(addr Value, offset int) []wat.Inst { if !addr.Type().(*Ptr).Base.Equal(t) { logger.Fatal("Type not match") diff --git a/internal/backends/compiler_wat/wir/value_ref.go b/internal/backends/compiler_wat/wir/value_ref.go index f223cc130fa214720ac6a8b9a0a1f13b0322e6a1..7a4ac907ca15564ee81a061d0de2eedad6bff2c2 100644 --- a/internal/backends/compiler_wat/wir/value_ref.go +++ b/internal/backends/compiler_wat/wir/value_ref.go @@ -31,12 +31,7 @@ func (m *Module) GenValueType_Ref(base ValueType) *Ref { ref_t._void = m.VOID base_ptr := m.GenValueType_Ptr(base) - var found bool - ref_t.underlying, found = m.GenValueType_Struct(ref_t.Name() + ".underlying") - if found { - logger.Fatalf("Type: %s already registered.", ref_t.Name()+".underlying") - } - + ref_t.underlying = m.genInternalStruct(ref_t.Name() + ".underlying") ref_t.underlying.AppendField(m.NewStructField("block", ref_t._base_block)) ref_t.underlying.AppendField(m.NewStructField("data", base_ptr)) ref_t.underlying.Finish() @@ -48,6 +43,7 @@ func (m *Module) GenValueType_Ref(base ValueType) *Ref { func (t *Ref) Name() string { return t.Base.Name() + ".$ref" } func (t *Ref) Size() int { return t.underlying.Size() } func (t *Ref) align() int { return t.underlying.align() } +func (t *Ref) Kind() TypeKind { return kRef } func (t *Ref) onFree() int { return t.underlying.onFree() } func (t *Ref) Raw() []wat.ValueType { return t.underlying.Raw() } func (t *Ref) Equal(u ValueType) bool { diff --git a/internal/backends/compiler_wat/wir/value_slice.go b/internal/backends/compiler_wat/wir/value_slice.go index e3fedb4bfb9f69e998deaad84d3348c144e92ac8..f9b9b50e8000da70f5fe2c6944e6d569a1a8d20b 100644 --- a/internal/backends/compiler_wat/wir/value_slice.go +++ b/internal/backends/compiler_wat/wir/value_slice.go @@ -34,12 +34,7 @@ func (m *Module) GenValueType_Slice(base ValueType) *Slice { slice_t._base_block = m.GenValueType_Block(base) slice_t._base_ptr = m.GenValueType_Ptr(base) - var found bool - slice_t.underlying, found = m.GenValueType_Struct(slice_t.Name() + ".underlying") - if found { - logger.Fatalf("Type: %s already registered.", slice_t.Name()+".underlying") - } - + slice_t.underlying = m.genInternalStruct(slice_t.Name() + ".underlying") slice_t.underlying.AppendField(m.NewStructField("block", slice_t._base_block)) slice_t.underlying.AppendField(m.NewStructField("data", slice_t._base_ptr)) slice_t.underlying.AppendField(m.NewStructField("len", slice_t._u32)) @@ -53,6 +48,7 @@ func (m *Module) GenValueType_Slice(base ValueType) *Slice { func (t *Slice) Name() string { return t.Base.Name() + ".$slice" } func (t *Slice) Size() int { return t.underlying.Size() } func (t *Slice) align() int { return t.underlying.align() } +func (t *Slice) Kind() TypeKind { return kSlice } func (t *Slice) onFree() int { return t.underlying.onFree() } func (t *Slice) Raw() []wat.ValueType { return t.underlying.Raw() } func (t *Slice) Equal(u ValueType) bool { diff --git a/internal/backends/compiler_wat/wir/value_string.go b/internal/backends/compiler_wat/wir/value_string.go index ff690dd30c6790b1b2ea91f6a207dc7d04baf041..f5d7bf4995721dfbc35730eacc73244b3ff99af2 100644 --- a/internal/backends/compiler_wat/wir/value_string.go +++ b/internal/backends/compiler_wat/wir/value_string.go @@ -6,7 +6,6 @@ import ( "strconv" "wa-lang.org/wa/internal/backends/compiler_wat/wir/wat" - "wa-lang.org/wa/internal/logger" ) /************************************** @@ -35,12 +34,7 @@ func (m *Module) GenValueType_String() *String { str_t._u8_block = m.GenValueType_Block(m.U8) str_t._u8_ptr = m.GenValueType_Ptr(m.U8) - var found bool - str_t.underlying, found = m.GenValueType_Struct(str_t.Name() + ".underlying") - if found { - logger.Fatalf("Type: %s already registered.", str_t.Name()+".underlying") - } - + str_t.underlying = m.genInternalStruct(str_t.Name() + ".underlying") str_t.underlying.AppendField(m.NewStructField("block", str_t._u8_block)) str_t.underlying.AppendField(m.NewStructField("data", str_t._u8_ptr)) str_t.underlying.AppendField(m.NewStructField("len", str_t._u32)) @@ -54,6 +48,7 @@ func (m *Module) GenValueType_String() *String { func (t *String) Name() string { return "string" } func (t *String) Size() int { return t.underlying.Size() } func (t *String) align() int { return t.underlying.align() } +func (t *String) Kind() TypeKind { return kString } func (t *String) onFree() int { return t.underlying.onFree() } func (t *String) Raw() []wat.ValueType { return t.underlying.Raw() } func (t *String) Equal(u ValueType) bool { _, ok := u.(*String); return ok } diff --git a/internal/backends/compiler_wat/wir/value_struct.go b/internal/backends/compiler_wat/wir/value_struct.go index 94e472b1925ef2350dafaa6ea2f8c2e3a5a5b870..0f167ab866444e29413155a86d74981a4e4255d6 100644 --- a/internal/backends/compiler_wat/wir/value_struct.go +++ b/internal/backends/compiler_wat/wir/value_struct.go @@ -65,9 +65,18 @@ func (m *Module) GenValueType_Struct(name string) (*Struct, bool) { return &struct_type, false } -func (t *Struct) Name() string { return t.name } -func (t *Struct) Size() int { return t._size } -func (t *Struct) align() int { return t._align } +func (m *Module) genInternalStruct(name string) *Struct { + var struct_type Struct + struct_type.name = name + struct_type._u32 = m.U32 + + return &struct_type +} + +func (t *Struct) Name() string { return t.name } +func (t *Struct) Size() int { return t._size } +func (t *Struct) align() int { return t._align } +func (t *Struct) Kind() TypeKind { return kStruct } func (t *Struct) AppendField(f *StructField) { t.fields = append(t.fields, f) diff --git a/internal/backends/compiler_wat/wir/value_tuple.go b/internal/backends/compiler_wat/wir/value_tuple.go index c061fe40e53fcabe764923aa617c2b371d3eb11a..4eecac72f6a791f01694dbb1a3bd5fffe5592318 100644 --- a/internal/backends/compiler_wat/wir/value_tuple.go +++ b/internal/backends/compiler_wat/wir/value_tuple.go @@ -6,7 +6,6 @@ import ( "strconv" "wa-lang.org/wa/internal/backends/compiler_wat/wir/wat" - "wa-lang.org/wa/internal/logger" ) /************************************** @@ -25,12 +24,7 @@ func (m *Module) GenValueType_Tuple(fields []ValueType) *Tuple { return t.(*Tuple) } - var found bool - tuple_t.underlying, found = m.GenValueType_Struct(tuple_t.Name() + ".underlying") - if found { - logger.Fatalf("Type: %s already registered.", tuple_t.Name()+".underlying") - } - + tuple_t.underlying = m.genInternalStruct(tuple_t.Name() + ".underlying") for i, t := range fields { name := "m" + strconv.Itoa(i) tuple_t.underlying.AppendField(m.NewStructField(name, t)) @@ -51,6 +45,7 @@ func (t *Tuple) Name() string { func (t *Tuple) Size() int { return t.underlying.Size() } func (t *Tuple) align() int { return t.underlying.align() } +func (t *Tuple) Kind() TypeKind { return kTuple } func (t *Tuple) onFree() int { return t.underlying.onFree() } func (t *Tuple) Raw() []wat.ValueType { return t.underlying.Raw() } func (t *Tuple) Equal(u ValueType) bool { diff --git a/internal/backends/compiler_wat/wir/value_type.go b/internal/backends/compiler_wat/wir/value_type.go index baffd751c7800342770a418ad6ac877d23604222..52c30dcfc11ae7995242e2dc11879e0b2a404f33 100644 --- a/internal/backends/compiler_wat/wir/value_type.go +++ b/internal/backends/compiler_wat/wir/value_type.go @@ -7,6 +7,34 @@ import ( "wa-lang.org/wa/internal/logger" ) +type TypeKind uint8 + +const ( + kUnknown TypeKind = iota + kVoid + kU8 + kU16 + kU32 + kU64 + kI8 + kI16 + kI32 + kI64 + kF32 + kF64 + kRune + kPtr + kBlock + kStruct + kTuple + kRef + kString + kSlice + kArray + kMap + kInterface +) + func toWatType(t ValueType) wat.ValueType { switch t.(type) { case *tI32, *tRune, *tI8, *tI16: @@ -44,6 +72,7 @@ func toWatType(t ValueType) wat.ValueType { tCommon: **************************************/ type tCommon struct { + addr int hash int methods []Method } @@ -53,6 +82,7 @@ func (t *tCommon) SetHash(h int) { t.hash = h } func (t *tCommon) AddMethod(m Method) { t.methods = append(t.methods, m) } func (t *tCommon) NumMethods() int { return len(t.methods) } func (t *tCommon) Method(i int) Method { return t.methods[i] } +func (t *tCommon) typeInfoAddr() int { return t.addr } //func (t *tCommon) AddMethodEntry(m FnType) { logger.Fatal("Can't add method for common type.") } // @@ -76,6 +106,7 @@ type tVoid struct { func (t *tVoid) Name() string { return "void" } func (t *tVoid) Size() int { return 0 } func (t *tVoid) align() int { return 0 } +func (t *tVoid) Kind() TypeKind { return kVoid } func (t *tVoid) onFree() int { return 0 } func (t *tVoid) Raw() []wat.ValueType { return []wat.ValueType{} } func (t *tVoid) Equal(u ValueType) bool { _, ok := u.(*tVoid); return ok } @@ -94,6 +125,7 @@ type tRune struct { func (t *tRune) Name() string { return "rune" } func (t *tRune) Size() int { return 4 } func (t *tRune) align() int { return 4 } +func (t *tRune) Kind() TypeKind { return kRune } func (t *tRune) onFree() int { return 0 } func (t *tRune) Raw() []wat.ValueType { return []wat.ValueType{wat.I32{}} } func (t *tRune) Equal(u ValueType) bool { _, ok := u.(*tRune); return ok } @@ -117,6 +149,7 @@ type tI8 struct { func (t *tI8) Name() string { return "i8" } func (t *tI8) Size() int { return 1 } func (t *tI8) align() int { return 1 } +func (t *tI8) Kind() TypeKind { return kI8 } func (t *tI8) onFree() int { return 0 } func (t *tI8) Raw() []wat.ValueType { return []wat.ValueType{wat.I32{}} } func (t *tI8) Equal(u ValueType) bool { _, ok := u.(*tI8); return ok } @@ -140,6 +173,7 @@ type tU8 struct { func (t *tU8) Name() string { return "u8" } func (t *tU8) Size() int { return 1 } func (t *tU8) align() int { return 1 } +func (t *tU8) Kind() TypeKind { return kU8 } func (t *tU8) onFree() int { return 0 } func (t *tU8) Raw() []wat.ValueType { return []wat.ValueType{wat.I32{}} } func (t *tU8) Equal(u ValueType) bool { _, ok := u.(*tU8); return ok } @@ -163,6 +197,7 @@ type tI16 struct { func (t *tI16) Name() string { return "i16" } func (t *tI16) Size() int { return 2 } func (t *tI16) align() int { return 2 } +func (t *tI16) Kind() TypeKind { return kI16 } func (t *tI16) onFree() int { return 0 } func (t *tI16) Raw() []wat.ValueType { return []wat.ValueType{wat.I32{}} } func (t *tI16) Equal(u ValueType) bool { _, ok := u.(*tI16); return ok } @@ -186,6 +221,7 @@ type tU16 struct { func (t *tU16) Name() string { return "u16" } func (t *tU16) Size() int { return 2 } func (t *tU16) align() int { return 2 } +func (t *tU16) Kind() TypeKind { return kU16 } func (t *tU16) onFree() int { return 0 } func (t *tU16) Raw() []wat.ValueType { return []wat.ValueType{wat.I32{}} } func (t *tU16) Equal(u ValueType) bool { _, ok := u.(*tU16); return ok } @@ -209,6 +245,7 @@ type tI32 struct { func (t *tI32) Name() string { return "i32" } func (t *tI32) Size() int { return 4 } func (t *tI32) align() int { return 4 } +func (t *tI32) Kind() TypeKind { return kI32 } func (t *tI32) onFree() int { return 0 } func (t *tI32) Raw() []wat.ValueType { return []wat.ValueType{wat.I32{}} } func (t *tI32) Equal(u ValueType) bool { _, ok := u.(*tI32); return ok } @@ -232,6 +269,7 @@ type tU32 struct { func (t *tU32) Name() string { return "u32" } func (t *tU32) Size() int { return 4 } func (t *tU32) align() int { return 4 } +func (t *tU32) Kind() TypeKind { return kU32 } func (t *tU32) onFree() int { return 0 } func (t *tU32) Raw() []wat.ValueType { return []wat.ValueType{wat.U32{}} } func (t *tU32) Equal(u ValueType) bool { _, ok := u.(*tU32); return ok } @@ -255,6 +293,7 @@ type tI64 struct { func (t *tI64) Name() string { return "i64" } func (t *tI64) Size() int { return 8 } func (t *tI64) align() int { return 8 } +func (t *tI64) Kind() TypeKind { return kI64 } func (t *tI64) onFree() int { return 0 } func (t *tI64) Raw() []wat.ValueType { return []wat.ValueType{wat.I64{}} } func (t *tI64) Equal(u ValueType) bool { _, ok := u.(*tI64); return ok } @@ -278,6 +317,7 @@ type tU64 struct { func (t *tU64) Name() string { return "u64" } func (t *tU64) Size() int { return 8 } func (t *tU64) align() int { return 8 } +func (t *tU64) Kind() TypeKind { return kU64 } func (t *tU64) onFree() int { return 0 } func (t *tU64) Raw() []wat.ValueType { return []wat.ValueType{wat.U64{}} } func (t *tU64) Equal(u ValueType) bool { _, ok := u.(*tU64); return ok } @@ -301,6 +341,7 @@ type tF32 struct { func (t *tF32) Name() string { return "f32" } func (t *tF32) Size() int { return 4 } func (t *tF32) align() int { return 4 } +func (t *tF32) Kind() TypeKind { return kF32 } func (t *tF32) onFree() int { return 0 } func (t *tF32) Raw() []wat.ValueType { return []wat.ValueType{wat.F32{}} } func (t *tF32) Equal(u ValueType) bool { _, ok := u.(*tF32); return ok } @@ -324,6 +365,7 @@ type tF64 struct { func (t *tF64) Name() string { return "f64" } func (t *tF64) Size() int { return 8 } func (t *tF64) align() int { return 8 } +func (t *tF64) Kind() TypeKind { return kF64 } func (t *tF64) onFree() int { return 0 } func (t *tF64) Raw() []wat.ValueType { return []wat.ValueType{wat.F64{}} } func (t *tF64) Equal(u ValueType) bool { _, ok := u.(*tF64); return ok } diff --git a/internal/backends/compiler_wat/wir/wir.go b/internal/backends/compiler_wat/wir/wir.go index 4ff43e1fc4195615ac77e439ebf967a5aded6fa3..02790917620e9e3cb6fd44e8b9606bdb8086faab 100644 --- a/internal/backends/compiler_wat/wir/wir.go +++ b/internal/backends/compiler_wat/wir/wir.go @@ -54,6 +54,7 @@ type ValueType interface { Name() string Size() int align() int + Kind() TypeKind onFree() int Raw() []wat.ValueType Equal(ValueType) bool @@ -65,6 +66,8 @@ type ValueType interface { AddMethod(m Method) NumMethods() int Method(i int) Method + + typeInfoAddr() int } /************************************** diff --git a/internal/waroot/_waroot/src/runtime/runtime_type.wa b/internal/waroot/_waroot/src/runtime/runtime_type.wa index 97023b808f29be9c15014d9bdb1e0ee11c44c79c..3b202b9432df817993970415c527c7cc0fe30147 100644 --- a/internal/waroot/_waroot/src/runtime/runtime_type.wa +++ b/internal/waroot/_waroot/src/runtime/runtime_type.wa @@ -13,8 +13,8 @@ type _type struct { type _refType struct { _type - uncommon: uintptr //@_uncommonType elemType: uintptr //@_type + uncommon: uintptr //@_uncommonType } type _arrayType struct { @@ -30,10 +30,8 @@ type _sliceType struct { type _structType struct { _type - uncommon: uintptr //@_uncommonType - fieldCount: i32 - fieldPtr: uintptr //@_structField, len==fieldCount -} + fieldCount: u32 +} //followed by [fieldCount]_structField type _structField struct { name: string @@ -42,9 +40,8 @@ type _structField struct { type _uncommonType struct { pkgName: string - methodCount: i32 - methodPtr: uintptr //@_method, len==methodCount -} + methodCount: u32 +} //followed by [methodCount]_method type _method struct { name: string @@ -53,19 +50,16 @@ type _method struct { } type _fnType struct { - _type - paramCount: i32 - paramPtr: uintptr //@@_type, len==paramCount - resultCount: i32 - resultPtr: uintptr //@@_type, len==resultCount -} + //_type //Todo + paramCount: u32 + resultCount: u32 +} //followed by [paramCount]@_type + [resultCount]@_type type _interfaceType struct { _type pkgName: string - methodCount: i32 - methodPtr: uintptr //@_imethod, len==methodCount -} + methodCount: u32 +} //followed by [methodCount]_imethod type _imethod struct { name: string @@ -75,7 +69,7 @@ type _imethod struct { type _itab struct { dtype: uintptr //@_type, ptr of (*data).(type) itype: uintptr //@_interfacetype -} //紧接[itype.methodCound]fnID, fnID=id for call_indirect +} //followed by [itype.methodCound]fnID, fnID=>id for call_indirect type _iface struct { data: *i32