1
16
17 package loader
18
19 import (
20 `reflect`
21 `unsafe`
22
23 `github.com/bytedance/sonic/internal/abi`
24 `github.com/bytedance/sonic/internal/rt`
25 )
26
27 var _C_Redzone = []bool{false, false, false, false}
28
29
30 type CFunc struct {
31
32 Name string
33
34
35 EntryOff uint32
36
37
38 TextSize uint32
39
40
41 MaxStack uintptr
42
43
44 Pcsp [][2]uint32
45 }
46
47
48 type GoC struct {
49
50 CName string
51
52
53
54 CEntry *uintptr
55
56
57
58
59
60
61
62 GoFunc interface{}
63 }
64
65
66 func WrapGoC(text []byte, natives []CFunc, stubs []GoC, modulename string, filename string) {
67 funcs := make([]Func, len(natives))
68
69
70 for i, f := range natives {
71 fn := Func{
72 Flag: FuncFlag_ASM,
73 EntryOff: f.EntryOff,
74 TextSize: f.TextSize,
75 Name: f.Name,
76 }
77 if len(f.Pcsp) != 0 {
78 fn.Pcsp = (*Pcdata)(unsafe.Pointer(&natives[i].Pcsp))
79 }
80
81 fn.PcUnsafePoint = &Pcdata{
82 {PC: f.TextSize, Val: PCDATA_UnsafePointUnsafe},
83 }
84
85 fn.Pcfile = &Pcdata{
86 {PC: f.TextSize, Val: 0},
87 }
88
89 fn.Pcline = &Pcdata{
90 {PC: f.TextSize, Val: 1},
91 }
92
93 fn.PcStackMapIndex = &Pcdata{
94 {PC: f.TextSize, Val: 0},
95 }
96 sm := rt.StackMapBuilder{}
97 sm.AddField(false)
98 fn.ArgsPointerMaps = sm.Build()
99 fn.LocalsPointerMaps = sm.Build()
100 funcs[i] = fn
101 }
102 rets := Load(text, funcs, modulename, []string{filename})
103
104
105 native_entry := **(**uintptr)(unsafe.Pointer(&rets[0]))
106
107
108 wraps := make([]Func, 0, len(stubs))
109 wrapIds := make([]int, 0, len(stubs))
110 code := make([]byte, 0, len(wraps))
111 entryOff := uint32(0)
112
113
114 for i := range stubs {
115 for j := range natives {
116 if stubs[i].CName != natives[j].Name {
117 continue
118 }
119
120
121 pc := uintptr(native_entry + uintptr(natives[j].EntryOff))
122 if stubs[i].CEntry != nil {
123 *stubs[i].CEntry = pc
124 }
125
126
127 if stubs[i].GoFunc == nil {
128 continue
129 }
130
131
132 layout := abi.NewFunctionLayout(reflect.TypeOf(stubs[i].GoFunc).Elem())
133 frame := abi.NewFrame(&layout, _C_Redzone, true)
134 tcode := abi.CallC(pc, frame, natives[j].MaxStack)
135 code = append(code, tcode...)
136 size := uint32(len(tcode))
137
138 fn := Func{
139 Flag: FuncFlag_ASM,
140 ArgsSize: int32(layout.ArgSize()),
141 EntryOff: entryOff,
142 TextSize: size,
143 Name: stubs[i].CName + "_go",
144 }
145
146
147 fn.Pcsp = &Pcdata{
148 {PC: uint32(frame.StackCheckTextSize()), Val: 0},
149 {PC: size - uint32(frame.GrowStackTextSize()), Val: int32(frame.Size())},
150 {PC: size, Val: 0},
151 }
152
153 fn.Pcfile = &Pcdata{
154 {PC: size, Val: 0},
155 }
156
157 fn.Pcline = &Pcdata{
158 {PC: size, Val: 1},
159 }
160
161 fn.PcUnsafePoint = &Pcdata{
162 {PC: size, Val: PCDATA_UnsafePointUnsafe},
163 }
164
165
166 fn.PcStackMapIndex = &Pcdata{
167 {PC: size, Val: 0},
168 }
169 fn.ArgsPointerMaps = frame.ArgPtrs()
170 fn.LocalsPointerMaps = frame.LocalPtrs()
171
172 entryOff += size
173 wraps = append(wraps, fn)
174 wrapIds = append(wrapIds, i)
175 }
176 }
177 gofuncs := Load(code, wraps, modulename+"/go", []string{filename+".go"})
178
179
180 for i := range gofuncs {
181 idx := wrapIds[i]
182 w := rt.UnpackEface(stubs[idx].GoFunc)
183 *(*Function)(w.Value) = gofuncs[i]
184 }
185 }
186
View as plain text