github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/irgen/ssa.go (about) 1 //===- ssa.go - IR generation from go/ssa ---------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the top-level LLVM IR generation from go/ssa form. 10 // 11 //===----------------------------------------------------------------------===// 12 13 package irgen 14 15 import ( 16 "fmt" 17 "go/ast" 18 "go/token" 19 "os" 20 "sort" 21 22 "llvm.org/llgo/ssaopt" 23 "llvm.org/llgo/third_party/gotools/go/ssa" 24 "llvm.org/llgo/third_party/gotools/go/ssa/ssautil" 25 "llvm.org/llgo/third_party/gotools/go/types" 26 "llvm.org/llvm/bindings/go/llvm" 27 ) 28 29 // A globalInit is used to temporarily store a global's initializer until 30 // we are ready to build it. 31 type globalInit struct { 32 val llvm.Value 33 elems []globalInit 34 } 35 36 func (gi *globalInit) update(typ llvm.Type, indices []uint32, val llvm.Value) { 37 if len(indices) == 0 { 38 gi.val = val 39 return 40 } 41 42 if gi.val.C != nil { 43 gi.val = llvm.ConstInsertValue(gi.val, val, indices) 44 } 45 46 tk := typ.TypeKind() 47 48 if len(gi.elems) == 0 { 49 switch tk { 50 case llvm.StructTypeKind: 51 gi.elems = make([]globalInit, typ.StructElementTypesCount()) 52 case llvm.ArrayTypeKind: 53 gi.elems = make([]globalInit, typ.ArrayLength()) 54 default: 55 panic("unexpected type") 56 } 57 } 58 59 var eltyp llvm.Type 60 switch tk { 61 case llvm.StructTypeKind: 62 eltyp = typ.StructElementTypes()[indices[0]] 63 case llvm.ArrayTypeKind: 64 eltyp = typ.ElementType() 65 default: 66 panic("unexpected type") 67 } 68 69 gi.elems[indices[0]].update(eltyp, indices[1:], val) 70 } 71 72 func (gi *globalInit) build(typ llvm.Type) llvm.Value { 73 if gi.val.C != nil { 74 return gi.val 75 } 76 if len(gi.elems) == 0 { 77 return llvm.ConstNull(typ) 78 } 79 80 switch typ.TypeKind() { 81 case llvm.StructTypeKind: 82 eltypes := typ.StructElementTypes() 83 elems := make([]llvm.Value, len(eltypes)) 84 for i, eltyp := range eltypes { 85 elems[i] = gi.elems[i].build(eltyp) 86 } 87 return llvm.ConstStruct(elems, false) 88 case llvm.ArrayTypeKind: 89 eltyp := typ.ElementType() 90 elems := make([]llvm.Value, len(gi.elems)) 91 for i := range gi.elems { 92 elems[i] = gi.elems[i].build(eltyp) 93 } 94 return llvm.ConstArray(eltyp, elems) 95 default: 96 panic("unexpected type") 97 } 98 } 99 100 type unit struct { 101 *compiler 102 pkg *ssa.Package 103 globals map[ssa.Value]llvm.Value 104 globalInits map[llvm.Value]*globalInit 105 106 // funcDescriptors maps *ssa.Functions to function descriptors, 107 // the first-class representation of functions. 108 funcDescriptors map[*ssa.Function]llvm.Value 109 110 // undefinedFuncs contains functions that have been resolved 111 // (declared) but not defined. 112 undefinedFuncs map[*ssa.Function]bool 113 114 gcRoots []llvm.Value 115 } 116 117 func newUnit(c *compiler, pkg *ssa.Package) *unit { 118 u := &unit{ 119 compiler: c, 120 pkg: pkg, 121 globals: make(map[ssa.Value]llvm.Value), 122 globalInits: make(map[llvm.Value]*globalInit), 123 funcDescriptors: make(map[*ssa.Function]llvm.Value), 124 undefinedFuncs: make(map[*ssa.Function]bool), 125 } 126 return u 127 } 128 129 type byMemberName []ssa.Member 130 131 func (ms byMemberName) Len() int { return len(ms) } 132 func (ms byMemberName) Swap(i, j int) { 133 ms[i], ms[j] = ms[j], ms[i] 134 } 135 func (ms byMemberName) Less(i, j int) bool { 136 return ms[i].Name() < ms[j].Name() 137 } 138 139 type byFunctionString []*ssa.Function 140 141 func (fns byFunctionString) Len() int { return len(fns) } 142 func (fns byFunctionString) Swap(i, j int) { 143 fns[i], fns[j] = fns[j], fns[i] 144 } 145 func (fns byFunctionString) Less(i, j int) bool { 146 return fns[i].String() < fns[j].String() 147 } 148 149 // Emit functions in order of their fully qualified names. This is so that a 150 // bootstrap build can be verified by comparing the stage2 and stage3 binaries. 151 func (u *unit) defineFunctionsInOrder(functions map[*ssa.Function]bool) { 152 fns := []*ssa.Function{} 153 for f, _ := range functions { 154 fns = append(fns, f) 155 } 156 sort.Sort(byFunctionString(fns)) 157 for _, f := range fns { 158 u.defineFunction(f) 159 } 160 } 161 162 // translatePackage translates an *ssa.Package into an LLVM module, and returns 163 // the translation unit information. 164 func (u *unit) translatePackage(pkg *ssa.Package) { 165 ms := make([]ssa.Member, len(pkg.Members)) 166 i := 0 167 for _, m := range pkg.Members { 168 ms[i] = m 169 i++ 170 } 171 172 sort.Sort(byMemberName(ms)) 173 174 // Initialize global storage and type descriptors for this package. 175 // We must create globals regardless of whether they're referenced, 176 // hence the duplication in frame.value. 177 for _, m := range ms { 178 switch v := m.(type) { 179 case *ssa.Global: 180 elemtyp := deref(v.Type()) 181 llelemtyp := u.llvmtypes.ToLLVM(elemtyp) 182 vname := u.types.mc.mangleGlobalName(v) 183 global := llvm.AddGlobal(u.module.Module, llelemtyp, vname) 184 if !v.Object().Exported() { 185 global.SetLinkage(llvm.InternalLinkage) 186 } 187 u.addGlobal(global, elemtyp) 188 global = llvm.ConstBitCast(global, u.llvmtypes.ToLLVM(v.Type())) 189 u.globals[v] = global 190 case *ssa.Type: 191 u.types.getTypeDescriptorPointer(v.Type()) 192 } 193 } 194 195 // Define functions. 196 u.defineFunctionsInOrder(ssautil.AllFunctions(pkg.Prog)) 197 198 // Emit initializers for type descriptors, which may trigger 199 // the resolution of additional functions. 200 u.types.emitTypeDescInitializers() 201 202 // Define remaining functions that were resolved during 203 // runtime type mapping, but not defined. 204 u.defineFunctionsInOrder(u.undefinedFuncs) 205 206 // Set initializers for globals. 207 for global, init := range u.globalInits { 208 initval := init.build(global.Type().ElementType()) 209 global.SetInitializer(initval) 210 } 211 } 212 213 func (u *unit) addGlobal(global llvm.Value, ty types.Type) { 214 u.globalInits[global] = new(globalInit) 215 216 if hasPointers(ty) { 217 global = llvm.ConstBitCast(global, llvm.PointerType(llvm.Int8Type(), 0)) 218 size := llvm.ConstInt(u.types.inttype, uint64(u.types.Sizeof(ty)), false) 219 root := llvm.ConstStruct([]llvm.Value{global, size}, false) 220 u.gcRoots = append(u.gcRoots, root) 221 } 222 } 223 224 // ResolveMethod implements MethodResolver.ResolveMethod. 225 func (u *unit) ResolveMethod(s *types.Selection) *govalue { 226 m := u.pkg.Prog.Method(s) 227 llfn := u.resolveFunctionGlobal(m) 228 llfn = llvm.ConstBitCast(llfn, llvm.PointerType(llvm.Int8Type(), 0)) 229 return newValue(llfn, m.Signature) 230 } 231 232 // resolveFunctionDescriptorGlobal returns a reference to the LLVM global 233 // storing the function's descriptor. 234 func (u *unit) resolveFunctionDescriptorGlobal(f *ssa.Function) llvm.Value { 235 llfd, ok := u.funcDescriptors[f] 236 if !ok { 237 name := u.types.mc.mangleFunctionName(f) + "$descriptor" 238 llfd = llvm.AddGlobal(u.module.Module, llvm.PointerType(llvm.Int8Type(), 0), name) 239 llfd.SetGlobalConstant(true) 240 u.funcDescriptors[f] = llfd 241 } 242 return llfd 243 } 244 245 // resolveFunctionDescriptor returns a function's 246 // first-class value representation. 247 func (u *unit) resolveFunctionDescriptor(f *ssa.Function) *govalue { 248 llfd := u.resolveFunctionDescriptorGlobal(f) 249 llfd = llvm.ConstBitCast(llfd, llvm.PointerType(llvm.Int8Type(), 0)) 250 return newValue(llfd, f.Signature) 251 } 252 253 // resolveFunctionGlobal returns an llvm.Value for a function global. 254 func (u *unit) resolveFunctionGlobal(f *ssa.Function) llvm.Value { 255 if v, ok := u.globals[f]; ok { 256 return v 257 } 258 name := u.types.mc.mangleFunctionName(f) 259 // It's possible that the function already exists in the module; 260 // for example, if it's a runtime intrinsic that the compiler 261 // has already referenced. 262 llvmFunction := u.module.Module.NamedFunction(name) 263 if llvmFunction.IsNil() { 264 fti := u.llvmtypes.getSignatureInfo(f.Signature) 265 llvmFunction = fti.declare(u.module.Module, name) 266 u.undefinedFuncs[f] = true 267 } 268 u.globals[f] = llvmFunction 269 return llvmFunction 270 } 271 272 func (u *unit) getFunctionLinkage(f *ssa.Function) llvm.Linkage { 273 switch { 274 case f.Pkg == nil: 275 // Synthetic functions outside packages may appear in multiple packages. 276 return llvm.LinkOnceODRLinkage 277 278 case f.Parent() != nil: 279 // Anonymous. 280 return llvm.InternalLinkage 281 282 case f.Signature.Recv() == nil && !ast.IsExported(f.Name()) && 283 !(f.Name() == "main" && f.Pkg.Object.Path() == "main") && 284 f.Name() != "init": 285 // Unexported methods may be referenced as part of an interface method 286 // table in another package. TODO(pcc): detect when this cannot happen. 287 return llvm.InternalLinkage 288 289 default: 290 return llvm.ExternalLinkage 291 } 292 } 293 294 func (u *unit) defineFunction(f *ssa.Function) { 295 // Only define functions from this package, or synthetic 296 // wrappers (which do not have a package). 297 if f.Pkg != nil && f.Pkg != u.pkg { 298 return 299 } 300 301 llfn := u.resolveFunctionGlobal(f) 302 linkage := u.getFunctionLinkage(f) 303 304 isMethod := f.Signature.Recv() != nil 305 306 // Methods cannot be referred to via a descriptor. 307 if !isMethod { 308 llfd := u.resolveFunctionDescriptorGlobal(f) 309 llfd.SetInitializer(llvm.ConstBitCast(llfn, llvm.PointerType(llvm.Int8Type(), 0))) 310 llfd.SetLinkage(linkage) 311 } 312 313 // We only need to emit a descriptor for functions without bodies. 314 if len(f.Blocks) == 0 { 315 return 316 } 317 318 ssaopt.LowerAllocsToStack(f) 319 320 if u.DumpSSA { 321 f.WriteTo(os.Stderr) 322 } 323 324 fr := newFrame(u, llfn) 325 defer fr.dispose() 326 fr.addCommonFunctionAttrs(fr.function) 327 fr.function.SetLinkage(linkage) 328 329 fr.logf("Define function: %s @ %s", f.String(), fr.pkg.Prog.Fset.Position(f.Pos())) 330 fti := u.llvmtypes.getSignatureInfo(f.Signature) 331 delete(u.undefinedFuncs, f) 332 fr.retInf = fti.retInf 333 334 // Push the compile unit and function onto the debug context. 335 if u.GenerateDebug { 336 u.debug.PushFunction(fr.function, f.Signature, f.Pos()) 337 defer u.debug.PopFunction() 338 u.debug.SetLocation(fr.builder, f.Pos()) 339 } 340 341 // If a function calls recover, we create a separate function to 342 // hold the real function, and this function calls __go_can_recover 343 // and bridges to it. 344 if callsRecover(f) { 345 fr = fr.bridgeRecoverFunc(fr.function, fti) 346 } 347 348 fr.blocks = make([]llvm.BasicBlock, len(f.Blocks)) 349 fr.lastBlocks = make([]llvm.BasicBlock, len(f.Blocks)) 350 for i, block := range f.Blocks { 351 fr.blocks[i] = llvm.AddBasicBlock(fr.function, fmt.Sprintf(".%d.%s", i, block.Comment)) 352 } 353 fr.builder.SetInsertPointAtEnd(fr.blocks[0]) 354 fr.transformSwitches(f) 355 356 prologueBlock := llvm.InsertBasicBlock(fr.blocks[0], "prologue") 357 fr.builder.SetInsertPointAtEnd(prologueBlock) 358 359 for i, param := range f.Params { 360 llparam := fti.argInfos[i].decode(llvm.GlobalContext(), fr.builder, fr.builder) 361 if isMethod && i == 0 { 362 if _, ok := param.Type().Underlying().(*types.Pointer); !ok { 363 llparam = fr.builder.CreateBitCast(llparam, llvm.PointerType(fr.types.ToLLVM(param.Type()), 0), "") 364 llparam = fr.builder.CreateLoad(llparam, "") 365 } 366 } 367 fr.env[param] = newValue(llparam, param.Type()) 368 } 369 370 // Load closure, extract free vars. 371 if len(f.FreeVars) > 0 { 372 for _, fv := range f.FreeVars { 373 fr.env[fv] = newValue(llvm.ConstNull(u.llvmtypes.ToLLVM(fv.Type())), fv.Type()) 374 } 375 elemTypes := make([]llvm.Type, len(f.FreeVars)+1) 376 elemTypes[0] = llvm.PointerType(llvm.Int8Type(), 0) // function pointer 377 for i, fv := range f.FreeVars { 378 elemTypes[i+1] = u.llvmtypes.ToLLVM(fv.Type()) 379 } 380 structType := llvm.StructType(elemTypes, false) 381 closure := fr.function.Param(fti.chainIndex) 382 closure = fr.builder.CreateBitCast(closure, llvm.PointerType(structType, 0), "") 383 for i, fv := range f.FreeVars { 384 ptr := fr.builder.CreateStructGEP(closure, i+1, "") 385 ptr = fr.builder.CreateLoad(ptr, "") 386 fr.env[fv] = newValue(ptr, fv.Type()) 387 } 388 } 389 390 // Allocate stack space for locals in the prologue block. 391 for _, local := range f.Locals { 392 typ := fr.llvmtypes.ToLLVM(deref(local.Type())) 393 alloca := fr.builder.CreateAlloca(typ, local.Comment) 394 fr.memsetZero(alloca, llvm.SizeOf(typ)) 395 bcalloca := fr.builder.CreateBitCast(alloca, llvm.PointerType(llvm.Int8Type(), 0), "") 396 value := newValue(bcalloca, local.Type()) 397 fr.env[local] = value 398 } 399 400 // If the function contains any defers, we must first create 401 // an unwind block. We can short-circuit the check for defers with 402 // f.Recover != nil. 403 if f.Recover != nil || hasDefer(f) { 404 fr.unwindBlock = llvm.AddBasicBlock(fr.function, "unwind") 405 fr.frameptr = fr.builder.CreateAlloca(llvm.Int8Type(), "") 406 } 407 408 // Keep track of the block into which we need to insert the call 409 // to __go_register_gc_roots. This needs to be inserted after the 410 // init guard check under the llgo ABI. 411 var registerGcBlock llvm.BasicBlock 412 413 // If this is the "init" function, emit the init guard check and 414 // enable init-specific optimizations. 415 if !isMethod && f.Name() == "init" { 416 registerGcBlock = fr.emitInitPrologue() 417 fr.isInit = true 418 } 419 420 fr.builder.CreateBr(fr.blocks[0]) 421 fr.allocaBuilder.SetInsertPointBefore(prologueBlock.FirstInstruction()) 422 423 for _, block := range f.DomPreorder() { 424 llblock := fr.blocks[block.Index] 425 if llblock.IsNil() { 426 continue 427 } 428 fr.translateBlock(block, llblock) 429 } 430 431 fr.fixupPhis() 432 433 if !fr.unwindBlock.IsNil() { 434 fr.setupUnwindBlock(f.Recover) 435 } 436 437 // The init function needs to register the GC roots first. We do this 438 // after generating code for it because allocations may have caused 439 // additional GC roots to be created. 440 if fr.isInit { 441 fr.builder.SetInsertPointBefore(registerGcBlock.FirstInstruction()) 442 fr.registerGcRoots() 443 } 444 } 445 446 type pendingPhi struct { 447 ssa *ssa.Phi 448 llvm llvm.Value 449 } 450 451 type frame struct { 452 *unit 453 function llvm.Value 454 builder, allocaBuilder llvm.Builder 455 retInf retInfo 456 blocks []llvm.BasicBlock 457 lastBlocks []llvm.BasicBlock 458 runtimeErrorBlocks [gccgoRuntimeErrorCount]llvm.BasicBlock 459 unwindBlock llvm.BasicBlock 460 frameptr llvm.Value 461 env map[ssa.Value]*govalue 462 ptr map[ssa.Value]llvm.Value 463 tuples map[ssa.Value][]*govalue 464 phis []pendingPhi 465 canRecover llvm.Value 466 isInit bool 467 } 468 469 func newFrame(u *unit, fn llvm.Value) *frame { 470 return &frame{ 471 unit: u, 472 function: fn, 473 builder: llvm.GlobalContext().NewBuilder(), 474 allocaBuilder: llvm.GlobalContext().NewBuilder(), 475 env: make(map[ssa.Value]*govalue), 476 ptr: make(map[ssa.Value]llvm.Value), 477 tuples: make(map[ssa.Value][]*govalue), 478 } 479 } 480 481 func (fr *frame) dispose() { 482 fr.builder.Dispose() 483 fr.allocaBuilder.Dispose() 484 } 485 486 // emitInitPrologue emits the init-specific function prologue (guard check and 487 // initialization of dependent packages under the llgo native ABI), and returns 488 // the basic block into which the GC registration call should be emitted. 489 func (fr *frame) emitInitPrologue() llvm.BasicBlock { 490 if fr.GccgoABI { 491 return fr.builder.GetInsertBlock() 492 } 493 494 initGuard := llvm.AddGlobal(fr.module.Module, llvm.Int1Type(), "init$guard") 495 initGuard.SetLinkage(llvm.InternalLinkage) 496 initGuard.SetInitializer(llvm.ConstNull(llvm.Int1Type())) 497 498 returnBlock := llvm.AddBasicBlock(fr.function, "") 499 initBlock := llvm.AddBasicBlock(fr.function, "") 500 501 initGuardVal := fr.builder.CreateLoad(initGuard, "") 502 fr.builder.CreateCondBr(initGuardVal, returnBlock, initBlock) 503 504 fr.builder.SetInsertPointAtEnd(returnBlock) 505 fr.builder.CreateRetVoid() 506 507 fr.builder.SetInsertPointAtEnd(initBlock) 508 fr.builder.CreateStore(llvm.ConstInt(llvm.Int1Type(), 1, false), initGuard) 509 int8ptr := llvm.PointerType(fr.types.ctx.Int8Type(), 0) 510 ftyp := llvm.FunctionType(llvm.VoidType(), []llvm.Type{int8ptr}, false) 511 for _, pkg := range fr.pkg.Object.Imports() { 512 initname := ManglePackagePath(pkg.Path()) + "..import" 513 initfn := fr.module.Module.NamedFunction(initname) 514 if initfn.IsNil() { 515 initfn = llvm.AddFunction(fr.module.Module, initname, ftyp) 516 } 517 args := []llvm.Value{llvm.Undef(int8ptr)} 518 fr.builder.CreateCall(initfn, args, "") 519 } 520 521 return initBlock 522 } 523 524 // bridgeRecoverFunc creates a function that may call recover(), and creates 525 // a call to it from the current frame. The created function will be called 526 // with a boolean parameter that indicates whether it may call recover(). 527 // 528 // The created function will have the same name as the current frame's function 529 // with "$recover" appended, having the same return types and parameters with 530 // an additional boolean parameter appended. 531 // 532 // A new frame will be returned for the newly created function. 533 func (fr *frame) bridgeRecoverFunc(llfn llvm.Value, fti functionTypeInfo) *frame { 534 // The bridging function must not be inlined, or the return address 535 // may not correspond to the source function. 536 attrKind := llvm.AttributeKindID("noinline") 537 noInlineAttr := fr.module.Context().CreateEnumAttribute(attrKind, 0) 538 llfn.AddFunctionAttr(noInlineAttr) 539 540 // Call __go_can_recover, passing in the function's return address. 541 entry := llvm.AddBasicBlock(llfn, "entry") 542 fr.builder.SetInsertPointAtEnd(entry) 543 canRecover := fr.runtime.canRecover.call(fr, fr.returnAddress(0))[0] 544 returnType := fti.functionType.ReturnType() 545 argTypes := fti.functionType.ParamTypes() 546 argTypes = append(argTypes, canRecover.Type()) 547 548 // Create and call the $recover function. 549 ftiRecover := fti 550 ftiRecover.functionType = llvm.FunctionType(returnType, argTypes, false) 551 llfnRecover := ftiRecover.declare(fr.module.Module, llfn.Name()+"$recover") 552 fr.addCommonFunctionAttrs(llfnRecover) 553 llfnRecover.SetLinkage(llvm.InternalLinkage) 554 args := make([]llvm.Value, len(argTypes)-1, len(argTypes)) 555 for i := range args { 556 args[i] = llfn.Param(i) 557 } 558 args = append(args, canRecover) 559 result := fr.builder.CreateCall(llfnRecover, args, "") 560 if returnType.TypeKind() == llvm.VoidTypeKind { 561 fr.builder.CreateRetVoid() 562 } else { 563 fr.builder.CreateRet(result) 564 } 565 566 // The $recover function must condition calls to __go_recover on 567 // the result of __go_can_recover passed in as an argument. 568 fr = newFrame(fr.unit, llfnRecover) 569 fr.retInf = ftiRecover.retInf 570 fr.canRecover = fr.function.Param(len(argTypes) - 1) 571 return fr 572 } 573 574 func (fr *frame) registerGcRoots() { 575 if len(fr.gcRoots) != 0 { 576 rootty := fr.gcRoots[0].Type() 577 roots := append(fr.gcRoots, llvm.ConstNull(rootty)) 578 rootsarr := llvm.ConstArray(rootty, roots) 579 rootsstruct := llvm.ConstStruct([]llvm.Value{llvm.ConstNull(llvm.PointerType(llvm.Int8Type(), 0)), rootsarr}, false) 580 581 rootsglobal := llvm.AddGlobal(fr.module.Module, rootsstruct.Type(), "") 582 rootsglobal.SetInitializer(rootsstruct) 583 rootsglobal.SetLinkage(llvm.InternalLinkage) 584 fr.runtime.registerGcRoots.callOnly(fr, llvm.ConstBitCast(rootsglobal, llvm.PointerType(llvm.Int8Type(), 0))) 585 } 586 } 587 588 func (fr *frame) fixupPhis() { 589 for _, phi := range fr.phis { 590 values := make([]llvm.Value, len(phi.ssa.Edges)) 591 blocks := make([]llvm.BasicBlock, len(phi.ssa.Edges)) 592 block := phi.ssa.Block() 593 for i, edge := range phi.ssa.Edges { 594 values[i] = fr.llvmvalue(edge) 595 blocks[i] = fr.lastBlock(block.Preds[i]) 596 } 597 phi.llvm.AddIncoming(values, blocks) 598 } 599 } 600 601 func (fr *frame) createLandingPad(cleanup bool) llvm.Value { 602 fr.function.SetPersonality(fr.runtime.gccgoPersonality) 603 lp := fr.builder.CreateLandingPad(fr.runtime.gccgoExceptionType, 0, "") 604 if cleanup { 605 lp.SetCleanup(true) 606 } else { 607 lp.AddClause(llvm.ConstNull(llvm.PointerType(llvm.Int8Type(), 0))) 608 } 609 return lp 610 } 611 612 // Runs defers. If a defer panics, check for recovers in later defers. 613 func (fr *frame) runDefers() { 614 loopbb := llvm.AddBasicBlock(fr.function, "") 615 fr.builder.CreateBr(loopbb) 616 617 retrylpad := llvm.AddBasicBlock(fr.function, "") 618 fr.builder.SetInsertPointAtEnd(retrylpad) 619 fr.createLandingPad(false) 620 fr.runtime.checkDefer.callOnly(fr, fr.frameptr) 621 fr.builder.CreateBr(loopbb) 622 623 fr.builder.SetInsertPointAtEnd(loopbb) 624 fr.runtime.undefer.invoke(fr, retrylpad, fr.frameptr) 625 } 626 627 func (fr *frame) setupUnwindBlock(rec *ssa.BasicBlock) { 628 var recoverbb llvm.BasicBlock 629 if rec != nil { 630 recoverbb = fr.blocks[rec.Index] 631 } else { 632 recoverbb = llvm.AddBasicBlock(fr.function, "recover") 633 fr.builder.SetInsertPointAtEnd(recoverbb) 634 fr.builder.CreateUnreachable() 635 } 636 637 checkunwindbb := llvm.AddBasicBlock(fr.function, "") 638 fr.builder.SetInsertPointAtEnd(checkunwindbb) 639 exc := fr.createLandingPad(true) 640 fr.runDefers() 641 642 frame := fr.builder.CreateLoad(fr.frameptr, "") 643 shouldresume := fr.builder.CreateIsNull(frame, "") 644 645 resumebb := llvm.AddBasicBlock(fr.function, "") 646 fr.builder.CreateCondBr(shouldresume, resumebb, recoverbb) 647 648 fr.builder.SetInsertPointAtEnd(resumebb) 649 fr.builder.CreateResume(exc) 650 651 fr.builder.SetInsertPointAtEnd(fr.unwindBlock) 652 fr.createLandingPad(false) 653 fr.runtime.checkDefer.invoke(fr, checkunwindbb, fr.frameptr) 654 fr.runDefers() 655 fr.builder.CreateBr(recoverbb) 656 } 657 658 func (fr *frame) translateBlock(b *ssa.BasicBlock, llb llvm.BasicBlock) { 659 fr.builder.SetInsertPointAtEnd(llb) 660 for _, instr := range b.Instrs { 661 fr.instruction(instr) 662 } 663 fr.lastBlocks[b.Index] = fr.builder.GetInsertBlock() 664 } 665 666 func (fr *frame) block(b *ssa.BasicBlock) llvm.BasicBlock { 667 return fr.blocks[b.Index] 668 } 669 670 func (fr *frame) lastBlock(b *ssa.BasicBlock) llvm.BasicBlock { 671 return fr.lastBlocks[b.Index] 672 } 673 674 func (fr *frame) value(v ssa.Value) (result *govalue) { 675 switch v := v.(type) { 676 case nil: 677 return nil 678 case *ssa.Function: 679 return fr.resolveFunctionDescriptor(v) 680 case *ssa.Const: 681 return fr.newValueFromConst(v.Value, v.Type()) 682 case *ssa.Global: 683 if g, ok := fr.globals[v]; ok { 684 return newValue(g, v.Type()) 685 } 686 // Create an external global. Globals for this package are defined 687 // on entry to translatePackage, and have initialisers. 688 llelemtyp := fr.llvmtypes.ToLLVM(deref(v.Type())) 689 vname := fr.types.mc.mangleGlobalName(v) 690 llglobal := llvm.AddGlobal(fr.module.Module, llelemtyp, vname) 691 llglobal = llvm.ConstBitCast(llglobal, fr.llvmtypes.ToLLVM(v.Type())) 692 fr.globals[v] = llglobal 693 return newValue(llglobal, v.Type()) 694 } 695 if value, ok := fr.env[v]; ok { 696 return value 697 } 698 699 panic(fmt.Errorf("Instruction %q not visited yet", v.Name())) 700 } 701 702 func (fr *frame) llvmvalue(v ssa.Value) llvm.Value { 703 if gv := fr.value(v); gv != nil { 704 return gv.value 705 } else { 706 return llvm.Value{nil} 707 } 708 } 709 710 func (fr *frame) isNonNull(v ssa.Value) bool { 711 switch v.(type) { 712 case 713 // Globals have a fixed (non-nil) address. 714 *ssa.Global, 715 // The language does not specify what happens if an allocation fails. 716 *ssa.Alloc, 717 // These have already been nil checked. 718 *ssa.FieldAddr, *ssa.IndexAddr: 719 return true 720 default: 721 return false 722 } 723 } 724 725 func (fr *frame) nilCheck(v ssa.Value, llptr llvm.Value) { 726 if !fr.isNonNull(v) { 727 ptrnull := fr.builder.CreateIsNull(llptr, "") 728 fr.condBrRuntimeError(ptrnull, gccgoRuntimeErrorNIL_DEREFERENCE) 729 } 730 } 731 732 func (fr *frame) canAvoidElementLoad(ptr ssa.Value) bool { 733 for _, ref := range *ptr.Referrers() { 734 switch ref := ref.(type) { 735 case *ssa.Field: 736 case *ssa.Index: 737 if ref.X != ptr { 738 return false 739 } 740 // ok 741 default: 742 return false 743 } 744 } 745 746 return true 747 } 748 749 // If this value is sufficiently large, look through referrers to see if we can 750 // avoid a load. 751 func (fr *frame) canAvoidLoad(instr *ssa.UnOp, op llvm.Value) bool { 752 if fr.types.Sizeof(instr.Type()) < 2*fr.types.Sizeof(types.Typ[types.Int]) { 753 // Don't bother with small values. 754 return false 755 } 756 757 // Keep track of whether our pointer may escape. We conservatively assume 758 // that MakeInterfaces will escape. 759 esc := false 760 761 // We only know how to avoid loads if they are used to create an interface 762 // or read an element of the structure. If we see any other referrer, abort. 763 for _, ref := range *instr.Referrers() { 764 switch ref := ref.(type) { 765 case *ssa.MakeInterface: 766 esc = true 767 case *ssa.Field: 768 case *ssa.Index: 769 if ref.X != instr { 770 // This should never happen, as indices are always of type int 771 // and we don't bother with values smaller than 2*sizeof(int). 772 panic("impossible") 773 } 774 // ok 775 default: 776 return false 777 } 778 } 779 780 var opcopy llvm.Value 781 if esc { 782 opcopy = fr.createTypeMalloc(instr.Type()) 783 } else { 784 opcopy = fr.allocaBuilder.CreateAlloca(fr.types.ToLLVM(instr.Type()), "") 785 } 786 fr.memcpy(opcopy, op, llvm.ConstInt(fr.types.inttype, uint64(fr.types.Sizeof(instr.Type())), false)) 787 788 fr.ptr[instr] = opcopy 789 return true 790 } 791 792 // Return true iff we think it might be beneficial to turn this alloc instruction 793 // into a statically allocated global. 794 // Precondition: we are compiling the init function. 795 func (fr *frame) shouldStaticallyAllocate(alloc *ssa.Alloc) bool { 796 // First, see if the allocated type is an array or struct, and if so determine 797 // the number of elements in the type. If the type is anything else, we 798 // statically allocate unconditionally. 799 var numElems int64 800 switch ty := deref(alloc.Type()).Underlying().(type) { 801 case *types.Array: 802 numElems = ty.Len() 803 case *types.Struct: 804 numElems = int64(ty.NumFields()) 805 default: 806 return true 807 } 808 809 // We treat the number of referrers to the alloc instruction as a rough 810 // proxy for the number of elements initialized. If the data structure 811 // is densely initialized (> 1/4 elements initialized), enable the 812 // optimization. 813 return int64(len(*alloc.Referrers()))*4 > numElems 814 } 815 816 // If val is a constant and addr refers to a global variable which is defined in 817 // this module or an element thereof, simulate the effect of storing val at addr 818 // in the global variable's initializer and return true, otherwise return false. 819 // Precondition: we are compiling the init function. 820 func (fr *frame) maybeStoreInInitializer(val, addr llvm.Value) bool { 821 if val.IsAConstant().IsNil() { 822 return false 823 } 824 825 if !addr.IsAConstantExpr().IsNil() && addr.OperandsCount() >= 2 && 826 // TODO(pcc): Explicitly check that this is a constant GEP. 827 // I don't think there are any other kinds of constantexpr which 828 // satisfy the conditions we test for here, so this is probably safe. 829 !addr.Operand(0).IsAGlobalVariable().IsNil() && 830 addr.Operand(1).IsNull() { 831 gv := addr.Operand(0) 832 globalInit, ok := fr.globalInits[gv] 833 if !ok { 834 return false 835 } 836 indices := make([]uint32, addr.OperandsCount()-2) 837 for i := range indices { 838 op := addr.Operand(i + 2) 839 if op.IsAConstantInt().IsNil() { 840 return false 841 } 842 indices[i] = uint32(op.ZExtValue()) 843 } 844 globalInit.update(gv.Type().ElementType(), indices, val) 845 return true 846 } else if !addr.IsAGlobalVariable().IsNil() { 847 if globalInit, ok := fr.globalInits[addr]; ok { 848 globalInit.update(addr.Type().ElementType(), nil, val) 849 return true 850 } 851 return false 852 } else { 853 return false 854 } 855 } 856 857 func (fr *frame) instruction(instr ssa.Instruction) { 858 fr.logf("[%T] %v @ %s\n", instr, instr, fr.pkg.Prog.Fset.Position(instr.Pos())) 859 if fr.GenerateDebug { 860 fr.debug.SetLocation(fr.builder, instr.Pos()) 861 } 862 863 switch instr := instr.(type) { 864 case *ssa.Alloc: 865 typ := deref(instr.Type()) 866 llvmtyp := fr.llvmtypes.ToLLVM(typ) 867 var value llvm.Value 868 if !instr.Heap { 869 value = fr.env[instr].value 870 fr.memsetZero(value, llvm.SizeOf(llvmtyp)) 871 } else if fr.isInit && fr.shouldStaticallyAllocate(instr) { 872 // If this is the init function and we think it may be beneficial, 873 // allocate memory statically in the object file rather than on the 874 // heap. This allows us to optimize constant stores into such 875 // variables as static initializations. 876 global := llvm.AddGlobal(fr.module.Module, llvmtyp, "") 877 global.SetLinkage(llvm.InternalLinkage) 878 fr.addGlobal(global, typ) 879 ptr := llvm.ConstBitCast(global, llvm.PointerType(llvm.Int8Type(), 0)) 880 fr.env[instr] = newValue(ptr, instr.Type()) 881 } else { 882 value = fr.createTypeMalloc(typ) 883 value.SetName(instr.Comment) 884 value = fr.builder.CreateBitCast(value, llvm.PointerType(llvm.Int8Type(), 0), "") 885 fr.env[instr] = newValue(value, instr.Type()) 886 } 887 888 case *ssa.BinOp: 889 lhs, rhs := fr.value(instr.X), fr.value(instr.Y) 890 fr.env[instr] = fr.binaryOp(lhs, instr.Op, rhs) 891 892 case *ssa.Call: 893 tuple := fr.callInstruction(instr) 894 if len(tuple) == 1 { 895 fr.env[instr] = tuple[0] 896 } else { 897 fr.tuples[instr] = tuple 898 } 899 900 case *ssa.ChangeInterface: 901 x := fr.value(instr.X) 902 // The source type must be a non-empty interface, 903 // as ChangeInterface cannot fail (E2I may fail). 904 if instr.Type().Underlying().(*types.Interface).NumMethods() > 0 { 905 x = fr.changeInterface(x, instr.Type(), false) 906 } else { 907 x = fr.convertI2E(x) 908 } 909 fr.env[instr] = x 910 911 case *ssa.ChangeType: 912 value := fr.llvmvalue(instr.X) 913 if _, ok := instr.Type().Underlying().(*types.Pointer); ok { 914 value = fr.builder.CreateBitCast(value, fr.llvmtypes.ToLLVM(instr.Type()), "") 915 } 916 fr.env[instr] = newValue(value, instr.Type()) 917 918 case *ssa.Convert: 919 v := fr.value(instr.X) 920 fr.env[instr] = fr.convert(v, instr.Type()) 921 922 case *ssa.Defer: 923 fn, arg := fr.createThunk(instr) 924 fr.runtime.Defer.call(fr, fr.frameptr, fn, arg) 925 926 case *ssa.Extract: 927 var elem llvm.Value 928 if t, ok := fr.tuples[instr.Tuple]; ok { 929 elem = t[instr.Index].value 930 } else { 931 tuple := fr.llvmvalue(instr.Tuple) 932 elem = fr.builder.CreateExtractValue(tuple, instr.Index, instr.Name()) 933 } 934 elemtyp := instr.Type() 935 fr.env[instr] = newValue(elem, elemtyp) 936 937 case *ssa.Field: 938 fieldtyp := instr.Type() 939 if p, ok := fr.ptr[instr.X]; ok { 940 field := fr.builder.CreateStructGEP(p, instr.Field, instr.Name()) 941 if fr.canAvoidElementLoad(instr) { 942 fr.ptr[instr] = field 943 } else { 944 fr.env[instr] = newValue(fr.builder.CreateLoad(field, ""), fieldtyp) 945 } 946 } else { 947 value := fr.llvmvalue(instr.X) 948 field := fr.builder.CreateExtractValue(value, instr.Field, instr.Name()) 949 fr.env[instr] = newValue(field, fieldtyp) 950 } 951 952 case *ssa.FieldAddr: 953 ptr := fr.llvmvalue(instr.X) 954 fr.nilCheck(instr.X, ptr) 955 xtyp := instr.X.Type().Underlying().(*types.Pointer).Elem() 956 ptrtyp := llvm.PointerType(fr.llvmtypes.ToLLVM(xtyp), 0) 957 ptr = fr.builder.CreateBitCast(ptr, ptrtyp, "") 958 fieldptr := fr.builder.CreateStructGEP(ptr, instr.Field, instr.Name()) 959 fieldptr = fr.builder.CreateBitCast(fieldptr, llvm.PointerType(llvm.Int8Type(), 0), "") 960 fieldptrtyp := instr.Type() 961 fr.env[instr] = newValue(fieldptr, fieldptrtyp) 962 963 case *ssa.Go: 964 fn, arg := fr.createThunk(instr) 965 fr.runtime.Go.call(fr, fn, arg) 966 967 case *ssa.If: 968 cond := fr.llvmvalue(instr.Cond) 969 block := instr.Block() 970 trueBlock := fr.block(block.Succs[0]) 971 falseBlock := fr.block(block.Succs[1]) 972 cond = fr.builder.CreateTrunc(cond, llvm.Int1Type(), "") 973 fr.builder.CreateCondBr(cond, trueBlock, falseBlock) 974 975 case *ssa.Index: 976 var arrayptr llvm.Value 977 978 if ptr, ok := fr.ptr[instr.X]; ok { 979 arrayptr = ptr 980 } else { 981 array := fr.llvmvalue(instr.X) 982 arrayptr = fr.allocaBuilder.CreateAlloca(array.Type(), "") 983 984 fr.builder.CreateStore(array, arrayptr) 985 } 986 index := fr.llvmvalue(instr.Index) 987 988 arraytyp := instr.X.Type().Underlying().(*types.Array) 989 arraylen := llvm.ConstInt(fr.llvmtypes.inttype, uint64(arraytyp.Len()), false) 990 991 // The index may not have been promoted to int (for example, if it 992 // came from a composite literal). 993 index = fr.createZExtOrTrunc(index, fr.types.inttype, "") 994 995 // Bounds checking: 0 <= index < len 996 zero := llvm.ConstNull(fr.types.inttype) 997 i0 := fr.builder.CreateICmp(llvm.IntSLT, index, zero, "") 998 li := fr.builder.CreateICmp(llvm.IntSLE, arraylen, index, "") 999 1000 cond := fr.builder.CreateOr(i0, li, "") 1001 1002 fr.condBrRuntimeError(cond, gccgoRuntimeErrorARRAY_INDEX_OUT_OF_BOUNDS) 1003 1004 addr := fr.builder.CreateGEP(arrayptr, []llvm.Value{zero, index}, "") 1005 if fr.canAvoidElementLoad(instr) { 1006 fr.ptr[instr] = addr 1007 } else { 1008 fr.env[instr] = newValue(fr.builder.CreateLoad(addr, ""), instr.Type()) 1009 } 1010 1011 case *ssa.IndexAddr: 1012 x := fr.llvmvalue(instr.X) 1013 index := fr.llvmvalue(instr.Index) 1014 var arrayptr, arraylen llvm.Value 1015 var elemtyp types.Type 1016 var errcode uint64 1017 switch typ := instr.X.Type().Underlying().(type) { 1018 case *types.Slice: 1019 elemtyp = typ.Elem() 1020 arrayptr = fr.builder.CreateExtractValue(x, 0, "") 1021 arraylen = fr.builder.CreateExtractValue(x, 1, "") 1022 errcode = gccgoRuntimeErrorSLICE_INDEX_OUT_OF_BOUNDS 1023 case *types.Pointer: // *array 1024 arraytyp := typ.Elem().Underlying().(*types.Array) 1025 elemtyp = arraytyp.Elem() 1026 fr.nilCheck(instr.X, x) 1027 arrayptr = x 1028 arraylen = llvm.ConstInt(fr.llvmtypes.inttype, uint64(arraytyp.Len()), false) 1029 errcode = gccgoRuntimeErrorARRAY_INDEX_OUT_OF_BOUNDS 1030 } 1031 1032 // The index may not have been promoted to int (for example, if it 1033 // came from a composite literal). 1034 index = fr.createZExtOrTrunc(index, fr.types.inttype, "") 1035 1036 // Bounds checking: 0 <= index < len 1037 zero := llvm.ConstNull(fr.types.inttype) 1038 i0 := fr.builder.CreateICmp(llvm.IntSLT, index, zero, "") 1039 li := fr.builder.CreateICmp(llvm.IntSLE, arraylen, index, "") 1040 1041 cond := fr.builder.CreateOr(i0, li, "") 1042 1043 fr.condBrRuntimeError(cond, errcode) 1044 1045 ptrtyp := llvm.PointerType(fr.llvmtypes.ToLLVM(elemtyp), 0) 1046 arrayptr = fr.builder.CreateBitCast(arrayptr, ptrtyp, "") 1047 addr := fr.builder.CreateGEP(arrayptr, []llvm.Value{index}, "") 1048 addr = fr.builder.CreateBitCast(addr, llvm.PointerType(llvm.Int8Type(), 0), "") 1049 fr.env[instr] = newValue(addr, types.NewPointer(elemtyp)) 1050 1051 case *ssa.Jump: 1052 succ := instr.Block().Succs[0] 1053 fr.builder.CreateBr(fr.block(succ)) 1054 1055 case *ssa.Lookup: 1056 x := fr.value(instr.X) 1057 index := fr.value(instr.Index) 1058 if isString(x.Type().Underlying()) { 1059 fr.env[instr] = fr.stringIndex(x, index) 1060 } else { 1061 v, ok := fr.mapLookup(x, index) 1062 if instr.CommaOk { 1063 fr.tuples[instr] = []*govalue{v, ok} 1064 } else { 1065 fr.env[instr] = v 1066 } 1067 } 1068 1069 case *ssa.MakeChan: 1070 fr.env[instr] = fr.makeChan(instr.Type(), fr.value(instr.Size)) 1071 1072 case *ssa.MakeClosure: 1073 llfn := fr.resolveFunctionGlobal(instr.Fn.(*ssa.Function)) 1074 llfn = llvm.ConstBitCast(llfn, llvm.PointerType(llvm.Int8Type(), 0)) 1075 fn := newValue(llfn, instr.Fn.(*ssa.Function).Signature) 1076 bindings := make([]*govalue, len(instr.Bindings)) 1077 for i, binding := range instr.Bindings { 1078 bindings[i] = fr.value(binding) 1079 } 1080 fr.env[instr] = fr.makeClosure(fn, bindings) 1081 1082 case *ssa.MakeInterface: 1083 // fr.ptr[instr.X] will be set if a pointer load was elided by canAvoidLoad 1084 if ptr, ok := fr.ptr[instr.X]; ok { 1085 fr.env[instr] = fr.makeInterfaceFromPointer(ptr, instr.X.Type(), instr.Type()) 1086 } else { 1087 receiver := fr.llvmvalue(instr.X) 1088 fr.env[instr] = fr.makeInterface(receiver, instr.X.Type(), instr.Type()) 1089 } 1090 1091 case *ssa.MakeMap: 1092 fr.env[instr] = fr.makeMap(instr.Type(), fr.value(instr.Reserve)) 1093 1094 case *ssa.MakeSlice: 1095 length := fr.value(instr.Len) 1096 capacity := fr.value(instr.Cap) 1097 fr.env[instr] = fr.makeSlice(instr.Type(), length, capacity) 1098 1099 case *ssa.MapUpdate: 1100 m := fr.value(instr.Map) 1101 k := fr.value(instr.Key) 1102 v := fr.value(instr.Value) 1103 fr.mapUpdate(m, k, v) 1104 1105 case *ssa.Next: 1106 iter := fr.tuples[instr.Iter] 1107 if instr.IsString { 1108 fr.tuples[instr] = fr.stringIterNext(iter) 1109 } else { 1110 fr.tuples[instr] = fr.mapIterNext(iter) 1111 } 1112 1113 case *ssa.Panic: 1114 arg := fr.value(instr.X) 1115 fr.callPanic(arg, true) 1116 1117 case *ssa.Phi: 1118 typ := instr.Type() 1119 phi := fr.builder.CreatePHI(fr.llvmtypes.ToLLVM(typ), instr.Comment) 1120 fr.env[instr] = newValue(phi, typ) 1121 fr.phis = append(fr.phis, pendingPhi{instr, phi}) 1122 1123 case *ssa.Range: 1124 x := fr.value(instr.X) 1125 switch x.Type().Underlying().(type) { 1126 case *types.Map: 1127 fr.tuples[instr] = fr.mapIterInit(x) 1128 case *types.Basic: // string 1129 fr.tuples[instr] = fr.stringIterInit(x) 1130 default: 1131 panic(fmt.Sprintf("unhandled range for type %T", x.Type())) 1132 } 1133 1134 case *ssa.Return: 1135 vals := make([]llvm.Value, len(instr.Results)) 1136 for i, res := range instr.Results { 1137 vals[i] = fr.llvmvalue(res) 1138 } 1139 fr.retInf.encode(llvm.GlobalContext(), fr.allocaBuilder, fr.builder, vals) 1140 1141 case *ssa.RunDefers: 1142 fr.runDefers() 1143 1144 case *ssa.Select: 1145 index, recvOk, recvElems := fr.chanSelect(instr) 1146 tuple := append([]*govalue{index, recvOk}, recvElems...) 1147 fr.tuples[instr] = tuple 1148 1149 case *ssa.Send: 1150 fr.chanSend(fr.value(instr.Chan), fr.value(instr.X)) 1151 1152 case *ssa.Slice: 1153 x := fr.llvmvalue(instr.X) 1154 low := fr.llvmvalue(instr.Low) 1155 high := fr.llvmvalue(instr.High) 1156 max := fr.llvmvalue(instr.Max) 1157 slice := fr.slice(x, instr.X.Type(), low, high, max) 1158 fr.env[instr] = newValue(slice, instr.Type()) 1159 1160 case *ssa.Store: 1161 addr := fr.llvmvalue(instr.Addr) 1162 value := fr.llvmvalue(instr.Val) 1163 addr = fr.builder.CreateBitCast(addr, llvm.PointerType(value.Type(), 0), "") 1164 // If this is the init function, see if we can simulate the effect 1165 // of the store in a global's initializer, in which case we can avoid 1166 // generating code for it. 1167 if !fr.isInit || !fr.maybeStoreInInitializer(value, addr) { 1168 fr.nilCheck(instr.Addr, addr) 1169 fr.builder.CreateStore(value, addr) 1170 } 1171 1172 case *switchInstr: 1173 fr.emitSwitch(instr) 1174 1175 case *ssa.TypeAssert: 1176 x := fr.value(instr.X) 1177 if instr.CommaOk { 1178 v, ok := fr.interfaceTypeCheck(x, instr.AssertedType) 1179 fr.tuples[instr] = []*govalue{v, ok} 1180 } else { 1181 fr.env[instr] = fr.interfaceTypeAssert(x, instr.AssertedType) 1182 } 1183 1184 case *ssa.UnOp: 1185 operand := fr.value(instr.X) 1186 switch instr.Op { 1187 case token.ARROW: 1188 x, ok := fr.chanRecv(operand, instr.CommaOk) 1189 if instr.CommaOk { 1190 fr.tuples[instr] = []*govalue{x, ok} 1191 } else { 1192 fr.env[instr] = x 1193 } 1194 case token.MUL: 1195 fr.nilCheck(instr.X, operand.value) 1196 if !fr.canAvoidLoad(instr, operand.value) { 1197 // The bitcast is necessary to handle recursive pointer loads. 1198 llptr := fr.builder.CreateBitCast(operand.value, llvm.PointerType(fr.llvmtypes.ToLLVM(instr.Type()), 0), "") 1199 fr.env[instr] = newValue(fr.builder.CreateLoad(llptr, ""), instr.Type()) 1200 } 1201 default: 1202 fr.env[instr] = fr.unaryOp(operand, instr.Op) 1203 } 1204 1205 default: 1206 panic(fmt.Sprintf("unhandled: %v", instr)) 1207 } 1208 } 1209 1210 func (fr *frame) callBuiltin(typ types.Type, builtin *ssa.Builtin, args []ssa.Value) []*govalue { 1211 switch builtin.Name() { 1212 case "print", "println": 1213 llargs := make([]*govalue, len(args)) 1214 for i, arg := range args { 1215 llargs[i] = fr.value(arg) 1216 } 1217 fr.printValues(builtin.Name() == "println", llargs...) 1218 return nil 1219 1220 case "panic": 1221 fr.callPanic(fr.value(args[0]), false) 1222 return nil 1223 1224 case "recover": 1225 return []*govalue{fr.callRecover(false)} 1226 1227 case "append": 1228 return []*govalue{fr.callAppend(fr.value(args[0]), fr.value(args[1]))} 1229 1230 case "close": 1231 fr.chanClose(fr.value(args[0])) 1232 return nil 1233 1234 case "cap": 1235 return []*govalue{fr.callCap(fr.value(args[0]))} 1236 1237 case "len": 1238 return []*govalue{fr.callLen(fr.value(args[0]))} 1239 1240 case "copy": 1241 return []*govalue{fr.callCopy(fr.value(args[0]), fr.value(args[1]))} 1242 1243 case "delete": 1244 fr.mapDelete(fr.value(args[0]), fr.value(args[1])) 1245 return nil 1246 1247 case "real": 1248 return []*govalue{fr.extractRealValue(fr.value(args[0]))} 1249 1250 case "imag": 1251 return []*govalue{fr.extractImagValue(fr.value(args[0]))} 1252 1253 case "complex": 1254 r := fr.llvmvalue(args[0]) 1255 i := fr.llvmvalue(args[1]) 1256 cmplx := llvm.Undef(fr.llvmtypes.ToLLVM(typ)) 1257 cmplx = fr.builder.CreateInsertValue(cmplx, r, 0, "") 1258 cmplx = fr.builder.CreateInsertValue(cmplx, i, 1, "") 1259 return []*govalue{newValue(cmplx, typ)} 1260 1261 case "ssa:wrapnilchk": 1262 ptr := fr.value(args[0]) 1263 fr.nilCheck(args[0], ptr.value) 1264 return []*govalue{ptr} 1265 1266 default: 1267 panic("unimplemented: " + builtin.Name()) 1268 } 1269 } 1270 1271 // callInstruction translates function call instructions. 1272 func (fr *frame) callInstruction(instr ssa.CallInstruction) []*govalue { 1273 call := instr.Common() 1274 if builtin, ok := call.Value.(*ssa.Builtin); ok { 1275 var typ types.Type 1276 if v := instr.Value(); v != nil { 1277 typ = v.Type() 1278 } 1279 return fr.callBuiltin(typ, builtin, call.Args) 1280 } 1281 1282 args := make([]*govalue, len(call.Args)) 1283 for i, arg := range call.Args { 1284 args[i] = fr.value(arg) 1285 } 1286 1287 var fn *govalue 1288 var chain llvm.Value 1289 if call.IsInvoke() { 1290 var recv *govalue 1291 fn, recv = fr.interfaceMethod(fr.llvmvalue(call.Value), call.Value.Type(), call.Method) 1292 args = append([]*govalue{recv}, args...) 1293 } else { 1294 if ssafn, ok := call.Value.(*ssa.Function); ok { 1295 llfn := fr.resolveFunctionGlobal(ssafn) 1296 llfn = llvm.ConstBitCast(llfn, llvm.PointerType(llvm.Int8Type(), 0)) 1297 fn = newValue(llfn, ssafn.Type()) 1298 } else { 1299 // First-class function values are stored as *{*fnptr}, so 1300 // we must extract the function pointer. We must also 1301 // set the chain, in case the function is a closure. 1302 fn = fr.value(call.Value) 1303 chain = fn.value 1304 fnptr := fr.builder.CreateBitCast(fn.value, llvm.PointerType(fn.value.Type(), 0), "") 1305 fnptr = fr.builder.CreateLoad(fnptr, "") 1306 fn = newValue(fnptr, fn.Type()) 1307 } 1308 if recv := call.Signature().Recv(); recv != nil { 1309 if _, ok := recv.Type().Underlying().(*types.Pointer); !ok { 1310 recvalloca := fr.allocaBuilder.CreateAlloca(args[0].value.Type(), "") 1311 fr.builder.CreateStore(args[0].value, recvalloca) 1312 args[0] = newValue(recvalloca, types.NewPointer(args[0].Type())) 1313 } 1314 } 1315 } 1316 return fr.createCall(fn, chain, args) 1317 } 1318 1319 func hasDefer(f *ssa.Function) bool { 1320 for _, b := range f.Blocks { 1321 for _, instr := range b.Instrs { 1322 if _, ok := instr.(*ssa.Defer); ok { 1323 return true 1324 } 1325 } 1326 } 1327 return false 1328 } 1329 1330 func callsRecover(f *ssa.Function) bool { 1331 for _, b := range f.Blocks { 1332 for _, instr := range b.Instrs { 1333 if instr, ok := instr.(ssa.CallInstruction); ok { 1334 b, ok := instr.Common().Value.(*ssa.Builtin) 1335 if ok && b.Name() == "recover" { 1336 return true 1337 } 1338 } 1339 } 1340 } 1341 return false 1342 }