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 authored 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.
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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) }
}
}
}
Loading

0 comments on commit 978c385

Please sign in to comment.