CODEGEN: AllocArrayInstance and AllocInstance return ArrayHeader * and ObjHeader * respectively
This commit is contained in:
committed by
vvlevchenko
parent
b62536f807
commit
b38a76e910
+2
-9
@@ -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)
|
||||
|
||||
+3
-2
@@ -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")
|
||||
}!!
|
||||
}
|
||||
|
||||
+32
-38
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
+25
-2
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user