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() {
|
fun printDescriptors() {
|
||||||
separator("Descriptors after: ${phase?.description}")
|
separator("Descriptors after: ${phase?.description}")
|
||||||
moduleDescriptor!!.deepPrint()
|
moduleDescriptor.deepPrint()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun verifyIr() {
|
fun verifyIr() {
|
||||||
|
|||||||
+57
-21
@@ -4,6 +4,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
|||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
|
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
@@ -11,31 +12,57 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
|
|||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
internal class CodeGenerator(override val context: Context) : ContextUtils {
|
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) {
|
fun prologue(descriptor: FunctionDescriptor) {
|
||||||
assert(declaration.body != null)
|
prologue(llvmFunction(descriptor),
|
||||||
|
LLVMGetReturnType(getLlvmFunctionType(descriptor))!!)
|
||||||
val descriptor = declaration.descriptor
|
if (descriptor is ConstructorDescriptor) {
|
||||||
if (currentFunction == descriptor) return
|
constructedClass = descriptor.constructedClass
|
||||||
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 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 prologueBb: LLVMBasicBlockRef? = null
|
||||||
private var entryBb: LLVMBasicBlockRef? = null
|
private var entryBb: LLVMBasicBlockRef? = null
|
||||||
|
private var epilogueBb: LLVMBasicBlockRef? = null
|
||||||
|
|
||||||
fun setName(value: LLVMValueRef, name: String) = LLVMSetValueName(value, name)
|
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 =
|
fun basicBlock(function: LLVMValueRef, name: String = "label_"): LLVMBasicBlockRef =
|
||||||
LLVMAppendBasicBlock(function, name)!!
|
LLVMAppendBasicBlock(function, name)!!
|
||||||
|
|
||||||
fun lastBasicBlock(): LLVMBasicBlockRef? = LLVMGetLastBasicBlock(currentFunction!!.llvmFunction)
|
fun lastBasicBlock(): LLVMBasicBlockRef? = LLVMGetLastBasicBlock(function)
|
||||||
|
|
||||||
fun functionLlvmValue(descriptor: FunctionDescriptor) = descriptor.llvmFunction
|
fun functionLlvmValue(descriptor: FunctionDescriptor) = descriptor.llvmFunction
|
||||||
fun functionEntryPointAddress(descriptor: FunctionDescriptor) = descriptor.entryPointAddress.llvm
|
fun functionEntryPointAddress(descriptor: FunctionDescriptor) = descriptor.entryPointAddress.llvm
|
||||||
@@ -157,7 +184,16 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun ret(value: LLVMValueRef?): LLVMValueRef {
|
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()
|
currentPositionHolder.setAfterTerminator()
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
@@ -181,7 +217,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
|||||||
|
|
||||||
fun getBuilder(): LLVMBuilderRef {
|
fun getBuilder(): LLVMBuilderRef {
|
||||||
if (isAfterTerminator) {
|
if (isAfterTerminator) {
|
||||||
positionAtEnd(basicBlock(currentFunction!!.llvmFunction, "unreachable"))
|
positionAtEnd(basicBlock(function!!, "unreachable"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder
|
return builder
|
||||||
|
|||||||
+2
@@ -16,6 +16,8 @@ internal fun ContextUtils.getLLVMType(type: KotlinType): LLVMTypeRef {
|
|||||||
KotlinBuiltIns.isInt(type) -> LLVMInt32Type()
|
KotlinBuiltIns.isInt(type) -> LLVMInt32Type()
|
||||||
KotlinBuiltIns.isLong(type) -> LLVMInt64Type()
|
KotlinBuiltIns.isLong(type) -> LLVMInt64Type()
|
||||||
KotlinBuiltIns.isUnit(type) -> LLVMVoidType() // TODO: handle Unit parameter case
|
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.isFloat(type) -> LLVMFloatType()
|
||||||
KotlinBuiltIns.isDouble(type) -> LLVMDoubleType()
|
KotlinBuiltIns.isDouble(type) -> LLVMDoubleType()
|
||||||
!KotlinBuiltIns.isPrimitiveType(type) -> this.kObjHeaderPtr
|
!KotlinBuiltIns.isPrimitiveType(type) -> this.kObjHeaderPtr
|
||||||
|
|||||||
+18
-19
@@ -244,12 +244,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
|
|
||||||
fun createInitBody(initName: String) {
|
fun createInitBody(initName: String) {
|
||||||
val initFunction = LLVMAddFunction(context.llvmModule, initName, kVoidFuncType)!! // create LLVM function
|
val initFunction = LLVMAddFunction(context.llvmModule, initName, kVoidFuncType)!! // create LLVM function
|
||||||
|
codegen.prologue(initFunction, voidType)
|
||||||
using(FunctionScope(initFunction)) {
|
using(FunctionScope(initFunction)) {
|
||||||
val bbEnter = LLVMAppendBasicBlock(initFunction, "label_enter")!!
|
context.llvm.fileInitializers.forEach {
|
||||||
codegen.positionAtEnd(bbEnter)
|
|
||||||
|
|
||||||
context.llvm.fileInitializers.forEachIndexed {
|
|
||||||
i, it ->
|
|
||||||
val irField = it as IrField
|
val irField = it as IrField
|
||||||
val descriptor = irField.descriptor
|
val descriptor = irField.descriptor
|
||||||
val initialization = evaluateExpression(irField.initializer)
|
val initialization = evaluateExpression(irField.initializer)
|
||||||
@@ -258,6 +255,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
}
|
}
|
||||||
codegen.ret(null)
|
codegen.ret(null)
|
||||||
}
|
}
|
||||||
|
codegen.epilogue()
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
@@ -277,12 +275,11 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
|
|
||||||
fun createInitCtor(ctorName: String, nodeName: String) {
|
fun createInitCtor(ctorName: String, nodeName: String) {
|
||||||
val ctorFunction = LLVMAddFunction(context.llvmModule, ctorName, kVoidFuncType)!! // Create constructor function.
|
val ctorFunction = LLVMAddFunction(context.llvmModule, ctorName, kVoidFuncType)!! // Create constructor function.
|
||||||
val bbEnter = LLVMAppendBasicBlock(ctorFunction, "label_enter")!! // Create basic block.
|
codegen.prologue(ctorFunction, voidType)
|
||||||
|
|
||||||
codegen.positionAtEnd(bbEnter)
|
|
||||||
val initNodePtr = LLVMGetNamedGlobal(context.llvmModule, nodeName)!! // Get LLVM function initializing globals of current file.
|
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.call(context.llvm.appendToInitalizersTail, initNodePtr.singletonList(), "") // Add node to the tail of initializers list.
|
||||||
codegen.ret(null)
|
codegen.ret(null)
|
||||||
|
codegen.epilogue()
|
||||||
|
|
||||||
context.llvm.staticInitializers.add(ctorFunction) // Push newly created constructor in staticInitializers list.
|
context.llvm.staticInitializers.add(ctorFunction) // Push newly created constructor in staticInitializers list.
|
||||||
}
|
}
|
||||||
@@ -374,7 +371,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
codegen.prologue(constructorDeclaration)
|
|
||||||
|
codegen.prologue(constructorDeclaration.descriptor)
|
||||||
|
|
||||||
val constructorDescriptor = constructorDeclaration.descriptor
|
val constructorDescriptor = constructorDeclaration.descriptor
|
||||||
val classDescriptor = constructorDescriptor.constructedClass
|
val classDescriptor = constructorDescriptor.constructedClass
|
||||||
|
|
||||||
@@ -433,7 +432,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
codegen.ret(thisPtr)
|
codegen.ret(thisPtr)
|
||||||
}
|
}
|
||||||
|
|
||||||
codegen.epilogue(constructorDeclaration)
|
codegen.epilogue()
|
||||||
context.log("visitConstructor : ${ir2string(constructorDeclaration)}")
|
context.log("visitConstructor : ${ir2string(constructorDeclaration)}")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,9 +447,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
override fun visitBlockBody(body: IrBlockBody) {
|
override fun visitBlockBody(body: IrBlockBody) {
|
||||||
using(VariableScope()) {
|
using(VariableScope()) {
|
||||||
super.visitBlockBody(body)
|
super.visitBlockBody(body)
|
||||||
val function = codegen.currentFunction!!
|
// TODO: write it properly!
|
||||||
if (function !is ConstructorDescriptor && !codegen.isAfterTerminator()) {
|
if (codegen.constructedClass == null && !codegen.isAfterTerminator()) {
|
||||||
if (function.returnType!!.isUnit()) {
|
if (codegen.returnType == voidType) {
|
||||||
codegen.ret(null)
|
codegen.ret(null)
|
||||||
} else {
|
} else {
|
||||||
codegen.unreachable()
|
codegen.unreachable()
|
||||||
@@ -470,7 +469,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
|
|
||||||
override fun visitCall(expression: IrCall) {
|
override fun visitCall(expression: IrCall) {
|
||||||
context.log("visitCall : ${ir2string(expression)}")
|
context.log("visitCall : ${ir2string(expression)}")
|
||||||
val isUnit = KotlinBuiltIns.isUnit(expression.descriptor.returnType!!)
|
|
||||||
evaluateExpression(expression)
|
evaluateExpression(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -606,15 +604,17 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
if (declaration.descriptor.modality == Modality.ABSTRACT || declaration.body == null)
|
if (declaration.descriptor.modality == Modality.ABSTRACT || declaration.body == null)
|
||||||
return
|
return
|
||||||
|
|
||||||
codegen.prologue(declaration)
|
|
||||||
|
codegen.prologue(declaration.descriptor)
|
||||||
|
|
||||||
using(FunctionScope(declaration)) {
|
using(FunctionScope(declaration)) {
|
||||||
declaration.acceptChildrenVoid(this)
|
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 {
|
arg0: LLVMValueRef, arg1: LLVMValueRef): LLVMValueRef {
|
||||||
|
|
||||||
val arg0Type = callee.argument0.type
|
val arg0Type = callee.argument0.type
|
||||||
val arg1Type = callee.argument1.type
|
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
KotlinBuiltIns.isPrimitiveType(arg0Type) -> TODO("${ir2string(callee)}")
|
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 {
|
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 thisPtr = currentCodeContext.genGetValue(constructedClass.thisAsReceiverParameter)
|
||||||
|
|
||||||
val thisPtrArgType = codegen.getLLVMType(descriptor.allValueParameters[0].type)
|
val thisPtrArgType = codegen.getLLVMType(descriptor.allValueParameters[0].type)
|
||||||
|
|||||||
Reference in New Issue
Block a user