backend: String concatenation lowering
This commit is contained in:
+4
@@ -17,6 +17,10 @@ internal class KonanLower(val context: Context) {
|
||||
fun lower(irFile: IrFile) {
|
||||
val phaser = PhaseManager(context)
|
||||
|
||||
// TODO: consider place of the pass.
|
||||
phaser.phase(KonanPhase.LOWER_STRING_CONCAT) {
|
||||
StringConcatenationLowering(context).lower(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_INLINE) {
|
||||
//FunctionInlining(context).inline(irFile)
|
||||
}
|
||||
|
||||
+1
@@ -22,6 +22,7 @@ enum class KonanPhase(val description: String,
|
||||
/* ... ... */ AUTOBOX("Autoboxing of primitive types"),
|
||||
/* ... ... */ LOWER_ENUMS("Enum classes lowering"),
|
||||
/* ... ... */ LOWER_INNER_CLASSES("Inner classes lowering"),
|
||||
/* ... ... */ LOWER_STRING_CONCAT("String concatenation lowering"),
|
||||
/* ... */ BITCODE("LLVM BitCode Generation"),
|
||||
/* ... ... */ RTTI("RTTI Generation"),
|
||||
/* ... ... */ CODEGEN("Code Generation"),
|
||||
|
||||
+1
-1
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.backend.konan.KonanPlatformConfigurator
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.resolve.ImportPath
|
||||
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.PlatformConfigurator
|
||||
@@ -31,7 +32,6 @@ class KonanBuiltIns: KotlinBuiltIns {
|
||||
constructor(storageManager: StorageManager, withModule: Boolean) : this(storageManager) {
|
||||
if (withModule) createBuiltInsModule()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object KonanPlatform : TargetPlatform("Konan") {
|
||||
|
||||
+9
-3
@@ -3,12 +3,18 @@ package org.jetbrains.kotlin.backend.konan.ir
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
inline fun IrBlockBuilder.irLetSequence(
|
||||
inline fun IrBuilderWithScope.irLetSequence(
|
||||
value: IrExpression,
|
||||
nameHint: String? = null,
|
||||
startOffset: Int = this.startOffset,
|
||||
endOffset: Int = this.endOffset,
|
||||
origin: IrStatementOrigin? = null,
|
||||
resultType: KotlinType? = null,
|
||||
body: IrBlockBuilder.(VariableDescriptor) -> Unit
|
||||
): IrExpression = block {
|
||||
): IrExpression = irBlock(startOffset, endOffset, origin, resultType) {
|
||||
val irTemporary = defineTemporary(value, nameHint)
|
||||
this.body(irTemporary)
|
||||
}
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.signature2Descriptor
|
||||
import org.jetbrains.kotlin.backend.konan.ir.irLetSequence
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
|
||||
/**
|
||||
* This lowering pass replaces [IrStringConcatenation]s with StringBuilder appends.
|
||||
*/
|
||||
internal class StringConcatenationLowering(val context: Context) : FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.transformChildrenVoid(StringConcatenationTransformer(this))
|
||||
}
|
||||
}
|
||||
|
||||
private class StringConcatenationTransformer(val lower: StringConcatenationLowering) : IrElementTransformerVoid() {
|
||||
|
||||
private val buildersStack = mutableListOf<IrBuilderWithScope>()
|
||||
private val context = lower.context
|
||||
private val builtIns = context.builtIns
|
||||
|
||||
private val typesWithSpecialAppendFunction =
|
||||
PrimitiveType.values().map { builtIns.getPrimitiveKotlinType(it) } + builtIns.stringType
|
||||
|
||||
private val kotlinTextFqName = FqName.fromSegments(listOf("kotlin", "text"))
|
||||
private val nameToString = Name.identifier("toString")
|
||||
private val nameStringBuilder = Name.identifier("StringBuilder")
|
||||
private val nameAppend = Name.identifier("append")
|
||||
|
||||
private val classStringBuilder = builtIns.builtInsModule.getPackage(kotlinTextFqName).
|
||||
memberScope.getContributedClassifier(nameStringBuilder,
|
||||
NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
||||
|
||||
//TODO: calculate and pass string length to the constructor.
|
||||
private val constructor = classStringBuilder.constructors.firstOrNull {
|
||||
it.valueParameters.size == 0
|
||||
}!!
|
||||
|
||||
private val toStringFunction = classStringBuilder.signature2Descriptor(nameToString)!!
|
||||
private val defaultAppendFunction =
|
||||
classStringBuilder.signature2Descriptor(nameAppend, arrayOf(builtIns.nullableAnyType))!!
|
||||
|
||||
private val appendFunctions: Map<KotlinType, CallableDescriptor?> =
|
||||
typesWithSpecialAppendFunction.map {
|
||||
it to classStringBuilder.signature2Descriptor(nameAppend, arrayOf(it))
|
||||
}.toMap()
|
||||
|
||||
private fun typeToAppendFunction(type : KotlinType) : CallableDescriptor {
|
||||
return appendFunctions[type]?:defaultAppendFunction
|
||||
}
|
||||
|
||||
override fun visitStringConcatenation(expression: IrStringConcatenation): IrExpression {
|
||||
assert(!buildersStack.isEmpty())
|
||||
|
||||
val blockBuilder = buildersStack.last()
|
||||
|
||||
return blockBuilder.irLetSequence(
|
||||
value = blockBuilder.irCall(constructor),
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
resultType = expression.type) { stringBuilderImpl ->
|
||||
expression.arguments.forEach { arg ->
|
||||
val appendFunction = typeToAppendFunction(arg.type)
|
||||
+irCall(appendFunction).apply {
|
||||
dispatchReceiver = irGet(stringBuilderImpl)
|
||||
putValueArgument(0, arg)
|
||||
}
|
||||
}
|
||||
+irCall(toStringFunction).apply {
|
||||
dispatchReceiver = irGet(stringBuilderImpl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitDeclaration(declaration: IrDeclaration): IrStatement {
|
||||
with(declaration) {
|
||||
buildersStack.add(
|
||||
IrBlockBuilder(IrGeneratorContext(context.irBuiltIns), Scope(descriptor), startOffset, endOffset)
|
||||
)
|
||||
transformChildrenVoid(this@StringConcatenationTransformer)
|
||||
buildersStack.removeAt(buildersStack.lastIndex)
|
||||
return this@with
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user