Rework entry point selector. (#3266)

This commit is contained in:
Nikolay Igotti
2019-08-21 16:56:38 +03:00
committed by GitHub
parent 48a75e9a07
commit 71e1be1a5c
9 changed files with 122 additions and 43 deletions
+1 -2
View File
@@ -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,
@@ -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,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)
@@ -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)
@@ -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) {
@@ -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)