Change code structure by adding explicit epilogue. (#150)
This commit is contained in:
+1
-1
@@ -61,7 +61,7 @@ internal final class Context(val config: KonanConfig,
|
||||
|
||||
fun printDescriptors() {
|
||||
separator("Descriptors after: ${phase?.description}")
|
||||
moduleDescriptor!!.deepPrint()
|
||||
moduleDescriptor.deepPrint()
|
||||
}
|
||||
|
||||
fun verifyIr() {
|
||||
|
||||
+57
-21
@@ -4,6 +4,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
||||
import kotlinx.cinterop.*
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
@@ -11,31 +12,57 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
var currentFunction:FunctionDescriptor? = null
|
||||
var function: LLVMValueRef? = null
|
||||
var returnType: LLVMTypeRef? = null
|
||||
val returns: MutableMap<LLVMBasicBlockRef, LLVMValueRef> = mutableMapOf()
|
||||
// TODO: remove, to make CodeGenerator descriptor-agnostic.
|
||||
var constructedClass: ClassDescriptor? = null
|
||||
|
||||
fun prologue(declaration: IrFunction) {
|
||||
assert(declaration.body != null)
|
||||
|
||||
val descriptor = declaration.descriptor
|
||||
if (currentFunction == descriptor) return
|
||||
currentFunction = declaration.descriptor
|
||||
val fn = declaration.descriptor.llvmFunction
|
||||
prologueBb = LLVMAppendBasicBlock(fn, "prologue")
|
||||
entryBb = LLVMAppendBasicBlock(fn, "entry")
|
||||
positionAtEnd(entryBb!!)
|
||||
}
|
||||
|
||||
|
||||
fun epilogue(declaration: IrFunction) {
|
||||
appendingTo(prologueBb!!) {
|
||||
br(entryBb!!)
|
||||
fun prologue(descriptor: FunctionDescriptor) {
|
||||
prologue(llvmFunction(descriptor),
|
||||
LLVMGetReturnType(getLlvmFunctionType(descriptor))!!)
|
||||
if (descriptor is ConstructorDescriptor) {
|
||||
constructedClass = descriptor.constructedClass
|
||||
}
|
||||
}
|
||||
|
||||
fun fields(descriptor: ClassDescriptor):List<PropertyDescriptor> = descriptor.fields
|
||||
fun prologue(function:LLVMValueRef, returnType:LLVMTypeRef) {
|
||||
assert(returns.size == 0)
|
||||
|
||||
assert(this.function != function)
|
||||
this.function = function
|
||||
this.returnType = returnType
|
||||
this.constructedClass = null
|
||||
prologueBb = LLVMAppendBasicBlock(function, "prologue")
|
||||
entryBb = LLVMAppendBasicBlock(function, "entry")
|
||||
epilogueBb = LLVMAppendBasicBlock(function, "epilogue")
|
||||
positionAtEnd(entryBb!!)
|
||||
}
|
||||
|
||||
fun epilogue() {
|
||||
appendingTo(prologueBb!!) {
|
||||
br(entryBb!!)
|
||||
}
|
||||
|
||||
appendingTo(epilogueBb!!) {
|
||||
when {
|
||||
returnType == voidType -> LLVMBuildRetVoid(builder)
|
||||
returns.size > 0 -> {
|
||||
val returnPhi = phi(returnType!!)
|
||||
addPhiIncoming(returnPhi, *returns.toList().toTypedArray())
|
||||
LLVMBuildRet(builder, returnPhi)
|
||||
}
|
||||
// Do nothing, all paths throw.
|
||||
else -> LLVMBuildUnreachable(builder)
|
||||
}
|
||||
}
|
||||
|
||||
returns.clear()
|
||||
}
|
||||
|
||||
private var prologueBb: LLVMBasicBlockRef? = null
|
||||
private var entryBb: LLVMBasicBlockRef? = null
|
||||
private var epilogueBb: LLVMBasicBlockRef? = null
|
||||
|
||||
fun setName(value: LLVMValueRef, name: String) = LLVMSetValueName(value, name)
|
||||
|
||||
@@ -138,7 +165,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
fun basicBlock(function: LLVMValueRef, name: String = "label_"): LLVMBasicBlockRef =
|
||||
LLVMAppendBasicBlock(function, name)!!
|
||||
|
||||
fun lastBasicBlock(): LLVMBasicBlockRef? = LLVMGetLastBasicBlock(currentFunction!!.llvmFunction)
|
||||
fun lastBasicBlock(): LLVMBasicBlockRef? = LLVMGetLastBasicBlock(function)
|
||||
|
||||
fun functionLlvmValue(descriptor: FunctionDescriptor) = descriptor.llvmFunction
|
||||
fun functionEntryPointAddress(descriptor: FunctionDescriptor) = descriptor.entryPointAddress.llvm
|
||||
@@ -157,7 +184,16 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
}
|
||||
|
||||
fun ret(value: LLVMValueRef?): LLVMValueRef {
|
||||
val res = LLVMBuildRet(builder, value)!!
|
||||
val res = LLVMBuildBr(builder, epilogueBb)!!
|
||||
|
||||
if (returns.get(currentBlock) != null) {
|
||||
// TODO: enable error throwing.
|
||||
throw Error("ret() in the same basic block twice!")
|
||||
}
|
||||
|
||||
if (value != null)
|
||||
returns[currentBlock] = value
|
||||
|
||||
currentPositionHolder.setAfterTerminator()
|
||||
return res
|
||||
}
|
||||
@@ -181,7 +217,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
fun getBuilder(): LLVMBuilderRef {
|
||||
if (isAfterTerminator) {
|
||||
positionAtEnd(basicBlock(currentFunction!!.llvmFunction, "unreachable"))
|
||||
positionAtEnd(basicBlock(function!!, "unreachable"))
|
||||
}
|
||||
|
||||
return builder
|
||||
|
||||
+2
@@ -16,6 +16,8 @@ internal fun ContextUtils.getLLVMType(type: KotlinType): LLVMTypeRef {
|
||||
KotlinBuiltIns.isInt(type) -> LLVMInt32Type()
|
||||
KotlinBuiltIns.isLong(type) -> LLVMInt64Type()
|
||||
KotlinBuiltIns.isUnit(type) -> LLVMVoidType() // TODO: handle Unit parameter case
|
||||
// TODO: stdlib have methods taking Nothing, such as kotlin.collections.EmptySet.contains().
|
||||
// KotlinBuiltIns.isNothing(type) -> LLVMVoidType()
|
||||
KotlinBuiltIns.isFloat(type) -> LLVMFloatType()
|
||||
KotlinBuiltIns.isDouble(type) -> LLVMDoubleType()
|
||||
!KotlinBuiltIns.isPrimitiveType(type) -> this.kObjHeaderPtr
|
||||
|
||||
+18
-19
@@ -244,12 +244,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
fun createInitBody(initName: String) {
|
||||
val initFunction = LLVMAddFunction(context.llvmModule, initName, kVoidFuncType)!! // create LLVM function
|
||||
codegen.prologue(initFunction, voidType)
|
||||
using(FunctionScope(initFunction)) {
|
||||
val bbEnter = LLVMAppendBasicBlock(initFunction, "label_enter")!!
|
||||
codegen.positionAtEnd(bbEnter)
|
||||
|
||||
context.llvm.fileInitializers.forEachIndexed {
|
||||
i, it ->
|
||||
context.llvm.fileInitializers.forEach {
|
||||
val irField = it as IrField
|
||||
val descriptor = irField.descriptor
|
||||
val initialization = evaluateExpression(irField.initializer)
|
||||
@@ -258,6 +255,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
}
|
||||
codegen.ret(null)
|
||||
}
|
||||
codegen.epilogue()
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -277,12 +275,11 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
fun createInitCtor(ctorName: String, nodeName: String) {
|
||||
val ctorFunction = LLVMAddFunction(context.llvmModule, ctorName, kVoidFuncType)!! // Create constructor function.
|
||||
val bbEnter = LLVMAppendBasicBlock(ctorFunction, "label_enter")!! // Create basic block.
|
||||
|
||||
codegen.positionAtEnd(bbEnter)
|
||||
codegen.prologue(ctorFunction, voidType)
|
||||
val initNodePtr = LLVMGetNamedGlobal(context.llvmModule, nodeName)!! // Get LLVM function initializing globals of current file.
|
||||
codegen.call(context.llvm.appendToInitalizersTail, initNodePtr.singletonList(), "") // Add node to the tail of initializers list.
|
||||
codegen.ret(null)
|
||||
codegen.epilogue()
|
||||
|
||||
context.llvm.staticInitializers.add(ctorFunction) // Push newly created constructor in staticInitializers list.
|
||||
}
|
||||
@@ -374,7 +371,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
return
|
||||
}
|
||||
|
||||
codegen.prologue(constructorDeclaration)
|
||||
|
||||
codegen.prologue(constructorDeclaration.descriptor)
|
||||
|
||||
val constructorDescriptor = constructorDeclaration.descriptor
|
||||
val classDescriptor = constructorDescriptor.constructedClass
|
||||
|
||||
@@ -433,7 +432,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
codegen.ret(thisPtr)
|
||||
}
|
||||
|
||||
codegen.epilogue(constructorDeclaration)
|
||||
codegen.epilogue()
|
||||
context.log("visitConstructor : ${ir2string(constructorDeclaration)}")
|
||||
}
|
||||
|
||||
@@ -448,9 +447,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
override fun visitBlockBody(body: IrBlockBody) {
|
||||
using(VariableScope()) {
|
||||
super.visitBlockBody(body)
|
||||
val function = codegen.currentFunction!!
|
||||
if (function !is ConstructorDescriptor && !codegen.isAfterTerminator()) {
|
||||
if (function.returnType!!.isUnit()) {
|
||||
// TODO: write it properly!
|
||||
if (codegen.constructedClass == null && !codegen.isAfterTerminator()) {
|
||||
if (codegen.returnType == voidType) {
|
||||
codegen.ret(null)
|
||||
} else {
|
||||
codegen.unreachable()
|
||||
@@ -470,7 +469,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
override fun visitCall(expression: IrCall) {
|
||||
context.log("visitCall : ${ir2string(expression)}")
|
||||
val isUnit = KotlinBuiltIns.isUnit(expression.descriptor.returnType!!)
|
||||
evaluateExpression(expression)
|
||||
}
|
||||
|
||||
@@ -606,15 +604,17 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
if (declaration.descriptor.modality == Modality.ABSTRACT || declaration.body == null)
|
||||
return
|
||||
|
||||
codegen.prologue(declaration)
|
||||
|
||||
codegen.prologue(declaration.descriptor)
|
||||
|
||||
using(FunctionScope(declaration)) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
codegen.epilogue(declaration)
|
||||
codegen.epilogue()
|
||||
|
||||
verifyModule(context.llvmModule!!, ir2string(declaration))
|
||||
verifyModule(context.llvmModule!!,
|
||||
"${declaration.descriptor.containingDeclaration}::${ir2string(declaration)}")
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -1923,7 +1923,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
arg0: LLVMValueRef, arg1: LLVMValueRef): LLVMValueRef {
|
||||
|
||||
val arg0Type = callee.argument0.type
|
||||
val arg1Type = callee.argument1.type
|
||||
|
||||
return when {
|
||||
KotlinBuiltIns.isPrimitiveType(arg0Type) -> TODO("${ir2string(callee)}")
|
||||
@@ -2009,7 +2008,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
fun delegatingConstructorCall(descriptor: ClassConstructorDescriptor, args: List<LLVMValueRef>): LLVMValueRef {
|
||||
|
||||
val constructedClass = (codegen.currentFunction!! as ConstructorDescriptor).constructedClass
|
||||
val constructedClass = codegen.constructedClass!!
|
||||
val thisPtr = currentCodeContext.genGetValue(constructedClass.thisAsReceiverParameter)
|
||||
|
||||
val thisPtrArgType = codegen.getLLVMType(descriptor.allValueParameters[0].type)
|
||||
|
||||
Reference in New Issue
Block a user