Support for objects' cast implemented
for code
--------8<--------
> cat ../backend.native/tests/codegen/basics/cast_simple.kt
open class A() {}
class B(): A() {}
fun castSimple(o: Any) : A = o as A
fun castTest(): Boolean {
val b = B()
castSimple(b)
return true
}
--------8<--------
translator generates
--------8<--------
>llvm-dis-mp-3.8 ../backend.native/tests/codegen/basics/cast_simple.kt.bc -o -
; ModuleID = '../backend.native/tests/codegen/basics/cast_simple.kt.bc'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.12.0"
...
define i8* @"kfun:castSimple(Any)"(i8*) {
entry:
%o = alloca i8*
store i8* %0, i8** %o
%tmp_1 = load i8*, i8** %o
%tmp_2 = bitcast i8* %tmp_1 to %struct.ObjHeader*
call void @CheckInstance(%struct.ObjHeader* %tmp_2, %struct.TypeInfo* @"ktype:A")
ret i8* %tmp_1
}
--------8<--------
This commit is contained in:
committed by
vvlevchenko
parent
9c28555e55
commit
3a49e69046
+2
@@ -28,6 +28,8 @@ internal class Context(val irModule: IrModuleFragment, val runtime: Runtime, val
|
||||
val allocArrayFunction = importRtFunction("AllocArrayInstance")
|
||||
val lookupFieldOffset = importRtFunction("LookupFieldOffset")
|
||||
val lookupOpenMethodFunction = importRtFunction("LookupOpenMethod")
|
||||
val isInstanceFunction = importRtFunction("IsInstance")
|
||||
val checkInstanceFunction = importRtFunction("CheckInstance")
|
||||
|
||||
fun dispose() {
|
||||
LLVMDisposeBuilder(llvmBuilder)
|
||||
|
||||
+34
-6
@@ -2,9 +2,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
import kotlin_native.interop.*
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.isArray
|
||||
import org.jetbrains.kotlin.backend.konan.isInterface
|
||||
import org.jetbrains.kotlin.backend.konan.isIntrinsic
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.LazyClassReceiverParameterDescriptor
|
||||
@@ -21,6 +19,8 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
|
||||
fun emitLLVM(module: IrModuleFragment, runtimeFile: String, outFile: String) {
|
||||
val llvmModule = LLVMModuleCreateWithName("out")!! // TODO: dispose
|
||||
@@ -294,6 +294,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
private fun evaluateExpression(tmpVariableName: String, value: IrElement?): LLVMOpaqueValue? {
|
||||
when (value) {
|
||||
is IrSetterCallImpl -> return evaluateSetterCall (tmpVariableName, value)
|
||||
is IrTypeOperatorCall-> return evaluateTypeOperator(tmpVariableName, value)
|
||||
is IrCall -> return evaluateCall (tmpVariableName, value)
|
||||
is IrGetValue -> return evaluateGetValue (tmpVariableName, value)
|
||||
is IrSetVariable -> return evaluateSetVariable ( value)
|
||||
@@ -370,6 +371,32 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
return codegen.store(ret!!, variable)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
// table of conversion with llvm for primitive types
|
||||
// to be used in replacement fo primitive.toX() calls with
|
||||
// translator intrinsics.
|
||||
// | byte short int long float double
|
||||
//------------|----------------------------------------------------
|
||||
// byte | x sext sext sext sitofp sitofp
|
||||
// short | trunc x sext sext sitofp sitofp
|
||||
// int | trunc trunc x sext sitofp sitofp
|
||||
// long | trunc trunc trunc x sitofp sitofp
|
||||
// float | fptosi fptosi fptosi fptosi x fpext
|
||||
// double | fptosi fptosi fptosi fptosi fptrunc x
|
||||
|
||||
private fun evaluateTypeOperator(tmpVariableName: String, value: IrTypeOperatorCall): LLVMOpaqueValue {
|
||||
logger.log("evaluateTypeOperator : ${ir2string(value)}")
|
||||
assert(!KotlinBuiltIns.isPrimitiveType(value.type) && !KotlinBuiltIns.isPrimitiveType(value.argument.type))
|
||||
|
||||
val dstDescriptor = TypeUtils.getClassDescriptor(value.type) // Get class descriptor for dst type.
|
||||
val dstTypeInfo = codegen.typeInfoValue(dstDescriptor!!) // Get TypeInfo for dst type.
|
||||
val srcArg = evaluateExpression(codegen.newVar(), value.argument)!! // Evaluate src expression.
|
||||
val srcObjInfoPtr = codegen.bitcast(kObjHeaderPtr, srcArg, codegen.newVar()) // Cast src to ObjInfoPtr.
|
||||
val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
|
||||
codegen.call(context.checkInstanceFunction, args, "") // Check if dst is subclass of src.
|
||||
return srcArg
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun evaluateGetField(value: IrGetField): LLVMOpaqueValue {
|
||||
@@ -603,7 +630,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
isInt -> return codegen.icmpEq(arg0, arg1, tmpVariableName)
|
||||
else -> {
|
||||
val functions = arg0Type.memberScope.getContributedFunctions(Name.identifier("equals"), NoLookupLocation.FROM_BACKEND).filter {
|
||||
it.valueParameters.size == 1 && KotlinBuiltIns.isAnyOrNullableAny(it.valueParameters[0].type)
|
||||
it.valueParameters.size == 1 && KotlinBuiltIns.isNullableAny(it.valueParameters[0].type)
|
||||
}
|
||||
assert(functions.size == 1)
|
||||
val descriptor = functions.first()
|
||||
@@ -659,8 +686,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
fun callDirect(descriptor: FunctionDescriptor, args: List<LLVMOpaqueValue?>, result: String?): LLVMOpaqueValue? {
|
||||
val llvmFunction = codegen.functionLlvmValue(descriptor)
|
||||
return call(descriptor, llvmFunction, args, result)
|
||||
val realDescriptor = DescriptorUtils.unwrapFakeOverride(descriptor)
|
||||
val llvmFunction = codegen.functionLlvmValue(realDescriptor)
|
||||
return codegen.call(llvmFunction, args, result)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
@@ -267,7 +267,7 @@ void* AllocInstance(const TypeInfo* type_info, PlacementHint hint);
|
||||
void* AllocArrayInstance(
|
||||
const TypeInfo* type_info, PlacementHint hint, uint32_t elements);
|
||||
int IsInstance(const ObjHeader* obj, const TypeInfo* type_info);
|
||||
void CheckCast(const ObjHeader* obj, const TypeInfo* type_info);
|
||||
void CheckInstance(const ObjHeader* obj, const TypeInfo* type_info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user