Fixed coroutines for wasm
Replaced llvm indirectBr instruction with switch instruction.
This commit is contained in:
+2
@@ -46,6 +46,8 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
internal val targetManager = TargetManager(
|
||||
configuration.get(KonanConfigKeys.TARGET))
|
||||
|
||||
val indirectBranchesAreAllowed = targetManager.target != KonanTarget.WASM32
|
||||
|
||||
init {
|
||||
val target = targetManager.target
|
||||
if (!target.enabled) {
|
||||
|
||||
+8
@@ -461,6 +461,14 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
currentPositionHolder.setAfterTerminator()
|
||||
return indirectBr
|
||||
}
|
||||
|
||||
fun switch(value: LLVMValueRef, cases: Collection<Pair<LLVMValueRef, LLVMBasicBlockRef>>, elseBB: LLVMBasicBlockRef): LLVMValueRef? {
|
||||
val switch = LLVMBuildSwitch(builder, value, elseBB, cases.size)
|
||||
cases.forEach { LLVMAddCase(switch, it.first, it.second) }
|
||||
currentPositionHolder.setAfterTerminator()
|
||||
return switch
|
||||
}
|
||||
|
||||
fun resetDebugLocation() {
|
||||
if (!context.shouldContainDebugInfo()) return
|
||||
if (!currentPositionHolder.isAfterTerminator)
|
||||
|
||||
+24
-8
@@ -189,7 +189,7 @@ internal interface CodeContext {
|
||||
*/
|
||||
fun classScope(): CodeContext?
|
||||
|
||||
fun addResumePoint(bbLabel: LLVMBasicBlockRef)
|
||||
fun addResumePoint(bbLabel: LLVMBasicBlockRef): Int
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -1747,8 +1747,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private inner class SuspendableExpressionScope(val resumePoints: MutableList<LLVMBasicBlockRef>) : InnerScopeImpl() {
|
||||
override fun addResumePoint(bbLabel: LLVMBasicBlockRef) {
|
||||
override fun addResumePoint(bbLabel: LLVMBasicBlockRef): Int {
|
||||
val result = resumePoints.size
|
||||
resumePoints.add(bbLabel)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1765,26 +1767,40 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val result = evaluateExpression(expression.result)
|
||||
|
||||
functionGenerationContext.appendingTo(bbDispatch) {
|
||||
functionGenerationContext.indirectBr(suspensionPointId, resumePoints)
|
||||
if (context.config.indirectBranchesAreAllowed)
|
||||
functionGenerationContext.indirectBr(suspensionPointId, resumePoints)
|
||||
else {
|
||||
val bbElse = functionGenerationContext.basicBlock("else", null) {
|
||||
functionGenerationContext.unreachable()
|
||||
}
|
||||
|
||||
val cases = resumePoints.withIndex().map { Int32(it.index + 1).llvm to it.value }
|
||||
functionGenerationContext.switch(functionGenerationContext.ptrToInt(suspensionPointId, int32Type), cases, bbElse)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private inner class SuspensionPointScope(val suspensionPointId: VariableDescriptor,
|
||||
val bbResume: LLVMBasicBlockRef): InnerScopeImpl() {
|
||||
val bbResume: LLVMBasicBlockRef,
|
||||
val bbResumeId: Int): InnerScopeImpl() {
|
||||
override fun genGetValue(descriptor: ValueDescriptor): LLVMValueRef {
|
||||
if (descriptor == suspensionPointId)
|
||||
return functionGenerationContext.blockAddress(bbResume)
|
||||
if (descriptor == suspensionPointId) {
|
||||
return if (context.config.indirectBranchesAreAllowed)
|
||||
functionGenerationContext.blockAddress(bbResume)
|
||||
else
|
||||
functionGenerationContext.intToPtr(Int32(bbResumeId + 1).llvm, int8TypePtr)
|
||||
}
|
||||
return super.genGetValue(descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
private fun evaluateSuspensionPoint(expression: IrSuspensionPoint): LLVMValueRef {
|
||||
val bbResume = functionGenerationContext.basicBlock("resume", expression.resumeResult.startLocation)
|
||||
currentCodeContext.addResumePoint(bbResume)
|
||||
val id = currentCodeContext.addResumePoint(bbResume)
|
||||
|
||||
using (SuspensionPointScope(expression.suspensionPointIdParameter.descriptor, bbResume)) {
|
||||
using (SuspensionPointScope(expression.suspensionPointIdParameter.descriptor, bbResume, id)) {
|
||||
continuationBlock(expression.type, expression.result.startLocation).run {
|
||||
val normalResult = evaluateExpression(expression.result)
|
||||
jump(this, normalResult)
|
||||
|
||||
@@ -350,7 +350,6 @@ task codegen_controlflow_for_loops_nested(type: RunKonanTest) {
|
||||
}
|
||||
|
||||
task codegen_controlflow_for_loops_coroutines(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
source = "codegen/controlflow/for_loops_coroutines.kt"
|
||||
goldValue = "before: 0 after: 0\n" +
|
||||
"before: 2 after: 2\n" +
|
||||
@@ -938,151 +937,126 @@ task kclass1(type: RunKonanTest) {
|
||||
}
|
||||
|
||||
task coroutines_simple(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "42\n"
|
||||
source = "codegen/coroutines/simple.kt"
|
||||
}
|
||||
|
||||
task coroutines_degenerate1(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "s1\n"
|
||||
source = "codegen/coroutines/degenerate1.kt"
|
||||
}
|
||||
|
||||
task coroutines_degenerate2(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "s2\ns1\n"
|
||||
source = "codegen/coroutines/degenerate2.kt"
|
||||
}
|
||||
|
||||
task coroutines_withReceiver(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "42\n"
|
||||
source = "codegen/coroutines/withReceiver.kt"
|
||||
}
|
||||
|
||||
task coroutines_correctOrder1(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "f1\ns1\nf2\n160\n"
|
||||
source = "codegen/coroutines/correctOrder1.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_if1(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "f1\ns1\nf3\n84\n"
|
||||
source = "codegen/coroutines/controlFlow_if1.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_if2(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "f1\ns1\nf2\n43\n"
|
||||
source = "codegen/coroutines/controlFlow_if2.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_finally1(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "f1\ns1\n117\n"
|
||||
source = "codegen/coroutines/controlFlow_finally1.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_finally2(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "f1\ns1\n117\n"
|
||||
source = "codegen/coroutines/controlFlow_finally2.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_finally3(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "f1\ns1\n117\n"
|
||||
source = "codegen/coroutines/controlFlow_finally3.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_finally4(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "s1\nfinally\n42\n"
|
||||
source = "codegen/coroutines/controlFlow_finally4.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_finally5(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "s1\nf2\nfinally\n1\n"
|
||||
source = "codegen/coroutines/controlFlow_finally5.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_finally6(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "s1\nfinally\nerror\n0\n"
|
||||
source = "codegen/coroutines/controlFlow_finally6.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_finally7(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "s1\nf2\nfinally1\ns2\nfinally2\n42\n"
|
||||
source = "codegen/coroutines/controlFlow_finally7.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_inline1(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "42\n"
|
||||
source = "codegen/coroutines/controlFlow_inline1.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_inline2(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "s1\n42\n"
|
||||
source = "codegen/coroutines/controlFlow_inline2.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_inline3(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "f1\ns1\n42\n"
|
||||
source = "codegen/coroutines/controlFlow_inline3.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_tryCatch1(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "s1\n42\n"
|
||||
source = "codegen/coroutines/controlFlow_tryCatch1.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_tryCatch2(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "s1\n42\n"
|
||||
source = "codegen/coroutines/controlFlow_tryCatch2.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_tryCatch3(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "s2\nf2\n1\n"
|
||||
source = "codegen/coroutines/controlFlow_tryCatch3.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_tryCatch4(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "s2\nf2\n1\n"
|
||||
source = "codegen/coroutines/controlFlow_tryCatch4.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_tryCatch5(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "s2\ns1\nError\n42\n"
|
||||
source = "codegen/coroutines/controlFlow_tryCatch5.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_while1(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "s3\ns3\ns3\ns3\n3\n"
|
||||
source = "codegen/coroutines/controlFlow_while1.kt"
|
||||
}
|
||||
|
||||
task coroutines_controlFlow_while2(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "s3\ns3\ns3\n3\n"
|
||||
source = "codegen/coroutines/controlFlow_while2.kt"
|
||||
}
|
||||
|
||||
task coroutines_returnsUnit1(type: RunKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
|
||||
goldValue = "117\ns1\n0\n"
|
||||
source = "codegen/coroutines/returnsUnit1.kt"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user