github.com/aykevl/tinygo@v0.5.0/compiler/compiler.go (about) 1 package compiler 2 3 import ( 4 "errors" 5 "fmt" 6 "go/build" 7 "go/constant" 8 "go/token" 9 "go/types" 10 "os" 11 "path/filepath" 12 "runtime" 13 "strconv" 14 "strings" 15 16 "github.com/tinygo-org/tinygo/ir" 17 "github.com/tinygo-org/tinygo/loader" 18 "golang.org/x/tools/go/ssa" 19 "tinygo.org/x/go-llvm" 20 ) 21 22 func init() { 23 llvm.InitializeAllTargets() 24 llvm.InitializeAllTargetMCs() 25 llvm.InitializeAllTargetInfos() 26 llvm.InitializeAllAsmParsers() 27 llvm.InitializeAllAsmPrinters() 28 } 29 30 // Configure the compiler. 31 type Config struct { 32 Triple string // LLVM target triple, e.g. x86_64-unknown-linux-gnu (empty string means default) 33 CPU string // LLVM CPU name, e.g. atmega328p (empty string means default) 34 GOOS string // 35 GOARCH string // 36 GC string // garbage collection strategy 37 CFlags []string // cflags to pass to cgo 38 LDFlags []string // ldflags to pass to cgo 39 DumpSSA bool // dump Go SSA, for compiler debugging 40 Debug bool // add debug symbols for gdb 41 RootDir string // GOROOT for TinyGo 42 GOPATH string // GOPATH, like `go env GOPATH` 43 BuildTags []string // build tags for TinyGo (empty means {Config.GOOS/Config.GOARCH}) 44 } 45 46 type Compiler struct { 47 Config 48 mod llvm.Module 49 ctx llvm.Context 50 builder llvm.Builder 51 dibuilder *llvm.DIBuilder 52 cu llvm.Metadata 53 difiles map[string]llvm.Metadata 54 ditypes map[string]llvm.Metadata 55 machine llvm.TargetMachine 56 targetData llvm.TargetData 57 intType llvm.Type 58 i8ptrType llvm.Type // for convenience 59 funcPtrAddrSpace int 60 uintptrType llvm.Type 61 initFuncs []llvm.Value 62 interfaceInvokeWrappers []interfaceInvokeWrapper 63 ir *ir.Program 64 } 65 66 type Frame struct { 67 fn *ir.Function 68 locals map[ssa.Value]llvm.Value // local variables 69 blockEntries map[*ssa.BasicBlock]llvm.BasicBlock // a *ssa.BasicBlock may be split up 70 blockExits map[*ssa.BasicBlock]llvm.BasicBlock // these are the exit blocks 71 currentBlock *ssa.BasicBlock 72 phis []Phi 73 taskHandle llvm.Value 74 deferPtr llvm.Value 75 difunc llvm.Metadata 76 allDeferFuncs []interface{} 77 deferFuncs map[*ir.Function]int 78 deferInvokeFuncs map[string]int 79 deferClosureFuncs map[*ir.Function]int 80 } 81 82 type Phi struct { 83 ssa *ssa.Phi 84 llvm llvm.Value 85 } 86 87 func NewCompiler(pkgName string, config Config) (*Compiler, error) { 88 if config.Triple == "" { 89 config.Triple = llvm.DefaultTargetTriple() 90 } 91 if len(config.BuildTags) == 0 { 92 config.BuildTags = []string{config.GOOS, config.GOARCH} 93 } 94 c := &Compiler{ 95 Config: config, 96 difiles: make(map[string]llvm.Metadata), 97 ditypes: make(map[string]llvm.Metadata), 98 } 99 100 target, err := llvm.GetTargetFromTriple(config.Triple) 101 if err != nil { 102 return nil, err 103 } 104 c.machine = target.CreateTargetMachine(config.Triple, config.CPU, "", llvm.CodeGenLevelDefault, llvm.RelocStatic, llvm.CodeModelDefault) 105 c.targetData = c.machine.CreateTargetData() 106 107 c.ctx = llvm.NewContext() 108 c.mod = c.ctx.NewModule(pkgName) 109 c.mod.SetTarget(config.Triple) 110 c.mod.SetDataLayout(c.targetData.String()) 111 c.builder = c.ctx.NewBuilder() 112 if c.Debug { 113 c.dibuilder = llvm.NewDIBuilder(c.mod) 114 } 115 116 c.uintptrType = c.ctx.IntType(c.targetData.PointerSize() * 8) 117 if c.targetData.PointerSize() <= 4 { 118 // 8, 16, 32 bits targets 119 c.intType = c.ctx.Int32Type() 120 } else if c.targetData.PointerSize() == 8 { 121 // 64 bits target 122 c.intType = c.ctx.Int64Type() 123 } else { 124 panic("unknown pointer size") 125 } 126 c.i8ptrType = llvm.PointerType(c.ctx.Int8Type(), 0) 127 128 dummyFuncType := llvm.FunctionType(c.ctx.VoidType(), nil, false) 129 dummyFunc := llvm.AddFunction(c.mod, "tinygo.dummy", dummyFuncType) 130 c.funcPtrAddrSpace = dummyFunc.Type().PointerAddressSpace() 131 dummyFunc.EraseFromParentAsFunction() 132 133 return c, nil 134 } 135 136 func (c *Compiler) Packages() []*loader.Package { 137 return c.ir.LoaderProgram.Sorted() 138 } 139 140 // Return the LLVM module. Only valid after a successful compile. 141 func (c *Compiler) Module() llvm.Module { 142 return c.mod 143 } 144 145 // Return the LLVM target data object. Only valid after a successful compile. 146 func (c *Compiler) TargetData() llvm.TargetData { 147 return c.targetData 148 } 149 150 // selectGC picks an appropriate GC strategy if none was provided. 151 func (c *Compiler) selectGC() string { 152 gc := c.GC 153 if gc == "" { 154 gc = "dumb" 155 } 156 return gc 157 } 158 159 // Compile the given package path or .go file path. Return an error when this 160 // fails (in any stage). 161 func (c *Compiler) Compile(mainPath string) error { 162 // Prefix the GOPATH with the system GOROOT, as GOROOT is already set to 163 // the TinyGo root. 164 overlayGopath := c.GOPATH 165 if overlayGopath == "" { 166 overlayGopath = runtime.GOROOT() 167 } else { 168 overlayGopath = runtime.GOROOT() + string(filepath.ListSeparator) + overlayGopath 169 } 170 171 wd, err := os.Getwd() 172 if err != nil { 173 return err 174 } 175 lprogram := &loader.Program{ 176 Build: &build.Context{ 177 GOARCH: c.GOARCH, 178 GOOS: c.GOOS, 179 GOROOT: runtime.GOROOT(), 180 GOPATH: c.GOPATH, 181 CgoEnabled: true, 182 UseAllFiles: false, 183 Compiler: "gc", // must be one of the recognized compilers 184 BuildTags: append([]string{"tinygo", "gc." + c.selectGC()}, c.BuildTags...), 185 }, 186 OverlayBuild: &build.Context{ 187 GOARCH: c.GOARCH, 188 GOOS: c.GOOS, 189 GOROOT: c.RootDir, 190 GOPATH: overlayGopath, 191 CgoEnabled: true, 192 UseAllFiles: false, 193 Compiler: "gc", // must be one of the recognized compilers 194 BuildTags: append([]string{"tinygo", "gc." + c.selectGC()}, c.BuildTags...), 195 }, 196 ShouldOverlay: func(path string) bool { 197 switch path { 198 case "machine", "os", "reflect", "runtime", "sync": 199 return true 200 default: 201 if strings.HasPrefix(path, "device/") || strings.HasPrefix(path, "examples/") { 202 return true 203 } else if path == "syscall" { 204 for _, tag := range c.BuildTags { 205 if tag == "avr" || tag == "cortexm" || tag == "darwin" { 206 return true 207 } 208 } 209 } 210 } 211 return false 212 }, 213 TypeChecker: types.Config{ 214 Sizes: &StdSizes{ 215 IntSize: int64(c.targetData.TypeAllocSize(c.intType)), 216 PtrSize: int64(c.targetData.PointerSize()), 217 MaxAlign: int64(c.targetData.PrefTypeAlignment(c.i8ptrType)), 218 }, 219 }, 220 Dir: wd, 221 CFlags: c.CFlags, 222 } 223 if strings.HasSuffix(mainPath, ".go") { 224 _, err = lprogram.ImportFile(mainPath) 225 if err != nil { 226 return err 227 } 228 } else { 229 _, err = lprogram.Import(mainPath, wd) 230 if err != nil { 231 return err 232 } 233 } 234 _, err = lprogram.Import("runtime", "") 235 if err != nil { 236 return err 237 } 238 239 err = lprogram.Parse() 240 if err != nil { 241 return err 242 } 243 244 c.ir = ir.NewProgram(lprogram, mainPath) 245 246 // Run a simple dead code elimination pass. 247 c.ir.SimpleDCE() 248 249 // Initialize debug information. 250 if c.Debug { 251 c.cu = c.dibuilder.CreateCompileUnit(llvm.DICompileUnit{ 252 Language: llvm.DW_LANG_Go, 253 File: mainPath, 254 Dir: "", 255 Producer: "TinyGo", 256 Optimized: true, 257 }) 258 } 259 260 var frames []*Frame 261 262 // Declare all named struct types. 263 for _, t := range c.ir.NamedTypes { 264 if named, ok := t.Type.Type().(*types.Named); ok { 265 if _, ok := named.Underlying().(*types.Struct); ok { 266 t.LLVMType = c.ctx.StructCreateNamed(named.Obj().Pkg().Path() + "." + named.Obj().Name()) 267 } 268 } 269 } 270 271 // Define all named struct types. 272 for _, t := range c.ir.NamedTypes { 273 if named, ok := t.Type.Type().(*types.Named); ok { 274 if st, ok := named.Underlying().(*types.Struct); ok { 275 llvmType, err := c.getLLVMType(st) 276 if err != nil { 277 return err 278 } 279 t.LLVMType.StructSetBody(llvmType.StructElementTypes(), false) 280 } 281 } 282 } 283 284 // Declare all globals. 285 for _, g := range c.ir.Globals { 286 typ := g.Type().(*types.Pointer).Elem() 287 llvmType, err := c.getLLVMType(typ) 288 if err != nil { 289 return err 290 } 291 global := c.mod.NamedGlobal(g.LinkName()) 292 if global.IsNil() { 293 global = llvm.AddGlobal(c.mod, llvmType, g.LinkName()) 294 } 295 g.LLVMGlobal = global 296 if !g.IsExtern() { 297 global.SetLinkage(llvm.InternalLinkage) 298 initializer, err := c.getZeroValue(llvmType) 299 if err != nil { 300 return err 301 } 302 global.SetInitializer(initializer) 303 } 304 } 305 306 // Declare all functions. 307 for _, f := range c.ir.Functions { 308 frame, err := c.parseFuncDecl(f) 309 if err != nil { 310 return err 311 } 312 frames = append(frames, frame) 313 } 314 315 // Add definitions to declarations. 316 for _, frame := range frames { 317 if frame.fn.Synthetic == "package initializer" { 318 c.initFuncs = append(c.initFuncs, frame.fn.LLVMFn) 319 } 320 if frame.fn.CName() != "" { 321 continue 322 } 323 if frame.fn.Blocks == nil { 324 continue // external function 325 } 326 err := c.parseFunc(frame) 327 if err != nil { 328 return err 329 } 330 } 331 332 // Define the already declared functions that wrap methods for use in 333 // interfaces. 334 for _, state := range c.interfaceInvokeWrappers { 335 err = c.createInterfaceInvokeWrapper(state) 336 if err != nil { 337 return err 338 } 339 } 340 341 // After all packages are imported, add a synthetic initializer function 342 // that calls the initializer of each package. 343 initFn := c.ir.GetFunction(c.ir.Program.ImportedPackage("runtime").Members["initAll"].(*ssa.Function)) 344 initFn.LLVMFn.SetLinkage(llvm.InternalLinkage) 345 initFn.LLVMFn.SetUnnamedAddr(true) 346 if c.Debug { 347 difunc, err := c.attachDebugInfo(initFn) 348 if err != nil { 349 return err 350 } 351 pos := c.ir.Program.Fset.Position(initFn.Pos()) 352 c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), difunc, llvm.Metadata{}) 353 } 354 block := c.ctx.AddBasicBlock(initFn.LLVMFn, "entry") 355 c.builder.SetInsertPointAtEnd(block) 356 for _, fn := range c.initFuncs { 357 c.builder.CreateCall(fn, []llvm.Value{llvm.Undef(c.i8ptrType), llvm.Undef(c.i8ptrType)}, "") 358 } 359 c.builder.CreateRetVoid() 360 361 // Conserve for goroutine lowering. Without marking these as external, they 362 // would be optimized away. 363 realMain := c.mod.NamedFunction(c.ir.MainPkg().Pkg.Path() + ".main") 364 realMain.SetLinkage(llvm.ExternalLinkage) // keep alive until goroutine lowering 365 c.mod.NamedFunction("runtime.alloc").SetLinkage(llvm.ExternalLinkage) 366 c.mod.NamedFunction("runtime.free").SetLinkage(llvm.ExternalLinkage) 367 c.mod.NamedFunction("runtime.chanSend").SetLinkage(llvm.ExternalLinkage) 368 c.mod.NamedFunction("runtime.chanRecv").SetLinkage(llvm.ExternalLinkage) 369 c.mod.NamedFunction("runtime.sleepTask").SetLinkage(llvm.ExternalLinkage) 370 c.mod.NamedFunction("runtime.activateTask").SetLinkage(llvm.ExternalLinkage) 371 c.mod.NamedFunction("runtime.scheduler").SetLinkage(llvm.ExternalLinkage) 372 373 // Load some attributes 374 getAttr := func(attrName string) llvm.Attribute { 375 attrKind := llvm.AttributeKindID(attrName) 376 return c.ctx.CreateEnumAttribute(attrKind, 0) 377 } 378 nocapture := getAttr("nocapture") 379 writeonly := getAttr("writeonly") 380 readonly := getAttr("readonly") 381 382 // Tell the optimizer that runtime.alloc is an allocator, meaning that it 383 // returns values that are never null and never alias to an existing value. 384 for _, attrName := range []string{"noalias", "nonnull"} { 385 c.mod.NamedFunction("runtime.alloc").AddAttributeAtIndex(0, getAttr(attrName)) 386 } 387 388 // See emitNilCheck in asserts.go. 389 c.mod.NamedFunction("runtime.isnil").AddAttributeAtIndex(1, nocapture) 390 391 // Memory copy operations do not capture pointers, even though some weird 392 // pointer arithmetic is happening in the Go implementation. 393 for _, fnName := range []string{"runtime.memcpy", "runtime.memmove"} { 394 fn := c.mod.NamedFunction(fnName) 395 fn.AddAttributeAtIndex(1, nocapture) 396 fn.AddAttributeAtIndex(1, writeonly) 397 fn.AddAttributeAtIndex(2, nocapture) 398 fn.AddAttributeAtIndex(2, readonly) 399 } 400 401 // see: https://reviews.llvm.org/D18355 402 if c.Debug { 403 c.mod.AddNamedMetadataOperand("llvm.module.flags", 404 c.ctx.MDNode([]llvm.Metadata{ 405 llvm.ConstInt(c.ctx.Int32Type(), 1, false).ConstantAsMetadata(), // Error on mismatch 406 llvm.GlobalContext().MDString("Debug Info Version"), 407 llvm.ConstInt(c.ctx.Int32Type(), 3, false).ConstantAsMetadata(), // DWARF version 408 }), 409 ) 410 c.dibuilder.Finalize() 411 } 412 413 return nil 414 } 415 416 func (c *Compiler) getLLVMType(goType types.Type) (llvm.Type, error) { 417 switch typ := goType.(type) { 418 case *types.Array: 419 elemType, err := c.getLLVMType(typ.Elem()) 420 if err != nil { 421 return llvm.Type{}, err 422 } 423 return llvm.ArrayType(elemType, int(typ.Len())), nil 424 case *types.Basic: 425 switch typ.Kind() { 426 case types.Bool, types.UntypedBool: 427 return c.ctx.Int1Type(), nil 428 case types.Int8, types.Uint8: 429 return c.ctx.Int8Type(), nil 430 case types.Int16, types.Uint16: 431 return c.ctx.Int16Type(), nil 432 case types.Int32, types.Uint32: 433 return c.ctx.Int32Type(), nil 434 case types.Int, types.Uint: 435 return c.intType, nil 436 case types.Int64, types.Uint64: 437 return c.ctx.Int64Type(), nil 438 case types.Float32: 439 return c.ctx.FloatType(), nil 440 case types.Float64: 441 return c.ctx.DoubleType(), nil 442 case types.Complex64: 443 return c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false), nil 444 case types.Complex128: 445 return c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false), nil 446 case types.String, types.UntypedString: 447 return c.mod.GetTypeByName("runtime._string"), nil 448 case types.Uintptr: 449 return c.uintptrType, nil 450 case types.UnsafePointer: 451 return c.i8ptrType, nil 452 default: 453 return llvm.Type{}, errors.New("todo: unknown basic type: " + typ.String()) 454 } 455 case *types.Chan: 456 return llvm.PointerType(c.mod.GetTypeByName("runtime.channel"), 0), nil 457 case *types.Interface: 458 return c.mod.GetTypeByName("runtime._interface"), nil 459 case *types.Map: 460 return llvm.PointerType(c.mod.GetTypeByName("runtime.hashmap"), 0), nil 461 case *types.Named: 462 if _, ok := typ.Underlying().(*types.Struct); ok { 463 llvmType := c.mod.GetTypeByName(typ.Obj().Pkg().Path() + "." + typ.Obj().Name()) 464 if llvmType.IsNil() { 465 return llvm.Type{}, errors.New("type not found: " + typ.Obj().Pkg().Path() + "." + typ.Obj().Name()) 466 } 467 return llvmType, nil 468 } 469 return c.getLLVMType(typ.Underlying()) 470 case *types.Pointer: 471 ptrTo, err := c.getLLVMType(typ.Elem()) 472 if err != nil { 473 return llvm.Type{}, err 474 } 475 return llvm.PointerType(ptrTo, 0), nil 476 case *types.Signature: // function value 477 return c.getFuncType(typ) 478 case *types.Slice: 479 elemType, err := c.getLLVMType(typ.Elem()) 480 if err != nil { 481 return llvm.Type{}, err 482 } 483 members := []llvm.Type{ 484 llvm.PointerType(elemType, 0), 485 c.uintptrType, // len 486 c.uintptrType, // cap 487 } 488 return c.ctx.StructType(members, false), nil 489 case *types.Struct: 490 members := make([]llvm.Type, typ.NumFields()) 491 for i := 0; i < typ.NumFields(); i++ { 492 member, err := c.getLLVMType(typ.Field(i).Type()) 493 if err != nil { 494 return llvm.Type{}, err 495 } 496 members[i] = member 497 } 498 if len(members) > 2 && typ.Field(0).Name() == "C union" { 499 // Not a normal struct but a C union emitted by cgo. 500 // Such a field name cannot be entered in regular Go code, this must 501 // be manually inserted in the AST so this is safe. 502 maxAlign := 0 503 maxSize := uint64(0) 504 mainType := members[0] 505 for _, member := range members { 506 align := c.targetData.ABITypeAlignment(member) 507 size := c.targetData.TypeAllocSize(member) 508 if align > maxAlign { 509 maxAlign = align 510 mainType = member 511 } else if align == maxAlign && size > maxSize { 512 maxAlign = align 513 maxSize = size 514 mainType = member 515 } else if size > maxSize { 516 maxSize = size 517 } 518 } 519 members = []llvm.Type{mainType} 520 mainTypeSize := c.targetData.TypeAllocSize(mainType) 521 if mainTypeSize < maxSize { 522 members = append(members, llvm.ArrayType(c.ctx.Int8Type(), int(maxSize-mainTypeSize))) 523 } 524 } 525 return c.ctx.StructType(members, false), nil 526 case *types.Tuple: 527 members := make([]llvm.Type, typ.Len()) 528 for i := 0; i < typ.Len(); i++ { 529 member, err := c.getLLVMType(typ.At(i).Type()) 530 if err != nil { 531 return llvm.Type{}, err 532 } 533 members[i] = member 534 } 535 return c.ctx.StructType(members, false), nil 536 default: 537 return llvm.Type{}, errors.New("todo: unknown type: " + goType.String()) 538 } 539 } 540 541 // Return a zero LLVM value for any LLVM type. Setting this value as an 542 // initializer has the same effect as setting 'zeroinitializer' on a value. 543 // Sadly, I haven't found a way to do it directly with the Go API but this works 544 // just fine. 545 func (c *Compiler) getZeroValue(typ llvm.Type) (llvm.Value, error) { 546 switch typ.TypeKind() { 547 case llvm.ArrayTypeKind: 548 subTyp := typ.ElementType() 549 subVal, err := c.getZeroValue(subTyp) 550 if err != nil { 551 return llvm.Value{}, err 552 } 553 vals := make([]llvm.Value, typ.ArrayLength()) 554 for i := range vals { 555 vals[i] = subVal 556 } 557 return llvm.ConstArray(subTyp, vals), nil 558 case llvm.FloatTypeKind, llvm.DoubleTypeKind: 559 return llvm.ConstFloat(typ, 0.0), nil 560 case llvm.IntegerTypeKind: 561 return llvm.ConstInt(typ, 0, false), nil 562 case llvm.PointerTypeKind: 563 return llvm.ConstPointerNull(typ), nil 564 case llvm.StructTypeKind: 565 types := typ.StructElementTypes() 566 vals := make([]llvm.Value, len(types)) 567 for i, subTyp := range types { 568 val, err := c.getZeroValue(subTyp) 569 if err != nil { 570 return llvm.Value{}, err 571 } 572 vals[i] = val 573 } 574 if typ.StructName() != "" { 575 return llvm.ConstNamedStruct(typ, vals), nil 576 } else { 577 return c.ctx.ConstStruct(vals, false), nil 578 } 579 default: 580 return llvm.Value{}, errors.New("todo: LLVM zero initializer: " + typ.String()) 581 } 582 } 583 584 // Is this a pointer type of some sort? Can be unsafe.Pointer or any *T pointer. 585 func isPointer(typ types.Type) bool { 586 if _, ok := typ.(*types.Pointer); ok { 587 return true 588 } else if typ, ok := typ.(*types.Basic); ok && typ.Kind() == types.UnsafePointer { 589 return true 590 } else { 591 return false 592 } 593 } 594 595 // Get the DWARF type for this Go type. 596 func (c *Compiler) getDIType(typ types.Type) (llvm.Metadata, error) { 597 name := typ.String() 598 if dityp, ok := c.ditypes[name]; ok { 599 return dityp, nil 600 } else { 601 llvmType, err := c.getLLVMType(typ) 602 if err != nil { 603 return llvm.Metadata{}, err 604 } 605 sizeInBytes := c.targetData.TypeAllocSize(llvmType) 606 var encoding llvm.DwarfTypeEncoding 607 switch typ := typ.(type) { 608 case *types.Basic: 609 if typ.Info()&types.IsBoolean != 0 { 610 encoding = llvm.DW_ATE_boolean 611 } else if typ.Info()&types.IsFloat != 0 { 612 encoding = llvm.DW_ATE_float 613 } else if typ.Info()&types.IsComplex != 0 { 614 encoding = llvm.DW_ATE_complex_float 615 } else if typ.Info()&types.IsUnsigned != 0 { 616 encoding = llvm.DW_ATE_unsigned 617 } else if typ.Info()&types.IsInteger != 0 { 618 encoding = llvm.DW_ATE_signed 619 } else if typ.Kind() == types.UnsafePointer { 620 encoding = llvm.DW_ATE_address 621 } 622 case *types.Pointer: 623 encoding = llvm.DW_ATE_address 624 } 625 // TODO: other types 626 dityp = c.dibuilder.CreateBasicType(llvm.DIBasicType{ 627 Name: name, 628 SizeInBits: sizeInBytes * 8, 629 Encoding: encoding, 630 }) 631 c.ditypes[name] = dityp 632 return dityp, nil 633 } 634 } 635 636 func (c *Compiler) parseFuncDecl(f *ir.Function) (*Frame, error) { 637 frame := &Frame{ 638 fn: f, 639 locals: make(map[ssa.Value]llvm.Value), 640 blockEntries: make(map[*ssa.BasicBlock]llvm.BasicBlock), 641 blockExits: make(map[*ssa.BasicBlock]llvm.BasicBlock), 642 } 643 644 var retType llvm.Type 645 if f.Signature.Results() == nil { 646 retType = c.ctx.VoidType() 647 } else if f.Signature.Results().Len() == 1 { 648 var err error 649 retType, err = c.getLLVMType(f.Signature.Results().At(0).Type()) 650 if err != nil { 651 return nil, err 652 } 653 } else { 654 results := make([]llvm.Type, 0, f.Signature.Results().Len()) 655 for i := 0; i < f.Signature.Results().Len(); i++ { 656 typ, err := c.getLLVMType(f.Signature.Results().At(i).Type()) 657 if err != nil { 658 return nil, err 659 } 660 results = append(results, typ) 661 } 662 retType = c.ctx.StructType(results, false) 663 } 664 665 var paramTypes []llvm.Type 666 for _, param := range f.Params { 667 paramType, err := c.getLLVMType(param.Type()) 668 if err != nil { 669 return nil, err 670 } 671 paramTypeFragments := c.expandFormalParamType(paramType) 672 paramTypes = append(paramTypes, paramTypeFragments...) 673 } 674 675 // Add an extra parameter as the function context. This context is used in 676 // closures and bound methods, but should be optimized away when not used. 677 if !f.IsExported() { 678 paramTypes = append(paramTypes, c.i8ptrType) // context 679 paramTypes = append(paramTypes, c.i8ptrType) // parent coroutine 680 } 681 682 fnType := llvm.FunctionType(retType, paramTypes, false) 683 684 name := f.LinkName() 685 frame.fn.LLVMFn = c.mod.NamedFunction(name) 686 if frame.fn.LLVMFn.IsNil() { 687 frame.fn.LLVMFn = llvm.AddFunction(c.mod, name, fnType) 688 } 689 690 return frame, nil 691 } 692 693 func (c *Compiler) attachDebugInfo(f *ir.Function) (llvm.Metadata, error) { 694 pos := c.ir.Program.Fset.Position(f.Syntax().Pos()) 695 return c.attachDebugInfoRaw(f, f.LLVMFn, "", pos.Filename, pos.Line) 696 } 697 698 func (c *Compiler) attachDebugInfoRaw(f *ir.Function, llvmFn llvm.Value, suffix, filename string, line int) (llvm.Metadata, error) { 699 if _, ok := c.difiles[filename]; !ok { 700 dir, file := filepath.Split(filename) 701 if dir != "" { 702 dir = dir[:len(dir)-1] 703 } 704 c.difiles[filename] = c.dibuilder.CreateFile(file, dir) 705 } 706 707 // Debug info for this function. 708 diparams := make([]llvm.Metadata, 0, len(f.Params)) 709 for _, param := range f.Params { 710 ditype, err := c.getDIType(param.Type()) 711 if err != nil { 712 return llvm.Metadata{}, err 713 } 714 diparams = append(diparams, ditype) 715 } 716 diFuncType := c.dibuilder.CreateSubroutineType(llvm.DISubroutineType{ 717 File: c.difiles[filename], 718 Parameters: diparams, 719 Flags: 0, // ? 720 }) 721 difunc := c.dibuilder.CreateFunction(c.difiles[filename], llvm.DIFunction{ 722 Name: f.RelString(nil) + suffix, 723 LinkageName: f.LinkName() + suffix, 724 File: c.difiles[filename], 725 Line: line, 726 Type: diFuncType, 727 LocalToUnit: true, 728 IsDefinition: true, 729 ScopeLine: 0, 730 Flags: llvm.FlagPrototyped, 731 Optimized: true, 732 }) 733 llvmFn.SetSubprogram(difunc) 734 return difunc, nil 735 } 736 737 func (c *Compiler) parseFunc(frame *Frame) error { 738 if c.DumpSSA { 739 fmt.Printf("\nfunc %s:\n", frame.fn.Function) 740 } 741 if !frame.fn.IsExported() { 742 frame.fn.LLVMFn.SetLinkage(llvm.InternalLinkage) 743 frame.fn.LLVMFn.SetUnnamedAddr(true) 744 } 745 if frame.fn.IsInterrupt() && strings.HasPrefix(c.Triple, "avr") { 746 frame.fn.LLVMFn.SetFunctionCallConv(85) // CallingConv::AVR_SIGNAL 747 } 748 749 // Add debug info, if needed. 750 if c.Debug { 751 if frame.fn.Synthetic == "package initializer" { 752 // Package initializers have no debug info. Create some fake debug 753 // info to at least have *something*. 754 difunc, err := c.attachDebugInfoRaw(frame.fn, frame.fn.LLVMFn, "", "", 0) 755 if err != nil { 756 return err 757 } 758 frame.difunc = difunc 759 } else if frame.fn.Syntax() != nil { 760 // Create debug info file if needed. 761 difunc, err := c.attachDebugInfo(frame.fn) 762 if err != nil { 763 return err 764 } 765 frame.difunc = difunc 766 } 767 pos := c.ir.Program.Fset.Position(frame.fn.Pos()) 768 c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), frame.difunc, llvm.Metadata{}) 769 } 770 771 // Pre-create all basic blocks in the function. 772 for _, block := range frame.fn.DomPreorder() { 773 llvmBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, block.Comment) 774 frame.blockEntries[block] = llvmBlock 775 frame.blockExits[block] = llvmBlock 776 } 777 entryBlock := frame.blockEntries[frame.fn.Blocks[0]] 778 c.builder.SetInsertPointAtEnd(entryBlock) 779 780 // Load function parameters 781 llvmParamIndex := 0 782 for i, param := range frame.fn.Params { 783 llvmType, err := c.getLLVMType(param.Type()) 784 if err != nil { 785 return err 786 } 787 fields := make([]llvm.Value, 0, 1) 788 for range c.expandFormalParamType(llvmType) { 789 fields = append(fields, frame.fn.LLVMFn.Param(llvmParamIndex)) 790 llvmParamIndex++ 791 } 792 frame.locals[param] = c.collapseFormalParam(llvmType, fields) 793 794 // Add debug information to this parameter (if available) 795 if c.Debug && frame.fn.Syntax() != nil { 796 pos := c.ir.Program.Fset.Position(frame.fn.Syntax().Pos()) 797 dityp, err := c.getDIType(param.Type()) 798 if err != nil { 799 return err 800 } 801 c.dibuilder.CreateParameterVariable(frame.difunc, llvm.DIParameterVariable{ 802 Name: param.Name(), 803 File: c.difiles[pos.Filename], 804 Line: pos.Line, 805 Type: dityp, 806 AlwaysPreserve: true, 807 ArgNo: i + 1, 808 }) 809 // TODO: set the value of this parameter. 810 } 811 } 812 813 // Load free variables from the context. This is a closure (or bound 814 // method). 815 var context llvm.Value 816 if !frame.fn.IsExported() { 817 parentHandle := frame.fn.LLVMFn.LastParam() 818 parentHandle.SetName("parentHandle") 819 context = llvm.PrevParam(parentHandle) 820 context.SetName("context") 821 } 822 if len(frame.fn.FreeVars) != 0 { 823 // Determine the context type. It's a struct containing all variables. 824 freeVarTypes := make([]llvm.Type, 0, len(frame.fn.FreeVars)) 825 for _, freeVar := range frame.fn.FreeVars { 826 typ, err := c.getLLVMType(freeVar.Type()) 827 if err != nil { 828 return err 829 } 830 freeVarTypes = append(freeVarTypes, typ) 831 } 832 contextType := c.ctx.StructType(freeVarTypes, false) 833 834 // Get a correctly-typed pointer to the context. 835 contextAlloc := llvm.Value{} 836 if c.targetData.TypeAllocSize(contextType) <= c.targetData.TypeAllocSize(c.i8ptrType) { 837 // Context stored directly in pointer. Load it using an alloca. 838 contextRawAlloc := c.builder.CreateAlloca(llvm.PointerType(c.i8ptrType, 0), "context.raw.alloc") 839 contextRawValue := c.builder.CreateBitCast(context, llvm.PointerType(c.i8ptrType, 0), "context.raw.value") 840 c.builder.CreateStore(contextRawValue, contextRawAlloc) 841 contextAlloc = c.builder.CreateBitCast(contextRawAlloc, llvm.PointerType(contextType, 0), "context.alloc") 842 } else { 843 // Context stored in the heap. Bitcast the passed-in pointer to the 844 // correct pointer type. 845 contextAlloc = c.builder.CreateBitCast(context, llvm.PointerType(contextType, 0), "context.raw.ptr") 846 } 847 848 // Load each free variable from the context. 849 // A free variable is always a pointer when this is a closure, but it 850 // can be another type when it is a wrapper for a bound method (these 851 // wrappers are generated by the ssa package). 852 for i, freeVar := range frame.fn.FreeVars { 853 indices := []llvm.Value{ 854 llvm.ConstInt(c.ctx.Int32Type(), 0, false), 855 llvm.ConstInt(c.ctx.Int32Type(), uint64(i), false), 856 } 857 gep := c.builder.CreateInBoundsGEP(contextAlloc, indices, "") 858 frame.locals[freeVar] = c.builder.CreateLoad(gep, "") 859 } 860 } 861 862 if frame.fn.Recover != nil { 863 // This function has deferred function calls. Set some things up for 864 // them. 865 c.deferInitFunc(frame) 866 } 867 868 // Fill blocks with instructions. 869 for _, block := range frame.fn.DomPreorder() { 870 if c.DumpSSA { 871 fmt.Printf("%d: %s:\n", block.Index, block.Comment) 872 } 873 c.builder.SetInsertPointAtEnd(frame.blockEntries[block]) 874 frame.currentBlock = block 875 for _, instr := range block.Instrs { 876 if _, ok := instr.(*ssa.DebugRef); ok { 877 continue 878 } 879 if c.DumpSSA { 880 if val, ok := instr.(ssa.Value); ok && val.Name() != "" { 881 fmt.Printf("\t%s = %s\n", val.Name(), val.String()) 882 } else { 883 fmt.Printf("\t%s\n", instr.String()) 884 } 885 } 886 err := c.parseInstr(frame, instr) 887 if err != nil { 888 return err 889 } 890 } 891 if frame.fn.Name() == "init" && len(block.Instrs) == 0 { 892 c.builder.CreateRetVoid() 893 } 894 } 895 896 // Resolve phi nodes 897 for _, phi := range frame.phis { 898 block := phi.ssa.Block() 899 for i, edge := range phi.ssa.Edges { 900 llvmVal, err := c.parseExpr(frame, edge) 901 if err != nil { 902 return err 903 } 904 llvmBlock := frame.blockExits[block.Preds[i]] 905 phi.llvm.AddIncoming([]llvm.Value{llvmVal}, []llvm.BasicBlock{llvmBlock}) 906 } 907 } 908 909 return nil 910 } 911 912 func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) error { 913 if c.Debug { 914 pos := c.ir.Program.Fset.Position(instr.Pos()) 915 c.builder.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), frame.difunc, llvm.Metadata{}) 916 } 917 918 switch instr := instr.(type) { 919 case ssa.Value: 920 value, err := c.parseExpr(frame, instr) 921 frame.locals[instr] = value 922 return err 923 case *ssa.DebugRef: 924 return nil // ignore 925 case *ssa.Defer: 926 return c.emitDefer(frame, instr) 927 case *ssa.Go: 928 if instr.Call.IsInvoke() { 929 return c.makeError(instr.Pos(), "todo: go on method receiver") 930 } 931 callee := instr.Call.StaticCallee() 932 if callee == nil { 933 return c.makeError(instr.Pos(), "todo: go on non-direct function (function pointer, etc.)") 934 } 935 calleeFn := c.ir.GetFunction(callee) 936 937 // Mark this function as a 'go' invocation and break invalid 938 // interprocedural optimizations. For example, heap-to-stack 939 // transformations are not sound as goroutines can outlive their parent. 940 calleeType := calleeFn.LLVMFn.Type() 941 calleeValue := c.builder.CreateBitCast(calleeFn.LLVMFn, c.i8ptrType, "") 942 calleeValue = c.createRuntimeCall("makeGoroutine", []llvm.Value{calleeValue}, "") 943 calleeValue = c.builder.CreateBitCast(calleeValue, calleeType, "") 944 945 // Get all function parameters to pass to the goroutine. 946 var params []llvm.Value 947 for _, param := range instr.Call.Args { 948 val, err := c.parseExpr(frame, param) 949 if err != nil { 950 return err 951 } 952 params = append(params, val) 953 } 954 if !calleeFn.IsExported() { 955 params = append(params, llvm.Undef(c.i8ptrType)) // context parameter 956 params = append(params, llvm.Undef(c.i8ptrType)) // parent coroutine handle 957 } 958 959 c.createCall(calleeValue, params, "") 960 return nil 961 case *ssa.If: 962 cond, err := c.parseExpr(frame, instr.Cond) 963 if err != nil { 964 return err 965 } 966 block := instr.Block() 967 blockThen := frame.blockEntries[block.Succs[0]] 968 blockElse := frame.blockEntries[block.Succs[1]] 969 c.builder.CreateCondBr(cond, blockThen, blockElse) 970 return nil 971 case *ssa.Jump: 972 blockJump := frame.blockEntries[instr.Block().Succs[0]] 973 c.builder.CreateBr(blockJump) 974 return nil 975 case *ssa.MapUpdate: 976 m, err := c.parseExpr(frame, instr.Map) 977 if err != nil { 978 return err 979 } 980 key, err := c.parseExpr(frame, instr.Key) 981 if err != nil { 982 return err 983 } 984 value, err := c.parseExpr(frame, instr.Value) 985 if err != nil { 986 return err 987 } 988 mapType := instr.Map.Type().Underlying().(*types.Map) 989 return c.emitMapUpdate(mapType.Key(), m, key, value, instr.Pos()) 990 case *ssa.Panic: 991 value, err := c.parseExpr(frame, instr.X) 992 if err != nil { 993 return err 994 } 995 c.createRuntimeCall("_panic", []llvm.Value{value}, "") 996 c.builder.CreateUnreachable() 997 return nil 998 case *ssa.Return: 999 if len(instr.Results) == 0 { 1000 c.builder.CreateRetVoid() 1001 return nil 1002 } else if len(instr.Results) == 1 { 1003 val, err := c.parseExpr(frame, instr.Results[0]) 1004 if err != nil { 1005 return err 1006 } 1007 c.builder.CreateRet(val) 1008 return nil 1009 } else { 1010 // Multiple return values. Put them all in a struct. 1011 retVal, err := c.getZeroValue(frame.fn.LLVMFn.Type().ElementType().ReturnType()) 1012 if err != nil { 1013 return err 1014 } 1015 for i, result := range instr.Results { 1016 val, err := c.parseExpr(frame, result) 1017 if err != nil { 1018 return err 1019 } 1020 retVal = c.builder.CreateInsertValue(retVal, val, i, "") 1021 } 1022 c.builder.CreateRet(retVal) 1023 return nil 1024 } 1025 case *ssa.RunDefers: 1026 return c.emitRunDefers(frame) 1027 case *ssa.Send: 1028 return c.emitChanSend(frame, instr) 1029 case *ssa.Store: 1030 llvmAddr, err := c.parseExpr(frame, instr.Addr) 1031 if err != nil { 1032 return err 1033 } 1034 llvmVal, err := c.parseExpr(frame, instr.Val) 1035 if err != nil { 1036 return err 1037 } 1038 if c.targetData.TypeAllocSize(llvmVal.Type()) == 0 { 1039 // nothing to store 1040 return nil 1041 } 1042 store := c.builder.CreateStore(llvmVal, llvmAddr) 1043 valType := instr.Addr.Type().Underlying().(*types.Pointer).Elem() 1044 if c.ir.IsVolatile(valType) { 1045 // Volatile store, for memory-mapped registers. 1046 store.SetVolatile(true) 1047 } 1048 return nil 1049 default: 1050 return c.makeError(instr.Pos(), "unknown instruction: "+instr.String()) 1051 } 1052 } 1053 1054 func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string, pos token.Pos) (llvm.Value, error) { 1055 switch callName { 1056 case "append": 1057 src, err := c.parseExpr(frame, args[0]) 1058 if err != nil { 1059 return llvm.Value{}, err 1060 } 1061 elems, err := c.parseExpr(frame, args[1]) 1062 if err != nil { 1063 return llvm.Value{}, err 1064 } 1065 srcBuf := c.builder.CreateExtractValue(src, 0, "append.srcBuf") 1066 srcPtr := c.builder.CreateBitCast(srcBuf, c.i8ptrType, "append.srcPtr") 1067 srcLen := c.builder.CreateExtractValue(src, 1, "append.srcLen") 1068 srcCap := c.builder.CreateExtractValue(src, 2, "append.srcCap") 1069 elemsBuf := c.builder.CreateExtractValue(elems, 0, "append.elemsBuf") 1070 elemsPtr := c.builder.CreateBitCast(elemsBuf, c.i8ptrType, "append.srcPtr") 1071 elemsLen := c.builder.CreateExtractValue(elems, 1, "append.elemsLen") 1072 elemType := srcBuf.Type().ElementType() 1073 elemSize := llvm.ConstInt(c.uintptrType, c.targetData.TypeAllocSize(elemType), false) 1074 result := c.createRuntimeCall("sliceAppend", []llvm.Value{srcPtr, elemsPtr, srcLen, srcCap, elemsLen, elemSize}, "append.new") 1075 newPtr := c.builder.CreateExtractValue(result, 0, "append.newPtr") 1076 newBuf := c.builder.CreateBitCast(newPtr, srcBuf.Type(), "append.newBuf") 1077 newLen := c.builder.CreateExtractValue(result, 1, "append.newLen") 1078 newCap := c.builder.CreateExtractValue(result, 2, "append.newCap") 1079 newSlice := llvm.Undef(src.Type()) 1080 newSlice = c.builder.CreateInsertValue(newSlice, newBuf, 0, "") 1081 newSlice = c.builder.CreateInsertValue(newSlice, newLen, 1, "") 1082 newSlice = c.builder.CreateInsertValue(newSlice, newCap, 2, "") 1083 return newSlice, nil 1084 case "cap": 1085 value, err := c.parseExpr(frame, args[0]) 1086 if err != nil { 1087 return llvm.Value{}, err 1088 } 1089 var llvmCap llvm.Value 1090 switch args[0].Type().(type) { 1091 case *types.Chan: 1092 // Channel. Buffered channels haven't been implemented yet so always 1093 // return 0. 1094 llvmCap = llvm.ConstInt(c.intType, 0, false) 1095 case *types.Slice: 1096 llvmCap = c.builder.CreateExtractValue(value, 2, "cap") 1097 default: 1098 return llvm.Value{}, c.makeError(pos, "todo: cap: unknown type") 1099 } 1100 if c.targetData.TypeAllocSize(llvmCap.Type()) < c.targetData.TypeAllocSize(c.intType) { 1101 llvmCap = c.builder.CreateZExt(llvmCap, c.intType, "len.int") 1102 } 1103 return llvmCap, nil 1104 case "close": 1105 return llvm.Value{}, c.emitChanClose(frame, args[0]) 1106 case "complex": 1107 r, err := c.parseExpr(frame, args[0]) 1108 if err != nil { 1109 return llvm.Value{}, err 1110 } 1111 i, err := c.parseExpr(frame, args[1]) 1112 if err != nil { 1113 return llvm.Value{}, err 1114 } 1115 t := args[0].Type().Underlying().(*types.Basic) 1116 var cplx llvm.Value 1117 switch t.Kind() { 1118 case types.Float32: 1119 cplx = llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false)) 1120 case types.Float64: 1121 cplx = llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false)) 1122 default: 1123 return llvm.Value{}, c.makeError(pos, "unsupported type in complex builtin: "+t.String()) 1124 } 1125 cplx = c.builder.CreateInsertValue(cplx, r, 0, "") 1126 cplx = c.builder.CreateInsertValue(cplx, i, 1, "") 1127 return cplx, nil 1128 case "copy": 1129 dst, err := c.parseExpr(frame, args[0]) 1130 if err != nil { 1131 return llvm.Value{}, err 1132 } 1133 src, err := c.parseExpr(frame, args[1]) 1134 if err != nil { 1135 return llvm.Value{}, err 1136 } 1137 dstLen := c.builder.CreateExtractValue(dst, 1, "copy.dstLen") 1138 srcLen := c.builder.CreateExtractValue(src, 1, "copy.srcLen") 1139 dstBuf := c.builder.CreateExtractValue(dst, 0, "copy.dstArray") 1140 srcBuf := c.builder.CreateExtractValue(src, 0, "copy.srcArray") 1141 elemType := dstBuf.Type().ElementType() 1142 dstBuf = c.builder.CreateBitCast(dstBuf, c.i8ptrType, "copy.dstPtr") 1143 srcBuf = c.builder.CreateBitCast(srcBuf, c.i8ptrType, "copy.srcPtr") 1144 elemSize := llvm.ConstInt(c.uintptrType, c.targetData.TypeAllocSize(elemType), false) 1145 return c.createRuntimeCall("sliceCopy", []llvm.Value{dstBuf, srcBuf, dstLen, srcLen, elemSize}, "copy.n"), nil 1146 case "delete": 1147 m, err := c.parseExpr(frame, args[0]) 1148 if err != nil { 1149 return llvm.Value{}, err 1150 } 1151 key, err := c.parseExpr(frame, args[1]) 1152 if err != nil { 1153 return llvm.Value{}, err 1154 } 1155 return llvm.Value{}, c.emitMapDelete(args[1].Type(), m, key, pos) 1156 case "imag": 1157 cplx, err := c.parseExpr(frame, args[0]) 1158 if err != nil { 1159 return llvm.Value{}, err 1160 } 1161 return c.builder.CreateExtractValue(cplx, 1, "imag"), nil 1162 case "len": 1163 value, err := c.parseExpr(frame, args[0]) 1164 if err != nil { 1165 return llvm.Value{}, err 1166 } 1167 var llvmLen llvm.Value 1168 switch args[0].Type().Underlying().(type) { 1169 case *types.Basic, *types.Slice: 1170 // string or slice 1171 llvmLen = c.builder.CreateExtractValue(value, 1, "len") 1172 case *types.Chan: 1173 // Channel. Buffered channels haven't been implemented yet so always 1174 // return 0. 1175 llvmLen = llvm.ConstInt(c.intType, 0, false) 1176 case *types.Map: 1177 llvmLen = c.createRuntimeCall("hashmapLen", []llvm.Value{value}, "len") 1178 default: 1179 return llvm.Value{}, c.makeError(pos, "todo: len: unknown type") 1180 } 1181 if c.targetData.TypeAllocSize(llvmLen.Type()) < c.targetData.TypeAllocSize(c.intType) { 1182 llvmLen = c.builder.CreateZExt(llvmLen, c.intType, "len.int") 1183 } 1184 return llvmLen, nil 1185 case "print", "println": 1186 for i, arg := range args { 1187 if i >= 1 && callName == "println" { 1188 c.createRuntimeCall("printspace", nil, "") 1189 } 1190 value, err := c.parseExpr(frame, arg) 1191 if err != nil { 1192 return llvm.Value{}, err 1193 } 1194 typ := arg.Type().Underlying() 1195 switch typ := typ.(type) { 1196 case *types.Basic: 1197 switch typ.Kind() { 1198 case types.String, types.UntypedString: 1199 c.createRuntimeCall("printstring", []llvm.Value{value}, "") 1200 case types.Uintptr: 1201 c.createRuntimeCall("printptr", []llvm.Value{value}, "") 1202 case types.UnsafePointer: 1203 ptrValue := c.builder.CreatePtrToInt(value, c.uintptrType, "") 1204 c.createRuntimeCall("printptr", []llvm.Value{ptrValue}, "") 1205 default: 1206 // runtime.print{int,uint}{8,16,32,64} 1207 if typ.Info()&types.IsInteger != 0 { 1208 name := "print" 1209 if typ.Info()&types.IsUnsigned != 0 { 1210 name += "uint" 1211 } else { 1212 name += "int" 1213 } 1214 name += strconv.FormatUint(c.targetData.TypeAllocSize(value.Type())*8, 10) 1215 c.createRuntimeCall(name, []llvm.Value{value}, "") 1216 } else if typ.Kind() == types.Bool { 1217 c.createRuntimeCall("printbool", []llvm.Value{value}, "") 1218 } else if typ.Kind() == types.Float32 { 1219 c.createRuntimeCall("printfloat32", []llvm.Value{value}, "") 1220 } else if typ.Kind() == types.Float64 { 1221 c.createRuntimeCall("printfloat64", []llvm.Value{value}, "") 1222 } else if typ.Kind() == types.Complex64 { 1223 c.createRuntimeCall("printcomplex64", []llvm.Value{value}, "") 1224 } else if typ.Kind() == types.Complex128 { 1225 c.createRuntimeCall("printcomplex128", []llvm.Value{value}, "") 1226 } else { 1227 return llvm.Value{}, c.makeError(pos, "unknown basic arg type: "+typ.String()) 1228 } 1229 } 1230 case *types.Interface: 1231 c.createRuntimeCall("printitf", []llvm.Value{value}, "") 1232 case *types.Map: 1233 c.createRuntimeCall("printmap", []llvm.Value{value}, "") 1234 case *types.Pointer: 1235 ptrValue := c.builder.CreatePtrToInt(value, c.uintptrType, "") 1236 c.createRuntimeCall("printptr", []llvm.Value{ptrValue}, "") 1237 default: 1238 return llvm.Value{}, c.makeError(pos, "unknown arg type: "+typ.String()) 1239 } 1240 } 1241 if callName == "println" { 1242 c.createRuntimeCall("printnl", nil, "") 1243 } 1244 return llvm.Value{}, nil // print() or println() returns void 1245 case "real": 1246 cplx, err := c.parseExpr(frame, args[0]) 1247 if err != nil { 1248 return llvm.Value{}, err 1249 } 1250 return c.builder.CreateExtractValue(cplx, 0, "real"), nil 1251 case "recover": 1252 return c.createRuntimeCall("_recover", nil, ""), nil 1253 case "ssa:wrapnilchk": 1254 // TODO: do an actual nil check? 1255 return c.parseExpr(frame, args[0]) 1256 default: 1257 return llvm.Value{}, c.makeError(pos, "todo: builtin: "+callName) 1258 } 1259 } 1260 1261 func (c *Compiler) parseFunctionCall(frame *Frame, args []ssa.Value, llvmFn, context llvm.Value, exported bool) (llvm.Value, error) { 1262 var params []llvm.Value 1263 for _, param := range args { 1264 val, err := c.parseExpr(frame, param) 1265 if err != nil { 1266 return llvm.Value{}, err 1267 } 1268 params = append(params, val) 1269 } 1270 1271 if !exported { 1272 // This function takes a context parameter. 1273 // Add it to the end of the parameter list. 1274 params = append(params, context) 1275 1276 // Parent coroutine handle. 1277 params = append(params, llvm.Undef(c.i8ptrType)) 1278 } 1279 1280 return c.createCall(llvmFn, params, ""), nil 1281 } 1282 1283 func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, error) { 1284 if instr.IsInvoke() { 1285 fnCast, args, err := c.getInvokeCall(frame, instr) 1286 if err != nil { 1287 return llvm.Value{}, err 1288 } 1289 return c.createCall(fnCast, args, ""), nil 1290 } 1291 1292 // Try to call the function directly for trivially static calls. 1293 if fn := instr.StaticCallee(); fn != nil { 1294 switch fn.RelString(nil) { 1295 case "device/arm.ReadRegister": 1296 return c.emitReadRegister(instr.Args) 1297 case "device/arm.Asm", "device/avr.Asm": 1298 return c.emitAsm(instr.Args) 1299 case "device/arm.AsmFull", "device/avr.AsmFull": 1300 return c.emitAsmFull(frame, instr) 1301 case "device/arm.SVCall0", "device/arm.SVCall1", "device/arm.SVCall2", "device/arm.SVCall3", "device/arm.SVCall4": 1302 return c.emitSVCall(frame, instr.Args) 1303 case "syscall.Syscall", "syscall.Syscall6", "syscall.Syscall9": 1304 return c.emitSyscall(frame, instr) 1305 } 1306 1307 targetFunc := c.ir.GetFunction(fn) 1308 if targetFunc.LLVMFn.IsNil() { 1309 return llvm.Value{}, c.makeError(instr.Pos(), "undefined function: "+targetFunc.LinkName()) 1310 } 1311 var context llvm.Value 1312 switch value := instr.Value.(type) { 1313 case *ssa.Function: 1314 // Regular function call. No context is necessary. 1315 context = llvm.Undef(c.i8ptrType) 1316 case *ssa.MakeClosure: 1317 // A call on a func value, but the callee is trivial to find. For 1318 // example: immediately applied functions. 1319 funcValue, err := c.parseExpr(frame, value) 1320 if err != nil { 1321 return llvm.Value{}, err 1322 } 1323 context = c.extractFuncContext(funcValue) 1324 default: 1325 panic("StaticCallee returned an unexpected value") 1326 } 1327 return c.parseFunctionCall(frame, instr.Args, targetFunc.LLVMFn, context, targetFunc.IsExported()) 1328 } 1329 1330 // Builtin or function pointer. 1331 switch call := instr.Value.(type) { 1332 case *ssa.Builtin: 1333 return c.parseBuiltin(frame, instr.Args, call.Name(), instr.Pos()) 1334 default: // function pointer 1335 value, err := c.parseExpr(frame, instr.Value) 1336 if err != nil { 1337 return llvm.Value{}, err 1338 } 1339 // This is a func value, which cannot be called directly. We have to 1340 // extract the function pointer and context first from the func value. 1341 funcPtr, context, err := c.decodeFuncValue(value, instr.Value.Type().(*types.Signature)) 1342 if err != nil { 1343 return llvm.Value{}, err 1344 } 1345 c.emitNilCheck(frame, funcPtr, "fpcall") 1346 return c.parseFunctionCall(frame, instr.Args, funcPtr, context, false) 1347 } 1348 } 1349 1350 func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) { 1351 if value, ok := frame.locals[expr]; ok { 1352 // Value is a local variable that has already been computed. 1353 if value.IsNil() { 1354 return llvm.Value{}, c.makeError(expr.Pos(), "undefined local var (from cgo?)") 1355 } 1356 return value, nil 1357 } 1358 1359 switch expr := expr.(type) { 1360 case *ssa.Alloc: 1361 typ, err := c.getLLVMType(expr.Type().Underlying().(*types.Pointer).Elem()) 1362 if err != nil { 1363 return llvm.Value{}, err 1364 } 1365 var buf llvm.Value 1366 if expr.Heap { 1367 size := c.targetData.TypeAllocSize(typ) 1368 // Calculate ^uintptr(0) 1369 maxSize := llvm.ConstNot(llvm.ConstInt(c.uintptrType, 0, false)).ZExtValue() 1370 if size > maxSize { 1371 // Size would be truncated if truncated to uintptr. 1372 return llvm.Value{}, c.makeError(expr.Pos(), fmt.Sprintf("value is too big (%v bytes)", size)) 1373 } 1374 // TODO: escape analysis 1375 sizeValue := llvm.ConstInt(c.uintptrType, size, false) 1376 buf = c.createRuntimeCall("alloc", []llvm.Value{sizeValue}, expr.Comment) 1377 buf = c.builder.CreateBitCast(buf, llvm.PointerType(typ, 0), "") 1378 } else { 1379 buf = c.builder.CreateAlloca(typ, expr.Comment) 1380 if c.targetData.TypeAllocSize(typ) != 0 { 1381 zero, err := c.getZeroValue(typ) 1382 if err != nil { 1383 return llvm.Value{}, err 1384 } 1385 c.builder.CreateStore(zero, buf) // zero-initialize var 1386 } 1387 } 1388 return buf, nil 1389 case *ssa.BinOp: 1390 x, err := c.parseExpr(frame, expr.X) 1391 if err != nil { 1392 return llvm.Value{}, err 1393 } 1394 y, err := c.parseExpr(frame, expr.Y) 1395 if err != nil { 1396 return llvm.Value{}, err 1397 } 1398 return c.parseBinOp(expr.Op, expr.X.Type(), x, y, expr.Pos()) 1399 case *ssa.Call: 1400 // Passing the current task here to the subroutine. It is only used when 1401 // the subroutine is blocking. 1402 return c.parseCall(frame, expr.Common()) 1403 case *ssa.ChangeInterface: 1404 // Do not change between interface types: always use the underlying 1405 // (concrete) type in the type number of the interface. Every method 1406 // call on an interface will do a lookup which method to call. 1407 // This is different from how the official Go compiler works, because of 1408 // heap allocation and because it's easier to implement, see: 1409 // https://research.swtch.com/interfaces 1410 return c.parseExpr(frame, expr.X) 1411 case *ssa.ChangeType: 1412 // This instruction changes the type, but the underlying value remains 1413 // the same. This is often a no-op, but sometimes we have to change the 1414 // LLVM type as well. 1415 x, err := c.parseExpr(frame, expr.X) 1416 if err != nil { 1417 return llvm.Value{}, err 1418 } 1419 llvmType, err := c.getLLVMType(expr.Type()) 1420 if err != nil { 1421 return llvm.Value{}, err 1422 } 1423 if x.Type() == llvmType { 1424 // Different Go type but same LLVM type (for example, named int). 1425 // This is the common case. 1426 return x, nil 1427 } 1428 // Figure out what kind of type we need to cast. 1429 switch llvmType.TypeKind() { 1430 case llvm.StructTypeKind: 1431 // Unfortunately, we can't just bitcast structs. We have to 1432 // actually create a new struct of the correct type and insert the 1433 // values from the previous struct in there. 1434 value := llvm.Undef(llvmType) 1435 for i := 0; i < llvmType.StructElementTypesCount(); i++ { 1436 field := c.builder.CreateExtractValue(x, i, "changetype.field") 1437 value = c.builder.CreateInsertValue(value, field, i, "changetype.struct") 1438 } 1439 return value, nil 1440 case llvm.PointerTypeKind: 1441 // This can happen with pointers to structs. This case is easy: 1442 // simply bitcast the pointer to the destination type. 1443 return c.builder.CreateBitCast(x, llvmType, "changetype.pointer"), nil 1444 default: 1445 return llvm.Value{}, errors.New("todo: unknown ChangeType type: " + expr.X.Type().String()) 1446 } 1447 case *ssa.Const: 1448 return c.parseConst(frame.fn.LinkName(), expr) 1449 case *ssa.Convert: 1450 x, err := c.parseExpr(frame, expr.X) 1451 if err != nil { 1452 return llvm.Value{}, err 1453 } 1454 return c.parseConvert(expr.X.Type(), expr.Type(), x, expr.Pos()) 1455 case *ssa.Extract: 1456 value, err := c.parseExpr(frame, expr.Tuple) 1457 if err != nil { 1458 return llvm.Value{}, err 1459 } 1460 result := c.builder.CreateExtractValue(value, expr.Index, "") 1461 return result, nil 1462 case *ssa.Field: 1463 value, err := c.parseExpr(frame, expr.X) 1464 if err != nil { 1465 return llvm.Value{}, err 1466 } 1467 if s := expr.X.Type().Underlying().(*types.Struct); s.NumFields() > 2 && s.Field(0).Name() == "C union" { 1468 // Extract a field from a CGo union. 1469 // This could be done directly, but as this is a very infrequent 1470 // operation it's much easier to bitcast it through an alloca. 1471 resultType, err := c.getLLVMType(expr.Type()) 1472 if err != nil { 1473 return llvm.Value{}, err 1474 } 1475 alloca := c.builder.CreateAlloca(value.Type(), "") 1476 c.builder.CreateStore(value, alloca) 1477 bitcast := c.builder.CreateBitCast(alloca, llvm.PointerType(resultType, 0), "") 1478 return c.builder.CreateLoad(bitcast, ""), nil 1479 } 1480 result := c.builder.CreateExtractValue(value, expr.Field, "") 1481 return result, nil 1482 case *ssa.FieldAddr: 1483 val, err := c.parseExpr(frame, expr.X) 1484 if err != nil { 1485 return llvm.Value{}, err 1486 } 1487 // Check for nil pointer before calculating the address, from the spec: 1488 // > For an operand x of type T, the address operation &x generates a 1489 // > pointer of type *T to x. [...] If the evaluation of x would cause a 1490 // > run-time panic, then the evaluation of &x does too. 1491 c.emitNilCheck(frame, val, "gep") 1492 if s := expr.X.Type().(*types.Pointer).Elem().Underlying().(*types.Struct); s.NumFields() > 2 && s.Field(0).Name() == "C union" { 1493 // This is not a regular struct but actually an union. 1494 // That simplifies things, as we can just bitcast the pointer to the 1495 // right type. 1496 ptrType, err := c.getLLVMType(expr.Type()) 1497 if err != nil { 1498 return llvm.Value{}, nil 1499 } 1500 return c.builder.CreateBitCast(val, ptrType, ""), nil 1501 } else { 1502 // Do a GEP on the pointer to get the field address. 1503 indices := []llvm.Value{ 1504 llvm.ConstInt(c.ctx.Int32Type(), 0, false), 1505 llvm.ConstInt(c.ctx.Int32Type(), uint64(expr.Field), false), 1506 } 1507 return c.builder.CreateGEP(val, indices, ""), nil 1508 } 1509 case *ssa.Function: 1510 fn := c.ir.GetFunction(expr) 1511 if fn.IsExported() { 1512 return llvm.Value{}, c.makeError(expr.Pos(), "cannot use an exported function as value") 1513 } 1514 return c.createFuncValue(fn.LLVMFn, llvm.Undef(c.i8ptrType), fn.Signature) 1515 case *ssa.Global: 1516 value := c.ir.GetGlobal(expr).LLVMGlobal 1517 if value.IsNil() { 1518 return llvm.Value{}, c.makeError(expr.Pos(), "global not found: "+c.ir.GetGlobal(expr).LinkName()) 1519 } 1520 return value, nil 1521 case *ssa.Index: 1522 array, err := c.parseExpr(frame, expr.X) 1523 if err != nil { 1524 return llvm.Value{}, err 1525 } 1526 index, err := c.parseExpr(frame, expr.Index) 1527 if err != nil { 1528 return llvm.Value{}, err 1529 } 1530 1531 // Check bounds. 1532 arrayLen := expr.X.Type().(*types.Array).Len() 1533 arrayLenLLVM := llvm.ConstInt(c.uintptrType, uint64(arrayLen), false) 1534 c.emitLookupBoundsCheck(frame, arrayLenLLVM, index, expr.Index.Type()) 1535 1536 // Can't load directly from array (as index is non-constant), so have to 1537 // do it using an alloca+gep+load. 1538 alloca := c.builder.CreateAlloca(array.Type(), "index.alloca") 1539 c.builder.CreateStore(array, alloca) 1540 zero := llvm.ConstInt(c.ctx.Int32Type(), 0, false) 1541 ptr := c.builder.CreateGEP(alloca, []llvm.Value{zero, index}, "index.gep") 1542 return c.builder.CreateLoad(ptr, "index.load"), nil 1543 case *ssa.IndexAddr: 1544 val, err := c.parseExpr(frame, expr.X) 1545 if err != nil { 1546 return llvm.Value{}, err 1547 } 1548 index, err := c.parseExpr(frame, expr.Index) 1549 if err != nil { 1550 return llvm.Value{}, err 1551 } 1552 1553 // Get buffer pointer and length 1554 var bufptr, buflen llvm.Value 1555 switch ptrTyp := expr.X.Type().Underlying().(type) { 1556 case *types.Pointer: 1557 typ := expr.X.Type().Underlying().(*types.Pointer).Elem().Underlying() 1558 switch typ := typ.(type) { 1559 case *types.Array: 1560 bufptr = val 1561 buflen = llvm.ConstInt(c.uintptrType, uint64(typ.Len()), false) 1562 // Check for nil pointer before calculating the address, from 1563 // the spec: 1564 // > For an operand x of type T, the address operation &x 1565 // > generates a pointer of type *T to x. [...] If the 1566 // > evaluation of x would cause a run-time panic, then the 1567 // > evaluation of &x does too. 1568 c.emitNilCheck(frame, bufptr, "gep") 1569 default: 1570 return llvm.Value{}, c.makeError(expr.Pos(), "todo: indexaddr: "+typ.String()) 1571 } 1572 case *types.Slice: 1573 bufptr = c.builder.CreateExtractValue(val, 0, "indexaddr.ptr") 1574 buflen = c.builder.CreateExtractValue(val, 1, "indexaddr.len") 1575 default: 1576 return llvm.Value{}, c.makeError(expr.Pos(), "todo: indexaddr: "+ptrTyp.String()) 1577 } 1578 1579 // Bounds check. 1580 c.emitLookupBoundsCheck(frame, buflen, index, expr.Index.Type()) 1581 1582 switch expr.X.Type().Underlying().(type) { 1583 case *types.Pointer: 1584 indices := []llvm.Value{ 1585 llvm.ConstInt(c.ctx.Int32Type(), 0, false), 1586 index, 1587 } 1588 return c.builder.CreateGEP(bufptr, indices, ""), nil 1589 case *types.Slice: 1590 return c.builder.CreateGEP(bufptr, []llvm.Value{index}, ""), nil 1591 default: 1592 panic("unreachable") 1593 } 1594 case *ssa.Lookup: 1595 value, err := c.parseExpr(frame, expr.X) 1596 if err != nil { 1597 return llvm.Value{}, nil 1598 } 1599 index, err := c.parseExpr(frame, expr.Index) 1600 if err != nil { 1601 return llvm.Value{}, nil 1602 } 1603 switch xType := expr.X.Type().Underlying().(type) { 1604 case *types.Basic: 1605 // Value type must be a string, which is a basic type. 1606 if xType.Info()&types.IsString == 0 { 1607 panic("lookup on non-string?") 1608 } 1609 1610 // Bounds check. 1611 length := c.builder.CreateExtractValue(value, 1, "len") 1612 c.emitLookupBoundsCheck(frame, length, index, expr.Index.Type()) 1613 1614 // Lookup byte 1615 buf := c.builder.CreateExtractValue(value, 0, "") 1616 bufPtr := c.builder.CreateGEP(buf, []llvm.Value{index}, "") 1617 return c.builder.CreateLoad(bufPtr, ""), nil 1618 case *types.Map: 1619 valueType := expr.Type() 1620 if expr.CommaOk { 1621 valueType = valueType.(*types.Tuple).At(0).Type() 1622 } 1623 return c.emitMapLookup(xType.Key(), valueType, value, index, expr.CommaOk, expr.Pos()) 1624 default: 1625 panic("unknown lookup type: " + expr.String()) 1626 } 1627 case *ssa.MakeChan: 1628 return c.emitMakeChan(expr) 1629 case *ssa.MakeClosure: 1630 return c.parseMakeClosure(frame, expr) 1631 case *ssa.MakeInterface: 1632 val, err := c.parseExpr(frame, expr.X) 1633 if err != nil { 1634 return llvm.Value{}, err 1635 } 1636 return c.parseMakeInterface(val, expr.X.Type(), expr.Pos()) 1637 case *ssa.MakeMap: 1638 mapType := expr.Type().Underlying().(*types.Map) 1639 llvmKeyType, err := c.getLLVMType(mapType.Key().Underlying()) 1640 if err != nil { 1641 return llvm.Value{}, err 1642 } 1643 llvmValueType, err := c.getLLVMType(mapType.Elem().Underlying()) 1644 if err != nil { 1645 return llvm.Value{}, err 1646 } 1647 keySize := c.targetData.TypeAllocSize(llvmKeyType) 1648 valueSize := c.targetData.TypeAllocSize(llvmValueType) 1649 llvmKeySize := llvm.ConstInt(c.ctx.Int8Type(), keySize, false) 1650 llvmValueSize := llvm.ConstInt(c.ctx.Int8Type(), valueSize, false) 1651 hashmap := c.createRuntimeCall("hashmapMake", []llvm.Value{llvmKeySize, llvmValueSize}, "") 1652 return hashmap, nil 1653 case *ssa.MakeSlice: 1654 sliceLen, err := c.parseExpr(frame, expr.Len) 1655 if err != nil { 1656 return llvm.Value{}, nil 1657 } 1658 sliceCap, err := c.parseExpr(frame, expr.Cap) 1659 if err != nil { 1660 return llvm.Value{}, nil 1661 } 1662 sliceType := expr.Type().Underlying().(*types.Slice) 1663 llvmElemType, err := c.getLLVMType(sliceType.Elem()) 1664 if err != nil { 1665 return llvm.Value{}, nil 1666 } 1667 elemSize := c.targetData.TypeAllocSize(llvmElemType) 1668 elemSizeValue := llvm.ConstInt(c.uintptrType, elemSize, false) 1669 1670 // Calculate (^uintptr(0)) >> 1, which is the max value that fits in 1671 // uintptr if uintptr were signed. 1672 maxSize := llvm.ConstLShr(llvm.ConstNot(llvm.ConstInt(c.uintptrType, 0, false)), llvm.ConstInt(c.uintptrType, 1, false)) 1673 if elemSize > maxSize.ZExtValue() { 1674 // This seems to be checked by the typechecker already, but let's 1675 // check it again just to be sure. 1676 return llvm.Value{}, c.makeError(expr.Pos(), fmt.Sprintf("slice element type is too big (%v bytes)", elemSize)) 1677 } 1678 1679 // Bounds checking. 1680 c.emitSliceBoundsCheck(frame, maxSize, sliceLen, sliceCap, expr.Len.Type().(*types.Basic), expr.Cap.Type().(*types.Basic)) 1681 1682 // Allocate the backing array. 1683 // TODO: escape analysis 1684 sliceCapCast, err := c.parseConvert(expr.Cap.Type(), types.Typ[types.Uintptr], sliceCap, expr.Pos()) 1685 if err != nil { 1686 return llvm.Value{}, err 1687 } 1688 sliceSize := c.builder.CreateBinOp(llvm.Mul, elemSizeValue, sliceCapCast, "makeslice.cap") 1689 slicePtr := c.createRuntimeCall("alloc", []llvm.Value{sliceSize}, "makeslice.buf") 1690 slicePtr = c.builder.CreateBitCast(slicePtr, llvm.PointerType(llvmElemType, 0), "makeslice.array") 1691 1692 // Extend or truncate if necessary. This is safe as we've already done 1693 // the bounds check. 1694 sliceLen, err = c.parseConvert(expr.Len.Type(), types.Typ[types.Uintptr], sliceLen, expr.Pos()) 1695 if err != nil { 1696 return llvm.Value{}, err 1697 } 1698 sliceCap, err = c.parseConvert(expr.Cap.Type(), types.Typ[types.Uintptr], sliceCap, expr.Pos()) 1699 if err != nil { 1700 return llvm.Value{}, err 1701 } 1702 1703 // Create the slice. 1704 slice := c.ctx.ConstStruct([]llvm.Value{ 1705 llvm.Undef(slicePtr.Type()), 1706 llvm.Undef(c.uintptrType), 1707 llvm.Undef(c.uintptrType), 1708 }, false) 1709 slice = c.builder.CreateInsertValue(slice, slicePtr, 0, "") 1710 slice = c.builder.CreateInsertValue(slice, sliceLen, 1, "") 1711 slice = c.builder.CreateInsertValue(slice, sliceCap, 2, "") 1712 return slice, nil 1713 case *ssa.Next: 1714 rangeVal := expr.Iter.(*ssa.Range).X 1715 llvmRangeVal, err := c.parseExpr(frame, rangeVal) 1716 if err != nil { 1717 return llvm.Value{}, err 1718 } 1719 it, err := c.parseExpr(frame, expr.Iter) 1720 if err != nil { 1721 return llvm.Value{}, err 1722 } 1723 if expr.IsString { 1724 return c.createRuntimeCall("stringNext", []llvm.Value{llvmRangeVal, it}, "range.next"), nil 1725 } else { // map 1726 llvmKeyType, err := c.getLLVMType(rangeVal.Type().Underlying().(*types.Map).Key()) 1727 if err != nil { 1728 return llvm.Value{}, err 1729 } 1730 llvmValueType, err := c.getLLVMType(rangeVal.Type().Underlying().(*types.Map).Elem()) 1731 if err != nil { 1732 return llvm.Value{}, err 1733 } 1734 1735 mapKeyAlloca := c.builder.CreateAlloca(llvmKeyType, "range.key") 1736 mapKeyPtr := c.builder.CreateBitCast(mapKeyAlloca, c.i8ptrType, "range.keyptr") 1737 mapValueAlloca := c.builder.CreateAlloca(llvmValueType, "range.value") 1738 mapValuePtr := c.builder.CreateBitCast(mapValueAlloca, c.i8ptrType, "range.valueptr") 1739 ok := c.createRuntimeCall("hashmapNext", []llvm.Value{llvmRangeVal, it, mapKeyPtr, mapValuePtr}, "range.next") 1740 1741 tuple := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.Int1Type(), llvmKeyType, llvmValueType}, false)) 1742 tuple = c.builder.CreateInsertValue(tuple, ok, 0, "") 1743 tuple = c.builder.CreateInsertValue(tuple, c.builder.CreateLoad(mapKeyAlloca, ""), 1, "") 1744 tuple = c.builder.CreateInsertValue(tuple, c.builder.CreateLoad(mapValueAlloca, ""), 2, "") 1745 return tuple, nil 1746 } 1747 case *ssa.Phi: 1748 t, err := c.getLLVMType(expr.Type()) 1749 if err != nil { 1750 return llvm.Value{}, err 1751 } 1752 phi := c.builder.CreatePHI(t, "") 1753 frame.phis = append(frame.phis, Phi{expr, phi}) 1754 return phi, nil 1755 case *ssa.Range: 1756 var iteratorType llvm.Type 1757 switch typ := expr.X.Type().Underlying().(type) { 1758 case *types.Basic: // string 1759 iteratorType = c.mod.GetTypeByName("runtime.stringIterator") 1760 case *types.Map: 1761 iteratorType = c.mod.GetTypeByName("runtime.hashmapIterator") 1762 default: 1763 panic("unknown type in range: " + typ.String()) 1764 } 1765 it := c.builder.CreateAlloca(iteratorType, "range.it") 1766 zero, err := c.getZeroValue(iteratorType) 1767 if err != nil { 1768 return llvm.Value{}, nil 1769 } 1770 c.builder.CreateStore(zero, it) 1771 return it, nil 1772 case *ssa.Select: 1773 if len(expr.States) == 0 { 1774 // Shortcuts for some simple selects. 1775 llvmType, err := c.getLLVMType(expr.Type()) 1776 if err != nil { 1777 return llvm.Value{}, err 1778 } 1779 if expr.Blocking { 1780 // Blocks forever: 1781 // select {} 1782 c.createRuntimeCall("deadlockStub", nil, "") 1783 return llvm.Undef(llvmType), nil 1784 } else { 1785 // No-op: 1786 // select { 1787 // default: 1788 // } 1789 retval := llvm.Undef(llvmType) 1790 retval = c.builder.CreateInsertValue(retval, llvm.ConstInt(c.intType, 0xffffffffffffffff, true), 0, "") 1791 return retval, nil // {-1, false} 1792 } 1793 } 1794 return llvm.Value{}, c.makeError(expr.Pos(), "unimplemented: "+expr.String()) 1795 case *ssa.Slice: 1796 if expr.Max != nil { 1797 return llvm.Value{}, c.makeError(expr.Pos(), "todo: full slice expressions (with max): "+expr.Type().String()) 1798 } 1799 value, err := c.parseExpr(frame, expr.X) 1800 if err != nil { 1801 return llvm.Value{}, err 1802 } 1803 1804 var lowType, highType *types.Basic 1805 var low, high llvm.Value 1806 1807 if expr.Low != nil { 1808 lowType = expr.Low.Type().Underlying().(*types.Basic) 1809 low, err = c.parseExpr(frame, expr.Low) 1810 if err != nil { 1811 return llvm.Value{}, nil 1812 } 1813 if low.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() { 1814 if lowType.Info()&types.IsUnsigned != 0 { 1815 low = c.builder.CreateZExt(low, c.uintptrType, "") 1816 } else { 1817 low = c.builder.CreateSExt(low, c.uintptrType, "") 1818 } 1819 } 1820 } else { 1821 lowType = types.Typ[types.Uintptr] 1822 low = llvm.ConstInt(c.uintptrType, 0, false) 1823 } 1824 1825 if expr.High != nil { 1826 highType = expr.High.Type().Underlying().(*types.Basic) 1827 high, err = c.parseExpr(frame, expr.High) 1828 if err != nil { 1829 return llvm.Value{}, nil 1830 } 1831 if high.Type().IntTypeWidth() < c.uintptrType.IntTypeWidth() { 1832 if highType.Info()&types.IsUnsigned != 0 { 1833 high = c.builder.CreateZExt(high, c.uintptrType, "") 1834 } else { 1835 high = c.builder.CreateSExt(high, c.uintptrType, "") 1836 } 1837 } 1838 } else { 1839 highType = types.Typ[types.Uintptr] 1840 } 1841 1842 switch typ := expr.X.Type().Underlying().(type) { 1843 case *types.Pointer: // pointer to array 1844 // slice an array 1845 length := typ.Elem().Underlying().(*types.Array).Len() 1846 llvmLen := llvm.ConstInt(c.uintptrType, uint64(length), false) 1847 if high.IsNil() { 1848 high = llvmLen 1849 } 1850 indices := []llvm.Value{ 1851 llvm.ConstInt(c.ctx.Int32Type(), 0, false), 1852 low, 1853 } 1854 1855 c.emitSliceBoundsCheck(frame, llvmLen, low, high, lowType, highType) 1856 1857 // Truncate ints bigger than uintptr. This is after the bounds 1858 // check so it's safe. 1859 if c.targetData.TypeAllocSize(high.Type()) > c.targetData.TypeAllocSize(c.uintptrType) { 1860 high = c.builder.CreateTrunc(high, c.uintptrType, "") 1861 } 1862 if c.targetData.TypeAllocSize(low.Type()) > c.targetData.TypeAllocSize(c.uintptrType) { 1863 low = c.builder.CreateTrunc(low, c.uintptrType, "") 1864 } 1865 1866 sliceLen := c.builder.CreateSub(high, low, "slice.len") 1867 slicePtr := c.builder.CreateGEP(value, indices, "slice.ptr") 1868 sliceCap := c.builder.CreateSub(llvmLen, low, "slice.cap") 1869 1870 slice := c.ctx.ConstStruct([]llvm.Value{ 1871 llvm.Undef(slicePtr.Type()), 1872 llvm.Undef(c.uintptrType), 1873 llvm.Undef(c.uintptrType), 1874 }, false) 1875 slice = c.builder.CreateInsertValue(slice, slicePtr, 0, "") 1876 slice = c.builder.CreateInsertValue(slice, sliceLen, 1, "") 1877 slice = c.builder.CreateInsertValue(slice, sliceCap, 2, "") 1878 return slice, nil 1879 1880 case *types.Slice: 1881 // slice a slice 1882 oldPtr := c.builder.CreateExtractValue(value, 0, "") 1883 oldLen := c.builder.CreateExtractValue(value, 1, "") 1884 oldCap := c.builder.CreateExtractValue(value, 2, "") 1885 if high.IsNil() { 1886 high = oldLen 1887 } 1888 1889 c.emitSliceBoundsCheck(frame, oldCap, low, high, lowType, highType) 1890 1891 // Truncate ints bigger than uintptr. This is after the bounds 1892 // check so it's safe. 1893 if c.targetData.TypeAllocSize(low.Type()) > c.targetData.TypeAllocSize(c.uintptrType) { 1894 low = c.builder.CreateTrunc(low, c.uintptrType, "") 1895 } 1896 if c.targetData.TypeAllocSize(high.Type()) > c.targetData.TypeAllocSize(c.uintptrType) { 1897 high = c.builder.CreateTrunc(high, c.uintptrType, "") 1898 } 1899 1900 newPtr := c.builder.CreateGEP(oldPtr, []llvm.Value{low}, "") 1901 newLen := c.builder.CreateSub(high, low, "") 1902 newCap := c.builder.CreateSub(oldCap, low, "") 1903 slice := c.ctx.ConstStruct([]llvm.Value{ 1904 llvm.Undef(newPtr.Type()), 1905 llvm.Undef(c.uintptrType), 1906 llvm.Undef(c.uintptrType), 1907 }, false) 1908 slice = c.builder.CreateInsertValue(slice, newPtr, 0, "") 1909 slice = c.builder.CreateInsertValue(slice, newLen, 1, "") 1910 slice = c.builder.CreateInsertValue(slice, newCap, 2, "") 1911 return slice, nil 1912 1913 case *types.Basic: 1914 if typ.Info()&types.IsString == 0 { 1915 return llvm.Value{}, c.makeError(expr.Pos(), "unknown slice type: "+typ.String()) 1916 } 1917 // slice a string 1918 oldPtr := c.builder.CreateExtractValue(value, 0, "") 1919 oldLen := c.builder.CreateExtractValue(value, 1, "") 1920 if high.IsNil() { 1921 high = oldLen 1922 } 1923 1924 c.emitSliceBoundsCheck(frame, oldLen, low, high, lowType, highType) 1925 1926 // Truncate ints bigger than uintptr. This is after the bounds 1927 // check so it's safe. 1928 if c.targetData.TypeAllocSize(low.Type()) > c.targetData.TypeAllocSize(c.uintptrType) { 1929 low = c.builder.CreateTrunc(low, c.uintptrType, "") 1930 } 1931 if c.targetData.TypeAllocSize(high.Type()) > c.targetData.TypeAllocSize(c.uintptrType) { 1932 high = c.builder.CreateTrunc(high, c.uintptrType, "") 1933 } 1934 1935 newPtr := c.builder.CreateGEP(oldPtr, []llvm.Value{low}, "") 1936 newLen := c.builder.CreateSub(high, low, "") 1937 str, err := c.getZeroValue(c.mod.GetTypeByName("runtime._string")) 1938 if err != nil { 1939 return llvm.Value{}, err 1940 } 1941 str = c.builder.CreateInsertValue(str, newPtr, 0, "") 1942 str = c.builder.CreateInsertValue(str, newLen, 1, "") 1943 return str, nil 1944 1945 default: 1946 return llvm.Value{}, c.makeError(expr.Pos(), "unknown slice type: "+typ.String()) 1947 } 1948 case *ssa.TypeAssert: 1949 return c.parseTypeAssert(frame, expr) 1950 case *ssa.UnOp: 1951 return c.parseUnOp(frame, expr) 1952 default: 1953 return llvm.Value{}, c.makeError(expr.Pos(), "todo: unknown expression: "+expr.String()) 1954 } 1955 } 1956 1957 func (c *Compiler) parseBinOp(op token.Token, typ types.Type, x, y llvm.Value, pos token.Pos) (llvm.Value, error) { 1958 switch typ := typ.Underlying().(type) { 1959 case *types.Basic: 1960 if typ.Info()&types.IsInteger != 0 { 1961 // Operations on integers 1962 signed := typ.Info()&types.IsUnsigned == 0 1963 switch op { 1964 case token.ADD: // + 1965 return c.builder.CreateAdd(x, y, ""), nil 1966 case token.SUB: // - 1967 return c.builder.CreateSub(x, y, ""), nil 1968 case token.MUL: // * 1969 return c.builder.CreateMul(x, y, ""), nil 1970 case token.QUO: // / 1971 if signed { 1972 return c.builder.CreateSDiv(x, y, ""), nil 1973 } else { 1974 return c.builder.CreateUDiv(x, y, ""), nil 1975 } 1976 case token.REM: // % 1977 if signed { 1978 return c.builder.CreateSRem(x, y, ""), nil 1979 } else { 1980 return c.builder.CreateURem(x, y, ""), nil 1981 } 1982 case token.AND: // & 1983 return c.builder.CreateAnd(x, y, ""), nil 1984 case token.OR: // | 1985 return c.builder.CreateOr(x, y, ""), nil 1986 case token.XOR: // ^ 1987 return c.builder.CreateXor(x, y, ""), nil 1988 case token.SHL, token.SHR: 1989 sizeX := c.targetData.TypeAllocSize(x.Type()) 1990 sizeY := c.targetData.TypeAllocSize(y.Type()) 1991 if sizeX > sizeY { 1992 // x and y must have equal sizes, make Y bigger in this case. 1993 // y is unsigned, this has been checked by the Go type checker. 1994 y = c.builder.CreateZExt(y, x.Type(), "") 1995 } else if sizeX < sizeY { 1996 // What about shifting more than the integer width? 1997 // I'm not entirely sure what the Go spec is on that, but as 1998 // Intel CPUs have undefined behavior when shifting more 1999 // than the integer width I'm assuming it is also undefined 2000 // in Go. 2001 y = c.builder.CreateTrunc(y, x.Type(), "") 2002 } 2003 switch op { 2004 case token.SHL: // << 2005 return c.builder.CreateShl(x, y, ""), nil 2006 case token.SHR: // >> 2007 if signed { 2008 return c.builder.CreateAShr(x, y, ""), nil 2009 } else { 2010 return c.builder.CreateLShr(x, y, ""), nil 2011 } 2012 default: 2013 panic("unreachable") 2014 } 2015 case token.EQL: // == 2016 return c.builder.CreateICmp(llvm.IntEQ, x, y, ""), nil 2017 case token.NEQ: // != 2018 return c.builder.CreateICmp(llvm.IntNE, x, y, ""), nil 2019 case token.AND_NOT: // &^ 2020 // Go specific. Calculate "and not" with x & (~y) 2021 inv := c.builder.CreateNot(y, "") // ~y 2022 return c.builder.CreateAnd(x, inv, ""), nil 2023 case token.LSS: // < 2024 if signed { 2025 return c.builder.CreateICmp(llvm.IntSLT, x, y, ""), nil 2026 } else { 2027 return c.builder.CreateICmp(llvm.IntULT, x, y, ""), nil 2028 } 2029 case token.LEQ: // <= 2030 if signed { 2031 return c.builder.CreateICmp(llvm.IntSLE, x, y, ""), nil 2032 } else { 2033 return c.builder.CreateICmp(llvm.IntULE, x, y, ""), nil 2034 } 2035 case token.GTR: // > 2036 if signed { 2037 return c.builder.CreateICmp(llvm.IntSGT, x, y, ""), nil 2038 } else { 2039 return c.builder.CreateICmp(llvm.IntUGT, x, y, ""), nil 2040 } 2041 case token.GEQ: // >= 2042 if signed { 2043 return c.builder.CreateICmp(llvm.IntSGE, x, y, ""), nil 2044 } else { 2045 return c.builder.CreateICmp(llvm.IntUGE, x, y, ""), nil 2046 } 2047 default: 2048 panic("binop on integer: " + op.String()) 2049 } 2050 } else if typ.Info()&types.IsFloat != 0 { 2051 // Operations on floats 2052 switch op { 2053 case token.ADD: // + 2054 return c.builder.CreateFAdd(x, y, ""), nil 2055 case token.SUB: // - 2056 return c.builder.CreateFSub(x, y, ""), nil 2057 case token.MUL: // * 2058 return c.builder.CreateFMul(x, y, ""), nil 2059 case token.QUO: // / 2060 return c.builder.CreateFDiv(x, y, ""), nil 2061 case token.EQL: // == 2062 return c.builder.CreateFCmp(llvm.FloatUEQ, x, y, ""), nil 2063 case token.NEQ: // != 2064 return c.builder.CreateFCmp(llvm.FloatUNE, x, y, ""), nil 2065 case token.LSS: // < 2066 return c.builder.CreateFCmp(llvm.FloatULT, x, y, ""), nil 2067 case token.LEQ: // <= 2068 return c.builder.CreateFCmp(llvm.FloatULE, x, y, ""), nil 2069 case token.GTR: // > 2070 return c.builder.CreateFCmp(llvm.FloatUGT, x, y, ""), nil 2071 case token.GEQ: // >= 2072 return c.builder.CreateFCmp(llvm.FloatUGE, x, y, ""), nil 2073 default: 2074 panic("binop on float: " + op.String()) 2075 } 2076 } else if typ.Info()&types.IsComplex != 0 { 2077 r1 := c.builder.CreateExtractValue(x, 0, "r1") 2078 r2 := c.builder.CreateExtractValue(y, 0, "r2") 2079 i1 := c.builder.CreateExtractValue(x, 1, "i1") 2080 i2 := c.builder.CreateExtractValue(y, 1, "i2") 2081 switch op { 2082 case token.EQL: // == 2083 req := c.builder.CreateFCmp(llvm.FloatOEQ, r1, r2, "") 2084 ieq := c.builder.CreateFCmp(llvm.FloatOEQ, i1, i2, "") 2085 return c.builder.CreateAnd(req, ieq, ""), nil 2086 case token.NEQ: // != 2087 req := c.builder.CreateFCmp(llvm.FloatOEQ, r1, r2, "") 2088 ieq := c.builder.CreateFCmp(llvm.FloatOEQ, i1, i2, "") 2089 neq := c.builder.CreateAnd(req, ieq, "") 2090 return c.builder.CreateNot(neq, ""), nil 2091 default: 2092 return llvm.Value{}, c.makeError(pos, "todo: binop on complex number: "+op.String()) 2093 } 2094 } else if typ.Info()&types.IsBoolean != 0 { 2095 // Operations on booleans 2096 switch op { 2097 case token.EQL: // == 2098 return c.builder.CreateICmp(llvm.IntEQ, x, y, ""), nil 2099 case token.NEQ: // != 2100 return c.builder.CreateICmp(llvm.IntNE, x, y, ""), nil 2101 default: 2102 panic("binop on bool: " + op.String()) 2103 } 2104 } else if typ.Kind() == types.UnsafePointer { 2105 // Operations on pointers 2106 switch op { 2107 case token.EQL: // == 2108 return c.builder.CreateICmp(llvm.IntEQ, x, y, ""), nil 2109 case token.NEQ: // != 2110 return c.builder.CreateICmp(llvm.IntNE, x, y, ""), nil 2111 default: 2112 panic("binop on pointer: " + op.String()) 2113 } 2114 } else if typ.Info()&types.IsString != 0 { 2115 // Operations on strings 2116 switch op { 2117 case token.ADD: // + 2118 return c.createRuntimeCall("stringConcat", []llvm.Value{x, y}, ""), nil 2119 case token.EQL: // == 2120 return c.createRuntimeCall("stringEqual", []llvm.Value{x, y}, ""), nil 2121 case token.NEQ: // != 2122 result := c.createRuntimeCall("stringEqual", []llvm.Value{x, y}, "") 2123 return c.builder.CreateNot(result, ""), nil 2124 case token.LSS: // < 2125 return c.createRuntimeCall("stringLess", []llvm.Value{x, y}, ""), nil 2126 case token.LEQ: // <= 2127 result := c.createRuntimeCall("stringLess", []llvm.Value{y, x}, "") 2128 return c.builder.CreateNot(result, ""), nil 2129 case token.GTR: // > 2130 result := c.createRuntimeCall("stringLess", []llvm.Value{x, y}, "") 2131 return c.builder.CreateNot(result, ""), nil 2132 case token.GEQ: // >= 2133 return c.createRuntimeCall("stringLess", []llvm.Value{y, x}, ""), nil 2134 default: 2135 panic("binop on string: " + op.String()) 2136 } 2137 } else { 2138 return llvm.Value{}, c.makeError(pos, "todo: unknown basic type in binop: "+typ.String()) 2139 } 2140 case *types.Signature: 2141 // Get raw scalars from the function value and compare those. 2142 // Function values may be implemented in multiple ways, but they all 2143 // have some way of getting a scalar value identifying the function. 2144 // This is safe: function pointers are generally not comparable 2145 // against each other, only against nil. So one of these has to be nil. 2146 x = c.extractFuncScalar(x) 2147 y = c.extractFuncScalar(y) 2148 switch op { 2149 case token.EQL: // == 2150 return c.builder.CreateICmp(llvm.IntEQ, x, y, ""), nil 2151 case token.NEQ: // != 2152 return c.builder.CreateICmp(llvm.IntNE, x, y, ""), nil 2153 default: 2154 return llvm.Value{}, c.makeError(pos, "binop on signature: "+op.String()) 2155 } 2156 case *types.Interface: 2157 switch op { 2158 case token.EQL, token.NEQ: // ==, != 2159 result := c.createRuntimeCall("interfaceEqual", []llvm.Value{x, y}, "") 2160 if op == token.NEQ { 2161 result = c.builder.CreateNot(result, "") 2162 } 2163 return result, nil 2164 default: 2165 return llvm.Value{}, c.makeError(pos, "binop on interface: "+op.String()) 2166 } 2167 case *types.Map, *types.Pointer: 2168 // Maps are in general not comparable, but can be compared against nil 2169 // (which is a nil pointer). This means they can be trivially compared 2170 // by treating them as a pointer. 2171 switch op { 2172 case token.EQL: // == 2173 return c.builder.CreateICmp(llvm.IntEQ, x, y, ""), nil 2174 case token.NEQ: // != 2175 return c.builder.CreateICmp(llvm.IntNE, x, y, ""), nil 2176 default: 2177 return llvm.Value{}, c.makeError(pos, "todo: binop on pointer: "+op.String()) 2178 } 2179 case *types.Slice: 2180 // Slices are in general not comparable, but can be compared against 2181 // nil. Assume at least one of them is nil to make the code easier. 2182 xPtr := c.builder.CreateExtractValue(x, 0, "") 2183 yPtr := c.builder.CreateExtractValue(y, 0, "") 2184 switch op { 2185 case token.EQL: // == 2186 return c.builder.CreateICmp(llvm.IntEQ, xPtr, yPtr, ""), nil 2187 case token.NEQ: // != 2188 return c.builder.CreateICmp(llvm.IntNE, xPtr, yPtr, ""), nil 2189 default: 2190 return llvm.Value{}, c.makeError(pos, "todo: binop on slice: "+op.String()) 2191 } 2192 case *types.Array: 2193 // Compare each array element and combine the result. From the spec: 2194 // Array values are comparable if values of the array element type 2195 // are comparable. Two array values are equal if their corresponding 2196 // elements are equal. 2197 result := llvm.ConstInt(c.ctx.Int1Type(), 1, true) 2198 for i := 0; i < int(typ.Len()); i++ { 2199 xField := c.builder.CreateExtractValue(x, i, "") 2200 yField := c.builder.CreateExtractValue(y, i, "") 2201 fieldEqual, err := c.parseBinOp(token.EQL, typ.Elem(), xField, yField, pos) 2202 if err != nil { 2203 return llvm.Value{}, err 2204 } 2205 result = c.builder.CreateAnd(result, fieldEqual, "") 2206 } 2207 switch op { 2208 case token.EQL: // == 2209 return result, nil 2210 case token.NEQ: // != 2211 return c.builder.CreateNot(result, ""), nil 2212 default: 2213 return llvm.Value{}, c.makeError(pos, "unknown: binop on struct: "+op.String()) 2214 } 2215 case *types.Struct: 2216 // Compare each struct field and combine the result. From the spec: 2217 // Struct values are comparable if all their fields are comparable. 2218 // Two struct values are equal if their corresponding non-blank 2219 // fields are equal. 2220 result := llvm.ConstInt(c.ctx.Int1Type(), 1, true) 2221 for i := 0; i < typ.NumFields(); i++ { 2222 if typ.Field(i).Name() == "_" { 2223 // skip blank fields 2224 continue 2225 } 2226 fieldType := typ.Field(i).Type() 2227 xField := c.builder.CreateExtractValue(x, i, "") 2228 yField := c.builder.CreateExtractValue(y, i, "") 2229 fieldEqual, err := c.parseBinOp(token.EQL, fieldType, xField, yField, pos) 2230 if err != nil { 2231 return llvm.Value{}, err 2232 } 2233 result = c.builder.CreateAnd(result, fieldEqual, "") 2234 } 2235 switch op { 2236 case token.EQL: // == 2237 return result, nil 2238 case token.NEQ: // != 2239 return c.builder.CreateNot(result, ""), nil 2240 default: 2241 return llvm.Value{}, c.makeError(pos, "unknown: binop on struct: "+op.String()) 2242 } 2243 default: 2244 return llvm.Value{}, c.makeError(pos, "todo: binop type: "+typ.String()) 2245 } 2246 } 2247 2248 func (c *Compiler) parseConst(prefix string, expr *ssa.Const) (llvm.Value, error) { 2249 switch typ := expr.Type().Underlying().(type) { 2250 case *types.Basic: 2251 llvmType, err := c.getLLVMType(typ) 2252 if err != nil { 2253 return llvm.Value{}, err 2254 } 2255 if typ.Info()&types.IsBoolean != 0 { 2256 b := constant.BoolVal(expr.Value) 2257 n := uint64(0) 2258 if b { 2259 n = 1 2260 } 2261 return llvm.ConstInt(llvmType, n, false), nil 2262 } else if typ.Info()&types.IsString != 0 { 2263 str := constant.StringVal(expr.Value) 2264 strLen := llvm.ConstInt(c.uintptrType, uint64(len(str)), false) 2265 objname := prefix + "$string" 2266 global := llvm.AddGlobal(c.mod, llvm.ArrayType(c.ctx.Int8Type(), len(str)), objname) 2267 global.SetInitializer(c.ctx.ConstString(str, false)) 2268 global.SetLinkage(llvm.InternalLinkage) 2269 global.SetGlobalConstant(true) 2270 global.SetUnnamedAddr(true) 2271 zero := llvm.ConstInt(c.ctx.Int32Type(), 0, false) 2272 strPtr := c.builder.CreateInBoundsGEP(global, []llvm.Value{zero, zero}, "") 2273 strObj := llvm.ConstNamedStruct(c.mod.GetTypeByName("runtime._string"), []llvm.Value{strPtr, strLen}) 2274 return strObj, nil 2275 } else if typ.Kind() == types.UnsafePointer { 2276 if !expr.IsNil() { 2277 value, _ := constant.Uint64Val(expr.Value) 2278 return llvm.ConstIntToPtr(llvm.ConstInt(c.uintptrType, value, false), c.i8ptrType), nil 2279 } 2280 return llvm.ConstNull(c.i8ptrType), nil 2281 } else if typ.Info()&types.IsUnsigned != 0 { 2282 n, _ := constant.Uint64Val(expr.Value) 2283 return llvm.ConstInt(llvmType, n, false), nil 2284 } else if typ.Info()&types.IsInteger != 0 { // signed 2285 n, _ := constant.Int64Val(expr.Value) 2286 return llvm.ConstInt(llvmType, uint64(n), true), nil 2287 } else if typ.Info()&types.IsFloat != 0 { 2288 n, _ := constant.Float64Val(expr.Value) 2289 return llvm.ConstFloat(llvmType, n), nil 2290 } else if typ.Kind() == types.Complex64 { 2291 r, err := c.parseConst(prefix, ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float32])) 2292 if err != nil { 2293 return llvm.Value{}, err 2294 } 2295 i, err := c.parseConst(prefix, ssa.NewConst(constant.Imag(expr.Value), types.Typ[types.Float32])) 2296 if err != nil { 2297 return llvm.Value{}, err 2298 } 2299 cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false)) 2300 cplx = c.builder.CreateInsertValue(cplx, r, 0, "") 2301 cplx = c.builder.CreateInsertValue(cplx, i, 1, "") 2302 return cplx, nil 2303 } else if typ.Kind() == types.Complex128 { 2304 r, err := c.parseConst(prefix, ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float64])) 2305 if err != nil { 2306 return llvm.Value{}, err 2307 } 2308 i, err := c.parseConst(prefix, ssa.NewConst(constant.Imag(expr.Value), types.Typ[types.Float64])) 2309 if err != nil { 2310 return llvm.Value{}, err 2311 } 2312 cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false)) 2313 cplx = c.builder.CreateInsertValue(cplx, r, 0, "") 2314 cplx = c.builder.CreateInsertValue(cplx, i, 1, "") 2315 return cplx, nil 2316 } else { 2317 return llvm.Value{}, errors.New("todo: unknown constant: " + expr.String()) 2318 } 2319 case *types.Chan: 2320 sig, err := c.getLLVMType(expr.Type()) 2321 if err != nil { 2322 return llvm.Value{}, err 2323 } 2324 return c.getZeroValue(sig) 2325 case *types.Signature: 2326 if expr.Value != nil { 2327 return llvm.Value{}, errors.New("non-nil signature constant") 2328 } 2329 sig, err := c.getLLVMType(expr.Type()) 2330 if err != nil { 2331 return llvm.Value{}, err 2332 } 2333 return c.getZeroValue(sig) 2334 case *types.Interface: 2335 if expr.Value != nil { 2336 return llvm.Value{}, errors.New("non-nil interface constant") 2337 } 2338 // Create a generic nil interface with no dynamic type (typecode=0). 2339 fields := []llvm.Value{ 2340 llvm.ConstInt(c.uintptrType, 0, false), 2341 llvm.ConstPointerNull(c.i8ptrType), 2342 } 2343 itf := llvm.ConstNamedStruct(c.mod.GetTypeByName("runtime._interface"), fields) 2344 return itf, nil 2345 case *types.Pointer: 2346 if expr.Value != nil { 2347 return llvm.Value{}, errors.New("non-nil pointer constant") 2348 } 2349 llvmType, err := c.getLLVMType(typ) 2350 if err != nil { 2351 return llvm.Value{}, err 2352 } 2353 return llvm.ConstPointerNull(llvmType), nil 2354 case *types.Slice: 2355 if expr.Value != nil { 2356 return llvm.Value{}, errors.New("non-nil slice constant") 2357 } 2358 elemType, err := c.getLLVMType(typ.Elem()) 2359 if err != nil { 2360 return llvm.Value{}, err 2361 } 2362 llvmPtr := llvm.ConstPointerNull(llvm.PointerType(elemType, 0)) 2363 llvmLen := llvm.ConstInt(c.uintptrType, 0, false) 2364 slice := c.ctx.ConstStruct([]llvm.Value{ 2365 llvmPtr, // backing array 2366 llvmLen, // len 2367 llvmLen, // cap 2368 }, false) 2369 return slice, nil 2370 case *types.Map: 2371 if !expr.IsNil() { 2372 // I believe this is not allowed by the Go spec. 2373 panic("non-nil map constant") 2374 } 2375 llvmType, err := c.getLLVMType(typ) 2376 if err != nil { 2377 return llvm.Value{}, err 2378 } 2379 return c.getZeroValue(llvmType) 2380 default: 2381 return llvm.Value{}, errors.New("todo: unknown constant: " + expr.String()) 2382 } 2383 } 2384 2385 func (c *Compiler) parseConvert(typeFrom, typeTo types.Type, value llvm.Value, pos token.Pos) (llvm.Value, error) { 2386 llvmTypeFrom := value.Type() 2387 llvmTypeTo, err := c.getLLVMType(typeTo) 2388 if err != nil { 2389 return llvm.Value{}, err 2390 } 2391 2392 // Conversion between unsafe.Pointer and uintptr. 2393 isPtrFrom := isPointer(typeFrom.Underlying()) 2394 isPtrTo := isPointer(typeTo.Underlying()) 2395 if isPtrFrom && !isPtrTo { 2396 return c.builder.CreatePtrToInt(value, llvmTypeTo, ""), nil 2397 } else if !isPtrFrom && isPtrTo { 2398 if !value.IsABinaryOperator().IsNil() && value.InstructionOpcode() == llvm.Add { 2399 // This is probably a pattern like the following: 2400 // unsafe.Pointer(uintptr(ptr) + index) 2401 // Used in functions like memmove etc. for lack of pointer 2402 // arithmetic. Convert it to real pointer arithmatic here. 2403 ptr := value.Operand(0) 2404 index := value.Operand(1) 2405 if !index.IsAPtrToIntInst().IsNil() { 2406 // Swap if necessary, if ptr and index are reversed. 2407 ptr, index = index, ptr 2408 } 2409 if !ptr.IsAPtrToIntInst().IsNil() { 2410 origptr := ptr.Operand(0) 2411 if origptr.Type() == c.i8ptrType { 2412 // This pointer can be calculated from the original 2413 // ptrtoint instruction with a GEP. The leftover inttoptr 2414 // instruction is trivial to optimize away. 2415 return c.builder.CreateGEP(origptr, []llvm.Value{index}, ""), nil 2416 } 2417 } 2418 } 2419 return c.builder.CreateIntToPtr(value, llvmTypeTo, ""), nil 2420 } 2421 2422 // Conversion between pointers and unsafe.Pointer. 2423 if isPtrFrom && isPtrTo { 2424 return c.builder.CreateBitCast(value, llvmTypeTo, ""), nil 2425 } 2426 2427 switch typeTo := typeTo.Underlying().(type) { 2428 case *types.Basic: 2429 sizeFrom := c.targetData.TypeAllocSize(llvmTypeFrom) 2430 2431 if typeTo.Info()&types.IsString != 0 { 2432 switch typeFrom := typeFrom.Underlying().(type) { 2433 case *types.Basic: 2434 // Assume a Unicode code point, as that is the only possible 2435 // value here. 2436 // Cast to an i32 value as expected by 2437 // runtime.stringFromUnicode. 2438 if sizeFrom > 4 { 2439 value = c.builder.CreateTrunc(value, c.ctx.Int32Type(), "") 2440 } else if sizeFrom < 4 && typeTo.Info()&types.IsUnsigned != 0 { 2441 value = c.builder.CreateZExt(value, c.ctx.Int32Type(), "") 2442 } else if sizeFrom < 4 { 2443 value = c.builder.CreateSExt(value, c.ctx.Int32Type(), "") 2444 } 2445 return c.createRuntimeCall("stringFromUnicode", []llvm.Value{value}, ""), nil 2446 case *types.Slice: 2447 switch typeFrom.Elem().(*types.Basic).Kind() { 2448 case types.Byte: 2449 return c.createRuntimeCall("stringFromBytes", []llvm.Value{value}, ""), nil 2450 default: 2451 return llvm.Value{}, c.makeError(pos, "todo: convert to string: "+typeFrom.String()) 2452 } 2453 default: 2454 return llvm.Value{}, c.makeError(pos, "todo: convert to string: "+typeFrom.String()) 2455 } 2456 } 2457 2458 typeFrom := typeFrom.Underlying().(*types.Basic) 2459 sizeTo := c.targetData.TypeAllocSize(llvmTypeTo) 2460 2461 if typeFrom.Info()&types.IsInteger != 0 && typeTo.Info()&types.IsInteger != 0 { 2462 // Conversion between two integers. 2463 if sizeFrom > sizeTo { 2464 return c.builder.CreateTrunc(value, llvmTypeTo, ""), nil 2465 } else if typeFrom.Info()&types.IsUnsigned != 0 { // if unsigned 2466 return c.builder.CreateZExt(value, llvmTypeTo, ""), nil 2467 } else { // if signed 2468 return c.builder.CreateSExt(value, llvmTypeTo, ""), nil 2469 } 2470 } 2471 2472 if typeFrom.Info()&types.IsFloat != 0 && typeTo.Info()&types.IsFloat != 0 { 2473 // Conversion between two floats. 2474 if sizeFrom > sizeTo { 2475 return c.builder.CreateFPTrunc(value, llvmTypeTo, ""), nil 2476 } else if sizeFrom < sizeTo { 2477 return c.builder.CreateFPExt(value, llvmTypeTo, ""), nil 2478 } else { 2479 return value, nil 2480 } 2481 } 2482 2483 if typeFrom.Info()&types.IsFloat != 0 && typeTo.Info()&types.IsInteger != 0 { 2484 // Conversion from float to int. 2485 if typeTo.Info()&types.IsUnsigned != 0 { // if unsigned 2486 return c.builder.CreateFPToUI(value, llvmTypeTo, ""), nil 2487 } else { // if signed 2488 return c.builder.CreateFPToSI(value, llvmTypeTo, ""), nil 2489 } 2490 } 2491 2492 if typeFrom.Info()&types.IsInteger != 0 && typeTo.Info()&types.IsFloat != 0 { 2493 // Conversion from int to float. 2494 if typeFrom.Info()&types.IsUnsigned != 0 { // if unsigned 2495 return c.builder.CreateUIToFP(value, llvmTypeTo, ""), nil 2496 } else { // if signed 2497 return c.builder.CreateSIToFP(value, llvmTypeTo, ""), nil 2498 } 2499 } 2500 2501 if typeFrom.Kind() == types.Complex128 && typeTo.Kind() == types.Complex64 { 2502 // Conversion from complex128 to complex64. 2503 r := c.builder.CreateExtractValue(value, 0, "real.f64") 2504 i := c.builder.CreateExtractValue(value, 1, "imag.f64") 2505 r = c.builder.CreateFPTrunc(r, c.ctx.FloatType(), "real.f32") 2506 i = c.builder.CreateFPTrunc(i, c.ctx.FloatType(), "imag.f32") 2507 cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false)) 2508 cplx = c.builder.CreateInsertValue(cplx, r, 0, "") 2509 cplx = c.builder.CreateInsertValue(cplx, i, 1, "") 2510 return cplx, nil 2511 } 2512 2513 if typeFrom.Kind() == types.Complex64 && typeTo.Kind() == types.Complex128 { 2514 // Conversion from complex64 to complex128. 2515 r := c.builder.CreateExtractValue(value, 0, "real.f32") 2516 i := c.builder.CreateExtractValue(value, 1, "imag.f32") 2517 r = c.builder.CreateFPExt(r, c.ctx.DoubleType(), "real.f64") 2518 i = c.builder.CreateFPExt(i, c.ctx.DoubleType(), "imag.f64") 2519 cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false)) 2520 cplx = c.builder.CreateInsertValue(cplx, r, 0, "") 2521 cplx = c.builder.CreateInsertValue(cplx, i, 1, "") 2522 return cplx, nil 2523 } 2524 2525 return llvm.Value{}, c.makeError(pos, "todo: convert: basic non-integer type: "+typeFrom.String()+" -> "+typeTo.String()) 2526 2527 case *types.Slice: 2528 if basic, ok := typeFrom.(*types.Basic); !ok || basic.Info()&types.IsString == 0 { 2529 panic("can only convert from a string to a slice") 2530 } 2531 2532 elemType := typeTo.Elem().Underlying().(*types.Basic) // must be byte or rune 2533 switch elemType.Kind() { 2534 case types.Byte: 2535 return c.createRuntimeCall("stringToBytes", []llvm.Value{value}, ""), nil 2536 default: 2537 return llvm.Value{}, c.makeError(pos, "todo: convert from string: "+elemType.String()) 2538 } 2539 2540 default: 2541 return llvm.Value{}, c.makeError(pos, "todo: convert "+typeTo.String()+" <- "+typeFrom.String()) 2542 } 2543 } 2544 2545 func (c *Compiler) parseUnOp(frame *Frame, unop *ssa.UnOp) (llvm.Value, error) { 2546 x, err := c.parseExpr(frame, unop.X) 2547 if err != nil { 2548 return llvm.Value{}, err 2549 } 2550 switch unop.Op { 2551 case token.NOT: // !x 2552 return c.builder.CreateNot(x, ""), nil 2553 case token.SUB: // -x 2554 if typ, ok := unop.X.Type().Underlying().(*types.Basic); ok { 2555 if typ.Info()&types.IsInteger != 0 { 2556 return c.builder.CreateSub(llvm.ConstInt(x.Type(), 0, false), x, ""), nil 2557 } else if typ.Info()&types.IsFloat != 0 { 2558 return c.builder.CreateFSub(llvm.ConstFloat(x.Type(), 0.0), x, ""), nil 2559 } else { 2560 return llvm.Value{}, c.makeError(unop.Pos(), "todo: unknown basic type for negate: "+typ.String()) 2561 } 2562 } else { 2563 return llvm.Value{}, c.makeError(unop.Pos(), "todo: unknown type for negate: "+unop.X.Type().Underlying().String()) 2564 } 2565 case token.MUL: // *x, dereference pointer 2566 valType := unop.X.Type().Underlying().(*types.Pointer).Elem() 2567 if c.targetData.TypeAllocSize(x.Type().ElementType()) == 0 { 2568 // zero-length data 2569 return c.getZeroValue(x.Type().ElementType()) 2570 } else if strings.HasSuffix(unop.X.String(), "$funcaddr") { 2571 // CGo function pointer. The cgo part has rewritten CGo function 2572 // pointers as stub global variables of the form: 2573 // var C.add unsafe.Pointer 2574 // Instead of a load from the global, create a bitcast of the 2575 // function pointer itself. 2576 global := c.ir.GetGlobal(unop.X.(*ssa.Global)) 2577 name := global.LinkName()[:len(global.LinkName())-len("$funcaddr")] 2578 fn := c.mod.NamedFunction(name) 2579 if fn.IsNil() { 2580 return llvm.Value{}, c.makeError(unop.Pos(), "cgo function not found: "+name) 2581 } 2582 return c.builder.CreateBitCast(fn, c.i8ptrType, ""), nil 2583 } else { 2584 c.emitNilCheck(frame, x, "deref") 2585 load := c.builder.CreateLoad(x, "") 2586 if c.ir.IsVolatile(valType) { 2587 // Volatile load, for memory-mapped registers. 2588 load.SetVolatile(true) 2589 } 2590 return load, nil 2591 } 2592 case token.XOR: // ^x, toggle all bits in integer 2593 return c.builder.CreateXor(x, llvm.ConstInt(x.Type(), ^uint64(0), false), ""), nil 2594 case token.ARROW: // <-x, receive from channel 2595 return c.emitChanRecv(frame, unop) 2596 default: 2597 return llvm.Value{}, c.makeError(unop.Pos(), "todo: unknown unop") 2598 } 2599 } 2600 2601 // IR returns the whole IR as a human-readable string. 2602 func (c *Compiler) IR() string { 2603 return c.mod.String() 2604 } 2605 2606 func (c *Compiler) Verify() error { 2607 return llvm.VerifyModule(c.mod, llvm.PrintMessageAction) 2608 } 2609 2610 func (c *Compiler) ApplyFunctionSections() { 2611 // Put every function in a separate section. This makes it possible for the 2612 // linker to remove dead code (-ffunction-sections). 2613 llvmFn := c.mod.FirstFunction() 2614 for !llvmFn.IsNil() { 2615 if !llvmFn.IsDeclaration() { 2616 name := llvmFn.Name() 2617 llvmFn.SetSection(".text." + name) 2618 } 2619 llvmFn = llvm.NextFunction(llvmFn) 2620 } 2621 } 2622 2623 // Turn all global constants into global variables. This works around a 2624 // limitation on Harvard architectures (e.g. AVR), where constant and 2625 // non-constant pointers point to a different address space. 2626 func (c *Compiler) NonConstGlobals() { 2627 global := c.mod.FirstGlobal() 2628 for !global.IsNil() { 2629 global.SetGlobalConstant(false) 2630 global = llvm.NextGlobal(global) 2631 } 2632 } 2633 2634 // When -wasm-abi flag set to "js" (default), 2635 // replace i64 in an external function with a stack-allocated i64*, to work 2636 // around the lack of 64-bit integers in JavaScript (commonly used together with 2637 // WebAssembly). Once that's resolved, this pass may be avoided. 2638 // See also the -wasm-abi= flag 2639 // https://github.com/WebAssembly/design/issues/1172 2640 func (c *Compiler) ExternalInt64AsPtr() error { 2641 int64Type := c.ctx.Int64Type() 2642 int64PtrType := llvm.PointerType(int64Type, 0) 2643 for fn := c.mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) { 2644 if fn.Linkage() != llvm.ExternalLinkage { 2645 // Only change externally visible functions (exports and imports). 2646 continue 2647 } 2648 if strings.HasPrefix(fn.Name(), "llvm.") || strings.HasPrefix(fn.Name(), "runtime.") { 2649 // Do not try to modify the signature of internal LLVM functions and 2650 // assume that runtime functions are only temporarily exported for 2651 // coroutine lowering. 2652 continue 2653 } 2654 2655 hasInt64 := false 2656 paramTypes := []llvm.Type{} 2657 2658 // Check return type for 64-bit integer. 2659 fnType := fn.Type().ElementType() 2660 returnType := fnType.ReturnType() 2661 if returnType == int64Type { 2662 hasInt64 = true 2663 paramTypes = append(paramTypes, int64PtrType) 2664 returnType = c.ctx.VoidType() 2665 } 2666 2667 // Check param types for 64-bit integers. 2668 for param := fn.FirstParam(); !param.IsNil(); param = llvm.NextParam(param) { 2669 if param.Type() == int64Type { 2670 hasInt64 = true 2671 paramTypes = append(paramTypes, int64PtrType) 2672 } else { 2673 paramTypes = append(paramTypes, param.Type()) 2674 } 2675 } 2676 2677 if !hasInt64 { 2678 // No i64 in the paramter list. 2679 continue 2680 } 2681 2682 // Add $i64wrapper to the real function name as it is only used 2683 // internally. 2684 // Add a new function with the correct signature that is exported. 2685 name := fn.Name() 2686 fn.SetName(name + "$i64wrap") 2687 externalFnType := llvm.FunctionType(returnType, paramTypes, fnType.IsFunctionVarArg()) 2688 externalFn := llvm.AddFunction(c.mod, name, externalFnType) 2689 2690 if fn.IsDeclaration() { 2691 // Just a declaration: the definition doesn't exist on the Go side 2692 // so it cannot be called from external code. 2693 // Update all users to call the external function. 2694 // The old $i64wrapper function could be removed, but it may as well 2695 // be left in place. 2696 for use := fn.FirstUse(); !use.IsNil(); use = use.NextUse() { 2697 call := use.User() 2698 c.builder.SetInsertPointBefore(call) 2699 callParams := []llvm.Value{} 2700 var retvalAlloca llvm.Value 2701 if fnType.ReturnType() == int64Type { 2702 retvalAlloca = c.builder.CreateAlloca(int64Type, "i64asptr") 2703 callParams = append(callParams, retvalAlloca) 2704 } 2705 for i := 0; i < call.OperandsCount()-1; i++ { 2706 operand := call.Operand(i) 2707 if operand.Type() == int64Type { 2708 // Pass a stack-allocated pointer instead of the value 2709 // itself. 2710 alloca := c.builder.CreateAlloca(int64Type, "i64asptr") 2711 c.builder.CreateStore(operand, alloca) 2712 callParams = append(callParams, alloca) 2713 } else { 2714 // Unchanged parameter. 2715 callParams = append(callParams, operand) 2716 } 2717 } 2718 if fnType.ReturnType() == int64Type { 2719 // Pass a stack-allocated pointer as the first parameter 2720 // where the return value should be stored, instead of using 2721 // the regular return value. 2722 c.builder.CreateCall(externalFn, callParams, call.Name()) 2723 returnValue := c.builder.CreateLoad(retvalAlloca, "retval") 2724 call.ReplaceAllUsesWith(returnValue) 2725 call.EraseFromParentAsInstruction() 2726 } else { 2727 newCall := c.builder.CreateCall(externalFn, callParams, call.Name()) 2728 call.ReplaceAllUsesWith(newCall) 2729 call.EraseFromParentAsInstruction() 2730 } 2731 } 2732 } else { 2733 // The function has a definition in Go. This means that it may still 2734 // be called both Go and from external code. 2735 // Keep existing calls with the existing convention in place (for 2736 // better performance), but export a new wrapper function with the 2737 // correct calling convention. 2738 fn.SetLinkage(llvm.InternalLinkage) 2739 fn.SetUnnamedAddr(true) 2740 entryBlock := llvm.AddBasicBlock(externalFn, "entry") 2741 c.builder.SetInsertPointAtEnd(entryBlock) 2742 var callParams []llvm.Value 2743 if fnType.ReturnType() == int64Type { 2744 return errors.New("not yet implemented: exported function returns i64 with -wasm-abi=js; " + 2745 "see https://tinygo.org/compiler-internals/calling-convention/") 2746 } 2747 for i, origParam := range fn.Params() { 2748 paramValue := externalFn.Param(i) 2749 if origParam.Type() == int64Type { 2750 paramValue = c.builder.CreateLoad(paramValue, "i64") 2751 } 2752 callParams = append(callParams, paramValue) 2753 } 2754 retval := c.builder.CreateCall(fn, callParams, "") 2755 if retval.Type().TypeKind() == llvm.VoidTypeKind { 2756 c.builder.CreateRetVoid() 2757 } else { 2758 c.builder.CreateRet(retval) 2759 } 2760 } 2761 } 2762 2763 return nil 2764 } 2765 2766 // Emit object file (.o). 2767 func (c *Compiler) EmitObject(path string) error { 2768 llvmBuf, err := c.machine.EmitToMemoryBuffer(c.mod, llvm.ObjectFile) 2769 if err != nil { 2770 return err 2771 } 2772 return c.writeFile(llvmBuf.Bytes(), path) 2773 } 2774 2775 // Emit LLVM bitcode file (.bc). 2776 func (c *Compiler) EmitBitcode(path string) error { 2777 data := llvm.WriteBitcodeToMemoryBuffer(c.mod).Bytes() 2778 return c.writeFile(data, path) 2779 } 2780 2781 // Emit LLVM IR source file (.ll). 2782 func (c *Compiler) EmitText(path string) error { 2783 data := []byte(c.mod.String()) 2784 return c.writeFile(data, path) 2785 } 2786 2787 // Write the data to the file specified by path. 2788 func (c *Compiler) writeFile(data []byte, path string) error { 2789 // Write output to file 2790 f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) 2791 if err != nil { 2792 return err 2793 } 2794 _, err = f.Write(data) 2795 if err != nil { 2796 return err 2797 } 2798 return f.Close() 2799 }