提交 fa21a260 编写于 作者: I Igor Chevdar

Fixed coroutines for wasm

Replaced llvm indirectBr instruction with switch instruction.
上级 8f581111
......@@ -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) {
......
......@@ -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)
......
......@@ -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"
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册