Review feedback, part 1

This commit is contained in:
Svyatoslav Scherbina
2016-12-13 12:32:06 +07:00
committed by SvyatoslavScherbina
parent 4dec392880
commit 7d4074a1a4
5 changed files with 61 additions and 32 deletions
@@ -1588,13 +1588,19 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
// 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 functionImpl = args[0] // Instance of `konan.internal.FunctionImpl`.
// `functionImpl.unboundRef` is the pointer to (static) function of type
// `(FunctionImpl, Arg_1, ..., Arg_n): Ret`. See [CallableReferenceLowering] for details.
// LLVM type for such function is equal to type for `FunctionImpl.invoke(Arg_1, ..., Arg_n): Ret`.
// So we can use the latter for simplicity:
val unboundRefType = codegen.getLlvmFunctionType(descriptor)
// Get `functionImpl.unboundRef`:
val unboundRef = evaluateSimpleFunctionCall(codegen.newVar(),
functionImplUnboundRefGetter, listOf(functionImpl))
// Cast `functionImpl.unboundRef` to pointer to function:
val entryPtr = codegen.bitcast(pointerType(unboundRefType), unboundRef, "entry")
return call(descriptor, entryPtr, args, tmpVariableName)
@@ -25,10 +25,13 @@ import org.jetbrains.kotlin.utils.addToStdlib.singletonList
* This lowering pass lowers all [IrCallableReference]s to unbound ones.
*/
internal class CallableReferenceLowering(val context: KonanBackendContext) : DeclarationContainerLoweringPass {
var callableReferenceCount = 0
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
irDeclarationContainer.declarations.transformFlat { memberDeclaration ->
if (memberDeclaration is IrFunction)
lowerCallableReferences(context, memberDeclaration)
lowerCallableReferences(this, memberDeclaration)
else
null
}
@@ -39,31 +42,43 @@ internal class CallableReferenceLowering(val context: KonanBackendContext) : Dec
* Replaces all callable references in the function body to unbound ones.
* Returns the list of this function and all created ones.
*/
private fun lowerCallableReferences(context: KonanBackendContext, function: IrFunction): List<IrFunction> {
val transformer = CallableReferencesUnbinder(context, function)
private fun lowerCallableReferences(lower: CallableReferenceLowering, function: IrFunction): List<IrFunction> {
val transformer = CallableReferencesUnbinder(lower, function)
function.transformChildrenVoid(transformer)
return function.singletonList() + transformer.createdFunctions
}
private object DECLARATION_ORIGIN_FUNCTION_FOR_CALLABLE_REFERENCE :
IrDeclarationOriginImpl("FUNCTION_FOR_CALLABLE_REFERENCE")
/**
* Replaces all callable references in the function body to unbound ones.
* Adds all created functions to [createdFunctions].
*/
private class CallableReferencesUnbinder(val context: KonanBackendContext,
private class CallableReferencesUnbinder(val lower: CallableReferenceLowering,
val function: IrFunction) : IrElementTransformerVoid() {
val createdFunctions = mutableListOf<IrFunction>()
private val builtIns = lower.context.builtIns
override fun visitElement(element: IrElement): IrElement {
return super.visitElement(element)
}
private val unboundCallableReferenceType by lazy {
context.builtIns.getKonanInternalClass("UnboundCallableReference").defaultType
builtIns.getKonanInternalClass("UnboundCallableReference").defaultType
}
private val simpleFunctionImplClass by lazy {
context.builtIns.getKonanInternalClass("SimpleFunctionImpl")
builtIns.getKonanInternalClass("SimpleFunctionImpl")
}
private val simpleFunctionImplBoundArgsGetter by lazy {
simpleFunctionImplClass.defaultType.memberScope.getContributedDescriptors()
.filterIsInstance<PropertyDescriptor>()
.single { it.name.asString() == "boundArgs" }
.getter!!
}
override fun visitCallableReference(expression: IrCallableReference): IrExpression {
@@ -77,8 +92,8 @@ private class CallableReferencesUnbinder(val context: KonanBackendContext,
val startOffset = expression.startOffset
val endOffset = expression.endOffset
// The code below creates a call to `SimpleFunctionImpl` constructor which creates the value to be used
// as required callable reference.
// The code below creates a call to `SimpleFunctionImpl` constructor which creates the object implementing
// the function type.
// Create the function to be used as `unboundRef` of `SimpleFunctionImpl`:
val newFunction = createSimpleFunctionImplTarget(descriptor, unboundParams, boundParams, startOffset, endOffset)
@@ -119,20 +134,13 @@ private class CallableReferencesUnbinder(val context: KonanBackendContext,
// Create new function declaration:
val origin = object : IrDeclarationOriginImpl("FUNCTION_FOR_CALLABLE_REFERENCE") {}
val simpleFunctionImplBoundArgsGetter =
simpleFunctionImplClass.defaultType.memberScope.getContributedDescriptors()
.filterIsInstance<PropertyDescriptor>().filter { it.name.asString() == "boundArgs" }
.single().getter!!
val boundArgsArray = IrCallImpl(startOffset, endOffset, simpleFunctionImplBoundArgsGetter, null).apply {
dispatchReceiver = IrGetValueImpl(startOffset, endOffset, newDescriptor.valueParameters[0])
}
// TODO: do not call boundArgs getter for each bound argument.
val arrayGet = boundArgsArray.type.memberScope.getContributedDescriptors()
.filterIsInstance<FunctionDescriptor>().filter { it.name.asString() == "get" }.single()
.filterIsInstance<FunctionDescriptor>().single { it.name.asString() == "get" }
// TODO: some handling for type parameters is probably required here.
@@ -150,14 +158,14 @@ private class CallableReferencesUnbinder(val context: KonanBackendContext,
call.addArguments(boundParams.mapIndexed { index, param ->
param to IrCallImpl(startOffset, endOffset, arrayGet).apply {
dispatchReceiver = boundArgsArray
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, index))
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, builtIns.intType, index))
}
})
val ret = IrReturnImpl(startOffset, endOffset, newDescriptor, call)
val newFunction = IrFunctionImpl(
startOffset, endOffset, origin,
startOffset, endOffset, DECLARATION_ORIGIN_FUNCTION_FOR_CALLABLE_REFERENCE,
newDescriptor,
IrBlockBodyImpl(startOffset, endOffset, listOf(ret))
)
@@ -171,7 +179,7 @@ private class CallableReferencesUnbinder(val context: KonanBackendContext,
private fun createSimpleFunctionImplTargetDescriptor(descriptor: CallableDescriptor,
unboundParams: List<ParameterDescriptor>): FunctionDescriptor {
val newName = Name.identifier(descriptor.hashCode().toString()) // FIXME
val newName = Name.identifier("${descriptor.name}\$bound-${lower.callableReferenceCount++}")
val newDescriptor = SimpleFunctionDescriptorImpl.create(
function.descriptor.containingDeclaration, Annotations.EMPTY,
@@ -179,19 +187,34 @@ private class CallableReferencesUnbinder(val context: KonanBackendContext,
val simpleFunctionImplType = simpleFunctionImplClass.defaultType
// Maps each unbound param of original function to parameter of new function
// Map each unbound param of original function to parameter of new function.
val newUnboundParams = unboundParams.mapIndexed { index, param ->
ValueParameterDescriptorImpl(newDescriptor, null, index + 1,
Annotations.EMPTY, param.name, param.type,
false, false, false, false,
(param as? ValueParameterDescriptor)?.varargElementType,
SourceElement.NO_SOURCE)
ValueParameterDescriptorImpl(
containingDeclaration = newDescriptor,
original = null,
index = index + 1,
annotations = Annotations.EMPTY,
name = param.name,
outType = param.type,
declaresDefaultValue = false,
isCrossinline = false, isNoinline = false,
isCoroutine = false,
varargElementType = (param as? ValueParameterDescriptor)?.varargElementType,
source = SourceElement.NO_SOURCE)
}
// `<func>: SimpleFunctionImpl`
val functionParameter = ValueParameterDescriptorImpl(newDescriptor, null, 0, Annotations.EMPTY,
Name.special("<func>"),
simpleFunctionImplType, false, false, false, false, null, SourceElement.NO_SOURCE)
val functionParameter = ValueParameterDescriptorImpl(
containingDeclaration = newDescriptor,
original = null,
index = 0,
annotations = Annotations.EMPTY,
name = Name.special("<func>"),
outType = simpleFunctionImplType,
declaresDefaultValue = false,
isCrossinline = false, isNoinline = false,
isCoroutine = false, varargElementType = null,
source = SourceElement.NO_SOURCE)
val newValueParameters = listOf(functionParameter) + newUnboundParams
+1 -1
View File
@@ -185,7 +185,7 @@ KConstRef Kotlin_getCurrentStackTrace() {
}
// TODO: consider handling it with compiler magic instead.
KRef Kotlin_internal_undefined() {
KRef Kotlin_konan_internal_undefined() {
return nullptr;
}
+1 -1
View File
@@ -100,7 +100,7 @@ KString Kotlin_String_subSequence(KString thiz, KInt startIndex, KInt endIndex);
KConstRef Kotlin_getCurrentStackTrace();
KRef Kotlin_internal_undefined();
KRef Kotlin_konan_internal_undefined();
#ifdef __cplusplus
}
@@ -4,5 +4,5 @@ package konan.internal
* Returns undefined value of type `T`.
* This method is unsafe and should be used with care.
*/
@SymbolName("Kotlin_internal_undefined")
@SymbolName("Kotlin_konan_internal_undefined")
internal external fun <T> undefined(): T