CODEGEN: AllocArrayInstance and AllocInstance return ArrayHeader * and ObjHeader * respectively

This commit is contained in:
Vasily Levchenko
2016-11-30 14:09:10 +03:00
committed by vvlevchenko
parent b62536f807
commit b38a76e910
4 changed files with 62 additions and 51 deletions
@@ -32,11 +32,6 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
if (descriptor is ClassConstructorDescriptor
|| descriptor.dispatchReceiverParameter != null
|| descriptor.extensionReceiverParameter != null) {
val name = "this"
val type = pointerType(LLVMInt8Type());
val v = alloca(type, name)
store(LLVMGetParam(fn, 0)!!, v)
currentFunction!!.registerVariable(name, v)
indexOffset = 1;
}
@@ -81,9 +76,6 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
val FunctionDescriptor.variables: MutableMap<String, LLVMValueRef?>
get() = this@CodeGenerator.function2variables[this]!!
val ClassConstructorDescriptor.thisValue: LLVMValueRef?
get() = thisValue
fun FunctionDescriptor.registerVariable(varName: String, value: LLVMValueRef?) = variables.put(varName, value)
private fun FunctionDescriptor.variable(varName: String): LLVMValueRef? = variables[varName]
@@ -165,7 +157,8 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
fun typeInfoType(descriptor: ClassDescriptor): LLVMTypeRef = descriptor.llvmTypeInfoPtr.getLlvmType()
fun typeInfoValue(descriptor: ClassDescriptor): LLVMValueRef = descriptor.llvmTypeInfoPtr.getLlvmValue()!!
fun thisVariable() = variable("this")!!
fun thisVariable() = LLVMGetParam(currentFunction!!.llvmFunction.getLlvmValue(), 0)!!
fun param(fn: FunctionDescriptor?, i: Int): LLVMValueRef? = LLVMGetParam(fn!!.llvmFunction.getLlvmValue(), i)
fun indexInClass(p:PropertyDescriptor):Int = (p.containingDeclaration as ClassDescriptor).fields.indexOf(p)
@@ -4,7 +4,7 @@ import llvm.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.types.KotlinType
internal fun getLLVMType(type: KotlinType): LLVMTypeRef {
internal fun ContextUtils.getLLVMType(type: KotlinType): LLVMTypeRef {
return when {
KotlinBuiltIns.isBoolean(type) -> LLVMInt1Type()
KotlinBuiltIns.isByte(type) -> LLVMInt8Type()
@@ -14,7 +14,8 @@ internal fun getLLVMType(type: KotlinType): LLVMTypeRef {
KotlinBuiltIns.isUnit(type) -> LLVMVoidType() // TODO: handle Unit parameter case
KotlinBuiltIns.isFloat(type) -> LLVMFloatType()
KotlinBuiltIns.isDouble(type) -> LLVMDoubleType()
!KotlinBuiltIns.isPrimitiveType(type) -> LLVMPointerType(LLVMInt8Type(), 0)
KotlinBuiltIns.isArray(type) -> this.kArrayHeaderPtr
!KotlinBuiltIns.isPrimitiveType(type) -> this.kObjHeaderPtr
else -> throw NotImplementedError(type.toString() + " is not supported")
}!!
}
@@ -227,7 +227,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
codegen.prologue(constructorDeclaration)
val constructorDescriptor = constructorDeclaration.descriptor
val classDescriptor = DescriptorUtils.getContainingClass(constructorDescriptor)
val thisPtr = codegen.load(codegen.thisVariable(), codegen.newVar())
using(FunctionScope(constructorDeclaration)) {
@@ -253,7 +252,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
override fun visitField(fieldDeclaration: IrField) {
val fieldDescriptor = fieldDeclaration.descriptor
val fieldPtr = fieldPtrOfClass(thisPtr, fieldDescriptor)
val fieldPtr = fieldPtrOfClass(codegen.thisVariable(), fieldDescriptor)
var value: LLVMValueRef? = null
if (constructorDescriptor.valueParameters.any { it.name == fieldDescriptor.name }) {
val variable = codegen.variable(fieldDescriptor.name.asString())
@@ -280,7 +279,12 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
}
}
codegen.ret(thisPtr)
if (KotlinBuiltIns.isArray(constructorDescriptor.returnType)) {
val arrayPtr = codegen.bitcast(codegen.kArrayHeaderPtr, codegen.thisVariable(), codegen.newVar())
codegen.ret(arrayPtr)
} else {
codegen.ret(codegen.thisVariable())
}
codegen.epilogue(constructorDeclaration)
logger.log("visitConstructor : ${ir2string(constructorDeclaration)}")
}
@@ -353,7 +357,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
= codegen.call(function, args, result)
override fun genThrow(exception: LLVMValueRef) {
val objHeaderPtr = codegen.bitcast(kObjHeaderPtr, exception, codegen.newVar())
val objHeaderPtr = codegen.bitcast(codegen.kObjHeaderPtr, exception, codegen.newVar())
val args = listOf(objHeaderPtr)
codegen.call(context.throwExceptionFunction, args, "")
codegen.unreachable()
@@ -474,7 +478,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
logger.log("visitField : ${ir2string(expression)}")
val descriptor = expression.descriptor
if (descriptor.containingDeclaration is PackageFragmentDescriptor) {
val globalProperty = LLVMAddGlobal(context.llvmModule, getLLVMType(descriptor.type), descriptor.symbolName)
val globalProperty = LLVMAddGlobal(context.llvmModule, codegen.getLLVMType(descriptor.type), descriptor.symbolName)
LLVMSetInitializer(globalProperty, evaluateExpression("", expression.initializer))
return
}
@@ -583,7 +587,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
code(null)
}
} else {
continuationBlock(getLLVMType(type), code)
continuationBlock(codegen.getLLVMType(type), code)
}
}
@@ -636,7 +640,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
*/
private val handler by lazy {
using(outerContext) {
continuationBlock(kInt8Ptr) { exception ->
continuationBlock(codegen.kObjHeaderPtr) { exception ->
genHandler(exception)
}
}
@@ -686,16 +690,16 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val exceptionRawPtr = call(beginCatch, listOf(exceptionRecord), "")
// Pointer to KotlinException instance:
val exceptionPtr = bitcast(pointerType(int8TypePtr), exceptionRawPtr, "")
val exceptionPtrPtr = bitcast(codegen.kObjHeaderPtrPtr, exceptionRawPtr, "")
// Pointer to Kotlin exception object:
val exception = load(exceptionPtr, "exception")
val exceptionPtr = load(exceptionPtrPtr, "exception")
// __cxa_end_catch performs some C++ cleanup, including calling `KotlinException` class destructor.
val endCatch = externalFunction("__cxa_end_catch", functionType(voidType, false))
call(endCatch, listOf(), "")
jumpToHandler(exception)
jumpToHandler(exceptionPtr)
}
}
@@ -893,7 +897,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
is LazyClassReceiverParameterDescriptor,
is ReceiverParameterDescriptor -> {
if (value.descriptor.name.asString() == "<this>") {
return codegen.load(codegen.thisVariable(), tmpVariableName)
return codegen.thisVariable()
}
TODO("${ir2string(value)}")
}
@@ -943,7 +947,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val bbTrue = codegen.basicBlock()!!
val bbFalse = codegen.basicBlock()!!
val bbExit = codegen.basicBlock()!!
val result = codegen.alloca(getLLVMType(value.type), codegen.newVar())
val result = codegen.alloca(codegen.getLLVMType(value.type), codegen.newVar())
val condition = evaluateInstanceOf(codegen.newVar(), value)
codegen.condBr(condition, bbTrue, bbFalse)
@@ -954,7 +958,8 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
codegen.br(bbExit)
codegen.positionAtEnd(bbFalse)
val nullResult = kNullPtr
val nullResult = if (KotlinBuiltIns.isArray(value.type)) codegen.kNullArrayHeaderPtr
else codegen.kNullObjHeaderPtr
codegen.store(nullResult, result)
codegen.br(bbExit)
@@ -982,7 +987,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val dstDescriptor = TypeUtils.getClassDescriptor(value.type) // Get class descriptor for dst type.
val dstTypeInfo = codegen.typeInfoValue(dstDescriptor!!) // Get TypeInfo for dst type.
val srcArg = evaluateExpression(codegen.newVar(), value.argument)!! // Evaluate src expression.
val srcObjInfoPtr = codegen.bitcast(kObjHeaderPtr, srcArg, codegen.newVar()) // Cast src to ObjInfoPtr.
val srcObjInfoPtr = codegen.bitcast(codegen.kObjHeaderPtr, srcArg, codegen.newVar()) // Cast src to ObjInfoPtr.
val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
currentCodeContext.genCall(context.checkInstanceFunction, args, "") // Check if dst is subclass of src.
return srcArg
@@ -1002,7 +1007,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
private fun genInstanceOf(tmpVariableName: String, obj: LLVMValueRef, type: KotlinType): LLVMValueRef {
val dstDescriptor = TypeUtils.getClassDescriptor(type) // Get class descriptor for dst type.
val dstTypeInfo = codegen.typeInfoValue(dstDescriptor!!) // Get TypeInfo for dst type.
val srcObjInfoPtr = codegen.bitcast(kObjHeaderPtr, obj, codegen.newVar()) // Cast src to ObjInfoPtr.
val srcObjInfoPtr = codegen.bitcast(codegen.kObjHeaderPtr, obj, codegen.newVar()) // Cast src to ObjInfoPtr.
val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
val result = currentCodeContext.genCall( // Check if dst is subclass of src.
@@ -1023,7 +1028,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
private fun evaluateGetField(value: IrGetField): LLVMValueRef {
logger.log("evaluateGetField : ${ir2string(value)}")
if (value.descriptor.dispatchReceiverParameter != null) {
val thisPtr = codegen.load(codegen.thisVariable(), codegen.newVar())
val thisPtr = codegen.thisVariable()
return codegen.load(fieldPtrOfClass(thisPtr, value.descriptor)!!, codegen.newVar())
}
else {
@@ -1038,7 +1043,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
logger.log("evaluateSetField : ${ir2string(value)}")
val valueToAssign = evaluateExpression(codegen.newVar(), value.value)!!
if (value.descriptor.dispatchReceiverParameter != null) {
val thisPtr = codegen.load(codegen.thisVariable(), codegen.newVar())
val thisPtr = codegen.thisVariable()
return codegen.store(valueToAssign, fieldPtrOfClass(thisPtr, value.descriptor)!!)
}
else {
@@ -1082,7 +1087,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
*/
private fun fieldPtrOfClass(thisPtr: LLVMValueRef, value: PropertyDescriptor): LLVMValueRef? {
val objHeaderPtr = codegen.bitcast(kObjHeaderPtr, thisPtr, codegen.newVar())
val objHeaderPtr = codegen.bitcast(codegen.kObjHeaderPtr, thisPtr, codegen.newVar())
val typePtr = pointerType(codegen.classType(value.containingDeclaration as ClassDescriptor))
memScoped {
val args = allocArrayOf(kImmOne)
@@ -1098,7 +1103,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
private fun evaluateConst(value: IrConst<*>): LLVMValueRef? {
logger.log("evaluateConst : ${ir2string(value)}")
when (value.kind) {
IrConstKind.Null -> return kNullPtr
IrConstKind.Null -> return codegen.kNullObjHeaderPtr
IrConstKind.Boolean -> when (value.value) {
true -> return kTrue
false -> return kFalse
@@ -1212,7 +1217,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val allocHint = Int32(1).getLlvmValue()!!
val thisValue = if (containingClass.isArray) {
assert(args.size == 1 && LLVMTypeOf(args[0]) == LLVMInt32Type())
currentCodeContext.genCall(context.allocArrayFunction, listOf(typeInfo, allocHint, args[0]), variableName)
val allocArrayInstanceArgs = listOf(typeInfo, allocHint, args[0])
val ptr = currentCodeContext.genCall(context.allocArrayFunction, allocArrayInstanceArgs, variableName)
codegen.bitcast(codegen.kObjHeaderPtr, ptr, codegen.newVar())
} else {
currentCodeContext.genCall(context.allocInstanceFunction, listOf(typeInfo, allocHint), variableName)
}
@@ -1298,9 +1305,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val bbEq2 = codegen.basicBlock() // Block to process "eqeq".
val bbEq3 = codegen.basicBlock() // Block to process "eqeqeq".
val bbExit = codegen.basicBlock() // Exit block for feather generation.
val result = codegen.alloca(getLLVMType(callee.type), codegen.newVar())
val result = codegen.alloca(codegen.getLLVMType(callee.type), codegen.newVar())
val condition = codegen.icmpEq(arg0, kNullPtr, codegen.newVar()) // Compare arg0 with "null".
val condition = codegen.icmpEq(arg0, codegen.kNullObjHeaderPtr, codegen.newVar()) // Compare arg0 with "null".
codegen.condBr(condition, bbEq3, bbEq2) // If (arg0 == null) bbEq3 else bbEq2.
codegen.positionAtEnd(bbEq3) // Get generation to bbEq3.
@@ -1378,22 +1385,10 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
//-------------------------------------------------------------------------//
/* Runtime constant */
private val kTypeInfo = LLVMGetTypeByName(context.llvmModule, "struct.TypeInfo")!!
private val kObjHeader = LLVMGetTypeByName(context.llvmModule, "struct.ObjHeader")!!
private val kObjHeaderPtr = pointerType(kObjHeader)!!
private val kTypeInfoPtr = pointerType(kTypeInfo)
private val kInt1 = LLVMInt1Type()
private val kInt8Ptr = pointerType(LLVMInt8Type())
private val kInt8PtrPtr = pointerType(kInt8Ptr)
private val kNullPtr = LLVMConstNull(kInt8Ptr)!!
//-------------------------------------------------------------------------//
fun callVirtual(descriptor: FunctionDescriptor, args: List<LLVMValueRef>, result: String?): LLVMValueRef {
val thisI8PtrPtr = codegen.bitcast(kInt8PtrPtr, args[0], codegen.newVar()) // Cast "this (i8*)" to i8**.
val typeInfoI8Ptr = codegen.load(thisI8PtrPtr, codegen.newVar()) // Load TypeInfo address.
val typeInfoPtr = codegen.bitcast(kTypeInfoPtr, typeInfoI8Ptr, codegen.newVar()) // Cast TypeInfo (i8*) to TypeInfo*.
val typeInfoPtr = codegen.bitcast(codegen.kTypeInfoPtr, typeInfoI8Ptr, codegen.newVar()) // Cast TypeInfo (i8*) to TypeInfo*.
val methodHash = codegen.functionHash(descriptor) // Calculate hash of the method to be invoked
val lookupArgs = listOf(typeInfoPtr, methodHash) // Prepare args for lookup
val llvmMethod = currentCodeContext.genCall(
@@ -1401,7 +1396,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
lookupArgs,
codegen.newVar()) // Get method ptr to be invoked
val functionPtrType = pointerType(getLlvmFunctionType(descriptor)) // Construct type of the method to be invoked
val functionPtrType = pointerType(codegen.getLlvmFunctionType(descriptor)) // Construct type of the method to be invoked
val function = codegen.bitcast(functionPtrType, llvmMethod, codegen.newVar()) // Cast method address to the type
return call(descriptor, function, args, result) // Invoke the method
}
@@ -1416,8 +1411,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
//-------------------------------------------------------------------------//
fun superCall(result:String, descriptor:ClassConstructorDescriptor, args:List<LLVMValueRef> ): LLVMValueRef {
val tmp = codegen.load(codegen.thisVariable(), codegen.newVar())
val rargs = listOf(tmp, *args.toTypedArray())
val rargs = listOf(codegen.thisVariable(), *args.toTypedArray())
return callDirect(descriptor, rargs, result)
}
@@ -97,13 +97,36 @@ internal val int8TypePtr = pointerType(int8Type)
internal val voidType = LLVMVoidType()
internal val ContextUtils.kTypeInfo: LLVMTypeRef
get() = LLVMGetTypeByName(context.llvmModule, "struct.TypeInfo")!!
internal val ContextUtils.kObjHeader: LLVMTypeRef
get() = LLVMGetTypeByName(context.llvmModule, "struct.ObjHeader")!!
internal val ContextUtils.kObjHeaderPtr: LLVMTypeRef
get() = pointerType(kObjHeader)
internal val ContextUtils.kObjHeaderPtrPtr: LLVMTypeRef
get() = pointerType(kObjHeaderPtr)
internal val ContextUtils.kArrayHeader: LLVMTypeRef
get() = LLVMGetTypeByName(context.llvmModule, "struct.ArrayHeader")!!
internal val ContextUtils.kArrayHeaderPtr: LLVMTypeRef
get() = pointerType(kArrayHeader)
internal val ContextUtils.kTypeInfoPtr: LLVMTypeRef
get() = pointerType(kTypeInfo)
internal val kInt1 = LLVMInt1Type()
internal val kInt8Ptr = pointerType(LLVMInt8Type())
internal val kInt8PtrPtr = pointerType(kInt8Ptr)
internal val ContextUtils.kNullObjHeaderPtr: LLVMValueRef
get() = LLVMConstNull(this.kObjHeaderPtr)!!
internal val ContextUtils.kNullArrayHeaderPtr: LLVMValueRef
get() = LLVMConstNull(this.kArrayHeaderPtr)!!
internal fun pointerType(pointeeType: LLVMTypeRef?) = LLVMPointerType(pointeeType, 0)!!
internal fun structType(vararg types: LLVMTypeRef?): LLVMTypeRef = memScoped {
LLVMStructType(allocArrayOf(*types)[0].ptr, types.size, 0)!!
}
internal fun getLlvmFunctionType(function: FunctionDescriptor): LLVMTypeRef? {
internal fun ContextUtils.getLlvmFunctionType(function: FunctionDescriptor): LLVMTypeRef? {
val returnType = getLLVMType(function.returnType!!)
val params = function.dispatchReceiverParameter.singletonOrEmptyList() +
function.extensionReceiverParameter.singletonOrEmptyList() +
@@ -111,7 +134,7 @@ internal fun getLlvmFunctionType(function: FunctionDescriptor): LLVMTypeRef? {
var extraParam = listOf<LLVMTypeRef?>()
if (function is ClassConstructorDescriptor) {
extraParam += pointerType(LLVMInt8Type())
extraParam += kObjHeaderPtr
}
val paramTypes:List<LLVMTypeRef?> = params.map { getLLVMType(it.type) }
extraParam += paramTypes