[K/N][codegen] Reworked fields building
This commit is contained in:
+1
@@ -34,4 +34,5 @@ object KonanFqNames {
|
||||
val hasFreezeHook = FqName("kotlin.native.internal.HasFreezeHook")
|
||||
val gcUnsafeCall = FqName("kotlin.native.internal.GCUnsafeCall")
|
||||
val eagerInitialization = FqName("kotlin.native.EagerInitialization")
|
||||
val noReorderFields = FqName("kotlin.native.internal.NoReorderFields")
|
||||
}
|
||||
|
||||
+30
-15
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.backend.common.ir.simpleFunctions
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.computeFunctionName
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.llvmType
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.getLLVMType
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.localHash
|
||||
import org.jetbrains.kotlin.backend.konan.lower.InnerClassLowering
|
||||
import org.jetbrains.kotlin.backend.konan.lower.bridgeTarget
|
||||
@@ -18,11 +18,12 @@ import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrClassReference
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
internal class OverriddenFunctionInfo(
|
||||
val function: IrSimpleFunction,
|
||||
@@ -392,15 +393,30 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context, va
|
||||
return context.getLayoutBuilder(superFunction.parentAsClass).itablePlace(superFunction)
|
||||
}
|
||||
|
||||
class FieldInfo(val name: String, val type: IrType, val isConst: Boolean, val hasConstInitializer: Boolean, val irField: IrField?) {
|
||||
var index = -1
|
||||
}
|
||||
|
||||
/**
|
||||
* All fields of the class instance.
|
||||
* The order respects the class hierarchy, i.e. a class [fields] contains superclass [fields] as a prefix.
|
||||
*/
|
||||
val fields: List<IrField> by lazy {
|
||||
val superClass = irClass.getSuperClassNotAny() // TODO: what if Any has fields?
|
||||
val fields: List<FieldInfo> by lazy {
|
||||
val superClass = irClass.getSuperClassNotAny()
|
||||
val superFields = if (superClass != null) context.getLayoutBuilder(superClass).fields else emptyList()
|
||||
|
||||
superFields + getDeclaredFields()
|
||||
val declaredFields = getDeclaredFields()
|
||||
val sortedDeclaredFields = if (irClass.hasAnnotation(KonanFqNames.noReorderFields))
|
||||
declaredFields
|
||||
else
|
||||
declaredFields.sortedByDescending {
|
||||
with(context.llvm) { LLVMStoreSizeOfType(runtime.targetData, getLLVMType(it.type)) }
|
||||
}
|
||||
|
||||
val superFieldsCount = 1 /* First field is ObjHeader */ + superFields.size
|
||||
sortedDeclaredFields.forEachIndexed { index, field -> field.index = superFieldsCount + index }
|
||||
|
||||
superFields + sortedDeclaredFields
|
||||
}
|
||||
|
||||
val associatedObjects by lazy {
|
||||
@@ -441,10 +457,15 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context, va
|
||||
|
||||
lateinit var hierarchyInfo: ClassGlobalHierarchyInfo
|
||||
|
||||
private fun IrField.toFieldInfo() =
|
||||
FieldInfo(name.asString(), type,
|
||||
correspondingPropertySymbol?.owner?.isConst ?: false,
|
||||
initializer?.expression is IrConst<*>, this)
|
||||
|
||||
/**
|
||||
* Fields declared in the class.
|
||||
*/
|
||||
private fun getDeclaredFields(): List<IrField> {
|
||||
fun getDeclaredFields(): List<FieldInfo> {
|
||||
val declarations: List<IrDeclaration> = if (irClass.isInner && !isLowered) {
|
||||
// Note: copying to avoid mutation of the original class.
|
||||
irClass.declarations.toMutableList()
|
||||
@@ -452,19 +473,13 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context, va
|
||||
} else {
|
||||
irClass.declarations
|
||||
}
|
||||
|
||||
val fields = declarations.mapNotNull {
|
||||
return declarations.mapNotNull {
|
||||
when (it) {
|
||||
is IrField -> it.takeIf { it.isReal }
|
||||
is IrProperty -> it.takeIf { it.isReal }?.backingField
|
||||
is IrField -> it.takeIf { it.isReal }?.toFieldInfo()
|
||||
is IrProperty -> it.takeIf { it.isReal }?.backingField?.toFieldInfo()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
if (irClass.hasAnnotation(FqName.fromSegments(listOf("kotlin", "native", "internal", "NoReorderFields"))))
|
||||
return fields
|
||||
|
||||
return fields.sortedByDescending{ LLVMStoreSizeOfType(context.llvm.runtime.targetData, it.type.llvmType(context)) }
|
||||
}
|
||||
|
||||
private val IrClass.overridableOrOverridingMethods: List<IrSimpleFunction>
|
||||
|
||||
+2
-2
@@ -43,7 +43,7 @@ internal fun IrClass.hasConstStateAndNoSideEffects(context: Context): Boolean {
|
||||
if (!context.shouldOptimize()) return false
|
||||
if (this.hasAnnotation(KonanFqNames.canBePrecreated)) return true
|
||||
val fields = context.getLayoutBuilder(this).fields
|
||||
return fields.all { (it.correspondingPropertySymbol?.owner?.isConst ?: false) && (it.initializer?.expression is IrConst<*>) } &&
|
||||
return fields.all { it.isConst && it.hasConstInitializer } &&
|
||||
this.constructors.all { it.isAutogeneratedSimpleConstructor(context) }
|
||||
}
|
||||
|
||||
@@ -367,7 +367,7 @@ internal class StackLocalsManagerImpl(
|
||||
} else {
|
||||
val type = context.llvmDeclarations.forClass(stackLocal.irClass).bodyType
|
||||
for (field in context.getLayoutBuilder(stackLocal.irClass).fields) {
|
||||
val fieldIndex = context.llvmDeclarations.forField(field).index
|
||||
val fieldIndex = field.index
|
||||
val fieldType = LLVMStructGetTypeAtIndex(type, fieldIndex)!!
|
||||
|
||||
if (isObjectType(fieldType)) {
|
||||
|
||||
+2
-2
@@ -254,7 +254,7 @@ internal class InitializersGenerationState {
|
||||
&& moduleGlobalInitializers.isEmpty() && moduleThreadLocalInitializers.isEmpty()
|
||||
}
|
||||
|
||||
internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
||||
internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) : RuntimeAware {
|
||||
|
||||
private fun importFunction(name: String, otherModule: LLVMModuleRef): LLVMValueRef {
|
||||
if (LLVMGetNamedFunction(llvmModule, name) != null) {
|
||||
@@ -462,7 +462,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
||||
private val target = context.config.target
|
||||
|
||||
val runtimeFile = context.config.distribution.runtime(target)
|
||||
val runtime = Runtime(runtimeFile) // TODO: dispose
|
||||
override val runtime = Runtime(runtimeFile) // TODO: dispose
|
||||
|
||||
val targetTriple = runtime.target
|
||||
|
||||
|
||||
+1
-1
@@ -924,7 +924,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
private fun computeFields(declaration: IrClass): Array<ConstValue> {
|
||||
val fields = context.getLayoutBuilder(declaration).fields
|
||||
return Array(fields.size) { index ->
|
||||
val initializer = fields[index].initializer!!.expression as IrConst<*>
|
||||
val initializer = fields[index].irField!!.initializer!!.expression as IrConst<*>
|
||||
constValue(evaluateConst(initializer))
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -76,7 +76,7 @@ internal class StaticFieldLlvmDeclarations(val storageAddressAccess: AddressAcce
|
||||
|
||||
internal class UniqueLlvmDeclarations(val pointer: ConstPointer)
|
||||
|
||||
private fun ContextUtils.createClassBodyType(name: String, fields: List<IrField>): LLVMTypeRef {
|
||||
private fun ContextUtils.createClassBodyType(name: String, fields: List<ClassLayoutBuilder.FieldInfo>): LLVMTypeRef {
|
||||
val fieldTypes = listOf(runtime.objHeaderType) + fields.map { getLLVMType(it.type) }
|
||||
// TODO: consider adding synthetic ObjHeader field to Any.
|
||||
|
||||
@@ -307,11 +307,12 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
val classDeclarations = (containingClass.metadata as? CodegenClassMetadata)?.llvm
|
||||
?: error(containingClass.descriptor.toString())
|
||||
val allFields = context.getLayoutBuilder(containingClass).fields
|
||||
val fieldInfo = allFields.firstOrNull { it.irField == declaration } ?: error("Field ${declaration.render()} is not found")
|
||||
declaration.metadata = CodegenInstanceFieldMetadata(
|
||||
declaration.metadata?.name,
|
||||
containingClass.konanLibrary,
|
||||
FieldLlvmDeclarations(
|
||||
allFields.indexOf(declaration) + 1, // First field is ObjHeader.
|
||||
fieldInfo.index,
|
||||
classDeclarations.bodyType
|
||||
)
|
||||
)
|
||||
|
||||
+5
-5
@@ -426,12 +426,12 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
NullPointer(int32Type), NullPointer(int8Type), NullPointer(kInt8Ptr),
|
||||
debugOperationsSize, debugOperations)
|
||||
} else {
|
||||
data class FieldRecord(val offset: Int, val type: Int, val name: String)
|
||||
val fields = getStructElements(bodyType).drop(1).mapIndexed { index, type ->
|
||||
class FieldRecord(val offset: Int, val type: Int, val name: String)
|
||||
val fields = context.getLayoutBuilder(irClass).fields.map {
|
||||
FieldRecord(
|
||||
LLVMOffsetOfElement(llvmTargetData, bodyType, index + 1).toInt(),
|
||||
mapRuntimeType(type),
|
||||
context.getLayoutBuilder(irClass).fields[index].name.asString())
|
||||
LLVMOffsetOfElement(llvmTargetData, bodyType, it.index).toInt(),
|
||||
mapRuntimeType(LLVMStructGetTypeAtIndex(bodyType, it.index)!!),
|
||||
it.name)
|
||||
}
|
||||
val offsetsPtr = staticData.placeGlobalConstArray("kextoff:$className", int32Type,
|
||||
fields.map { Int32(it.offset) })
|
||||
|
||||
+1
-5
@@ -92,11 +92,7 @@ internal fun StaticData.createConstArrayList(array: ConstPointer, length: Int):
|
||||
|
||||
// Now sort these values according to the order of fields returned by getFields()
|
||||
// to match the sorting order of the real ArrayList().
|
||||
val sorted = mutableListOf<ConstValue>()
|
||||
context.getLayoutBuilder(arrayListClass).fields.forEach {
|
||||
require (it.parent == arrayListClass)
|
||||
sorted.add(arrayListFields[it.name.asString()]!!)
|
||||
}
|
||||
val sorted = context.getLayoutBuilder(arrayListClass).fields.map { arrayListFields[it.name]!! }
|
||||
|
||||
return createConstKotlinObject(arrayListClass, *sorted.toTypedArray())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user