diff --git a/internal/backends/compiler_wat/compile_func.go b/internal/backends/compiler_wat/compile_func.go index f339fb3..74a4c47 100644 --- a/internal/backends/compiler_wat/compile_func.go +++ b/internal/backends/compiler_wat/compile_func.go @@ -876,16 +876,23 @@ func (g *functionGenerator) genMakeClosre_Anonymous(inst *ssa.MakeClosure) (inst panic("ret_type != inst.Type()") } - var st_free_data wir.ValueType + var st_free_data *wir.Struct { - var fields []wir.Field - for _, freevar := range f.FreeVars { - feild := wir.NewField(freevar.Name(), g.tLib.compile(freevar.Type())) - fields = append(fields, feild) - } fn_internal_name, _ := wir.GetFnMangleName(f) st_name := fn_internal_name + ".$warpdata" - st_free_data = g.module.GenValueType_Struct(st_name, fields) + + var found bool + st_free_data, found = g.module.GenValueType_Struct(st_name) + if found { + logger.Fatalf("Type: %s already registered.", st_name) + } + + for _, freevar := range f.FreeVars { + vtype := g.tLib.compile(freevar.Type()) + field := g.module.NewStructField(freevar.Name(), vtype) + st_free_data.AppendField(field) + } + st_free_data.Finish() } var warp_fn_index int diff --git a/internal/backends/compiler_wat/compile_type.go b/internal/backends/compiler_wat/compile_type.go index 024d800..e4bcfde 100644 --- a/internal/backends/compiler_wat/compile_type.go +++ b/internal/backends/compiler_wat/compile_type.go @@ -41,9 +41,6 @@ func (tLib *typeLib) compile(from types.Type) wir.ValueType { return *v } - //s := from.String() - //println(s) - var newType wir.ValueType tLib.typeTable[from.String()] = &newType uncommanFlag := false @@ -119,20 +116,23 @@ func (tLib *typeLib) compile(from types.Type) wir.ValueType { case *types.Named: switch ut := t.Underlying().(type) { case *types.Struct: - //Todo: 待解决类型嵌套包含的问题 - var fs []wir.Field - for i := 0; i < ut.NumFields(); i++ { - f := ut.Field(i) - wtyp := tLib.compile(f.Type()) - if f.Embedded() { - fs = append(fs, wir.NewField("$"+wtyp.Name(), wtyp)) - } else { - fs = append(fs, wir.NewField(wir.GenSymbolName(f.Name()), wtyp)) - } - } pkg_name, _ := wir.GetPkgMangleName(t.Obj().Pkg().Path()) obj_name := wir.GenSymbolName(t.Obj().Name()) - tStruct := tLib.module.GenValueType_Struct(pkg_name+"."+obj_name, fs) + tStruct, found := tLib.module.GenValueType_Struct(pkg_name + "." + obj_name) + if !found { + for i := 0; i < ut.NumFields(); i++ { + sf := ut.Field(i) + dtyp := tLib.compile(sf.Type()) + if sf.Embedded() { + df := tLib.module.NewStructField("$"+dtyp.Name(), dtyp) + tStruct.AppendField(df) + } else { + df := tLib.module.NewStructField(wir.GenSymbolName(sf.Name()), dtyp) + tStruct.AppendField(df) + } + } + tStruct.Finish() + } newType = tStruct uncommanFlag = true diff --git a/internal/backends/compiler_wat/wir/instruction_emitter.go b/internal/backends/compiler_wat/wir/instruction_emitter.go index bb4f19f..3c093e4 100644 --- a/internal/backends/compiler_wat/wir/instruction_emitter.go +++ b/internal/backends/compiler_wat/wir/instruction_emitter.go @@ -227,7 +227,7 @@ func (m *Module) EmitGenField(x Value, field_name string) (insts []wat.Inst, ret func (m *Module) EmitGenFieldAddr(x Value, field_name string) (insts []wat.Inst, ret_type ValueType) { insts = append(insts, x.EmitPush()...) - var field *Field + var field *StructField switch addr := x.(type) { case *aRef: field = addr.Type().(*Ref).Base.(*Struct).findFieldByName(field_name) diff --git a/internal/backends/compiler_wat/wir/value_array.go b/internal/backends/compiler_wat/wir/value_array.go index 57497c2..b132bb2 100644 --- a/internal/backends/compiler_wat/wir/value_array.go +++ b/internal/backends/compiler_wat/wir/value_array.go @@ -26,11 +26,18 @@ func (m *Module) GenValueType_Array(base ValueType, capacity int) *Array { return t.(*Array) } - var members []Field - for i := 0; i < capacity; i++ { - members = append(members, NewField("m"+strconv.Itoa(i), base)) + 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.GenValueType_Struct(arr_t.Name()+".underlying", members) + + for i := 0; i < capacity; i++ { + field := m.NewStructField("m"+strconv.Itoa(i), base) + arr_t.underlying.AppendField(field) + } + arr_t.underlying.Finish() + m.addValueType(&arr_t) return &arr_t } diff --git a/internal/backends/compiler_wat/wir/value_closure.go b/internal/backends/compiler_wat/wir/value_closure.go index 989190b..1efffa1 100644 --- a/internal/backends/compiler_wat/wir/value_closure.go +++ b/internal/backends/compiler_wat/wir/value_closure.go @@ -84,10 +84,15 @@ func (m *Module) GenValueType_Closure(sig FnSig) *Closure { closure_t._fn_type.Name = "closure$" + strconv.Itoa(_closure_id) _closure_id++ m.AddFnType(&closure_t._fn_type) - var fields []Field - fields = append(fields, NewField("fn_index", m.U32)) - fields = append(fields, NewField("data", m.GenValueType_Ref(m.VOID))) - closure_t.underlying = m.GenValueType_Struct(closure_t.Name()+".underlying", fields) + + 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.underlying.AppendField(m.NewStructField("fn_index", m.U32)) + closure_t.underlying.AppendField(m.NewStructField("data", m.GenValueType_Ref(m.VOID))) + closure_t.underlying.Finish() m.addValueType(&closure_t) return &closure_t diff --git a/internal/backends/compiler_wat/wir/value_interface.go b/internal/backends/compiler_wat/wir/value_interface.go index 06e52cf..de1d011 100644 --- a/internal/backends/compiler_wat/wir/value_interface.go +++ b/internal/backends/compiler_wat/wir/value_interface.go @@ -6,6 +6,7 @@ import ( "strconv" "wa-lang.org/wa/internal/backends/compiler_wat/wir/wat" + "wa-lang.org/wa/internal/logger" ) /************************************** @@ -26,20 +27,16 @@ func (m *Module) GenValueType_Interface(name string) *Interface { var interface_t Interface interface_t.name = name - //interface_t.methodTab = make([]FnType, len(methods)) - //copy(interface_t.methodTab, methods) - // - //for i := 0; i < s.NumMethods(); i++ { - // var method FnType - // method.Name = s.Method(i).Name() - // method.FnSig = m.GenFnSig(s.Method(i).Type().(*types.Signature)) - // interface_t.methods = append(interface_t.methods, method) - //} + 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.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() - var fields []Field - fields = append(fields, NewField("data", m.GenValueType_Ref(m.GenValueType_Ref(m.VOID)))) - fields = append(fields, NewField("itab", m.U32)) - interface_t.underlying = m.GenValueType_Struct(interface_t.Name()+".underlying", fields) m.addValueType(&interface_t) return &interface_t } diff --git a/internal/backends/compiler_wat/wir/value_ref.go b/internal/backends/compiler_wat/wir/value_ref.go index 707ec8f..f223cc1 100644 --- a/internal/backends/compiler_wat/wir/value_ref.go +++ b/internal/backends/compiler_wat/wir/value_ref.go @@ -30,10 +30,17 @@ func (m *Module) GenValueType_Ref(base ValueType) *Ref { ref_t._base_block = m.GenValueType_Block(base) ref_t._void = m.VOID base_ptr := m.GenValueType_Ptr(base) - var members []Field - members = append(members, NewField("block", ref_t._base_block)) - members = append(members, NewField("data", base_ptr)) - ref_t.underlying = m.GenValueType_Struct(ref_t.Name()+".underlying", members) + + 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.AppendField(m.NewStructField("block", ref_t._base_block)) + ref_t.underlying.AppendField(m.NewStructField("data", base_ptr)) + ref_t.underlying.Finish() + m.addValueType(&ref_t) return &ref_t } diff --git a/internal/backends/compiler_wat/wir/value_slice.go b/internal/backends/compiler_wat/wir/value_slice.go index 35486ec..e3fedb4 100644 --- a/internal/backends/compiler_wat/wir/value_slice.go +++ b/internal/backends/compiler_wat/wir/value_slice.go @@ -34,12 +34,18 @@ 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 members []Field - members = append(members, NewField("block", slice_t._base_block)) - members = append(members, NewField("data", slice_t._base_ptr)) - members = append(members, NewField("len", slice_t._u32)) - members = append(members, NewField("cap", slice_t._u32)) - slice_t.underlying = m.GenValueType_Struct(slice_t.Name()+".underlying", members) + 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.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)) + slice_t.underlying.AppendField(m.NewStructField("cap", slice_t._u32)) + slice_t.underlying.Finish() + m.addValueType(&slice_t) return &slice_t } diff --git a/internal/backends/compiler_wat/wir/value_string.go b/internal/backends/compiler_wat/wir/value_string.go index 0a6eb59..ff690dd 100644 --- a/internal/backends/compiler_wat/wir/value_string.go +++ b/internal/backends/compiler_wat/wir/value_string.go @@ -6,6 +6,7 @@ import ( "strconv" "wa-lang.org/wa/internal/backends/compiler_wat/wir/wat" + "wa-lang.org/wa/internal/logger" ) /************************************** @@ -34,11 +35,17 @@ 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 members []Field - members = append(members, NewField("block", str_t._u8_block)) - members = append(members, NewField("data", str_t._u8_ptr)) - members = append(members, NewField("len", str_t._u32)) - str_t.underlying = m.GenValueType_Struct(str_t.Name()+".underlying", members) + 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.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)) + str_t.underlying.Finish() + m.addValueType(&str_t) return &str_t diff --git a/internal/backends/compiler_wat/wir/value_struct.go b/internal/backends/compiler_wat/wir/value_struct.go index 62ab515..94e472b 100644 --- a/internal/backends/compiler_wat/wir/value_struct.go +++ b/internal/backends/compiler_wat/wir/value_struct.go @@ -8,30 +8,35 @@ import ( ) /************************************** -Field: +StructField: **************************************/ -type Field struct { +type StructField struct { name string typ ValueType _start int _typ_ptr *Ptr //type of *typ } -func NewField(n string, t ValueType) Field { return Field{name: n, typ: t} } -func (i *Field) Name() string { return i.name } -func (i *Field) Type() ValueType { return i.typ } -func (i *Field) Equal(u Field) bool { return i.name == u.name && i.typ.Equal(u.typ) } +func (m *Module) NewStructField(name string, typ ValueType) *StructField { + f := StructField{name: name, typ: typ} + f._typ_ptr = m.GenValueType_Ptr(typ) + return &f +} + +func (i *StructField) Name() string { return i.name } +func (i *StructField) Type() ValueType { return i.typ } +func (i *StructField) Equal(u *StructField) bool { return i.name == u.name && i.typ.Equal(u.typ) } /************************************** Struct: **************************************/ type Struct struct { tCommon - name string - Members []Field - _size int - _align int - _u32 ValueType + name string + fields []*StructField + _size int + _align int + _u32 ValueType } type iStruct interface { @@ -46,10 +51,10 @@ func makeAlign(i, align int) int { return (i + align - 1) / align * align } -func (m *Module) GenValueType_Struct(name string, fields []Field) *Struct { +func (m *Module) GenValueType_Struct(name string) (*Struct, bool) { t, ok := m.findValueType(name) if ok { - return t.(*Struct) + return t.(*Struct), true } var struct_type Struct @@ -57,32 +62,38 @@ func (m *Module) GenValueType_Struct(name string, fields []Field) *Struct { struct_type._u32 = m.U32 m.addValueType(&struct_type) - for _, f := range fields { - ma := f.Type().align() - f._start = makeAlign(struct_type._size, ma) - f._typ_ptr = m.GenValueType_Ptr(f.typ) - struct_type.Members = append(struct_type.Members, f) - - struct_type._size = f._start + f.Type().Size() - if ma > struct_type._align { - struct_type._align = ma - } - } - struct_type._size = makeAlign(struct_type._size, struct_type._align) - return &struct_type + 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 (t *Struct) AppendField(f *StructField) { + t.fields = append(t.fields, f) +} + +func (t *Struct) Finish() { + t._size = 0 + for _, field := range t.fields { + fa := field.Type().align() + field._start = makeAlign(t._size, fa) + + t._size = field._start + field.Type().Size() + if fa > t._align { + t._align = fa + } + } + t._size = makeAlign(t._size, t._align) +} + type fn_offset_pair struct { fn int offset int } func (t *Struct) genRawFree() (ret []fn_offset_pair) { - for _, member := range t.Members { + for _, member := range t.fields { member_type := member.Type() if istruct, ok := member_type.(iStruct); ok { rfs := istruct.genRawFree() @@ -131,7 +142,7 @@ func (t *Struct) onFree() int { func (t *Struct) Raw() []wat.ValueType { var r []wat.ValueType - for _, f := range t.Members { + for _, f := range t.fields { r = append(r, f.Type().Raw()...) } return r @@ -143,12 +154,12 @@ func (t *Struct) Equal(u ValueType) bool { return false } - if len(t.Members) != len(ut.Members) { + if len(t.fields) != len(ut.fields) { return false } - for i := range t.Members { - if !t.Members[i].Equal(ut.Members[i]) { + for i := range t.fields { + if !t.fields[i].Equal(ut.fields[i]) { return false } } @@ -157,17 +168,17 @@ func (t *Struct) Equal(u ValueType) bool { } func (t *Struct) EmitLoadFromAddr(addr Value, offset int) (insts []wat.Inst) { - for _, m := range t.Members { + for _, m := range t.fields { ptr := newValue_Ptr(addr.Name(), addr.Kind(), m._typ_ptr) insts = append(insts, m.Type().EmitLoadFromAddr(ptr, m._start+offset)...) } return } -func (t *Struct) findFieldByName(field_name string) *Field { - for i := range t.Members { - if t.Members[i].Name() == field_name { - return &t.Members[i] +func (t *Struct) findFieldByName(field_name string) *StructField { + for i := range t.fields { + if t.fields[i].Name() == field_name { + return t.fields[i] } } return nil @@ -191,7 +202,7 @@ func newValue_Struct(name string, kind ValueKind, typ *Struct) *aStruct { return &v } -func (v *aStruct) genSubValue(m Field) Value { +func (v *aStruct) genSubValue(m *StructField) Value { if v.Kind() != ValueKindConst { return newValue(v.Name()+"."+m.Name(), v.Kind(), m.Type()) } else { @@ -217,7 +228,7 @@ func (v *aStruct) setFieldConstValue(field string, sv Value) { func (v *aStruct) raw() []wat.Value { var r []wat.Value st := v.Type().(*Struct) - for _, m := range st.Members { + for _, m := range st.fields { t := v.genSubValue(m) r = append(r, t.raw()...) } @@ -227,7 +238,7 @@ func (v *aStruct) raw() []wat.Value { func (v *aStruct) EmitInit() []wat.Inst { var insts []wat.Inst st := v.Type().(*Struct) - for _, m := range st.Members { + for _, m := range st.fields { t := v.genSubValue(m) insts = append(insts, t.EmitInit()...) } @@ -237,7 +248,7 @@ func (v *aStruct) EmitInit() []wat.Inst { func (v *aStruct) EmitPush() []wat.Inst { var insts []wat.Inst st := v.Type().(*Struct) - for _, m := range st.Members { + for _, m := range st.fields { t := v.genSubValue(m) insts = append(insts, t.EmitPush()...) } @@ -247,8 +258,8 @@ func (v *aStruct) EmitPush() []wat.Inst { func (v *aStruct) EmitPop() []wat.Inst { var insts []wat.Inst st := v.Type().(*Struct) - for i := range st.Members { - m := st.Members[len(st.Members)-i-1] + for i := range st.fields { + m := st.fields[len(st.fields)-i-1] t := v.genSubValue(m) insts = append(insts, t.EmitPop()...) } @@ -258,8 +269,8 @@ func (v *aStruct) EmitPop() []wat.Inst { func (v *aStruct) EmitRelease() []wat.Inst { var insts []wat.Inst st := v.Type().(*Struct) - for i := range st.Members { - m := st.Members[len(st.Members)-i-1] + for i := range st.fields { + m := st.fields[len(st.fields)-i-1] t := v.genSubValue(m) insts = append(insts, t.EmitRelease()...) } @@ -268,7 +279,7 @@ func (v *aStruct) EmitRelease() []wat.Inst { func (v *aStruct) Extract(member_name string) Value { st := v.Type().(*Struct) - for _, m := range st.Members { + for _, m := range st.fields { if m.Name() == member_name { return v.genSubValue(m) } @@ -278,7 +289,7 @@ func (v *aStruct) Extract(member_name string) Value { func (v *aStruct) emitStoreToAddr(addr Value, offset int) (insts []wat.Inst) { st := v.Type().(*Struct) - for _, m := range st.Members { + for _, m := range st.fields { t := v.genSubValue(m) ptr := newValue_Ptr(addr.Name(), addr.Kind(), m._typ_ptr) insts = append(insts, t.emitStoreToAddr(ptr, m._start+offset)...) @@ -288,7 +299,7 @@ func (v *aStruct) emitStoreToAddr(addr Value, offset int) (insts []wat.Inst) { func (v *aStruct) emitStore(offset int) (insts []wat.Inst) { st := v.Type().(*Struct) - for _, m := range st.Members { + for _, m := range st.fields { t := v.genSubValue(m) insts = append(insts, t.emitStore(m._start+offset)...) } @@ -301,7 +312,7 @@ func (v *aStruct) Bin() (b []byte) { } b = make([]byte, v.typ.Size()) - for _, m := range v.typ.Members { + for _, m := range v.typ.fields { d := b[m._start:] copy(d, v.genSubValue(m).Bin()) } diff --git a/internal/backends/compiler_wat/wir/value_tuple.go b/internal/backends/compiler_wat/wir/value_tuple.go index 94cba20..c061fe4 100644 --- a/internal/backends/compiler_wat/wir/value_tuple.go +++ b/internal/backends/compiler_wat/wir/value_tuple.go @@ -6,6 +6,7 @@ import ( "strconv" "wa-lang.org/wa/internal/backends/compiler_wat/wir/wat" + "wa-lang.org/wa/internal/logger" ) /************************************** @@ -24,12 +25,18 @@ func (m *Module) GenValueType_Tuple(fields []ValueType) *Tuple { return t.(*Tuple) } - var members []Field - for i, t := range fields { - fname := "m" + strconv.Itoa(i) - members = append(members, NewField(fname, t)) + 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.GenValueType_Struct(tuple_t.Name()+".underlying", members) + + for i, t := range fields { + name := "m" + strconv.Itoa(i) + tuple_t.underlying.AppendField(m.NewStructField(name, t)) + } + tuple_t.underlying.Finish() + m.addValueType(&tuple_t) return &tuple_t } @@ -98,9 +105,9 @@ func (v *aTuple) emitStoreToAddr(addr Value, offset int) []wat.Inst { func (v *aTuple) Extract(id int) Value { st := v.typ.underlying - if id >= len(st.Members) { + if id >= len(st.fields) { panic("id >= len(st.Members)") } - return v.aStruct.genSubValue(st.Members[id]) + return v.aStruct.genSubValue(st.fields[id]) }