Rework entry point selector. (#3266)
This commit is contained in:
@@ -178,8 +178,7 @@ final List<File> stdLibSrc = [
|
||||
project(':Interop:Runtime').file('src/main/kotlin'),
|
||||
project(':Interop:Runtime').file('src/native/kotlin'),
|
||||
project(':Interop:JsRuntime').file('src/main/kotlin'),
|
||||
project(':runtime').file('src/main/kotlin'),
|
||||
project(':runtime').file('src/launcher/kotlin')
|
||||
project(':runtime').file('src/main/kotlin')
|
||||
]
|
||||
|
||||
// These files are built before the 'dist' is complete,
|
||||
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
||||
import org.jetbrains.kotlin.backend.konan.ir.buildSimpleAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTryImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.typeWith
|
||||
import org.jetbrains.kotlin.ir.util.irCatch
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
internal fun makeEntryPoint(context: Context): IrFunction {
|
||||
val entryPointDescriptor = WrappedSimpleFunctionDescriptor()
|
||||
val actualMain = context.ir.symbols.entryPoint!!.owner
|
||||
val entryPoint = IrFunctionImpl(
|
||||
actualMain.startOffset,
|
||||
actualMain.startOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
IrSimpleFunctionSymbolImpl(entryPointDescriptor),
|
||||
Name.identifier("Konan_start"),
|
||||
Visibilities.PRIVATE,
|
||||
Modality.FINAL,
|
||||
context.irBuiltIns.intType,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = false
|
||||
).also { function ->
|
||||
function.valueParameters.add(WrappedValueParameterDescriptor().let {
|
||||
IrValueParameterImpl(
|
||||
actualMain.startOffset, actualMain.startOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
IrValueParameterSymbolImpl(it),
|
||||
Name.identifier("args"),
|
||||
index = 0,
|
||||
varargElementType = null,
|
||||
isCrossinline = false,
|
||||
type = context.irBuiltIns.arrayClass.typeWith(context.irBuiltIns.stringType),
|
||||
isNoinline = false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
parent = function
|
||||
}
|
||||
})
|
||||
}
|
||||
entryPointDescriptor.bind(entryPoint)
|
||||
entryPoint.annotations += buildSimpleAnnotation(context.irBuiltIns,
|
||||
actualMain.startOffset, actualMain.startOffset,
|
||||
context.ir.symbols.exportForCppRuntime.owner, "Konan_start")
|
||||
|
||||
val builder = context.createIrBuilder(entryPoint.symbol)
|
||||
entryPoint.body = builder.irBlockBody(entryPoint) {
|
||||
+IrTryImpl(
|
||||
startOffset = actualMain.startOffset,
|
||||
endOffset = actualMain.startOffset,
|
||||
type = context.irBuiltIns.nothingType
|
||||
).apply {
|
||||
tryResult = irBlock {
|
||||
+irCall(actualMain).apply {
|
||||
if (actualMain.valueParameters.size != 0)
|
||||
putValueArgument(0, irGet(entryPoint.valueParameters[0]))
|
||||
}
|
||||
+irReturn(irInt(0))
|
||||
}
|
||||
catches += irCatch(context.irBuiltIns.throwableType).apply {
|
||||
result = irBlock {
|
||||
+irCall(context.ir.symbols.onUnhandledException).apply {
|
||||
putValueArgument(0, irGet(catchParameter))
|
||||
}
|
||||
+irReturn(irInt(1))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return entryPoint
|
||||
}
|
||||
+18
@@ -18,6 +18,8 @@ import org.jetbrains.kotlin.descriptors.konan.isKonanStdlib
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.addChild
|
||||
import org.jetbrains.kotlin.ir.util.file
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
||||
@@ -320,6 +322,20 @@ internal val dependenciesLowerPhase = SameTypeNamedPhaseWrapper(
|
||||
}
|
||||
})
|
||||
|
||||
internal val entryPointPhase = SameTypeNamedPhaseWrapper(
|
||||
name = "addEntryPoint",
|
||||
description = "Add entry point for program",
|
||||
prerequisite = emptySet(),
|
||||
lower = object : CompilerPhase<Context, IrModuleFragment, IrModuleFragment> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<IrModuleFragment>,
|
||||
context: Context, input: IrModuleFragment): IrModuleFragment {
|
||||
assert(context.config.produce == CompilerOutputKind.PROGRAM)
|
||||
context.ir.symbols.entryPoint!!.owner.file.addChild(makeEntryPoint(context))
|
||||
return input
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
internal val bitcodePhase = namedIrModulePhase(
|
||||
name = "Bitcode",
|
||||
description = "LLVM Bitcode generation",
|
||||
@@ -357,6 +373,7 @@ val toplevelPhase: CompilerPhase<*, Unit, Unit> = namedUnitPhase(
|
||||
allLoweringsPhase then // Lower current module first.
|
||||
dependenciesLowerPhase then // Then lower all libraries in topological order.
|
||||
// With that we guarantee that inline functions are unlowered while being inlined.
|
||||
entryPointPhase then
|
||||
bitcodePhase then
|
||||
verifyBitcodePhase then
|
||||
printBitcodePhase then
|
||||
@@ -384,6 +401,7 @@ internal fun PhaseConfig.konanPhasesConfig(config: KonanConfig) {
|
||||
// Don't serialize anything to a final executable.
|
||||
disableUnless(serializerPhase, config.produce == CompilerOutputKind.LIBRARY)
|
||||
disableIf(dependenciesLowerPhase, config.produce == CompilerOutputKind.LIBRARY)
|
||||
disableUnless(entryPointPhase, config.produce == CompilerOutputKind.PROGRAM)
|
||||
disableIf(bitcodePhase, config.produce == CompilerOutputKind.LIBRARY)
|
||||
disableUnless(linkPhase, config.produce.isNativeBinary)
|
||||
disableIf(testProcessorPhase, getNotNull(KonanConfigKeys.GENERATE_TEST_RUNNER) == TestRunnerKind.NONE)
|
||||
|
||||
+2
@@ -114,6 +114,8 @@ internal class KonanSymbols(
|
||||
|
||||
val objCMethodImp = symbolTable.referenceClass(context.interopBuiltIns.objCMethodImp)
|
||||
|
||||
val onUnhandledException = internalFunction("OnUnhandledException")
|
||||
|
||||
val interopNativePointedGetRawPointer =
|
||||
symbolTable.referenceSimpleFunction(context.interopBuiltIns.nativePointedGetRawPointer)
|
||||
|
||||
|
||||
+3
-1
@@ -89,7 +89,9 @@ fun IrClass.companionObject() = this.declarations.filterIsInstance<IrClass>().at
|
||||
|
||||
fun buildSimpleAnnotation(irBuiltIns: IrBuiltIns, startOffset: Int, endOffset: Int,
|
||||
annotationClass: IrClass, vararg args: String): IrConstructorCall {
|
||||
val constructor = annotationClass.constructors.single()
|
||||
val constructor = annotationClass.constructors.let {
|
||||
it.singleOrNull() ?: it.single { ctor -> ctor.valueParameters.size == args.size }
|
||||
}
|
||||
return IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, constructor.returnType, constructor.symbol).apply {
|
||||
args.forEachIndexed { index, arg ->
|
||||
assert(constructor.valueParameters[index].type == irBuiltIns.stringType) {
|
||||
|
||||
-8
@@ -63,7 +63,6 @@ internal enum class IntrinsicType {
|
||||
IDENTITY,
|
||||
IMMUTABLE_BLOB,
|
||||
INIT_INSTANCE,
|
||||
SELECT_ENTRY_POINT,
|
||||
// Coroutines
|
||||
GET_CONTINUATION,
|
||||
RETURN_IF_SUSPEND,
|
||||
@@ -239,7 +238,6 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
IntrinsicType.IDENTITY -> emitIdentity(args)
|
||||
IntrinsicType.GET_CONTINUATION -> emitGetContinuation()
|
||||
IntrinsicType.INTEROP_MEMORY_COPY -> emitMemoryCopy(callSite, args)
|
||||
IntrinsicType.SELECT_ENTRY_POINT -> emitEntryPointSelection(args)
|
||||
IntrinsicType.RETURN_IF_SUSPEND,
|
||||
IntrinsicType.INTEROP_BITS_TO_FLOAT,
|
||||
IntrinsicType.INTEROP_BITS_TO_DOUBLE,
|
||||
@@ -270,12 +268,6 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
private fun FunctionGenerationContext.emitIdentity(args: List<LLVMValueRef>): LLVMValueRef =
|
||||
args.single()
|
||||
|
||||
private fun FunctionGenerationContext.emitEntryPointSelection(args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val entryPoint = context.ir.symbols.entryPoint?.owner ?: return unreachable()!! // TODO: Don't put start.kt in source set unless produce=PROGRAM.
|
||||
return call(codegen.llvmFunction(entryPoint), args.take(entryPoint.valueParameters.size),
|
||||
Lifetime.IRRELEVANT, environment.exceptionHandler)
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitListOfInternal(callSite: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val varargExpression = callSite.getValueArgument(0) as IrVararg
|
||||
val vararg = args.single()
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
import kotlin.native.internal.ExportForCppRuntime
|
||||
import kotlin.native.internal.TypedIntrinsic
|
||||
import kotlin.native.internal.IntrinsicType
|
||||
|
||||
// This function is produced by the code generator given
|
||||
// the '-entry foo.bar.main' flag.
|
||||
// It calls the requested entry point.
|
||||
// The default is main(Array<String>):Unit in the root package.
|
||||
@TypedIntrinsic(IntrinsicType.SELECT_ENTRY_POINT)
|
||||
private external fun EntryPointSelector(args: Array<String>)
|
||||
|
||||
@SymbolName("OnUnhandledException")
|
||||
private external fun OnUnhandledException(throwable: Throwable)
|
||||
|
||||
@ExportForCppRuntime
|
||||
private fun Konan_start(args: Array<String>): Int {
|
||||
try {
|
||||
EntryPointSelector(args)
|
||||
// Successfully finished:
|
||||
return 0
|
||||
} catch (e: Throwable) {
|
||||
OnUnhandledException(e)
|
||||
return 1
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,6 @@ class IntrinsicType {
|
||||
const val IDENTITY = "IDENTITY"
|
||||
const val IMMUTABLE_BLOB = "IMMUTABLE_BLOB"
|
||||
const val INIT_INSTANCE = "INIT_INSTANCE"
|
||||
const val SELECT_ENTRY_POINT = "SELECT_ENTRY_POINT"
|
||||
|
||||
const val GET_CONTINUATION = "GET_CONTINUATION"
|
||||
const val RETURN_IF_SUSPEND = "RETURN_IF_SUSPEND"
|
||||
|
||||
@@ -180,4 +180,9 @@ internal fun <T> listOfInternal(vararg elements: T): List<T> {
|
||||
for (i in 0 until elements.size)
|
||||
result.add(elements[i])
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@PublishedApi
|
||||
@SymbolName("OnUnhandledException")
|
||||
external internal fun OnUnhandledException(throwable: Throwable)
|
||||
Reference in New Issue
Block a user