github.com/cloudwego/frugal@v0.1.15/internal/atm/hir/builder.go (about) 1 /* 2 * Copyright 2022 ByteDance Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package hir 18 19 import ( 20 `strconv` 21 `strings` 22 `unsafe` 23 24 `github.com/cloudwego/frugal/internal/rt` 25 ) 26 27 const ( 28 _LB_jump_pc = "_jump_pc_" 29 ) 30 31 type Builder struct { 32 i int 33 head *Ir 34 tail *Ir 35 refs map[string]*Ir 36 pends map[string][]**Ir 37 } 38 39 func CreateBuilder() *Builder { 40 return newBuilder() 41 } 42 43 func (self *Builder) add(ins *Ir) *Ir { 44 self.push(ins) 45 return ins 46 } 47 48 func (self *Builder) jmp(p *Ir, to string) *Ir { 49 ok := false 50 lr := Likely 51 lb := strings.ReplaceAll(to, "{n}", strconv.Itoa(self.i)) 52 53 /* backward jumps are predicted "likely", forward "unlikely" */ 54 if p.Br, ok = self.refs[lb]; !ok { 55 lr = Unlikely 56 self.pends[lb] = append(self.pends[lb], &p.Br) 57 } 58 59 /* unconditional jumps are always predicted "likely" */ 60 if p.Op == OP_jmp { 61 lr = Likely 62 } 63 64 /* add to instruction buffer */ 65 p.An = uint8(lr) 66 return self.add(p) 67 } 68 69 func (self *Builder) tab(p *Ir, sw []string) *Ir { 70 nb := len(sw) 71 sb := make([]*Ir, nb) 72 73 /* patch each branch */ 74 for i, to := range sw { 75 ok := false 76 lb := strings.ReplaceAll(to, "{n}", strconv.Itoa(self.i)) 77 78 /* check for backward jumps */ 79 if lb != "" { 80 if sb[i], ok = self.refs[lb]; !ok { 81 self.pends[lb] = append(self.pends[lb], &sb[i]) 82 } 83 } 84 } 85 86 /* save the switch table */ 87 p.Iv = int64(nb) 88 p.Pr = (*rt.GoSlice)(unsafe.Pointer(&sb)).Ptr 89 return self.add(p) 90 } 91 92 func (self *Builder) push(ins *Ir) { 93 if self.head == nil { 94 self.head, self.tail = ins, ins 95 } else { 96 self.tail.Ln, self.tail = ins, ins 97 } 98 } 99 100 func (self *Builder) rejmp(br **Ir) { 101 for *br != nil && (*br).Ln != nil && (*br).Op == OP_nop { 102 *br = (*br).Ln 103 } 104 } 105 106 func (self *Builder) At(pc int) string { 107 return _LB_jump_pc + strconv.Itoa(pc) 108 } 109 110 func (self *Builder) Mark(pc int) { 111 self.i++ 112 self.Label(self.At(pc)) 113 } 114 115 func (self *Builder) Label(to string) { 116 ok := false 117 lb := strings.ReplaceAll(to, "{n}", strconv.Itoa(self.i)) 118 119 /* check for duplications */ 120 if _, ok = self.refs[lb]; ok { 121 panic("label " + lb + " has already been linked") 122 } 123 124 /* get the pending links */ 125 p := self.NOP() 126 v := self.pends[lb] 127 128 /* patch all the pending jumps */ 129 for _, q := range v { 130 *q = p 131 } 132 133 /* mark the label as resolved */ 134 self.refs[lb] = p 135 delete(self.pends, lb) 136 } 137 138 func (self *Builder) Build() (r Program) { 139 var n int 140 var p *Ir 141 var q *Ir 142 143 /* check for unresolved labels */ 144 for key := range self.pends { 145 panic("labels are not fully resolved: " + key) 146 } 147 148 /* adjust jumps to point at actual instructions */ 149 for p = self.head; p != nil; p = p.Ln { 150 if p.IsBranch() { 151 if p.Op != OP_bsw { 152 self.rejmp(&p.Br) 153 } else { 154 for i := int64(0); i < p.Iv * 8; i += 8 { 155 self.rejmp((**Ir)(unsafe.Pointer(uintptr(p.Pr) + uintptr(i)))) 156 } 157 } 158 } 159 } 160 161 /* remove NOPs at the front */ 162 for self.head != nil && self.head.Op == OP_nop { 163 self.head = self.head.Ln 164 } 165 166 /* no instructions left, the program was composed entirely by NOPs */ 167 if self.head == nil { 168 self.tail = nil 169 return 170 } 171 172 /* remove all the NOPs, there should be no jumps pointing to any NOPs */ 173 for p = self.head; p != nil; p, n = p.Ln, n + 1 { 174 for p.Ln != nil && p.Ln.Op == OP_nop { 175 q = p.Ln 176 p.Ln = q.Ln 177 q.Free() 178 } 179 } 180 181 /* the Builder's life-time ends here */ 182 r.Head = self.head 183 freeBuilder(self) 184 return 185 } 186 187 func (self *Builder) Append(p *Ir) (r *Ir) { 188 self.push(p) 189 r = self.head 190 freeBuilder(self) 191 return 192 } 193 194 func (self *Builder) NOP() *Ir { 195 return self.add(newInstr(OP_nop)) 196 } 197 198 func (self *Builder) IB(v int8, rx GenericRegister) *Ir { 199 return self.ADDI(Rz, int64(v), rx) 200 } 201 202 func (self *Builder) IW(v int16, rx GenericRegister) *Ir { 203 return self.ADDI(Rz, int64(v), rx) 204 } 205 206 func (self *Builder) IL(v int32, rx GenericRegister) *Ir { 207 return self.ADDI(Rz, int64(v), rx) 208 } 209 210 func (self *Builder) IQ(v int64, rx GenericRegister) *Ir { 211 return self.ADDI(Rz, v, rx) 212 } 213 214 func (self *Builder) IP(v interface{}, pd PointerRegister) *Ir { 215 if vv := rt.UnpackEface(v); !rt.IsPtr(vv.Type) { 216 panic("v is not a pointer") 217 } else { 218 return self.add(newInstr(OP_ip).pr(vv.Value).pd(pd)) 219 } 220 } 221 222 func (self *Builder) LB(ps PointerRegister, disp int64, rx GenericRegister) *Ir { 223 return self.add(newInstr(OP_lb).ps(ps).iv(disp).rx(rx)) 224 } 225 226 func (self *Builder) LW(ps PointerRegister, disp int64, rx GenericRegister) *Ir { 227 return self.add(newInstr(OP_lw).ps(ps).iv(disp).rx(rx)) 228 } 229 230 func (self *Builder) LL(ps PointerRegister, disp int64, rx GenericRegister) *Ir { 231 return self.add(newInstr(OP_ll).ps(ps).iv(disp).rx(rx)) 232 } 233 234 func (self *Builder) LQ(ps PointerRegister, disp int64, rx GenericRegister) *Ir { 235 return self.add(newInstr(OP_lq).ps(ps).iv(disp).rx(rx)) 236 } 237 238 func (self *Builder) LP(ps PointerRegister, disp int64, pd PointerRegister) *Ir { 239 return self.add(newInstr(OP_lp).ps(ps).iv(disp).pd(pd)) 240 } 241 242 func (self *Builder) SB(rx GenericRegister, pd PointerRegister, disp int64) *Ir { 243 return self.add(newInstr(OP_sb).rx(rx).pd(pd).iv(disp)) 244 } 245 246 func (self *Builder) SW(rx GenericRegister, pd PointerRegister, disp int64) *Ir { 247 return self.add(newInstr(OP_sw).rx(rx).pd(pd).iv(disp)) 248 } 249 250 func (self *Builder) SL(rx GenericRegister, pd PointerRegister, disp int64) *Ir { 251 return self.add(newInstr(OP_sl).rx(rx).pd(pd).iv(disp)) 252 } 253 254 func (self *Builder) SQ(rx GenericRegister, pd PointerRegister, disp int64) *Ir { 255 return self.add(newInstr(OP_sq).rx(rx).pd(pd).iv(disp)) 256 } 257 258 func (self *Builder) SP(ps PointerRegister, pd PointerRegister, disp int64) *Ir { 259 return self.add(newInstr(OP_sp).ps(ps).pd(pd).iv(disp)) 260 } 261 262 func (self *Builder) MOV(rx GenericRegister, ry GenericRegister) *Ir { 263 return self.ADD(rx, Rz, ry) 264 } 265 266 func (self *Builder) MOVP(ps PointerRegister, pd PointerRegister) *Ir { 267 return self.ADDP(ps, Rz, pd) 268 } 269 270 func (self *Builder) LDAQ(id int, rx GenericRegister) *Ir { 271 return self.add(newInstr(OP_ldaq).iv(int64(id)).rx(rx)) 272 } 273 274 func (self *Builder) LDAP(id int, pd PointerRegister) *Ir { 275 return self.add(newInstr(OP_ldap).iv(int64(id)).pd(pd)) 276 } 277 278 func (self *Builder) ADDP(ps PointerRegister, rx GenericRegister, pd PointerRegister) *Ir { 279 return self.add(newInstr(OP_addp).ps(ps).rx(rx).pd(pd)) 280 } 281 282 func (self *Builder) SUBP(ps PointerRegister, rx GenericRegister, pd PointerRegister) *Ir { 283 return self.add(newInstr(OP_subp).ps(ps).rx(rx).pd(pd)) 284 } 285 286 func (self *Builder) ADDPI(ps PointerRegister, im int64, pd PointerRegister) *Ir { 287 return self.add(newInstr(OP_addpi).ps(ps).iv(im).pd(pd)) 288 } 289 290 func (self *Builder) SUBPI(ps PointerRegister, im int64, pd PointerRegister) *Ir { 291 return self.ADDPI(ps, -im, pd) 292 } 293 294 func (self *Builder) ADD(rx GenericRegister, ry GenericRegister, rz GenericRegister) *Ir { 295 return self.add(newInstr(OP_add).rx(rx).ry(ry).rz(rz)) 296 } 297 298 func (self *Builder) SUB(rx GenericRegister, ry GenericRegister, rz GenericRegister) *Ir { 299 return self.add(newInstr(OP_sub).rx(rx).ry(ry).rz(rz)) 300 } 301 302 func (self *Builder) BTS(rx GenericRegister, ry GenericRegister, rz GenericRegister) *Ir { 303 return self.add(newInstr(OP_bts).rx(rx).ry(ry).rz(rz)) 304 } 305 306 func (self *Builder) ADDI(rx GenericRegister, im int64, ry GenericRegister) *Ir { 307 return self.add(newInstr(OP_addi).rx(rx).iv(im).ry(ry)) 308 } 309 310 func (self *Builder) SUBI(rx GenericRegister, im int64, ry GenericRegister) *Ir { 311 return self.ADDI(rx, -im, ry) 312 } 313 314 func (self *Builder) MULI(rx GenericRegister, im int64, ry GenericRegister) *Ir { 315 return self.add(newInstr(OP_muli).rx(rx).iv(im).ry(ry)) 316 } 317 318 func (self *Builder) ANDI(rx GenericRegister, im int64, ry GenericRegister) *Ir { 319 return self.add(newInstr(OP_andi).rx(rx).iv(im).ry(ry)) 320 } 321 322 func (self *Builder) XORI(rx GenericRegister, im int64, ry GenericRegister) *Ir { 323 return self.add(newInstr(OP_xori).rx(rx).iv(im).ry(ry)) 324 } 325 326 func (self *Builder) SHRI(rx GenericRegister, im int64, ry GenericRegister) *Ir { 327 return self.add(newInstr(OP_shri).rx(rx).iv(im).ry(ry)) 328 } 329 330 func (self *Builder) BSI(rx GenericRegister, im int64, ry GenericRegister) *Ir { 331 return self.add(newInstr(OP_bsi).rx(rx).iv(im).ry(ry)) 332 } 333 334 func (self *Builder) SWAPW(rx GenericRegister, ry GenericRegister) *Ir { 335 return self.add(newInstr(OP_swapw).rx(rx).ry(ry)) 336 } 337 338 func (self *Builder) SWAPL(rx GenericRegister, ry GenericRegister) *Ir { 339 return self.add(newInstr(OP_swapl).rx(rx).ry(ry)) 340 } 341 342 func (self *Builder) SWAPQ(rx GenericRegister, ry GenericRegister) *Ir { 343 return self.add(newInstr(OP_swapq).rx(rx).ry(ry)) 344 } 345 346 func (self *Builder) SXLQ(rx GenericRegister, ry GenericRegister) *Ir { 347 return self.add(newInstr(OP_sxlq).rx(rx).ry(ry)) 348 } 349 350 func (self *Builder) BEQ(rx GenericRegister, ry GenericRegister, to string) *Ir { 351 return self.jmp(newInstr(OP_beq).rx(rx).ry(ry), to) 352 } 353 354 func (self *Builder) BNE(rx GenericRegister, ry GenericRegister, to string) *Ir { 355 return self.jmp(newInstr(OP_bne).rx(rx).ry(ry), to) 356 } 357 358 func (self *Builder) BLT(rx GenericRegister, ry GenericRegister, to string) *Ir { 359 return self.jmp(newInstr(OP_blt).rx(rx).ry(ry), to) 360 } 361 362 func (self *Builder) BLTU(rx GenericRegister, ry GenericRegister, to string) *Ir { 363 return self.jmp(newInstr(OP_bltu).rx(rx).ry(ry), to) 364 } 365 366 func (self *Builder) BGEU(rx GenericRegister, ry GenericRegister, to string) *Ir { 367 return self.jmp(newInstr(OP_bgeu).rx(rx).ry(ry), to) 368 } 369 370 func (self *Builder) BSW(rx GenericRegister, sw []string) *Ir { 371 return self.tab(newInstr(OP_bsw).rx(rx), sw) 372 } 373 374 func (self *Builder) BEQP(ps PointerRegister, pd PointerRegister, to string) *Ir { 375 return self.jmp(newInstr(OP_beqp).ps(ps).pd(pd), to) 376 } 377 378 func (self *Builder) BNEP(ps PointerRegister, pd PointerRegister, to string) *Ir { 379 return self.jmp(newInstr(OP_bnep).ps(ps).pd(pd), to) 380 } 381 382 func (self *Builder) JMP(to string) *Ir { 383 return self.jmp(newInstr(OP_jmp), to) 384 } 385 386 func (self *Builder) BZERO(nb int64, pd PointerRegister) *Ir { 387 return self.add(newInstr(OP_bzero).iv(nb).pd(pd)) 388 } 389 390 func (self *Builder) BCOPY(ps PointerRegister, rx GenericRegister, pd PointerRegister) *Ir { 391 return self.add(newInstr(OP_bcopy).ps(ps).rx(rx).pd(pd)) 392 } 393 394 func (self *Builder) CCALL(fn *CallHandle) *Ir { 395 return self.add(newInstr(OP_ccall).iv(int64(fn.Id))) 396 } 397 398 func (self *Builder) GCALL(fn *CallHandle) *Ir { 399 return self.add(newInstr(OP_gcall).iv(int64(fn.Id))) 400 } 401 402 func (self *Builder) ICALL(vt PointerRegister, vp PointerRegister, mt *CallHandle) *Ir { 403 return self.add(newInstr(OP_icall).ps(vt).pd(vp).iv(int64(mt.Id))) 404 } 405 406 func (self *Builder) RET() *Ir { 407 return self.add(newInstr(OP_ret)) 408 } 409 410 func (self *Builder) BREAK() *Ir { 411 return self.add(newInstr(OP_break)) 412 }