CODEGEN: Support for "Throw" implemented
for code
--------8<--------
fun main(args : Array<String>) {
val cond = 1
if (cond == 2) throw RuntimeException()
if (cond == 3) throw NoSuchElementException("no such element")
if (cond == 4) throw Error("error happens")
println("Done")
}
--------8<--------
translator generates following: code
--------8<--------
; ModuleID = 'backend.native/tests/runtime/basic/throw0.kt.bc'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.12.0"
...
define void @"kfun:main(Array<String>)"(i8*) {
entry:
%args = alloca i8*
store i8* %0, i8** %args
%cond = alloca i32
store i32 1, i32* %cond
%tmp_1 = load i32, i32* %cond
%tmp_0 = icmp eq i32 %tmp_1, 2
br i1 %tmp_0, label %label_1, label %label_0
label_0: ; preds = %label_1, %entry
%tmp_7 = load i32, i32* %cond
%tmp_6 = icmp eq i32 %tmp_7, 3
br i1 %tmp_6, label %label_3, label %label_2
label_1: ; preds = %entry
%tmp_4 = call i8* @AllocInstance(%struct.TypeInfo* @"ktype:kotlin.RuntimeException", i32 1)
%tmp_41 = call i8* @"kfun:kotlin.RuntimeException.<init>()"(i8* %tmp_4)
%tmp_5 = bitcast i8* %tmp_41 to %struct.ObjHeader*
call void @ThrowException(%struct.ObjHeader* %tmp_5) ; <------- throwing RuntimeException
br label %label_0
label_2: ; preds = %label_3, %label_0
%tmp_14 = load i32, i32* %cond
%tmp_13 = icmp eq i32 %tmp_14, 4
br i1 %tmp_13, label %label_5, label %label_4
label_3: ; preds = %label_0
%tmp_10 = call i8* @AllocInstance(%struct.TypeInfo* @"ktype:kotlin.NoSuchElementException", i32 1)
%tmp_102 = call i8* @"kfun:kotlin.NoSuchElementException.<init>(String)"(i8* %tmp_10, i8* @"kstr:2E869yDM+y/5vqQYAKDPRI+j44w=")
%tmp_12 = bitcast i8* %tmp_102 to %struct.ObjHeader*
call void @ThrowException(%struct.ObjHeader* %tmp_12)
br label %label_2
label_4: ; preds = %label_5, %label_2
call void @Kotlin_io_Console_println(i8* @"kstr:6bRQ0UvCNj0pLITxfPrVz71YpFg=")
ret void
label_5: ; preds = %label_2
%tmp_17 = call i8* @AllocInstance(%struct.TypeInfo* @"ktype:kotlin.Error", i32 1)
%tmp_173 = call i8* @"kfun:kotlin.Error.<init>(String)"(i8* %tmp_17, i8* @"kstr:7YdnBMJy09naL/RsuOEV6Im2kOg=")
%tmp_19 = bitcast i8* %tmp_173 to %struct.ObjHeader*
call void @ThrowException(%struct.ObjHeader* %tmp_19)
br label %label_4
}
--------8<--------
This commit is contained in:
committed by
KonstantinAnisimov
parent
81811e8c3a
commit
4d24d735de
+1
@@ -164,6 +164,7 @@ internal class CodeGenerator(override val context:Context) : ContextUtils {
|
||||
= LLVMPositionBuilderAtEnd(context.llvmBuilder, bbLabel)
|
||||
|
||||
fun ret(value: LLVMOpaqueValue?) = LLVMBuildRet(context.llvmBuilder, value)
|
||||
fun unreachable(): LLVMOpaqueValue? = LLVMBuildUnreachable(context.llvmBuilder)
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
@@ -30,6 +30,7 @@ internal class Context(val irModule: IrModuleFragment, val runtime: Runtime, val
|
||||
val lookupOpenMethodFunction = importRtFunction("LookupOpenMethod")
|
||||
val isInstanceFunction = importRtFunction("IsInstance")
|
||||
val checkInstanceFunction = importRtFunction("CheckInstance")
|
||||
val throwExceptionFunction = importRtFunction("ThrowException")
|
||||
|
||||
fun dispose() {
|
||||
LLVMDisposeBuilder(llvmBuilder)
|
||||
|
||||
+17
@@ -201,6 +201,13 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
override fun visitThrow(expression: IrThrow) {
|
||||
logger.log("visitThrow : ${ir2string(expression)}")
|
||||
evaluateExpression("", expression)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
logger.log("visitFunction : ${ir2string(declaration)}")
|
||||
codegen.function(declaration)
|
||||
@@ -328,6 +335,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
is IrBlock -> return evaluateBlock ( value)
|
||||
is IrExpressionBody -> return evaluateExpression (tmpVariableName, value.expression)
|
||||
is IrWhen -> return evaluateWhen (tmpVariableName, value)
|
||||
is IrThrow -> return evaluateThrow (tmpVariableName, value)
|
||||
null -> return null
|
||||
else -> {
|
||||
TODO()
|
||||
@@ -337,6 +345,15 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun evaluateThrow(tmpVariableName: String, expression: IrThrow): LLVMOpaqueValue? {
|
||||
val objPointer = evaluateExpression(codegen.newVar(), expression.value)
|
||||
val objHeaderPtr = codegen.bitcast(kObjHeaderPtr, objPointer!!, codegen.newVar())
|
||||
val args = listOf(objHeaderPtr) // Create arg list.
|
||||
return codegen.call(context.throwExceptionFunction, args, "")
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun evaluateWhen(tmpVariableName:String, expression: IrWhen): LLVMOpaqueValue? {
|
||||
logger.log("evaluateWhen : ${ir2string(expression)}")
|
||||
var bbExit:LLVMOpaqueBasicBlock? = null // By default "when" does not have "exit".
|
||||
|
||||
Reference in New Issue
Block a user