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 { @@ -245,6 +247,12 @@ res: []types.Type{EmptyInterface, Bool}, }, { + name: "__go_byte_array_to_string", + rfi: &ri.byteArrayToString, + args: []types.Type{UnsafePointer, Int}, + res: []types.Type{String}, + }, + { name: "__go_int_array_to_string", rfi: &ri.intArrayToString, args: []types.Type{UnsafePointer, Int}, @@ -319,12 +327,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 +468,12 @@ res: []types.Type{String}, }, { + name: "__go_string_to_byte_array", + rfi: &ri.stringToByteArray, + args: []types.Type{String}, + res: []types.Type{ByteSlice}, + }, + { name: "__go_string_to_int_array", rfi: &ri.stringToIntArray, args: []types.Type{String}, @@ -563,12 +571,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/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