Skip to content

Commit 65e41bb

Browse files
committed
Implement header compilation by eliding method bodies in LightTree -> FIR
1 parent 45981b7 commit 65e41bb

File tree

2 files changed

+75
-7
lines changed

2 files changed

+75
-7
lines changed

compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
5353
import org.jetbrains.kotlin.lexer.KtTokens.*
5454
import org.jetbrains.kotlin.name.*
5555
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
56+
import org.jetbrains.kotlin.types.ConstantValueKind
5657
import org.jetbrains.kotlin.util.getChildren
5758
import org.jetbrains.kotlin.utils.addToStdlib.runIf
5859
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
@@ -96,7 +97,12 @@ class LightTreeRawFirDeclarationBuilder(
9697
}
9798
IMPORT_LIST -> importList += convertImportDirectives(child)
9899
CLASS -> firDeclarationList += convertClass(child)
99-
FUN -> firDeclarationList += convertFunctionDeclaration(child) as FirDeclaration
100+
FUN -> {
101+
val functionDeclaration = convertFunctionDeclaration(child)
102+
if (functionDeclaration != null) {
103+
firDeclarationList += functionDeclaration as FirDeclaration
104+
}
105+
}
100106
KtNodeTypes.PROPERTY -> firDeclarationList += convertPropertyDeclaration(child)
101107
TYPEALIAS -> firDeclarationList += convertTypeAlias(child)
102108
OBJECT_DECLARATION -> firDeclarationList += convertClass(child)
@@ -142,7 +148,12 @@ class LightTreeRawFirDeclarationBuilder(
142148
val firStatements = block.forEachChildrenReturnList { node, container ->
143149
when (node.tokenType) {
144150
CLASS, OBJECT_DECLARATION -> container += convertClass(node) as FirStatement
145-
FUN -> container += convertFunctionDeclaration(node)
151+
FUN -> {
152+
val functionDeclaration = convertFunctionDeclaration(node)
153+
if (functionDeclaration != null) {
154+
container += functionDeclaration
155+
}
156+
}
146157
KtNodeTypes.PROPERTY -> container += convertPropertyDeclaration(node) as FirStatement
147158
DESTRUCTURING_DECLARATION -> container +=
148159
convertDestructingDeclaration(node).toFirDestructingDeclaration(this, baseModuleData)
@@ -938,7 +949,11 @@ class LightTreeRawFirDeclarationBuilder(
938949
when (node.tokenType) {
939950
ENUM_ENTRY -> container += convertEnumEntry(node, classWrapper!!)
940951
CLASS -> container += convertClass(node)
941-
FUN -> container += convertFunctionDeclaration(node) as FirDeclaration
952+
FUN -> {
953+
val functionDeclaration = convertFunctionDeclaration(node)
954+
if (functionDeclaration != null)
955+
container += functionDeclaration as FirDeclaration
956+
}
942957
KtNodeTypes.PROPERTY -> container += convertPropertyDeclaration(node, classWrapper)
943958
TYPEALIAS -> container += convertTypeAlias(node)
944959
OBJECT_DECLARATION -> container += convertClass(node)
@@ -1238,6 +1253,7 @@ class LightTreeRawFirDeclarationBuilder(
12381253
modifiers?.convertAnnotationsTo(annotations)
12391254
typeParameters += constructorTypeParametersFromConstructedClass(classWrapper.classBuilder.typeParameters)
12401255
valueParameters += firValueParameters.map { it.firValueParameter }
1256+
// TODO-HEADER-COMPILATION: Potentially remove this and produce an empty constructor body.
12411257
val (body, contractDescription) = withForcedLocalContext {
12421258
convertFunctionBody(block, null, allowLegacyContractDescription = true)
12431259
}
@@ -1759,6 +1775,10 @@ class LightTreeRawFirDeclarationBuilder(
17591775
valueParameters += firValueParameters
17601776
}
17611777
val allowLegacyContractDescription = outerContractDescription == null
1778+
// TODO-HEADER-COMPILATION: Potentially remove getter/setter code.
1779+
// (headerCompilationMode) {
1780+
// buildEmptyExpressionBlock() to null
1781+
// }
17621782
val bodyWithContractDescription = withForcedLocalContext {
17631783
convertFunctionBody(block, expression, allowLegacyContractDescription)
17641784
}
@@ -1922,7 +1942,7 @@ class LightTreeRawFirDeclarationBuilder(
19221942
/**
19231943
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseFunction
19241944
*/
1925-
fun convertFunctionDeclaration(functionDeclaration: LighterASTNode): FirStatement {
1945+
fun convertFunctionDeclaration(functionDeclaration: LighterASTNode): FirStatement? {
19261946
var modifiers: ModifierList? = null
19271947
var identifier: String? = null
19281948
var valueParametersList: LighterASTNode? = null
@@ -1976,8 +1996,23 @@ class LightTreeRawFirDeclarationBuilder(
19761996
else implicitType
19771997
}
19781998

1999+
// TODO-HEADER-COMPILE: While it's a good idea to try to avoid
2000+
// producing private functions, this breaks when the function is
2001+
// decorated with @JvmStatic since it makes it visible to Java
2002+
// programs and causes symbol not found errors.
2003+
// Fix would be to check if the annotation is there and then skip.
2004+
/*
2005+
if (headerCompilationMode) {
2006+
if (calculatedModifiers.getVisibility() == Visibilities.Private) {
2007+
return null
2008+
}
2009+
}
2010+
*/
2011+
19792012
val receiverTypeCalculator = receiverTypeNode?.let { { convertType(it) } }
19802013
val functionBuilder = if (isAnonymousFunction) {
2014+
if (headerCompilationMode)
2015+
return null
19812016
FirAnonymousFunctionBuilder().apply {
19822017
source = functionSource
19832018
receiverParameter = receiverTypeCalculator?.let { createReceiverParameter(it, baseModuleData, functionSymbol) }
@@ -2064,8 +2099,41 @@ class LightTreeRawFirDeclarationBuilder(
20642099
}
20652100

20662101
val allowLegacyContractDescription = outerContractDescription == null
2067-
val bodyWithContractDescription = withForcedLocalContext {
2068-
convertFunctionBody(block, expression, allowLegacyContractDescription)
2102+
2103+
// TODO: HEADER-COMPILATION
2104+
// replacing method bodies with `return null!!` doesn't seem to be ideal since it's producing a rather
2105+
// long bytecode sequence:
2106+
// Code:
2107+
// 0: aconst_null
2108+
// 1: dup
2109+
// 2: invokestatic #18 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
2110+
// 5: pop
2111+
// 6: new #26 // class kotlin/KotlinNothingValueException
2112+
// 9: dup
2113+
// 10: invokespecial #27 // Method kotlin/KotlinNothingValueException."<init>":()V
2114+
// 13: athrow
2115+
//
2116+
// Consider unconditionally throwing an exception instead.
2117+
fun buildReturnNullExclExclBlock() = (
2118+
FirSingleExpressionBlock(
2119+
buildReturnExpression {
2120+
this.target = target
2121+
result = buildCheckNotNullCall {
2122+
argumentList = buildUnaryArgumentList(
2123+
buildLiteralExpression(null, ConstantValueKind.Null, null, setType = true)
2124+
)
2125+
}
2126+
}
2127+
) to null)
2128+
2129+
// Block is null when you have an interface or abstract function declaration.
2130+
// In such cases, for header compile mode you shall not generate any code either.
2131+
val bodyWithContractDescription = if (headerCompilationMode && block != null) {
2132+
buildReturnNullExclExclBlock()
2133+
} else {
2134+
withForcedLocalContext {
2135+
convertFunctionBody(block, expression, allowLegacyContractDescription)
2136+
}
20692137
}
20702138
this.body = bodyWithContractDescription.first
20712139
val contractDescription = outerContractDescription ?: bodyWithContractDescription.second

compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class LightTreeRawFirExpressionBuilder(
129129
}
130130

131131
/***** EXPRESSIONS *****/
132-
fun convertExpression(expression: LighterASTNode, errorReason: String): FirElement {
132+
fun convertExpression(expression: LighterASTNode, errorReason: String): FirElement? {
133133
return when (expression.tokenType) {
134134
LAMBDA_EXPRESSION -> convertLambdaExpression(expression)
135135
BINARY_EXPRESSION -> convertBinaryExpression(expression)

0 commit comments

Comments
 (0)