github.com/goplus/llgo@v0.8.3/ssa/expr.go (about) 1 /* 2 * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. 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 ssa 18 19 import ( 20 "bytes" 21 "fmt" 22 "go/constant" 23 "go/token" 24 "go/types" 25 "log" 26 27 "github.com/goplus/llgo/internal/abi" 28 "github.com/goplus/llvm" 29 ) 30 31 // ----------------------------------------------------------------------------- 32 33 type Expr struct { 34 impl llvm.Value 35 Type 36 } 37 38 var Nil Expr // Zero value is a nil Expr 39 40 // IsNil checks if the expression is nil or not. 41 func (v Expr) IsNil() bool { 42 return v.Type == nil 43 } 44 45 // Do evaluates the delay expression and returns the result. 46 func (v Expr) Do(b Builder) Expr { 47 switch vt := v.Type; vt.kind { 48 case vkPhisExpr: 49 e := vt.raw.Type.(*phisExprTy) 50 return b.aggregateValue(e.Type, e.phis...) 51 } 52 return v 53 } 54 55 // ----------------------------------------------------------------------------- 56 57 type pyVarTy struct { 58 mod Expr 59 name string 60 } 61 62 func (p pyVarTy) Underlying() types.Type { 63 panic("don't call") 64 } 65 66 func (p pyVarTy) String() string { 67 return "pyVar" 68 } 69 70 func pyVarExpr(mod Expr, name string) Expr { 71 tvar := &aType{raw: rawType{&pyVarTy{mod, name}}, kind: vkPyVarRef} 72 return Expr{Type: tvar} 73 } 74 75 // ----------------------------------------------------------------------------- 76 77 type phisExprTy struct { 78 phis []llvm.Value 79 Type 80 } 81 82 func (p phisExprTy) Underlying() types.Type { 83 panic("don't call") 84 } 85 86 func (p phisExprTy) String() string { 87 return "phisExpr" 88 } 89 90 func phisExpr(t Type, phis []llvm.Value) Expr { 91 tphi := &aType{raw: rawType{&phisExprTy{phis, t}}, kind: vkPhisExpr} 92 return Expr{Type: tphi} 93 } 94 95 // ----------------------------------------------------------------------------- 96 97 // Null returns a null constant expression. 98 func (p Program) Null(t Type) Expr { 99 return Expr{llvm.ConstNull(t.ll), t} 100 } 101 102 // PyNull returns a null *PyObject constant expression. 103 func (p Program) PyNull() Expr { 104 return p.Null(p.PyObjectPtr()) 105 } 106 107 // BoolVal returns a boolean constant expression. 108 func (p Program) BoolVal(v bool) Expr { 109 t := p.Bool() 110 var bv uint64 111 if v { 112 bv = 1 113 } 114 ret := llvm.ConstInt(t.ll, bv, v) 115 return Expr{ret, t} 116 } 117 118 // IntVal returns an integer constant expression. 119 func (p Program) IntVal(v uint64, t Type) Expr { 120 ret := llvm.ConstInt(t.ll, v, false) 121 return Expr{ret, t} 122 } 123 124 func (p Program) FloatVal(v float64, t Type) Expr { 125 ret := llvm.ConstFloat(t.ll, v) 126 return Expr{ret, t} 127 } 128 129 // Val returns a constant expression. 130 func (p Program) Val(v interface{}) Expr { 131 switch v := v.(type) { 132 case int: 133 return p.IntVal(uint64(v), p.Int()) 134 case uintptr: 135 return p.IntVal(uint64(v), p.Uintptr()) 136 case bool: 137 return p.BoolVal(v) 138 case float64: 139 t := p.Float64() 140 ret := llvm.ConstFloat(t.ll, v) 141 return Expr{ret, t} 142 } 143 panic("todo") 144 } 145 146 // Const returns a constant expression. 147 func (b Builder) Const(v constant.Value, typ Type) Expr { 148 prog := b.Prog 149 if v == nil { 150 return prog.Null(typ) 151 } 152 raw := typ.raw.Type 153 switch t := raw.(type) { 154 case *types.Basic: 155 kind := t.Kind() 156 switch { 157 case kind == types.Bool: 158 return prog.BoolVal(constant.BoolVal(v)) 159 case kind >= types.Int && kind <= types.Int64: 160 if v, exact := constant.Int64Val(v); exact { 161 return prog.IntVal(uint64(v), typ) 162 } 163 case kind >= types.Uint && kind <= types.Uintptr: 164 if v, exact := constant.Uint64Val(v); exact { 165 return prog.IntVal(v, typ) 166 } 167 case kind == types.Float32 || kind == types.Float64: 168 if v, exact := constant.Float64Val(v); exact { 169 return prog.FloatVal(v, typ) 170 } 171 case kind == types.String: 172 return b.Str(constant.StringVal(v)) 173 } 174 } 175 panic(fmt.Sprintf("unsupported Const: %v, %v", v, raw)) 176 } 177 178 // SizeOf returns the size of a type. 179 func (b Builder) SizeOf(t Type, n ...int64) Expr { 180 prog := b.Prog 181 size := prog.SizeOf(t, n...) 182 return prog.IntVal(size, prog.Uintptr()) 183 } 184 185 // CStr returns a c-style string constant expression. 186 func (b Builder) CStr(v string) Expr { 187 return Expr{llvm.CreateGlobalStringPtr(b.impl, v), b.Prog.CStr()} 188 } 189 190 // Str returns a Go string constant expression. 191 func (b Builder) Str(v string) (ret Expr) { 192 prog := b.Prog 193 cstr := b.CStr(v) 194 ret = b.InlineCall(b.Func.Pkg.rtFunc("NewString"), cstr, prog.Val(len(v))) 195 ret.Type = prog.String() 196 return 197 } 198 199 // ----------------------------------------------------------------------------- 200 201 const ( 202 mathOpBase = token.ADD 203 mathOpLast = token.REM 204 ) 205 206 var mathOpToLLVM = []llvm.Opcode{ 207 int(token.ADD-mathOpBase)<<2 | vkSigned: llvm.Add, 208 int(token.ADD-mathOpBase)<<2 | vkUnsigned: llvm.Add, 209 int(token.ADD-mathOpBase)<<2 | vkFloat: llvm.FAdd, 210 211 int(token.SUB-mathOpBase)<<2 | vkSigned: llvm.Sub, 212 int(token.SUB-mathOpBase)<<2 | vkUnsigned: llvm.Sub, 213 int(token.SUB-mathOpBase)<<2 | vkFloat: llvm.FSub, 214 215 int(token.MUL-mathOpBase)<<2 | vkSigned: llvm.Mul, 216 int(token.MUL-mathOpBase)<<2 | vkUnsigned: llvm.Mul, 217 int(token.MUL-mathOpBase)<<2 | vkFloat: llvm.FMul, 218 219 int(token.QUO-mathOpBase)<<2 | vkSigned: llvm.SDiv, 220 int(token.QUO-mathOpBase)<<2 | vkUnsigned: llvm.UDiv, 221 int(token.QUO-mathOpBase)<<2 | vkFloat: llvm.FDiv, 222 223 int(token.REM-mathOpBase)<<2 | vkSigned: llvm.SRem, 224 int(token.REM-mathOpBase)<<2 | vkUnsigned: llvm.URem, 225 int(token.REM-mathOpBase)<<2 | vkFloat: llvm.FRem, 226 } 227 228 func mathOpIdx(op token.Token, x valueKind) int { 229 return int(op-mathOpBase)<<2 | x 230 } 231 232 // ADD SUB MUL QUO REM + - * / % 233 func isMathOp(op token.Token) bool { 234 return op >= mathOpBase && op <= mathOpLast 235 } 236 237 const ( 238 logicOpBase = token.AND 239 logicOpLast = token.AND_NOT 240 ) 241 242 var logicOpToLLVM = []llvm.Opcode{ 243 token.AND - logicOpBase: llvm.And, 244 token.OR - logicOpBase: llvm.Or, 245 token.XOR - logicOpBase: llvm.Xor, 246 token.SHL - logicOpBase: llvm.Shl, 247 token.SHR - logicOpBase: llvm.AShr, // Arithmetic Shift Right 248 } 249 250 // AND OR XOR SHL SHR AND_NOT & | ^ << >> &^ 251 func isLogicOp(op token.Token) bool { 252 return op >= logicOpBase && op <= logicOpLast 253 } 254 255 const ( 256 predOpBase = token.EQL 257 predOpLast = token.GEQ 258 ) 259 260 var intPredOpToLLVM = []llvm.IntPredicate{ 261 token.EQL - predOpBase: llvm.IntEQ, 262 token.NEQ - predOpBase: llvm.IntNE, 263 token.LSS - predOpBase: llvm.IntSLT, 264 token.LEQ - predOpBase: llvm.IntSLE, 265 token.GTR - predOpBase: llvm.IntSGT, 266 token.GEQ - predOpBase: llvm.IntSGE, 267 } 268 269 var uintPredOpToLLVM = []llvm.IntPredicate{ 270 token.EQL - predOpBase: llvm.IntEQ, 271 token.NEQ - predOpBase: llvm.IntNE, 272 token.LSS - predOpBase: llvm.IntULT, 273 token.LEQ - predOpBase: llvm.IntULE, 274 token.GTR - predOpBase: llvm.IntUGT, 275 token.GEQ - predOpBase: llvm.IntUGE, 276 } 277 278 var floatPredOpToLLVM = []llvm.FloatPredicate{ 279 token.EQL - predOpBase: llvm.FloatOEQ, 280 token.NEQ - predOpBase: llvm.FloatONE, 281 token.LSS - predOpBase: llvm.FloatOLT, 282 token.LEQ - predOpBase: llvm.FloatOLE, 283 token.GTR - predOpBase: llvm.FloatOGT, 284 token.GEQ - predOpBase: llvm.FloatOGE, 285 } 286 287 var boolPredOpToLLVM = []llvm.IntPredicate{ 288 token.EQL - predOpBase: llvm.IntEQ, 289 token.NEQ - predOpBase: llvm.IntNE, 290 } 291 292 // EQL NEQ LSS LEQ GTR GEQ == != < <= < >= 293 func isPredOp(op token.Token) bool { 294 return op >= predOpBase && op <= predOpLast 295 } 296 297 // The BinOp instruction yields the result of binary operation (x op y). 298 // op can be: 299 // ADD SUB MUL QUO REM + - * / % 300 // AND OR XOR SHL SHR AND_NOT & | ^ << >> &^ 301 // EQL NEQ LSS LEQ GTR GEQ == != < <= < >= 302 func (b Builder) BinOp(op token.Token, x, y Expr) Expr { 303 if debugInstr { 304 log.Printf("BinOp %d, %v, %v\n", op, x.impl, y.impl) 305 } 306 switch { 307 case isMathOp(op): // op: + - * / % 308 kind := x.kind 309 switch kind { 310 case vkString: 311 if op == token.ADD { 312 pkg := b.Func.Pkg 313 return Expr{b.InlineCall(pkg.rtFunc("StringCat"), x, y).impl, x.Type} 314 } 315 case vkComplex: 316 default: 317 idx := mathOpIdx(op, kind) 318 if llop := mathOpToLLVM[idx]; llop != 0 { 319 return Expr{llvm.CreateBinOp(b.impl, llop, x.impl, y.impl), x.Type} 320 } 321 } 322 case isLogicOp(op): // op: & | ^ << >> &^ 323 switch op { 324 case token.AND_NOT: 325 return Expr{b.impl.CreateAnd(x.impl, b.impl.CreateNot(y.impl, ""), ""), x.Type} 326 case token.SHL, token.SHR: 327 if needsNegativeCheck(y) { 328 check := Expr{b.impl.CreateICmp(llvm.IntSLT, y.impl, llvm.ConstInt(y.ll, 0, false), ""), b.Prog.Bool()} 329 b.InlineCall(b.Func.Pkg.rtFunc("AssertNegativeShift"), check) 330 } 331 xsize, ysize := b.Prog.SizeOf(x.Type), b.Prog.SizeOf(y.Type) 332 if xsize != ysize { 333 y = b.Convert(x.Type, y) 334 } 335 overflows := b.impl.CreateICmp(llvm.IntUGE, y.impl, llvm.ConstInt(y.ll, xsize*8, false), "") 336 xzero := llvm.ConstInt(x.ll, 0, false) 337 if op == token.SHL { 338 rhs := b.impl.CreateShl(x.impl, y.impl, "") 339 return Expr{b.impl.CreateSelect(overflows, xzero, rhs, ""), x.Type} 340 } else { 341 if x.kind == vkSigned { 342 rhs := b.impl.CreateSelect(overflows, llvm.ConstInt(y.ll, 8*xsize-1, false), y.impl, "") 343 return Expr{b.impl.CreateAShr(x.impl, rhs, ""), x.Type} 344 } else { 345 rsh := b.impl.CreateLShr(x.impl, y.impl, "") 346 return Expr{b.impl.CreateSelect(overflows, xzero, rsh, ""), x.Type} 347 } 348 } 349 default: 350 llop := logicOpToLLVM[op-logicOpBase] 351 return Expr{llvm.CreateBinOp(b.impl, llop, x.impl, y.impl), x.Type} 352 } 353 case isPredOp(op): // op: == != < <= < >= 354 tret := b.Prog.Bool() 355 kind := x.kind 356 switch kind { 357 case vkSigned: 358 pred := intPredOpToLLVM[op-predOpBase] 359 return Expr{llvm.CreateICmp(b.impl, pred, x.impl, y.impl), tret} 360 case vkUnsigned, vkPtr: 361 pred := uintPredOpToLLVM[op-predOpBase] 362 return Expr{llvm.CreateICmp(b.impl, pred, x.impl, y.impl), tret} 363 case vkFloat: 364 pred := floatPredOpToLLVM[op-predOpBase] 365 return Expr{llvm.CreateFCmp(b.impl, pred, x.impl, y.impl), tret} 366 case vkBool: 367 pred := boolPredOpToLLVM[op-predOpBase] 368 return Expr{llvm.CreateICmp(b.impl, pred, x.impl, y.impl), tret} 369 case vkString, vkComplex: 370 panic("todo") 371 } 372 } 373 panic("todo") 374 } 375 376 // The UnOp instruction yields the result of (op x). 377 // ARROW is channel receive. 378 // MUL is pointer indirection (load). 379 // XOR is bitwise complement. 380 // SUB is negation. 381 // NOT is logical negation. 382 func (b Builder) UnOp(op token.Token, x Expr) (ret Expr) { 383 if debugInstr { 384 log.Printf("UnOp %v, %v\n", op, x.impl) 385 } 386 switch op { 387 case token.MUL: 388 return b.Load(x) 389 case token.SUB: 390 switch t := x.Type.raw.Underlying().(type) { 391 case *types.Basic: 392 ret.Type = x.Type 393 if t.Info()&types.IsInteger != 0 { 394 ret.impl = b.impl.CreateNeg(x.impl, "") 395 } else if t.Info()&types.IsFloat != 0 { 396 ret.impl = b.impl.CreateFNeg(x.impl, "") 397 } else { 398 panic("todo") 399 } 400 default: 401 panic("unreachable") 402 } 403 case token.NOT: 404 ret.Type = x.Type 405 ret.impl = b.impl.CreateNot(x.impl, "") 406 case token.XOR: 407 ret.Type = x.Type 408 ret.impl = b.impl.CreateXor(x.impl, llvm.ConstInt(x.Type.ll, ^uint64(0), false), "") 409 case token.ARROW: 410 panic("todo") 411 } 412 return 413 } 414 415 // ----------------------------------------------------------------------------- 416 417 func checkExpr(v Expr, t types.Type, b Builder) Expr { 418 if t, ok := t.(*types.Struct); ok && isClosure(t) { 419 if v.kind != vkClosure { 420 return b.Func.Pkg.closureStub(b, t, v) 421 } 422 } 423 return v 424 } 425 426 func llvmParamsEx(data Expr, vals []Expr, params *types.Tuple, b Builder) (ret []llvm.Value) { 427 if data.IsNil() { 428 return llvmParams(0, vals, params, b) 429 } 430 ret = llvmParams(1, vals, params, b) 431 ret[0] = data.impl 432 return 433 } 434 435 func llvmParams(base int, vals []Expr, params *types.Tuple, b Builder) (ret []llvm.Value) { 436 n := params.Len() 437 if n > 0 { 438 ret = make([]llvm.Value, len(vals)+base) 439 for idx, v := range vals { 440 i := base + idx 441 if i < n { 442 v = checkExpr(v, params.At(i).Type(), b) 443 } 444 ret[i] = v.impl 445 } 446 } 447 return 448 } 449 450 func llvmFields(vals []Expr, t *types.Struct, b Builder) (ret []llvm.Value) { 451 n := t.NumFields() 452 if n > 0 { 453 ret = make([]llvm.Value, len(vals)) 454 for i, v := range vals { 455 if i < n { 456 v = checkExpr(v, t.Field(i).Type(), b) 457 } 458 ret[i] = v.impl 459 } 460 } 461 return 462 } 463 464 func llvmDelayValues(f func(i int) Expr, n int) []llvm.Value { 465 ret := make([]llvm.Value, n) 466 for i := 0; i < n; i++ { 467 ret[i] = f(i).impl 468 } 469 return ret 470 } 471 472 func llvmBlocks(bblks []BasicBlock) []llvm.BasicBlock { 473 ret := make([]llvm.BasicBlock, len(bblks)) 474 for i, v := range bblks { 475 ret[i] = v.impl 476 } 477 return ret 478 } 479 480 // Phi represents a phi node. 481 type Phi struct { 482 Expr 483 } 484 485 // AddIncoming adds incoming values to a phi node. 486 func (p Phi) AddIncoming(b Builder, bblks []BasicBlock, f func(i int) Expr) { 487 bs := llvmBlocks(bblks) 488 if p.kind != vkPhisExpr { // normal phi node 489 vs := llvmDelayValues(f, len(bblks)) 490 p.impl.AddIncoming(vs, bs) 491 return 492 } 493 e := p.raw.Type.(*phisExprTy) 494 phis := e.phis 495 vals := make([][]llvm.Value, len(phis)) 496 for iblk, blk := range bblks { 497 last := blk.impl.LastInstruction() 498 b.impl.SetInsertPointBefore(last) 499 impl := b.impl 500 val := f(iblk).impl 501 for i := range phis { 502 if iblk == 0 { 503 vals[i] = make([]llvm.Value, len(bblks)) 504 } 505 vals[i][iblk] = llvm.CreateExtractValue(impl, val, i) 506 } 507 } 508 for i, phi := range phis { 509 phi.AddIncoming(vals[i], bs) 510 } 511 } 512 513 // Phi returns a phi node. 514 func (b Builder) Phi(t Type) Phi { 515 impl := b.impl 516 switch tund := t.raw.Type.Underlying().(type) { 517 case *types.Basic: 518 kind := tund.Kind() 519 switch kind { 520 case types.String: 521 prog := b.Prog 522 phis := make([]llvm.Value, 2) 523 phis[0] = llvm.CreatePHI(impl, prog.tyVoidPtr()) 524 phis[1] = llvm.CreatePHI(impl, prog.tyInt()) 525 return Phi{phisExpr(t, phis)} 526 } 527 case *types.Struct: 528 panic("todo") 529 } 530 phi := llvm.CreatePHI(impl, t.ll) 531 return Phi{Expr{phi, t}} 532 } 533 534 // ----------------------------------------------------------------------------- 535 536 // Advance returns the pointer ptr advanced by offset. 537 func (b Builder) Advance(ptr Expr, offset Expr) Expr { 538 if debugInstr { 539 log.Printf("Advance %v, %v\n", ptr.impl, offset.impl) 540 } 541 var elem llvm.Type 542 var prog = b.Prog 543 switch t := ptr.raw.Type.(type) { 544 case *types.Basic: // void 545 elem = prog.tyInt8() 546 default: 547 elem = prog.rawType(t.(*types.Pointer).Elem()).ll 548 } 549 ret := llvm.CreateGEP(b.impl, elem, ptr.impl, []llvm.Value{offset.impl}) 550 return Expr{ret, ptr.Type} 551 } 552 553 // Load returns the value at the pointer ptr. 554 func (b Builder) Load(ptr Expr) Expr { 555 if debugInstr { 556 log.Printf("Load %v\n", ptr.impl) 557 } 558 if ptr.kind == vkPyVarRef { 559 return b.pyLoad(ptr) 560 } 561 telem := b.Prog.Elem(ptr.Type) 562 return Expr{llvm.CreateLoad(b.impl, telem.ll, ptr.impl), telem} 563 } 564 565 // Store stores val at the pointer ptr. 566 func (b Builder) Store(ptr, val Expr) Builder { 567 raw := ptr.raw.Type 568 if debugInstr { 569 log.Printf("Store %v, %v, %v\n", raw, ptr.impl, val.impl) 570 } 571 val = checkExpr(val, raw.(*types.Pointer).Elem(), b) 572 b.impl.CreateStore(val.impl, ptr.impl) 573 return b 574 } 575 576 func (b Builder) aggregateAlloc(t Type, flds ...llvm.Value) llvm.Value { 577 prog := b.Prog 578 pkg := b.Func.Pkg 579 size := prog.SizeOf(t) 580 ptr := b.InlineCall(pkg.rtFunc("AllocU"), prog.IntVal(size, prog.Uintptr())).impl 581 tll := t.ll 582 impl := b.impl 583 for i, fld := range flds { 584 impl.CreateStore(fld, llvm.CreateStructGEP(impl, tll, ptr, i)) 585 } 586 return ptr 587 } 588 589 // aggregateValue yields the value of the aggregate X with the fields 590 func (b Builder) aggregateValue(t Type, flds ...llvm.Value) Expr { 591 tll := t.ll 592 impl := b.impl 593 ptr := llvm.CreateAlloca(impl, tll) 594 for i, fld := range flds { 595 impl.CreateStore(fld, llvm.CreateStructGEP(impl, tll, ptr, i)) 596 } 597 return Expr{llvm.CreateLoad(b.impl, tll, ptr), t} 598 } 599 600 // The MakeClosure instruction yields a closure value whose code is 601 // Fn and whose free variables' values are supplied by Bindings. 602 // 603 // Type() returns a (possibly named) *types.Signature. 604 // 605 // Example printed form: 606 // 607 // t0 = make closure anon@1.2 [x y z] 608 // t1 = make closure bound$(main.I).add [i] 609 func (b Builder) MakeClosure(fn Expr, bindings []Expr) Expr { 610 if debugInstr { 611 log.Printf("MakeClosure %v, %v\n", fn, bindings) 612 } 613 prog := b.Prog 614 tfn := fn.Type 615 sig := tfn.raw.Type.(*types.Signature) 616 tctx := sig.Params().At(0).Type().Underlying().(*types.Pointer).Elem().(*types.Struct) 617 flds := llvmFields(bindings, tctx, b) 618 data := b.aggregateAlloc(prog.rawType(tctx), flds...) 619 return b.aggregateValue(prog.Closure(tfn), fn.impl, data) 620 } 621 622 // The FieldAddr instruction yields the address of Field of *struct X. 623 // 624 // The field is identified by its index within the field list of the 625 // struct type of X. 626 // 627 // Dynamically, this instruction panics if X evaluates to a nil 628 // pointer. 629 // 630 // Type() returns a (possibly named) *types.Pointer. 631 // 632 // Example printed form: 633 // 634 // t1 = &t0.name [#1] 635 func (b Builder) FieldAddr(x Expr, idx int) Expr { 636 if debugInstr { 637 log.Printf("FieldAddr %v, %d\n", x.impl, idx) 638 } 639 prog := b.Prog 640 tstruc := prog.Elem(x.Type) 641 telem := prog.Field(tstruc, idx) 642 pt := prog.Pointer(telem) 643 return Expr{llvm.CreateStructGEP(b.impl, tstruc.ll, x.impl, idx), pt} 644 } 645 646 // The Field instruction yields the value of Field of struct X. 647 func (b Builder) Field(x Expr, idx int) Expr { 648 if debugInstr { 649 log.Printf("Field %v, %d\n", x.impl, idx) 650 } 651 return b.getField(x, idx) 652 } 653 654 func (b Builder) getField(x Expr, idx int) Expr { 655 tfld := b.Prog.Field(x.Type, idx) 656 fld := llvm.CreateExtractValue(b.impl, x.impl, idx) 657 return Expr{fld, tfld} 658 } 659 660 // StringData returns the data pointer of a string. 661 func (b Builder) StringData(x Expr) Expr { 662 if debugInstr { 663 log.Printf("StringData %v\n", x.impl) 664 } 665 prog := b.Prog 666 ptr := llvm.CreateExtractValue(b.impl, x.impl, 0) 667 return Expr{ptr, prog.CStr()} 668 } 669 670 // StringLen returns the length of a string. 671 func (b Builder) StringLen(x Expr) Expr { 672 if debugInstr { 673 log.Printf("StringLen %v\n", x.impl) 674 } 675 prog := b.Prog 676 ptr := llvm.CreateExtractValue(b.impl, x.impl, 1) 677 return Expr{ptr, prog.Int()} 678 } 679 680 // SliceData returns the data pointer of a slice. 681 func (b Builder) SliceData(x Expr) Expr { 682 if debugInstr { 683 log.Printf("SliceData %v\n", x.impl) 684 } 685 prog := b.Prog 686 ptr := llvm.CreateExtractValue(b.impl, x.impl, 0) 687 return Expr{ptr, prog.CStr()} 688 } 689 690 // SliceLen returns the length of a slice. 691 func (b Builder) SliceLen(x Expr) Expr { 692 if debugInstr { 693 log.Printf("SliceLen %v\n", x.impl) 694 } 695 prog := b.Prog 696 ptr := llvm.CreateExtractValue(b.impl, x.impl, 1) 697 return Expr{ptr, prog.Int()} 698 } 699 700 // SliceCap returns the length of a slice cap. 701 func (b Builder) SliceCap(x Expr) Expr { 702 if debugInstr { 703 log.Printf("SliceCap %v\n", x.impl) 704 } 705 prog := b.Prog 706 ptr := llvm.CreateExtractValue(b.impl, x.impl, 2) 707 return Expr{ptr, prog.Int()} 708 } 709 710 // The IndexAddr instruction yields the address of the element at 711 // index `idx` of collection `x`. `idx` is an integer expression. 712 // 713 // The elements of maps and strings are not addressable; use Lookup (map), 714 // Index (string), or MapUpdate instead. 715 // 716 // Dynamically, this instruction panics if `x` evaluates to a nil *array 717 // pointer. 718 // 719 // Example printed form: 720 // 721 // t2 = &t0[t1] 722 func (b Builder) IndexAddr(x, idx Expr) Expr { 723 if debugInstr { 724 log.Printf("IndexAddr %v, %v\n", x.impl, idx.impl) 725 } 726 idx = b.checkIndex(idx) 727 prog := b.Prog 728 telem := prog.Index(x.Type) 729 pt := prog.Pointer(telem) 730 switch x.raw.Type.Underlying().(type) { 731 case *types.Slice: 732 ptr := b.SliceData(x) 733 indices := []llvm.Value{idx.impl} 734 return Expr{llvm.CreateInBoundsGEP(b.impl, telem.ll, ptr.impl, indices), pt} 735 } 736 // case *types.Pointer: 737 indices := []llvm.Value{idx.impl} 738 return Expr{llvm.CreateInBoundsGEP(b.impl, telem.ll, x.impl, indices), pt} 739 } 740 741 func needsNegativeCheck(x Expr) bool { 742 if x.kind == vkSigned { 743 if rv := x.impl.IsAConstantInt(); !rv.IsNil() && rv.SExtValue() >= 0 { 744 return false 745 } 746 return true 747 } 748 return false 749 } 750 751 // check index >= 0 and size to uint 752 func (b Builder) checkIndex(idx Expr) Expr { 753 if needsNegativeCheck(idx) { 754 check := Expr{b.impl.CreateICmp(llvm.IntSLT, idx.impl, llvm.ConstInt(idx.ll, 0, false), ""), b.Prog.Bool()} 755 b.InlineCall(b.Func.Pkg.rtFunc("AssertIndexRange"), check) 756 } 757 typ := b.Prog.Uint() 758 if b.Prog.SizeOf(idx.Type) < b.Prog.SizeOf(typ) { 759 idx.Type = typ 760 idx.impl = castUintptr(b, idx.impl, typ) 761 } 762 return idx 763 } 764 765 // The Index instruction yields element Index of collection X, an array, 766 // string or type parameter containing an array, a string, a pointer to an, 767 // array or a slice. 768 // 769 // Example printed form: 770 // 771 // t2 = t0[t1] 772 func (b Builder) Index(x, idx Expr, addr func(Expr) Expr) Expr { 773 if debugInstr { 774 log.Printf("Index %v, %v\n", x.impl, idx.impl) 775 } 776 prog := b.Prog 777 var telem Type 778 var ptr Expr 779 switch t := x.raw.Type.Underlying().(type) { 780 case *types.Basic: 781 if t.Kind() != types.String { 782 panic(fmt.Errorf("invalid operation: cannot index %v", t)) 783 } 784 telem = prog.rawType(types.Typ[types.Byte]) 785 ptr = b.StringData(x) 786 case *types.Array: 787 telem = prog.Index(x.Type) 788 if addr != nil { 789 ptr = addr(x) 790 } else { 791 size := b.SizeOf(telem, t.Len()) 792 ptr = b.Alloca(size) 793 b.Store(ptr, x) 794 } 795 } 796 idx = b.checkIndex(idx) 797 pt := prog.Pointer(telem) 798 indices := []llvm.Value{idx.impl} 799 buf := Expr{llvm.CreateInBoundsGEP(b.impl, telem.ll, ptr.impl, indices), pt} 800 return b.Load(buf) 801 } 802 803 // The Lookup instruction yields element Index of collection map X. 804 // Index is the appropriate key type. 805 // 806 // If CommaOk, the result is a 2-tuple of the value above and a 807 // boolean indicating the result of a map membership test for the key. 808 // The components of the tuple are accessed using Extract. 809 // 810 // Example printed form: 811 // 812 // t2 = t0[t1] 813 // t5 = t3[t4],ok 814 func (b Builder) Lookup(x, key Expr, commaOk bool) (ret Expr) { 815 if debugInstr { 816 log.Printf("Lookup %v, %v, %v\n", x.impl, key.impl, commaOk) 817 } 818 // TODO(xsw) 819 // panic("todo") 820 return 821 } 822 823 // The Slice instruction yields a slice of an existing string, slice 824 // or *array X between optional integer bounds Low and High. 825 // 826 // Dynamically, this instruction panics if X evaluates to a nil *array 827 // pointer. 828 // 829 // Type() returns string if the type of X was string, otherwise a 830 // *types.Slice with the same element type as X. 831 // 832 // Example printed form: 833 // 834 // t1 = slice t0[1:] 835 func (b Builder) Slice(x, low, high, max Expr) (ret Expr) { 836 if debugInstr { 837 log.Printf("Slice %v, %v, %v\n", x.impl, low.impl, high.impl) 838 } 839 prog := b.Prog 840 pkg := b.Func.Pkg 841 var nCap Expr 842 var nEltSize Expr 843 var base Expr 844 if low.IsNil() { 845 low = prog.IntVal(0, prog.Int()) 846 } 847 switch t := x.raw.Type.Underlying().(type) { 848 case *types.Basic: 849 if t.Kind() != types.String { 850 panic(fmt.Errorf("invalid operation: cannot slice %v", t)) 851 } 852 if high.IsNil() { 853 high = b.StringLen(x) 854 } 855 ret.Type = x.Type 856 ret.impl = b.InlineCall(pkg.rtFunc("NewStringSlice"), x, low, high).impl 857 return 858 case *types.Slice: 859 nEltSize = b.SizeOf(prog.Index(x.Type)) 860 nCap = b.SliceCap(x) 861 if high.IsNil() { 862 high = b.SliceCap(x) 863 } 864 ret.Type = x.Type 865 base = b.SliceData(x) 866 case *types.Pointer: 867 telem := t.Elem() 868 switch te := telem.Underlying().(type) { 869 case *types.Array: 870 elem := prog.rawType(te.Elem()) 871 ret.Type = prog.Slice(elem) 872 nEltSize = b.SizeOf(elem) 873 nCap = prog.IntVal(uint64(te.Len()), prog.Int()) 874 if high.IsNil() { 875 high = nCap 876 } 877 base = x 878 } 879 } 880 if max.IsNil() { 881 max = nCap 882 } 883 ret.impl = b.InlineCall(pkg.rtFunc("NewSlice3"), base, nEltSize, nCap, low, high, max).impl 884 return 885 } 886 887 // ----------------------------------------------------------------------------- 888 889 // The MakeMap instruction creates a new hash-table-based map object 890 // and yields a value of kind map. 891 // 892 // t is a (possibly named) *types.Map. 893 // 894 // Example printed form: 895 // 896 // t1 = make map[string]int t0 897 // t1 = make StringIntMap t0 898 func (b Builder) MakeMap(t Type, nReserve Expr) (ret Expr) { 899 if debugInstr { 900 log.Printf("MakeMap %v, %v\n", t.RawType(), nReserve.impl) 901 } 902 pkg := b.Func.Pkg 903 ret.Type = t 904 ret.impl = b.InlineCall(pkg.rtFunc("MakeSmallMap")).impl 905 // TODO(xsw): nReserve 906 return 907 } 908 909 // The MakeSlice instruction yields a slice of length Len backed by a 910 // newly allocated array of length Cap. 911 // 912 // Both Len and Cap must be non-nil Values of integer type. 913 // 914 // (Alloc(types.Array) followed by Slice will not suffice because 915 // Alloc can only create arrays of constant length.) 916 // 917 // Type() returns a (possibly named) *types.Slice. 918 // 919 // Example printed form: 920 // 921 // t1 = make []string 1:int t0 922 // t1 = make StringSlice 1:int t0 923 func (b Builder) MakeSlice(t Type, len, cap Expr) (ret Expr) { 924 if debugInstr { 925 log.Printf("MakeSlice %v, %v, %v\n", t.RawType(), len.impl, cap.impl) 926 } 927 pkg := b.Func.Pkg 928 if cap.IsNil() { 929 cap = len 930 } 931 elemSize := b.SizeOf(b.Prog.Index(t)) 932 size := b.BinOp(token.MUL, cap, elemSize) 933 ptr := b.InlineCall(pkg.rtFunc("AllocZ"), size) 934 ret.impl = b.InlineCall(pkg.rtFunc("NewSlice"), ptr, len, cap).impl 935 ret.Type = t 936 return 937 } 938 939 // ----------------------------------------------------------------------------- 940 941 // The Alloc instruction reserves space for a variable of the given type, 942 // zero-initializes it, and yields its address. 943 // 944 // If heap is false, Alloc zero-initializes the same local variable in 945 // the call frame and returns its address; in this case the Alloc must 946 // be present in Function.Locals. We call this a "local" alloc. 947 // 948 // If heap is true, Alloc allocates a new zero-initialized variable 949 // each time the instruction is executed. We call this a "new" alloc. 950 // 951 // When Alloc is applied to a channel, map or slice type, it returns 952 // the address of an uninitialized (nil) reference of that kind; store 953 // the result of MakeSlice, MakeMap or MakeChan in that location to 954 // instantiate these types. 955 // 956 // Example printed form: 957 // 958 // t0 = local int 959 // t1 = new int 960 func (b Builder) Alloc(elem Type, heap bool) (ret Expr) { 961 if debugInstr { 962 log.Printf("Alloc %v, %v\n", elem.RawType(), heap) 963 } 964 prog := b.Prog 965 pkg := b.Func.Pkg 966 size := b.SizeOf(elem) 967 if heap { 968 ret = b.InlineCall(pkg.rtFunc("AllocZ"), size) 969 } else { 970 ret = Expr{llvm.CreateAlloca(b.impl, elem.ll), prog.VoidPtr()} 971 ret.impl = b.InlineCall(pkg.rtFunc("Zeroinit"), ret, size).impl 972 } 973 ret.Type = prog.Pointer(elem) 974 return 975 } 976 977 // Alloca allocates space for n bytes. 978 func (b Builder) Alloca(n Expr) (ret Expr) { 979 if debugInstr { 980 log.Printf("Alloca %v\n", n.impl) 981 } 982 prog := b.Prog 983 telem := prog.tyInt8() 984 ret.impl = llvm.CreateArrayAlloca(b.impl, telem, n.impl) 985 ret.Type = prog.VoidPtr() 986 return 987 } 988 989 /* 990 // ArrayAlloca reserves space for an array of n elements of type telem. 991 func (b Builder) ArrayAlloca(telem Type, n Expr) (ret Expr) { 992 if debugInstr { 993 log.Printf("ArrayAlloca %v, %v\n", telem.t, n.impl) 994 } 995 ret.impl = llvm.CreateArrayAlloca(b.impl, telem.ll, n.impl) 996 ret.Type = b.Prog.Pointer(telem) 997 return 998 } 999 */ 1000 1001 // AllocaCStr allocates space for copy it from a Go string. 1002 func (b Builder) AllocaCStr(gostr Expr) (ret Expr) { 1003 if debugInstr { 1004 log.Printf("AllocaCStr %v\n", gostr.impl) 1005 } 1006 pkg := b.Func.Pkg 1007 n := b.StringLen(gostr) 1008 n1 := b.BinOp(token.ADD, n, b.Prog.Val(1)) 1009 cstr := b.Alloca(n1) 1010 return b.InlineCall(pkg.rtFunc("CStrCopy"), cstr, gostr) 1011 } 1012 1013 // ----------------------------------------------------------------------------- 1014 1015 // The ChangeType instruction applies to X a value-preserving type 1016 // change to Type(). 1017 // 1018 // Type changes are permitted: 1019 // - between a named type and its underlying type. 1020 // - between two named types of the same underlying type. 1021 // - between (possibly named) pointers to identical base types. 1022 // - from a bidirectional channel to a read- or write-channel, 1023 // optionally adding/removing a name. 1024 // - between a type (t) and an instance of the type (tσ), i.e. 1025 // Type() == σ(X.Type()) (or X.Type()== σ(Type())) where 1026 // σ is the type substitution of Parent().TypeParams by 1027 // Parent().TypeArgs. 1028 // 1029 // This operation cannot fail dynamically. 1030 // 1031 // Type changes may to be to or from a type parameter (or both). All 1032 // types in the type set of X.Type() have a value-preserving type 1033 // change to all types in the type set of Type(). 1034 // 1035 // Example printed form: 1036 // 1037 // t1 = changetype *int <- IntPtr (t0) 1038 func (b Builder) ChangeType(t Type, x Expr) (ret Expr) { 1039 if debugInstr { 1040 log.Printf("ChangeType %v, %v\n", t.RawType(), x.impl) 1041 } 1042 typ := t.raw.Type 1043 switch typ.(type) { 1044 default: 1045 // TODO(xsw): remove instr name 1046 ret.impl = b.impl.CreateBitCast(x.impl, t.ll, "bitCast") 1047 ret.Type = b.Prog.rawType(typ) 1048 return 1049 } 1050 } 1051 1052 // The Convert instruction yields the conversion of value X to type 1053 // Type(). One or both of those types is basic (but possibly named). 1054 // 1055 // A conversion may change the value and representation of its operand. 1056 // Conversions are permitted: 1057 // - between real numeric types. 1058 // - between complex numeric types. 1059 // - between string and []byte or []rune. 1060 // - between pointers and unsafe.Pointer. 1061 // - between unsafe.Pointer and uintptr. 1062 // - from (Unicode) integer to (UTF-8) string. 1063 // 1064 // A conversion may imply a type name change also. 1065 // 1066 // Conversions may to be to or from a type parameter. All types in 1067 // the type set of X.Type() can be converted to all types in the type 1068 // set of Type(). 1069 // 1070 // This operation cannot fail dynamically. 1071 // 1072 // Conversions of untyped string/number/bool constants to a specific 1073 // representation are eliminated during SSA construction. 1074 // 1075 // Example printed form: 1076 // 1077 // t1 = convert []byte <- string (t0) 1078 func (b Builder) Convert(t Type, x Expr) (ret Expr) { 1079 if debugInstr { 1080 log.Printf("Convert %v <- %v\n", t.RawType(), x.RawType()) 1081 } 1082 typ := t.raw.Type 1083 ret.Type = b.Prog.rawType(typ) 1084 switch typ := typ.Underlying().(type) { 1085 case *types.Basic: 1086 switch typ.Kind() { 1087 case types.Uintptr: 1088 ret.impl = castUintptr(b, x.impl, t) 1089 return 1090 case types.UnsafePointer: 1091 ret.impl = castPtr(b.impl, x.impl, t.ll) 1092 return 1093 } 1094 switch xtyp := x.RawType().Underlying().(type) { 1095 case *types.Basic: 1096 if typ.Info()&types.IsInteger != 0 { 1097 // int <- int/float 1098 if xtyp.Info()&types.IsInteger != 0 { 1099 ret.impl = castInt(b, x.impl, t) 1100 return 1101 } else if xtyp.Info()&types.IsFloat != 0 { 1102 if typ.Info()&types.IsUnsigned != 0 { 1103 ret.impl = b.impl.CreateFPToUI(x.impl, t.ll, "") 1104 } else { 1105 ret.impl = b.impl.CreateFPToSI(x.impl, t.ll, "") 1106 } 1107 return 1108 } 1109 } else if typ.Info()&types.IsFloat != 0 { 1110 // float <- int/float 1111 if xtyp.Info()&types.IsInteger != 0 { 1112 if xtyp.Info()&types.IsUnsigned != 0 { 1113 ret.impl = b.impl.CreateUIToFP(x.impl, t.ll, "") 1114 } else { 1115 ret.impl = b.impl.CreateSIToFP(x.impl, t.ll, "") 1116 } 1117 return 1118 } else if xtyp.Info()&types.IsFloat != 0 { 1119 ret.impl = castFloat(b, x.impl, t) 1120 return 1121 } 1122 } 1123 } 1124 case *types.Pointer: 1125 ret.impl = castPtr(b.impl, x.impl, t.ll) 1126 return 1127 } 1128 panic("todo") 1129 } 1130 1131 func castUintptr(b Builder, x llvm.Value, typ Type) llvm.Value { 1132 if x.Type().TypeKind() == llvm.PointerTypeKind { 1133 return llvm.CreatePtrToInt(b.impl, x, typ.ll) 1134 } 1135 return castInt(b, x, typ) 1136 } 1137 1138 func castInt(b Builder, x llvm.Value, typ Type) llvm.Value { 1139 xsize := b.Prog.td.TypeAllocSize(x.Type()) 1140 size := b.Prog.td.TypeAllocSize(typ.ll) 1141 if xsize > size { 1142 return b.impl.CreateTrunc(x, typ.ll, "") 1143 } else if typ.kind == vkUnsigned { 1144 return b.impl.CreateZExt(x, typ.ll, "") 1145 } else { 1146 return b.impl.CreateSExt(x, typ.ll, "") 1147 } 1148 } 1149 1150 func castFloat(b Builder, x llvm.Value, typ Type) llvm.Value { 1151 xsize := b.Prog.td.TypeAllocSize(x.Type()) 1152 size := b.Prog.td.TypeAllocSize(typ.ll) 1153 if xsize > size { 1154 return b.impl.CreateFPTrunc(x, typ.ll, "") 1155 } else { 1156 return b.impl.CreateFPExt(x, typ.ll, "") 1157 } 1158 } 1159 1160 func castPtr(b llvm.Builder, x llvm.Value, t llvm.Type) llvm.Value { 1161 if x.Type().TypeKind() == llvm.PointerTypeKind { 1162 return llvm.CreatePointerCast(b, x, t) 1163 } 1164 return llvm.CreateIntToPtr(b, x, t) 1165 } 1166 1167 // MakeInterface constructs an instance of an interface type from a 1168 // value of a concrete type. 1169 // 1170 // Use Program.MethodSets.MethodSet(X.Type()) to find the method-set 1171 // of X, and Program.MethodValue(m) to find the implementation of a method. 1172 // 1173 // To construct the zero value of an interface type T, use: 1174 // 1175 // NewConst(constant.MakeNil(), T, pos) 1176 // 1177 // Example printed form: 1178 // 1179 // t1 = make interface{} <- int (42:int) 1180 // t2 = make Stringer <- t0 1181 func (b Builder) MakeInterface(tinter Type, x Expr) (ret Expr) { 1182 raw := tinter.raw.Type 1183 if debugInstr { 1184 log.Printf("MakeInterface %v, %v\n", raw, x.impl) 1185 } 1186 prog := b.Prog 1187 pkg := b.Func.Pkg 1188 switch tx := x.raw.Type.Underlying().(type) { 1189 case *types.Basic: 1190 kind := tx.Kind() 1191 switch { 1192 case kind >= types.Bool && kind <= types.Uintptr: 1193 t := b.InlineCall(pkg.rtFunc("Basic"), prog.Val(int(kind))) 1194 tptr := prog.Uintptr() 1195 vptr := Expr{llvm.CreateIntCast(b.impl, x.impl, tptr.ll), tptr} 1196 return Expr{b.InlineCall(pkg.rtFunc("MakeAnyInt"), t, vptr).impl, tinter} 1197 case kind == types.Float32: 1198 t := b.InlineCall(pkg.rtFunc("Basic"), prog.Val(int(kind))) 1199 tptr := prog.Uintptr() 1200 i32 := b.impl.CreateBitCast(x.impl, prog.tyInt32(), "") 1201 vptr := Expr{llvm.CreateIntCast(b.impl, i32, tptr.ll), tptr} 1202 return Expr{b.InlineCall(pkg.rtFunc("MakeAnyInt"), t, vptr).impl, tinter} 1203 case kind == types.Float64: 1204 t := b.InlineCall(pkg.rtFunc("Basic"), prog.Val(int(kind))) 1205 tptr := prog.Uintptr() 1206 vptr := Expr{b.impl.CreateBitCast(x.impl, tptr.ll, ""), tptr} 1207 return Expr{b.InlineCall(pkg.rtFunc("MakeAnyInt"), t, vptr).impl, tinter} 1208 case kind == types.String: 1209 return Expr{b.InlineCall(pkg.rtFunc("MakeAnyString"), x).impl, tinter} 1210 } 1211 } 1212 panic("todo") 1213 } 1214 1215 // The TypeAssert instruction tests whether interface value X has type 1216 // AssertedType. 1217 // 1218 // If !CommaOk, on success it returns v, the result of the conversion 1219 // (defined below); on failure it panics. 1220 // 1221 // If CommaOk: on success it returns a pair (v, true) where v is the 1222 // result of the conversion; on failure it returns (z, false) where z 1223 // is AssertedType's zero value. The components of the pair must be 1224 // accessed using the Extract instruction. 1225 // 1226 // If Underlying: tests whether interface value X has the underlying 1227 // type AssertedType. 1228 // 1229 // If AssertedType is a concrete type, TypeAssert checks whether the 1230 // dynamic type in interface X is equal to it, and if so, the result 1231 // of the conversion is a copy of the value in the interface. 1232 // 1233 // If AssertedType is an interface, TypeAssert checks whether the 1234 // dynamic type of the interface is assignable to it, and if so, the 1235 // result of the conversion is a copy of the interface value X. 1236 // If AssertedType is a superinterface of X.Type(), the operation will 1237 // fail iff the operand is nil. (Contrast with ChangeInterface, which 1238 // performs no nil-check.) 1239 // 1240 // Type() reflects the actual type of the result, possibly a 1241 // 2-types.Tuple; AssertedType is the asserted type. 1242 // 1243 // Depending on the TypeAssert's purpose, Pos may return: 1244 // - the ast.CallExpr.Lparen of an explicit T(e) conversion; 1245 // - the ast.TypeAssertExpr.Lparen of an explicit e.(T) operation; 1246 // - the ast.CaseClause.Case of a case of a type-switch statement; 1247 // - the Ident(m).NamePos of an interface method value i.m 1248 // (for which TypeAssert may be used to effect the nil check). 1249 // 1250 // Example printed form: 1251 // 1252 // t1 = typeassert t0.(int) 1253 // t3 = typeassert,ok t2.(T) 1254 func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) (ret Expr) { 1255 if debugInstr { 1256 log.Printf("TypeAssert %v, %v, %v\n", x.impl, assertedTyp.raw.Type, commaOk) 1257 } 1258 switch assertedTyp.kind { 1259 case vkSigned, vkUnsigned, vkFloat, vkBool: 1260 pkg := b.Func.Pkg 1261 fnName := "I2Int" 1262 if commaOk { 1263 fnName = "CheckI2Int" 1264 } 1265 fn := pkg.rtFunc(fnName) 1266 var kind types.BasicKind 1267 switch t := assertedTyp.raw.Type.(type) { 1268 case *types.Basic: 1269 kind = t.Kind() 1270 default: 1271 panic("todo") 1272 } 1273 typ := b.InlineCall(pkg.rtFunc("Basic"), b.Prog.Val(int(kind))) 1274 ret = b.InlineCall(fn, x, typ) 1275 if kind != types.Uintptr { 1276 conv := func(v llvm.Value) llvm.Value { 1277 switch kind { 1278 case types.Float32: 1279 v = castInt(b, v, b.Prog.Int32()) 1280 v = b.impl.CreateBitCast(v, assertedTyp.ll, "") 1281 case types.Float64: 1282 v = b.impl.CreateBitCast(v, assertedTyp.ll, "") 1283 default: 1284 v = castInt(b, v, assertedTyp) 1285 } 1286 return v 1287 } 1288 if !commaOk { 1289 ret.Type = assertedTyp 1290 ret.impl = conv(ret.impl) 1291 } else { 1292 ret.Type = b.Prog.toTuple( 1293 types.NewTuple( 1294 types.NewVar(token.NoPos, nil, "", assertedTyp.RawType()), 1295 ret.Type.RawType().(*types.Tuple).At(1), 1296 ), 1297 ) 1298 val0 := conv(b.impl.CreateExtractValue(ret.impl, 0, "")) 1299 val1 := b.impl.CreateExtractValue(ret.impl, 1, "") 1300 ret.impl = llvm.ConstStruct([]llvm.Value{val0, val1}, false) 1301 } 1302 } 1303 return 1304 case vkString: 1305 pkg := b.Func.Pkg 1306 fnName := "I2String" 1307 if commaOk { 1308 fnName = "CheckI2String" 1309 } 1310 fn := pkg.rtFunc(fnName) 1311 typ := b.InlineCall(pkg.rtFunc("Basic"), b.Prog.Val(int(abi.String))) 1312 return b.InlineCall(fn, x, typ) 1313 } 1314 panic("todo") 1315 } 1316 1317 // ----------------------------------------------------------------------------- 1318 1319 // TODO(xsw): make inline call 1320 func (b Builder) InlineCall(fn Expr, args ...Expr) (ret Expr) { 1321 return b.Call(fn, args...) 1322 } 1323 1324 // The Call instruction represents a function or method call. 1325 // 1326 // The Call instruction yields the function result if there is exactly 1327 // one. Otherwise it returns a tuple, the components of which are 1328 // accessed via Extract. 1329 // 1330 // Example printed form: 1331 // 1332 // t2 = println(t0, t1) 1333 // t4 = t3() 1334 // t7 = invoke t5.Println(...t6) 1335 func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) { 1336 if debugInstr { 1337 var b bytes.Buffer 1338 name := fn.impl.Name() 1339 if name == "" { 1340 name = "closure" 1341 } 1342 fmt.Fprint(&b, "Call ", fn.kind, " ", fn.raw.Type, " ", name) 1343 sep := ": " 1344 for _, arg := range args { 1345 fmt.Fprint(&b, sep, arg.impl) 1346 sep = ", " 1347 } 1348 log.Println(b.String()) 1349 } 1350 var kind = fn.kind 1351 if kind == vkPyFuncRef { 1352 return b.pyCall(fn, args) 1353 } 1354 var ll llvm.Type 1355 var data Expr 1356 var sig *types.Signature 1357 var prog = b.Prog 1358 var raw = fn.raw.Type 1359 switch kind { 1360 case vkClosure: 1361 data = b.Field(fn, 1) 1362 fn = b.Field(fn, 0) 1363 raw = fn.raw.Type 1364 fallthrough 1365 case vkFuncPtr: 1366 sig = raw.(*types.Signature) 1367 ll = prog.FuncDecl(sig, InC).ll 1368 case vkFuncDecl: 1369 sig = raw.(*types.Signature) 1370 ll = fn.ll 1371 default: 1372 panic("unreachable") 1373 } 1374 ret.Type = prog.retType(sig) 1375 ret.impl = llvm.CreateCall(b.impl, ll, fn.impl, llvmParamsEx(data, args, sig.Params(), b)) 1376 return 1377 } 1378 1379 // The Extract instruction yields component Index of Tuple. 1380 // 1381 // This is used to access the results of instructions with multiple 1382 // return values, such as Call, TypeAssert, Next, UnOp(ARROW) and 1383 // IndexExpr(Map). 1384 // 1385 // Example printed form: 1386 // 1387 // t1 = extract t0 #1 1388 func (b Builder) Extract(x Expr, index int) (ret Expr) { 1389 ret.Type = b.Prog.toType(x.Type.raw.Type.(*types.Tuple).At(index).Type()) 1390 ret.impl = b.impl.CreateExtractValue(x.impl, index, "") 1391 return 1392 } 1393 1394 // A Builtin represents a specific use of a built-in function, e.g. len. 1395 // 1396 // Builtins are immutable values. Builtins do not have addresses. 1397 // 1398 // `fn` indicates the function: one of the built-in functions from the 1399 // Go spec (excluding "make" and "new"). 1400 func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) { 1401 switch fn { 1402 case "len": 1403 if len(args) == 1 { 1404 arg := args[0] 1405 switch arg.kind { 1406 case vkSlice: 1407 return b.SliceLen(arg) 1408 case vkString: 1409 return b.StringLen(arg) 1410 } 1411 } 1412 case "cap": 1413 if len(args) == 1 { 1414 arg := args[0] 1415 switch arg.kind { 1416 case vkSlice: 1417 return b.SliceCap(arg) 1418 } 1419 } 1420 case "append": 1421 if len(args) == 2 { 1422 src := args[0] 1423 if src.kind == vkSlice { 1424 elem := args[1] 1425 switch elem.kind { 1426 case vkSlice: 1427 etSize := b.Prog.SizeOf(b.Prog.Elem(elem.Type)) 1428 ret.Type = src.Type 1429 ret.impl = b.InlineCall(b.Func.Pkg.rtFunc("SliceAppend"), 1430 src, b.SliceData(elem), b.SliceLen(elem), b.Prog.Val(int(etSize))).impl 1431 return 1432 case vkString: 1433 etSize := b.Prog.SizeOf(b.Prog.Byte()) 1434 ret.Type = src.Type 1435 ret.impl = b.InlineCall(b.Func.Pkg.rtFunc("SliceAppend"), 1436 src, b.StringData(elem), b.StringLen(elem), b.Prog.Val(int(etSize))).impl 1437 return 1438 } 1439 } 1440 } 1441 case "print", "println": 1442 ln := fn == "println" 1443 ret.Type = b.Prog.Void() 1444 for i, arg := range args { 1445 if ln && i > 0 { 1446 b.InlineCall(b.Func.Pkg.rtFunc("PrintString"), b.Str(" ")) 1447 } 1448 var fn string 1449 var typ Type 1450 switch arg.kind { 1451 case vkBool: 1452 fn = "PrintBool" 1453 case vkSigned: 1454 fn = "PrintInt" 1455 typ = b.Prog.Int64() 1456 case vkUnsigned: 1457 fn = "PrintUint" 1458 typ = b.Prog.Uint64() 1459 case vkFloat: 1460 fn = "PrintFloat" 1461 typ = b.Prog.Float64() 1462 case vkSlice: 1463 fn = "PrintSlice" 1464 case vkPtr, vkFuncPtr, vkFuncDecl, vkClosure, vkPyVarRef, vkPyFuncRef: 1465 fn = "PrintPointer" 1466 typ = b.Prog.VoidPtr() 1467 case vkString: 1468 fn = "PrintString" 1469 case vkInterface: 1470 fn = "PrintIface" 1471 // case vkComplex: 1472 // fn = "PrintComplex" 1473 default: 1474 panic(fmt.Errorf("illegal types for operand: print %v", arg.RawType())) 1475 } 1476 if typ != nil && typ != arg.Type { 1477 arg = b.Convert(typ, arg) 1478 } 1479 b.InlineCall(b.Func.Pkg.rtFunc(fn), arg) 1480 } 1481 if ln { 1482 b.InlineCall(b.Func.Pkg.rtFunc("PrintString"), b.Str("\n")) 1483 } 1484 return 1485 } 1486 panic("todo") 1487 } 1488 1489 // -----------------------------------------------------------------------------