github.com/axw/llgo@v0.0.0-20160805011314-95b5fe4dca20/irgen/typemap.go (about) 1 //===- typemap.go - type and type descriptor mapping ----------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the mapping from go/types types to LLVM types and to 11 // type descriptors. 12 // 13 //===----------------------------------------------------------------------===// 14 15 package irgen 16 17 import ( 18 "bytes" 19 "fmt" 20 "sort" 21 "strconv" 22 "strings" 23 24 "llvm.org/llgo/third_party/gotools/go/ssa" 25 "llvm.org/llgo/third_party/gotools/go/ssa/ssautil" 26 "llvm.org/llgo/third_party/gotools/go/types" 27 "llvm.org/llgo/third_party/gotools/go/types/typeutil" 28 "llvm.org/llvm/bindings/go/llvm" 29 ) 30 31 type MethodResolver interface { 32 ResolveMethod(*types.Selection) *govalue 33 } 34 35 // llvmTypeMap is provides a means of mapping from a types.Map 36 // to llgo's corresponding LLVM type representation. 37 type llvmTypeMap struct { 38 sizes *types.StdSizes 39 ctx llvm.Context 40 target llvm.TargetData 41 inttype llvm.Type 42 stringType llvm.Type 43 44 types typeutil.Map 45 } 46 47 type typeDescInfo struct { 48 global llvm.Value 49 commonTypePtr llvm.Value 50 mapDescPtr llvm.Value 51 gc, gcPtr llvm.Value 52 53 interfaceMethodTables typeutil.Map 54 } 55 56 type TypeMap struct { 57 *llvmTypeMap 58 mc manglerContext 59 60 module llvm.Module 61 pkgpath string 62 types, algs typeutil.Map 63 runtime *runtimeInterface 64 methodResolver MethodResolver 65 types.MethodSetCache 66 67 commonTypeType, uncommonTypeType, ptrTypeType, funcTypeType, arrayTypeType, sliceTypeType, mapTypeType, chanTypeType, interfaceTypeType, structTypeType llvm.Type 68 mapDescType llvm.Type 69 70 methodType, imethodType, structFieldType llvm.Type 71 72 typeSliceType, methodSliceType, imethodSliceType, structFieldSliceType llvm.Type 73 74 funcValType llvm.Type 75 hashFnType, equalFnType llvm.Type 76 77 algsEmptyInterface, 78 algsInterface, 79 algsFloat, 80 algsComplex, 81 algsString, 82 algsIdentity, 83 algsError algorithms 84 } 85 86 type algorithms struct { 87 hash, hashDescriptor, equal, equalDescriptor llvm.Value 88 } 89 90 func NewLLVMTypeMap(ctx llvm.Context, target llvm.TargetData) *llvmTypeMap { 91 // spec says int is either 32-bit or 64-bit. 92 // ABI currently requires sizeof(int) == sizeof(uint) == sizeof(uintptr). 93 inttype := ctx.IntType(8 * target.PointerSize()) 94 95 i8ptr := llvm.PointerType(llvm.Int8Type(), 0) 96 elements := []llvm.Type{i8ptr, inttype} 97 stringType := llvm.StructType(elements, false) 98 99 return &llvmTypeMap{ 100 ctx: ctx, 101 sizes: &types.StdSizes{ 102 WordSize: int64(target.PointerSize()), 103 MaxAlign: 8, 104 }, 105 target: target, 106 inttype: inttype, 107 stringType: stringType, 108 } 109 } 110 111 func NewTypeMap(pkg *ssa.Package, llvmtm *llvmTypeMap, module llvm.Module, r *runtimeInterface, mr MethodResolver) *TypeMap { 112 tm := &TypeMap{ 113 llvmTypeMap: llvmtm, 114 module: module, 115 pkgpath: pkg.Object.Path(), 116 runtime: r, 117 methodResolver: mr, 118 } 119 120 tm.mc.init(pkg.Prog, &tm.MethodSetCache) 121 122 uintptrType := tm.inttype 123 voidPtrType := llvm.PointerType(tm.ctx.Int8Type(), 0) 124 boolType := llvm.Int8Type() 125 stringPtrType := llvm.PointerType(tm.stringType, 0) 126 127 tm.funcValType = tm.ctx.StructCreateNamed("funcVal") 128 tm.funcValType.StructSetBody([]llvm.Type{ 129 llvm.PointerType(llvm.FunctionType(llvm.VoidType(), []llvm.Type{}, false), 0), 130 }, false) 131 132 params := []llvm.Type{voidPtrType, uintptrType} 133 tm.hashFnType = llvm.FunctionType(uintptrType, params, false) 134 params = []llvm.Type{voidPtrType, voidPtrType, uintptrType} 135 tm.equalFnType = llvm.FunctionType(boolType, params, false) 136 137 typeAlgorithms := [...]struct { 138 Name string 139 *algorithms 140 }{ 141 {"empty_interface", &tm.algsEmptyInterface}, 142 {"interface", &tm.algsInterface}, 143 {"float", &tm.algsFloat}, 144 {"complex", &tm.algsComplex}, 145 {"string", &tm.algsString}, 146 {"identity", &tm.algsIdentity}, 147 {"error", &tm.algsError}, 148 } 149 for _, typeAlgs := range typeAlgorithms { 150 hashFnName := "__go_type_hash_" + typeAlgs.Name 151 hashDescriptorName := hashFnName + "_descriptor" 152 equalFnName := "__go_type_equal_" + typeAlgs.Name 153 equalDescriptorName := equalFnName + "_descriptor" 154 typeAlgs.hash = llvm.AddGlobal(tm.module, tm.hashFnType, hashFnName) 155 typeAlgs.hashDescriptor = llvm.AddGlobal(tm.module, tm.funcValType, hashDescriptorName) 156 typeAlgs.equal = llvm.AddGlobal(tm.module, tm.equalFnType, equalFnName) 157 typeAlgs.equalDescriptor = llvm.AddGlobal(tm.module, tm.funcValType, equalDescriptorName) 158 } 159 160 tm.commonTypeType = tm.ctx.StructCreateNamed("commonType") 161 commonTypeTypePtr := llvm.PointerType(tm.commonTypeType, 0) 162 163 tm.methodType = tm.ctx.StructCreateNamed("method") 164 tm.methodType.StructSetBody([]llvm.Type{ 165 stringPtrType, // name 166 stringPtrType, // pkgPath 167 commonTypeTypePtr, // mtype (without receiver) 168 commonTypeTypePtr, // type (with receiver) 169 voidPtrType, // function 170 }, false) 171 172 tm.methodSliceType = tm.makeNamedSliceType("methodSlice", tm.methodType) 173 174 tm.uncommonTypeType = tm.ctx.StructCreateNamed("uncommonType") 175 tm.uncommonTypeType.StructSetBody([]llvm.Type{ 176 stringPtrType, // name 177 stringPtrType, // pkgPath 178 tm.methodSliceType, // methods 179 }, false) 180 181 tm.commonTypeType.StructSetBody([]llvm.Type{ 182 tm.ctx.Int8Type(), // Kind 183 tm.ctx.Int8Type(), // align 184 tm.ctx.Int8Type(), // fieldAlign 185 uintptrType, // size 186 tm.ctx.Int32Type(), // hash 187 llvm.PointerType(tm.funcValType, 0), // hashfn 188 llvm.PointerType(tm.funcValType, 0), // equalfn 189 voidPtrType, // gc 190 stringPtrType, // string 191 llvm.PointerType(tm.uncommonTypeType, 0), // uncommonType 192 commonTypeTypePtr, // ptrToThis 193 }, false) 194 195 tm.typeSliceType = tm.makeNamedSliceType("typeSlice", commonTypeTypePtr) 196 197 tm.ptrTypeType = tm.ctx.StructCreateNamed("ptrType") 198 tm.ptrTypeType.StructSetBody([]llvm.Type{ 199 tm.commonTypeType, 200 commonTypeTypePtr, 201 }, false) 202 203 tm.funcTypeType = tm.ctx.StructCreateNamed("funcType") 204 tm.funcTypeType.StructSetBody([]llvm.Type{ 205 tm.commonTypeType, 206 tm.ctx.Int8Type(), // dotdotdot 207 tm.typeSliceType, // in 208 tm.typeSliceType, // out 209 }, false) 210 211 tm.arrayTypeType = tm.ctx.StructCreateNamed("arrayType") 212 tm.arrayTypeType.StructSetBody([]llvm.Type{ 213 tm.commonTypeType, 214 commonTypeTypePtr, // elem 215 commonTypeTypePtr, // slice 216 tm.inttype, // len 217 }, false) 218 219 tm.sliceTypeType = tm.ctx.StructCreateNamed("sliceType") 220 tm.sliceTypeType.StructSetBody([]llvm.Type{ 221 tm.commonTypeType, 222 commonTypeTypePtr, // elem 223 }, false) 224 225 tm.mapTypeType = tm.ctx.StructCreateNamed("mapType") 226 tm.mapTypeType.StructSetBody([]llvm.Type{ 227 tm.commonTypeType, 228 commonTypeTypePtr, // key 229 commonTypeTypePtr, // elem 230 }, false) 231 232 tm.chanTypeType = tm.ctx.StructCreateNamed("chanType") 233 tm.chanTypeType.StructSetBody([]llvm.Type{ 234 tm.commonTypeType, 235 commonTypeTypePtr, // elem 236 tm.inttype, // dir 237 }, false) 238 239 tm.imethodType = tm.ctx.StructCreateNamed("imethod") 240 tm.imethodType.StructSetBody([]llvm.Type{ 241 stringPtrType, // name 242 stringPtrType, // pkgPath 243 commonTypeTypePtr, // typ 244 }, false) 245 246 tm.imethodSliceType = tm.makeNamedSliceType("imethodSlice", tm.imethodType) 247 248 tm.interfaceTypeType = tm.ctx.StructCreateNamed("interfaceType") 249 tm.interfaceTypeType.StructSetBody([]llvm.Type{ 250 tm.commonTypeType, 251 tm.imethodSliceType, 252 }, false) 253 254 tm.structFieldType = tm.ctx.StructCreateNamed("structField") 255 tm.structFieldType.StructSetBody([]llvm.Type{ 256 stringPtrType, // name 257 stringPtrType, // pkgPath 258 commonTypeTypePtr, // typ 259 stringPtrType, // tag 260 tm.inttype, // offset 261 }, false) 262 263 tm.structFieldSliceType = tm.makeNamedSliceType("structFieldSlice", tm.structFieldType) 264 265 tm.structTypeType = tm.ctx.StructCreateNamed("structType") 266 tm.structTypeType.StructSetBody([]llvm.Type{ 267 tm.commonTypeType, 268 tm.structFieldSliceType, // fields 269 }, false) 270 271 tm.mapDescType = tm.ctx.StructCreateNamed("mapDesc") 272 tm.mapDescType.StructSetBody([]llvm.Type{ 273 commonTypeTypePtr, // map_descriptor 274 tm.inttype, // entry_size 275 tm.inttype, // key_offset 276 tm.inttype, // value_offset 277 }, false) 278 279 return tm 280 } 281 282 func (tm *llvmTypeMap) ToLLVM(t types.Type) llvm.Type { 283 return tm.toLLVM(t, "") 284 } 285 286 func (tm *llvmTypeMap) toLLVM(t types.Type, name string) llvm.Type { 287 lt, ok := tm.types.At(t).(llvm.Type) 288 if !ok { 289 lt = tm.makeLLVMType(t, name) 290 if lt.IsNil() { 291 panic(fmt.Sprint("Failed to create LLVM type for: ", t)) 292 } 293 tm.types.Set(t, lt) 294 } 295 return lt 296 } 297 298 func (tm *llvmTypeMap) makeLLVMType(t types.Type, name string) llvm.Type { 299 return tm.getBackendType(t).ToLLVM(tm.ctx) 300 } 301 302 func (tm *llvmTypeMap) Offsetsof(fields []*types.Var) []int64 { 303 offsets := make([]int64, len(fields)) 304 var o int64 305 for i, f := range fields { 306 a := tm.Alignof(f.Type()) 307 o = align(o, a) 308 offsets[i] = o 309 o += tm.Sizeof(f.Type()) 310 } 311 return offsets 312 } 313 314 var basicSizes = [...]byte{ 315 types.Bool: 1, 316 types.Int8: 1, 317 types.Int16: 2, 318 types.Int32: 4, 319 types.Int64: 8, 320 types.Uint8: 1, 321 types.Uint16: 2, 322 types.Uint32: 4, 323 types.Uint64: 8, 324 types.Float32: 4, 325 types.Float64: 8, 326 types.Complex64: 8, 327 types.Complex128: 16, 328 } 329 330 func (tm *llvmTypeMap) Sizeof(T types.Type) int64 { 331 switch t := T.Underlying().(type) { 332 case *types.Basic: 333 k := t.Kind() 334 if int(k) < len(basicSizes) { 335 if s := basicSizes[k]; s > 0 { 336 return int64(s) 337 } 338 } 339 if k == types.String { 340 return tm.sizes.WordSize * 2 341 } 342 case *types.Array: 343 a := tm.Alignof(t.Elem()) 344 z := tm.Sizeof(t.Elem()) 345 return align(z, a) * t.Len() // may be 0 346 case *types.Slice: 347 return tm.sizes.WordSize * 3 348 case *types.Struct: 349 n := t.NumFields() 350 if n == 0 { 351 return 0 352 } 353 fields := make([]*types.Var, t.NumFields()) 354 for i := 0; i != t.NumFields(); i++ { 355 fields[i] = t.Field(i) 356 } 357 offsets := tm.Offsetsof(fields) 358 return align(offsets[n-1]+tm.Sizeof(t.Field(n-1).Type()), tm.Alignof(t)) 359 case *types.Interface: 360 return tm.sizes.WordSize * 2 361 } 362 return tm.sizes.WordSize // catch-all 363 } 364 365 func (tm *llvmTypeMap) Alignof(t types.Type) int64 { 366 return tm.sizes.Alignof(t) 367 } 368 369 /////////////////////////////////////////////////////////////////////////////// 370 371 func (tm *TypeMap) ToRuntime(t types.Type) llvm.Value { 372 return llvm.ConstBitCast(tm.getTypeDescriptorPointer(t), llvm.PointerType(llvm.Int8Type(), 0)) 373 } 374 375 type localNamedTypeInfo struct { 376 functionName string 377 scopeNum int 378 } 379 380 type namedTypeInfo struct { 381 pkgname, pkgpath string 382 name string 383 localNamedTypeInfo 384 } 385 386 type manglerContext struct { 387 ti map[*types.Named]localNamedTypeInfo 388 msc *types.MethodSetCache 389 } 390 391 // Assembles the method set into the order that gccgo uses (unexported methods first). 392 // TODO(pcc): cache this. 393 func orderedMethodSet(ms *types.MethodSet) []*types.Selection { 394 oms := make([]*types.Selection, ms.Len()) 395 omsi := 0 396 for i := 0; i != ms.Len(); i++ { 397 if sel := ms.At(i); !sel.Obj().Exported() { 398 oms[omsi] = sel 399 omsi++ 400 } 401 } 402 for i := 0; i != ms.Len(); i++ { 403 if sel := ms.At(i); sel.Obj().Exported() { 404 oms[omsi] = sel 405 omsi++ 406 } 407 } 408 return oms 409 } 410 411 func (ctx *manglerContext) init(prog *ssa.Program, msc *types.MethodSetCache) { 412 ctx.msc = msc 413 ctx.ti = make(map[*types.Named]localNamedTypeInfo) 414 for f, _ := range ssautil.AllFunctions(prog) { 415 scopeNum := 0 416 var addNamedTypesToMap func(*types.Scope) 417 addNamedTypesToMap = func(scope *types.Scope) { 418 hasNamedTypes := false 419 for _, n := range scope.Names() { 420 if tn, ok := scope.Lookup(n).(*types.TypeName); ok { 421 hasNamedTypes = true 422 ctx.ti[tn.Type().(*types.Named)] = localNamedTypeInfo{f.Name(), scopeNum} 423 } 424 } 425 if hasNamedTypes { 426 scopeNum++ 427 } 428 for i := 0; i != scope.NumChildren(); i++ { 429 addNamedTypesToMap(scope.Child(i)) 430 } 431 } 432 if fobj, ok := f.Object().(*types.Func); ok && fobj.Scope() != nil { 433 addNamedTypesToMap(fobj.Scope()) 434 } 435 } 436 } 437 438 func (ctx *manglerContext) getNamedTypeInfo(t types.Type) (nti namedTypeInfo) { 439 switch t := t.(type) { 440 case *types.Basic: 441 switch t.Kind() { 442 case types.Byte: 443 nti.name = "uint8" 444 case types.Rune: 445 nti.name = "int32" 446 case types.UnsafePointer: 447 nti.pkgname = "unsafe" 448 nti.pkgpath = "unsafe" 449 nti.name = "Pointer" 450 default: 451 nti.name = t.Name() 452 } 453 454 case *types.Named: 455 obj := t.Obj() 456 if pkg := obj.Pkg(); pkg != nil { 457 nti.pkgname = obj.Pkg().Name() 458 nti.pkgpath = obj.Pkg().Path() 459 } 460 nti.name = obj.Name() 461 nti.localNamedTypeInfo = ctx.ti[t] 462 463 default: 464 panic("not a named type") 465 } 466 467 return 468 } 469 470 func (ctx *manglerContext) mangleSignature(s *types.Signature, recv *types.Var, b *bytes.Buffer) { 471 b.WriteRune('F') 472 if recv != nil { 473 b.WriteRune('m') 474 ctx.mangleType(recv.Type(), b) 475 } 476 477 if p := s.Params(); p.Len() != 0 { 478 b.WriteRune('p') 479 for i := 0; i != p.Len(); i++ { 480 ctx.mangleType(p.At(i).Type(), b) 481 } 482 if s.Variadic() { 483 b.WriteRune('V') 484 } 485 b.WriteRune('e') 486 } 487 488 if r := s.Results(); r.Len() != 0 { 489 b.WriteRune('r') 490 for i := 0; i != r.Len(); i++ { 491 ctx.mangleType(r.At(i).Type(), b) 492 } 493 b.WriteRune('e') 494 } 495 496 b.WriteRune('e') 497 } 498 499 func ManglePackagePath(pkgpath string) string { 500 pkgpath = strings.Replace(pkgpath, "/", "_", -1) 501 pkgpath = strings.Replace(pkgpath, ".", "_", -1) 502 return pkgpath 503 } 504 505 func (ctx *manglerContext) mangleType(t types.Type, b *bytes.Buffer) { 506 switch t := t.(type) { 507 case *types.Basic, *types.Named: 508 var nb bytes.Buffer 509 ti := ctx.getNamedTypeInfo(t) 510 if ti.pkgpath != "" { 511 nb.WriteString(ManglePackagePath(ti.pkgpath)) 512 nb.WriteRune('.') 513 } 514 if ti.functionName != "" { 515 nb.WriteString(ti.functionName) 516 nb.WriteRune('$') 517 if ti.scopeNum != 0 { 518 nb.WriteString(strconv.Itoa(ti.scopeNum)) 519 nb.WriteRune('$') 520 } 521 } 522 nb.WriteString(ti.name) 523 524 b.WriteRune('N') 525 b.WriteString(strconv.Itoa(nb.Len())) 526 b.WriteRune('_') 527 b.WriteString(nb.String()) 528 529 case *types.Pointer: 530 b.WriteRune('p') 531 ctx.mangleType(t.Elem(), b) 532 533 case *types.Map: 534 b.WriteRune('M') 535 ctx.mangleType(t.Key(), b) 536 b.WriteString("__") 537 ctx.mangleType(t.Elem(), b) 538 539 case *types.Chan: 540 b.WriteRune('C') 541 ctx.mangleType(t.Elem(), b) 542 switch t.Dir() { 543 case types.SendOnly: 544 b.WriteRune('s') 545 case types.RecvOnly: 546 b.WriteRune('r') 547 case types.SendRecv: 548 b.WriteString("sr") 549 } 550 b.WriteRune('e') 551 552 case *types.Signature: 553 ctx.mangleSignature(t, t.Recv(), b) 554 555 case *types.Array: 556 b.WriteRune('A') 557 ctx.mangleType(t.Elem(), b) 558 b.WriteString(strconv.FormatInt(t.Len(), 10)) 559 b.WriteRune('e') 560 561 case *types.Slice: 562 b.WriteRune('A') 563 ctx.mangleType(t.Elem(), b) 564 b.WriteRune('e') 565 566 case *types.Struct: 567 b.WriteRune('S') 568 for i := 0; i != t.NumFields(); i++ { 569 f := t.Field(i) 570 if f.Anonymous() { 571 b.WriteString("0_") 572 } else { 573 b.WriteString(strconv.Itoa(len(f.Name()))) 574 b.WriteRune('_') 575 b.WriteString(f.Name()) 576 } 577 ctx.mangleType(f.Type(), b) 578 // TODO: tags are mangled here 579 } 580 b.WriteRune('e') 581 582 case *types.Interface: 583 b.WriteRune('I') 584 methodset := ctx.msc.MethodSet(t) 585 for _, m := range orderedMethodSet(methodset) { 586 method := m.Obj() 587 var nb bytes.Buffer 588 if !method.Exported() { 589 nb.WriteRune('.') 590 nb.WriteString(method.Pkg().Path()) 591 nb.WriteRune('.') 592 } 593 nb.WriteString(method.Name()) 594 595 b.WriteString(strconv.Itoa(nb.Len())) 596 b.WriteRune('_') 597 b.WriteString(nb.String()) 598 599 ctx.mangleSignature(method.Type().(*types.Signature), nil, b) 600 } 601 b.WriteRune('e') 602 603 default: 604 panic(fmt.Sprintf("unhandled type: %#v", t)) 605 } 606 } 607 608 func (ctx *manglerContext) mangleTypeDescriptorName(t types.Type, b *bytes.Buffer) { 609 switch t := t.(type) { 610 case *types.Basic, *types.Named: 611 b.WriteString("__go_tdn_") 612 ti := ctx.getNamedTypeInfo(t) 613 if ti.pkgpath != "" { 614 b.WriteString(ManglePackagePath(ti.pkgpath)) 615 b.WriteRune('.') 616 } 617 if ti.functionName != "" { 618 b.WriteString(ti.functionName) 619 b.WriteRune('.') 620 if ti.scopeNum != 0 { 621 b.WriteString(strconv.Itoa(ti.scopeNum)) 622 b.WriteRune('.') 623 } 624 } 625 b.WriteString(ti.name) 626 627 default: 628 b.WriteString("__go_td_") 629 ctx.mangleType(t, b) 630 } 631 } 632 633 func (ctx *manglerContext) mangleMapDescriptorName(t types.Type, b *bytes.Buffer) { 634 b.WriteString("__go_map_") 635 ctx.mangleType(t, b) 636 } 637 638 func (ctx *manglerContext) mangleImtName(srctype types.Type, targettype *types.Interface, b *bytes.Buffer) { 639 b.WriteString("__go_imt_") 640 ctx.mangleType(targettype, b) 641 b.WriteString("__") 642 ctx.mangleType(srctype, b) 643 } 644 645 func (ctx *manglerContext) mangleHashFunctionName(t types.Type) string { 646 var b bytes.Buffer 647 b.WriteString("__go_type_hash_") 648 ctx.mangleType(t, &b) 649 return b.String() 650 } 651 652 func (ctx *manglerContext) mangleEqualFunctionName(t types.Type) string { 653 var b bytes.Buffer 654 b.WriteString("__go_type_equal_") 655 ctx.mangleType(t, &b) 656 return b.String() 657 } 658 659 func (ctx *manglerContext) mangleFunctionName(f *ssa.Function) string { 660 var b bytes.Buffer 661 662 if f.Parent() != nil { 663 // Anonymous functions are not guaranteed to 664 // have unique identifiers at the global scope. 665 b.WriteString(ctx.mangleFunctionName(f.Parent())) 666 b.WriteRune(':') 667 b.WriteString(f.String()) 668 return b.String() 669 } 670 671 // Synthetic bound and thunk functions are special cases; they can only be 672 // distinguished using private data that is only exposed via String(). 673 if strings.HasSuffix(f.Name(), "$bound") || strings.HasSuffix(f.Name(), "$thunk") { 674 b.WriteString(f.String()) 675 return b.String() 676 } 677 678 var pkg *types.Package 679 if f.Pkg != nil { 680 pkg = f.Pkg.Object 681 } else if !f.Object().Exported() { 682 pkg = f.Object().Pkg() 683 } 684 685 if pkg != nil { 686 b.WriteString(ManglePackagePath(pkg.Path())) 687 b.WriteRune('.') 688 } 689 690 if f.Signature.Recv() == nil && f.Name() == "init" { 691 b.WriteString(".import") 692 } else { 693 b.WriteString(f.Name()) 694 } 695 if f.Signature.Recv() != nil { 696 b.WriteRune('.') 697 ctx.mangleType(f.Signature.Recv().Type(), &b) 698 } 699 700 return b.String() 701 } 702 703 func (ctx *manglerContext) mangleGlobalName(g *ssa.Global) string { 704 var b bytes.Buffer 705 706 b.WriteString(ManglePackagePath(g.Pkg.Object.Path())) 707 b.WriteRune('.') 708 b.WriteString(g.Name()) 709 710 return b.String() 711 } 712 713 const ( 714 // From gofrontend/types.h 715 gccgoTypeClassERROR = iota 716 gccgoTypeClassVOID 717 gccgoTypeClassBOOLEAN 718 gccgoTypeClassINTEGER 719 gccgoTypeClassFLOAT 720 gccgoTypeClassCOMPLEX 721 gccgoTypeClassSTRING 722 gccgoTypeClassSINK 723 gccgoTypeClassFUNCTION 724 gccgoTypeClassPOINTER 725 gccgoTypeClassNIL 726 gccgoTypeClassCALL_MULTIPLE_RESULT 727 gccgoTypeClassSTRUCT 728 gccgoTypeClassARRAY 729 gccgoTypeClassMAP 730 gccgoTypeClassCHANNEL 731 gccgoTypeClassINTERFACE 732 gccgoTypeClassNAMED 733 gccgoTypeClassFORWARD 734 ) 735 736 func getStringHash(s string, h uint32) uint32 { 737 for _, c := range []byte(s) { 738 h ^= uint32(c) 739 h += 16777619 740 } 741 return h 742 } 743 744 func (tm *TypeMap) getTypeHash(t types.Type) uint32 { 745 switch t := t.(type) { 746 case *types.Basic, *types.Named: 747 nti := tm.mc.getNamedTypeInfo(t) 748 h := getStringHash(nti.functionName+nti.name+nti.pkgpath, 0) 749 h ^= uint32(nti.scopeNum) 750 return gccgoTypeClassNAMED + h 751 752 case *types.Signature: 753 var h uint32 754 755 p := t.Params() 756 for i := 0; i != p.Len(); i++ { 757 h += tm.getTypeHash(p.At(i).Type()) << uint32(i+1) 758 } 759 760 r := t.Results() 761 for i := 0; i != r.Len(); i++ { 762 h += tm.getTypeHash(r.At(i).Type()) << uint32(i+2) 763 } 764 765 if t.Variadic() { 766 h += 1 767 } 768 h <<= 4 769 return gccgoTypeClassFUNCTION + h 770 771 case *types.Pointer: 772 return gccgoTypeClassPOINTER + (tm.getTypeHash(t.Elem()) << 4) 773 774 case *types.Struct: 775 var h uint32 776 for i := 0; i != t.NumFields(); i++ { 777 h = (h << 1) + tm.getTypeHash(t.Field(i).Type()) 778 } 779 h <<= 2 780 return gccgoTypeClassSTRUCT + h 781 782 case *types.Array: 783 return gccgoTypeClassARRAY + tm.getTypeHash(t.Elem()) + 1 784 785 case *types.Slice: 786 return gccgoTypeClassARRAY + tm.getTypeHash(t.Elem()) + 1 787 788 case *types.Map: 789 return gccgoTypeClassMAP + tm.getTypeHash(t.Key()) + tm.getTypeHash(t.Elem()) + 2 790 791 case *types.Chan: 792 var h uint32 793 794 switch t.Dir() { 795 case types.SendOnly: 796 h = 1 797 case types.RecvOnly: 798 h = 2 799 case types.SendRecv: 800 h = 3 801 } 802 803 h += tm.getTypeHash(t.Elem()) << 2 804 h <<= 3 805 return gccgoTypeClassCHANNEL + h 806 807 case *types.Interface: 808 var h uint32 809 for _, m := range orderedMethodSet(tm.MethodSet(t)) { 810 h = getStringHash(m.Obj().Name(), h) 811 h <<= 1 812 } 813 return gccgoTypeClassINTERFACE + h 814 815 default: 816 panic(fmt.Sprintf("unhandled type: %#v", t)) 817 } 818 } 819 820 func (tm *TypeMap) writeType(typ types.Type, b *bytes.Buffer) { 821 switch t := typ.(type) { 822 case *types.Basic, *types.Named: 823 ti := tm.mc.getNamedTypeInfo(t) 824 if ti.pkgpath != "" { 825 b.WriteByte('\t') 826 b.WriteString(ManglePackagePath(ti.pkgpath)) 827 b.WriteByte('\t') 828 b.WriteString(ti.pkgname) 829 b.WriteByte('.') 830 } 831 if ti.functionName != "" { 832 b.WriteByte('\t') 833 b.WriteString(ti.functionName) 834 b.WriteByte('$') 835 if ti.scopeNum != 0 { 836 b.WriteString(strconv.Itoa(ti.scopeNum)) 837 b.WriteByte('$') 838 } 839 b.WriteByte('\t') 840 } 841 b.WriteString(ti.name) 842 843 case *types.Array: 844 fmt.Fprintf(b, "[%d]", t.Len()) 845 tm.writeType(t.Elem(), b) 846 847 case *types.Slice: 848 b.WriteString("[]") 849 tm.writeType(t.Elem(), b) 850 851 case *types.Struct: 852 if t.NumFields() == 0 { 853 b.WriteString("struct {}") 854 return 855 } 856 b.WriteString("struct { ") 857 for i := 0; i != t.NumFields(); i++ { 858 f := t.Field(i) 859 if i > 0 { 860 b.WriteString("; ") 861 } 862 if !f.Anonymous() { 863 b.WriteString(f.Name()) 864 b.WriteByte(' ') 865 } 866 tm.writeType(f.Type(), b) 867 if tag := t.Tag(i); tag != "" { 868 fmt.Fprintf(b, " %q", tag) 869 } 870 } 871 b.WriteString(" }") 872 873 case *types.Pointer: 874 b.WriteByte('*') 875 tm.writeType(t.Elem(), b) 876 877 case *types.Signature: 878 b.WriteString("func") 879 tm.writeSignature(t, b) 880 881 case *types.Interface: 882 if t.NumMethods() == 0 && t.NumEmbeddeds() == 0 { 883 b.WriteString("interface {}") 884 return 885 } 886 // We write the source-level methods and embedded types rather 887 // than the actual method set since resolved method signatures 888 // may have non-printable cycles if parameters have anonymous 889 // interface types that (directly or indirectly) embed the 890 // current interface. For instance, consider the result type 891 // of m: 892 // 893 // type T interface{ 894 // m() interface{ T } 895 // } 896 // 897 b.WriteString("interface { ") 898 // print explicit interface methods and embedded types 899 for i := 0; i != t.NumMethods(); i++ { 900 m := t.Method(i) 901 if i > 0 { 902 b.WriteString("; ") 903 } 904 if !m.Exported() { 905 b.WriteString(m.Pkg().Path()) 906 b.WriteByte('.') 907 } 908 b.WriteString(m.Name()) 909 tm.writeSignature(m.Type().(*types.Signature), b) 910 } 911 for i := 0; i != t.NumEmbeddeds(); i++ { 912 typ := t.Embedded(i) 913 if i > 0 || t.NumMethods() > 0 { 914 b.WriteString("; ") 915 } 916 tm.writeType(typ, b) 917 } 918 b.WriteString(" }") 919 920 case *types.Map: 921 b.WriteString("map[") 922 tm.writeType(t.Key(), b) 923 b.WriteByte(']') 924 tm.writeType(t.Elem(), b) 925 926 case *types.Chan: 927 var s string 928 var parens bool 929 switch t.Dir() { 930 case types.SendRecv: 931 s = "chan " 932 // chan (<-chan T) requires parentheses 933 if c, _ := t.Elem().(*types.Chan); c != nil && c.Dir() == types.RecvOnly { 934 parens = true 935 } 936 case types.SendOnly: 937 s = "chan<- " 938 case types.RecvOnly: 939 s = "<-chan " 940 default: 941 panic("unreachable") 942 } 943 b.WriteString(s) 944 if parens { 945 b.WriteByte('(') 946 } 947 tm.writeType(t.Elem(), b) 948 if parens { 949 b.WriteByte(')') 950 } 951 952 default: 953 panic(fmt.Sprintf("unhandled type: %#v", t)) 954 } 955 } 956 957 func (tm *TypeMap) writeTuple(tup *types.Tuple, variadic bool, b *bytes.Buffer) { 958 b.WriteByte('(') 959 if tup != nil { 960 for i := 0; i != tup.Len(); i++ { 961 v := tup.At(i) 962 if i > 0 { 963 b.WriteString(", ") 964 } 965 typ := v.Type() 966 if variadic && i == tup.Len()-1 { 967 b.WriteString("...") 968 typ = typ.(*types.Slice).Elem() 969 } 970 tm.writeType(typ, b) 971 } 972 } 973 b.WriteByte(')') 974 } 975 976 func (tm *TypeMap) writeSignature(sig *types.Signature, b *bytes.Buffer) { 977 tm.writeTuple(sig.Params(), sig.Variadic(), b) 978 979 n := sig.Results().Len() 980 if n == 0 { 981 // no result 982 return 983 } 984 985 b.WriteByte(' ') 986 if n == 1 { 987 tm.writeType(sig.Results().At(0).Type(), b) 988 return 989 } 990 991 // multiple results 992 tm.writeTuple(sig.Results(), false, b) 993 } 994 995 func (tm *TypeMap) getTypeDescType(t types.Type) llvm.Type { 996 switch t.Underlying().(type) { 997 case *types.Basic: 998 return tm.commonTypeType 999 case *types.Pointer: 1000 return tm.ptrTypeType 1001 case *types.Signature: 1002 return tm.funcTypeType 1003 case *types.Array: 1004 return tm.arrayTypeType 1005 case *types.Slice: 1006 return tm.sliceTypeType 1007 case *types.Map: 1008 return tm.mapTypeType 1009 case *types.Chan: 1010 return tm.chanTypeType 1011 case *types.Struct: 1012 return tm.structTypeType 1013 case *types.Interface: 1014 return tm.interfaceTypeType 1015 default: 1016 panic(fmt.Sprintf("unhandled type: %#v", t)) 1017 } 1018 } 1019 1020 func (tm *TypeMap) getNamedTypeLinkage(nt *types.Named) (linkage llvm.Linkage, emit bool) { 1021 if pkg := nt.Obj().Pkg(); pkg != nil { 1022 linkage = llvm.ExternalLinkage 1023 emit = pkg.Path() == tm.pkgpath 1024 } else { 1025 linkage = llvm.LinkOnceODRLinkage 1026 emit = true 1027 } 1028 1029 return 1030 } 1031 1032 func (tm *TypeMap) getTypeDescLinkage(t types.Type) (linkage llvm.Linkage, emit bool) { 1033 switch t := t.(type) { 1034 case *types.Named: 1035 linkage, emit = tm.getNamedTypeLinkage(t) 1036 1037 case *types.Pointer: 1038 elem := t.Elem() 1039 if nt, ok := elem.(*types.Named); ok { 1040 // Thanks to the ptrToThis member, pointers to named types appear 1041 // in exactly the same objects as the named types themselves, so 1042 // we can give them the same linkage. 1043 linkage, emit = tm.getNamedTypeLinkage(nt) 1044 return 1045 } 1046 linkage = llvm.LinkOnceODRLinkage 1047 emit = true 1048 1049 default: 1050 linkage = llvm.LinkOnceODRLinkage 1051 emit = true 1052 } 1053 1054 return 1055 } 1056 1057 type typeAndInfo struct { 1058 typ types.Type 1059 typeString string 1060 tdi *typeDescInfo 1061 } 1062 1063 type byTypeName []typeAndInfo 1064 1065 func (ts byTypeName) Len() int { return len(ts) } 1066 func (ts byTypeName) Swap(i, j int) { 1067 ts[i], ts[j] = ts[j], ts[i] 1068 } 1069 func (ts byTypeName) Less(i, j int) bool { 1070 return ts[i].typeString < ts[j].typeString 1071 } 1072 1073 func (tm *TypeMap) emitTypeDescInitializers() { 1074 var maxSize, maxAlign int64 1075 maxAlign = 1 1076 1077 for changed := true; changed; { 1078 changed = false 1079 1080 var ts []typeAndInfo 1081 1082 tm.types.Iterate(func(key types.Type, value interface{}) { 1083 tdi := value.(*typeDescInfo) 1084 if tdi.global.Initializer().C == nil { 1085 linkage, emit := tm.getTypeDescLinkage(key) 1086 tdi.global.SetLinkage(linkage) 1087 tdi.gc.SetLinkage(linkage) 1088 if emit { 1089 changed = true 1090 ts = append(ts, typeAndInfo{key, key.String(), tdi}) 1091 } 1092 } 1093 }) 1094 1095 if changed { 1096 sort.Sort(byTypeName(ts)) 1097 for _, t := range ts { 1098 tm.emitTypeDescInitializer(t.typ, t.tdi) 1099 if size := tm.Sizeof(t.typ); size > maxSize { 1100 maxSize = size 1101 } 1102 if align := tm.Alignof(t.typ); align > maxAlign { 1103 maxAlign = align 1104 } 1105 } 1106 } 1107 } 1108 } 1109 1110 const ( 1111 // From libgo/runtime/mgc0.h 1112 gcOpcodeEND = iota 1113 gcOpcodePTR 1114 gcOpcodeAPTR 1115 gcOpcodeARRAY_START 1116 gcOpcodeARRAY_NEXT 1117 gcOpcodeCALL 1118 gcOpcodeCHAN_PTR 1119 gcOpcodeSTRING 1120 gcOpcodeEFACE 1121 gcOpcodeIFACE 1122 gcOpcodeSLICE 1123 gcOpcodeREGION 1124 1125 gcStackCapacity = 8 1126 ) 1127 1128 func (tm *TypeMap) makeGcInst(val int64) llvm.Value { 1129 c := llvm.ConstInt(tm.inttype, uint64(val), false) 1130 return llvm.ConstIntToPtr(c, llvm.PointerType(tm.ctx.Int8Type(), 0)) 1131 } 1132 1133 func (tm *TypeMap) appendGcInsts(insts []llvm.Value, t types.Type, offset, stackSize int64) []llvm.Value { 1134 switch u := t.Underlying().(type) { 1135 case *types.Basic: 1136 switch u.Kind() { 1137 case types.String: 1138 insts = append(insts, tm.makeGcInst(gcOpcodeSTRING), tm.makeGcInst(offset)) 1139 case types.UnsafePointer: 1140 insts = append(insts, tm.makeGcInst(gcOpcodeAPTR), tm.makeGcInst(offset)) 1141 } 1142 case *types.Pointer: 1143 insts = append(insts, tm.makeGcInst(gcOpcodePTR), tm.makeGcInst(offset), 1144 tm.getGcPointer(u.Elem())) 1145 case *types.Signature, *types.Map: 1146 insts = append(insts, tm.makeGcInst(gcOpcodeAPTR), tm.makeGcInst(offset)) 1147 case *types.Array: 1148 if u.Len() == 0 { 1149 return insts 1150 } else if stackSize >= gcStackCapacity { 1151 insts = append(insts, tm.makeGcInst(gcOpcodeREGION), tm.makeGcInst(offset), 1152 tm.makeGcInst(tm.Sizeof(t)), tm.getGcPointer(t)) 1153 } else { 1154 insts = append(insts, tm.makeGcInst(gcOpcodeARRAY_START), tm.makeGcInst(offset), 1155 tm.makeGcInst(u.Len()), tm.makeGcInst(tm.Sizeof(u.Elem()))) 1156 insts = tm.appendGcInsts(insts, u.Elem(), 0, stackSize+1) 1157 insts = append(insts, tm.makeGcInst(gcOpcodeARRAY_NEXT)) 1158 } 1159 case *types.Slice: 1160 if tm.Sizeof(u.Elem()) == 0 { 1161 insts = append(insts, tm.makeGcInst(gcOpcodeAPTR), tm.makeGcInst(offset)) 1162 } else { 1163 insts = append(insts, tm.makeGcInst(gcOpcodeSLICE), tm.makeGcInst(offset), 1164 tm.getGcPointer(u.Elem())) 1165 } 1166 case *types.Chan: 1167 insts = append(insts, tm.makeGcInst(gcOpcodeCHAN_PTR), tm.makeGcInst(offset), 1168 tm.ToRuntime(t)) 1169 case *types.Struct: 1170 fields := make([]*types.Var, u.NumFields()) 1171 for i := range fields { 1172 fields[i] = u.Field(i) 1173 } 1174 offsets := tm.Offsetsof(fields) 1175 1176 for i, field := range fields { 1177 insts = tm.appendGcInsts(insts, field.Type(), offset+offsets[i], stackSize) 1178 } 1179 case *types.Interface: 1180 if u.NumMethods() == 0 { 1181 insts = append(insts, tm.makeGcInst(gcOpcodeEFACE), tm.makeGcInst(offset)) 1182 } else { 1183 insts = append(insts, tm.makeGcInst(gcOpcodeIFACE), tm.makeGcInst(offset)) 1184 } 1185 default: 1186 panic(fmt.Sprintf("unhandled type: %#v", t)) 1187 } 1188 1189 return insts 1190 } 1191 1192 func (tm *TypeMap) emitTypeDescInitializer(t types.Type, tdi *typeDescInfo) { 1193 // initialize type descriptor 1194 tdi.global.SetInitializer(tm.makeTypeDescInitializer(t)) 1195 1196 // initialize GC program 1197 insts := []llvm.Value{tm.makeGcInst(tm.Sizeof(t))} 1198 insts = tm.appendGcInsts(insts, t, 0, 0) 1199 insts = append(insts, tm.makeGcInst(gcOpcodeEND)) 1200 1201 i8ptr := llvm.PointerType(llvm.Int8Type(), 0) 1202 instArray := llvm.ConstArray(i8ptr, insts) 1203 1204 newGc := llvm.AddGlobal(tm.module, instArray.Type(), "") 1205 newGc.SetGlobalConstant(true) 1206 newGc.SetInitializer(instArray) 1207 gcName := tdi.gc.Name() 1208 tdi.gc.SetName("") 1209 newGc.SetName(gcName) 1210 newGc.SetLinkage(tdi.gc.Linkage()) 1211 1212 tdi.gc.ReplaceAllUsesWith(llvm.ConstBitCast(newGc, tdi.gc.Type())) 1213 tdi.gc.EraseFromParentAsGlobal() 1214 tdi.gc = llvm.Value{nil} 1215 tdi.gcPtr = llvm.ConstBitCast(newGc, i8ptr) 1216 } 1217 1218 func (tm *TypeMap) makeTypeDescInitializer(t types.Type) llvm.Value { 1219 switch u := t.Underlying().(type) { 1220 case *types.Basic: 1221 return tm.makeBasicType(t, u) 1222 case *types.Pointer: 1223 return tm.makePointerType(t, u) 1224 case *types.Signature: 1225 return tm.makeFuncType(t, u) 1226 case *types.Array: 1227 return tm.makeArrayType(t, u) 1228 case *types.Slice: 1229 return tm.makeSliceType(t, u) 1230 case *types.Map: 1231 return tm.makeMapType(t, u) 1232 case *types.Chan: 1233 return tm.makeChanType(t, u) 1234 case *types.Struct: 1235 return tm.makeStructType(t, u) 1236 case *types.Interface: 1237 return tm.makeInterfaceType(t, u) 1238 default: 1239 panic(fmt.Sprintf("unhandled type: %#v", t)) 1240 } 1241 } 1242 1243 func (tm *TypeMap) getStructAlgorithms(st *types.Struct) algorithms { 1244 if algs, ok := tm.algs.At(st).(algorithms); ok { 1245 return algs 1246 } 1247 1248 hashes := make([]llvm.Value, st.NumFields()) 1249 equals := make([]llvm.Value, st.NumFields()) 1250 1251 for i := range hashes { 1252 algs := tm.getAlgorithms(st.Field(i).Type()) 1253 if algs.hashDescriptor == tm.algsError.hashDescriptor { 1254 return algs 1255 } 1256 hashes[i], equals[i] = algs.hash, algs.equal 1257 } 1258 1259 i8ptr := llvm.PointerType(tm.ctx.Int8Type(), 0) 1260 llsptrty := llvm.PointerType(tm.ToLLVM(st), 0) 1261 1262 builder := tm.ctx.NewBuilder() 1263 defer builder.Dispose() 1264 1265 hashFunctionName := tm.mc.mangleHashFunctionName(st) 1266 hash := llvm.AddFunction(tm.module, hashFunctionName, tm.hashFnType) 1267 hash.SetLinkage(llvm.LinkOnceODRLinkage) 1268 hashDescriptor := tm.createAlgorithmDescriptor(hashFunctionName+"_descriptor", hash) 1269 1270 builder.SetInsertPointAtEnd(llvm.AddBasicBlock(hash, "entry")) 1271 sptr := builder.CreateBitCast(hash.Param(0), llsptrty, "") 1272 1273 hashval := llvm.ConstNull(tm.inttype) 1274 i33 := llvm.ConstInt(tm.inttype, 33, false) 1275 1276 for i, fhash := range hashes { 1277 fptr := builder.CreateStructGEP(sptr, i, "") 1278 fptr = builder.CreateBitCast(fptr, i8ptr, "") 1279 fsize := llvm.ConstInt(tm.inttype, uint64(tm.sizes.Sizeof(st.Field(i).Type())), false) 1280 hashcall := builder.CreateCall(fhash, []llvm.Value{fptr, fsize}, "") 1281 hashval = builder.CreateMul(hashval, i33, "") 1282 hashval = builder.CreateAdd(hashval, hashcall, "") 1283 } 1284 1285 builder.CreateRet(hashval) 1286 1287 equalFunctionName := tm.mc.mangleEqualFunctionName(st) 1288 equal := llvm.AddFunction(tm.module, equalFunctionName, tm.equalFnType) 1289 equal.SetLinkage(llvm.LinkOnceODRLinkage) 1290 equalDescriptor := tm.createAlgorithmDescriptor(equalFunctionName+"_descriptor", equal) 1291 1292 eqentrybb := llvm.AddBasicBlock(equal, "entry") 1293 eqretzerobb := llvm.AddBasicBlock(equal, "retzero") 1294 builder.SetInsertPointAtEnd(eqentrybb) 1295 s1ptr := builder.CreateBitCast(equal.Param(0), llsptrty, "") 1296 s2ptr := builder.CreateBitCast(equal.Param(1), llsptrty, "") 1297 1298 zerobool := llvm.ConstNull(tm.ctx.Int8Type()) 1299 onebool := llvm.ConstInt(tm.ctx.Int8Type(), 1, false) 1300 1301 for i, fequal := range equals { 1302 f1ptr := builder.CreateStructGEP(s1ptr, i, "") 1303 f1ptr = builder.CreateBitCast(f1ptr, i8ptr, "") 1304 f2ptr := builder.CreateStructGEP(s2ptr, i, "") 1305 f2ptr = builder.CreateBitCast(f2ptr, i8ptr, "") 1306 fsize := llvm.ConstInt(tm.inttype, uint64(tm.sizes.Sizeof(st.Field(i).Type())), false) 1307 equalcall := builder.CreateCall(fequal, []llvm.Value{f1ptr, f2ptr, fsize}, "") 1308 equaleqzero := builder.CreateICmp(llvm.IntEQ, equalcall, zerobool, "") 1309 contbb := llvm.AddBasicBlock(equal, "cont") 1310 builder.CreateCondBr(equaleqzero, eqretzerobb, contbb) 1311 builder.SetInsertPointAtEnd(contbb) 1312 } 1313 1314 builder.CreateRet(onebool) 1315 1316 builder.SetInsertPointAtEnd(eqretzerobb) 1317 builder.CreateRet(zerobool) 1318 1319 algs := algorithms{ 1320 hash: hash, 1321 hashDescriptor: hashDescriptor, 1322 equal: equal, 1323 equalDescriptor: equalDescriptor, 1324 } 1325 tm.algs.Set(st, algs) 1326 return algs 1327 } 1328 1329 func (tm *TypeMap) getArrayAlgorithms(at *types.Array) algorithms { 1330 if algs, ok := tm.algs.At(at).(algorithms); ok { 1331 return algs 1332 } 1333 1334 elemAlgs := tm.getAlgorithms(at.Elem()) 1335 if elemAlgs.hashDescriptor == tm.algsError.hashDescriptor { 1336 return elemAlgs 1337 } 1338 1339 i8ptr := llvm.PointerType(tm.ctx.Int8Type(), 0) 1340 llelemty := llvm.PointerType(tm.ToLLVM(at.Elem()), 0) 1341 1342 i1 := llvm.ConstInt(tm.inttype, 1, false) 1343 alen := llvm.ConstInt(tm.inttype, uint64(at.Len()), false) 1344 esize := llvm.ConstInt(tm.inttype, uint64(tm.sizes.Sizeof(at.Elem())), false) 1345 1346 builder := tm.ctx.NewBuilder() 1347 defer builder.Dispose() 1348 1349 hashFunctionName := tm.mc.mangleHashFunctionName(at) 1350 hash := llvm.AddFunction(tm.module, hashFunctionName, tm.hashFnType) 1351 hash.SetLinkage(llvm.LinkOnceODRLinkage) 1352 hashDescriptor := tm.createAlgorithmDescriptor(hashFunctionName+"_descriptor", hash) 1353 equalFunctionName := tm.mc.mangleHashFunctionName(at) 1354 equal := llvm.AddFunction(tm.module, equalFunctionName, tm.equalFnType) 1355 equal.SetLinkage(llvm.LinkOnceODRLinkage) 1356 equalDescriptor := tm.createAlgorithmDescriptor(equalFunctionName+"_descriptor", equal) 1357 algs := algorithms{ 1358 hash: hash, 1359 hashDescriptor: hashDescriptor, 1360 equal: equal, 1361 equalDescriptor: equalDescriptor, 1362 } 1363 tm.algs.Set(at, algs) 1364 1365 hashentrybb := llvm.AddBasicBlock(hash, "entry") 1366 builder.SetInsertPointAtEnd(hashentrybb) 1367 if at.Len() == 0 { 1368 builder.CreateRet(llvm.ConstNull(tm.inttype)) 1369 } else { 1370 i33 := llvm.ConstInt(tm.inttype, 33, false) 1371 1372 aptr := builder.CreateBitCast(hash.Param(0), llelemty, "") 1373 loopbb := llvm.AddBasicBlock(hash, "loop") 1374 builder.CreateBr(loopbb) 1375 1376 exitbb := llvm.AddBasicBlock(hash, "exit") 1377 1378 builder.SetInsertPointAtEnd(loopbb) 1379 indexphi := builder.CreatePHI(tm.inttype, "") 1380 index := indexphi 1381 hashvalphi := builder.CreatePHI(tm.inttype, "") 1382 hashval := hashvalphi 1383 1384 eptr := builder.CreateGEP(aptr, []llvm.Value{index}, "") 1385 eptr = builder.CreateBitCast(eptr, i8ptr, "") 1386 1387 hashcall := builder.CreateCall(elemAlgs.hash, []llvm.Value{eptr, esize}, "") 1388 hashval = builder.CreateMul(hashval, i33, "") 1389 hashval = builder.CreateAdd(hashval, hashcall, "") 1390 1391 index = builder.CreateAdd(index, i1, "") 1392 1393 indexphi.AddIncoming( 1394 []llvm.Value{llvm.ConstNull(tm.inttype), index}, 1395 []llvm.BasicBlock{hashentrybb, loopbb}, 1396 ) 1397 hashvalphi.AddIncoming( 1398 []llvm.Value{llvm.ConstNull(tm.inttype), hashval}, 1399 []llvm.BasicBlock{hashentrybb, loopbb}, 1400 ) 1401 1402 exit := builder.CreateICmp(llvm.IntEQ, index, alen, "") 1403 builder.CreateCondBr(exit, exitbb, loopbb) 1404 1405 builder.SetInsertPointAtEnd(exitbb) 1406 builder.CreateRet(hashval) 1407 } 1408 1409 zerobool := llvm.ConstNull(tm.ctx.Int8Type()) 1410 onebool := llvm.ConstInt(tm.ctx.Int8Type(), 1, false) 1411 1412 eqentrybb := llvm.AddBasicBlock(equal, "entry") 1413 builder.SetInsertPointAtEnd(eqentrybb) 1414 if at.Len() == 0 { 1415 builder.CreateRet(onebool) 1416 } else { 1417 a1ptr := builder.CreateBitCast(equal.Param(0), llelemty, "") 1418 a2ptr := builder.CreateBitCast(equal.Param(1), llelemty, "") 1419 loopbb := llvm.AddBasicBlock(equal, "loop") 1420 builder.CreateBr(loopbb) 1421 1422 exitbb := llvm.AddBasicBlock(equal, "exit") 1423 retzerobb := llvm.AddBasicBlock(equal, "retzero") 1424 1425 builder.SetInsertPointAtEnd(loopbb) 1426 indexphi := builder.CreatePHI(tm.inttype, "") 1427 index := indexphi 1428 1429 e1ptr := builder.CreateGEP(a1ptr, []llvm.Value{index}, "") 1430 e1ptr = builder.CreateBitCast(e1ptr, i8ptr, "") 1431 e2ptr := builder.CreateGEP(a2ptr, []llvm.Value{index}, "") 1432 e2ptr = builder.CreateBitCast(e2ptr, i8ptr, "") 1433 1434 equalcall := builder.CreateCall(elemAlgs.equal, []llvm.Value{e1ptr, e2ptr, esize}, "") 1435 equaleqzero := builder.CreateICmp(llvm.IntEQ, equalcall, zerobool, "") 1436 1437 contbb := llvm.AddBasicBlock(equal, "cont") 1438 builder.CreateCondBr(equaleqzero, retzerobb, contbb) 1439 1440 builder.SetInsertPointAtEnd(contbb) 1441 1442 index = builder.CreateAdd(index, i1, "") 1443 1444 indexphi.AddIncoming( 1445 []llvm.Value{llvm.ConstNull(tm.inttype), index}, 1446 []llvm.BasicBlock{eqentrybb, contbb}, 1447 ) 1448 1449 exit := builder.CreateICmp(llvm.IntEQ, index, alen, "") 1450 builder.CreateCondBr(exit, exitbb, loopbb) 1451 1452 builder.SetInsertPointAtEnd(exitbb) 1453 builder.CreateRet(onebool) 1454 1455 builder.SetInsertPointAtEnd(retzerobb) 1456 builder.CreateRet(zerobool) 1457 } 1458 1459 return algs 1460 } 1461 1462 func (tm *TypeMap) createAlgorithmDescriptor(name string, fn llvm.Value) llvm.Value { 1463 d := llvm.AddGlobal(tm.module, tm.funcValType, name) 1464 d.SetLinkage(llvm.LinkOnceODRLinkage) 1465 d.SetGlobalConstant(true) 1466 fn = llvm.ConstBitCast(fn, tm.funcValType.StructElementTypes()[0]) 1467 init := llvm.ConstNull(tm.funcValType) 1468 init = llvm.ConstInsertValue(init, fn, []uint32{0}) 1469 d.SetInitializer(init) 1470 return d 1471 } 1472 1473 func (tm *TypeMap) getAlgorithms(t types.Type) algorithms { 1474 switch t := t.Underlying().(type) { 1475 case *types.Interface: 1476 if t.NumMethods() == 0 { 1477 return tm.algsEmptyInterface 1478 } 1479 return tm.algsInterface 1480 case *types.Basic: 1481 switch t.Kind() { 1482 case types.Float32, types.Float64: 1483 return tm.algsFloat 1484 case types.Complex64, types.Complex128: 1485 return tm.algsComplex 1486 case types.String: 1487 return tm.algsString 1488 } 1489 return tm.algsIdentity 1490 case *types.Signature, *types.Map, *types.Slice: 1491 return tm.algsError 1492 case *types.Struct: 1493 return tm.getStructAlgorithms(t) 1494 case *types.Array: 1495 return tm.getArrayAlgorithms(t) 1496 } 1497 return tm.algsIdentity 1498 } 1499 1500 func (tm *TypeMap) getTypeDescInfo(t types.Type) *typeDescInfo { 1501 if tdi, ok := tm.types.At(t).(*typeDescInfo); ok { 1502 return tdi 1503 } 1504 1505 var b bytes.Buffer 1506 tm.mc.mangleTypeDescriptorName(t, &b) 1507 1508 global := llvm.AddGlobal(tm.module, tm.getTypeDescType(t), b.String()) 1509 global.SetGlobalConstant(true) 1510 ptr := llvm.ConstBitCast(global, llvm.PointerType(tm.commonTypeType, 0)) 1511 1512 gc := llvm.AddGlobal(tm.module, llvm.PointerType(llvm.Int8Type(), 0), b.String()+"$gc") 1513 gc.SetGlobalConstant(true) 1514 gcPtr := llvm.ConstBitCast(gc, llvm.PointerType(tm.ctx.Int8Type(), 0)) 1515 1516 var mapDescPtr llvm.Value 1517 if m, ok := t.Underlying().(*types.Map); ok { 1518 var mapb bytes.Buffer 1519 tm.mc.mangleMapDescriptorName(t, &mapb) 1520 1521 mapDescPtr = llvm.AddGlobal(tm.module, tm.mapDescType, mapb.String()) 1522 mapDescPtr.SetGlobalConstant(true) 1523 mapDescPtr.SetLinkage(llvm.LinkOnceODRLinkage) 1524 mapDescPtr.SetInitializer(tm.makeMapDesc(ptr, m)) 1525 } 1526 1527 tdi := &typeDescInfo{ 1528 global: global, 1529 commonTypePtr: ptr, 1530 mapDescPtr: mapDescPtr, 1531 gc: gc, 1532 gcPtr: gcPtr, 1533 } 1534 tm.types.Set(t, tdi) 1535 return tdi 1536 } 1537 1538 func (tm *TypeMap) getTypeDescriptorPointer(t types.Type) llvm.Value { 1539 return tm.getTypeDescInfo(t).commonTypePtr 1540 } 1541 1542 func (tm *TypeMap) getMapDescriptorPointer(t types.Type) llvm.Value { 1543 return tm.getTypeDescInfo(t).mapDescPtr 1544 } 1545 1546 func (tm *TypeMap) getGcPointer(t types.Type) llvm.Value { 1547 return tm.getTypeDescInfo(t).gcPtr 1548 } 1549 1550 func (tm *TypeMap) getItabPointer(srctype types.Type, targettype *types.Interface) llvm.Value { 1551 if targettype.NumMethods() == 0 { 1552 return tm.ToRuntime(srctype) 1553 } else { 1554 return tm.getImtPointer(srctype, targettype) 1555 } 1556 } 1557 1558 func (tm *TypeMap) getImtPointer(srctype types.Type, targettype *types.Interface) llvm.Value { 1559 tdi := tm.getTypeDescInfo(srctype) 1560 1561 if ptr, ok := tdi.interfaceMethodTables.At(targettype).(llvm.Value); ok { 1562 return ptr 1563 } 1564 1565 srcms := tm.MethodSet(srctype) 1566 targetms := tm.MethodSet(targettype) 1567 1568 i8ptr := llvm.PointerType(llvm.Int8Type(), 0) 1569 1570 elems := make([]llvm.Value, targetms.Len()+1) 1571 elems[0] = tm.ToRuntime(srctype) 1572 for i, targetm := range orderedMethodSet(targetms) { 1573 srcm := srcms.Lookup(targetm.Obj().Pkg(), targetm.Obj().Name()) 1574 1575 elems[i+1] = tm.methodResolver.ResolveMethod(srcm).value 1576 } 1577 imtinit := llvm.ConstArray(i8ptr, elems) 1578 1579 var b bytes.Buffer 1580 tm.mc.mangleImtName(srctype, targettype, &b) 1581 imt := llvm.AddGlobal(tm.module, imtinit.Type(), b.String()) 1582 imt.SetGlobalConstant(true) 1583 imt.SetInitializer(imtinit) 1584 imt.SetLinkage(llvm.LinkOnceODRLinkage) 1585 1586 imtptr := llvm.ConstBitCast(imt, i8ptr) 1587 tdi.interfaceMethodTables.Set(targettype, imtptr) 1588 return imtptr 1589 } 1590 1591 const ( 1592 // From gofrontend/types.h 1593 gccgoRuntimeTypeKindBOOL = 1 1594 gccgoRuntimeTypeKindINT = 2 1595 gccgoRuntimeTypeKindINT8 = 3 1596 gccgoRuntimeTypeKindINT16 = 4 1597 gccgoRuntimeTypeKindINT32 = 5 1598 gccgoRuntimeTypeKindINT64 = 6 1599 gccgoRuntimeTypeKindUINT = 7 1600 gccgoRuntimeTypeKindUINT8 = 8 1601 gccgoRuntimeTypeKindUINT16 = 9 1602 gccgoRuntimeTypeKindUINT32 = 10 1603 gccgoRuntimeTypeKindUINT64 = 11 1604 gccgoRuntimeTypeKindUINTPTR = 12 1605 gccgoRuntimeTypeKindFLOAT32 = 13 1606 gccgoRuntimeTypeKindFLOAT64 = 14 1607 gccgoRuntimeTypeKindCOMPLEX64 = 15 1608 gccgoRuntimeTypeKindCOMPLEX128 = 16 1609 gccgoRuntimeTypeKindARRAY = 17 1610 gccgoRuntimeTypeKindCHAN = 18 1611 gccgoRuntimeTypeKindFUNC = 19 1612 gccgoRuntimeTypeKindINTERFACE = 20 1613 gccgoRuntimeTypeKindMAP = 21 1614 gccgoRuntimeTypeKindPTR = 22 1615 gccgoRuntimeTypeKindSLICE = 23 1616 gccgoRuntimeTypeKindSTRING = 24 1617 gccgoRuntimeTypeKindSTRUCT = 25 1618 gccgoRuntimeTypeKindUNSAFE_POINTER = 26 1619 gccgoRuntimeTypeKindDIRECT_IFACE = (1 << 5) 1620 gccgoRuntimeTypeKindNO_POINTERS = (1 << 7) 1621 ) 1622 1623 func hasPointers(t types.Type) bool { 1624 switch t := t.(type) { 1625 case *types.Basic: 1626 return t.Kind() == types.String || t.Kind() == types.UnsafePointer 1627 1628 case *types.Signature, *types.Pointer, *types.Slice, *types.Map, *types.Chan, *types.Interface: 1629 return true 1630 1631 case *types.Struct: 1632 for i := 0; i != t.NumFields(); i++ { 1633 if hasPointers(t.Field(i).Type()) { 1634 return true 1635 } 1636 } 1637 return false 1638 1639 case *types.Named: 1640 return hasPointers(t.Underlying()) 1641 1642 case *types.Array: 1643 return hasPointers(t.Elem()) 1644 1645 default: 1646 panic("unrecognized type") 1647 } 1648 } 1649 1650 func runtimeTypeKind(t types.Type) (k uint8) { 1651 switch t := t.(type) { 1652 case *types.Basic: 1653 switch t.Kind() { 1654 case types.Bool: 1655 k = gccgoRuntimeTypeKindBOOL 1656 case types.Int: 1657 k = gccgoRuntimeTypeKindINT 1658 case types.Int8: 1659 k = gccgoRuntimeTypeKindINT8 1660 case types.Int16: 1661 k = gccgoRuntimeTypeKindINT16 1662 case types.Int32: 1663 k = gccgoRuntimeTypeKindINT32 1664 case types.Int64: 1665 k = gccgoRuntimeTypeKindINT64 1666 case types.Uint: 1667 k = gccgoRuntimeTypeKindUINT 1668 case types.Uint8: 1669 k = gccgoRuntimeTypeKindUINT8 1670 case types.Uint16: 1671 k = gccgoRuntimeTypeKindUINT16 1672 case types.Uint32: 1673 k = gccgoRuntimeTypeKindUINT32 1674 case types.Uint64: 1675 k = gccgoRuntimeTypeKindUINT64 1676 case types.Uintptr: 1677 k = gccgoRuntimeTypeKindUINTPTR 1678 case types.Float32: 1679 k = gccgoRuntimeTypeKindFLOAT32 1680 case types.Float64: 1681 k = gccgoRuntimeTypeKindFLOAT64 1682 case types.Complex64: 1683 k = gccgoRuntimeTypeKindCOMPLEX64 1684 case types.Complex128: 1685 k = gccgoRuntimeTypeKindCOMPLEX128 1686 case types.String: 1687 k = gccgoRuntimeTypeKindSTRING 1688 case types.UnsafePointer: 1689 k = gccgoRuntimeTypeKindUNSAFE_POINTER | gccgoRuntimeTypeKindDIRECT_IFACE 1690 default: 1691 panic("unrecognized builtin type") 1692 } 1693 case *types.Array: 1694 k = gccgoRuntimeTypeKindARRAY 1695 case *types.Slice: 1696 k = gccgoRuntimeTypeKindSLICE 1697 case *types.Struct: 1698 k = gccgoRuntimeTypeKindSTRUCT 1699 case *types.Pointer: 1700 k = gccgoRuntimeTypeKindPTR | gccgoRuntimeTypeKindDIRECT_IFACE 1701 case *types.Signature: 1702 k = gccgoRuntimeTypeKindFUNC 1703 case *types.Interface: 1704 k = gccgoRuntimeTypeKindINTERFACE 1705 case *types.Map: 1706 k = gccgoRuntimeTypeKindMAP 1707 case *types.Chan: 1708 k = gccgoRuntimeTypeKindCHAN 1709 case *types.Named: 1710 return runtimeTypeKind(t.Underlying()) 1711 default: 1712 panic("unrecognized type") 1713 } 1714 1715 if !hasPointers(t) { 1716 k |= gccgoRuntimeTypeKindNO_POINTERS 1717 } 1718 1719 return 1720 } 1721 1722 func (tm *TypeMap) makeCommonType(t types.Type) llvm.Value { 1723 var vals [11]llvm.Value 1724 vals[0] = llvm.ConstInt(tm.ctx.Int8Type(), uint64(runtimeTypeKind(t)), false) 1725 vals[1] = llvm.ConstInt(tm.ctx.Int8Type(), uint64(tm.Alignof(t)), false) 1726 vals[2] = vals[1] 1727 vals[3] = llvm.ConstInt(tm.inttype, uint64(tm.Sizeof(t)), false) 1728 vals[4] = llvm.ConstInt(tm.ctx.Int32Type(), uint64(tm.getTypeHash(t)), false) 1729 algs := tm.getAlgorithms(t) 1730 vals[5] = algs.hashDescriptor 1731 vals[6] = algs.equalDescriptor 1732 vals[7] = tm.getGcPointer(t) 1733 var b bytes.Buffer 1734 tm.writeType(t, &b) 1735 vals[8] = tm.globalStringPtr(b.String()) 1736 vals[9] = tm.makeUncommonTypePtr(t) 1737 switch t.(type) { 1738 case *types.Named, *types.Struct: 1739 vals[10] = tm.getTypeDescriptorPointer(types.NewPointer(t)) 1740 default: 1741 vals[10] = llvm.ConstPointerNull(llvm.PointerType(tm.commonTypeType, 0)) 1742 } 1743 return llvm.ConstNamedStruct(tm.commonTypeType, vals[:]) 1744 } 1745 1746 func (tm *TypeMap) makeBasicType(t types.Type, u *types.Basic) llvm.Value { 1747 return tm.makeCommonType(t) 1748 } 1749 1750 func (tm *TypeMap) makeArrayType(t types.Type, a *types.Array) llvm.Value { 1751 var vals [4]llvm.Value 1752 vals[0] = tm.makeCommonType(t) 1753 vals[1] = tm.getTypeDescriptorPointer(a.Elem()) 1754 vals[2] = tm.getTypeDescriptorPointer(types.NewSlice(a.Elem())) 1755 vals[3] = llvm.ConstInt(tm.inttype, uint64(a.Len()), false) 1756 1757 return llvm.ConstNamedStruct(tm.arrayTypeType, vals[:]) 1758 } 1759 1760 func (tm *TypeMap) makeSliceType(t types.Type, s *types.Slice) llvm.Value { 1761 var vals [2]llvm.Value 1762 vals[0] = tm.makeCommonType(t) 1763 vals[1] = tm.getTypeDescriptorPointer(s.Elem()) 1764 1765 return llvm.ConstNamedStruct(tm.sliceTypeType, vals[:]) 1766 } 1767 1768 func (tm *TypeMap) makeStructType(t types.Type, s *types.Struct) llvm.Value { 1769 var vals [2]llvm.Value 1770 vals[0] = tm.makeCommonType(t) 1771 1772 fieldVars := make([]*types.Var, s.NumFields()) 1773 for i := range fieldVars { 1774 fieldVars[i] = s.Field(i) 1775 } 1776 offsets := tm.Offsetsof(fieldVars) 1777 structFields := make([]llvm.Value, len(fieldVars)) 1778 for i, field := range fieldVars { 1779 var sfvals [5]llvm.Value 1780 if !field.Anonymous() { 1781 sfvals[0] = tm.globalStringPtr(field.Name()) 1782 } else { 1783 sfvals[0] = llvm.ConstPointerNull(llvm.PointerType(tm.stringType, 0)) 1784 } 1785 if !field.Exported() && field.Pkg() != nil { 1786 sfvals[1] = tm.globalStringPtr(field.Pkg().Path()) 1787 } else { 1788 sfvals[1] = llvm.ConstPointerNull(llvm.PointerType(tm.stringType, 0)) 1789 } 1790 sfvals[2] = tm.getTypeDescriptorPointer(field.Type()) 1791 if tag := s.Tag(i); tag != "" { 1792 sfvals[3] = tm.globalStringPtr(tag) 1793 } else { 1794 sfvals[3] = llvm.ConstPointerNull(llvm.PointerType(tm.stringType, 0)) 1795 } 1796 sfvals[4] = llvm.ConstInt(tm.inttype, uint64(offsets[i]), false) 1797 1798 structFields[i] = llvm.ConstNamedStruct(tm.structFieldType, sfvals[:]) 1799 } 1800 vals[1] = tm.makeSlice(structFields, tm.structFieldSliceType) 1801 1802 return llvm.ConstNamedStruct(tm.structTypeType, vals[:]) 1803 } 1804 1805 func (tm *TypeMap) makePointerType(t types.Type, p *types.Pointer) llvm.Value { 1806 var vals [2]llvm.Value 1807 vals[0] = tm.makeCommonType(t) 1808 vals[1] = tm.getTypeDescriptorPointer(p.Elem()) 1809 1810 return llvm.ConstNamedStruct(tm.ptrTypeType, vals[:]) 1811 } 1812 1813 func (tm *TypeMap) rtypeSlice(t *types.Tuple) llvm.Value { 1814 rtypes := make([]llvm.Value, t.Len()) 1815 for i := range rtypes { 1816 rtypes[i] = tm.getTypeDescriptorPointer(t.At(i).Type()) 1817 } 1818 return tm.makeSlice(rtypes, tm.typeSliceType) 1819 } 1820 1821 func (tm *TypeMap) makeFuncType(t types.Type, f *types.Signature) llvm.Value { 1822 var vals [4]llvm.Value 1823 vals[0] = tm.makeCommonType(t) 1824 // dotdotdot 1825 variadic := 0 1826 if f.Variadic() { 1827 variadic = 1 1828 } 1829 vals[1] = llvm.ConstInt(llvm.Int8Type(), uint64(variadic), false) 1830 // in 1831 vals[2] = tm.rtypeSlice(f.Params()) 1832 // out 1833 vals[3] = tm.rtypeSlice(f.Results()) 1834 1835 return llvm.ConstNamedStruct(tm.funcTypeType, vals[:]) 1836 } 1837 1838 func (tm *TypeMap) makeInterfaceType(t types.Type, i *types.Interface) llvm.Value { 1839 var vals [2]llvm.Value 1840 vals[0] = tm.makeCommonType(t) 1841 1842 methodset := tm.MethodSet(i) 1843 imethods := make([]llvm.Value, methodset.Len()) 1844 for index, ms := range orderedMethodSet(methodset) { 1845 method := ms.Obj() 1846 var imvals [3]llvm.Value 1847 imvals[0] = tm.globalStringPtr(method.Name()) 1848 if !method.Exported() && method.Pkg() != nil { 1849 imvals[1] = tm.globalStringPtr(method.Pkg().Path()) 1850 } else { 1851 imvals[1] = llvm.ConstPointerNull(llvm.PointerType(tm.stringType, 0)) 1852 } 1853 mtyp := method.Type().(*types.Signature) 1854 mftyp := types.NewSignature(nil, nil, mtyp.Params(), mtyp.Results(), mtyp.Variadic()) 1855 imvals[2] = tm.getTypeDescriptorPointer(mftyp) 1856 1857 imethods[index] = llvm.ConstNamedStruct(tm.imethodType, imvals[:]) 1858 } 1859 vals[1] = tm.makeSlice(imethods, tm.imethodSliceType) 1860 1861 return llvm.ConstNamedStruct(tm.interfaceTypeType, vals[:]) 1862 } 1863 1864 func (tm *TypeMap) makeMapType(t types.Type, m *types.Map) llvm.Value { 1865 var vals [3]llvm.Value 1866 vals[0] = tm.makeCommonType(t) 1867 vals[1] = tm.getTypeDescriptorPointer(m.Key()) 1868 vals[2] = tm.getTypeDescriptorPointer(m.Elem()) 1869 1870 return llvm.ConstNamedStruct(tm.mapTypeType, vals[:]) 1871 } 1872 1873 func (tm *TypeMap) makeMapDesc(ptr llvm.Value, m *types.Map) llvm.Value { 1874 mapEntryType := structBType{[]backendType{ 1875 tm.getBackendType(types.Typ[types.UnsafePointer]), 1876 tm.getBackendType(m.Key()), 1877 tm.getBackendType(m.Elem()), 1878 }}.ToLLVM(tm.ctx) 1879 1880 var vals [4]llvm.Value 1881 // map_descriptor 1882 vals[0] = ptr 1883 // entry_size 1884 vals[1] = llvm.ConstInt(tm.inttype, tm.target.TypeAllocSize(mapEntryType), false) 1885 // key_offset 1886 vals[2] = llvm.ConstInt(tm.inttype, tm.target.ElementOffset(mapEntryType, 1), false) 1887 // value_offset 1888 vals[3] = llvm.ConstInt(tm.inttype, tm.target.ElementOffset(mapEntryType, 2), false) 1889 1890 return llvm.ConstNamedStruct(tm.mapDescType, vals[:]) 1891 } 1892 1893 func (tm *TypeMap) makeChanType(t types.Type, c *types.Chan) llvm.Value { 1894 var vals [3]llvm.Value 1895 vals[0] = tm.makeCommonType(t) 1896 vals[1] = tm.getTypeDescriptorPointer(c.Elem()) 1897 1898 // From gofrontend/go/types.cc 1899 // These bits must match the ones in libgo/runtime/go-type.h. 1900 var dir int 1901 switch c.Dir() { 1902 case types.RecvOnly: 1903 dir = 1 1904 case types.SendOnly: 1905 dir = 2 1906 case types.SendRecv: 1907 dir = 3 1908 } 1909 vals[2] = llvm.ConstInt(tm.inttype, uint64(dir), false) 1910 1911 return llvm.ConstNamedStruct(tm.chanTypeType, vals[:]) 1912 } 1913 1914 func (tm *TypeMap) makeUncommonTypePtr(t types.Type) llvm.Value { 1915 _, isbasic := t.(*types.Basic) 1916 _, isnamed := t.(*types.Named) 1917 1918 var mset types.MethodSet 1919 // We store interface methods on the interface type. 1920 if _, ok := t.Underlying().(*types.Interface); !ok { 1921 mset = *tm.MethodSet(t) 1922 } 1923 1924 if !isbasic && !isnamed && mset.Len() == 0 { 1925 return llvm.ConstPointerNull(llvm.PointerType(tm.uncommonTypeType, 0)) 1926 } 1927 1928 var vals [3]llvm.Value 1929 1930 nullStringPtr := llvm.ConstPointerNull(llvm.PointerType(tm.stringType, 0)) 1931 vals[0] = nullStringPtr 1932 vals[1] = nullStringPtr 1933 1934 if isbasic || isnamed { 1935 nti := tm.mc.getNamedTypeInfo(t) 1936 vals[0] = tm.globalStringPtr(nti.name) 1937 if nti.pkgpath != "" { 1938 path := nti.pkgpath 1939 if nti.functionName != "" { 1940 path += "." + nti.functionName 1941 if nti.scopeNum != 0 { 1942 path += "$" + strconv.Itoa(nti.scopeNum) 1943 } 1944 } 1945 vals[1] = tm.globalStringPtr(path) 1946 } 1947 } 1948 1949 // Store methods. All methods must be stored, not only exported ones; 1950 // this is to allow satisfying of interfaces with non-exported methods. 1951 methods := make([]llvm.Value, mset.Len()) 1952 omset := orderedMethodSet(&mset) 1953 for i := range methods { 1954 var mvals [5]llvm.Value 1955 1956 sel := omset[i] 1957 mname := sel.Obj().Name() 1958 mfunc := tm.methodResolver.ResolveMethod(sel) 1959 ftyp := mfunc.Type().(*types.Signature) 1960 1961 // name 1962 mvals[0] = tm.globalStringPtr(mname) 1963 1964 // pkgPath 1965 mvals[1] = nullStringPtr 1966 if pkg := sel.Obj().Pkg(); pkg != nil && !sel.Obj().Exported() { 1967 mvals[1] = tm.globalStringPtr(pkg.Path()) 1968 } 1969 1970 // mtyp (method type, no receiver) 1971 mftyp := types.NewSignature(nil, nil, ftyp.Params(), ftyp.Results(), ftyp.Variadic()) 1972 mvals[2] = tm.getTypeDescriptorPointer(mftyp) 1973 1974 // typ (function type, with receiver) 1975 recvparam := types.NewParam(0, nil, "", t) 1976 params := ftyp.Params() 1977 rfparams := make([]*types.Var, params.Len()+1) 1978 rfparams[0] = recvparam 1979 for i := 0; i != ftyp.Params().Len(); i++ { 1980 rfparams[i+1] = params.At(i) 1981 } 1982 rftyp := types.NewSignature(nil, nil, types.NewTuple(rfparams...), ftyp.Results(), ftyp.Variadic()) 1983 mvals[3] = tm.getTypeDescriptorPointer(rftyp) 1984 1985 // function 1986 mvals[4] = mfunc.value 1987 1988 methods[i] = llvm.ConstNamedStruct(tm.methodType, mvals[:]) 1989 } 1990 1991 vals[2] = tm.makeSlice(methods, tm.methodSliceType) 1992 1993 uncommonType := llvm.ConstNamedStruct(tm.uncommonTypeType, vals[:]) 1994 1995 uncommonTypePtr := llvm.AddGlobal(tm.module, tm.uncommonTypeType, "") 1996 uncommonTypePtr.SetGlobalConstant(true) 1997 uncommonTypePtr.SetInitializer(uncommonType) 1998 uncommonTypePtr.SetLinkage(llvm.InternalLinkage) 1999 return uncommonTypePtr 2000 } 2001 2002 // globalStringPtr returns a *string with the specified value. 2003 func (tm *TypeMap) globalStringPtr(value string) llvm.Value { 2004 strval := llvm.ConstString(value, false) 2005 strglobal := llvm.AddGlobal(tm.module, strval.Type(), "") 2006 strglobal.SetGlobalConstant(true) 2007 strglobal.SetLinkage(llvm.InternalLinkage) 2008 strglobal.SetInitializer(strval) 2009 strglobal = llvm.ConstBitCast(strglobal, llvm.PointerType(llvm.Int8Type(), 0)) 2010 strlen := llvm.ConstInt(tm.inttype, uint64(len(value)), false) 2011 str := llvm.ConstStruct([]llvm.Value{strglobal, strlen}, false) 2012 g := llvm.AddGlobal(tm.module, str.Type(), "") 2013 g.SetGlobalConstant(true) 2014 g.SetLinkage(llvm.InternalLinkage) 2015 g.SetInitializer(str) 2016 return g 2017 } 2018 2019 func (tm *TypeMap) makeNamedSliceType(tname string, elemtyp llvm.Type) llvm.Type { 2020 t := tm.ctx.StructCreateNamed(tname) 2021 t.StructSetBody([]llvm.Type{ 2022 llvm.PointerType(elemtyp, 0), 2023 tm.inttype, 2024 tm.inttype, 2025 }, false) 2026 return t 2027 } 2028 2029 func (tm *TypeMap) makeSlice(values []llvm.Value, slicetyp llvm.Type) llvm.Value { 2030 ptrtyp := slicetyp.StructElementTypes()[0] 2031 var globalptr llvm.Value 2032 if len(values) > 0 { 2033 array := llvm.ConstArray(ptrtyp.ElementType(), values) 2034 globalptr = llvm.AddGlobal(tm.module, array.Type(), "") 2035 globalptr.SetGlobalConstant(true) 2036 globalptr.SetLinkage(llvm.InternalLinkage) 2037 globalptr.SetInitializer(array) 2038 globalptr = llvm.ConstBitCast(globalptr, ptrtyp) 2039 } else { 2040 globalptr = llvm.ConstNull(ptrtyp) 2041 } 2042 len_ := llvm.ConstInt(tm.inttype, uint64(len(values)), false) 2043 slice := llvm.ConstNull(slicetyp) 2044 slice = llvm.ConstInsertValue(slice, globalptr, []uint32{0}) 2045 slice = llvm.ConstInsertValue(slice, len_, []uint32{1}) 2046 slice = llvm.ConstInsertValue(slice, len_, []uint32{2}) 2047 return slice 2048 } 2049 2050 func isGlobalObject(obj types.Object) bool { 2051 pkg := obj.Pkg() 2052 return pkg == nil || obj.Parent() == pkg.Scope() 2053 }