func (v *Codegen) genAddressOfExpr(n *parser.AddressOfExpr) llvm.Value { gep := v.builder.CreateGEP(v.variableLookup[n.Access.Accesses[0].Variable], []llvm.Value{llvm.ConstInt(llvm.Int32Type(), 0, false)}, "") for i := 0; i < len(n.Access.Accesses); i++ { switch n.Access.Accesses[i].AccessType { case parser.ACCESS_ARRAY: gepIndexes := []llvm.Value{llvm.ConstInt(llvm.Int32Type(), 0, false), llvm.ConstInt(llvm.Int32Type(), 1, false)} gep = v.builder.CreateGEP(gep, gepIndexes, "") load := v.builder.CreateLoad(gep, "") // TODO check that access is in bounds! gepIndexes = []llvm.Value{llvm.ConstInt(llvm.Int32Type(), 0, false), v.genExpr(n.Access.Accesses[i].Subscript)} gep = v.builder.CreateGEP(load, gepIndexes, "") case parser.ACCESS_VARIABLE: // nothing to do case parser.ACCESS_STRUCT: index := n.Access.Accesses[i].Variable.Type.(*parser.StructType).VariableIndex(n.Access.Accesses[i+1].Variable) gep = v.builder.CreateGEP(gep, []llvm.Value{llvm.ConstInt(llvm.Int32Type(), 0, false), llvm.ConstInt(llvm.Int32Type(), uint64(index), false)}, "") default: panic("") } } return gep }
func (fr *frame) chanSelect(sel *ssa.Select) (index, recvOk *govalue, recvElems []*govalue) { n := uint64(len(sel.States)) if !sel.Blocking { // non-blocking means there's a default case n++ } size := llvm.ConstInt(llvm.Int32Type(), n, false) selectp := fr.runtime.newSelect.call(fr, size)[0] // Allocate stack for the values to send and receive. ptrs := make([]llvm.Value, len(sel.States)) for i, state := range sel.States { chantyp := state.Chan.Type().Underlying().(*types.Chan) elemtyp := fr.types.ToLLVM(chantyp.Elem()) if state.Dir == types.SendOnly { ptrs[i] = fr.allocaBuilder.CreateAlloca(elemtyp, "") fr.builder.CreateStore(fr.llvmvalue(state.Send), ptrs[i]) } else { // Only allocate stack space if the received value is used. used := chanSelectStateUsed(sel, len(recvElems)) if used { ptrs[i] = fr.allocaBuilder.CreateAlloca(elemtyp, "") } else { ptrs[i] = llvm.ConstNull(llvm.PointerType(llvm.Int8Type(), 0)) } recvElems = append(recvElems, newValue(ptrs[i], chantyp.Elem())) } } // Create select{send,recv2} calls. var receivedp llvm.Value if len(recvElems) > 0 { receivedp = fr.allocaBuilder.CreateAlloca(fr.types.ToLLVM(types.Typ[types.Bool]), "") } if !sel.Blocking { // If the default case is chosen, the index must be -1. fr.runtime.selectdefault.call(fr, selectp, llvm.ConstAllOnes(llvm.Int32Type())) } for i, state := range sel.States { ch := fr.llvmvalue(state.Chan) index := llvm.ConstInt(llvm.Int32Type(), uint64(i), false) if state.Dir == types.SendOnly { fr.runtime.selectsend.call(fr, selectp, ch, ptrs[i], index) } else { fr.runtime.selectrecv2.call(fr, selectp, ch, ptrs[i], receivedp, index) } } // Fire off the select. index = newValue(fr.runtime.selectgo.call(fr, selectp)[0], types.Typ[types.Int]) if len(recvElems) > 0 { recvOk = newValue(fr.builder.CreateLoad(receivedp, ""), types.Typ[types.Bool]) for _, recvElem := range recvElems { recvElem.value = fr.builder.CreateLoad(recvElem.value, "") } } return index, recvOk, recvElems }
func (v *Codegen) genAccessGEP(n parser.Expr) llvm.Value { switch access := n.(type) { case *parser.VariableAccessExpr: varType := v.getVariable(access.Variable) log.Debugln("codegen", "%v => %v", access.Variable, varType) if varType.IsNil() { panic("varType was nil") } gep := v.builder().CreateGEP(varType, []llvm.Value{llvm.ConstInt(llvm.Int32Type(), 0, false)}, "") if _, ok := access.GetType().(parser.MutableReferenceType); ok { return v.builder().CreateLoad(gep, "") } if _, ok := access.GetType().(parser.ConstantReferenceType); ok { return v.builder().CreateLoad(gep, "") } return gep case *parser.StructAccessExpr: gep := v.genAccessGEP(access.Struct) typ := access.Struct.GetType().ActualType() index := typ.(parser.StructType).VariableIndex(access.Variable) return v.builder().CreateStructGEP(gep, index, "") case *parser.ArrayAccessExpr: gep := v.genAccessGEP(access.Array) subscriptExpr := v.genExpr(access.Subscript) v.genBoundsCheck(v.builder().CreateLoad(v.builder().CreateStructGEP(gep, 0, ""), ""), subscriptExpr, access.Subscript.GetType()) gep = v.builder().CreateStructGEP(gep, 1, "") load := v.builder().CreateLoad(gep, "") gepIndexes := []llvm.Value{llvm.ConstInt(llvm.Int32Type(), 0, false), subscriptExpr} return v.builder().CreateGEP(load, gepIndexes, "") case *parser.TupleAccessExpr: gep := v.genAccessGEP(access.Tuple) // TODO: Check overflow return v.builder().CreateStructGEP(gep, int(access.Index), "") case *parser.DerefAccessExpr: return v.genExpr(access.Expr) default: panic("unhandled access type") } }
func (fr *frame) setBranchWeightMetadata(br llvm.Value, trueweight, falseweight uint64) { mdprof := llvm.MDKindID("prof") mdnode := llvm.MDNode([]llvm.Value{ llvm.MDString("branch_weights"), llvm.ConstInt(llvm.Int32Type(), trueweight, false), llvm.ConstInt(llvm.Int32Type(), falseweight, false), }) br.SetMetadata(mdprof, mdnode) }
func (fr *frame) chanSelect(states []selectState, blocking bool) (index, recvOk *govalue, recvElems []*govalue) { n := uint64(len(states)) if !blocking { // non-blocking means there's a default case n++ } size := llvm.ConstInt(llvm.Int32Type(), n, false) selectp := fr.runtime.newSelect.call(fr, size)[0] // Allocate stack for the values to send and receive. // // TODO(axw) check if received elements have any users, and // elide stack allocation if not (pass nil to recv2 instead.) ptrs := make([]llvm.Value, len(states)) for i, state := range states { chantyp := state.Chan.Type().Underlying().(*types.Chan) elemtyp := fr.types.ToLLVM(chantyp.Elem()) ptrs[i] = fr.allocaBuilder.CreateAlloca(elemtyp, "") if state.Dir == types.SendOnly { fr.builder.CreateStore(state.Send.value, ptrs[i]) } else { recvElems = append(recvElems, newValue(ptrs[i], chantyp.Elem())) } } // Create select{send,recv2} calls. var receivedp llvm.Value if len(recvElems) > 0 { receivedp = fr.allocaBuilder.CreateAlloca(fr.types.ToLLVM(types.Typ[types.Bool]), "") } if !blocking { // If the default case is chosen, the index must be -1. fr.runtime.selectdefault.call(fr, selectp, llvm.ConstAllOnes(llvm.Int32Type())) } for i, state := range states { ch := state.Chan.value index := llvm.ConstInt(llvm.Int32Type(), uint64(i), false) if state.Dir == types.SendOnly { fr.runtime.selectsend.call(fr, selectp, ch, ptrs[i], index) } else { fr.runtime.selectrecv2.call(fr, selectp, ch, ptrs[i], receivedp, index) } } // Fire off the select. index = newValue(fr.runtime.selectgo.call(fr, selectp)[0], types.Typ[types.Int]) if len(recvElems) > 0 { recvOk = newValue(fr.builder.CreateLoad(receivedp, ""), types.Typ[types.Bool]) for _, recvElem := range recvElems { recvElem.value = fr.builder.CreateLoad(recvElem.value, "") } } return index, recvOk, recvElems }
// interfaceMethod returns a function and receiver pointer for the specified // interface and method pair. func (fr *frame) interfaceMethod(lliface llvm.Value, ifacety types.Type, method *types.Func) (fn, recv *govalue) { llitab := fr.builder.CreateExtractValue(lliface, 0, "") recv = newValue(fr.builder.CreateExtractValue(lliface, 1, ""), types.Typ[types.UnsafePointer]) methodset := fr.types.MethodSet(ifacety) // TODO(axw) cache ordered method index index := -1 for i, m := range orderedMethodSet(methodset) { if m.Obj() == method { index = i break } } if index == -1 { panic("could not find method index") } llitab = fr.builder.CreateBitCast(llitab, llvm.PointerType(llvm.PointerType(llvm.Int8Type(), 0), 0), "") // Skip runtime type pointer. llifnptr := fr.builder.CreateGEP(llitab, []llvm.Value{ llvm.ConstInt(llvm.Int32Type(), uint64(index+1), false), }, "") llifn := fr.builder.CreateLoad(llifnptr, "") // Replace receiver type with unsafe.Pointer. recvparam := types.NewParam(0, nil, "", types.Typ[types.UnsafePointer]) sig := method.Type().(*types.Signature) sig = types.NewSignature(nil, recvparam, sig.Params(), sig.Results(), sig.Variadic()) fn = newValue(llifn, sig) return }
func (fr *frame) condBrRuntimeError(cond llvm.Value, errcode uint64) { if cond.IsNull() { return } errorbb := fr.runtimeErrorBlocks[errcode] newbb := errorbb.C == nil if newbb { errorbb = llvm.AddBasicBlock(fr.function, "") fr.runtimeErrorBlocks[errcode] = errorbb } contbb := llvm.AddBasicBlock(fr.function, "") br := fr.builder.CreateCondBr(cond, errorbb, contbb) fr.setBranchWeightMetadata(br, 1, 1000) if newbb { fr.builder.SetInsertPointAtEnd(errorbb) fr.runtime.runtimeError.call(fr, llvm.ConstInt(llvm.Int32Type(), errcode, false)) fr.builder.CreateUnreachable() } fr.builder.SetInsertPointAtEnd(contbb) }
func (v *Codegen) genAccessGEP(n parser.Expr) llvm.Value { switch n.(type) { case *parser.VariableAccessExpr: vae := n.(*parser.VariableAccessExpr) return v.builder.CreateGEP(v.variableLookup[vae.Variable], []llvm.Value{llvm.ConstInt(llvm.Int32Type(), 0, false)}, "") case *parser.StructAccessExpr: sae := n.(*parser.StructAccessExpr) gep := v.genAccessGEP(sae.Struct) index := sae.Struct.GetType().(*parser.StructType).VariableIndex(sae.Variable) return v.builder.CreateGEP(gep, []llvm.Value{llvm.ConstInt(llvm.Int32Type(), 0, false), llvm.ConstInt(llvm.Int32Type(), uint64(index), false)}, "") case *parser.ArrayAccessExpr: aae := n.(*parser.ArrayAccessExpr) gep := v.genAccessGEP(aae.Array) subscriptExpr := v.genExpr(aae.Subscript) sizeGepIndexes := []llvm.Value{llvm.ConstInt(llvm.Int32Type(), 0, false), llvm.ConstInt(llvm.Int32Type(), 0, false)} v.genBoundsCheck(v.builder.CreateLoad(v.builder.CreateGEP(gep, sizeGepIndexes, ""), ""), subscriptExpr, aae.Subscript.GetType()) gepIndexes := []llvm.Value{llvm.ConstInt(llvm.Int32Type(), 0, false), llvm.ConstInt(llvm.Int32Type(), 1, false)} gep = v.builder.CreateGEP(gep, gepIndexes, "") load := v.builder.CreateLoad(gep, "") gepIndexes = []llvm.Value{llvm.ConstInt(llvm.Int32Type(), 0, false), subscriptExpr} return v.builder.CreateGEP(load, gepIndexes, "") case *parser.TupleAccessExpr: tae := n.(*parser.TupleAccessExpr) gep := v.genAccessGEP(tae.Tuple) index := tae.Index return v.builder.CreateGEP(gep, []llvm.Value{llvm.ConstInt(llvm.Int32Type(), 0, false), llvm.ConstInt(llvm.Int32Type(), index, false)}, "") case *parser.DerefAccessExpr: dae := n.(*parser.DerefAccessExpr) return v.genExpr(dae.Expr) default: panic("unhandled access type") } }
func (fr *frame) memcpy(dest llvm.Value, src llvm.Value, size llvm.Value) { memcpy := fr.runtime.memcpy dest = fr.builder.CreateBitCast(dest, llvm.PointerType(llvm.Int8Type(), 0), "") src = fr.builder.CreateBitCast(src, llvm.PointerType(llvm.Int8Type(), 0), "") size = fr.createZExtOrTrunc(size, fr.target.IntPtrType(), "") align := llvm.ConstInt(llvm.Int32Type(), 1, false) isvolatile := llvm.ConstNull(llvm.Int1Type()) fr.builder.CreateCall(memcpy, []llvm.Value{dest, src, size, align, isvolatile}, "") }
func (fr *frame) memsetZero(ptr llvm.Value, size llvm.Value) { memset := fr.runtime.memset ptr = fr.builder.CreateBitCast(ptr, llvm.PointerType(llvm.Int8Type(), 0), "") fill := llvm.ConstNull(llvm.Int8Type()) size = fr.createZExtOrTrunc(size, fr.target.IntPtrType(), "") align := llvm.ConstInt(llvm.Int32Type(), 1, false) isvolatile := llvm.ConstNull(llvm.Int1Type()) fr.builder.CreateCall(memset, []llvm.Value{ptr, fill, size, align, isvolatile}, "") }
// SetLocation sets the current debug location. func (d *DIBuilder) SetLocation(b llvm.Builder, pos token.Pos) { if !pos.IsValid() { return } position := d.fset.Position(pos) d.lb = llvm.Value{nil} if position.Filename != d.fnFile && position.Filename != "" { // This can happen rarely, e.g. in init functions. diFile := d.builder.CreateFile(d.remapFilePath(position.Filename), "") d.lb = d.builder.CreateLexicalBlockFile(d.scope(), diFile, 0) } b.SetCurrentDebugLocation(llvm.MDNode([]llvm.Value{ llvm.ConstInt(llvm.Int32Type(), uint64(position.Line), false), llvm.ConstInt(llvm.Int32Type(), uint64(position.Column), false), d.scope(), llvm.Value{}, })) }
// Finalize must be called after all compilation units are translated, // generating the final debug metadata for the module. func (d *DIBuilder) Finalize() { d.module.AddNamedMetadataOperand( "llvm.module.flags", llvm.GlobalContext().MDNode([]llvm.Metadata{ llvm.ConstInt(llvm.Int32Type(), 2, false).ConstantAsMetadata(), // Warn on mismatch llvm.GlobalContext().MDString("Dwarf Version"), llvm.ConstInt(llvm.Int32Type(), 4, false).ConstantAsMetadata(), }), ) d.module.AddNamedMetadataOperand( "llvm.module.flags", llvm.GlobalContext().MDNode([]llvm.Metadata{ llvm.ConstInt(llvm.Int32Type(), 1, false).ConstantAsMetadata(), // Error on mismatch llvm.GlobalContext().MDString("Debug Info Version"), llvm.ConstInt(llvm.Int32Type(), 2, false).ConstantAsMetadata(), }), ) d.builder.Finalize() }
func (fr *frame) returnAddress(level uint64) llvm.Value { returnaddress := fr.runtime.returnaddress levelValue := llvm.ConstInt(llvm.Int32Type(), level, false) return fr.builder.CreateCall(returnaddress, []llvm.Value{levelValue}, "") }
func newRuntimeInterface(module llvm.Module, tm *llvmTypeMap) (*runtimeInterface, error) { var ri runtimeInterface Bool := types.Typ[types.Bool] Complex128 := types.Typ[types.Complex128] Float64 := types.Typ[types.Float64] Int32 := types.Typ[types.Int32] Int64 := types.Typ[types.Int64] Int := types.Typ[types.Int] Rune := types.Typ[types.Rune] String := types.Typ[types.String] Uintptr := types.Typ[types.Uintptr] UnsafePointer := types.Typ[types.UnsafePointer] EmptyInterface := types.NewInterface(nil, nil) IntSlice := types.NewSlice(types.Typ[types.Int]) for _, rt := range [...]struct { name string rfi *runtimeFnInfo args, res []types.Type attrs []llvm.Attribute }{ { name: "__go_append", rfi: &ri.append, args: []types.Type{IntSlice, UnsafePointer, Uintptr, Uintptr}, res: []types.Type{IntSlice}, }, { name: "__go_assert_interface", rfi: &ri.assertInterface, args: []types.Type{UnsafePointer, UnsafePointer}, res: []types.Type{UnsafePointer}, }, { name: "__go_can_recover", rfi: &ri.canRecover, args: []types.Type{UnsafePointer}, res: []types.Type{Bool}, }, { name: "__go_chan_cap", rfi: &ri.chanCap, args: []types.Type{UnsafePointer}, res: []types.Type{Int}, }, { name: "__go_chan_len", rfi: &ri.chanLen, args: []types.Type{UnsafePointer}, res: []types.Type{Int}, }, { name: "runtime.chanrecv2", rfi: &ri.chanrecv2, args: []types.Type{UnsafePointer, UnsafePointer, UnsafePointer}, res: []types.Type{Bool}, }, { name: "__go_check_defer", rfi: &ri.checkDefer, args: []types.Type{UnsafePointer}, }, { name: "__go_check_interface_type", rfi: &ri.checkInterfaceType, args: []types.Type{UnsafePointer, UnsafePointer, UnsafePointer}, }, { name: "__go_builtin_close", rfi: &ri.builtinClose, args: []types.Type{UnsafePointer}, }, { name: "__go_convert_interface", rfi: &ri.convertInterface, args: []types.Type{UnsafePointer, UnsafePointer}, res: []types.Type{UnsafePointer}, }, { name: "__go_copy", rfi: &ri.copy, args: []types.Type{UnsafePointer, UnsafePointer, Uintptr}, }, { name: "__go_defer", rfi: &ri.Defer, args: []types.Type{UnsafePointer, UnsafePointer, UnsafePointer}, }, { name: "__go_deferred_recover", rfi: &ri.deferredRecover, res: []types.Type{EmptyInterface}, }, { name: "__go_empty_interface_compare", rfi: &ri.emptyInterfaceCompare, args: []types.Type{EmptyInterface, EmptyInterface}, res: []types.Type{Int}, }, { name: "__go_go", rfi: &ri.Go, args: []types.Type{UnsafePointer, UnsafePointer}, }, { name: "runtime.ifaceE2I2", rfi: &ri.ifaceE2I2, args: []types.Type{UnsafePointer, EmptyInterface}, res: []types.Type{EmptyInterface, Bool}, }, { name: "runtime.ifaceI2I2", rfi: &ri.ifaceI2I2, args: []types.Type{UnsafePointer, EmptyInterface}, res: []types.Type{EmptyInterface, Bool}, }, { name: "__go_int_array_to_string", rfi: &ri.intArrayToString, args: []types.Type{UnsafePointer, Int}, res: []types.Type{String}, }, { name: "__go_int_to_string", rfi: &ri.intToString, args: []types.Type{Int}, res: []types.Type{String}, }, { name: "__go_interface_compare", rfi: &ri.interfaceCompare, args: []types.Type{EmptyInterface, EmptyInterface}, res: []types.Type{Int}, }, { name: "__go_make_slice2", rfi: &ri.makeSlice, args: []types.Type{UnsafePointer, Uintptr, Uintptr}, res: []types.Type{IntSlice}, }, { name: "runtime.mapdelete", rfi: &ri.mapdelete, args: []types.Type{UnsafePointer, UnsafePointer}, }, { name: "runtime.mapiter2", rfi: &ri.mapiter2, args: []types.Type{UnsafePointer, UnsafePointer, UnsafePointer}, }, { name: "runtime.mapiterinit", rfi: &ri.mapiterinit, args: []types.Type{UnsafePointer, UnsafePointer}, }, { name: "runtime.mapiternext", rfi: &ri.mapiternext, args: []types.Type{UnsafePointer}, }, { name: "__go_map_index", rfi: &ri.mapIndex, args: []types.Type{UnsafePointer, UnsafePointer, Bool}, res: []types.Type{UnsafePointer}, }, { name: "__go_map_len", rfi: &ri.mapLen, args: []types.Type{UnsafePointer}, res: []types.Type{Int}, }, { name: "__go_new", rfi: &ri.New, args: []types.Type{UnsafePointer, Uintptr}, res: []types.Type{UnsafePointer}, }, { name: "__go_new_channel", rfi: &ri.newChannel, args: []types.Type{UnsafePointer, Uintptr}, res: []types.Type{UnsafePointer}, }, { name: "__go_new_map", rfi: &ri.newMap, args: []types.Type{UnsafePointer, Uintptr}, res: []types.Type{UnsafePointer}, }, { name: "__go_new_nopointers", rfi: &ri.NewNopointers, args: []types.Type{UnsafePointer, Uintptr}, res: []types.Type{UnsafePointer}, }, { name: "runtime.newselect", rfi: &ri.newSelect, args: []types.Type{Int32}, res: []types.Type{UnsafePointer}, }, { name: "__go_panic", rfi: &ri.panic, args: []types.Type{EmptyInterface}, attrs: []llvm.Attribute{llvm.NoReturnAttribute}, }, { name: "__go_print_bool", rfi: &ri.printBool, args: []types.Type{Bool}, }, { name: "__go_print_complex", rfi: &ri.printComplex, args: []types.Type{Complex128}, }, { name: "__go_print_double", rfi: &ri.printDouble, args: []types.Type{Float64}, }, { name: "__go_print_empty_interface", rfi: &ri.printEmptyInterface, args: []types.Type{EmptyInterface}, }, { name: "__go_print_interface", rfi: &ri.printInterface, args: []types.Type{EmptyInterface}, }, { name: "__go_print_int64", rfi: &ri.printInt64, args: []types.Type{Int64}, }, { name: "__go_print_nl", rfi: &ri.printNl, }, { name: "__go_print_pointer", rfi: &ri.printPointer, args: []types.Type{UnsafePointer}, }, { name: "__go_print_slice", rfi: &ri.printSlice, args: []types.Type{IntSlice}, }, { name: "__go_print_space", rfi: &ri.printSpace, }, { name: "__go_print_string", rfi: &ri.printString, args: []types.Type{String}, }, { name: "__go_print_uint64", rfi: &ri.printUint64, args: []types.Type{Int64}, }, { name: "__go_receive", rfi: &ri.receive, args: []types.Type{UnsafePointer, UnsafePointer, UnsafePointer}, }, { name: "__go_recover", rfi: &ri.recover, res: []types.Type{EmptyInterface}, }, { name: "__go_register_gc_roots", rfi: &ri.registerGcRoots, args: []types.Type{UnsafePointer}, }, { name: "__go_runtime_error", rfi: &ri.runtimeError, args: []types.Type{Int32}, attrs: []llvm.Attribute{llvm.NoReturnAttribute}, }, { name: "runtime.selectdefault", rfi: &ri.selectdefault, args: []types.Type{UnsafePointer, Int32}, }, { name: "runtime.selectgo", rfi: &ri.selectgo, args: []types.Type{UnsafePointer}, res: []types.Type{Int}, }, { name: "runtime.selectrecv2", rfi: &ri.selectrecv2, args: []types.Type{UnsafePointer, UnsafePointer, UnsafePointer, UnsafePointer, Int32}, }, { name: "runtime.selectsend", rfi: &ri.selectsend, args: []types.Type{UnsafePointer, UnsafePointer, UnsafePointer, Int32}, }, { name: "__go_send_big", rfi: &ri.sendBig, args: []types.Type{UnsafePointer, UnsafePointer, UnsafePointer}, }, { name: "__go_set_defer_retaddr", rfi: &ri.setDeferRetaddr, args: []types.Type{UnsafePointer}, res: []types.Type{Bool}, }, { name: "__go_strcmp", rfi: &ri.strcmp, args: []types.Type{String, String}, res: []types.Type{Int}, }, { name: "__go_string_plus", rfi: &ri.stringPlus, args: []types.Type{String, String}, res: []types.Type{String}, }, { name: "__go_string_slice", rfi: &ri.stringSlice, args: []types.Type{String, Int, Int}, res: []types.Type{String}, }, { name: "__go_string_to_int_array", rfi: &ri.stringToIntArray, args: []types.Type{String}, res: []types.Type{IntSlice}, }, { name: "runtime.stringiter2", rfi: &ri.stringiter2, args: []types.Type{String, Int}, res: []types.Type{Int, Rune}, }, { name: "__go_type_descriptors_equal", rfi: &ri.typeDescriptorsEqual, args: []types.Type{UnsafePointer, UnsafePointer}, res: []types.Type{Bool}, }, { name: "__go_undefer", rfi: &ri.undefer, args: []types.Type{UnsafePointer}, }, } { rt.rfi.init(tm, module, rt.name, rt.args, rt.res) for _, attr := range rt.attrs { rt.rfi.fn.AddFunctionAttr(attr) } } memsetName := "llvm.memset.p0i8.i" + strconv.Itoa(tm.target.IntPtrType().IntTypeWidth()) memsetType := llvm.FunctionType( llvm.VoidType(), []llvm.Type{ llvm.PointerType(llvm.Int8Type(), 0), llvm.Int8Type(), tm.target.IntPtrType(), llvm.Int32Type(), llvm.Int1Type(), }, false, ) ri.memset = llvm.AddFunction(module, memsetName, memsetType) memcpyName := "llvm.memcpy.p0i8.p0i8.i" + strconv.Itoa(tm.target.IntPtrType().IntTypeWidth()) memcpyType := llvm.FunctionType( llvm.VoidType(), []llvm.Type{ llvm.PointerType(llvm.Int8Type(), 0), llvm.PointerType(llvm.Int8Type(), 0), tm.target.IntPtrType(), llvm.Int32Type(), llvm.Int1Type(), }, false, ) ri.memcpy = llvm.AddFunction(module, memcpyName, memcpyType) returnaddressType := llvm.FunctionType( llvm.PointerType(llvm.Int8Type(), 0), []llvm.Type{llvm.Int32Type()}, false, ) ri.returnaddress = llvm.AddFunction(module, "llvm.returnaddress", returnaddressType) gccgoPersonalityType := llvm.FunctionType( llvm.Int32Type(), []llvm.Type{ llvm.Int32Type(), llvm.Int64Type(), llvm.PointerType(llvm.Int8Type(), 0), llvm.PointerType(llvm.Int8Type(), 0), }, false, ) ri.gccgoPersonality = llvm.AddFunction(module, "__gccgo_personality_v0", gccgoPersonalityType) ri.gccgoExceptionType = llvm.StructType( []llvm.Type{ llvm.PointerType(llvm.Int8Type(), 0), llvm.Int32Type(), }, false, ) return &ri, nil }
func (v *Codegen) genSizeofExpr(n *parser.SizeofExpr) llvm.Value { if n.Expr != nil { gep := v.builder.CreateGEP(llvm.ConstNull(llvm.PointerType(v.typeToLLVMType(n.Expr.GetType()), 0)), []llvm.Value{llvm.ConstInt(llvm.Int32Type(), 1, false)}, "") return v.builder.CreatePtrToInt(gep, v.typeToLLVMType(n.GetType()), "sizeof") } else { // we have a type panic("can't do this yet") } }
package codegen import ( "log" "github.com/furryfaust/lyca/src/parser" "llvm.org/llvm/bindings/go/llvm" ) var PRIMITIVE_TYPES = map[string]llvm.Type{ "int": llvm.Int32Type(), "char": llvm.Int8Type(), "float": llvm.FloatType(), "boolean": llvm.Int1Type(), } var null llvm.Value = llvm.Value{} func (c *Codegen) getLLVMFuncType(ret parser.Node, params []*parser.VarDeclNode, obj llvm.Type) llvm.Type { p := make([]llvm.Type, 0) if obj != llvm.VoidType() { p = append(p, obj) } for _, v := range params { p = append(p, c.getLLVMType(v.Type)) } return llvm.FunctionType(c.getLLVMType(ret), p, false) } func (c *Codegen) getLLVMType(node parser.Node) llvm.Type { switch t := node.(type) { /*