createConvert creates a Go type conversion instruction.
(typeFrom, typeTo types.Type, value llvm.Value, pos token.Pos)
| 3185 | |
| 3186 | // createConvert creates a Go type conversion instruction. |
| 3187 | func (b *builder) createConvert(typeFrom, typeTo types.Type, value llvm.Value, pos token.Pos) (llvm.Value, error) { |
| 3188 | llvmTypeFrom := value.Type() |
| 3189 | llvmTypeTo := b.getLLVMType(typeTo) |
| 3190 | |
| 3191 | // Conversion between unsafe.Pointer and uintptr. |
| 3192 | isPtrFrom := isPointer(typeFrom.Underlying()) |
| 3193 | isPtrTo := isPointer(typeTo.Underlying()) |
| 3194 | if isPtrFrom && !isPtrTo { |
| 3195 | return b.CreatePtrToInt(value, llvmTypeTo, ""), nil |
| 3196 | } else if !isPtrFrom && isPtrTo { |
| 3197 | return b.CreateIntToPtr(value, llvmTypeTo, ""), nil |
| 3198 | } |
| 3199 | |
| 3200 | // Conversion between pointers and unsafe.Pointer. |
| 3201 | if isPtrFrom && isPtrTo { |
| 3202 | return value, nil |
| 3203 | } |
| 3204 | |
| 3205 | switch typeTo := typeTo.Underlying().(type) { |
| 3206 | case *types.Basic: |
| 3207 | sizeFrom := b.targetData.TypeAllocSize(llvmTypeFrom) |
| 3208 | |
| 3209 | if typeTo.Info()&types.IsString != 0 { |
| 3210 | switch typeFrom := typeFrom.Underlying().(type) { |
| 3211 | case *types.Basic: |
| 3212 | // Assume a Unicode code point, as that is the only possible |
| 3213 | // value here. |
| 3214 | // Cast to an i32 value as expected by |
| 3215 | // runtime.stringFromUnicode. |
| 3216 | if sizeFrom > 4 { |
| 3217 | value = b.CreateTrunc(value, b.ctx.Int32Type(), "") |
| 3218 | } else if sizeFrom < 4 && typeTo.Info()&types.IsUnsigned != 0 { |
| 3219 | value = b.CreateZExt(value, b.ctx.Int32Type(), "") |
| 3220 | } else if sizeFrom < 4 { |
| 3221 | value = b.CreateSExt(value, b.ctx.Int32Type(), "") |
| 3222 | } |
| 3223 | return b.createRuntimeCall("stringFromUnicode", []llvm.Value{value}, ""), nil |
| 3224 | case *types.Slice: |
| 3225 | switch typeFrom.Elem().(*types.Basic).Kind() { |
| 3226 | case types.Byte: |
| 3227 | return b.createRuntimeCall("stringFromBytes", []llvm.Value{value}, ""), nil |
| 3228 | case types.Rune: |
| 3229 | return b.createRuntimeCall("stringFromRunes", []llvm.Value{value}, ""), nil |
| 3230 | default: |
| 3231 | return llvm.Value{}, b.makeError(pos, "todo: convert to string: "+typeFrom.String()) |
| 3232 | } |
| 3233 | default: |
| 3234 | return llvm.Value{}, b.makeError(pos, "todo: convert to string: "+typeFrom.String()) |
| 3235 | } |
| 3236 | } |
| 3237 | |
| 3238 | typeFrom := typeFrom.Underlying().(*types.Basic) |
| 3239 | sizeTo := b.targetData.TypeAllocSize(llvmTypeTo) |
| 3240 | |
| 3241 | if typeFrom.Info()&types.IsInteger != 0 && typeTo.Info()&types.IsInteger != 0 { |
| 3242 | // Conversion between two integers. |
| 3243 | if sizeFrom > sizeTo { |
| 3244 | return b.CreateTrunc(value, llvmTypeTo, ""), nil |
no test coverage detected