Index: CMakeLists.txt =================================================================== --- CMakeLists.txt +++ CMakeLists.txt @@ -63,6 +63,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/third_party/gofrontend/libgo/go/cmd/go/http.go ${CMAKE_CURRENT_SOURCE_DIR}/third_party/gofrontend/libgo/go/cmd/go/list.go ${CMAKE_CURRENT_SOURCE_DIR}/third_party/gofrontend/libgo/go/cmd/go/main.go + ${CMAKE_CURRENT_SOURCE_DIR}/third_party/gofrontend/libgo/go/cmd/go/note.go ${CMAKE_CURRENT_SOURCE_DIR}/third_party/gofrontend/libgo/go/cmd/go/pkg.go ${CMAKE_CURRENT_SOURCE_DIR}/third_party/gofrontend/libgo/go/cmd/go/run.go ${CMAKE_CURRENT_SOURCE_DIR}/third_party/gofrontend/libgo/go/cmd/go/signal.go @@ -78,6 +79,7 @@ add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/bin/llgo-go${CMAKE_EXECUTABLE_SUFFIX} COMMAND ${CMAKE_BINARY_DIR}/bin/llgo -static-libgo + -I ${CMAKE_CURRENT_BINARY_DIR}/libgo -o ${CMAKE_BINARY_DIR}/bin/llgo-go${CMAKE_EXECUTABLE_SUFFIX} ${LLGO_GO_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/libgo/zstdpkglist.go Index: cmd/gllgo/gllgo.go =================================================================== --- cmd/gllgo/gllgo.go +++ cmd/gllgo/gllgo.go @@ -746,7 +746,7 @@ if opts.staticLibgo { args = append(args, "-Wl,-Bstatic", "-lgo-llgo", "-Wl,-Bdynamic", "-lpthread", "-lm") } else { - args = append(args, "-lgo-llgo") + args = append(args, "-lgo-llgo", "-lm") } } else { linkerPath = opts.gccgoPath Index: irgen/runtime.go =================================================================== --- irgen/runtime.go +++ irgen/runtime.go @@ -64,6 +64,7 @@ // Runtime intrinsics append, assertInterface, + byteArrayToString, canRecover, chanCap, chanLen, @@ -92,7 +93,6 @@ New, newChannel, newMap, - NewNopointers, newSelect, panic, printBool, @@ -121,6 +121,7 @@ stringiter2, stringPlus, stringSlice, + stringToByteArray, stringToIntArray, typeDescriptorsEqual, undefer runtimeFnInfo @@ -141,6 +142,7 @@ UnsafePointer := types.Typ[types.UnsafePointer] EmptyInterface := types.NewInterface(nil, nil) + ByteSlice := types.NewSlice(types.Typ[types.Byte]) IntSlice := types.NewSlice(types.Typ[types.Int]) for _, rt := range [...]struct { @@ -162,6 +164,13 @@ res: []types.Type{UnsafePointer}, }, { + name: "__go_byte_array_to_string", + rfi: &ri.byteArrayToString, + args: []types.Type{UnsafePointer, Int}, + res: []types.Type{String}, + attrs: []llvm.Attribute{llvm.NoUnwindAttribute}, + }, + { name: "__go_can_recover", rfi: &ri.canRecover, args: []types.Type{UnsafePointer}, @@ -301,10 +310,11 @@ res: []types.Type{Int}, }, { - name: "__go_new", - rfi: &ri.New, - args: []types.Type{UnsafePointer, Uintptr}, - res: []types.Type{UnsafePointer}, + name: "__go_new", + rfi: &ri.New, + args: []types.Type{UnsafePointer, Uintptr}, + res: []types.Type{UnsafePointer}, + attrs: []llvm.Attribute{llvm.NoUnwindAttribute}, }, { name: "__go_new_channel", @@ -319,12 +329,6 @@ 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}, @@ -466,6 +470,13 @@ res: []types.Type{String}, }, { + name: "__go_string_to_byte_array", + rfi: &ri.stringToByteArray, + args: []types.Type{String}, + res: []types.Type{ByteSlice}, + attrs: []llvm.Attribute{llvm.NoUnwindAttribute}, + }, + { name: "__go_string_to_int_array", rfi: &ri.stringToIntArray, args: []types.Type{String}, @@ -563,12 +574,6 @@ return v } -func (fr *frame) createMalloc(size llvm.Value) llvm.Value { - return fr.runtime.NewNopointers.callOnly(fr, - llvm.ConstNull(llvm.PointerType(llvm.Int8Type(), 0)), - fr.createZExtOrTrunc(size, fr.target.IntPtrType(), ""))[0] -} - func (fr *frame) createTypeMalloc(t types.Type) llvm.Value { size := llvm.ConstInt(fr.target.IntPtrType(), uint64(fr.llvmtypes.Sizeof(t)), false) malloc := fr.runtime.New.callOnly(fr, fr.types.ToRuntime(t), size)[0] Index: irgen/ssa.go =================================================================== --- irgen/ssa.go +++ irgen/ssa.go @@ -402,7 +402,7 @@ // an unwind block. We can short-circuit the check for defers with // f.Recover != nil. if f.Recover != nil || hasDefer(f) { - fr.unwindBlock = llvm.AddBasicBlock(fr.function, "") + fr.unwindBlock = llvm.AddBasicBlock(fr.function, "unwind") fr.frameptr = fr.builder.CreateAlloca(llvm.Int8Type(), "") } @@ -432,7 +432,7 @@ fr.fixupPhis() if !fr.unwindBlock.IsNil() { - fr.setupUnwindBlock(f.Recover, f.Signature.Results()) + fr.setupUnwindBlock(f.Recover) } // The init function needs to register the GC roots first. We do this @@ -623,19 +623,12 @@ fr.runtime.undefer.invoke(fr, retrylpad, fr.frameptr) } -func (fr *frame) setupUnwindBlock(rec *ssa.BasicBlock, results *types.Tuple) { - recoverbb := llvm.AddBasicBlock(fr.function, "") +func (fr *frame) setupUnwindBlock(rec *ssa.BasicBlock) { + var recoverbb llvm.BasicBlock if rec != nil { - fr.translateBlock(rec, recoverbb) - } else if results.Len() == 0 || results.At(0).Anonymous() { - // TODO(pcc): Remove this code after https://codereview.appspot.com/87210044/ lands - fr.builder.SetInsertPointAtEnd(recoverbb) - values := make([]llvm.Value, results.Len()) - for i := range values { - values[i] = llvm.ConstNull(fr.llvmtypes.ToLLVM(results.At(i).Type())) - } - fr.retInf.encode(llvm.GlobalContext(), fr.allocaBuilder, fr.builder, values) + recoverbb = fr.blocks[rec.Index] } else { + recoverbb = llvm.AddBasicBlock(fr.function, "recover") fr.builder.SetInsertPointAtEnd(recoverbb) fr.builder.CreateUnreachable() } Index: irgen/typemap.go =================================================================== --- irgen/typemap.go +++ irgen/typemap.go @@ -71,13 +71,25 @@ typeSliceType, methodSliceType, imethodSliceType, structFieldSliceType llvm.Type - hashFnType, equalFnType llvm.Type - - hashFnEmptyInterface, hashFnInterface, hashFnFloat, hashFnComplex, hashFnString, hashFnIdentity, hashFnError llvm.Value - equalFnEmptyInterface, equalFnInterface, equalFnFloat, equalFnComplex, equalFnString, equalFnIdentity, equalFnError llvm.Value - - zeroType llvm.Type - zeroValue llvm.Value + funcValType llvm.Type + hashFnType, equalFnType llvm.Type + ptrHashFnNestType, ptrEqualFnNestType llvm.Type // with *funcValType as first arg + + hashFnEmptyInterfaceDescriptor, + hashFnInterfaceDescriptor, + hashFnFloatDescriptor, + hashFnComplexDescriptor, + hashFnStringDescriptor, + hashFnIdentityDescriptor, + hashFnErrorDescriptor llvm.Value + + equalFnEmptyInterfaceDescriptor, + equalFnInterfaceDescriptor, + equalFnFloatDescriptor, + equalFnComplexDescriptor, + equalFnStringDescriptor, + equalFnIdentityDescriptor, + equalFnErrorDescriptor llvm.Value } func NewLLVMTypeMap(ctx llvm.Context, target llvm.TargetData) *llvmTypeMap { @@ -117,35 +129,60 @@ boolType := llvm.Int8Type() stringPtrType := llvm.PointerType(tm.stringType, 0) - // Create runtime algorithm function types. + tm.funcValType = tm.ctx.StructCreateNamed("funcVal") + tm.funcValType.StructSetBody([]llvm.Type{ + llvm.PointerType(llvm.FunctionType(llvm.VoidType(), []llvm.Type{}, false), 0), + }, false) + ptrFuncValType := llvm.PointerType(tm.funcValType, 0) + params := []llvm.Type{voidPtrType, uintptrType} tm.hashFnType = llvm.FunctionType(uintptrType, params, false) + params = []llvm.Type{ptrFuncValType, voidPtrType, uintptrType} + tm.ptrHashFnNestType = llvm.PointerType(llvm.FunctionType(uintptrType, params, false), 0) params = []llvm.Type{voidPtrType, voidPtrType, uintptrType} tm.equalFnType = llvm.FunctionType(boolType, params, false) + params = []llvm.Type{ptrFuncValType, voidPtrType, voidPtrType, uintptrType} + tm.ptrEqualFnNestType = llvm.PointerType(llvm.FunctionType(boolType, params, false), 0) - tm.hashFnEmptyInterface = llvm.AddFunction(tm.module, "__go_type_hash_empty_interface", tm.hashFnType) - tm.hashFnInterface = llvm.AddFunction(tm.module, "__go_type_hash_interface", tm.hashFnType) - tm.hashFnFloat = llvm.AddFunction(tm.module, "__go_type_hash_float", tm.hashFnType) - tm.hashFnComplex = llvm.AddFunction(tm.module, "__go_type_hash_complex", tm.hashFnType) - tm.hashFnString = llvm.AddFunction(tm.module, "__go_type_hash_string", tm.hashFnType) - tm.hashFnIdentity = llvm.AddFunction(tm.module, "__go_type_hash_identity", tm.hashFnType) - tm.hashFnError = llvm.AddFunction(tm.module, "__go_type_hash_error", tm.hashFnType) - - tm.equalFnEmptyInterface = llvm.AddFunction(tm.module, "__go_type_equal_empty_interface", tm.equalFnType) - tm.equalFnInterface = llvm.AddFunction(tm.module, "__go_type_equal_interface", tm.equalFnType) - tm.equalFnFloat = llvm.AddFunction(tm.module, "__go_type_equal_float", tm.equalFnType) - tm.equalFnComplex = llvm.AddFunction(tm.module, "__go_type_equal_complex", tm.equalFnType) - tm.equalFnString = llvm.AddFunction(tm.module, "__go_type_equal_string", tm.equalFnType) - tm.equalFnIdentity = llvm.AddFunction(tm.module, "__go_type_equal_identity", tm.equalFnType) - tm.equalFnError = llvm.AddFunction(tm.module, "__go_type_equal_error", tm.equalFnType) - - // The body of this type is set in emitTypeDescInitializers once we have scanned - // every type, as it needs to be as large and well aligned as the - // largest/most aligned type. - tm.zeroType = tm.ctx.StructCreateNamed("zero") - tm.zeroValue = llvm.AddGlobal(tm.module, tm.zeroType, "go$zerovalue") - tm.zeroValue.SetLinkage(llvm.CommonLinkage) - tm.zeroValue.SetInitializer(llvm.ConstNull(tm.zeroType)) + algorithmDescriptors := [...]struct { + Name string + Hash *llvm.Value + Equal *llvm.Value + }{{ + "empty_interface", + &tm.hashFnEmptyInterfaceDescriptor, + &tm.equalFnEmptyInterfaceDescriptor, + }, { + "interface", + &tm.hashFnInterfaceDescriptor, + &tm.equalFnInterfaceDescriptor, + }, { + "float", + &tm.hashFnFloatDescriptor, + &tm.equalFnFloatDescriptor, + }, { + "complex", + &tm.hashFnComplexDescriptor, + &tm.equalFnComplexDescriptor, + }, { + "string", + &tm.hashFnStringDescriptor, + &tm.equalFnStringDescriptor, + }, { + "identity", + &tm.hashFnIdentityDescriptor, + &tm.equalFnIdentityDescriptor, + }, { + "error", + &tm.hashFnErrorDescriptor, + &tm.equalFnErrorDescriptor, + }} + for _, alg := range algorithmDescriptors { + hashDescriptorName := "__go_type_hash_" + alg.Name + "_descriptor" + equalDescriptorName := "__go_type_equal_" + alg.Name + "_descriptor" + *alg.Hash = llvm.AddGlobal(tm.module, tm.funcValType, hashDescriptorName) + *alg.Equal = llvm.AddGlobal(tm.module, tm.funcValType, equalDescriptorName) + } tm.commonTypeType = tm.ctx.StructCreateNamed("commonType") commonTypeTypePtr := llvm.PointerType(tm.commonTypeType, 0) @@ -174,13 +211,12 @@ tm.ctx.Int8Type(), // fieldAlign uintptrType, // size tm.ctx.Int32Type(), // hash - llvm.PointerType(tm.hashFnType, 0), // hashfn - llvm.PointerType(tm.equalFnType, 0), // equalfn + llvm.PointerType(tm.funcValType, 0), // hashfn + llvm.PointerType(tm.funcValType, 0), // equalfn voidPtrType, // gc stringPtrType, // string llvm.PointerType(tm.uncommonTypeType, 0), // uncommonType commonTypeTypePtr, // ptrToThis - llvm.PointerType(tm.zeroType, 0), // zero }, false) tm.typeSliceType = tm.makeNamedSliceType("typeSlice", commonTypeTypePtr) @@ -1096,9 +1132,6 @@ } } } - - tm.zeroType.StructSetBody([]llvm.Type{llvm.ArrayType(tm.ctx.Int8Type(), int(maxSize))}, false) - tm.zeroValue.SetAlignment(int(maxAlign)) } const ( @@ -1247,8 +1280,8 @@ equals := make([]llvm.Value, st.NumFields()) for i := range hashes { - fhash, fequal := tm.getAlgorithmFunctions(st.Field(i).Type()) - if fhash == tm.hashFnError { + fhash, fequal := tm.getAlgorithmDescriptors(st.Field(i).Type()) + if fhash == tm.hashFnErrorDescriptor { return fhash, fequal } hashes[i], equals[i] = fhash, fequal @@ -1260,53 +1293,52 @@ builder := tm.ctx.NewBuilder() defer builder.Dispose() - hash = llvm.AddFunction(tm.module, tm.mc.mangleHashFunctionName(st), tm.hashFnType) - hash.SetLinkage(llvm.LinkOnceODRLinkage) - builder.SetInsertPointAtEnd(llvm.AddBasicBlock(hash, "entry")) - sptr := builder.CreateBitCast(hash.Param(0), llsptrty, "") + hashFunctionName := tm.mc.mangleHashFunctionName(st) + hashFn := llvm.AddFunction(tm.module, hashFunctionName, tm.hashFnType) + hashFn.SetLinkage(llvm.LinkOnceODRLinkage) + hash = tm.createAlgorithmDescriptor(hashFunctionName+"_descriptor", hashFn) + + builder.SetInsertPointAtEnd(llvm.AddBasicBlock(hashFn, "entry")) + sptr := builder.CreateBitCast(hashFn.Param(0), llsptrty, "") hashval := llvm.ConstNull(tm.inttype) i33 := llvm.ConstInt(tm.inttype, 33, false) - for i, fhash := range hashes { + for i, hashDescriptor := range hashes { fptr := builder.CreateStructGEP(sptr, i, "") fptr = builder.CreateBitCast(fptr, i8ptr, "") - fsize := llvm.ConstInt(tm.inttype, uint64(tm.sizes.Sizeof(st.Field(i).Type())), false) - - hashcall := builder.CreateCall(fhash, []llvm.Value{fptr, fsize}, "") + fhash := tm.callHashDescriptor(builder, hashDescriptor, fptr, fsize) hashval = builder.CreateMul(hashval, i33, "") - hashval = builder.CreateAdd(hashval, hashcall, "") + hashval = builder.CreateAdd(hashval, fhash, "") } builder.CreateRet(hashval) - equal = llvm.AddFunction(tm.module, tm.mc.mangleEqualFunctionName(st), tm.equalFnType) - equal.SetLinkage(llvm.LinkOnceODRLinkage) - eqentrybb := llvm.AddBasicBlock(equal, "entry") - eqretzerobb := llvm.AddBasicBlock(equal, "retzero") + equalFunctionName := tm.mc.mangleEqualFunctionName(st) + equalFn := llvm.AddFunction(tm.module, equalFunctionName, tm.equalFnType) + equalFn.SetLinkage(llvm.LinkOnceODRLinkage) + equal = tm.createAlgorithmDescriptor(equalFunctionName+"_descriptor", equalFn) + eqentrybb := llvm.AddBasicBlock(equalFn, "entry") + eqretzerobb := llvm.AddBasicBlock(equalFn, "retzero") builder.SetInsertPointAtEnd(eqentrybb) - s1ptr := builder.CreateBitCast(equal.Param(0), llsptrty, "") - s2ptr := builder.CreateBitCast(equal.Param(1), llsptrty, "") + s1ptr := builder.CreateBitCast(equalFn.Param(0), llsptrty, "") + s2ptr := builder.CreateBitCast(equalFn.Param(1), llsptrty, "") zerobool := llvm.ConstNull(tm.ctx.Int8Type()) onebool := llvm.ConstInt(tm.ctx.Int8Type(), 1, false) - for i, fequal := range equals { + for i, equalDescriptor := range equals { f1ptr := builder.CreateStructGEP(s1ptr, i, "") f1ptr = builder.CreateBitCast(f1ptr, i8ptr, "") f2ptr := builder.CreateStructGEP(s2ptr, i, "") f2ptr = builder.CreateBitCast(f2ptr, i8ptr, "") - fsize := llvm.ConstInt(tm.inttype, uint64(tm.sizes.Sizeof(st.Field(i).Type())), false) - - equalcall := builder.CreateCall(fequal, []llvm.Value{f1ptr, f2ptr, fsize}, "") - equaleqzero := builder.CreateICmp(llvm.IntEQ, equalcall, zerobool, "") - - contbb := llvm.AddBasicBlock(equal, "cont") + fequal := tm.callEqualDescriptor(builder, equalDescriptor, f1ptr, f2ptr, fsize) + equaleqzero := builder.CreateICmp(llvm.IntEQ, fequal, zerobool, "") + contbb := llvm.AddBasicBlock(equalFn, "cont") builder.CreateCondBr(equaleqzero, eqretzerobb, contbb) - builder.SetInsertPointAtEnd(contbb) } @@ -1324,8 +1356,8 @@ return algs.hash, algs.equal } - ehash, eequal := tm.getAlgorithmFunctions(at.Elem()) - if ehash == tm.hashFnError { + ehash, eequal := tm.getAlgorithmDescriptors(at.Elem()) + if ehash == tm.hashFnErrorDescriptor { return ehash, eequal } @@ -1339,20 +1371,28 @@ builder := tm.ctx.NewBuilder() defer builder.Dispose() - hash = llvm.AddFunction(tm.module, tm.mc.mangleHashFunctionName(at), tm.hashFnType) - hash.SetLinkage(llvm.LinkOnceODRLinkage) - hashentrybb := llvm.AddBasicBlock(hash, "entry") + hashFunctionName := tm.mc.mangleHashFunctionName(at) + hashFn := llvm.AddFunction(tm.module, hashFunctionName, tm.hashFnType) + hashFn.SetLinkage(llvm.LinkOnceODRLinkage) + hash = tm.createAlgorithmDescriptor(hashFunctionName+"_descriptor", hashFn) + equalFunctionName := tm.mc.mangleHashFunctionName(at) + equalFn := llvm.AddFunction(tm.module, equalFunctionName, tm.equalFnType) + equalFn.SetLinkage(llvm.LinkOnceODRLinkage) + equal = tm.createAlgorithmDescriptor(equalFunctionName+"_descriptor", equalFn) + tm.algs.Set(at, algorithmFns{hash, equal}) + + hashentrybb := llvm.AddBasicBlock(hashFn, "entry") builder.SetInsertPointAtEnd(hashentrybb) if at.Len() == 0 { builder.CreateRet(llvm.ConstNull(tm.inttype)) } else { i33 := llvm.ConstInt(tm.inttype, 33, false) - aptr := builder.CreateBitCast(hash.Param(0), llelemty, "") - loopbb := llvm.AddBasicBlock(hash, "loop") + aptr := builder.CreateBitCast(hashFn.Param(0), llelemty, "") + loopbb := llvm.AddBasicBlock(hashFn, "loop") builder.CreateBr(loopbb) - exitbb := llvm.AddBasicBlock(hash, "exit") + exitbb := llvm.AddBasicBlock(hashFn, "exit") builder.SetInsertPointAtEnd(loopbb) indexphi := builder.CreatePHI(tm.inttype, "") @@ -1363,7 +1403,7 @@ eptr := builder.CreateGEP(aptr, []llvm.Value{index}, "") eptr = builder.CreateBitCast(eptr, i8ptr, "") - hashcall := builder.CreateCall(ehash, []llvm.Value{eptr, esize}, "") + hashcall := tm.callHashDescriptor(builder, ehash, eptr, esize) hashval = builder.CreateMul(hashval, i33, "") hashval = builder.CreateAdd(hashval, hashcall, "") @@ -1388,20 +1428,18 @@ zerobool := llvm.ConstNull(tm.ctx.Int8Type()) onebool := llvm.ConstInt(tm.ctx.Int8Type(), 1, false) - equal = llvm.AddFunction(tm.module, tm.mc.mangleEqualFunctionName(at), tm.equalFnType) - equal.SetLinkage(llvm.LinkOnceODRLinkage) - eqentrybb := llvm.AddBasicBlock(equal, "entry") + eqentrybb := llvm.AddBasicBlock(equalFn, "entry") builder.SetInsertPointAtEnd(eqentrybb) if at.Len() == 0 { builder.CreateRet(onebool) } else { - a1ptr := builder.CreateBitCast(equal.Param(0), llelemty, "") - a2ptr := builder.CreateBitCast(equal.Param(1), llelemty, "") - loopbb := llvm.AddBasicBlock(equal, "loop") + a1ptr := builder.CreateBitCast(equalFn.Param(0), llelemty, "") + a2ptr := builder.CreateBitCast(equalFn.Param(1), llelemty, "") + loopbb := llvm.AddBasicBlock(equalFn, "loop") builder.CreateBr(loopbb) - exitbb := llvm.AddBasicBlock(equal, "exit") - retzerobb := llvm.AddBasicBlock(equal, "retzero") + exitbb := llvm.AddBasicBlock(equalFn, "exit") + retzerobb := llvm.AddBasicBlock(equalFn, "retzero") builder.SetInsertPointAtEnd(loopbb) indexphi := builder.CreatePHI(tm.inttype, "") @@ -1412,10 +1450,10 @@ e2ptr := builder.CreateGEP(a2ptr, []llvm.Value{index}, "") e2ptr = builder.CreateBitCast(e2ptr, i8ptr, "") - equalcall := builder.CreateCall(eequal, []llvm.Value{e1ptr, e2ptr, esize}, "") + equalcall := tm.callEqualDescriptor(builder, eequal, e1ptr, e2ptr, esize) equaleqzero := builder.CreateICmp(llvm.IntEQ, equalcall, zerobool, "") - contbb := llvm.AddBasicBlock(equal, "cont") + contbb := llvm.AddBasicBlock(equalFn, "cont") builder.CreateCondBr(equaleqzero, retzerobb, contbb) builder.SetInsertPointAtEnd(contbb) @@ -1437,45 +1475,71 @@ builder.CreateRet(zerobool) } - tm.algs.Set(at, algorithmFns{hash, equal}) return } -func (tm *TypeMap) getAlgorithmFunctions(t types.Type) (hash, equal llvm.Value) { +func (tm *TypeMap) createAlgorithmDescriptor(name string, fn llvm.Value) llvm.Value { + d := llvm.AddGlobal(tm.module, tm.funcValType, name) + d.SetLinkage(llvm.LinkOnceODRLinkage) + d.SetGlobalConstant(true) + fn = llvm.ConstBitCast(fn, tm.funcValType.StructElementTypes()[0]) + init := llvm.ConstNull(tm.funcValType) + init = llvm.ConstInsertValue(init, fn, []uint32{0}) + d.SetInitializer(init) + return d +} + +func (tm *TypeMap) callHashDescriptor(builder llvm.Builder, descriptor, ptr, size llvm.Value) llvm.Value { + hashFn := builder.CreateLoad(builder.CreateStructGEP(descriptor, 0, ""), "") + hashFn = builder.CreateBitCast(hashFn, tm.ptrHashFnNestType, "") + hashcall := builder.CreateCall(hashFn, []llvm.Value{descriptor, ptr, size}, "") + hashcall.AddInstrAttribute(1, llvm.NestAttribute) + return hashcall +} + +func (tm *TypeMap) callEqualDescriptor(builder llvm.Builder, descriptor, ptr1, ptr2, size llvm.Value) llvm.Value { + equalFn := builder.CreateLoad(builder.CreateStructGEP(descriptor, 0, ""), "") + equalFn = builder.CreateBitCast(equalFn, tm.ptrEqualFnNestType, "") + equalcall := builder.CreateCall(equalFn, []llvm.Value{descriptor, ptr1, ptr2, size}, "") + equalcall.AddInstrAttribute(1, llvm.NestAttribute) + return equalcall +} + +func (tm *TypeMap) getAlgorithmDescriptors(t types.Type) (hash, equal llvm.Value) { switch t := t.Underlying().(type) { case *types.Interface: if t.NumMethods() == 0 { - hash = tm.hashFnEmptyInterface - equal = tm.equalFnEmptyInterface + hash = tm.hashFnEmptyInterfaceDescriptor + equal = tm.equalFnEmptyInterfaceDescriptor } else { - hash = tm.hashFnInterface - equal = tm.equalFnInterface + hash = tm.hashFnInterfaceDescriptor + equal = tm.equalFnInterfaceDescriptor } case *types.Basic: switch t.Kind() { case types.Float32, types.Float64: - hash = tm.hashFnFloat - equal = tm.equalFnFloat + hash = tm.hashFnFloatDescriptor + equal = tm.equalFnFloatDescriptor case types.Complex64, types.Complex128: - hash = tm.hashFnComplex - equal = tm.equalFnComplex + hash = tm.hashFnComplexDescriptor + equal = tm.equalFnComplexDescriptor case types.String: - hash = tm.hashFnString - equal = tm.equalFnString + hash = tm.hashFnStringDescriptor + equal = tm.equalFnStringDescriptor default: - hash = tm.hashFnIdentity - equal = tm.equalFnIdentity + hash = tm.hashFnIdentityDescriptor + equal = tm.equalFnIdentityDescriptor } case *types.Signature, *types.Map, *types.Slice: - hash = tm.hashFnError - equal = tm.equalFnError + hash = tm.hashFnErrorDescriptor + equal = tm.equalFnErrorDescriptor case *types.Struct: hash, equal = tm.getStructAlgorithmFunctions(t) case *types.Array: hash, equal = tm.getArrayAlgorithmFunctions(t) default: - hash = tm.hashFnIdentity - equal = tm.equalFnIdentity + hash = tm.hashFnIdentityDescriptor + equal = tm.equalFnIdentityDescriptor } return @@ -1704,13 +1768,13 @@ } func (tm *TypeMap) makeCommonType(t types.Type) llvm.Value { - var vals [12]llvm.Value + var vals [11]llvm.Value vals[0] = llvm.ConstInt(tm.ctx.Int8Type(), uint64(runtimeTypeKind(t)), false) vals[1] = llvm.ConstInt(tm.ctx.Int8Type(), uint64(tm.Alignof(t)), false) vals[2] = vals[1] vals[3] = llvm.ConstInt(tm.inttype, uint64(tm.Sizeof(t)), false) vals[4] = llvm.ConstInt(tm.ctx.Int32Type(), uint64(tm.getTypeHash(t)), false) - hash, equal := tm.getAlgorithmFunctions(t) + hash, equal := tm.getAlgorithmDescriptors(t) vals[5] = hash vals[6] = equal vals[7] = tm.getGcPointer(t) @@ -1718,13 +1782,12 @@ tm.writeType(t, &b) vals[8] = tm.globalStringPtr(b.String()) vals[9] = tm.makeUncommonTypePtr(t) - if _, ok := t.(*types.Named); ok { + switch t.(type) { + case *types.Named, *types.Struct: vals[10] = tm.getTypeDescriptorPointer(types.NewPointer(t)) - } else { + default: vals[10] = llvm.ConstPointerNull(llvm.PointerType(tm.commonTypeType, 0)) } - vals[11] = tm.zeroValue - return llvm.ConstNamedStruct(tm.commonTypeType, vals[:]) } Index: irgen/value.go =================================================================== --- irgen/value.go +++ irgen/value.go @@ -17,6 +17,7 @@ import ( "fmt" "go/token" + "llvm.org/llgo/third_party/gotools/go/exact" "llvm.org/llgo/third_party/gotools/go/types" "llvm.org/llvm/bindings/go/llvm" @@ -480,20 +481,8 @@ // string -> []byte if isSlice(dsttyp, types.Byte) { - value := v.value - strdata := fr.builder.CreateExtractValue(value, 0, "") - strlen := fr.builder.CreateExtractValue(value, 1, "") - - // Data must be copied, to prevent changes in - // the byte slice from mutating the string. - newdata := fr.createMalloc(strlen) - fr.memcpy(newdata, strdata, strlen) - - struct_ := llvm.Undef(fr.types.ToLLVM(dsttyp)) - struct_ = fr.builder.CreateInsertValue(struct_, newdata, 0, "") - struct_ = fr.builder.CreateInsertValue(struct_, strlen, 1, "") - struct_ = fr.builder.CreateInsertValue(struct_, strlen, 2, "") - return newValue(struct_, origdsttyp) + sliceValue := fr.runtime.stringToByteArray.callOnly(fr, v.value)[0] + return newValue(sliceValue, origdsttyp) } // string -> []rune @@ -504,19 +493,10 @@ // []byte -> string if isSlice(srctyp, types.Byte) && isString(dsttyp) { - value := v.value - data := fr.builder.CreateExtractValue(value, 0, "") - len := fr.builder.CreateExtractValue(value, 1, "") - - // Data must be copied, to prevent changes in - // the byte slice from mutating the string. - newdata := fr.createMalloc(len) - fr.memcpy(newdata, data, len) - - struct_ := llvm.Undef(fr.types.ToLLVM(types.Typ[types.String])) - struct_ = fr.builder.CreateInsertValue(struct_, newdata, 0, "") - struct_ = fr.builder.CreateInsertValue(struct_, len, 1, "") - return newValue(struct_, types.Typ[types.String]) + data := fr.builder.CreateExtractValue(v.value, 0, "") + len := fr.builder.CreateExtractValue(v.value, 1, "") + stringValue := fr.runtime.byteArrayToString.callOnly(fr, data, len)[0] + return newValue(stringValue, dsttyp) } // []rune -> string Index: libgo-check-failures.diff =================================================================== --- libgo-check-failures.diff +++ libgo-check-failures.diff @@ -47,15 +47,3 @@ select { case <-ch: case <-time.After(time.Second * 4): -diff -r a6e10414311a libgo/go/runtime/runtime_test.go ---- a/libgo/go/runtime/runtime_test.go Fri Jan 16 07:57:02 2015 -0800 -+++ b/libgo/go/runtime/runtime_test.go Fri Apr 03 15:07:47 2015 -0700 -@@ -176,6 +176,8 @@ - } - - func TestSetPanicOnFault(t *testing.T) { -+ t.Skip("skipping for llgo due to lack of non-call exception support") -+ - // This currently results in a fault in the signal trampoline on - // dragonfly/386 - see issue 7421. - if GOOS == "dragonfly" && GOARCH == "386" { Index: update_third_party.sh =================================================================== --- update_third_party.sh +++ update_third_party.sh @@ -4,8 +4,8 @@ llgosrcdir=$(dirname "$scriptpath") cd $llgosrcdir -gofrontendrepo=https://code.google.com/p/gofrontend -gofrontendrev=15a24202fa42 +gofrontendrepo=https://go.googlesource.com/gofrontend +gofrontendrev=81eb6a3f425b2158c67ee32c0cc973a72ce9d6be gccrepo=svn://gcc.gnu.org/svn/gcc/trunk gccrev=219477 @@ -14,7 +14,7 @@ gotoolsrev=d4e70101500b43ffe705d4c45e50dd4f1c8e3b2e linerrepo=https://github.com/peterh/liner.git -linerrev=1bb0d1c1a25ed393d8feb09bab039b2b1b1fbced +linerrev=4d47685ab2fd2dbb46c66b831344d558bc4be5b9 tempdir=$(mktemp -d /tmp/update_third_party.XXXXXX) gofrontenddir=$tempdir/gofrontend @@ -24,9 +24,21 @@ rm -rf third_party mkdir -p third_party/gofrontend third_party/gotools +git_clone() { + repo=$1 + dir=$2 + rev=$3 + git clone $repo $dir + ( + cd $dir + git checkout $rev + rm -fr .git + ) +} + # --------------------- gofrontend --------------------- -hg clone -r $gofrontendrev $gofrontendrepo $gofrontenddir +git_clone $gofrontendrepo $gofrontenddir $gofrontendrev cp -r $gofrontenddir/LICENSE $gofrontenddir/libgo third_party/gofrontend @@ -88,8 +100,7 @@ # --------------------- go.tools --------------------- -git clone $gotoolsrepo $gotoolsdir -(cd $gotoolsdir && git checkout $gotoolsrev) +git_clone $gotoolsrepo $gotoolsdir $gotoolsrev cp -r $gotoolsdir/LICENSE $gotoolsdir/go third_party/gotools @@ -99,8 +110,7 @@ # --------------------- peterh/liner ----------------- -git clone $linerrepo $linerdir -(cd $linerdir && git checkout $linerrev && rm -rf .git) +git_clone $linerrepo $linerdir $linerrev # --------------------- license check ---------------------