Refactoring:

1. generator -> codegen
2. tmpVariable -> newVar
3. All calls for LLVM* functions migrated to CodeGenerator
4. mutable list -> list for arguments.
This commit is contained in:
Konstantin Anisimov
2016-11-08 12:50:42 +03:00
committed by vvlevchenko
parent c47a58d34f
commit d1a303bb25
3 changed files with 126 additions and 119 deletions
@@ -54,7 +54,7 @@ internal class CodeGenerator(override val context:Context) : ContextUtils {
/* constructor */ /* constructor */
fun initFunction(declaration: IrConstructor) { fun initFunction(declaration: IrConstructor) {
function(declaration) function(declaration)
val thisPtr = bitcast(pointerType(classType(declaration.descriptor.containingDeclaration)), load(thisVariable(), tmpVariable()), tmpVariable()) val thisPtr = bitcast(pointerType(classType(declaration.descriptor.containingDeclaration)), load(thisVariable(), newVar()), newVar())
/** /**
* TODO: check shadowing. * TODO: check shadowing.
@@ -65,10 +65,10 @@ internal class CodeGenerator(override val context:Context) : ContextUtils {
if (!declaration.descriptor.valueParameters.any { it -> it.name.asString() == name }) if (!declaration.descriptor.valueParameters.any { it -> it.name.asString() == name })
return@forEachIndexed return@forEachIndexed
val ptr = LLVMBuildStructGEP(context.llvmBuilder, thisPtr, i, tmpVariable()) val ptr = LLVMBuildStructGEP(context.llvmBuilder, thisPtr, i, newVar())
val value = load(variable(name)!!, tmpVariable()) val value = load(variable(name)!!, newVar())
val typePtr = bitcast(pointerType(LLVMTypeOf(value)), ptr!!, tmpVariable()) val typePtr = bitcast(pointerType(LLVMTypeOf(value)), ptr!!, newVar())
store(value, typePtr!!) store(value, typePtr!!)
} }
currentClass = declaration.descriptor.constructedClass currentClass = declaration.descriptor.constructedClass
@@ -86,7 +86,7 @@ internal class CodeGenerator(override val context:Context) : ContextUtils {
return fn return fn
} }
fun tmpVariable():String = currentFunction!!.tmpVariable() fun newVar():String = currentFunction!!.tmpVariable()
val variablesGlobal = mapOf<String, LLVMOpaqueValue?>() val variablesGlobal = mapOf<String, LLVMOpaqueValue?>()
fun variable(varName:String):LLVMOpaqueValue? = currentFunction!!.variable(varName) fun variable(varName:String):LLVMOpaqueValue? = currentFunction!!.variable(varName)
@@ -140,7 +140,7 @@ internal class CodeGenerator(override val context:Context) : ContextUtils {
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
fun call(llvmFunction: LLVMOpaqueValue?, args: MutableList<LLVMOpaqueValue?>, result: String?): LLVMOpaqueValue? { fun call(llvmFunction: LLVMOpaqueValue?, args: List<LLVMOpaqueValue?>, result: String?): LLVMOpaqueValue? {
if (args.size == 0) return LLVMBuildCall(context.llvmBuilder, llvmFunction, null, 0, result) if (args.size == 0) return LLVMBuildCall(context.llvmBuilder, llvmFunction, null, 0, result)
memScoped { memScoped {
val rargs = alloc(array[args.size](Ref to LLVMOpaqueValue)) val rargs = alloc(array[args.size](Ref to LLVMOpaqueValue))
@@ -174,12 +174,21 @@ internal class CodeGenerator(override val context:Context) : ContextUtils {
fun indexInClass(p:PropertyDescriptor):Int = currentClass!!.fields.indexOf(p) fun indexInClass(p:PropertyDescriptor):Int = currentClass!!.fields.indexOf(p)
fun basicBlock(): LLVMOpaqueBasicBlock? = LLVMAppendBasicBlock(currentFunction!!.llvmFunction.getLlvmValue(), currentFunction!!.bbLabel()) fun basicBlock(): LLVMOpaqueBasicBlock? = LLVMAppendBasicBlock(currentFunction!!.llvmFunction.getLlvmValue(), currentFunction!!.bbLabel())
fun lastBasicBlock(): LLVMOpaqueBasicBlock? = LLVMGetLastBasicBlock(currentFunction!!.llvmFunction.getLlvmValue()) fun lastBasicBlock(): LLVMOpaqueBasicBlock? = LLVMGetLastBasicBlock(currentFunction!!.llvmFunction.getLlvmValue())
fun functionLlvmValue(descriptor: FunctionDescriptor) = descriptor.llvmFunction.getLlvmValue() fun functionLlvmValue(descriptor: FunctionDescriptor) = descriptor.llvmFunction.getLlvmValue()
fun functionHash(descriptor: FunctionDescriptor): LLVMOpaqueValue? = descriptor.functionName.localHash.getLlvmValue() fun functionHash(descriptor: FunctionDescriptor): LLVMOpaqueValue? = descriptor.functionName.localHash.getLlvmValue()
fun br(bbLabel: LLVMOpaqueBasicBlock) = LLVMBuildBr(context.llvmBuilder, bbLabel)
fun condBr(condition: LLVMOpaqueValue?, bbTrue: LLVMOpaqueBasicBlock?, bbFalse: LLVMOpaqueBasicBlock?)
= LLVMBuildCondBr(context.llvmBuilder, condition, bbTrue, bbFalse)
fun positionAtEnd(bbLabel: LLVMOpaqueBasicBlock)
= LLVMPositionBuilderAtEnd(context.llvmBuilder, bbLabel)
fun ret(value: LLVMOpaqueValue?) = LLVMBuildRet(context.llvmBuilder, value)
} }
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.* import org.jetbrains.kotlin.ir.descriptors.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrBinaryPrimitiveImpl import org.jetbrains.kotlin.ir.expressions.impl.IrBinaryPrimitiveImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrSetVariableImpl
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
@@ -70,8 +69,8 @@ internal class RTTIGeneratorVisitor(context: Context) : IrElementVisitorVoid {
internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid { internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid {
val generator = CodeGenerator(context) val codegen = CodeGenerator(context)
val logger = Logger(generator, context) val logger = Logger(codegen, context)
val metadator = MetadataGenerator(context) val metadator = MetadataGenerator(context)
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
@@ -86,12 +85,12 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
logger.log("visitWhen : ${ir2string(expression)}") logger.log("visitWhen : ${ir2string(expression)}")
var bbExit:LLVMOpaqueBasicBlock? = null // By default "when" does not have "exit" var bbExit:LLVMOpaqueBasicBlock? = null // By default "when" does not have "exit"
if (!KotlinBuiltIns.isNothing(expression.type)) // If "when" has "exit". if (!KotlinBuiltIns.isNothing(expression.type)) // If "when" has "exit".
bbExit = generator.basicBlock() // Create basic block to process "exit". bbExit = codegen.basicBlock() // Create basic block to process "exit".
expression.branches.forEach { // Iterate through "when" branches (clauses). expression.branches.forEach { // Iterate through "when" branches (clauses).
var bbNext = bbExit // For last clause bbNext coincides with bbExit. var bbNext = bbExit // For last clause bbNext coincides with bbExit.
if (it != expression.branches.last()) // If it is not last clause. if (it != expression.branches.last()) // If it is not last clause.
bbNext = generator.basicBlock() // Create new basic block for next clause. bbNext = codegen.basicBlock() // Create new basic block for next clause.
generateWhenCase(it, bbNext, bbExit) // Generate code for current clause. generateWhenCase(it, bbNext, bbExit) // Generate code for current clause.
} }
} }
@@ -105,48 +104,48 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
override fun visitWhileLoop(loop: IrWhileLoop) { override fun visitWhileLoop(loop: IrWhileLoop) {
val loopEnter = generator.basicBlock() val loopEnter = codegen.basicBlock()
val loopBody = generator.basicBlock() val loopBody = codegen.basicBlock()
val loopExit = generator.basicBlock() val loopExit = codegen.basicBlock()
LLVMBuildBr(context.llvmBuilder, loopEnter) LLVMBuildBr(context.llvmBuilder, loopEnter)
LLVMPositionBuilderAtEnd(context.llvmBuilder, loopEnter) codegen.positionAtEnd(loopEnter!!)
val condition = evaluateExpression(generator.tmpVariable(), loop.condition) val condition = evaluateExpression(codegen.newVar(), loop.condition)
LLVMBuildCondBr(context.llvmBuilder, condition, loopBody, loopExit) LLVMBuildCondBr(context.llvmBuilder, condition, loopBody, loopExit)
LLVMPositionBuilderAtEnd(context.llvmBuilder, loopBody) codegen.positionAtEnd(loopBody!!)
evaluateExpression(generator.tmpVariable(), loop.body) evaluateExpression(codegen.newVar(), loop.body)
LLVMBuildBr(context.llvmBuilder, loopEnter) LLVMBuildBr(context.llvmBuilder, loopEnter)
LLVMPositionBuilderAtEnd(context.llvmBuilder, loopExit) codegen.positionAtEnd(loopExit!!)
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
override fun visitDoWhileLoop(loop: IrDoWhileLoop) { override fun visitDoWhileLoop(loop: IrDoWhileLoop) {
val loopBody = generator.basicBlock() val loopBody = codegen.basicBlock()
val loopCheck = generator.basicBlock() val loopCheck = codegen.basicBlock()
val loopExit = generator.basicBlock() val loopExit = codegen.basicBlock()
LLVMBuildBr(context.llvmBuilder, loopBody) LLVMBuildBr(context.llvmBuilder, loopBody)
LLVMPositionBuilderAtEnd(context.llvmBuilder, loopBody) codegen.positionAtEnd(loopBody!!)
evaluateExpression(generator.tmpVariable(), loop.body) evaluateExpression(codegen.newVar(), loop.body)
LLVMBuildBr(context.llvmBuilder, loopCheck) LLVMBuildBr(context.llvmBuilder, loopCheck)
LLVMPositionBuilderAtEnd(context.llvmBuilder, loopCheck) codegen.positionAtEnd(loopCheck!!)
val condition = evaluateExpression(generator.tmpVariable(), loop.condition) val condition = evaluateExpression(codegen.newVar(), loop.condition)
LLVMBuildCondBr(context.llvmBuilder, condition, loopBody, loopExit) LLVMBuildCondBr(context.llvmBuilder, condition, loopBody, loopExit)
LLVMPositionBuilderAtEnd(context.llvmBuilder, loopExit) codegen.positionAtEnd(loopExit!!)
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
override fun visitConstructor(declaration: IrConstructor) { override fun visitConstructor(declaration: IrConstructor) {
generator.initFunction(declaration) codegen.initFunction(declaration)
val thisValue = generator.variable("this") val thisValue = codegen.variable("this")
//super.visitConstructor(declaration) //super.visitConstructor(declaration)
/** /**
* %this = alloca i8* * %this = alloca i8*
@@ -155,7 +154,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
* %tmp0 = load i8*, i8** %this <- epilog * %tmp0 = load i8*, i8** %this <- epilog
* ret i8* %tmp0 * ret i8* %tmp0
*/ */
LLVMBuildRet(context.llvmBuilder, generator.load(thisValue!!, generator.tmpVariable())) codegen.ret(codegen.load(thisValue!!, codegen.newVar()))
logger.log("visitConstructor : ${ir2string(declaration)}") logger.log("visitConstructor : ${ir2string(declaration)}")
} }
@@ -163,8 +162,8 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
override fun visitBlockBody(body: IrBlockBody) { override fun visitBlockBody(body: IrBlockBody) {
super.visitBlockBody(body) super.visitBlockBody(body)
if (KotlinBuiltIns.isUnit(generator.currentFunction!!.returnType!!)) { if (KotlinBuiltIns.isUnit(codegen.currentFunction!!.returnType!!)) {
LLVMBuildRet(context.llvmBuilder, null) codegen.ret(null)
} }
logger.log("visitBlockBody : ${ir2string(body)}") logger.log("visitBlockBody : ${ir2string(body)}")
} }
@@ -172,7 +171,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) { override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) {
evaluateCall(generator.tmpVariable(), expression) evaluateCall(codegen.newVar(), expression)
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
@@ -180,14 +179,14 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
override fun visitCall(expression: IrCall) { override fun visitCall(expression: IrCall) {
logger.log("visitCall ${ir2string(expression)}") logger.log("visitCall ${ir2string(expression)}")
val isUnit = KotlinBuiltIns.isUnit(expression.descriptor.returnType!!) val isUnit = KotlinBuiltIns.isUnit(expression.descriptor.returnType!!)
val tmpVariable = if (isUnit) "" else generator.tmpVariable() val tmpVariable = if (isUnit) "" else codegen.newVar()
evaluateExpression(tmpVariable, expression) evaluateExpression(tmpVariable, expression)
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
override fun visitFunction(declaration: IrFunction) { override fun visitFunction(declaration: IrFunction) {
generator.function(declaration) codegen.function(declaration)
metadator.function(declaration) metadator.function(declaration)
declaration.acceptChildrenVoid(this) declaration.acceptChildrenVoid(this)
} }
@@ -220,27 +219,27 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
logger.log("visitVariable : ${ir2string(declaration)}") logger.log("visitVariable : ${ir2string(declaration)}")
val variableName = declaration.descriptor.name.asString() val variableName = declaration.descriptor.name.asString()
val variableType = declaration.descriptor.type val variableType = declaration.descriptor.type
val newVariable = generator.alloca(variableType, variableName) // Create LLVM variable. val newVariable = codegen.alloca(variableType, variableName) // Create LLVM variable.
generator.registerVariable(variableName, newVariable) // Map variableName -> LLVM variable. codegen.registerVariable(variableName, newVariable) // Map variableName -> LLVM variable.
val value = evaluateExpression(variableName, declaration.initializer) // Generate initialization code. val value = evaluateExpression(variableName, declaration.initializer) // Generate initialization code.
generator.store(value!!, generator.variable(variableName)!!) // Store init result in the variable codegen.store(value!!, codegen.variable(variableName)!!) // Store init result in the variable
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
override fun visitReturn(expression: IrReturn) { override fun visitReturn(expression: IrReturn) {
logger.log("visitReturn : ${ir2string(expression)}") logger.log("visitReturn : ${ir2string(expression)}")
val tmpVarName = generator.tmpVariable() // Generate new tmp name. val tmpVarName = codegen.newVar() // Generate new tmp name.
val value = evaluateExpression(tmpVarName, expression.value) // val value = evaluateExpression(tmpVarName, expression.value) //
LLVMBuildRet(context.llvmBuilder, value) codegen.ret(value)
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
override fun visitSetVariable(expression: IrSetVariable) { override fun visitSetVariable(expression: IrSetVariable) {
logger.log("visitSetVariable : ${ir2string(expression)}") logger.log("visitSetVariable : ${ir2string(expression)}")
val value = evaluateExpression(generator.tmpVariable(), expression.value) val value = evaluateExpression(codegen.newVar(), expression.value)
generator.store(value!!, generator.variable(expression.descriptor.name.asString())!!) codegen.store(value!!, codegen.variable(expression.descriptor.name.asString())!!)
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
@@ -269,7 +268,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val args = mutableListOf<LLVMOpaqueValue?>() // Create list of function args. val args = mutableListOf<LLVMOpaqueValue?>() // Create list of function args.
value!!.acceptChildrenVoid(object: IrElementVisitorVoid { // Iterate args of the function. value!!.acceptChildrenVoid(object: IrElementVisitorVoid { // Iterate args of the function.
override fun visitElement(element: IrElement) { // Visit arg. override fun visitElement(element: IrElement) { // Visit arg.
val tmp = generator.tmpVariable() // Create variable representing the arg in generator val tmp = codegen.newVar() // Create variable representing the arg in codegen
args.add(evaluateExpression(tmp, element as IrExpression)) // Evaluate expression and get LLVM arg args.add(evaluateExpression(tmp, element as IrExpression)) // Evaluate expression and get LLVM arg
} }
}) })
@@ -291,12 +290,12 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
is LocalVariableDescriptor, is LocalVariableDescriptor,
is ValueParameterDescriptor, is ValueParameterDescriptor,
is IrTemporaryVariableDescriptor -> { is IrTemporaryVariableDescriptor -> {
val variable = generator.variable(value.descriptor.name.asString()) val variable = codegen.variable(value.descriptor.name.asString())
return generator.load(variable!!, tmpVariableName) return codegen.load(variable!!, tmpVariableName)
} }
is LazyClassReceiverParameterDescriptor -> { is LazyClassReceiverParameterDescriptor -> {
if (value.descriptor.name.asString() == "<this>") { if (value.descriptor.name.asString() == "<this>") {
return generator.load(generator.thisVariable(), tmpVariableName) return codegen.load(codegen.thisVariable(), tmpVariableName)
} }
TODO() TODO()
} }
@@ -310,19 +309,19 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
private fun evaluateSetVariable(value: IrSetVariable): LLVMOpaqueValue { private fun evaluateSetVariable(value: IrSetVariable): LLVMOpaqueValue {
logger.log("evaluateSetVariable : ${ir2string(value)}") logger.log("evaluateSetVariable : ${ir2string(value)}")
val ret = evaluateExpression(generator.tmpVariable(), value.value) val ret = evaluateExpression(codegen.newVar(), value.value)
return generator.store(ret!!, generator.variable(value.descriptor.name.asString())!!) return codegen.store(ret!!, codegen.variable(value.descriptor.name.asString())!!)
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
private fun evaluateVariable(value: IrVariable): LLVMOpaqueValue { private fun evaluateVariable(value: IrVariable): LLVMOpaqueValue {
logger.log("evaluateVariable : ${ir2string(value)}") logger.log("evaluateVariable : ${ir2string(value)}")
val ret = evaluateExpression(generator.tmpVariable(), value.initializer) val ret = evaluateExpression(codegen.newVar(), value.initializer)
val variableName = value.descriptor.name.asString() val variableName = value.descriptor.name.asString()
val variable = generator.alloca(LLVMTypeOf(ret), variableName) val variable = codegen.alloca(LLVMTypeOf(ret), variableName)
generator.registerVariable(variableName, variable) codegen.registerVariable(variableName, variable)
return generator.store(ret!!, variable) return codegen.store(ret!!, variable)
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
@@ -331,13 +330,13 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
logger.log("evaluateGetField : ${ir2string(value)}") logger.log("evaluateGetField : ${ir2string(value)}")
if (value.descriptor.dispatchReceiverParameter != null) { if (value.descriptor.dispatchReceiverParameter != null) {
if (value.descriptor.getter != null) { if (value.descriptor.getter != null) {
val tmpThis = generator.load(generator.thisVariable(), generator.tmpVariable()) val tmpThis = codegen.load(codegen.thisVariable(), codegen.newVar())
return evaluateSimpleFunctionCall(generator.tmpVariable(), value.descriptor.getter!!.original, mutableListOf(tmpThis))!! return evaluateSimpleFunctionCall(codegen.newVar(), value.descriptor.getter!!.original, mutableListOf(tmpThis))!!
} else { } else {
val thisPtr = generator.load(generator.thisVariable(), generator.tmpVariable()) val thisPtr = codegen.load(codegen.thisVariable(), codegen.newVar())
val typedPtr = generator.bitcast(pointerType(generator.classType(generator.currentClass!!)), thisPtr, generator.tmpVariable()) val typedPtr = codegen.bitcast(pointerType(codegen.classType(codegen.currentClass!!)), thisPtr, codegen.newVar())
val fieldPtr = LLVMBuildStructGEP(generator.context.llvmBuilder, typedPtr, generator.indexInClass(value.descriptor), generator.tmpVariable()) val fieldPtr = LLVMBuildStructGEP(codegen.context.llvmBuilder, typedPtr, codegen.indexInClass(value.descriptor), codegen.newVar())
return generator.load(fieldPtr!!, generator.tmpVariable()) return codegen.load(fieldPtr!!, codegen.newVar())
} }
} }
TODO() TODO()
@@ -356,8 +355,8 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
IrConstKind.Char -> return LLVMConstInt(LLVMInt16Type(), (value.value as Char).toLong(), 0) IrConstKind.Char -> return LLVMConstInt(LLVMInt16Type(), (value.value as Char).toLong(), 0)
IrConstKind.Byte -> return LLVMConstInt(LLVMInt32Type(), (value.value as Byte).toLong(), 1) IrConstKind.Byte -> return LLVMConstInt(LLVMInt32Type(), (value.value as Byte).toLong(), 1)
IrConstKind.Short -> return LLVMConstInt(LLVMInt32Type(), (value.value as Short).toLong(), 1) IrConstKind.Short -> return LLVMConstInt(LLVMInt32Type(), (value.value as Short).toLong(), 1)
IrConstKind.Int -> return LLVMConstInt(LLVMInt32Type(), (value.value as Int).toLong(), 1) IrConstKind.Int -> return LLVMConstInt(LLVMInt32Type(), (value.value as Int).toLong(), 1)
IrConstKind.Long -> return LLVMConstInt(LLVMInt64Type(), value.value as Long, 1) IrConstKind.Long -> return LLVMConstInt(LLVMInt64Type(), value.value as Long, 1)
IrConstKind.String -> IrConstKind.String ->
return context.staticData.createStringLiteral(value as IrConst<String>).getLlvmValue() return context.staticData.createStringLiteral(value as IrConst<String>).getLlvmValue()
IrConstKind.Float -> return LLVMConstRealOfString(LLVMFloatType(), (value.value as Float).toString()) IrConstKind.Float -> return LLVMConstRealOfString(LLVMFloatType(), (value.value as Float).toString())
@@ -370,8 +369,8 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
private fun evaluateReturn(value: IrReturn): LLVMOpaqueValue? { private fun evaluateReturn(value: IrReturn): LLVMOpaqueValue? {
logger.log("evaluateReturn : ${ir2string(value)}") logger.log("evaluateReturn : ${ir2string(value)}")
val ret = evaluateExpression(generator.tmpVariable(), value.value) val ret = evaluateExpression(codegen.newVar(), value.value)
return LLVMBuildRet(context.llvmBuilder, ret) return codegen.ret(ret)
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
@@ -379,9 +378,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
private fun evaluateBlock(value: IrBlock): LLVMOpaqueValue? { private fun evaluateBlock(value: IrBlock): LLVMOpaqueValue? {
logger.log("evaluateBlock : ${ir2string(value)}") logger.log("evaluateBlock : ${ir2string(value)}")
value.statements.dropLast(1).forEach { value.statements.dropLast(1).forEach {
evaluateExpression(generator.tmpVariable(), it) evaluateExpression(codegen.newVar(), it)
} }
return evaluateExpression(generator.tmpVariable(), value.statements.lastOrNull()) return evaluateExpression(codegen.newVar(), value.statements.lastOrNull())
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
@@ -411,18 +410,13 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
logger.log("evaluateConstructorCall : $variableName = ${ir2string(callee)}") logger.log("evaluateConstructorCall : $variableName = ${ir2string(callee)}")
memScoped { memScoped {
val containingClass = (callee.descriptor as ClassConstructorDescriptor).containingDeclaration val containingClass = (callee.descriptor as ClassConstructorDescriptor).containingDeclaration
val typeInfo = generator.typeInfoValue(containingClass) val typeInfo = codegen.typeInfoValue(containingClass)
val allocHint = Int32(1).getLlvmValue() val allocHint = Int32(1).getLlvmValue()
val thisValue = if (containingClass.isArray) { val thisValue = if (containingClass.isArray) {
assert(args.size == 1 && LLVMTypeOf(args[0]) == LLVMInt32Type()) assert(args.size == 1 && LLVMTypeOf(args[0]) == LLVMInt32Type())
val size = args[0] codegen.call(context.allocArrayFunction, mutableListOf(typeInfo, allocHint, args[0]), variableName)
val params = allocNativeArrayOf(LLVMOpaqueValue, typeInfo, allocHint, size)
LLVMBuildCall(
context.llvmBuilder, context.allocArrayFunction, params[0], 3, variableName)
} else { } else {
val params = allocNativeArrayOf(LLVMOpaqueValue, typeInfo, allocHint) codegen.call(context.allocInstanceFunction, mutableListOf(typeInfo, allocHint), variableName)
LLVMBuildCall(
context.llvmBuilder, context.allocInstanceFunction, params[0], 2, variableName)
} }
val constructorParams: MutableList<LLVMOpaqueValue?> = mutableListOf() val constructorParams: MutableList<LLVMOpaqueValue?> = mutableListOf()
constructorParams += thisValue constructorParams += thisValue
@@ -449,12 +443,12 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val operandType = callee.argument0.type val operandType = callee.argument0.type
assert(operandType == callee.argument1.type) assert(operandType == callee.argument1.type)
when { when {
KotlinBuiltIns.isByte (operandType) -> return generator.icmpEq(arg0, arg1, tmpVariableName) KotlinBuiltIns.isByte (operandType) -> return codegen.icmpEq(arg0, arg1, tmpVariableName)
KotlinBuiltIns.isShort (operandType) -> return generator.icmpEq(arg0, arg1, tmpVariableName) KotlinBuiltIns.isShort (operandType) -> return codegen.icmpEq(arg0, arg1, tmpVariableName)
KotlinBuiltIns.isInt (operandType) -> return generator.icmpEq(arg0, arg1, tmpVariableName) KotlinBuiltIns.isInt (operandType) -> return codegen.icmpEq(arg0, arg1, tmpVariableName)
KotlinBuiltIns.isLong (operandType) -> return generator.icmpEq(arg0, arg1, tmpVariableName) KotlinBuiltIns.isLong (operandType) -> return codegen.icmpEq(arg0, arg1, tmpVariableName)
KotlinBuiltIns.isFloat (operandType) -> return generator.fcmpEq(arg0, arg1, tmpVariableName) KotlinBuiltIns.isFloat (operandType) -> return codegen.fcmpEq(arg0, arg1, tmpVariableName)
KotlinBuiltIns.isDouble(operandType) -> return generator.fcmpEq(arg0, arg1, tmpVariableName) KotlinBuiltIns.isDouble(operandType) -> return codegen.fcmpEq(arg0, arg1, tmpVariableName)
else -> TODO("ComplexType") else -> TODO("ComplexType")
} }
} }
@@ -462,20 +456,20 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
private fun generateWhenCase(branch: IrBranch, bbNext: LLVMOpaqueBasicBlock?, bbExit: LLVMOpaqueBasicBlock?) { private fun generateWhenCase(branch: IrBranch, bbNext: LLVMOpaqueBasicBlock?, bbExit: LLVMOpaqueBasicBlock?) {
if (isUnconditional(branch)) { // It is the "else" clause. if (isUnconditional(branch)) { // It is the "else" clause.
evaluateExpression(generator.tmpVariable(), branch.result) // Generate clause body. evaluateExpression(codegen.newVar(), branch.result) // Generate clause body.
if (bbExit == null) return // If "when" does not have exit - return. if (bbExit == null) return // If "when" does not have exit - return.
LLVMBuildBr(context.llvmBuilder, bbExit) // Generate branch to bbExit. codegen.br(bbExit) // Generate branch to bbExit.
LLVMPositionBuilderAtEnd(context.llvmBuilder, bbExit) // Switch generation to bbExit. codegen.positionAtEnd(bbExit) // Switch generation to bbExit.
} else { // It is conditional clause. } else { // It is conditional clause.
val bbCurr = generator.basicBlock() // Create block for clause body. val bbCurr = codegen.basicBlock() // Create block for clause body.
val condition = evaluateExpression(generator.tmpVariable(), branch.condition) // Generate cmp instruction. val condition = evaluateExpression(codegen.newVar(), branch.condition) // Generate cmp instruction.
LLVMBuildCondBr(context.llvmBuilder, condition, bbCurr, bbNext) // Conditional branch depending on cmp result. codegen.condBr(condition, bbCurr, bbNext) // Conditional branch depending on cmp result.
LLVMPositionBuilderAtEnd(context.llvmBuilder, bbCurr) // Switch generation to block for clause body. codegen.positionAtEnd(bbCurr!!) // Switch generation to block for clause body.
evaluateExpression(generator.tmpVariable(), branch.result) // Generate clause body. evaluateExpression(codegen.newVar(), branch.result) // Generate clause body.
if (!KotlinBuiltIns.isNothing(branch.result.type)) // If clause code does not contain "return". if (!KotlinBuiltIns.isNothing(branch.result.type)) // If clause code does not contain "return".
LLVMBuildBr(context.llvmBuilder, bbExit) // Generate branch to bbExit. codegen.br(bbExit!!) // Generate branch to bbExit.
LLVMPositionBuilderAtEnd(context.llvmBuilder, bbNext) // Switch generation to bbNextClause. codegen.positionAtEnd(bbNext!!) // Switch generation to bbNextClause.
} }
} }
@@ -488,47 +482,47 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
fun callDirect(descriptor: FunctionDescriptor, args: MutableList<LLVMOpaqueValue?>, result: String?): LLVMOpaqueValue? { fun callDirect(descriptor: FunctionDescriptor, args: List<LLVMOpaqueValue?>, result: String?): LLVMOpaqueValue? {
val llvmFunction = generator.functionLlvmValue(descriptor) val llvmFunction = codegen.functionLlvmValue(descriptor)
return generator.call(llvmFunction, args, result) return codegen.call(llvmFunction, args, result)
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
/* Runtime constant */ /* Runtime constant */
private val kTypeInfo = LLVMGetTypeByName(context.llvmModule, "struct.TypeInfo")!! private val kTypeInfo = LLVMGetTypeByName(context.llvmModule, "struct.TypeInfo")!!
private val kTypeInfoPtr = pointerType(kTypeInfo) private val kTypeInfoPtr = pointerType(kTypeInfo)
private val kInt8Ptr = pointerType(LLVMInt8Type()) private val kInt8Ptr = pointerType(LLVMInt8Type())
private val kInt8PtrPtr = pointerType(kInt8Ptr) private val kInt8PtrPtr = pointerType(kInt8Ptr)
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
fun callVirtual(descriptor: FunctionDescriptor, args: MutableList<LLVMOpaqueValue?>, result: String?): LLVMOpaqueValue? { fun callVirtual(descriptor: FunctionDescriptor, args: List<LLVMOpaqueValue?>, result: String?): LLVMOpaqueValue? {
val thisI8PtrPtr = generator.bitcast(kInt8PtrPtr, args[0]!!, generator.tmpVariable()) // Cast "this (i8*)" to i8**. val thisI8PtrPtr = codegen.bitcast(kInt8PtrPtr, args[0]!!, codegen.newVar()) // Cast "this (i8*)" to i8**.
val typeInfoI8Ptr = generator.load(thisI8PtrPtr!!, generator.tmpVariable()) // Load TypeInfo address. val typeInfoI8Ptr = codegen.load(thisI8PtrPtr!!, codegen.newVar()) // Load TypeInfo address.
val typeInfoPtr = generator.bitcast(kTypeInfoPtr, typeInfoI8Ptr, generator.tmpVariable()) // Cast TypeInfo (i8*) to TypeInfo*. val typeInfoPtr = codegen.bitcast(kTypeInfoPtr, typeInfoI8Ptr, codegen.newVar()) // Cast TypeInfo (i8*) to TypeInfo*.
val methodHash = generator.functionHash(descriptor) // Calculate hash of the method to be invoked val methodHash = codegen.functionHash(descriptor) // Calculate hash of the method to be invoked
val lookupArgs = mutableListOf(typeInfoPtr, methodHash) // Prepare args for lookup val lookupArgs = listOf(typeInfoPtr, methodHash) // Prepare args for lookup
val llvmMethod = generator.call( val llvmMethod = codegen.call(
context.lookupOpenMethodFunction, context.lookupOpenMethodFunction,
lookupArgs, lookupArgs,
generator.tmpVariable()) // Get method ptr to be invoked codegen.newVar()) // Get method ptr to be invoked
val functionPtrType = pointerType(getLlvmFunctionType(descriptor)) // Construct type of the method to be invoked val functionPtrType = pointerType(getLlvmFunctionType(descriptor)) // Construct type of the method to be invoked
val function = generator.bitcast(functionPtrType, llvmMethod!!, generator.tmpVariable()) // Cast method address to the type val function = codegen.bitcast(functionPtrType, llvmMethod!!, codegen.newVar()) // Cast method address to the type
return generator.call(function, args, result) // Invoke the method return codegen.call(function, args, result) // Invoke the method
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
fun superCall(result:String, descriptor:ClassConstructorDescriptor, args:MutableList<LLVMOpaqueValue?> ):LLVMOpaqueValue? { fun superCall(result:String, descriptor:ClassConstructorDescriptor, args:List<LLVMOpaqueValue?> ):LLVMOpaqueValue? {
val tmp = generator.load(generator.thisVariable(), generator.tmpVariable()) val tmp = codegen.load(codegen.thisVariable(), codegen.newVar())
var rargs:MutableList<LLVMOpaqueValue?>? = null val rargs =
if (args.size != 0) if (args.isNotEmpty())
rargs = mutableListOf<LLVMOpaqueValue?>(tmp, *args.toTypedArray()) listOf<LLVMOpaqueValue?>(tmp, *args.toTypedArray())
else else
rargs = mutableListOf<LLVMOpaqueValue?>(tmp) listOf<LLVMOpaqueValue?>(tmp)
return callDirect(descriptor, rargs, result) return callDirect(descriptor, rargs!!, result)
} }
} }
@@ -16,10 +16,12 @@ internal class Logger(val generator: CodeGenerator, override val context: Contex
//---------------------------------------------------------------------------// //---------------------------------------------------------------------------//
fun log(msg: String) { fun log(msg: String) {
logIr() // logIr()
println(msg) println(msg)
} }
//---------------------------------------------------------------------------//
fun logIr() { fun logIr() {
val function = generator.currentFunction ?: return val function = generator.currentFunction ?: return
@@ -29,7 +31,7 @@ internal class Logger(val generator: CodeGenerator, override val context: Contex
} }
//-------------------------------------------------------------------------// //-----------------------------------------------------------------------------//
fun ir2string(ir: IrElement?): String { fun ir2string(ir: IrElement?): String {
val strWriter = StringWriter() val strWriter = StringWriter()
@@ -38,6 +40,8 @@ fun ir2string(ir: IrElement?): String {
return strWriter.toString().takeWhile { it != '\n' } return strWriter.toString().takeWhile { it != '\n' }
} }
//-----------------------------------------------------------------------------//
fun llvm2string(value: LLVMOpaqueValue?): String { fun llvm2string(value: LLVMOpaqueValue?): String {
if (value == null) return "<null>" if (value == null) return "<null>"
return LLVMPrintValueToString(value)!!.asCString().toString() return LLVMPrintValueToString(value)!!.asCString().toString()