Renamed “descriptor” identifiers
This commit is contained in:
committed by
alexander-gorshenev
parent
9565420c7a
commit
27a31167e6
+5
-5
@@ -123,12 +123,12 @@ internal class SpecialDeclarationsFactory(val context: Context) {
|
||||
return ordinals.getOrPut(enumClassDescriptor) { assignOrdinalsToEnumEntries(enumClassDescriptor) }[entryDescriptor]!!
|
||||
}
|
||||
|
||||
fun getBridge(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): IrSimpleFunction {
|
||||
val irFunction = overriddenFunctionDescriptor.descriptor
|
||||
assert(overriddenFunctionDescriptor.needBridge) {
|
||||
"Function ${irFunction.descriptor} is not needed in a bridge to call overridden function ${overriddenFunctionDescriptor.overriddenDescriptor.descriptor}"
|
||||
fun getBridge(overriddenFunction: OverriddenFunctionInfo): IrSimpleFunction {
|
||||
val irFunction = overriddenFunction.function
|
||||
assert(overriddenFunction.needBridge) {
|
||||
"Function ${irFunction.descriptor} is not needed in a bridge to call overridden function ${overriddenFunction.overriddenFunction.descriptor}"
|
||||
}
|
||||
val bridgeDirections = overriddenFunctionDescriptor.bridgeDirections
|
||||
val bridgeDirections = overriddenFunction.bridgeDirections
|
||||
return bridgesDescriptors.getOrPut(irFunction to bridgeDirections) {
|
||||
createBridge(irFunction, bridgeDirections)
|
||||
}
|
||||
|
||||
+50
-52
@@ -16,98 +16,96 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.util.simpleFunctions
|
||||
|
||||
internal class OverriddenFunctionDescriptor(
|
||||
val descriptor: IrSimpleFunction,
|
||||
overriddenDescriptor: IrSimpleFunction
|
||||
internal class OverriddenFunctionInfo(
|
||||
val function: IrSimpleFunction,
|
||||
val overriddenFunction: IrSimpleFunction
|
||||
) {
|
||||
val overriddenDescriptor = overriddenDescriptor.original
|
||||
|
||||
val needBridge: Boolean
|
||||
get() = descriptor.target.needBridgeTo(overriddenDescriptor)
|
||||
get() = function.target.needBridgeTo(overriddenFunction)
|
||||
|
||||
val bridgeDirections: BridgeDirections
|
||||
get() = descriptor.target.bridgeDirectionsTo(overriddenDescriptor)
|
||||
get() = function.target.bridgeDirectionsTo(overriddenFunction)
|
||||
|
||||
val canBeCalledVirtually: Boolean
|
||||
get() {
|
||||
if (overriddenDescriptor.isObjCClassMethod()) {
|
||||
return descriptor.canObjCClassMethodBeCalledVirtually(this.overriddenDescriptor)
|
||||
if (overriddenFunction.isObjCClassMethod()) {
|
||||
return function.canObjCClassMethodBeCalledVirtually(overriddenFunction)
|
||||
}
|
||||
|
||||
return overriddenDescriptor.isOverridable
|
||||
return overriddenFunction.isOverridable
|
||||
}
|
||||
|
||||
val inheritsBridge: Boolean
|
||||
get() = !descriptor.isReal
|
||||
&& descriptor.target.overrides(overriddenDescriptor)
|
||||
&& descriptor.bridgeDirectionsTo(overriddenDescriptor).allNotNeeded()
|
||||
get() = !function.isReal
|
||||
&& function.target.overrides(overriddenFunction)
|
||||
&& function.bridgeDirectionsTo(overriddenFunction).allNotNeeded()
|
||||
|
||||
fun getImplementation(context: Context): IrSimpleFunction? {
|
||||
val target = descriptor.target
|
||||
val target = function.target
|
||||
val implementation = if (!needBridge)
|
||||
target
|
||||
else {
|
||||
val bridgeOwner = if (inheritsBridge) {
|
||||
target // Bridge is inherited from superclass.
|
||||
} else {
|
||||
descriptor
|
||||
function
|
||||
}
|
||||
context.specialDeclarationsFactory.getBridge(OverriddenFunctionDescriptor(bridgeOwner, overriddenDescriptor))
|
||||
context.specialDeclarationsFactory.getBridge(OverriddenFunctionInfo(bridgeOwner, overriddenFunction))
|
||||
}
|
||||
return if (implementation.modality == Modality.ABSTRACT) null else implementation
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "(descriptor=$descriptor, overriddenDescriptor=$overriddenDescriptor)"
|
||||
return "(descriptor=$function, overriddenDescriptor=$overriddenFunction)"
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is OverriddenFunctionDescriptor) return false
|
||||
if (other !is OverriddenFunctionInfo) return false
|
||||
|
||||
if (descriptor != other.descriptor) return false
|
||||
if (overriddenDescriptor != other.overriddenDescriptor) return false
|
||||
if (function != other.function) return false
|
||||
if (overriddenFunction != other.overriddenFunction) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = descriptor.hashCode()
|
||||
result = 31 * result + overriddenDescriptor.hashCode()
|
||||
var result = function.hashCode()
|
||||
result = 31 * result + overriddenFunction.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
internal class ClassVtablesBuilder(val classDescriptor: IrClass, val context: Context) {
|
||||
internal class ClassVtablesBuilder(val irClass: IrClass, val context: Context) {
|
||||
private val DEBUG = 0
|
||||
|
||||
private inline fun DEBUG_OUTPUT(severity: Int, block: () -> Unit) {
|
||||
if (DEBUG > severity) block()
|
||||
}
|
||||
|
||||
val vtableEntries: List<OverriddenFunctionDescriptor> by lazy {
|
||||
val vtableEntries: List<OverriddenFunctionInfo> by lazy {
|
||||
|
||||
assert(!classDescriptor.isInterface)
|
||||
assert(!irClass.isInterface)
|
||||
|
||||
DEBUG_OUTPUT(0) {
|
||||
println()
|
||||
println("BUILDING vTable for ${classDescriptor.descriptor}")
|
||||
println("BUILDING vTable for ${irClass.descriptor}")
|
||||
}
|
||||
|
||||
val superVtableEntries = if (classDescriptor.isSpecialClassWithNoSupertypes()) {
|
||||
val superVtableEntries = if (irClass.isSpecialClassWithNoSupertypes()) {
|
||||
emptyList()
|
||||
} else {
|
||||
val superClass = classDescriptor.getSuperClassNotAny() ?: context.ir.symbols.any.owner
|
||||
val superClass = irClass.getSuperClassNotAny() ?: context.ir.symbols.any.owner
|
||||
context.getVtableBuilder(superClass).vtableEntries
|
||||
}
|
||||
|
||||
val methods = classDescriptor.sortedOverridableOrOverridingMethods
|
||||
val newVtableSlots = mutableListOf<OverriddenFunctionDescriptor>()
|
||||
val methods = irClass.sortedOverridableOrOverridingMethods
|
||||
val newVtableSlots = mutableListOf<OverriddenFunctionInfo>()
|
||||
|
||||
DEBUG_OUTPUT(0) {
|
||||
println()
|
||||
println("SUPER vTable:")
|
||||
superVtableEntries.forEach { println(" ${it.overriddenDescriptor.descriptor} -> ${it.descriptor.descriptor}") }
|
||||
superVtableEntries.forEach { println(" ${it.overriddenFunction.descriptor} -> ${it.function.descriptor}") }
|
||||
|
||||
println()
|
||||
println("METHODS:")
|
||||
@@ -118,57 +116,57 @@ internal class ClassVtablesBuilder(val classDescriptor: IrClass, val context: Co
|
||||
}
|
||||
|
||||
val inheritedVtableSlots = superVtableEntries.map { superMethod ->
|
||||
val overridingMethod = methods.singleOrNull { it.overrides(superMethod.descriptor) }
|
||||
val overridingMethod = methods.singleOrNull { it.overrides(superMethod.function) }
|
||||
if (overridingMethod == null) {
|
||||
|
||||
DEBUG_OUTPUT(0) { println("Taking super ${superMethod.overriddenDescriptor.descriptor} -> ${superMethod.descriptor.descriptor}") }
|
||||
DEBUG_OUTPUT(0) { println("Taking super ${superMethod.overriddenFunction.descriptor} -> ${superMethod.function.descriptor}") }
|
||||
|
||||
superMethod
|
||||
} else {
|
||||
newVtableSlots.add(OverriddenFunctionDescriptor(overridingMethod, superMethod.descriptor))
|
||||
newVtableSlots.add(OverriddenFunctionInfo(overridingMethod, superMethod.function))
|
||||
|
||||
DEBUG_OUTPUT(0) { println("Taking overridden ${superMethod.overriddenDescriptor.descriptor} -> ${overridingMethod.descriptor}") }
|
||||
DEBUG_OUTPUT(0) { println("Taking overridden ${superMethod.overriddenFunction.descriptor} -> ${overridingMethod.descriptor}") }
|
||||
|
||||
OverriddenFunctionDescriptor(overridingMethod, superMethod.overriddenDescriptor)
|
||||
OverriddenFunctionInfo(overridingMethod, superMethod.overriddenFunction)
|
||||
}
|
||||
}
|
||||
|
||||
// Add all possible (descriptor, overriddenDescriptor) edges for now, redundant will be removed later.
|
||||
methods.mapTo(newVtableSlots) { OverriddenFunctionDescriptor(it, it) }
|
||||
methods.mapTo(newVtableSlots) { OverriddenFunctionInfo(it, it) }
|
||||
|
||||
val inheritedVtableSlotsSet = inheritedVtableSlots.map { it.descriptor to it.bridgeDirections }.toSet()
|
||||
val inheritedVtableSlotsSet = inheritedVtableSlots.map { it.function to it.bridgeDirections }.toSet()
|
||||
|
||||
val filteredNewVtableSlots = newVtableSlots
|
||||
.filterNot { inheritedVtableSlotsSet.contains(it.descriptor to it.bridgeDirections) }
|
||||
.distinctBy { it.descriptor to it.bridgeDirections }
|
||||
.filter { it.descriptor.isOverridable }
|
||||
.filterNot { inheritedVtableSlotsSet.contains(it.function to it.bridgeDirections) }
|
||||
.distinctBy { it.function to it.bridgeDirections }
|
||||
.filter { it.function.isOverridable }
|
||||
|
||||
DEBUG_OUTPUT(0) {
|
||||
println()
|
||||
println("INHERITED vTable slots:")
|
||||
inheritedVtableSlots.forEach { println(" ${it.overriddenDescriptor.descriptor} -> ${it.descriptor.descriptor}") }
|
||||
inheritedVtableSlots.forEach { println(" ${it.overriddenFunction.descriptor} -> ${it.function.descriptor}") }
|
||||
|
||||
println()
|
||||
println("MY OWN vTable slots:")
|
||||
filteredNewVtableSlots.forEach { println(" ${it.overriddenDescriptor.descriptor} -> ${it.descriptor.descriptor}") }
|
||||
filteredNewVtableSlots.forEach { println(" ${it.overriddenFunction.descriptor} -> ${it.function.descriptor}") }
|
||||
}
|
||||
|
||||
inheritedVtableSlots + filteredNewVtableSlots.sortedBy { it.overriddenDescriptor.uniqueId }
|
||||
inheritedVtableSlots + filteredNewVtableSlots.sortedBy { it.overriddenFunction.uniqueId }
|
||||
}
|
||||
|
||||
fun vtableIndex(function: IrSimpleFunction): Int {
|
||||
val bridgeDirections = function.target.bridgeDirectionsTo(function.original)
|
||||
val index = vtableEntries.indexOfFirst { it.descriptor == function.original && it.bridgeDirections == bridgeDirections }
|
||||
if (index < 0) throw Error(function.toString() + " not in vtable of " + classDescriptor.toString())
|
||||
val bridgeDirections = function.target.bridgeDirectionsTo(function)
|
||||
val index = vtableEntries.indexOfFirst { it.function == function && it.bridgeDirections == bridgeDirections }
|
||||
if (index < 0) throw Error(function.toString() + " not in vtable of " + irClass.toString())
|
||||
return index
|
||||
}
|
||||
|
||||
val methodTableEntries: List<OverriddenFunctionDescriptor> by lazy {
|
||||
classDescriptor.sortedOverridableOrOverridingMethods
|
||||
.flatMap { method -> method.allOverriddenDescriptors.map { OverriddenFunctionDescriptor(method, it) } }
|
||||
val methodTableEntries: List<OverriddenFunctionInfo> by lazy {
|
||||
irClass.sortedOverridableOrOverridingMethods
|
||||
.flatMap { method -> method.allOverriddenFunctions.map { OverriddenFunctionInfo(method, it) } }
|
||||
.filter { it.canBeCalledVirtually }
|
||||
.distinctBy { it.overriddenDescriptor.uniqueId }
|
||||
.sortedBy { it.overriddenDescriptor.uniqueId }
|
||||
.distinctBy { it.overriddenFunction.uniqueId }
|
||||
.sortedBy { it.overriddenFunction.uniqueId }
|
||||
// TODO: probably method table should contain all accessible methods to improve binary compatibility
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -127,7 +127,7 @@ internal fun IrFunction.needBridgeTo(target: IrFunction)
|
||||
= (0..this.valueParameters.size + 2).any { needBridgeToAt(target, it) }
|
||||
|
||||
internal val IrSimpleFunction.target: IrSimpleFunction
|
||||
get() = (if (modality == Modality.ABSTRACT) this else resolveFakeOverride()).original
|
||||
get() = (if (modality == Modality.ABSTRACT) this else resolveFakeOverride())
|
||||
|
||||
internal val IrFunction.target: IrFunction
|
||||
get() = when (this) {
|
||||
@@ -181,7 +181,7 @@ internal class BridgeDirections(val array: Array<BridgeDirection>) {
|
||||
}
|
||||
}
|
||||
|
||||
val IrSimpleFunction.allOverriddenDescriptors: Set<IrSimpleFunction>
|
||||
val IrSimpleFunction.allOverriddenFunctions: Set<IrSimpleFunction>
|
||||
get() {
|
||||
val result = mutableSetOf<IrSimpleFunction>()
|
||||
|
||||
@@ -214,13 +214,13 @@ internal fun IrSimpleFunction.bridgeDirectionsTo(
|
||||
return ourDirections
|
||||
}
|
||||
|
||||
tailrec internal fun IrDeclaration.findPackage(): IrPackageFragment {
|
||||
internal tailrec fun IrDeclaration.findPackage(): IrPackageFragment {
|
||||
val parent = this.parent
|
||||
return parent as? IrPackageFragment
|
||||
?: (parent as IrDeclaration).findPackage()
|
||||
}
|
||||
|
||||
fun IrFunction.isComparisonDescriptor(map: Map<SimpleType, IrSimpleFunction>): Boolean =
|
||||
fun IrFunction.isComparisonFunction(map: Map<SimpleType, IrSimpleFunction>): Boolean =
|
||||
this in map.values
|
||||
|
||||
val IrDeclaration.isPropertyAccessor get() =
|
||||
|
||||
-7
@@ -28,9 +28,6 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
|
||||
|
||||
val IrConstructor.constructedClass get() = this.parent as IrClass
|
||||
|
||||
val <T : IrDeclaration> T.original get() = this
|
||||
val IrDeclaration.containingDeclaration get() = this.parent
|
||||
|
||||
val IrDeclarationParent.fqNameSafe: FqName get() = when (this) {
|
||||
is IrPackageFragment -> this.fqName
|
||||
is IrDeclaration -> this.parent.fqNameSafe.child(this.name)
|
||||
@@ -116,8 +113,6 @@ val IrProperty.konanBackingField: IrField?
|
||||
return null
|
||||
}
|
||||
|
||||
val IrField.containingClass get() = this.parent as? IrClass
|
||||
|
||||
val IrFunction.isReal get() = this.origin != IrDeclarationOrigin.FAKE_OVERRIDE
|
||||
|
||||
// Note: psi2ir doesn't set `origin = FAKE_OVERRIDE` for fields and properties yet.
|
||||
@@ -151,8 +146,6 @@ fun IrSimpleFunction.overrides(other: IrSimpleFunction): Boolean {
|
||||
|
||||
fun IrClass.isSpecialClassWithNoSupertypes() = this.isAny() || this.isNothing()
|
||||
|
||||
internal val IrValueParameter.isValueParameter get() = this.index >= 0
|
||||
|
||||
private val IrCall.annotationClass
|
||||
get() = (this.symbol.owner as IrConstructor).constructedClass
|
||||
|
||||
|
||||
+28
-32
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
@@ -181,37 +180,35 @@ private val IrFunction.signature: String
|
||||
// TODO: rename to indicate that it has signature included
|
||||
internal val IrFunction.functionName: String
|
||||
get() {
|
||||
with(this.original) { // basic support for generics
|
||||
(if (this is IrConstructor && this.isObjCConstructor) this.getObjCInitMethod() else this)?.getObjCMethodInfo()?.let {
|
||||
return buildString {
|
||||
if (extensionReceiverParameter != null) {
|
||||
append(extensionReceiverParameter!!.type.getClass()!!.name)
|
||||
append(".")
|
||||
}
|
||||
(if (this is IrConstructor && this.isObjCConstructor) this.getObjCInitMethod() else this)?.getObjCMethodInfo()?.let {
|
||||
return buildString {
|
||||
if (extensionReceiverParameter != null) {
|
||||
append(extensionReceiverParameter!!.type.getClass()!!.name)
|
||||
append(".")
|
||||
}
|
||||
|
||||
append("objc:")
|
||||
append(it.selector)
|
||||
if (this@with is IrConstructor && this@with.isObjCConstructor) append("#Constructor")
|
||||
append("objc:")
|
||||
append(it.selector)
|
||||
if (this@functionName is IrConstructor && this@functionName.isObjCConstructor) append("#Constructor")
|
||||
|
||||
// We happen to have the clashing combinations such as
|
||||
//@ObjCMethod("issueChallengeToPlayers:message:", "objcKniBridge1165")
|
||||
//external fun GKScore.issueChallengeToPlayers(playerIDs: List<*>?, message: String?): Unit
|
||||
//@ObjCMethod("issueChallengeToPlayers:message:", "objcKniBridge1172")
|
||||
//external fun GKScore.issueChallengeToPlayers(playerIDs: List<*>?, message: String?): Unit
|
||||
// So disambiguate by the name of the bridge for now.
|
||||
// TODO: idealy we'd never generate such identical declarations.
|
||||
// We happen to have the clashing combinations such as
|
||||
//@ObjCMethod("issueChallengeToPlayers:message:", "objcKniBridge1165")
|
||||
//external fun GKScore.issueChallengeToPlayers(playerIDs: List<*>?, message: String?): Unit
|
||||
//@ObjCMethod("issueChallengeToPlayers:message:", "objcKniBridge1172")
|
||||
//external fun GKScore.issueChallengeToPlayers(playerIDs: List<*>?, message: String?): Unit
|
||||
// So disambiguate by the name of the bridge for now.
|
||||
// TODO: idealy we'd never generate such identical declarations.
|
||||
|
||||
if (this@with is IrSimpleFunction && this@with.hasObjCMethodAnnotation()) {
|
||||
this@with.objCMethodArgValue("selector") ?.let { append("#$it") }
|
||||
this@with.objCMethodArgValue("bridge") ?.let { append("#$it") }
|
||||
}
|
||||
if (this@functionName is IrSimpleFunction && this@functionName.hasObjCMethodAnnotation()) {
|
||||
this@functionName.objCMethodArgValue("selector") ?.let { append("#$it") }
|
||||
this@functionName.objCMethodArgValue("bridge") ?.let { append("#$it") }
|
||||
}
|
||||
}
|
||||
|
||||
val name = this.name.mangleIfInternal(this.module, this.visibility)
|
||||
|
||||
return "$name$signature"
|
||||
}
|
||||
|
||||
val name = this.name.mangleIfInternal(this.module, this.visibility)
|
||||
|
||||
return "$name$signature"
|
||||
}
|
||||
|
||||
private fun Name.mangleIfInternal(moduleDescriptor: ModuleDescriptor, visibility: Visibility): String =
|
||||
@@ -260,14 +257,13 @@ internal val IrField.symbolName: String
|
||||
|
||||
// TODO: bring here dependencies of this method?
|
||||
internal fun RuntimeAware.getLlvmFunctionType(function: IrFunction): LLVMTypeRef {
|
||||
val original = function.original
|
||||
val returnType = when {
|
||||
original is IrConstructor -> voidType
|
||||
original.isSuspend -> kObjHeaderPtr // Suspend functions return Any?.
|
||||
else -> getLLVMReturnType(original.returnType)
|
||||
function is IrConstructor -> voidType
|
||||
function.isSuspend -> kObjHeaderPtr // Suspend functions return Any?.
|
||||
else -> getLLVMReturnType(function.returnType)
|
||||
}
|
||||
val paramTypes = ArrayList(original.allParameters.map { getLLVMType(it.type) })
|
||||
if (original.isSuspend)
|
||||
val paramTypes = ArrayList(function.allParameters.map { getLLVMType(it.type) })
|
||||
if (function.isSuspend)
|
||||
paramTypes.add(kObjHeaderPtr) // Suspend functions have implicit parameter of type Continuation<>.
|
||||
if (isObjectType(returnType)) paramTypes.add(kObjHeaderPtrPtr)
|
||||
|
||||
|
||||
+51
-54
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
import kotlinx.cinterop.*
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.common.ir.ir2string
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
@@ -29,8 +28,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
/* to class descriptor */
|
||||
fun typeInfoValue(descriptor: IrClass): LLVMValueRef = descriptor.llvmTypeInfoPtr
|
||||
fun typeInfoValue(irClass: IrClass): LLVMValueRef = irClass.llvmTypeInfoPtr
|
||||
|
||||
fun param(fn: IrFunction, i: Int): LLVMValueRef {
|
||||
assert(i >= 0 && i < countParams(fn))
|
||||
@@ -39,19 +37,19 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
private fun countParams(fn: IrFunction) = LLVMCountParams(fn.llvmFunction)
|
||||
|
||||
fun functionEntryPointAddress(descriptor: IrFunction) = descriptor.entryPointAddress.llvm
|
||||
fun functionHash(descriptor: IrFunction): LLVMValueRef = descriptor.functionName.localHash.llvm
|
||||
fun functionEntryPointAddress(function: IrFunction) = function.entryPointAddress.llvm
|
||||
fun functionHash(function: IrFunction): LLVMValueRef = function.functionName.localHash.llvm
|
||||
|
||||
fun getObjectInstanceStorage(descriptor: IrClass, shared: Boolean): LLVMValueRef {
|
||||
assert (!descriptor.isUnit())
|
||||
val llvmGlobal = if (!isExternal(descriptor)) {
|
||||
context.llvmDeclarations.forSingleton(descriptor).instanceFieldRef
|
||||
fun getObjectInstanceStorage(irClass: IrClass, shared: Boolean): LLVMValueRef {
|
||||
assert (!irClass.isUnit())
|
||||
val llvmGlobal = if (!isExternal(irClass)) {
|
||||
context.llvmDeclarations.forSingleton(irClass).instanceFieldRef
|
||||
} else {
|
||||
val llvmType = getLLVMType(descriptor.defaultType)
|
||||
val llvmType = getLLVMType(irClass.defaultType)
|
||||
importGlobal(
|
||||
descriptor.objectInstanceFieldSymbolName,
|
||||
irClass.objectInstanceFieldSymbolName,
|
||||
llvmType,
|
||||
origin = descriptor.llvmSymbolOrigin,
|
||||
origin = irClass.llvmSymbolOrigin,
|
||||
threadLocal = !shared
|
||||
)
|
||||
}
|
||||
@@ -62,17 +60,17 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
return llvmGlobal
|
||||
}
|
||||
|
||||
fun getObjectInstanceShadowStorage(descriptor: IrClass): LLVMValueRef {
|
||||
assert (!descriptor.isUnit())
|
||||
assert (descriptor.objectIsShared)
|
||||
val llvmGlobal = if (!isExternal(descriptor)) {
|
||||
context.llvmDeclarations.forSingleton(descriptor).instanceShadowFieldRef!!
|
||||
fun getObjectInstanceShadowStorage(irClass: IrClass): LLVMValueRef {
|
||||
assert (!irClass.isUnit())
|
||||
assert (irClass.objectIsShared)
|
||||
val llvmGlobal = if (!isExternal(irClass)) {
|
||||
context.llvmDeclarations.forSingleton(irClass).instanceShadowFieldRef!!
|
||||
} else {
|
||||
val llvmType = getLLVMType(descriptor.defaultType)
|
||||
val llvmType = getLLVMType(irClass.defaultType)
|
||||
importGlobal(
|
||||
descriptor.objectInstanceShadowFieldSymbolName,
|
||||
irClass.objectInstanceShadowFieldSymbolName,
|
||||
llvmType,
|
||||
origin = descriptor.llvmSymbolOrigin,
|
||||
origin = irClass.llvmSymbolOrigin,
|
||||
threadLocal = true
|
||||
)
|
||||
}
|
||||
@@ -112,18 +110,18 @@ val LLVMValueRef.isConst:Boolean
|
||||
|
||||
|
||||
internal inline fun<R> generateFunction(codegen: CodeGenerator,
|
||||
descriptor: IrFunction,
|
||||
function: IrFunction,
|
||||
startLocation: LocationInfo? = null,
|
||||
endLocation: LocationInfo? = null,
|
||||
code:FunctionGenerationContext.(FunctionGenerationContext) -> R) {
|
||||
val llvmFunction = codegen.llvmFunction(descriptor)
|
||||
val llvmFunction = codegen.llvmFunction(function)
|
||||
|
||||
generateFunctionBody(FunctionGenerationContext(
|
||||
llvmFunction,
|
||||
codegen,
|
||||
startLocation,
|
||||
endLocation,
|
||||
descriptor), code)
|
||||
function), code)
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +141,7 @@ internal inline fun generateFunction(
|
||||
return function
|
||||
}
|
||||
|
||||
inline private fun <R> generateFunctionBody(
|
||||
private inline fun <R> generateFunctionBody(
|
||||
functionGenerationContext: FunctionGenerationContext,
|
||||
code: FunctionGenerationContext.(FunctionGenerationContext) -> R) {
|
||||
functionGenerationContext.prologue()
|
||||
@@ -158,7 +156,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
val codegen: CodeGenerator,
|
||||
startLocation: LocationInfo?,
|
||||
endLocation: LocationInfo?,
|
||||
internal val functionDescriptor: IrFunction? = null): ContextUtils {
|
||||
internal val irFunction: IrFunction? = null): ContextUtils {
|
||||
|
||||
override val context = codegen.context
|
||||
val vars = VariableManager(this)
|
||||
@@ -171,9 +169,8 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
|
||||
var returnType: LLVMTypeRef? = LLVMGetReturnType(getFunctionType(function))
|
||||
private val returns: MutableMap<LLVMBasicBlockRef, LLVMValueRef> = mutableMapOf()
|
||||
// TODO: remove, to make CodeGenerator descriptor-agnostic.
|
||||
val constructedClass: IrClass?
|
||||
get() = (functionDescriptor as? IrConstructor)?.constructedClass
|
||||
get() = (irFunction as? IrConstructor)?.constructedClass
|
||||
private var returnSlot: LLVMValueRef? = null
|
||||
private var slotsPhi: LLVMValueRef? = null
|
||||
private val frameOverlaySlotCount =
|
||||
@@ -195,8 +192,8 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
var forwardingForeignExceptionsTerminatedWith: LLVMValueRef? = null
|
||||
|
||||
init {
|
||||
functionDescriptor?.let {
|
||||
if (!functionDescriptor.isExported()) {
|
||||
irFunction?.let {
|
||||
if (!irFunction.isExported()) {
|
||||
LLVMSetLinkage(function, LLVMLinkage.LLVMInternalLinkage)
|
||||
// (Cannot do this before the function body is created).
|
||||
}
|
||||
@@ -409,8 +406,8 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
return call(context.llvm.allocInstanceFunction, listOf(typeInfo), lifetime)
|
||||
}
|
||||
|
||||
fun allocInstance(descriptor: IrClass, lifetime: Lifetime): LLVMValueRef =
|
||||
allocInstance(codegen.typeInfoForAllocation(descriptor), lifetime)
|
||||
fun allocInstance(irClass: IrClass, lifetime: Lifetime): LLVMValueRef =
|
||||
allocInstance(codegen.typeInfoForAllocation(irClass), lifetime)
|
||||
|
||||
fun allocArray(
|
||||
typeInfo: LLVMValueRef, count: LLVMValueRef, lifetime: Lifetime): LLVMValueRef {
|
||||
@@ -628,10 +625,10 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
return switch
|
||||
}
|
||||
|
||||
fun lookupVirtualImpl(receiver: LLVMValueRef, descriptor: IrFunction): LLVMValueRef {
|
||||
fun lookupVirtualImpl(receiver: LLVMValueRef, irFunction: IrFunction): LLVMValueRef {
|
||||
assert(LLVMTypeOf(receiver) == codegen.kObjHeaderPtr)
|
||||
|
||||
val typeInfoPtr: LLVMValueRef = if (descriptor.getObjCMethodInfo() != null) {
|
||||
val typeInfoPtr: LLVMValueRef = if (irFunction.getObjCMethodInfo() != null) {
|
||||
call(context.llvm.getObjCKotlinTypeInfo, listOf(receiver))
|
||||
} else {
|
||||
val typeInfoOrMetaPtr = structGep(receiver, 0 /* typeInfoOrMeta_ */)
|
||||
@@ -651,12 +648,12 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
* if toString/eq/hc is invoked on an interface instance, we resolve
|
||||
* owner as Any and dispatch it via vtable.
|
||||
*/
|
||||
val anyMethod = (descriptor as IrSimpleFunction).findOverriddenMethodOfAny()
|
||||
val owner = (anyMethod ?: descriptor).containingDeclaration as IrClass
|
||||
val anyMethod = (irFunction as IrSimpleFunction).findOverriddenMethodOfAny()
|
||||
val owner = (anyMethod ?: irFunction).parentAsClass
|
||||
|
||||
val llvmMethod = if (!owner.isInterface) {
|
||||
// If this is a virtual method of the class - we can call via vtable.
|
||||
val index = context.getVtableBuilder(owner).vtableIndex(anyMethod ?: descriptor)
|
||||
val index = context.getVtableBuilder(owner).vtableIndex(anyMethod ?: irFunction)
|
||||
val vtablePlace = gep(typeInfoPtr, Int32(1).llvm) // typeInfoPtr + 1
|
||||
val vtable = bitcast(kInt8PtrPtr, vtablePlace)
|
||||
val slot = gep(vtable, Int32(index).llvm)
|
||||
@@ -666,11 +663,11 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
// TODO: optimize by storing interface number in lower bits of 'this' pointer
|
||||
// when passing object as an interface. This way we can use those bits as index
|
||||
// for an additional per-interface vtable.
|
||||
val methodHash = codegen.functionHash(descriptor) // Calculate hash of the method to be invoked
|
||||
val methodHash = codegen.functionHash(irFunction) // Calculate hash of the method to be invoked
|
||||
val lookupArgs = listOf(typeInfoPtr, methodHash) // Prepare args for lookup
|
||||
call(context.llvm.lookupOpenMethodFunction, lookupArgs)
|
||||
}
|
||||
val functionPtrType = pointerType(codegen.getLlvmFunctionType(descriptor)) // Construct type of the method to be invoked
|
||||
val functionPtrType = pointerType(codegen.getLlvmFunctionType(irFunction)) // Construct type of the method to be invoked
|
||||
return bitcast(functionPtrType, llvmMethod) // Cast method address to the type
|
||||
}
|
||||
|
||||
@@ -685,16 +682,16 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
}
|
||||
|
||||
fun getObjectValue(
|
||||
descriptor: IrClass,
|
||||
exceptionHandler: ExceptionHandler,
|
||||
locationInfo: LocationInfo?
|
||||
irClass: IrClass,
|
||||
exceptionHandler: ExceptionHandler,
|
||||
locationInfo: LocationInfo?
|
||||
): LLVMValueRef {
|
||||
if (descriptor.isUnit()) {
|
||||
if (irClass.isUnit()) {
|
||||
return codegen.theUnitInstanceRef.llvm
|
||||
}
|
||||
|
||||
if (descriptor.isCompanion) {
|
||||
val parent = descriptor.parent as IrClass
|
||||
if (irClass.isCompanion) {
|
||||
val parent = irClass.parent as IrClass
|
||||
if (parent.isObjCClass()) {
|
||||
// TODO: cache it too.
|
||||
|
||||
@@ -707,8 +704,8 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
}
|
||||
}
|
||||
|
||||
val shared = descriptor.objectIsShared && context.config.threadsAreAllowed
|
||||
val objectPtr = codegen.getObjectInstanceStorage(descriptor, shared)
|
||||
val shared = irClass.objectIsShared && context.config.threadsAreAllowed
|
||||
val objectPtr = codegen.getObjectInstanceStorage(irClass, shared)
|
||||
val bbInit = basicBlock("label_init", locationInfo)
|
||||
val bbExit = basicBlock("label_continue", locationInfo)
|
||||
val objectVal = loadSlot(objectPtr, false)
|
||||
@@ -717,12 +714,12 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
condBr(objectInitialized, bbExit, bbInit)
|
||||
|
||||
positionAtEnd(bbInit)
|
||||
val typeInfo = codegen.typeInfoForAllocation(descriptor)
|
||||
val defaultConstructor = descriptor.constructors.single { it.valueParameters.size == 0 }
|
||||
val typeInfo = codegen.typeInfoForAllocation(irClass)
|
||||
val defaultConstructor = irClass.constructors.single { it.valueParameters.size == 0 }
|
||||
val ctor = codegen.llvmFunction(defaultConstructor)
|
||||
val (initFunction, args) =
|
||||
if (shared) {
|
||||
val shadowObjectPtr = codegen.getObjectInstanceShadowStorage(descriptor)
|
||||
val shadowObjectPtr = codegen.getObjectInstanceShadowStorage(irClass)
|
||||
context.llvm.initSharedInstanceFunction to listOf(objectPtr, shadowObjectPtr, typeInfo, ctor)
|
||||
} else {
|
||||
context.llvm.initInstanceFunction to listOf(objectPtr, typeInfo, ctor)
|
||||
@@ -732,7 +729,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
br(bbExit)
|
||||
|
||||
positionAtEnd(bbExit)
|
||||
val valuePhi = phi(codegen.getLLVMType(descriptor.defaultType))
|
||||
val valuePhi = phi(codegen.getLLVMType(irClass.defaultType))
|
||||
addPhiIncoming(valuePhi, bbCurrent to objectVal, bbInitResult to newValue)
|
||||
|
||||
return valuePhi
|
||||
@@ -741,11 +738,11 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
/**
|
||||
* Note: the same code is generated as IR in [org.jetbrains.kotlin.backend.konan.lower.EnumUsageLowering].
|
||||
*/
|
||||
fun getEnumEntry(descriptor: IrEnumEntry, exceptionHandler: ExceptionHandler): LLVMValueRef {
|
||||
val enumClassDescriptor = descriptor.containingDeclaration as IrClass
|
||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor)
|
||||
fun getEnumEntry(enumEntry: IrEnumEntry, exceptionHandler: ExceptionHandler): LLVMValueRef {
|
||||
val enumClass = enumEntry.parentAsClass
|
||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClass)
|
||||
|
||||
val ordinal = loweredEnum.entriesMap[descriptor.name]!!
|
||||
val ordinal = loweredEnum.entriesMap[enumEntry.name]!!
|
||||
val values = call(
|
||||
loweredEnum.valuesGetter.llvmFunction,
|
||||
emptyList(),
|
||||
|
||||
+2
-2
@@ -141,8 +141,8 @@ internal interface ContextUtils : RuntimeAware {
|
||||
val staticData: StaticData
|
||||
get() = context.llvm.staticData
|
||||
|
||||
fun isExternal(descriptor: IrDeclaration): Boolean {
|
||||
val pkg = descriptor.findPackage()
|
||||
fun isExternal(declaration: IrDeclaration): Boolean {
|
||||
val pkg = declaration.findPackage()
|
||||
return when (pkg) {
|
||||
is IrFile -> pkg.packageFragmentDescriptor.containingDeclaration != context.moduleDescriptor
|
||||
is IrExternalPackageFragment -> true
|
||||
|
||||
+86
-102
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SourceFile
|
||||
import org.jetbrains.kotlin.descriptors.konan.CurrentKonanModuleOrigin
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
@@ -33,7 +32,7 @@ import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.getArguments
|
||||
import org.jetbrains.kotlin.ir.util.getContainingFile
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
@@ -194,11 +193,9 @@ internal class RTTIGeneratorVisitor(context: Context) : IrElementVisitorVoid {
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
super.visitClass(declaration)
|
||||
|
||||
val descriptor = declaration
|
||||
generator.generate(declaration)
|
||||
|
||||
generator.generate(descriptor)
|
||||
|
||||
if (descriptor.isKotlinObjCClass()) {
|
||||
if (declaration.isKotlinObjCClass()) {
|
||||
kotlinObjCClassInfoGenerator.generate(declaration)
|
||||
}
|
||||
}
|
||||
@@ -232,19 +229,19 @@ internal interface CodeContext {
|
||||
* Declares the variable.
|
||||
* @return index of declared variable.
|
||||
*/
|
||||
fun genDeclareVariable(descriptor: IrVariable, value: LLVMValueRef?, variableLocation: VariableDebugLocation?): Int
|
||||
fun genDeclareVariable(variable: IrVariable, value: LLVMValueRef?, variableLocation: VariableDebugLocation?): Int
|
||||
|
||||
/**
|
||||
* @return index of variable declared before, or -1 if no such variable has been declared yet.
|
||||
*/
|
||||
fun getDeclaredVariable(descriptor: IrVariable): Int
|
||||
fun getDeclaredVariable(variable: IrVariable): Int
|
||||
|
||||
/**
|
||||
* Generates the code to obtain a value available in this context.
|
||||
*
|
||||
* @return the requested value
|
||||
*/
|
||||
fun genGetValue(descriptor: IrValueDeclaration): LLVMValueRef
|
||||
fun genGetValue(value: IrValueDeclaration): LLVMValueRef
|
||||
|
||||
/**
|
||||
* Returns owning function scope.
|
||||
@@ -342,11 +339,11 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
override fun genThrow(exception: LLVMValueRef) = unsupported()
|
||||
|
||||
override fun genDeclareVariable(descriptor: IrVariable, value: LLVMValueRef?, variableLocation: VariableDebugLocation?) = unsupported(descriptor)
|
||||
override fun genDeclareVariable(variable: IrVariable, value: LLVMValueRef?, variableLocation: VariableDebugLocation?) = unsupported(variable)
|
||||
|
||||
override fun getDeclaredVariable(descriptor: IrVariable) = -1
|
||||
override fun getDeclaredVariable(variable: IrVariable) = -1
|
||||
|
||||
override fun genGetValue(descriptor: IrValueDeclaration) = unsupported(descriptor)
|
||||
override fun genGetValue(value: IrValueDeclaration) = unsupported(value)
|
||||
|
||||
override fun functionScope(): CodeContext? = null
|
||||
|
||||
@@ -622,19 +619,19 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
*/
|
||||
private inner class VariableScope : InnerScopeImpl() {
|
||||
|
||||
override fun genDeclareVariable(descriptor: IrVariable, value: LLVMValueRef?, variableLocation: VariableDebugLocation?): Int {
|
||||
return functionGenerationContext.vars.createVariable(descriptor, value, variableLocation)
|
||||
override fun genDeclareVariable(variable: IrVariable, value: LLVMValueRef?, variableLocation: VariableDebugLocation?): Int {
|
||||
return functionGenerationContext.vars.createVariable(variable, value, variableLocation)
|
||||
}
|
||||
|
||||
override fun getDeclaredVariable(descriptor: IrVariable): Int {
|
||||
val index = functionGenerationContext.vars.indexOf(descriptor)
|
||||
return if (index < 0) super.getDeclaredVariable(descriptor) else return index
|
||||
override fun getDeclaredVariable(variable: IrVariable): Int {
|
||||
val index = functionGenerationContext.vars.indexOf(variable)
|
||||
return if (index < 0) super.getDeclaredVariable(variable) else return index
|
||||
}
|
||||
|
||||
override fun genGetValue(descriptor: IrValueDeclaration): LLVMValueRef {
|
||||
val index = functionGenerationContext.vars.indexOf(descriptor)
|
||||
override fun genGetValue(value: IrValueDeclaration): LLVMValueRef {
|
||||
val index = functionGenerationContext.vars.indexOf(value)
|
||||
if (index < 0) {
|
||||
return super.genGetValue(descriptor)
|
||||
return super.genGetValue(value)
|
||||
} else {
|
||||
return functionGenerationContext.vars.load(index)
|
||||
}
|
||||
@@ -653,21 +650,20 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
init {
|
||||
if (function != null) {
|
||||
parameters.forEach{
|
||||
val descriptor = it.key
|
||||
val ir = descriptor
|
||||
val parameter = it.key
|
||||
|
||||
val local = functionGenerationContext.vars.createParameter(descriptor,
|
||||
debugInfoIfNeeded(function, ir))
|
||||
val local = functionGenerationContext.vars.createParameter(parameter,
|
||||
debugInfoIfNeeded(function, parameter))
|
||||
functionGenerationContext.mapParameterForDebug(local, it.value)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun genGetValue(descriptor: IrValueDeclaration): LLVMValueRef {
|
||||
val index = functionGenerationContext.vars.indexOf(descriptor)
|
||||
override fun genGetValue(value: IrValueDeclaration): LLVMValueRef {
|
||||
val index = functionGenerationContext.vars.indexOf(value)
|
||||
if (index < 0) {
|
||||
return super.genGetValue(descriptor)
|
||||
return super.genGetValue(value)
|
||||
} else {
|
||||
return functionGenerationContext.vars.load(index)
|
||||
}
|
||||
@@ -690,7 +686,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
codegen.llvmFunction(it)
|
||||
}
|
||||
|
||||
private var name:String? = declaration?.descriptor?.name?.asString()
|
||||
private var name:String? = declaration?.name?.asString()
|
||||
|
||||
override fun genReturn(target: IrSymbolOwner, value: LLVMValueRef?) {
|
||||
if (declaration == null || target == declaration) {
|
||||
@@ -735,13 +731,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
/**
|
||||
* Binds LLVM function parameters to IR parameter descriptors.
|
||||
*/
|
||||
private fun bindParameters(descriptor: IrFunction?): Map<IrValueParameter, LLVMValueRef> {
|
||||
if (descriptor == null) return emptyMap()
|
||||
val parameterDescriptors = descriptor.allParameters
|
||||
return parameterDescriptors.mapIndexed { i, parameterDescriptor ->
|
||||
val parameter = codegen.param(descriptor, i)
|
||||
assert(codegen.getLLVMType(parameterDescriptor.type) == parameter.type)
|
||||
parameterDescriptor to parameter
|
||||
private fun bindParameters(function: IrFunction?): Map<IrValueParameter, LLVMValueRef> {
|
||||
if (function == null) return emptyMap()
|
||||
return function.allParameters.mapIndexed { i, irParameter ->
|
||||
val parameter = codegen.param(function, i)
|
||||
assert(codegen.getLLVMType(irParameter.type) == parameter.type)
|
||||
irParameter to parameter
|
||||
}.toMap()
|
||||
}
|
||||
|
||||
@@ -750,9 +745,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
val body = declaration.body
|
||||
|
||||
if (declaration.descriptor.modality == Modality.ABSTRACT) return
|
||||
if (declaration.descriptor.isExternal) return
|
||||
if (body == null) return
|
||||
if ((declaration as? IrSimpleFunction)?.modality == Modality.ABSTRACT
|
||||
|| declaration.isExternal
|
||||
|| body == null)
|
||||
return
|
||||
|
||||
generateFunction(codegen, declaration,
|
||||
declaration.location(start = true),
|
||||
@@ -826,10 +822,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
override fun visitField(declaration: IrField) {
|
||||
context.log{"visitField : ${ir2string(declaration)}"}
|
||||
debugFieldDeclaration(declaration)
|
||||
val descriptor = declaration
|
||||
if (context.needGlobalInit(declaration)) {
|
||||
val type = codegen.getLLVMType(descriptor.type)
|
||||
val globalProperty = context.llvmDeclarations.forStaticField(descriptor).storage
|
||||
val type = codegen.getLLVMType(declaration.type)
|
||||
val globalProperty = context.llvmDeclarations.forStaticField(declaration).storage
|
||||
val initializer = declaration.initializer?.expression as? IrConst<*>
|
||||
if (initializer != null)
|
||||
LLVMSetInitializer(globalProperty, evaluateExpression(initializer))
|
||||
@@ -1378,14 +1373,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
private fun evaluateCast(value: IrTypeOperatorCall): LLVMValueRef {
|
||||
context.log{"evaluateCast : ${ir2string(value)}"}
|
||||
val dstDescriptor = value.typeOperand.getClass()!!
|
||||
val dstClass = value.typeOperand.getClass()!!
|
||||
|
||||
val srcArg = evaluateExpression(value.argument) // Evaluate src expression.
|
||||
val srcArg = evaluateExpression(value.argument) // Evaluate src expression.
|
||||
assert(srcArg.type == codegen.kObjHeaderPtr)
|
||||
|
||||
if (dstDescriptor.defaultType.isObjCObjectType()) {
|
||||
if (dstClass.defaultType.isObjCObjectType()) {
|
||||
with(functionGenerationContext) {
|
||||
ifThen(not(genInstanceOf(srcArg, dstDescriptor))) {
|
||||
ifThen(not(genInstanceOf(srcArg, dstClass))) {
|
||||
callDirect(
|
||||
context.ir.symbols.ThrowTypeCastException.owner,
|
||||
emptyList(),
|
||||
@@ -1398,7 +1393,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
// Note: the code above would actually work for any classes.
|
||||
// However, the code generated below is shorter. Consider it to be a specialization.
|
||||
|
||||
val dstTypeInfo = codegen.typeInfoValue(dstDescriptor) // Get TypeInfo for dst type.
|
||||
val dstTypeInfo = codegen.typeInfoValue(dstClass) // Get TypeInfo for dst type.
|
||||
val srcObjInfoPtr = functionGenerationContext.bitcast(codegen.kObjHeaderPtr, srcArg) // Cast src to ObjInfoPtr.
|
||||
val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
|
||||
call(context.llvm.checkInstanceFunction, args) // Check if dst is subclass of src.
|
||||
@@ -1600,24 +1595,23 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
private fun fieldPtrOfClass(thisPtr: LLVMValueRef, value: IrField): LLVMValueRef {
|
||||
val fieldInfo = context.llvmDeclarations.forField(value)
|
||||
|
||||
val classDescriptor = value.containingDeclaration as IrClass
|
||||
val typePtr = pointerType(fieldInfo.classBodyType)
|
||||
|
||||
val bodyPtr = getObjectBodyPtr(classDescriptor, thisPtr)
|
||||
val bodyPtr = getObjectBodyPtr(value.parentAsClass, thisPtr)
|
||||
|
||||
val typedBodyPtr = functionGenerationContext.bitcast(typePtr, bodyPtr)
|
||||
val fieldPtr = LLVMBuildStructGEP(functionGenerationContext.builder, typedBodyPtr, fieldInfo.index, "")
|
||||
return fieldPtr!!
|
||||
}
|
||||
|
||||
private fun getObjectBodyPtr(classDescriptor: IrClass, objectPtr: LLVMValueRef): LLVMValueRef {
|
||||
return if (classDescriptor.isObjCClass()) {
|
||||
assert(classDescriptor.isKotlinObjCClass())
|
||||
private fun getObjectBodyPtr(irClass: IrClass, objectPtr: LLVMValueRef): LLVMValueRef {
|
||||
return if (irClass.isObjCClass()) {
|
||||
assert(irClass.isKotlinObjCClass())
|
||||
|
||||
val objCPtr = callDirect(context.ir.symbols.interopObjCObjectRawValueGetter.owner,
|
||||
listOf(objectPtr), Lifetime.IRRELEVANT)
|
||||
|
||||
val objCDeclarations = context.llvmDeclarations.forClass(classDescriptor).objCDeclarations!!
|
||||
val objCDeclarations = context.llvmDeclarations.forClass(irClass).objCDeclarations!!
|
||||
val bodyOffset = functionGenerationContext.load(objCDeclarations.bodyOffsetGlobal.llvmGlobal)
|
||||
|
||||
functionGenerationContext.gep(objCPtr, bodyOffset)
|
||||
@@ -1962,7 +1956,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
.filterIsInstance<IrSimpleFunction>().single { it.name.asString() == "invokeSuspend" }
|
||||
|
||||
private fun getContinuation(): LLVMValueRef {
|
||||
val caller = functionGenerationContext.functionDescriptor!!
|
||||
val caller = functionGenerationContext.irFunction!!
|
||||
return if (caller.isSuspend)
|
||||
codegen.param(caller, caller.allParameters.size) // The last argument.
|
||||
else {
|
||||
@@ -2002,11 +1996,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
assert (expression.getArguments().isEmpty())
|
||||
|
||||
val descriptor = expression.symbol.owner
|
||||
assert (descriptor.dispatchReceiverParameter == null)
|
||||
val function = expression.symbol.owner
|
||||
assert (function.dispatchReceiverParameter == null)
|
||||
|
||||
val entry = codegen.functionEntryPointAddress(descriptor)
|
||||
return entry
|
||||
return codegen.functionEntryPointAddress(function)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -2050,14 +2043,14 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
private inner class SuspensionPointScope(val suspensionPointId: IrVariable,
|
||||
val bbResume: LLVMBasicBlockRef,
|
||||
val bbResumeId: Int): InnerScopeImpl() {
|
||||
override fun genGetValue(descriptor: IrValueDeclaration): LLVMValueRef {
|
||||
if (descriptor == suspensionPointId) {
|
||||
override fun genGetValue(value: IrValueDeclaration): LLVMValueRef {
|
||||
if (value == suspensionPointId) {
|
||||
return if (context.config.indirectBranchesAreAllowed)
|
||||
functionGenerationContext.blockAddress(bbResume)
|
||||
else
|
||||
functionGenerationContext.intToPtr(Int32(bbResumeId + 1).llvm, int8TypePtr)
|
||||
}
|
||||
return super.genGetValue(descriptor)
|
||||
return super.genGetValue(value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2141,13 +2134,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun evaluateSimpleFunctionCall(
|
||||
descriptor: IrFunction, args: List<LLVMValueRef>,
|
||||
resultLifetime: Lifetime, superClass: IrClass? = null): LLVMValueRef {
|
||||
function: IrFunction, args: List<LLVMValueRef>,
|
||||
resultLifetime: Lifetime, superClass: IrClass? = null): LLVMValueRef {
|
||||
//context.log{"evaluateSimpleFunctionCall : $tmpVariableName = ${ir2string(value)}"}
|
||||
if (superClass == null && descriptor is IrSimpleFunction && descriptor.isOverridable)
|
||||
return callVirtual(descriptor, args, resultLifetime)
|
||||
if (superClass == null && function is IrSimpleFunction && function.isOverridable)
|
||||
return callVirtual(function, args, resultLifetime)
|
||||
else
|
||||
return callDirect(descriptor, args, resultLifetime)
|
||||
return callDirect(function, args, resultLifetime)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -2190,8 +2183,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
}
|
||||
}
|
||||
|
||||
private fun genGetObjCClass(classDescriptor: IrClass): LLVMValueRef {
|
||||
return functionGenerationContext.getObjCClass(classDescriptor, currentCodeContext.exceptionHandler)
|
||||
private fun genGetObjCClass(irClass: IrClass): LLVMValueRef {
|
||||
return functionGenerationContext.getObjCClass(irClass, currentCodeContext.exceptionHandler)
|
||||
}
|
||||
|
||||
private fun genGetObjCProtocol(irClass: IrClass): LLVMValueRef {
|
||||
@@ -2220,68 +2213,63 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
// TODO: Intrinsify?
|
||||
private fun evaluateOperatorCall(callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
||||
context.log{"evaluateOperatorCall : origin:${ir2string(callee)}"}
|
||||
val descriptor = callee.symbol.owner
|
||||
val function = callee.symbol.owner
|
||||
val ib = context.irModule!!.irBuiltins
|
||||
|
||||
with(functionGenerationContext) {
|
||||
return when {
|
||||
descriptor == ib.eqeqeqFun -> icmpEq(args[0], args[1])
|
||||
descriptor == ib.booleanNotFun -> icmpNe(args[0], kTrue)
|
||||
function == ib.eqeqeqFun -> icmpEq(args[0], args[1])
|
||||
function == ib.booleanNotFun -> icmpNe(args[0], kTrue)
|
||||
|
||||
descriptor.isComparisonDescriptor(ib.greaterFunByOperandType) -> {
|
||||
function.isComparisonFunction(ib.greaterFunByOperandType) -> {
|
||||
if (args[0].type.isFloatingPoint()) fcmpGt(args[0], args[1])
|
||||
else icmpGt(args[0], args[1])
|
||||
}
|
||||
descriptor.isComparisonDescriptor(ib.greaterOrEqualFunByOperandType) -> {
|
||||
function.isComparisonFunction(ib.greaterOrEqualFunByOperandType) -> {
|
||||
if (args[0].type.isFloatingPoint()) fcmpGe(args[0], args[1])
|
||||
else icmpGe(args[0], args[1])
|
||||
}
|
||||
descriptor.isComparisonDescriptor(ib.lessFunByOperandType) -> {
|
||||
function.isComparisonFunction(ib.lessFunByOperandType) -> {
|
||||
if (args[0].type.isFloatingPoint()) fcmpLt(args[0], args[1])
|
||||
else icmpLt(args[0], args[1])
|
||||
}
|
||||
descriptor.isComparisonDescriptor(ib.lessOrEqualFunByOperandType) -> {
|
||||
function.isComparisonFunction(ib.lessOrEqualFunByOperandType) -> {
|
||||
if (args[0].type.isFloatingPoint()) fcmpLe(args[0], args[1])
|
||||
else icmpLe(args[0], args[1])
|
||||
}
|
||||
else -> TODO(descriptor.name.toString())
|
||||
else -> TODO(function.name.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
fun callDirect(descriptor: IrFunction, args: List<LLVMValueRef>,
|
||||
fun callDirect(function: IrFunction, args: List<LLVMValueRef>,
|
||||
resultLifetime: Lifetime): LLVMValueRef {
|
||||
val realDescriptor = descriptor.target
|
||||
val llvmFunction = codegen.llvmFunction(realDescriptor)
|
||||
return call(descriptor, llvmFunction, args, resultLifetime)
|
||||
val llvmFunction = codegen.llvmFunction(function.target)
|
||||
return call(function, llvmFunction, args, resultLifetime)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
fun callVirtual(descriptor: IrFunction, args: List<LLVMValueRef>,
|
||||
fun callVirtual(function: IrFunction, args: List<LLVMValueRef>,
|
||||
resultLifetime: Lifetime): LLVMValueRef {
|
||||
|
||||
val function = functionGenerationContext.lookupVirtualImpl(args.first(), descriptor)
|
||||
val llvmFunction = functionGenerationContext.lookupVirtualImpl(args.first(), function)
|
||||
|
||||
return call(descriptor, function, args, resultLifetime) // Invoke the method
|
||||
return call(function, llvmFunction, args, resultLifetime) // Invoke the method
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
// TODO: it seems to be much more reliable to get args as a mapping from parameter descriptor to LLVM value,
|
||||
// instead of a plain list.
|
||||
// In such case it would be possible to check that all args are available and in the correct order.
|
||||
// However, it currently requires some refactoring to be performed.
|
||||
private fun call(descriptor: IrFunction, function: LLVMValueRef, args: List<LLVMValueRef>,
|
||||
private fun call(function: IrFunction, llvmFunction: LLVMValueRef, args: List<LLVMValueRef>,
|
||||
resultLifetime: Lifetime): LLVMValueRef {
|
||||
val result = call(function, args, resultLifetime)
|
||||
if (descriptor.returnType.isNothing()) {
|
||||
val result = call(llvmFunction, args, resultLifetime)
|
||||
if (function.returnType.isNothing()) {
|
||||
functionGenerationContext.unreachable()
|
||||
}
|
||||
|
||||
if (LLVMGetReturnType(getFunctionType(function)) == voidType) {
|
||||
if (LLVMGetReturnType(getFunctionType(llvmFunction)) == voidType) {
|
||||
return codegen.theUnitInstanceRef.llvm
|
||||
}
|
||||
|
||||
@@ -2289,10 +2277,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
}
|
||||
|
||||
|
||||
// TODO: it seems to be much more reliable to get args as a mapping from parameter descriptor to LLVM value,
|
||||
// instead of a plain list.
|
||||
// In such case it would be possible to check that all args are available and in the correct order.
|
||||
// However, it currently requires some refactoring to be performed.
|
||||
private fun call(symbol: DataFlowIR.FunctionSymbol, function: LLVMValueRef, args: List<LLVMValueRef>,
|
||||
resultLifetime: Lifetime): LLVMValueRef {
|
||||
val result = call(function, args, resultLifetime)
|
||||
@@ -2315,17 +2299,17 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun delegatingConstructorCall(
|
||||
descriptor: IrConstructor, args: List<LLVMValueRef>): LLVMValueRef {
|
||||
constructor: IrConstructor, args: List<LLVMValueRef>): LLVMValueRef {
|
||||
|
||||
val constructedClass = functionGenerationContext.constructedClass!!
|
||||
val thisPtr = currentCodeContext.genGetValue(constructedClass.thisReceiver!!)
|
||||
|
||||
if (descriptor.constructedClass.isExternalObjCClass()) {
|
||||
if (constructor.constructedClass.isExternalObjCClass()) {
|
||||
assert(args.isEmpty())
|
||||
return codegen.theUnitInstanceRef.llvm
|
||||
}
|
||||
|
||||
val thisPtrArgType = codegen.getLLVMType(descriptor.allParameters[0].type)
|
||||
val thisPtrArgType = codegen.getLLVMType(constructor.allParameters[0].type)
|
||||
val thisPtrArg = if (thisPtr.type == thisPtrArgType) {
|
||||
thisPtr
|
||||
} else {
|
||||
@@ -2333,7 +2317,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
functionGenerationContext.bitcast(thisPtrArgType, thisPtr)
|
||||
}
|
||||
|
||||
return callDirect(descriptor, listOf(thisPtrArg) + args,
|
||||
return callDirect(constructor, listOf(thisPtrArg) + args,
|
||||
Lifetime.IRRELEVANT /* no value returned */)
|
||||
}
|
||||
|
||||
@@ -2385,13 +2369,13 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun appendEntryPointSelector(descriptor: IrFunction?) {
|
||||
if (descriptor == null) return
|
||||
private fun appendEntryPointSelector(function: IrFunction?) {
|
||||
if (function == null) return
|
||||
|
||||
val entryPoint = codegen.llvmFunction(descriptor)
|
||||
val entryPoint = codegen.llvmFunction(function)
|
||||
val selectorName = "EntryPointSelector"
|
||||
val entryPointType = getFunctionType(entryPoint)
|
||||
val argCount = descriptor.valueParameters.size
|
||||
val argCount = function.valueParameters.size
|
||||
assert(argCount <= 1)
|
||||
|
||||
val selector = entryPointSelector(entryPoint, entryPointType, selectorName, argCount)
|
||||
|
||||
+79
-85
@@ -41,20 +41,20 @@ internal class LlvmDeclarations(
|
||||
private val fields: Map<IrField, FieldLlvmDeclarations>,
|
||||
private val staticFields: Map<IrField, StaticFieldLlvmDeclarations>,
|
||||
private val unique: Map<UniqueKind, UniqueLlvmDeclarations>) {
|
||||
fun forFunction(descriptor: IrFunction) = functions[descriptor] ?:
|
||||
error("${descriptor.toString()} ${descriptor.name} in ${(descriptor.parent as IrDeclaration).name}")
|
||||
fun forFunction(function: IrFunction) = functions[function] ?:
|
||||
error("${function.descriptor} in ${(function.parent as IrDeclaration).name}")
|
||||
|
||||
fun forClass(descriptor: IrClass) = classes[descriptor] ?:
|
||||
error("$descriptor ${descriptor.name}")
|
||||
fun forClass(irClass: IrClass) = classes[irClass] ?:
|
||||
error(irClass.descriptor.toString())
|
||||
|
||||
fun forField(descriptor: IrField) = fields[descriptor] ?:
|
||||
error(descriptor.toString())
|
||||
fun forField(field: IrField) = fields[field] ?:
|
||||
error(field.descriptor.toString())
|
||||
|
||||
fun forStaticField(descriptor: IrField) = staticFields[descriptor] ?:
|
||||
error(descriptor.toString())
|
||||
fun forStaticField(field: IrField) = staticFields[field] ?:
|
||||
error(field.descriptor.toString())
|
||||
|
||||
fun forSingleton(descriptor: IrClass) = forClass(descriptor).singletonDeclarations ?:
|
||||
error(descriptor.toString())
|
||||
fun forSingleton(irClass: IrClass) = forClass(irClass).singletonDeclarations ?:
|
||||
error(irClass.descriptor.toString())
|
||||
|
||||
fun forUnique(kind: UniqueKind) = unique[kind] ?: error("No unique $kind")
|
||||
|
||||
@@ -91,19 +91,19 @@ internal class UniqueLlvmDeclarations(val pointer: ConstPointer)
|
||||
* All fields of the class instance.
|
||||
* The order respects the class hierarchy, i.e. a class [fields] contains superclass [fields] as a prefix.
|
||||
*/
|
||||
internal fun ContextUtils.getFields(classDescriptor: IrClass) = context.getFields(classDescriptor)
|
||||
internal fun ContextUtils.getFields(irClass: IrClass) = context.getFields(irClass)
|
||||
|
||||
internal fun Context.getFields(classDescriptor: IrClass): List<IrField> {
|
||||
val superClass = classDescriptor.getSuperClassNotAny() // TODO: what if Any has fields?
|
||||
internal fun Context.getFields(irClass: IrClass): List<IrField> {
|
||||
val superClass = irClass.getSuperClassNotAny() // TODO: what if Any has fields?
|
||||
val superFields = if (superClass != null) getFields(superClass) else emptyList()
|
||||
|
||||
return superFields + getDeclaredFields(classDescriptor)
|
||||
return superFields + getDeclaredFields(irClass)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fields declared in the class.
|
||||
*/
|
||||
private fun Context.getDeclaredFields(classDescriptor: IrClass): List<IrField> {
|
||||
private fun Context.getDeclaredFields(irClass: IrClass): List<IrField> {
|
||||
// TODO: Here's what is going on here:
|
||||
// The existence of a backing field for a property is only described in the IR,
|
||||
// but not in the PropertyDescriptor.
|
||||
@@ -114,7 +114,6 @@ private fun Context.getDeclaredFields(classDescriptor: IrClass): List<IrField> {
|
||||
// In this function we check the presence of the backing field
|
||||
// two ways: first we check IR, then we check the protobuf extension.
|
||||
|
||||
val irClass = classDescriptor
|
||||
val fields = irClass.declarations.mapNotNull {
|
||||
when (it) {
|
||||
is IrField -> it.takeIf { it.isReal }
|
||||
@@ -125,7 +124,7 @@ private fun Context.getDeclaredFields(classDescriptor: IrClass): List<IrField> {
|
||||
// TODO: hack over missed parents in deserialized fields/property declarations.
|
||||
fields.forEach{it.parent = irClass}
|
||||
|
||||
if (classDescriptor.hasAnnotation(FqName.fromSegments(listOf("kotlin", "native", "internal", "NoReorderFields"))))
|
||||
if (irClass.hasAnnotation(FqName.fromSegments(listOf("kotlin", "native", "internal", "NoReorderFields"))))
|
||||
return fields
|
||||
|
||||
return fields.sortedBy {
|
||||
@@ -157,8 +156,8 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
private val names = mutableMapOf<IrDeclaration, Name>()
|
||||
private val counts = mutableMapOf<FqName, Int>()
|
||||
|
||||
fun getName(parent: FqName, descriptor: IrDeclaration): Name {
|
||||
return names.getOrPut(descriptor) {
|
||||
fun getName(parent: FqName, declaration: IrDeclaration): Name {
|
||||
return names.getOrPut(declaration) {
|
||||
val count = counts.getOrDefault(parent, 0) + 1
|
||||
counts[parent] = count
|
||||
Name.identifier(prefix + count)
|
||||
@@ -168,34 +167,34 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
|
||||
val objectNamer = Namer("object-")
|
||||
|
||||
private fun getLocalName(parent: FqName, descriptor: IrDeclaration): Name {
|
||||
if (descriptor.isAnonymousObject) {
|
||||
return objectNamer.getName(parent, descriptor)
|
||||
private fun getLocalName(parent: FqName, declaration: IrDeclaration): Name {
|
||||
if (declaration.isAnonymousObject) {
|
||||
return objectNamer.getName(parent, declaration)
|
||||
}
|
||||
|
||||
return descriptor.name
|
||||
return declaration.name
|
||||
}
|
||||
|
||||
private fun getFqName(descriptor: IrDeclaration): FqName {
|
||||
val parent = descriptor.parent
|
||||
private fun getFqName(declaration: IrDeclaration): FqName {
|
||||
val parent = declaration.parent
|
||||
val parentFqName = when (parent) {
|
||||
is IrPackageFragment -> parent.fqName
|
||||
is IrDeclaration -> getFqName(parent)
|
||||
else -> error(parent)
|
||||
}
|
||||
|
||||
val localName = getLocalName(parentFqName, descriptor)
|
||||
val localName = getLocalName(parentFqName, declaration)
|
||||
return parentFqName.child(localName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces the name to be used for non-exported LLVM declarations corresponding to [descriptor].
|
||||
* Produces the name to be used for non-exported LLVM declarations corresponding to [declaration].
|
||||
*
|
||||
* Note: since these declarations are going to be private, the name is only required not to clash with any
|
||||
* exported declarations.
|
||||
*/
|
||||
private fun qualifyInternalName(descriptor: IrDeclaration): String {
|
||||
return getFqName(descriptor).asString() + "#internal"
|
||||
private fun qualifyInternalName(declaration: IrDeclaration): String {
|
||||
return getFqName(declaration).asString() + "#internal"
|
||||
}
|
||||
|
||||
override fun visitElement(element: IrElement) {
|
||||
@@ -209,30 +208,28 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
}
|
||||
|
||||
private fun createClassDeclarations(declaration: IrClass): ClassLlvmDeclarations {
|
||||
val descriptor = declaration
|
||||
val internalName = qualifyInternalName(declaration)
|
||||
|
||||
val internalName = qualifyInternalName(descriptor)
|
||||
|
||||
val fields = getFields(descriptor)
|
||||
val fields = getFields(declaration)
|
||||
val bodyType = createClassBodyType("kclassbody:$internalName", fields)
|
||||
|
||||
val typeInfoPtr: ConstPointer
|
||||
val typeInfoGlobal: StaticData.Global
|
||||
|
||||
val typeInfoSymbolName = if (descriptor.isExported()) {
|
||||
descriptor.typeInfoSymbolName
|
||||
val typeInfoSymbolName = if (declaration.isExported()) {
|
||||
declaration.typeInfoSymbolName
|
||||
} else {
|
||||
"ktype:$internalName"
|
||||
}
|
||||
|
||||
if (descriptor.typeInfoHasVtableAttached) {
|
||||
if (declaration.typeInfoHasVtableAttached) {
|
||||
// Create the special global consisting of TypeInfo and vtable.
|
||||
|
||||
val typeInfoGlobalName = "ktypeglobal:$internalName"
|
||||
|
||||
val typeInfoWithVtableType = structType(
|
||||
runtime.typeInfoType,
|
||||
LLVMArrayType(int8TypePtr, context.getVtableBuilder(descriptor).vtableEntries.size)!!
|
||||
LLVMArrayType(int8TypePtr, context.getVtableBuilder(declaration).vtableEntries.size)!!
|
||||
)
|
||||
|
||||
typeInfoGlobal = staticData.createGlobal(typeInfoWithVtableType, typeInfoGlobalName, isExported = false)
|
||||
@@ -242,7 +239,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
typeInfoGlobal.pointer.getElementPtr(0).llvm,
|
||||
typeInfoSymbolName)!!
|
||||
|
||||
if (descriptor.isExported()) {
|
||||
if (declaration.isExported()) {
|
||||
if (llvmTypeInfoPtr.name != typeInfoSymbolName) {
|
||||
// So alias name has been mangled by LLVM to avoid name clash.
|
||||
throw IllegalArgumentException("Global '$typeInfoSymbolName' already exists")
|
||||
@@ -256,22 +253,22 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
} else {
|
||||
typeInfoGlobal = staticData.createGlobal(runtime.typeInfoType,
|
||||
typeInfoSymbolName,
|
||||
isExported = descriptor.isExported())
|
||||
isExported = declaration.isExported())
|
||||
|
||||
typeInfoPtr = typeInfoGlobal.pointer
|
||||
}
|
||||
|
||||
if (descriptor.isUnit() || descriptor.isKotlinArray())
|
||||
createUniqueDeclarations(descriptor, typeInfoPtr, bodyType)
|
||||
if (declaration.isUnit() || declaration.isKotlinArray())
|
||||
createUniqueDeclarations(declaration, typeInfoPtr, bodyType)
|
||||
|
||||
val singletonDeclarations = if (descriptor.kind.isSingleton) {
|
||||
createSingletonDeclarations(descriptor)
|
||||
val singletonDeclarations = if (declaration.kind.isSingleton) {
|
||||
createSingletonDeclarations(declaration)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
val objCDeclarations = if (descriptor.isKotlinObjCClass()) {
|
||||
createKotlinObjCClassDeclarations(descriptor)
|
||||
val objCDeclarations = if (declaration.isKotlinObjCClass()) {
|
||||
createKotlinObjCClassDeclarations(declaration)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
@@ -279,8 +276,8 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
val writableTypeInfoType = runtime.writableTypeInfoType
|
||||
val writableTypeInfoGlobal = if (writableTypeInfoType == null) {
|
||||
null
|
||||
} else if (descriptor.isExported()) {
|
||||
val name = descriptor.writableTypeInfoSymbolName
|
||||
} else if (declaration.isExported()) {
|
||||
val name = declaration.writableTypeInfoSymbolName
|
||||
staticData.createGlobal(writableTypeInfoType, name, isExported = true).also {
|
||||
it.setLinkage(LLVMLinkage.LLVMCommonLinkage) // Allows to be replaced by other bitcode module.
|
||||
}
|
||||
@@ -295,35 +292,35 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
}
|
||||
|
||||
private fun createUniqueDeclarations(
|
||||
descriptor: IrClass, typeInfoPtr: ConstPointer, bodyType: LLVMTypeRef) {
|
||||
irClass: IrClass, typeInfoPtr: ConstPointer, bodyType: LLVMTypeRef) {
|
||||
when {
|
||||
descriptor.isUnit() -> {
|
||||
irClass.isUnit() -> {
|
||||
uniques[UniqueKind.UNIT] =
|
||||
UniqueLlvmDeclarations(staticData.createUniqueInstance(UniqueKind.UNIT, bodyType, typeInfoPtr))
|
||||
}
|
||||
descriptor.isKotlinArray() -> {
|
||||
irClass.isKotlinArray() -> {
|
||||
uniques[UniqueKind.EMPTY_ARRAY] =
|
||||
UniqueLlvmDeclarations(staticData.createUniqueInstance(UniqueKind.EMPTY_ARRAY, bodyType, typeInfoPtr))
|
||||
}
|
||||
else -> TODO("Unsupported unique $descriptor")
|
||||
else -> TODO("Unsupported unique $irClass")
|
||||
}
|
||||
}
|
||||
|
||||
private fun createSingletonDeclarations(descriptor: IrClass): SingletonLlvmDeclarations? {
|
||||
private fun createSingletonDeclarations(irClass: IrClass): SingletonLlvmDeclarations? {
|
||||
|
||||
if (descriptor.isUnit()) {
|
||||
if (irClass.isUnit()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val isExported = descriptor.isExported()
|
||||
val isExported = irClass.isExported()
|
||||
val symbolName = if (isExported) {
|
||||
descriptor.objectInstanceFieldSymbolName
|
||||
irClass.objectInstanceFieldSymbolName
|
||||
} else {
|
||||
"kobjref:" + qualifyInternalName(descriptor)
|
||||
"kobjref:" + qualifyInternalName(irClass)
|
||||
}
|
||||
val threadLocal = !(descriptor.objectIsShared && context.config.threadsAreAllowed)
|
||||
val threadLocal = !(irClass.objectIsShared && context.config.threadsAreAllowed)
|
||||
val instanceFieldRef = addGlobal(
|
||||
symbolName, getLLVMType(descriptor.defaultType), isExported = isExported, threadLocal = threadLocal)
|
||||
symbolName, getLLVMType(irClass.defaultType), isExported = isExported, threadLocal = threadLocal)
|
||||
|
||||
LLVMSetInitializer(instanceFieldRef, kNullObjHeaderPtr)
|
||||
|
||||
@@ -331,11 +328,11 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
if (threadLocal) null
|
||||
else {
|
||||
val shadowSymbolName = if (isExported) {
|
||||
descriptor.objectInstanceShadowFieldSymbolName
|
||||
irClass.objectInstanceShadowFieldSymbolName
|
||||
} else {
|
||||
"kshadowobjref:" + qualifyInternalName(descriptor)
|
||||
"kshadowobjref:" + qualifyInternalName(irClass)
|
||||
}
|
||||
addGlobal(shadowSymbolName, getLLVMType(descriptor.defaultType), isExported = isExported, threadLocal = true)
|
||||
addGlobal(shadowSymbolName, getLLVMType(irClass.defaultType), isExported = isExported, threadLocal = true)
|
||||
}
|
||||
|
||||
instanceShadowFieldRef?.let { LLVMSetInitializer(it, kNullObjHeaderPtr) }
|
||||
@@ -343,8 +340,8 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
return SingletonLlvmDeclarations(instanceFieldRef, instanceShadowFieldRef)
|
||||
}
|
||||
|
||||
private fun createKotlinObjCClassDeclarations(descriptor: IrClass): KotlinObjCClassLlvmDeclarations {
|
||||
val internalName = qualifyInternalName(descriptor)
|
||||
private fun createKotlinObjCClassDeclarations(irClass: IrClass): KotlinObjCClassLlvmDeclarations {
|
||||
val internalName = qualifyInternalName(irClass)
|
||||
|
||||
val classPointerGlobal = staticData.createGlobal(int8TypePtr, "kobjcclassptr:$internalName")
|
||||
|
||||
@@ -363,25 +360,23 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
override fun visitField(declaration: IrField) {
|
||||
super.visitField(declaration)
|
||||
|
||||
val descriptor = declaration
|
||||
|
||||
val containingClass = descriptor.containingClass
|
||||
val containingClass = declaration.parent as? IrClass
|
||||
if (containingClass != null) {
|
||||
val classDeclarations = this.classes[containingClass] ?:
|
||||
error(containingClass.descriptor.toString())
|
||||
val allFields = classDeclarations.fields
|
||||
this.fields[descriptor] = FieldLlvmDeclarations(
|
||||
allFields.indexOf(descriptor) + 1, // First field is ObjHeader.
|
||||
this.fields[declaration] = FieldLlvmDeclarations(
|
||||
allFields.indexOf(declaration) + 1, // First field is ObjHeader.
|
||||
classDeclarations.bodyType
|
||||
)
|
||||
} else {
|
||||
// Fields are module-private, so we use internal name:
|
||||
val name = "kvar:" + qualifyInternalName(descriptor)
|
||||
val name = "kvar:" + qualifyInternalName(declaration)
|
||||
val storage = addGlobal(
|
||||
name, getLLVMType(descriptor.type), isExported = false,
|
||||
name, getLLVMType(declaration.type), isExported = false,
|
||||
threadLocal = declaration.storageClass == FieldStorage.THREAD_LOCAL)
|
||||
|
||||
this.staticFields[descriptor] = StaticFieldLlvmDeclarations(storage)
|
||||
this.staticFields[declaration] = StaticFieldLlvmDeclarations(storage)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,25 +385,24 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
|
||||
if (!declaration.isReal) return
|
||||
|
||||
val descriptor = declaration
|
||||
val llvmFunctionType = getLlvmFunctionType(descriptor)
|
||||
val llvmFunctionType = getLlvmFunctionType(declaration)
|
||||
|
||||
if ((descriptor is IrConstructor && descriptor.isObjCConstructor)) {
|
||||
if ((declaration is IrConstructor && declaration.isObjCConstructor)) {
|
||||
return
|
||||
}
|
||||
|
||||
val llvmFunction = if (descriptor.isExternal) {
|
||||
if (descriptor.isTypedIntrinsic || descriptor.isObjCBridgeBased()
|
||||
|| descriptor.annotations.hasAnnotation(RuntimeNames.cCall)) return
|
||||
val llvmFunction = if (declaration.isExternal) {
|
||||
if (declaration.isTypedIntrinsic || declaration.isObjCBridgeBased()
|
||||
|| declaration.annotations.hasAnnotation(RuntimeNames.cCall)) return
|
||||
|
||||
context.llvm.externalFunction(descriptor.symbolName, llvmFunctionType,
|
||||
context.llvm.externalFunction(declaration.symbolName, llvmFunctionType,
|
||||
// Assume that `external fun` is defined in native libs attached to this module:
|
||||
origin = descriptor.llvmSymbolOrigin
|
||||
origin = declaration.llvmSymbolOrigin
|
||||
)
|
||||
} else {
|
||||
val symbolName = if (descriptor.isExported()) {
|
||||
descriptor.symbolName.also {
|
||||
if (descriptor.name.asString() != "main") {
|
||||
val symbolName = if (declaration.isExported()) {
|
||||
declaration.symbolName.also {
|
||||
if (declaration.name.asString() != "main") {
|
||||
assert(LLVMGetNamedFunction(context.llvm.llvmModule, it) == null) { it }
|
||||
} else {
|
||||
// As a workaround, allow `main` functions to clash because frontend accepts this.
|
||||
@@ -416,10 +410,10 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
}
|
||||
}
|
||||
} else {
|
||||
"kfun:" + qualifyInternalName(descriptor)
|
||||
"kfun:" + qualifyInternalName(declaration)
|
||||
}
|
||||
val function = LLVMAddFunction(context.llvmModule, symbolName, llvmFunctionType)!!
|
||||
if (descriptor.returnType.isNothing())
|
||||
if (declaration.returnType.isNothing())
|
||||
setFunctionNoReturn(function)
|
||||
function
|
||||
}
|
||||
@@ -429,6 +423,6 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
LLVMAddTargetDependentFunctionAttr(llvmFunction, "no-frame-pointer-elim", "true")
|
||||
}
|
||||
|
||||
this.functions[descriptor] = FunctionLlvmDeclarations(llvmFunction)
|
||||
this.functions[declaration] = FunctionLlvmDeclarations(llvmFunction)
|
||||
}
|
||||
}
|
||||
|
||||
+57
-60
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.common.ir.ir2string
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.computePrimitiveBinaryTypeOrNull
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
@@ -46,24 +45,24 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAcyclicClass(classDescriptor: IrClass): Boolean = when {
|
||||
classDescriptor.symbol == context.ir.symbols.array -> false
|
||||
classDescriptor.isArray -> true
|
||||
context.llvmDeclarations.forClass(classDescriptor).fields.all { checkAcyclicFieldType(it.type) } -> true
|
||||
private fun checkAcyclicClass(irClass: IrClass): Boolean = when {
|
||||
irClass.symbol == context.ir.symbols.array -> false
|
||||
irClass.isArray -> true
|
||||
context.llvmDeclarations.forClass(irClass).fields.all { checkAcyclicFieldType(it.type) } -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
private fun flagsFromClass(classDescriptor: IrClass): Int {
|
||||
private fun flagsFromClass(irClass: IrClass): Int {
|
||||
var result = 0
|
||||
if (classDescriptor.isFrozen)
|
||||
if (irClass.isFrozen)
|
||||
result = result or TF_IMMUTABLE
|
||||
// TODO: maybe perform deeper analysis to find surely acyclic types.
|
||||
if (!classDescriptor.isInterface && !classDescriptor.isAbstract() && !classDescriptor.isAnnotationClass) {
|
||||
if (checkAcyclicClass(classDescriptor)) {
|
||||
if (!irClass.isInterface && !irClass.isAbstract() && !irClass.isAnnotationClass) {
|
||||
if (checkAcyclicClass(irClass)) {
|
||||
result = result or TF_ACYCLIC
|
||||
}
|
||||
}
|
||||
if (classDescriptor.isInterface)
|
||||
if (irClass.isInterface)
|
||||
result = result or TF_INTERFACE
|
||||
return result
|
||||
}
|
||||
@@ -125,10 +124,10 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
private val EXPORT_TYPE_INFO_FQ_NAME = FqName.fromSegments(listOf("kotlin", "native", "internal", "ExportTypeInfo"))
|
||||
|
||||
private fun exportTypeInfoIfRequired(classDesc: IrClass, typeInfoGlobal: LLVMValueRef?) {
|
||||
val annot = classDesc.descriptor.annotations.findAnnotation(EXPORT_TYPE_INFO_FQ_NAME)
|
||||
if (annot != null) {
|
||||
val name = getAnnotationValue(annot)!!
|
||||
private fun exportTypeInfoIfRequired(irClass: IrClass, typeInfoGlobal: LLVMValueRef?) {
|
||||
val annotation = irClass.descriptor.annotations.findAnnotation(EXPORT_TYPE_INFO_FQ_NAME)
|
||||
if (annotation != null) {
|
||||
val name = getAnnotationValue(annotation)!!
|
||||
// TODO: use LLVMAddAlias.
|
||||
val global = addGlobal(name, pointerType(runtime.typeInfoType), isExported = true)
|
||||
LLVMSetInitializer(global, typeInfoGlobal)
|
||||
@@ -170,21 +169,21 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
return LLVMStoreSizeOfType(llvmTargetData, classType).toInt()
|
||||
}
|
||||
|
||||
fun generate(classDesc: IrClass) {
|
||||
fun generate(irClass: IrClass) {
|
||||
|
||||
val className = classDesc.fqNameSafe
|
||||
val className = irClass.fqNameSafe
|
||||
|
||||
val llvmDeclarations = context.llvmDeclarations.forClass(classDesc)
|
||||
val llvmDeclarations = context.llvmDeclarations.forClass(irClass)
|
||||
|
||||
val bodyType = llvmDeclarations.bodyType
|
||||
|
||||
val size = getInstanceSize(bodyType, className)
|
||||
|
||||
val superTypeOrAny = classDesc.getSuperClassNotAny() ?: context.ir.symbols.any.owner
|
||||
val superType = if (classDesc.isAny()) NullPointer(runtime.typeInfoType)
|
||||
val superTypeOrAny = irClass.getSuperClassNotAny() ?: context.ir.symbols.any.owner
|
||||
val superType = if (irClass.isAny()) NullPointer(runtime.typeInfoType)
|
||||
else superTypeOrAny.typeInfoPtr
|
||||
|
||||
val interfaces = classDesc.implementedInterfaces.map { it.typeInfoPtr }
|
||||
val interfaces = irClass.implementedInterfaces.map { it.typeInfoPtr }
|
||||
val interfacesPtr = staticData.placeGlobalConstArray("kintf:$className",
|
||||
pointerType(runtime.typeInfoType), interfaces)
|
||||
|
||||
@@ -199,26 +198,26 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
val objOffsetsPtr = staticData.placeGlobalConstArray("krefs:$className", int32Type,
|
||||
objOffsets.map { Int32(it.toInt()) })
|
||||
|
||||
val objOffsetsCount = if (classDesc.descriptor == context.builtIns.array) {
|
||||
val objOffsetsCount = if (irClass.descriptor == context.builtIns.array) {
|
||||
1 // To mark it as non-leaf.
|
||||
} else {
|
||||
objOffsets.size
|
||||
}
|
||||
|
||||
val methods = if (classDesc.isAbstract()) {
|
||||
val methods = if (irClass.isAbstract()) {
|
||||
emptyList()
|
||||
} else {
|
||||
methodTableRecords(classDesc)
|
||||
methodTableRecords(irClass)
|
||||
}
|
||||
|
||||
val methodsPtr = staticData.placeGlobalConstArray("kmethods:$className",
|
||||
runtime.methodTableRecordType, methods)
|
||||
|
||||
val reflectionInfo = getReflectionInfo(classDesc)
|
||||
val reflectionInfo = getReflectionInfo(irClass)
|
||||
val typeInfoGlobal = llvmDeclarations.typeInfoGlobal
|
||||
val typeInfo = TypeInfo(
|
||||
classDesc.typeInfoPtr,
|
||||
makeExtendedInfo(classDesc),
|
||||
irClass.typeInfoPtr,
|
||||
makeExtendedInfo(irClass),
|
||||
size,
|
||||
superType,
|
||||
objOffsetsPtr, objOffsetsCount,
|
||||
@@ -226,26 +225,26 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
methodsPtr, methods.size,
|
||||
reflectionInfo.packageName,
|
||||
reflectionInfo.relativeName,
|
||||
flagsFromClass(classDesc),
|
||||
flagsFromClass(irClass),
|
||||
llvmDeclarations.writableTypeInfoGlobal?.pointer
|
||||
)
|
||||
|
||||
val typeInfoGlobalValue = if (!classDesc.typeInfoHasVtableAttached) {
|
||||
val typeInfoGlobalValue = if (!irClass.typeInfoHasVtableAttached) {
|
||||
typeInfo
|
||||
} else {
|
||||
val vtable = vtable(classDesc)
|
||||
val vtable = vtable(irClass)
|
||||
Struct(typeInfo, vtable)
|
||||
}
|
||||
|
||||
typeInfoGlobal.setInitializer(typeInfoGlobalValue)
|
||||
typeInfoGlobal.setConstant(true)
|
||||
|
||||
exportTypeInfoIfRequired(classDesc, classDesc.llvmTypeInfoPtr)
|
||||
exportTypeInfoIfRequired(irClass, irClass.llvmTypeInfoPtr)
|
||||
}
|
||||
|
||||
fun vtable(classDesc: IrClass): ConstArray {
|
||||
fun vtable(irClass: IrClass): ConstArray {
|
||||
// TODO: compile-time resolution limits binary compatibility
|
||||
val vtableEntries = context.getVtableBuilder(classDesc).vtableEntries.map {
|
||||
val vtableEntries = context.getVtableBuilder(irClass).vtableEntries.map {
|
||||
val implementation = it.implementation
|
||||
if (implementation == null || implementation.isExternalObjCClassMethod()) {
|
||||
NullPointer(int8Type)
|
||||
@@ -256,10 +255,10 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
return ConstArray(int8TypePtr, vtableEntries)
|
||||
}
|
||||
|
||||
fun methodTableRecords(classDesc: IrClass): List<MethodTableRecord> {
|
||||
val functionNames = mutableMapOf<Long, OverriddenFunctionDescriptor>()
|
||||
return context.getVtableBuilder(classDesc).methodTableEntries.map {
|
||||
val functionName = it.overriddenDescriptor.functionName
|
||||
fun methodTableRecords(irClass: IrClass): List<MethodTableRecord> {
|
||||
val functionNames = mutableMapOf<Long, OverriddenFunctionInfo>()
|
||||
return context.getVtableBuilder(irClass).methodTableEntries.map {
|
||||
val functionName = it.overriddenFunction.functionName
|
||||
val nameSignature = functionName.localHash
|
||||
val previous = functionNames.putIfAbsent(nameSignature.value, it)
|
||||
if (previous != null)
|
||||
@@ -275,13 +274,13 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
private fun mapRuntimeType(type: LLVMTypeRef): Int =
|
||||
runtimeTypeMap[type] ?: throw Error("Unmapped type: ${llvmtype2string(type)}")
|
||||
|
||||
private fun makeExtendedInfo(descriptor: IrClass): ConstPointer {
|
||||
private fun makeExtendedInfo(irClass: IrClass): ConstPointer {
|
||||
// TODO: shall we actually do that?
|
||||
if (context.shouldOptimize())
|
||||
return NullPointer(runtime.extendedTypeInfoType)
|
||||
|
||||
val className = descriptor.fqNameSafe.toString()
|
||||
val llvmDeclarations = context.llvmDeclarations.forClass(descriptor)
|
||||
val className = irClass.fqNameSafe.toString()
|
||||
val llvmDeclarations = context.llvmDeclarations.forClass(irClass)
|
||||
val bodyType = llvmDeclarations.bodyType
|
||||
val elementType = arrayClasses[className]
|
||||
val value = if (elementType != null) {
|
||||
@@ -313,18 +312,18 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
// TODO: extract more code common with generate().
|
||||
fun generateSyntheticInterfaceImpl(
|
||||
descriptor: IrClass,
|
||||
methodImpls: Map<IrFunction, ConstPointer>,
|
||||
immutable: Boolean = false
|
||||
irClass: IrClass,
|
||||
methodImpls: Map<IrFunction, ConstPointer>,
|
||||
immutable: Boolean = false
|
||||
): ConstPointer {
|
||||
assert(descriptor.isInterface)
|
||||
assert(irClass.isInterface)
|
||||
|
||||
val size = LLVMStoreSizeOfType(llvmTargetData, kObjHeader).toInt()
|
||||
|
||||
val superClass = context.ir.symbols.any.owner
|
||||
|
||||
assert(superClass.implementedInterfaces.isEmpty())
|
||||
val interfaces = listOf(descriptor.typeInfoPtr)
|
||||
val interfaces = listOf(irClass.typeInfoPtr)
|
||||
val interfacesPtr = staticData.placeGlobalConstArray("",
|
||||
pointerType(runtime.typeInfoType), interfaces)
|
||||
|
||||
@@ -333,7 +332,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
val objOffsetsCount = 0
|
||||
|
||||
val methods = (methodTableRecords(superClass) + methodImpls.map { (method, impl) ->
|
||||
assert(method.containingDeclaration == descriptor)
|
||||
assert(method.parent == irClass)
|
||||
MethodTableRecord(method.functionName.localHash, impl.bitcast(int8TypePtr))
|
||||
}).sortedBy { it.nameSignature.value }.also {
|
||||
assert(it.distinctBy { it.nameSignature.value } == it)
|
||||
@@ -365,7 +364,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
methods = methodsPtr, methodsCount = methods.size,
|
||||
packageName = reflectionInfo.packageName,
|
||||
relativeName = reflectionInfo.relativeName,
|
||||
flags = flagsFromClass(descriptor) or (if (immutable) TF_IMMUTABLE else 0),
|
||||
flags = flagsFromClass(irClass) or (if (immutable) TF_IMMUTABLE else 0),
|
||||
writableTypeInfo = writableTypeInfo
|
||||
), vtable)
|
||||
|
||||
@@ -375,23 +374,21 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
return result
|
||||
}
|
||||
|
||||
private val OverriddenFunctionDescriptor.implementation get() = getImplementation(context)
|
||||
private val OverriddenFunctionInfo.implementation get() = getImplementation(context)
|
||||
|
||||
data class ReflectionInfo(val packageName: String?, val relativeName: String?)
|
||||
|
||||
private fun getReflectionInfo(descriptor: IrClass): ReflectionInfo {
|
||||
return if (descriptor.isAnonymousObject) {
|
||||
ReflectionInfo(packageName = null, relativeName = null)
|
||||
} else if (descriptor.isLocal) {
|
||||
ReflectionInfo(packageName = null, relativeName = descriptor.name.asString())
|
||||
} else {
|
||||
ReflectionInfo(
|
||||
packageName = descriptor.findPackage().fqName.asString(),
|
||||
relativeName = generateSequence(descriptor, { it.parent as? IrClass })
|
||||
.toList().reversed()
|
||||
.joinToString(".") { it.name.asString() }
|
||||
)
|
||||
}
|
||||
private fun getReflectionInfo(irClass: IrClass): ReflectionInfo = when {
|
||||
irClass.isAnonymousObject -> ReflectionInfo(packageName = null, relativeName = null)
|
||||
|
||||
irClass.isLocal -> ReflectionInfo(packageName = null, relativeName = irClass.name.asString())
|
||||
|
||||
else -> ReflectionInfo(
|
||||
packageName = irClass.findPackage().fqName.asString(),
|
||||
relativeName = generateSequence(irClass) { it.parent as? IrClass }
|
||||
.toList().reversed()
|
||||
.joinToString(".") { it.name.asString() }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+22
-24
@@ -8,14 +8,12 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.common.ir.ir2string
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
internal fun IrElement.needDebugInfo(context: Context) = context.shouldContainDebugInfo() || (this is IrVariable && this.descriptor.isVar)
|
||||
internal fun IrElement.needDebugInfo(context: Context) = context.shouldContainDebugInfo() || (this is IrVariable && this.isVar)
|
||||
|
||||
internal class VariableManager(val functionGenerationContext: FunctionGenerationContext) {
|
||||
internal interface Record {
|
||||
@@ -54,41 +52,41 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
|
||||
contextVariablesToIndex.clear()
|
||||
}
|
||||
|
||||
fun createVariable(descriptor: IrValueDeclaration, value: LLVMValueRef? = null, variableLocation: VariableDebugLocation?) : Int {
|
||||
val isVar = descriptor is IrVariable && descriptor.isVar
|
||||
fun createVariable(valueDeclaration: IrValueDeclaration, value: LLVMValueRef? = null, variableLocation: VariableDebugLocation?) : Int {
|
||||
val isVar = valueDeclaration is IrVariable && valueDeclaration.isVar
|
||||
// Note that we always create slot for object references for memory management.
|
||||
if (!functionGenerationContext.context.shouldContainDebugInfo() && !isVar && value != null)
|
||||
return createImmutable(descriptor, value)
|
||||
return createImmutable(valueDeclaration, value)
|
||||
else
|
||||
// Unfortunately, we have to create mutable slots here,
|
||||
// as even vals can be assigned on multiple paths. However, we use varness
|
||||
// knowledge, as anonymous slots are created only for true vars (for vals
|
||||
// their single assigner already have slot).
|
||||
return createMutable(descriptor, isVar, value, variableLocation)
|
||||
return createMutable(valueDeclaration, isVar, value, variableLocation)
|
||||
}
|
||||
|
||||
internal fun createMutable(descriptor: IrValueDeclaration,
|
||||
internal fun createMutable(valueDeclaration: IrValueDeclaration,
|
||||
isVar: Boolean, value: LLVMValueRef? = null, variableLocation: VariableDebugLocation?) : Int {
|
||||
assert(!contextVariablesToIndex.contains(descriptor))
|
||||
assert(!contextVariablesToIndex.contains(valueDeclaration))
|
||||
val index = variables.size
|
||||
val type = functionGenerationContext.getLLVMType(descriptor.type)
|
||||
val slot = functionGenerationContext.alloca(type, descriptor.name.asString(), variableLocation)
|
||||
val type = functionGenerationContext.getLLVMType(valueDeclaration.type)
|
||||
val slot = functionGenerationContext.alloca(type, valueDeclaration.name.asString(), variableLocation)
|
||||
if (value != null)
|
||||
functionGenerationContext.storeAny(value, slot)
|
||||
variables.add(SlotRecord(slot, functionGenerationContext.isObjectType(type), isVar))
|
||||
contextVariablesToIndex[descriptor] = index
|
||||
contextVariablesToIndex[valueDeclaration] = index
|
||||
return index
|
||||
}
|
||||
|
||||
internal var skip = 0
|
||||
internal fun createParameter(descriptor: IrValueDeclaration, variableLocation: VariableDebugLocation?) : Int {
|
||||
assert(!contextVariablesToIndex.contains(descriptor))
|
||||
internal fun createParameter(valueDeclaration: IrValueDeclaration, variableLocation: VariableDebugLocation?) : Int {
|
||||
assert(!contextVariablesToIndex.contains(valueDeclaration))
|
||||
val index = variables.size
|
||||
val type = functionGenerationContext.getLLVMType(descriptor.type)
|
||||
val slot = functionGenerationContext.alloca(type, "p-${descriptor.name.asString()}", variableLocation)
|
||||
val type = functionGenerationContext.getLLVMType(valueDeclaration.type)
|
||||
val slot = functionGenerationContext.alloca(type, "p-${valueDeclaration.name.asString()}", variableLocation)
|
||||
val isObject = functionGenerationContext.isObjectType(type)
|
||||
variables.add(ParameterRecord(slot, isObject))
|
||||
contextVariablesToIndex[descriptor] = index
|
||||
contextVariablesToIndex[valueDeclaration] = index
|
||||
if (isObject)
|
||||
skip++
|
||||
return index
|
||||
@@ -110,17 +108,17 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
|
||||
return index
|
||||
}
|
||||
|
||||
internal fun createImmutable(descriptor: IrValueDeclaration, value: LLVMValueRef) : Int {
|
||||
if (contextVariablesToIndex.containsKey(descriptor))
|
||||
throw Error("${ir2string(descriptor)} is already defined")
|
||||
internal fun createImmutable(valueDeclaration: IrValueDeclaration, value: LLVMValueRef) : Int {
|
||||
if (contextVariablesToIndex.containsKey(valueDeclaration))
|
||||
throw Error("${ir2string(valueDeclaration)} is already defined")
|
||||
val index = variables.size
|
||||
variables.add(ValueRecord(value, descriptor.name))
|
||||
contextVariablesToIndex[descriptor] = index
|
||||
variables.add(ValueRecord(value, valueDeclaration.name))
|
||||
contextVariablesToIndex[valueDeclaration] = index
|
||||
return index
|
||||
}
|
||||
|
||||
fun indexOf(descriptor: IrValueDeclaration) : Int {
|
||||
return contextVariablesToIndex.getOrElse(descriptor) { -1 }
|
||||
fun indexOf(valueDeclaration: IrValueDeclaration) : Int {
|
||||
return contextVariablesToIndex.getOrElse(valueDeclaration) { -1 }
|
||||
}
|
||||
|
||||
fun addressOf(index: Int): LLVMValueRef {
|
||||
|
||||
+1
-1
@@ -1010,7 +1010,7 @@ private fun ObjCExportCodeGenerator.createDirectAdapters(
|
||||
val implementation = if (this.modality == Modality.ABSTRACT) {
|
||||
null
|
||||
} else {
|
||||
OverriddenFunctionDescriptor(
|
||||
OverriddenFunctionInfo(
|
||||
context.ir.get(this) as IrSimpleFunction,
|
||||
context.ir.get(base) as IrSimpleFunction
|
||||
).getImplementation(context)
|
||||
|
||||
+12
-12
@@ -102,13 +102,13 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain
|
||||
).apply { it.bind(this) }
|
||||
}
|
||||
}
|
||||
val overriddenJobDescriptor = OverriddenFunctionDescriptor(jobFunction, runtimeJobFunction)
|
||||
val overriddenJobDescriptor = OverriddenFunctionInfo(jobFunction, runtimeJobFunction)
|
||||
if (!overriddenJobDescriptor.needBridge) return expression
|
||||
|
||||
val bridge = context.buildBridge(
|
||||
startOffset = job.startOffset,
|
||||
endOffset = job.endOffset,
|
||||
descriptor = overriddenJobDescriptor,
|
||||
overriddenFunction = overriddenJobDescriptor,
|
||||
targetSymbol = job.symbol)
|
||||
bridges += bridge
|
||||
expression.putValueArgument(3, IrFunctionReferenceImpl(
|
||||
@@ -133,15 +133,15 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
||||
|
||||
irClass.simpleFunctions()
|
||||
.forEach { function ->
|
||||
function.allOverriddenDescriptors
|
||||
.map { OverriddenFunctionDescriptor(function, it) }
|
||||
function.allOverriddenFunctions
|
||||
.map { OverriddenFunctionInfo(function, it) }
|
||||
.filter { !it.bridgeDirections.allNotNeeded() }
|
||||
.filter { it.canBeCalledVirtually }
|
||||
.filter { !it.inheritsBridge }
|
||||
.distinctBy { it.bridgeDirections }
|
||||
.forEach {
|
||||
buildBridge(it, irClass)
|
||||
builtBridges += it.descriptor
|
||||
builtBridges += it.function
|
||||
}
|
||||
}
|
||||
irClass.transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||
@@ -165,12 +165,12 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
||||
})
|
||||
}
|
||||
|
||||
private fun buildBridge(descriptor: OverriddenFunctionDescriptor, irClass: IrClass) {
|
||||
private fun buildBridge(overriddenFunction: OverriddenFunctionInfo, irClass: IrClass) {
|
||||
irClass.declarations.add(context.buildBridge(
|
||||
startOffset = irClass.startOffset,
|
||||
endOffset = irClass.endOffset,
|
||||
descriptor = descriptor,
|
||||
targetSymbol = descriptor.descriptor.symbol,
|
||||
overriddenFunction = overriddenFunction,
|
||||
targetSymbol = overriddenFunction.function.symbol,
|
||||
superQualifierSymbol = irClass.symbol)
|
||||
)
|
||||
}
|
||||
@@ -217,10 +217,10 @@ private fun IrBlockBodyBuilder.buildTypeSafeBarrier(function: IrFunction,
|
||||
}
|
||||
|
||||
private fun Context.buildBridge(startOffset: Int, endOffset: Int,
|
||||
descriptor: OverriddenFunctionDescriptor, targetSymbol: IrFunctionSymbol,
|
||||
overriddenFunction: OverriddenFunctionInfo, targetSymbol: IrFunctionSymbol,
|
||||
superQualifierSymbol: IrClassSymbol? = null): IrFunction {
|
||||
|
||||
val bridge = specialDeclarationsFactory.getBridge(descriptor)
|
||||
val bridge = specialDeclarationsFactory.getBridge(overriddenFunction)
|
||||
|
||||
if (bridge.modality == Modality.ABSTRACT) {
|
||||
return bridge
|
||||
@@ -228,8 +228,8 @@ private fun Context.buildBridge(startOffset: Int, endOffset: Int,
|
||||
|
||||
val irBuilder = createIrBuilder(bridge.symbol, startOffset, endOffset)
|
||||
bridge.body = irBuilder.irBlockBody(bridge) {
|
||||
val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor.overriddenDescriptor.descriptor)
|
||||
typeSafeBarrierDescription?.let { buildTypeSafeBarrier(bridge, descriptor.descriptor, it) }
|
||||
val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(overriddenFunction.overriddenFunction.descriptor)
|
||||
typeSafeBarrierDescription?.let { buildTypeSafeBarrier(bridge, overriddenFunction.function, it) }
|
||||
|
||||
val delegatingCall = IrCallImpl(
|
||||
startOffset,
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.backend.konan.cgen.KotlinStubs
|
||||
import org.jetbrains.kotlin.backend.konan.cgen.generateCCall
|
||||
import org.jetbrains.kotlin.backend.konan.cgen.generateCFunctionPointer
|
||||
import org.jetbrains.kotlin.backend.konan.getInlinedClass
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenDescriptors
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
@@ -478,7 +478,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
context.ir.symbols.any.owner.declarations.filterIsInstance<IrSimpleFunction>().toSet()
|
||||
|
||||
irClass.declarations.filterIsInstance<IrSimpleFunction>().filter { it.isReal }.forEach { method ->
|
||||
val overriddenMethodOfAny = method.allOverriddenDescriptors.firstOrNull {
|
||||
val overriddenMethodOfAny = method.allOverriddenFunctions.firstOrNull {
|
||||
it in methodsOfAny
|
||||
}
|
||||
|
||||
|
||||
+36
-35
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.backend.common.peek
|
||||
import org.jetbrains.kotlin.backend.common.pop
|
||||
import org.jetbrains.kotlin.backend.common.push
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenDescriptors
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.target
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.getArguments
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.util.simpleFunctions
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
@@ -34,7 +35,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
private fun IrClass.getOverridingOf(function: IrFunction) = (function as? IrSimpleFunction)?.let {
|
||||
it.allOverriddenDescriptors.atMostOne { it.parent == this }
|
||||
it.allOverriddenFunctions.atMostOne { it.parent == this }
|
||||
}
|
||||
|
||||
private fun IrTypeOperator.isCast() =
|
||||
@@ -78,9 +79,9 @@ private class VariableValues {
|
||||
if (element !is IrGetValue)
|
||||
result += element
|
||||
else {
|
||||
val descriptor = element.symbol.owner
|
||||
if (descriptor is IrVariable && !seen.contains(descriptor))
|
||||
dfs(descriptor, seen, result)
|
||||
val declaration = element.symbol.owner
|
||||
if (declaration is IrVariable && !seen.contains(declaration))
|
||||
dfs(declaration, seen, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -230,7 +231,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
}
|
||||
}
|
||||
|
||||
private fun analyze(descriptor: IrDeclaration, body: IrElement?) {
|
||||
private fun analyze(declaration: IrDeclaration, body: IrElement?) {
|
||||
// Find all interesting expressions, variables and functions.
|
||||
val visitor = ElementFinderVisitor()
|
||||
body?.acceptVoid(visitor)
|
||||
@@ -262,7 +263,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
}
|
||||
|
||||
val function = FunctionDFGBuilder(expressionValuesExtractor, visitor.variableValues,
|
||||
descriptor, visitor.expressions, visitor.returnValues, visitor.thrownValues, visitor.catchParameters).build()
|
||||
declaration, visitor.expressions, visitor.returnValues, visitor.thrownValues, visitor.catchParameters).build()
|
||||
|
||||
DEBUG_OUTPUT(0) {
|
||||
function.debugOutput()
|
||||
@@ -274,8 +275,8 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
|
||||
DEBUG_OUTPUT(1) {
|
||||
println("SYMBOL TABLE:")
|
||||
symbolTable.classMap.forEach { descriptor, type ->
|
||||
println(" DESCRIPTOR: $descriptor")
|
||||
symbolTable.classMap.forEach { irClass, type ->
|
||||
println(" DESCRIPTOR: ${irClass.descriptor}")
|
||||
println(" TYPE: $type")
|
||||
if (type !is DataFlowIR.Type.Declared)
|
||||
return@forEach
|
||||
@@ -326,13 +327,13 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
// Producer and job of executeImpl are called externally, we need to reflect this somehow.
|
||||
val producerInvocation = IrCallImpl(expression.startOffset, expression.endOffset,
|
||||
executeImplProducerInvoke.returnType,
|
||||
executeImplProducerInvoke.symbol, executeImplProducerInvoke.descriptor)
|
||||
executeImplProducerInvoke.symbol)
|
||||
producerInvocation.dispatchReceiver = expression.getValueArgument(2)
|
||||
val jobFunctionReference = expression.getValueArgument(3) as? IrFunctionReference
|
||||
?: error("A function reference expected")
|
||||
val jobInvocation = IrCallImpl(expression.startOffset, expression.endOffset,
|
||||
jobFunctionReference.symbol.owner.returnType,
|
||||
jobFunctionReference.symbol, jobFunctionReference.descriptor)
|
||||
jobFunctionReference.symbol)
|
||||
jobInvocation.putValueArgument(0, producerInvocation)
|
||||
|
||||
expressions += jobInvocation
|
||||
@@ -410,27 +411,27 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
|
||||
private inner class FunctionDFGBuilder(val expressionValuesExtractor: ExpressionValuesExtractor,
|
||||
val variableValues: VariableValues,
|
||||
val descriptor: IrDeclaration,
|
||||
val declaration: IrDeclaration,
|
||||
val expressions: List<IrExpression>,
|
||||
val returnValues: List<IrExpression>,
|
||||
val thrownValues: List<IrExpression>,
|
||||
val catchParameters: Set<IrVariable>) {
|
||||
|
||||
private val allParameters = (descriptor as? IrFunction)?.allParameters ?: emptyList()
|
||||
private val allParameters = (declaration as? IrFunction)?.allParameters ?: emptyList()
|
||||
private val templateParameters = allParameters.withIndex().associateBy({ it.value }, { DataFlowIR.Node.Parameter(it.index) })
|
||||
|
||||
private val continuationParameter = when {
|
||||
descriptor !is IrSimpleFunction -> null
|
||||
declaration !is IrSimpleFunction -> null
|
||||
|
||||
descriptor.isSuspend -> DataFlowIR.Node.Parameter(allParameters.size)
|
||||
declaration.isSuspend -> DataFlowIR.Node.Parameter(allParameters.size)
|
||||
|
||||
descriptor.overrides(invokeSuspendFunctionSymbol.owner) -> // <this> is a ContinuationImpl inheritor.
|
||||
templateParameters[descriptor.dispatchReceiverParameter!!] // It is its own continuation.
|
||||
declaration.overrides(invokeSuspendFunctionSymbol.owner) -> // <this> is a ContinuationImpl inheritor.
|
||||
templateParameters[declaration.dispatchReceiverParameter!!] // It is its own continuation.
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
private fun getContinuation() = continuationParameter ?: error("Function $descriptor has no continuation parameter")
|
||||
private fun getContinuation() = continuationParameter ?: error("Function ${declaration.descriptor} has no continuation parameter")
|
||||
|
||||
private val nodes = mutableMapOf<IrExpression, DataFlowIR.Node>()
|
||||
private val variables = variableValues.elementData.keys.associate {
|
||||
@@ -444,14 +445,14 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
}
|
||||
|
||||
fun build(): DataFlowIR.Function {
|
||||
val isSuspend = descriptor is IrSimpleFunction && descriptor.isSuspend
|
||||
val isSuspend = declaration is IrSimpleFunction && declaration.isSuspend
|
||||
|
||||
expressions.forEach { getNode(it) }
|
||||
|
||||
val returnNodeType = when (descriptor) {
|
||||
is IrField -> descriptor.type
|
||||
is IrFunction -> descriptor.returnType
|
||||
else -> error(descriptor)
|
||||
val returnNodeType = when (declaration) {
|
||||
is IrField -> declaration.type
|
||||
is IrFunction -> declaration.returnType
|
||||
else -> error(declaration)
|
||||
}
|
||||
|
||||
val returnsNode = DataFlowIR.Node.Variable(
|
||||
@@ -464,8 +465,8 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
type = symbolTable.mapClassReferenceType(symbols.throwable.owner),
|
||||
kind = DataFlowIR.VariableKind.Temporary
|
||||
)
|
||||
variables.forEach { descriptor, node ->
|
||||
variableValues.elementData[descriptor]!!.forEach {
|
||||
variables.forEach { variable, node ->
|
||||
variableValues.elementData[variable]!!.forEach {
|
||||
node.values += expressionToEdge(it)
|
||||
}
|
||||
}
|
||||
@@ -473,7 +474,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
(if (isSuspend) listOf(continuationParameter!!) else emptyList())
|
||||
|
||||
return DataFlowIR.Function(
|
||||
symbol = symbolTable.mapFunction(descriptor),
|
||||
symbol = symbolTable.mapFunction(declaration),
|
||||
body = DataFlowIR.FunctionBody(allNodes.distinct().toList(), returnsNode, throwsNode)
|
||||
)
|
||||
}
|
||||
@@ -488,10 +489,10 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
|
||||
private fun getNode(expression: IrExpression): DataFlowIR.Node {
|
||||
if (expression is IrGetValue) {
|
||||
val descriptor = expression.symbol.owner
|
||||
if (descriptor is IrValueParameter)
|
||||
return templateParameters[descriptor]!!
|
||||
return variables[descriptor]!!
|
||||
val valueDeclaration = expression.symbol.owner
|
||||
if (valueDeclaration is IrValueParameter)
|
||||
return templateParameters[valueDeclaration]!!
|
||||
return variables[valueDeclaration]!!
|
||||
}
|
||||
return nodes.getOrPut(expression) {
|
||||
DEBUG_OUTPUT(0) {
|
||||
@@ -580,7 +581,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
} else {
|
||||
callee as IrSimpleFunction
|
||||
if (callee.isOverridable && value.superQualifier == null) {
|
||||
val owner = callee.containingDeclaration as IrClass
|
||||
val owner = callee.parentAsClass
|
||||
val actualReceiverType = value.dispatchReceiver!!.type
|
||||
val actualReceiverClassifier = actualReceiverType.classifierOrFail
|
||||
|
||||
@@ -634,7 +635,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
}
|
||||
|
||||
is IrDelegatingConstructorCall -> {
|
||||
val thisReceiver = (descriptor as IrConstructor).constructedClass.thisReceiver!!
|
||||
val thisReceiver = (declaration as IrConstructor).constructedClass.thisReceiver!!
|
||||
val thiz = IrGetValueImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, thisReceiver.type,
|
||||
thisReceiver.symbol)
|
||||
val arguments = listOf(thiz) + value.getArguments().map { it.second }
|
||||
@@ -649,7 +650,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
is IrGetField -> {
|
||||
val receiver = value.receiver?.let { expressionToEdge(it) }
|
||||
val receiverType = value.receiver?.let { symbolTable.mapType(it.type) }
|
||||
val name = value.descriptor.name.asString()
|
||||
val name = value.symbol.owner.name.asString()
|
||||
DataFlowIR.Node.FieldRead(
|
||||
receiver,
|
||||
DataFlowIR.Field(
|
||||
@@ -665,7 +666,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
is IrSetField -> {
|
||||
val receiver = value.receiver?.let { expressionToEdge(it) }
|
||||
val receiverType = value.receiver?.let { symbolTable.mapType(it.type) }
|
||||
val name = value.descriptor.name.asString()
|
||||
val name = value.symbol.owner.name.asString()
|
||||
DataFlowIR.Node.FieldWrite(
|
||||
receiver,
|
||||
DataFlowIR.Field(
|
||||
@@ -679,7 +680,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
}
|
||||
|
||||
is IrTypeOperatorCall -> {
|
||||
assert(!value.operator.isCast(), { "Casts should've been handled earlier" })
|
||||
assert(!value.operator.isCast()) { "Casts should've been handled earlier" }
|
||||
expressionToEdge(value.argument) // Put argument as a separate vertex.
|
||||
DataFlowIR.Node.Const(symbolTable.mapType(value.type)) // All operators except casts are basically constants.
|
||||
}
|
||||
|
||||
+34
-34
@@ -490,41 +490,41 @@ internal object DataFlowIR {
|
||||
|
||||
private fun IrClass.isFinal() = modality == Modality.FINAL && kind != ClassKind.ENUM_CLASS
|
||||
|
||||
fun mapClassReferenceType(descriptor: IrClass, eraseLocalObjects: Boolean = true): Type {
|
||||
fun mapClassReferenceType(irClass: IrClass, eraseLocalObjects: Boolean = true): Type {
|
||||
// Do not try to devirtualize ObjC classes.
|
||||
if (descriptor.module.name == Name.special("<forward declarations>") || descriptor.isObjCClass())
|
||||
if (irClass.module.name == Name.special("<forward declarations>") || irClass.isObjCClass())
|
||||
return Type.Virtual
|
||||
|
||||
if (eraseLocalObjects && descriptor.isAnonymousObject && descriptor.isLocal)
|
||||
return mapClassReferenceType(descriptor.getSuperClassNotAny() ?: context.irBuiltIns.anyClass.owner)
|
||||
if (eraseLocalObjects && irClass.isAnonymousObject && irClass.isLocal)
|
||||
return mapClassReferenceType(irClass.getSuperClassNotAny() ?: context.irBuiltIns.anyClass.owner)
|
||||
|
||||
val isFinal = descriptor.isFinal()
|
||||
val isAbstract = descriptor.isAbstract()
|
||||
val name = descriptor.fqNameSafe.asString()
|
||||
if (descriptor.module != irModule.descriptor)
|
||||
return classMap.getOrPut(descriptor) {
|
||||
val isFinal = irClass.isFinal()
|
||||
val isAbstract = irClass.isAbstract()
|
||||
val name = irClass.fqNameSafe.asString()
|
||||
if (irClass.module != irModule.descriptor)
|
||||
return classMap.getOrPut(irClass) {
|
||||
Type.External(name.localHash.value, isFinal, isAbstract, null, takeName { name })
|
||||
}
|
||||
|
||||
classMap[descriptor]?.let { return it }
|
||||
classMap[irClass]?.let { return it }
|
||||
|
||||
val placeToClassTable = true
|
||||
val symbolTableIndex = if (placeToClassTable) module.numberOfClasses++ else -1
|
||||
val type = if (descriptor.isExported())
|
||||
val type = if (irClass.isExported())
|
||||
Type.Public(name.localHash.value, isFinal, isAbstract, null,
|
||||
module, symbolTableIndex, takeName { name })
|
||||
else
|
||||
Type.Private(privateTypeIndex++, isFinal, isAbstract, null,
|
||||
module, symbolTableIndex, takeName { name })
|
||||
|
||||
classMap[descriptor] = type
|
||||
classMap[irClass] = type
|
||||
|
||||
type.superTypes += descriptor.superTypes.map { mapClassReferenceType(it.getClass()!!) }
|
||||
type.superTypes += irClass.superTypes.map { mapClassReferenceType(it.getClass()!!) }
|
||||
if (!isAbstract) {
|
||||
val vtableBuilder = context.getVtableBuilder(descriptor)
|
||||
val vtableBuilder = context.getVtableBuilder(irClass)
|
||||
type.vtable += vtableBuilder.vtableEntries.map { mapFunction(it.getImplementation(context)!!) }
|
||||
vtableBuilder.methodTableEntries.forEach {
|
||||
type.itable[it.overriddenDescriptor.functionName.localHash.value] = mapFunction(it.getImplementation(context)!!)
|
||||
type.itable[it.overriddenFunction.functionName.localHash.value] = mapFunction(it.getImplementation(context)!!)
|
||||
}
|
||||
}
|
||||
return type
|
||||
@@ -564,18 +564,18 @@ internal object DataFlowIR {
|
||||
}
|
||||
|
||||
// TODO: use from LlvmDeclarations.
|
||||
private fun getFqName(descriptor: IrDeclaration): FqName =
|
||||
descriptor.parent.fqNameSafe.child(descriptor.name)
|
||||
private fun getFqName(declaration: IrDeclaration): FqName =
|
||||
declaration.parent.fqNameSafe.child(declaration.name)
|
||||
|
||||
private val IrFunction.internalName get() = getFqName(this).asString() + "#internal"
|
||||
|
||||
fun mapFunction(descriptor: IrDeclaration): FunctionSymbol = when (descriptor) {
|
||||
is IrFunction -> mapFunction(descriptor)
|
||||
is IrField -> mapPropertyInitializer(descriptor)
|
||||
else -> error("Unknown descriptor: $descriptor")
|
||||
fun mapFunction(declaration: IrDeclaration): FunctionSymbol = when (declaration) {
|
||||
is IrFunction -> mapFunction(declaration)
|
||||
is IrField -> mapPropertyInitializer(declaration)
|
||||
else -> error("Unknown declaration: $declaration")
|
||||
}
|
||||
|
||||
private fun mapFunction(descriptor: IrFunction): FunctionSymbol = descriptor.target.let {
|
||||
private fun mapFunction(function: IrFunction): FunctionSymbol = function.target.let {
|
||||
functionMap[it]?.let { return it }
|
||||
|
||||
val name = if (it.isExported()) it.symbolName else it.internalName
|
||||
@@ -602,15 +602,15 @@ internal object DataFlowIR {
|
||||
|
||||
else -> {
|
||||
val isAbstract = it is IrSimpleFunction && it.modality == Modality.ABSTRACT
|
||||
val classDescriptor = it.containingDeclaration as? IrClass
|
||||
val irClass = it.parent as? IrClass
|
||||
val bridgeTarget = it.bridgeTarget
|
||||
val isSpecialBridge = bridgeTarget.let {
|
||||
it != null && BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(it.descriptor) != null
|
||||
}
|
||||
val bridgeTargetSymbol = if (isSpecialBridge || bridgeTarget == null) null else mapFunction(bridgeTarget)
|
||||
val placeToFunctionsTable = !isAbstract && it !is IrConstructor && classDescriptor != null
|
||||
&& !classDescriptor.isNonGeneratedAnnotation()
|
||||
&& (it.isOverridableOrOverrides || bridgeTarget != null || descriptor.isSpecial || !classDescriptor.isFinal())
|
||||
val placeToFunctionsTable = !isAbstract && it !is IrConstructor && irClass != null
|
||||
&& !irClass.isNonGeneratedAnnotation()
|
||||
&& (it.isOverridableOrOverrides || bridgeTarget != null || function.isSpecial || !irClass.isFinal())
|
||||
val symbolTableIndex = if (placeToFunctionsTable) module.numberOfFunctions++ else -1
|
||||
if (it.isExported())
|
||||
FunctionSymbol.Public(name.localHash.value, module, symbolTableIndex, attributes, bridgeTargetSymbol, takeName { name })
|
||||
@@ -621,13 +621,13 @@ internal object DataFlowIR {
|
||||
functionMap[it] = symbol
|
||||
|
||||
symbol.parameters =
|
||||
(descriptor.allParameters.map { it.type } + (if (descriptor.isSuspend) listOf(continuationType) else emptyList()))
|
||||
(function.allParameters.map { it.type } + (if (function.isSuspend) listOf(continuationType) else emptyList()))
|
||||
.map { mapTypeToFunctionParameter(it) }
|
||||
.toTypedArray()
|
||||
symbol.returnParameter = mapTypeToFunctionParameter(if (descriptor.isSuspend)
|
||||
symbol.returnParameter = mapTypeToFunctionParameter(if (function.isSuspend)
|
||||
context.irBuiltIns.anyType
|
||||
else
|
||||
descriptor.returnType)
|
||||
function.returnType)
|
||||
|
||||
return symbol
|
||||
}
|
||||
@@ -635,14 +635,14 @@ internal object DataFlowIR {
|
||||
private val IrFunction.isSpecial get() =
|
||||
name.asString().let { it.startsWith("<bridge-") || it == "<box>" || it == "<unbox>" }
|
||||
|
||||
private fun mapPropertyInitializer(descriptor: IrField): FunctionSymbol = descriptor.original.let {
|
||||
functionMap[it]?.let { return it }
|
||||
private fun mapPropertyInitializer(irField: IrField): FunctionSymbol {
|
||||
functionMap[irField]?.let { return it }
|
||||
|
||||
assert(it.parent !is IrClass) { "All local properties initializers should've been lowered" }
|
||||
assert(irField.parent !is IrClass) { "All local properties initializers should've been lowered" }
|
||||
val attributes = FunctionAttributes.IS_GLOBAL_INITIALIZER or FunctionAttributes.RETURNS_UNIT
|
||||
val symbol = FunctionSymbol.Private(privateFunIndex++, module, -1, attributes, null, takeName { "${it.symbolName}_init" })
|
||||
val symbol = FunctionSymbol.Private(privateFunIndex++, module, -1, attributes, null, takeName { "${irField.symbolName}_init" })
|
||||
|
||||
functionMap[it] = symbol
|
||||
functionMap[irField] = symbol
|
||||
|
||||
symbol.parameters = emptyArray()
|
||||
symbol.returnParameter = mapTypeToFunctionParameter(context.irBuiltIns.unitType)
|
||||
|
||||
Reference in New Issue
Block a user