backend.konan: support function types in codegen

This commit is contained in:
Svyatoslav Scherbina
2016-12-08 15:01:32 +07:00
committed by SvyatoslavScherbina
parent 2fa2727935
commit b5ffc48547
3 changed files with 45 additions and 0 deletions
@@ -154,6 +154,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
fun lastBasicBlock(): LLVMBasicBlockRef? = LLVMGetLastBasicBlock(currentFunction!!.llvmFunction)
fun functionLlvmValue(descriptor: FunctionDescriptor) = descriptor.llvmFunction
fun functionEntryPointAddress(descriptor: FunctionDescriptor) = descriptor.entryPointAddress.llvm
fun functionHash(descriptor: FunctionDescriptor): LLVMValueRef = descriptor.functionName.localHash.llvm
fun br(bbLabel: LLVMBasicBlockRef): LLVMValueRef {
@@ -1,6 +1,7 @@
package org.jetbrains.kotlin.backend.konan.llvm
import llvm.*
import org.jetbrains.kotlin.backend.konan.isUnboundCallableReference
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.types.KotlinType
@@ -8,6 +9,7 @@ internal fun ContextUtils.getLLVMType(type: KotlinType): LLVMTypeRef {
return when {
// Nullable types must be represented as objects for boxing.
type.isMarkedNullable -> this.kObjHeaderPtr
type.isUnboundCallableReference() -> int8TypePtr
KotlinBuiltIns.isBoolean(type) -> LLVMInt1Type()
KotlinBuiltIns.isByte(type) -> LLVMInt8Type()
KotlinBuiltIns.isShort(type) || KotlinBuiltIns.isChar(type) -> LLVMInt16Type()
@@ -4,6 +4,7 @@ import kotlinx.cinterop.*
import llvm.*
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrElement
@@ -607,12 +608,14 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
is IrTry -> return evaluateTry ( value)
is IrStringConcatenation -> return evaluateStringConcatenation(tmpVariableName, value)
is IrBlockBody -> return evaluateBlock (tmpVariableName, value as IrStatementContainer)
is IrComposite -> return evaluateBlock (tmpVariableName, value)
is IrWhileLoop -> return evaluateWhileLoop ( value)
is IrDoWhileLoop -> return evaluateDoWhileLoop ( value)
is IrVararg -> return evaluateVararg (tmpVariableName, value)
is IrBreak -> return evaluateBreak ( value)
is IrContinue -> return evaluateContinue ( value)
is IrGetObjectValue -> return evaluateGetObjectValue (tmpVariableName, value)
is IrCallableReference -> return evaluateCallableReference (tmpVariableName, value)
null -> return null
else -> {
TODO("${ir2string(value)}")
@@ -1549,9 +1552,19 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
//-------------------------------------------------------------------------//
private fun evaluateCallableReference(tmpVariableName: String, expression: IrCallableReference): LLVMValueRef {
assert (expression.type.isUnboundCallableReference())
assert (expression.getArguments().isEmpty())
val entry = codegen.functionEntryPointAddress(expression.descriptor as FunctionDescriptor)
return entry
}
//-------------------------------------------------------------------------//
private fun evaluateFunctionCall(tmpVariableName: String, callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
val descriptor:FunctionDescriptor = callee.descriptor as FunctionDescriptor
when (descriptor) {
is FunctionInvokeDescriptor -> return evaluateFunctionInvoke (tmpVariableName, descriptor, args)
is IrBuiltinOperatorDescriptorBase -> return evaluateOperatorCall (tmpVariableName, callee, args)
is ClassConstructorDescriptor -> return evaluateConstructorCall (tmpVariableName, callee, args)
else -> return evaluateSimpleFunctionCall(tmpVariableName, descriptor, args)
@@ -1560,6 +1573,35 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
//-------------------------------------------------------------------------//
private val functionImplUnboundRefGetter by lazy {
context.builtIns.getKonanInternalClass("FunctionImpl")
.unsubstitutedMemberScope.getContributedDescriptors()
.filterIsInstance<PropertyDescriptor>()
.single { it.name.asString() == "unboundRef" }
.getter!!
}
private fun evaluateFunctionInvoke(tmpVariableName: String,
descriptor: FunctionInvokeDescriptor,
args: List<LLVMValueRef>): LLVMValueRef {
// Note: the whole function code below is written in the assumption that
// `invoke` method receiver is passed as first argument.
val functionImpl = args[0]
val unboundRefType = codegen.getLlvmFunctionType(descriptor)
val unboundRef = evaluateSimpleFunctionCall(codegen.newVar(),
functionImplUnboundRefGetter, listOf(functionImpl))
val entryPtr = codegen.bitcast(pointerType(unboundRefType), unboundRef, "entry")
return call(descriptor, entryPtr, args, tmpVariableName)
}
//-------------------------------------------------------------------------//
private fun evaluateSimpleFunctionCall(tmpVariableName: String, descriptor: FunctionDescriptor, args: List<LLVMValueRef>): LLVMValueRef {
//logger.log("evaluateSimpleFunctionCall : $tmpVariableName = ${ir2string(value)}")
if (descriptor.isOverridable)