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