Skip to content
This repository has been archived by the owner on Aug 10, 2021. It is now read-only.

Commit

Permalink
Merge branch 'master' into vi/fix_termination_race
Browse files Browse the repository at this point in the history
  • Loading branch information
knebekaizer committed Jun 19, 2020
2 parents e37e351 + 6008d12 commit 978c385
Show file tree
Hide file tree
Showing 67 changed files with 972 additions and 492 deletions.
Expand Up @@ -33,7 +33,8 @@ fun createInteropLibrary(
manifest: Properties,
dependencies: List<KotlinLibrary>,
nopack: Boolean,
shortName: String?
shortName: String?,
staticLibraries: List<String>
) {
val version = KotlinLibraryVersioning(
libraryVersion = null,
Expand All @@ -58,6 +59,7 @@ fun createInteropLibrary(
nativeBitcodeFiles.forEach(this::addNativeBitcode)
addManifestAddend(manifest)
addLinkDependencies(dependencies)
staticLibraries.forEach(this::addIncludedBinary)
commit()
}
}
Expand Down
Expand Up @@ -377,7 +377,8 @@ private fun processCLib(flavorName: String, cinteropArguments: CInteropArguments
manifest = def.manifestAddendProperties,
dependencies = stdlibDependency + imports.requiredLibraries.toList(),
nopack = cinteropArguments.nopack,
shortName = cinteropArguments.shortModuleName
shortName = cinteropArguments.shortModuleName,
staticLibraries = staticLibraries
)
return null
}
Expand Down
13 changes: 9 additions & 4 deletions OBJC_INTEROP.md
Expand Up @@ -30,8 +30,8 @@ The table below shows how Kotlin concepts are mapped to Swift/Objective-C and vi
| `constructor`/`create` | Initializer | Initializer | [note](#initializers) |
| Property | Property | Property | [note](#top-level-functions-and-properties) [note](#setters)|
| Method | Method | Method | [note](#top-level-functions-and-properties) [note](#method-names-translation) |
| `suspend` -> | `completionHandler:` | | |
| `@Throws` | `throws` | `error:(NSError**)error` | [note](#errors-and-exceptions) |
| `suspend` -> | `completionHandler:` | | [note](#errors-and-exceptions) |
| `@Throws fun` | `throws` | `error:(NSError**)error` | [note](#errors-and-exceptions) |
| Extension | Extension | Category member | [note](#category-members) |
| `companion` member <- | Class method or property | Class method or property | |
| `null` | `nil` | `nil` | |
Expand Down Expand Up @@ -133,15 +133,20 @@ Swift has only checked errors. So if Swift or Objective-C code calls a Kotlin me
which throws an exception to be handled, then the Kotlin method should be marked
with a `@Throws` annotation specifying a list of "expected" exception classes.

When compiling to Objective-C/Swift framework, functions having or inheriting
When compiling to Objective-C/Swift framework, non-`suspend` functions having or inheriting
`@Throws` annotation are represented as `NSError*`-producing methods in Objective-C
and as `throws` methods in Swift.
and as `throws` methods in Swift. Representations for `suspend` functions always have
`NSError*`/`Error` parameter in completion handler.

When Kotlin function called from Swift/Objective-C code throws an exception
which is an instance of one of the `@Throws`-specified classes or their subclasses,
it is propagated as `NSError`. Other Kotlin exceptions reaching Swift/Objective-C
are considered unhandled and cause program termination.

`suspend` functions without `@Throws` propagate only
`CancellationException` as `NSError`. Non-`suspend` functions without `@Throws`
don't propagate Kotlin exceptions at all.

Note that the opposite reversed translation is not implemented yet:
Swift/Objective-C error-throwing methods aren't imported to Kotlin as
exception-throwing.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -12,7 +12,7 @@ without the need to ship an additional execution runtime.

Prerequisites:
* install JDK for your platform, instead of JRE. The build requires ```tools.jar```, which is not included in JRE;
* on macOS install Xcode 11 (Xcode 11.4 is required to compile Kotlin/Native from sources)
* on macOS install Xcode 11 (Xcode 11.5 is required to compile Kotlin/Native from sources)
* on Fedora 26+ ```yum install ncurses-compat-libs``` may be needed
* on recent Ubuntu ```apt install libncurses5``` is needed

Expand Down
Expand Up @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.descriptors.IrAbstractFunctionFactory
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.linkage.IrProvider
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
Expand Down
Expand Up @@ -848,7 +848,20 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
output("typedef unsigned long long ${prefix}_KULong;")
output("typedef float ${prefix}_KFloat;")
output("typedef double ${prefix}_KDouble;")
output("typedef float __attribute__ ((__vector_size__ (16))) ${prefix}_KVector128;")

val typedef_KVector128 = "typedef float __attribute__ ((__vector_size__ (16))) ${prefix}_KVector128;"
if (context.config.target.family == Family.MINGW) {
// Separate `output` for each line to ensure Windows EOL (LFCR), otherwise generated file will have inconsistent line ending.
output("#ifndef _MSC_VER")
output(typedef_KVector128)
output("#else")
output("#include <xmmintrin.h>")
output("typedef __m128 ${prefix}_KVector128;")
output("#endif")
} else {
output(typedef_KVector128)
}

output("typedef void* ${prefix}_KNativePtr;")
output("struct ${prefix}_KType;")
output("typedef struct ${prefix}_KType ${prefix}_KType;")
Expand Down
Expand Up @@ -5,6 +5,7 @@

package org.jetbrains.kotlin.backend.konan

import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
Expand Down Expand Up @@ -49,11 +50,15 @@ class CacheSupport(
library to cachePath
}

val optimized = configuration.getBoolean(KonanConfigKeys.OPTIMIZATION)
if (optimized && (explicitCacheFiles.isNotEmpty() || implicitCacheDirectories.isNotEmpty()))
configuration.report(CompilerMessageSeverity.WARNING, "Cached libraries will not be used for optimized compilation")

CachedLibraries(
target = target,
allLibraries = allLibraries,
explicitCaches = explicitCaches,
implicitCacheDirectories = implicitCacheDirectories
explicitCaches = if (optimized) emptyMap() else explicitCaches,
implicitCacheDirectories = if (optimized) emptyList() else implicitCacheDirectories
)
}

Expand Down
Expand Up @@ -254,7 +254,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
val layoutBuilders = mutableMapOf<IrClass, ClassLayoutBuilder>()

fun getLayoutBuilder(irClass: IrClass) = layoutBuilders.getOrPut(irClass) {
ClassLayoutBuilder(irClass, this)
ClassLayoutBuilder(irClass, this, isLowered = shouldLower(this, irClass))
}

lateinit var globalHierarchyAnalysisResult: GlobalHierarchyAnalysisResult
Expand Down
Expand Up @@ -5,7 +5,7 @@

package org.jetbrains.kotlin.backend.konan

import org.jetbrains.kotlin.backend.common.ir.addFakeOverrides
import org.jetbrains.kotlin.backend.common.ir.addFakeOverridesViaIncorrectHeuristic
import org.jetbrains.kotlin.backend.common.ir.addSimpleDelegatingConstructor
import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
Expand Down Expand Up @@ -115,7 +115,7 @@ internal class EnumSpecialDeclarationsFactory(val context: Context) {
)

implObject.superTypes += context.irBuiltIns.anyType
implObject.addFakeOverrides()
implObject.addFakeOverridesViaIncorrectHeuristic()

val itemGetterSymbol = symbols.array.functions.single { it.descriptor.name == Name.identifier("get") }
val enumEntriesMap = enumClass.declarations
Expand Down
Expand Up @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.symbols.IrSymbol
Expand Down Expand Up @@ -233,6 +234,7 @@ internal val psiToIrPhase = konanUnitPhase(
generatorContext,
environment.getSourceFiles(),
irProviders,
pluginExtensions,
// TODO: This is a hack to allow platform libs to build in reasonable time.
// referenceExpectsForUsedActuals() appears to be quadratic in time because of
// how ExpectedActualResolver is implemented.
Expand All @@ -256,7 +258,10 @@ internal val psiToIrPhase = konanUnitPhase(
linker.modules.values.forEach{ fakeOverrideChecker.check(it) }

irModule = module

// Note: coupled with [shouldLower] below.
irModules = linker.modules.filterValues { llvmModuleSpecification.containsModule(it) }

ir.symbols = symbols

functionIrClassFactory.module =
Expand All @@ -268,6 +273,11 @@ internal val psiToIrPhase = konanUnitPhase(
prerequisite = setOf(createSymbolTablePhase)
)

// Coupled with [psiToIrPhase] logic above.
internal fun shouldLower(context: Context, declaration: IrDeclaration): Boolean {
return context.llvmModuleSpecification.containsDeclaration(declaration)
}

internal val destroySymbolTablePhase = konanUnitPhase(
op = {
this.symbolTable = null // TODO: invalidate symbolTable itself.
Expand Down
@@ -1,6 +1,6 @@
package org.jetbrains.kotlin.backend.konan.cgen

import org.jetbrains.kotlin.backend.common.ir.addFakeOverrides
import org.jetbrains.kotlin.backend.common.ir.addFakeOverridesViaIncorrectHeuristic
import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter
import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations
import org.jetbrains.kotlin.backend.common.ir.simpleFunctions
Expand Down Expand Up @@ -1318,7 +1318,7 @@ private class ObjCBlockPointerValuePassing(
+irReturn(callBlock(blockPointer, arguments))
}

irClass.addFakeOverrides()
irClass.addFakeOverridesViaIncorrectHeuristic()

stubs.addKotlin(irClass)
return constructor
Expand Down
Expand Up @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.konan.ir.*
import org.jetbrains.kotlin.backend.konan.llvm.functionName
import org.jetbrains.kotlin.backend.konan.llvm.llvmType
import org.jetbrains.kotlin.backend.konan.llvm.localHash
import org.jetbrains.kotlin.backend.konan.lower.InnerClassLowering
import org.jetbrains.kotlin.backend.konan.lower.bridgeTarget
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrElement
Expand Down Expand Up @@ -260,7 +261,7 @@ internal class GlobalHierarchyAnalysis(val context: Context, val irModule: IrMod
}
}

internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context) {
internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context, val isLowered: Boolean) {
private val DEBUG = 0

private inline fun DEBUG_OUTPUT(severity: Int, block: () -> Unit) {
Expand Down Expand Up @@ -432,7 +433,15 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context) {
* Fields declared in the class.
*/
private fun getDeclaredFields(): List<IrField> {
val fields = irClass.declarations.mapNotNull {
val declarations: List<IrDeclaration> = if (irClass.isInner && !isLowered) {
// Note: copying to avoid mutation of the original class.
irClass.declarations.toMutableList()
.also { InnerClassLowering.addOuterThisField(it, irClass, context) }
} else {
irClass.declarations
}

val fields = declarations.mapNotNull {
when (it) {
is IrField -> it.takeIf { it.isReal }
is IrProperty -> it.takeIf { it.isReal }?.backingField
Expand Down
Expand Up @@ -246,7 +246,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
}

functionReferenceClass.superTypes += superTypes
functionReferenceClass.addFakeOverrides()
functionReferenceClass.addFakeOverridesViaIncorrectHeuristic()

return BuiltFunctionReference(functionReferenceClass, constructor)
}
Expand Down
Expand Up @@ -9,9 +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.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
Expand All @@ -20,7 +18,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.parentAsClass
Expand All @@ -32,6 +29,14 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
InnerClassTransformer(irClass).lowerInnerClass()
}

companion object {
fun addOuterThisField(declarations: MutableList<IrDeclaration>, irClass: IrClass, context: Context): IrField {
val outerThisField = context.specialDeclarationsFactory.getOuterThisField(irClass)
declarations += outerThisField
return outerThisField
}
}

private inner class InnerClassTransformer(val irClass: IrClass) {
lateinit var outerThisFieldSymbol: IrFieldSymbol

Expand All @@ -44,8 +49,8 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
}

private fun createOuterThisField() {
irClass.declarations += context.specialDeclarationsFactory.getOuterThisField(irClass)
outerThisFieldSymbol = context.specialDeclarationsFactory.getOuterThisField(irClass).symbol
val outerThisField = addOuterThisField(irClass.declarations, irClass, context)
outerThisFieldSymbol = outerThisField.symbol
}

private fun lowerConstructors() {
Expand Down
Expand Up @@ -5,14 +5,20 @@

package org.jetbrains.kotlin.backend.konan.lower

import org.jetbrains.kotlin.backend.common.ScopeWithIr
import org.jetbrains.kotlin.backend.common.lower.SingleAbstractMethodLowering
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.util.render

internal class NativeSingleAbstractMethodLowering(context: Context) : SingleAbstractMethodLowering(context) {
override fun getWrapperVisibility(expression: IrTypeOperatorCall, scopes: List<ScopeWithIr>) =
Visibilities.PRIVATE

override fun getSuperTypeForWrapper(typeOperand: IrType): IrType {
return typeOperand.classOrNull?.defaultType ?: error("Unsupported SAM conversion: ${typeOperand.render()}")
}
Expand Down
Expand Up @@ -5,10 +5,7 @@

package org.jetbrains.kotlin.backend.konan.lower

import org.jetbrains.kotlin.backend.common.ir.addFakeOverrides
import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter
import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations
import org.jetbrains.kotlin.backend.common.ir.simpleFunctions
import org.jetbrains.kotlin.backend.common.ir.*
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.reportWarning
import org.jetbrains.kotlin.backend.konan.Context
Expand All @@ -35,6 +32,7 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.addChild
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
Expand Down Expand Up @@ -529,7 +527,7 @@ internal class TestProcessor (val context: Context) {
companionGetter?.let { declarations += it }

superTypes += symbols.baseClassSuite.typeWith(listOf(testClassType, testCompanionType))
addFakeOverrides()
addFakeOverridesViaIncorrectHeuristic()
}
}
//endregion
Expand Down
Expand Up @@ -33,10 +33,12 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass
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.types.classOrNull
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.library.IrLibrary
import org.jetbrains.kotlin.library.KotlinLibrary
Expand Down Expand Up @@ -136,6 +138,19 @@ internal class KonanIrLinker(

val symbolOwner = stubGenerator.generateMemberStub(descriptor) as IrSymbolOwner

// Make sure all class hierarchy is available, otherwise we won't be able
// to build fake overrides.
// TODO: we actually only need it to tell if class .isObjCClass
// So if we could come up with a way to tell without looking at class hierarchy
// this hack could be erased.
if (symbolOwner is IrLazyClass) {
symbolOwner.superTypes.forEach {
it.classOrNull?.let {
symbolTable.referenceClassFromLinker(it.descriptor, it.signature)
}
}
}

return symbolOwner.symbol
}

Expand Down Expand Up @@ -165,7 +180,7 @@ internal class KonanIrLinker(

private fun resolveDescriptor(idSig: IdSignature): ClassDescriptor =
with(idSig as IdSignature.PublicSignature) {
val classId = ClassId(packageFqn, declarationFqn, false)
val classId = ClassId(packageFqName(), FqName(declarationFqName), false)
moduleDescriptor.findClassAcrossModuleDependencies(classId) ?: error("No declaration found with $idSig")
}

Expand Down Expand Up @@ -216,4 +231,4 @@ internal class KonanIrLinker(
.filter { !it.key.isForwardDeclarationModule && it.value.moduleDescriptor !== currentModule }
.forEach { this.put(it.key.konanLibrary!!.libraryName, it.value.moduleFragment) }
}
}
}

0 comments on commit 978c385

Please sign in to comment.