Allow entry points without args: Array<String> (#2049)

This commit is contained in:
alexander-gorshenev
2018-09-13 10:23:02 +03:00
committed by Nikolay Igotti
parent b6a01a86f1
commit 30f5eb0bfa
5 changed files with 41 additions and 11 deletions
@@ -36,16 +36,21 @@ internal fun findMainEntryPoint(context: Context): FunctionDescriptor? {
val packageScope = context.builtIns.builtInsModule.getPackage(packageName).memberScope
val main = packageScope.getContributedFunctions(entryName,
NoLookupLocation.FROM_BACKEND).singleOrNull {
val candidates = packageScope.getContributedFunctions(entryName,
NoLookupLocation.FROM_BACKEND).filter {
it.returnType?.isUnit() == true &&
it.hasSingleArrayOfStringParameter &&
it.typeParameters.isEmpty() &&
it.visibility.isPublicAPI
}
if (main == null) {
context.reportCompilationError("Could not find '$entryName' in '$packageName' package.")
}
val main =
candidates.singleOrNull { it.hasSingleArrayOfStringParameter } ?:
candidates.singleOrNull { it.hasNoParameters } ?:
run {
context.reportCompilationError("Could not find '$entryName' in '$packageName' package.")
null
}
return main
}
@@ -73,3 +78,5 @@ private val KotlinType.isArrayOfString: Boolean
private val FunctionDescriptor.hasSingleArrayOfStringParameter: Boolean
get() = valueParameters.singleOrNull()?.type?.isArrayOfString ?: false
private val FunctionDescriptor.hasNoParameters: Boolean
get() = valueParameters.isEmpty()
@@ -2618,9 +2618,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
//-------------------------------------------------------------------------//
private fun entryPointSelector(entryPoint: LLVMValueRef,
entryPointType: LLVMTypeRef, selectorName: String): LLVMValueRef {
entryPointType: LLVMTypeRef, selectorName: String, argCount: Int): LLVMValueRef {
assert(LLVMCountParams(entryPoint) == 1)
assert(LLVMCountParams(entryPoint) <= 1)
val selector = LLVMAddFunction(context.llvmModule, selectorName, entryPointType)!!
generateFunction(codegen, selector) {
@@ -2629,8 +2629,11 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
// scheme for arguments guarantees, that reference is being held in C++
// launcher, so we could optimize out creating slot for 'parameter' in
// this function.
val parameter = LLVMGetParam(selector, 0)!!
call(entryPoint, listOf(parameter), Lifetime.IRRELEVANT, ExceptionHandler.Caller)
val parameters = if (argCount == 1)
listOf(LLVMGetParam(selector, 0)!!)
else
emptyList()
call(entryPoint, parameters, Lifetime.IRRELEVANT, ExceptionHandler.Caller)
ret(null)
}
return selector
@@ -2644,8 +2647,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
val entryPoint = codegen.llvmFunction(descriptor)
val selectorName = "EntryPointSelector"
val entryPointType = getFunctionType(entryPoint)
val argCount = descriptor.valueParameters.size
assert(argCount <= 1)
val selector = entryPointSelector(entryPoint, entryPointType, selectorName)
val selector = entryPointSelector(entryPoint, entryPointType, selectorName, argCount)
LLVMSetLinkage(selector, LLVMLinkage.LLVMExternalLinkage)
}
+11
View File
@@ -546,6 +546,17 @@ task entry2(type: LinkKonanTest) {
flags = ["-entry", "foo"]
}
task entry3(type: RunStandaloneKonanTest) {
goldValue = "Hello, without args.\n"
source = "runtime/basic/entry1.kt"
flags = ["-entry", "bar"]
}
task entry4(type: RunStandaloneKonanTest) {
goldValue = "This is main without args\n"
source = "runtime/basic/entry4.kt"
}
task readline0(type: RunStandaloneKonanTest) {
goldValue = "41"
testData = "41\r\n"
@@ -11,6 +11,10 @@ fun foo(args: Array<String>) {
println("Hello.")
}
fun bar() {
println("Hello, without args.")
}
fun main(args: Array<String>) {
fail()
@@ -0,0 +1,3 @@
fun main() {
println("This is main without args")
}