diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt index 5e8cb735e70..9761318106d 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt @@ -53,6 +53,114 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va codeBuilder.addUnconditionalJump(nextIterationLabel ?: return) } + fun evaluateExpression(expr: PsiElement?, scopeDepth: Int): LLVMSingleValue? = + when (expr) { + is KtBlockExpression -> { + expressionWalker(expr.lBrace, breakLabel = null, scopeDepth = scopeDepth + 1) + null + } + is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth) + is KtPostfixExpression -> evaluatePostfixExpression(expr, scopeDepth) + is KtPrefixExpression -> evaluatePrefixExpression(expr, scopeDepth) + is KtConstantExpression -> evaluateConstantExpression(expr) + is KtCallExpression -> evaluateCallExpression(expr, scopeDepth) + is KtWhenExpression -> evaluateWhenExpression(expr, scopeDepth) + is KtCallableReferenceExpression -> evaluateCallableReferenceExpression(expr) + is KtDotQualifiedExpression -> evaluateDotExpression(expr, scopeDepth) + is KtReferenceExpression -> evaluateReferenceExpression(expr, scopeDepth) + is KtIfExpression -> evaluateIfOperator(expr, scopeDepth + 1) + is KtStringTemplateExpression -> evaluateStringTemplateExpression(expr) + is KtReturnExpression -> evaluateReturnInstruction(expr.firstChild, scopeDepth) + is KtThisExpression -> evaluateThisExpression() + is KtSafeQualifiedExpression -> evaluateSafeAccessExpression(expr, scopeDepth) + is KtParenthesizedExpression -> evaluateExpression(expr.expression, scopeDepth) + null, + is PsiWhiteSpace -> null + is PsiElement -> evaluatePsiElement(expr, scopeDepth) + else -> throw UnsupportedOperationException() + } + + fun evaluateConstructorDelegationReferenceExpression(expr: KtConstructorDelegationReferenceExpression, structCodegen: StructCodegen, constructorArguments: List, scopeDepth: Int): LLVMSingleValue? { + val targetCall = state.bindingContext.get(BindingContext.CALL, expr) + val names = parseValueArguments(targetCall!!.valueArguments, scopeDepth) + val args = codeBuilder.loadArgsIfRequired(names, constructorArguments) + return evaluateConstructorCallExpression(LLVMVariable(structCodegen.structName + LLVMType.mangleFunctionArguments(names), structCodegen.type, scope = LLVMVariableScope()), args) + } + + fun evaluateMemberMethodOrField(receiver: LLVMVariable, selectorName: String, scopeDepth: Int, call: PsiElement? = null): LLVMSingleValue? { + val type = receiver.type as LLVMReferenceType + val clazz = resolveClassOrObjectLocation(type) ?: throw UnexpectedException(type.toString() + receiver.toString()) + val field = clazz.fieldsIndex[selectorName] + + if (field != null) { + return evaluateClassField(receiver, field) + } else { + return evaluateMemberMethod(receiver, clazz, scopeDepth, call as? KtCallExpression ?: throw UnexpectedException("$receiver:$selectorName")) + } + } + + fun addPrimitiveBinaryOperation(operator: IElementType, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue, referenceName: KtSimpleNameExpression? = null): LLVMVariable { + val firstNativeOp = codeBuilder.receiveNativeValue(firstOp) + val secondNativeOp = codeBuilder.receiveNativeValue(secondOp) + + val llvmExpression = when (operator) { + KtTokens.PLUS -> firstOp.type.operatorPlus(firstNativeOp, secondNativeOp) + KtTokens.MINUS -> firstOp.type.operatorMinus(firstNativeOp, secondNativeOp) + KtTokens.MUL -> firstOp.type.operatorTimes(firstNativeOp, secondNativeOp) + KtTokens.DIV -> firstOp.type.operatorDiv(firstNativeOp, secondNativeOp) + KtTokens.LT -> firstOp.type.operatorLt(firstNativeOp, secondNativeOp) + KtTokens.GT -> firstOp.type.operatorGt(firstNativeOp, secondNativeOp) + KtTokens.LTEQ -> firstOp.type.operatorLeq(firstNativeOp, secondNativeOp) + KtTokens.GTEQ -> firstOp.type.operatorGeq(firstNativeOp, secondNativeOp) + KtTokens.EQEQ -> + if (LLVMType.isReferredType(firstOp.type) && LLVMType.isReferredType(secondOp.type)) { + val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1) + val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1) + firstOp.type.operatorEq(firstPointedArgument, secondPointedArgument) + } else + firstOp.type.operatorEq(firstNativeOp, secondNativeOp) + KtTokens.EQEQEQ -> { + val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1) + val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1) + firstOp.type.operatorEq(firstPointedArgument, secondPointedArgument) + } + KtTokens.EXCLEQ -> { + if (LLVMType.isReferredType(firstOp.type) && LLVMType.isReferredType(secondOp.type)) { + val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1) + val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1) + firstOp.type.operatorNeq(firstPointedArgument, secondPointedArgument) + } else + firstOp.type.operatorNeq(firstNativeOp, secondNativeOp) + } + KtTokens.EXCLEQEQEQ -> { + val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1) + val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1) + firstOp.type.operatorNeq(firstPointedArgument, secondPointedArgument) + } + KtTokens.EQ -> { + if (secondOp.type is LLVMNullType) { + codeBuilder.storeNull(firstOp as LLVMVariable) + return firstOp + } + + val result = firstOp as LLVMVariable + val sourceArgument: LLVMSingleValue + if ((firstOp.pointer == 2) && secondOp.type.isPrimitive && (secondOp.pointer == 0)) { + sourceArgument = codeBuilder.getNewVariable(secondOp.type, 1) + codeBuilder.allocStaticVar(sourceArgument, asValue = true) + codeBuilder.storeVariable(sourceArgument, secondOp) + } else { + sourceArgument = if (result.pointer == secondOp.pointer + 1) secondOp else secondNativeOp + } + + codeBuilder.storeVariable(result, sourceArgument) + return result + } + else -> addPrimitiveReferenceOperationByName(referenceName!!.getReferencedName(), firstOp, secondNativeOp) + } + return codeBuilder.storeExpression(llvmExpression) + } + private fun expressionWalker(expr: PsiElement?, breakLabel: LLVMLabel?, scopeDepth: Int) { when (expr) { is KtBlockExpression -> expressionWalker(expr.lBrace, breakLabel, scopeDepth + 1) @@ -81,42 +189,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va private fun evaluateDoWhileExpression(expr: KtDoWhileExpression, scopeDepth: Int) = executeWhileBlock(expr.condition!!, expr.body!!, scopeDepth, checkConditionBeforeExecute = false) - - fun evaluateExpression(expr: PsiElement?, scopeDepth: Int): LLVMSingleValue? { - return when (expr) { - is KtBlockExpression -> { - expressionWalker(expr.lBrace, breakLabel = null, scopeDepth = scopeDepth + 1) - return null - } - is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth) - is KtPostfixExpression -> evaluatePostfixExpression(expr, scopeDepth) - is KtPrefixExpression -> evaluatePrefixExpression(expr, scopeDepth) - is KtConstantExpression -> evaluateConstantExpression(expr) - is KtCallExpression -> evaluateCallExpression(expr, scopeDepth) - is KtWhenExpression -> evaluateWhenExpression(expr, scopeDepth) - is KtCallableReferenceExpression -> evaluateCallableReferenceExpression(expr) - is KtDotQualifiedExpression -> evaluateDotExpression(expr, scopeDepth) - is KtReferenceExpression -> evaluateReferenceExpression(expr, scopeDepth) - is KtIfExpression -> evaluateIfOperator(expr, scopeDepth + 1) - is KtStringTemplateExpression -> evaluateStringTemplateExpression(expr) - is KtReturnExpression -> evaluateReturnInstruction(expr.firstChild, scopeDepth) - is KtThisExpression -> evaluateThisExpression() - is KtSafeQualifiedExpression -> evaluateSafeAccessExpression(expr, scopeDepth) - is KtParenthesizedExpression -> evaluateExpression(expr.expression, scopeDepth) - null, - is PsiWhiteSpace -> null - is PsiElement -> evaluatePsiElement(expr, scopeDepth) - else -> throw UnsupportedOperationException() - } - } - - fun evaluateConstructorDelegationReferenceExpression(expr: KtConstructorDelegationReferenceExpression, structCodegen: StructCodegen, constructorArguments: List, scopeDepth: Int): LLVMSingleValue? { - val targetCall = state.bindingContext.get(BindingContext.CALL, expr) - val names = parseValueArguments(targetCall!!.valueArguments, scopeDepth) - val args = codeBuilder.loadArgsIfRequired(names, constructorArguments) - return evaluateConstructorCallExpression(LLVMVariable(structCodegen.structName + LLVMType.mangleFunctionArguments(names), structCodegen.type, scope = LLVMVariableScope()), args) - } - private fun evaluateThisExpression(): LLVMSingleValue? = variableManager["this"] @@ -263,25 +335,13 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va else -> throw UnsupportedOperationException() } - fun evaluateMemberMethodOrField(receiver: LLVMVariable, selectorName: String, scopeDepth: Int, call: PsiElement? = null): LLVMSingleValue? { - val type = receiver.type as LLVMReferenceType - val clazz = resolveClassOrObjectLocation(type) ?: throw UnexpectedException(type.toString() + receiver.toString()) - val field = clazz.fieldsIndex[selectorName] - - if (field != null) { - return evaluateClassField(receiver, field) - } else { - return evaluateMemberMethod(receiver, clazz, scopeDepth, call as? KtCallExpression ?: throw UnexpectedException("$receiver:$selectorName")) - } - } - - fun evaluateClassField(receiver: LLVMVariable, field: LLVMClassVariable): LLVMVariable { + private fun evaluateClassField(receiver: LLVMVariable, field: LLVMClassVariable): LLVMVariable { val result = codeBuilder.getNewVariable(field.type, pointer = field.pointer + 1) codeBuilder.loadClassField(result, receiver, field.offset) return result } - fun evaluateMemberMethod(receiver: LLVMVariable, clazz: StructCodegen, scopeDepth: Int, call: KtCallExpression): LLVMSingleValue? { + private fun evaluateMemberMethod(receiver: LLVMVariable, clazz: StructCodegen, scopeDepth: Int, call: KtCallExpression): LLVMSingleValue? { val resolvedCall = call.getCall(state.bindingContext)!!.getResolvedCallWithAssert(state.bindingContext) val functionDescriptor = resolvedCall.candidateDescriptor val functionArguments = functionDescriptor.valueParameters.map { it -> it.type }.map { LLVMMapStandardType(it, state) } @@ -329,7 +389,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return if (codegen?.structName == type.type) codegen else codegen?.nestedClasses?.get(type.type) } - fun evaluateArrayAccessExpression(expr: KtArrayAccessExpression, scope: Int): LLVMSingleValue? { + private fun evaluateArrayAccessExpression(expr: KtArrayAccessExpression, scope: Int): LLVMSingleValue? { val arrayNameVariable = evaluateExpression(expr.arrayExpression, scope) as LLVMVariable return when (arrayNameVariable.type) { is LLVMReferenceType -> { @@ -536,10 +596,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va parseValueArguments(expr.getValueArgumentsInParentheses(), scopeDepth) private fun parseValueArguments(args: List, scopeDepth: Int): List = - args.map { parseOneValueArgument(it, scopeDepth) } - - fun parseOneValueArgument(arg: ValueArgument, scopeDepth: Int): LLVMSingleValue = - evaluateExpression(arg.getArgumentExpression(), scopeDepth) as LLVMSingleValue + args.map { evaluateExpression(it.getArgumentExpression(), scopeDepth) as LLVMSingleValue } private fun parseArgumentsWithDefaultValues(args: MutableCollection, defaultValues: List, scopeDepth: Int): List = args.mapIndexed(fun(i: Int, value: ResolvedValueArgument): LLVMSingleValue { @@ -550,7 +607,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } }).toList() - private fun evaluateBinaryExpression(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable? { val operator = expr.operationToken @@ -667,7 +723,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return left } - fun addPrimitiveReferenceOperationByName(operator: String, firstOp: LLVMSingleValue, secondNativeOp: LLVMSingleValue): LLVMExpression { + private fun addPrimitiveReferenceOperationByName(operator: String, firstOp: LLVMSingleValue, secondNativeOp: LLVMSingleValue): LLVMExpression { val firstNativeOp = codeBuilder.receiveNativeValue(firstOp) return when (operator) { @@ -711,68 +767,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } } - fun addPrimitiveBinaryOperation(operator: IElementType, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue, referenceName: KtSimpleNameExpression? = null): LLVMVariable { - val firstNativeOp = codeBuilder.receiveNativeValue(firstOp) - val secondNativeOp = codeBuilder.receiveNativeValue(secondOp) - - val llvmExpression = when (operator) { - KtTokens.PLUS -> firstOp.type.operatorPlus(firstNativeOp, secondNativeOp) - KtTokens.MINUS -> firstOp.type.operatorMinus(firstNativeOp, secondNativeOp) - KtTokens.MUL -> firstOp.type.operatorTimes(firstNativeOp, secondNativeOp) - KtTokens.DIV -> firstOp.type.operatorDiv(firstNativeOp, secondNativeOp) - KtTokens.LT -> firstOp.type.operatorLt(firstNativeOp, secondNativeOp) - KtTokens.GT -> firstOp.type.operatorGt(firstNativeOp, secondNativeOp) - KtTokens.LTEQ -> firstOp.type.operatorLeq(firstNativeOp, secondNativeOp) - KtTokens.GTEQ -> firstOp.type.operatorGeq(firstNativeOp, secondNativeOp) - KtTokens.EQEQ -> - if (LLVMType.isReferredType(firstOp.type) && LLVMType.isReferredType(secondOp.type)) { - val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1) - val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1) - firstOp.type.operatorEq(firstPointedArgument, secondPointedArgument) - } else - firstOp.type.operatorEq(firstNativeOp, secondNativeOp) - KtTokens.EQEQEQ -> { - val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1) - val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1) - firstOp.type.operatorEq(firstPointedArgument, secondPointedArgument) - } - KtTokens.EXCLEQ -> { - if (LLVMType.isReferredType(firstOp.type) && LLVMType.isReferredType(secondOp.type)) { - val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1) - val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1) - firstOp.type.operatorNeq(firstPointedArgument, secondPointedArgument) - } else - firstOp.type.operatorNeq(firstNativeOp, secondNativeOp) - } - KtTokens.EXCLEQEQEQ -> { - val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1) - val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1) - firstOp.type.operatorNeq(firstPointedArgument, secondPointedArgument) - } - KtTokens.EQ -> { - if (secondOp.type is LLVMNullType) { - codeBuilder.storeNull(firstOp as LLVMVariable) - return firstOp - } - - val result = firstOp as LLVMVariable - val sourceArgument: LLVMSingleValue - if ((firstOp.pointer == 2) && secondOp.type.isPrimitive && (secondOp.pointer == 0)) { - sourceArgument = codeBuilder.getNewVariable(secondOp.type, 1) - codeBuilder.allocStaticVar(sourceArgument, asValue = true) - codeBuilder.storeVariable(sourceArgument, secondOp) - } else { - sourceArgument = if (result.pointer == secondOp.pointer + 1) secondOp else secondNativeOp - } - - codeBuilder.storeVariable(result, sourceArgument) - return result - } - else -> addPrimitiveReferenceOperationByName(referenceName!!.getReferencedName(), firstOp, secondNativeOp) - } - return codeBuilder.storeExpression(llvmExpression) - } - private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMConstant { val expressionKotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!! val expressionValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr)?.getValue(expressionKotlinType) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt index a9836e830ec..d7ab4a694cd 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt @@ -36,18 +36,6 @@ class ClassCodegen(state: TranslationState, type.align = TranslationState.POINTER_ALIGN } - private fun indexFields(parameters: MutableList) { - if (annotation) { - return - } - - val currentConstructorFields = parameters.mapIndexed { i, it -> resolveType(it, state.bindingContext.get(BindingContext.TYPE, it.typeReference)!!, fields.size + i) } - fields.addAll(currentConstructorFields) - fieldsIndex.putAll(currentConstructorFields.map { Pair(it.label, it) }) - primaryConstructorIndex = LLVMType.mangleFunctionArguments(currentConstructorFields) - constructorFields.put(primaryConstructorIndex!!, currentConstructorFields) - } - override fun prepareForGenerate() { val parameterList = clazz.getPrimaryConstructorParameterList()?.parameters ?: listOf() indexFields(parameterList) @@ -79,4 +67,16 @@ class ClassCodegen(state: TranslationState, companionObjectCodegen?.generate() } + private fun indexFields(parameters: MutableList) { + if (annotation) { + return + } + + val currentConstructorFields = parameters.mapIndexed { i, it -> resolveType(it, state.bindingContext.get(BindingContext.TYPE, it.typeReference)!!, fields.size + i) } + fields.addAll(currentConstructorFields) + fieldsIndex.putAll(currentConstructorFields.map { Pair(it.label, it) }) + primaryConstructorIndex = LLVMType.mangleFunctionArguments(currentConstructorFields) + constructorFields.put(primaryConstructorIndex!!, currentConstructorFields) + } + } \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt index 6561a3aa776..fbe25455e9c 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt @@ -97,7 +97,6 @@ abstract class StructCodegen(val state: TranslationState, } } - private fun generateEnumFields() { val enumEntries = classOrObject.declarations.filter { it is KtEnumEntry }