Merge pull request #4496 from JetBrains/small_backend_optimizations

Small backend optimizations
This commit is contained in:
Igor Chevdar
2020-11-10 10:59:24 +03:00
committed by Stanislav Erokhin
parent 2c898fe72c
commit f8b4db21aa
16 changed files with 234 additions and 82 deletions
@@ -390,11 +390,29 @@ private class CString(val bytes: ByteArray): CValues<ByteVar>() {
}
}
private object EmptyCString: CValues<ByteVar>() {
override val size get() = 1
override val align get() = 1
private val placement =
interpretCPointer<ByteVar>(nativeMemUtils.alloc(1, 1).rawPtr)!!.also {
it[0] = 0.toByte()
}
override fun getPointer(scope: AutofreeScope): CPointer<ByteVar> {
return placement
}
override fun place(placement: CPointer<ByteVar>): CPointer<ByteVar> {
placement[0] = 0.toByte()
return placement
}
}
/**
* @return the value of zero-terminated UTF-8-encoded C string constructed from given [kotlin.String].
*/
public val String.cstr: CValues<ByteVar>
get() = CString(encodeToUtf8(this))
get() = if (isEmpty()) EmptyCString else CString(encodeToUtf8(this))
/**
* @return the value of zero-terminated UTF-8-encoded C string constructed from given [kotlin.String].
@@ -40,6 +40,7 @@ import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyToWithoutSuperTypes
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
import org.jetbrains.kotlin.backend.konan.llvm.coverage.CoverageManager
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
@@ -47,6 +48,7 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.konan.library.KonanLibraryLayout
import org.jetbrains.kotlin.library.SerializedIrModule
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.utils.addToStdlib.getOrPut
/**
* Offset for synthetic elements created by lowerings and not attributable to other places in the source code.
@@ -254,10 +256,20 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
KonanReflectionTypes(moduleDescriptor, KonanFqNames.internalPackageName)
}
val layoutBuilders = mutableMapOf<IrClass, ClassLayoutBuilder>()
// TODO: Remove after adding special <userData> property to IrDeclaration.
private val layoutBuilders = mutableMapOf<IrClass, ClassLayoutBuilder>()
fun getLayoutBuilder(irClass: IrClass) = layoutBuilders.getOrPut(irClass) {
ClassLayoutBuilder(irClass, this, isLowered = shouldLower(this, irClass))
fun getLayoutBuilder(irClass: IrClass): ClassLayoutBuilder {
if (irClass is IrLazyClass)
return layoutBuilders.getOrPut(irClass) {
ClassLayoutBuilder(irClass, this, isLowered = shouldLower(this, irClass))
}
val metadata = irClass.metadata as? CodegenClassMetadata
?: CodegenClassMetadata(irClass).also { irClass.metadata = it }
metadata.layoutBuilder?.let { return it }
val layoutBuilder = ClassLayoutBuilder(irClass, this, isLowered = shouldLower(this, irClass))
metadata.layoutBuilder = layoutBuilder
return layoutBuilder
}
lateinit var globalHierarchyAnalysisResult: GlobalHierarchyAnalysisResult
@@ -5,11 +5,10 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
import org.jetbrains.kotlin.backend.konan.ir.konanLibrary
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.module
import org.jetbrains.kotlin.library.KotlinLibrary
internal abstract class LlvmModuleSpecificationBase(protected val cachedLibraries: CachedLibraries) : LlvmModuleSpecification {
@@ -26,7 +25,7 @@ internal abstract class LlvmModuleSpecificationBase(protected val cachedLibrarie
module.konanLibrary.let { it == null || containsLibrary(it) }
override fun containsDeclaration(declaration: IrDeclaration): Boolean =
declaration.module.konanLibrary.let { it == null || containsLibrary(it) }
declaration.konanLibrary.let { it == null || containsLibrary(it) }
}
internal class DefaultLlvmModuleSpecification(cachedLibraries: CachedLibraries)
@@ -8,12 +8,11 @@ import org.jetbrains.kotlin.backend.common.serialization.mangle.ManglerChecker
import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.Ir2DescriptorManglerAdapter
import org.jetbrains.kotlin.backend.konan.descriptors.isForwardDeclarationModule
import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
import org.jetbrains.kotlin.backend.konan.ir.konanLibrary
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs
import org.jetbrains.kotlin.backend.konan.serialization.*
import org.jetbrains.kotlin.backend.konan.serialization.KonanIrLinker
import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerDesc
import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerIr
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
@@ -154,7 +153,7 @@ internal fun Context.psiToIr(
}
expectDescriptorToSymbol = mutableMapOf()
val module = translator.generateModuleFragment(
val mainModule = translator.generateModuleFragment(
generatorContext,
environment.getSourceFiles(),
irProviders = listOf(irDeserializer),
@@ -164,7 +163,7 @@ internal fun Context.psiToIr(
// how ExpectedActualResolver is implemented.
// Need to fix ExpectActualResolver to either cache expects or somehow reduce the member scope searches.
expectDescriptorToSymbol = if (expectActualLinker) expectDescriptorToSymbol else null
)
).toKonanModule()
irDeserializer.postProcess()
@@ -173,7 +172,7 @@ internal fun Context.psiToIr(
symbolTable.noUnboundLeft("Unbound symbols left after linker")
module.acceptVoid(ManglerChecker(KonanManglerIr, Ir2DescriptorManglerAdapter(KonanManglerDesc)))
mainModule.acceptVoid(ManglerChecker(KonanManglerIr, Ir2DescriptorManglerAdapter(KonanManglerDesc)))
val modules = if (isProducingLibrary) emptyMap() else (irDeserializer as KonanIrLinker).modules
@@ -182,7 +181,7 @@ internal fun Context.psiToIr(
modules.values.forEach { fakeOverrideChecker.check(it) }
}
irModule = module
irModule = mainModule
// Note: coupled with [shouldLower] below.
irModules = modules.filterValues { llvmModuleSpecification.containsModule(it) }
@@ -196,6 +195,11 @@ internal fun Context.psiToIr(
functionIrClassFactory.module = (modules.values + irModule!!).single { it.descriptor.isNativeStdlib() }
}
mainModule.files.forEach { it.metadata = KonanFileMetadataSource(mainModule) }
modules.values.forEach { module ->
module.files.forEach { it.metadata = KonanFileMetadataSource(module as KonanIrModuleFragmentImpl) }
}
val originalBindingContext = bindingContext as? CleanableBindingContext
?: error("BindingContext should be cleanable in K/N IR to avoid leaking memory: $bindingContext")
originalBindingContext.clear()
@@ -8,7 +8,7 @@ import org.jetbrains.kotlin.backend.common.lower.at
import org.jetbrains.kotlin.backend.common.lower.irNot
import org.jetbrains.kotlin.backend.konan.PrimitiveBinaryType
import org.jetbrains.kotlin.backend.konan.RuntimeNames
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
import org.jetbrains.kotlin.backend.konan.ir.konanLibrary
import org.jetbrains.kotlin.backend.konan.getObjCMethodInfo
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
import org.jetbrains.kotlin.backend.konan.ir.buildSimpleAnnotation
@@ -303,7 +303,7 @@ internal fun KotlinStubs.generateObjCCall(
) = builder.irBlock {
val resolved = method.resolveFakeOverride(allowAbstract = true)?: method
val exceptionMode = ForeignExceptionMode.byValue(
resolved.module.konanLibrary?.manifestProperties
resolved.konanLibrary?.manifestProperties
?.getProperty(ForeignExceptionMode.manifestKey)
)
@@ -10,8 +10,6 @@ import org.jetbrains.kotlin.backend.konan.RuntimeNames
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.klibModuleOrigin
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.OverridingUtil
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
@@ -156,5 +154,3 @@ internal val DeclarationDescriptor.isExpectMember: Boolean
internal val DeclarationDescriptor.isSerializableExpectClass: Boolean
get() = this is ClassDescriptor && ExpectedActualDeclarationChecker.shouldGenerateExpectClass(this)
val ModuleDescriptor.konanLibrary get() = (this.klibModuleOrigin as? DeserializedKlibModuleOrigin)?.library
@@ -7,9 +7,17 @@ package org.jetbrains.kotlin.backend.konan.ir
import org.jetbrains.kotlin.backend.common.atMostOne
import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_INLINE_CLASS_SPECIAL_FUNCTION
import org.jetbrains.kotlin.backend.konan.descriptors.isInteropLibrary
import org.jetbrains.kotlin.backend.konan.llvm.KonanMetadata
import org.jetbrains.kotlin.backend.konan.serialization.KonanFileMetadataSource
import org.jetbrains.kotlin.backend.konan.serialization.KonanIrModuleFragmentImpl
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.klibModuleOrigin
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyDeclarationBase
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConst
@@ -23,6 +31,7 @@ import org.jetbrains.kotlin.ir.types.IdSignatureValues
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.isMarkedNullable
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -101,3 +110,23 @@ fun buildSimpleAnnotation(irBuiltIns: IrBuiltIns, startOffset: Int, endOffset: I
internal fun IrExpression.isBoxOrUnboxCall() =
(this is IrCall && symbol.owner.origin == DECLARATION_ORIGIN_INLINE_CLASS_SPECIAL_FUNCTION)
val ModuleDescriptor.konanLibrary get() = (this.klibModuleOrigin as? DeserializedKlibModuleOrigin)?.library
val IrModuleFragment.konanLibrary get() =
(this as? KonanIrModuleFragmentImpl)?.konanLibrary ?: descriptor.konanLibrary
val IrFile.konanLibrary get() =
(metadata as? KonanFileMetadataSource)?.module?.konanLibrary ?: packageFragmentDescriptor.containingDeclaration.konanLibrary
val IrDeclaration.konanLibrary: KotlinLibrary? get() {
((this as? IrMetadataSourceOwner)?.metadata as? KonanMetadata)?.let { return it.konanLibrary }
val result = when (val parent = parent) {
is IrFile -> parent.konanLibrary
is IrPackageFragment -> parent.packageFragmentDescriptor.containingDeclaration.konanLibrary
is IrDeclaration -> parent.konanLibrary
else -> TODO("Unexpected declaration parent: $parent")
}
if (this is IrMetadataSourceOwner && this !is IrLazyDeclarationBase)
metadata = KonanMetadata(metadata?.name, result)
return result
}
fun IrDeclaration.isFromInteropLibrary() = konanLibrary?.isInteropLibrary() == true
@@ -636,4 +636,4 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
val llvmVector128 = vector128Type
}
class IrStaticInitializer(val module: ModuleDescriptor, val initializer: LLVMValueRef)
class IrStaticInitializer(val konanLibrary: KotlinLibrary?, val initializer: LLVMValueRef)
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.descriptors.*
import org.jetbrains.kotlin.backend.konan.ir.*
import org.jetbrains.kotlin.backend.konan.llvm.coverage.LLVMCoverageInstrumentation
import org.jetbrains.kotlin.backend.konan.serialization.KonanIrModuleFragmentImpl
import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
@@ -32,6 +33,7 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.konan.ForeignExceptionMode
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.konan.target.Family
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
@@ -323,7 +325,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
context.cAdapterGenerator.generateBindings(codegen)
}
private fun runAndProcessInitializers(module: ModuleDescriptor, f: () -> Unit) {
private fun runAndProcessInitializers(konanLibrary: KotlinLibrary?, f: () -> Unit) {
// TODO: collect those two in one place.
context.llvm.fileInitializers.clear()
context.llvm.fileUsesThreadLocalObjects = false
@@ -337,7 +339,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
// Create global initialization records.
val initNode = createInitNode(createInitBody())
context.llvm.irStaticInitializers.add(IrStaticInitializer(module, createInitCtor(initNode)))
context.llvm.irStaticInitializers.add(IrStaticInitializer(konanLibrary, createInitCtor(initNode)))
}
//-------------------------------------------------------------------------//
@@ -355,7 +357,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
initializeCachedBoxes(context)
declaration.acceptChildrenVoid(this)
runAndProcessInitializers(declaration.descriptor) {
runAndProcessInitializers(null) {
// Note: it is here because it also generates some bitcode.
context.objCExport.generate(codegen)
@@ -510,7 +512,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
override fun visitFile(declaration: IrFile) {
@Suppress("UNCHECKED_CAST")
using(FileScope(declaration)) {
runAndProcessInitializers(declaration.packageFragmentDescriptor.module) {
runAndProcessInitializers(declaration.konanLibrary) {
declaration.acceptChildrenVoid(this)
}
}
@@ -2424,7 +2426,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
}
context.llvm.irStaticInitializers.forEach {
val library = it.module.konanLibrary
val library = it.konanLibrary
val initializers = libraryToInitializers[library]
?: error("initializer for not included library ${library?.libraryFile}")
@@ -15,17 +15,14 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
internal fun createLlvmDeclarations(context: Context): LlvmDeclarations {
val generator = DeclarationsGeneratorVisitor(context)
context.ir.irModule.acceptChildrenVoid(generator)
return with(generator) {
LlvmDeclarations(
functions, classes, fields, staticFields, uniques
)
}
return LlvmDeclarations(generator.uniques)
}
// Please note, that llvmName is part of the ABI, and cannot be liberally changed.
@@ -34,22 +31,17 @@ enum class UniqueKind(val llvmName: String) {
EMPTY_ARRAY("theEmptyArray")
}
internal class LlvmDeclarations(
private val functions: Map<IrFunction, FunctionLlvmDeclarations>,
private val classes: Map<IrClass, ClassLlvmDeclarations>,
private val fields: Map<IrField, FieldLlvmDeclarations>,
private val staticFields: Map<IrField, StaticFieldLlvmDeclarations>,
private val unique: Map<UniqueKind, UniqueLlvmDeclarations>) {
internal class LlvmDeclarations(private val unique: Map<UniqueKind, UniqueLlvmDeclarations>) {
fun forFunction(function: IrFunction) = forFunctionOrNull(function) ?: with(function){error("$name in $file/${parent.fqNameForIrSerialization}")}
fun forFunctionOrNull(function: IrFunction) = functions[function]
fun forFunctionOrNull(function: IrFunction) = (function.metadata as? CodegenFunctionMetadata)?.llvm
fun forClass(irClass: IrClass) = classes[irClass] ?:
fun forClass(irClass: IrClass) = (irClass.metadata as? CodegenClassMetadata)?.llvm ?:
error(irClass.descriptor.toString())
fun forField(field: IrField) = fields[field] ?:
fun forField(field: IrField) = (field.metadata as? CodegenInstanceFieldMetadata)?.llvm ?:
error(field.descriptor.toString())
fun forStaticField(field: IrField) = staticFields[field] ?:
fun forStaticField(field: IrField) = (field.metadata as? CodegenStaticFieldMetadata)?.llvm ?:
error(field.descriptor.toString())
fun forSingleton(irClass: IrClass) = forClass(irClass).singletonDeclarations ?:
@@ -100,10 +92,6 @@ private fun ContextUtils.createClassBodyType(name: String, fields: List<IrField>
private class DeclarationsGeneratorVisitor(override val context: Context) :
IrElementVisitorVoid, ContextUtils {
val functions = mutableMapOf<IrFunction, FunctionLlvmDeclarations>()
val classes = mutableMapOf<IrClass, ClassLlvmDeclarations>()
val fields = mutableMapOf<IrField, FieldLlvmDeclarations>()
val staticFields = mutableMapOf<IrField, StaticFieldLlvmDeclarations>()
val uniques = mutableMapOf<UniqueKind, UniqueLlvmDeclarations>()
private class Namer(val prefix: String) {
@@ -157,7 +145,10 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
override fun visitClass(declaration: IrClass) {
if (declaration.requiresRtti()) {
this.classes[declaration] = createClassDeclarations(declaration)
val classLlvmDeclarations = createClassDeclarations(declaration)
val metadata = declaration.metadata as? CodegenClassMetadata
?: CodegenClassMetadata(declaration).also { declaration.metadata = it }
metadata.llvm = classLlvmDeclarations
}
super.visitClass(declaration)
}
@@ -311,12 +302,16 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
val containingClass = declaration.parent as? IrClass
if (containingClass != null) {
if (!containingClass.requiresRtti()) return
val classDeclarations = this.classes[containingClass] ?:
error(containingClass.descriptor.toString())
val classDeclarations = (containingClass.metadata as? CodegenClassMetadata)?.llvm
?: error(containingClass.descriptor.toString())
val allFields = context.getLayoutBuilder(containingClass).fields
this.fields[declaration] = FieldLlvmDeclarations(
allFields.indexOf(declaration) + 1, // First field is ObjHeader.
classDeclarations.bodyType
declaration.metadata = CodegenInstanceFieldMetadata(
declaration.metadata?.name,
containingClass.konanLibrary,
FieldLlvmDeclarations(
allFields.indexOf(declaration) + 1, // First field is ObjHeader.
classDeclarations.bodyType
)
)
} else {
// Fields are module-private, so we use internal name:
@@ -327,7 +322,11 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
addKotlinGlobal(name, getLLVMType(declaration.type), isExported = false)
}
this.staticFields[declaration] = StaticFieldLlvmDeclarations(storage)
declaration.metadata = CodegenStaticFieldMetadata(
declaration.metadata?.name,
declaration.konanLibrary,
StaticFieldLlvmDeclarations(storage)
)
}
}
@@ -346,7 +345,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
if (declaration.isTypedIntrinsic || declaration.isObjCBridgeBased()
// All call-sites to external accessors to interop properties
// are lowered by InteropLowering.
|| (declaration.isAccessor && declaration.isFromMetadataInteropLibrary())
|| (declaration.isAccessor && declaration.isFromInteropLibrary())
|| declaration.annotations.hasAnnotation(RuntimeNames.cCall)) return
context.llvm.externalFunction(declaration.symbolName, llvmFunctionType,
@@ -374,6 +373,36 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
function
}
this.functions[declaration] = FunctionLlvmDeclarations(llvmFunction)
declaration.metadata = CodegenFunctionMetadata(
declaration.metadata?.name,
declaration.konanLibrary,
FunctionLlvmDeclarations(llvmFunction)
)
}
}
internal open class KonanMetadata(override val name: Name?, val konanLibrary: KotlinLibrary?) : MetadataSource
internal class CodegenClassMetadata(irClass: IrClass)
: KonanMetadata(irClass.metadata?.name, irClass.konanLibrary), MetadataSource.Class {
var layoutBuilder: ClassLayoutBuilder? = null
var llvm: ClassLlvmDeclarations? = null
}
private class CodegenFunctionMetadata(
name: Name?,
konanLibrary: KotlinLibrary?,
val llvm: FunctionLlvmDeclarations
) : KonanMetadata(name, konanLibrary), MetadataSource.Function
private class CodegenInstanceFieldMetadata(
name: Name?,
konanLibrary: KotlinLibrary?,
val llvm: FieldLlvmDeclarations
) : KonanMetadata(name, konanLibrary), MetadataSource.Property
private class CodegenStaticFieldMetadata(
name: Name?,
konanLibrary: KotlinLibrary?,
val llvm: StaticFieldLlvmDeclarations
) : KonanMetadata(name, konanLibrary), MetadataSource.Property
@@ -53,6 +53,10 @@ internal class WorkersBridgesBuilding(val context: Context) : DeclarationContain
private fun buildWorkerBridges(declaration: IrDeclaration): List<IrFunction> {
val bridges = mutableListOf<IrFunction>()
declaration.transformChildrenVoid(object: IrElementTransformerVoid() {
override fun visitClass(declaration: IrClass): IrStatement {
// Skip nested.
return declaration
}
override fun visitCall(expression: IrCall): IrExpression {
expression.transformChildrenVoid(this)
@@ -133,20 +137,24 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
override fun lower(irClass: IrClass) {
val builtBridges = mutableSetOf<IrSimpleFunction>()
irClass.simpleFunctions()
.forEach { function ->
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.function
}
for (function in irClass.simpleFunctions()) {
val set = mutableSetOf<BridgeDirections>()
for (overriddenFunction in function.allOverriddenFunctions) {
val overriddenFunctionInfo = OverriddenFunctionInfo(function, overriddenFunction)
val bridgeDirections = overriddenFunctionInfo.bridgeDirections
if (!bridgeDirections.allNotNeeded() && overriddenFunctionInfo.canBeCalledVirtually
&& !overriddenFunctionInfo.inheritsBridge && set.add(bridgeDirections)) {
buildBridge(overriddenFunctionInfo, irClass)
builtBridges += function
}
}
}
irClass.transformChildrenVoid(object: IrElementTransformerVoid() {
override fun visitClass(declaration: IrClass): IrStatement {
// Skip nested.
return declaration
}
override fun visitFunction(declaration: IrFunction): IrStatement {
declaration.transformChildrenVoid(this)
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENUM
import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType
import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl
@@ -124,19 +125,25 @@ internal class EnumUsageLowering(val context: Context)
}
}
internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
internal class EnumClassLowering(val context: Context) : FileLoweringPass {
fun run(irFile: IrFile) {
// EnumWhenLowering should be performed before EnumUsageLowering because
// the latter performs lowering of IrGetEnumValue
EnumWhenLowering(context).lower(irFile)
runOnFilePostfix(irFile)
lower(irFile)
EnumUsageLowering(context).lower(irFile)
}
override fun lower(irClass: IrClass) {
if (irClass.kind != ClassKind.ENUM_CLASS) return
EnumClassTransformer(irClass).run()
override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitClass(declaration: IrClass): IrStatement {
declaration.transformChildrenVoid()
if (declaration.kind == ClassKind.ENUM_CLASS)
EnumClassTransformer(declaration).run()
return declaration
}
})
}
private inner class EnumClassTransformer(val irClass: IrClass) {
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.lower.callsSuper
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrExpression
@@ -87,6 +88,11 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
private fun lowerOuterThisReferences() {
irClass.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
override fun visitClassNew(declaration: IrClass): IrStatement {
// Skip nested.
return declaration
}
override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid(this)
@@ -14,8 +14,6 @@ import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.cgen.*
import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions
import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.konan.ir.*
import org.jetbrains.kotlin.backend.konan.ir.companionObject
@@ -811,7 +809,7 @@ private class InteropTransformer(val context: Context, override val irFile: IrFi
private fun tryGenerateInteropConstantRead(expression: IrCall): IrExpression? {
val function = expression.symbol.owner
if (!function.descriptor.module.isFromInteropLibrary()) return null
if (!function.isFromInteropLibrary()) return null
if (!function.isGetter) return null
val constantProperty = (function as? IrSimpleFunction)
@@ -870,7 +868,7 @@ private class InteropTransformer(val context: Context, override val irFile: IrFi
if (function.annotations.hasAnnotation(RuntimeNames.cCall)) {
context.llvmImports.add(function.llvmSymbolOrigin)
val exceptionMode = ForeignExceptionMode.byValue(
function.module.konanLibrary?.manifestProperties?.getProperty(ForeignExceptionMode.manifestKey)
function.konanLibrary?.manifestProperties?.getProperty(ForeignExceptionMode.manifestKey)
)
return generateWithStubs { generateCCall(expression, builder, isInvoke = false, exceptionMode) }
}
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.backend.konan.KonanBackendContext
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
@@ -61,6 +62,11 @@ internal class VarargInjectionLowering constructor(val context: KonanBackendCont
private fun lower(owner: IrSymbol, element: IrElement?) {
element?.transformChildrenVoid(object: IrElementTransformerVoid() {
override fun visitClass(declaration: IrClass): IrStatement {
// Skip nested.
return declaration
}
val transformer = this
private fun replaceEmptyParameterWithEmptyArray(expression: IrFunctionAccessExpression) {
@@ -24,22 +24,24 @@ import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolD
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer
import org.jetbrains.kotlin.backend.konan.CachedLibraries
import org.jetbrains.kotlin.backend.konan.descriptors.isInteropLibrary
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs
import org.jetbrains.kotlin.backend.konan.ir.konanLibrary
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib
import org.jetbrains.kotlin.descriptors.konan.klibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.kotlinLibrary
import org.jetbrains.kotlin.ir.builders.TranslationPluginContext
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
import org.jetbrains.kotlin.ir.descriptors.IrAbstractFunctionFactory
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrFileSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrPublicSymbolBase
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.name.ClassId
@@ -107,8 +109,13 @@ internal class KonanIrLinker(
return KonanModuleDeserializer(moduleDescriptor, klib ?: error("Expecting kotlin library"), strategy)
}
private inner class KonanModuleDeserializer(moduleDescriptor: ModuleDescriptor, klib: IrLibrary, strategy: DeserializationStrategy):
KotlinIrLinker.BasicIrModuleDeserializer(moduleDescriptor, klib, strategy)
private inner class KonanModuleDeserializer(
moduleDescriptor: ModuleDescriptor,
klib: IrLibrary,
strategy: DeserializationStrategy
): KotlinIrLinker.BasicIrModuleDeserializer(moduleDescriptor, klib, strategy) {
override val moduleFragment: IrModuleFragment = KonanIrModuleFragmentImpl(moduleDescriptor, builtIns, emptyList())
}
private inner class KonanInteropModuleDeserializer(
moduleDescriptor: ModuleDescriptor,
@@ -160,7 +167,7 @@ internal class KonanIrLinker(
return symbolOwner.symbol
}
override val moduleFragment: IrModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns)
override val moduleFragment: IrModuleFragment = KonanIrModuleFragmentImpl(moduleDescriptor, builtIns)
override val moduleDependencies: Collection<IrModuleDeserializer> = listOfNotNull(forwardDeclarationDeserializer)
}
@@ -208,7 +215,7 @@ internal class KonanIrLinker(
return declaredDeclaration.getOrPut(idSig) { buildForwardDeclarationStub(descriptor) }.symbol
}
override val moduleFragment: IrModuleFragment = IrModuleFragmentImpl(moduleDescriptor, builtIns)
override val moduleFragment: IrModuleFragment = KonanIrModuleFragmentImpl(moduleDescriptor, builtIns)
override val moduleDependencies: Collection<IrModuleDeserializer> = emptyList()
}
@@ -226,3 +233,34 @@ internal class KonanIrLinker(
override val irBuiltIns: IrBuiltIns
):TranslationPluginContext
}
class KonanIrModuleFragmentImpl(
override val descriptor: ModuleDescriptor,
override val irBuiltins: IrBuiltIns,
files: List<IrFile> = emptyList(),
) : IrModuleFragment() {
override val name: Name get() = descriptor.name // TODO
override val files: MutableList<IrFile> = files.toMutableList()
val konanLibrary = (descriptor.klibModuleOrigin as? DeserializedKlibModuleOrigin)?.library
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitModuleFragment(this, data)
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
files.forEach { it.accept(visitor, data) }
}
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
files.forEachIndexed { i, irFile ->
files[i] = irFile.transform(transformer, data)
}
}
}
fun IrModuleFragment.toKonanModule() = KonanIrModuleFragmentImpl(descriptor, irBuiltins, files)
class KonanFileMetadataSource(val module: KonanIrModuleFragmentImpl) : MetadataSource.File {
override val name: Name? = null
}