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
|
if (descriptor is ClassConstructorDescriptor
|
||||||
|| descriptor.dispatchReceiverParameter != null
|
|| descriptor.dispatchReceiverParameter != null
|
||||||
|| descriptor.extensionReceiverParameter != 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;
|
indexOffset = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,9 +76,6 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
|||||||
val FunctionDescriptor.variables: MutableMap<String, LLVMValueRef?>
|
val FunctionDescriptor.variables: MutableMap<String, LLVMValueRef?>
|
||||||
get() = this@CodeGenerator.function2variables[this]!!
|
get() = this@CodeGenerator.function2variables[this]!!
|
||||||
|
|
||||||
val ClassConstructorDescriptor.thisValue: LLVMValueRef?
|
|
||||||
get() = thisValue
|
|
||||||
|
|
||||||
|
|
||||||
fun FunctionDescriptor.registerVariable(varName: String, value: LLVMValueRef?) = variables.put(varName, value)
|
fun FunctionDescriptor.registerVariable(varName: String, value: LLVMValueRef?) = variables.put(varName, value)
|
||||||
private fun FunctionDescriptor.variable(varName: String): LLVMValueRef? = variables[varName]
|
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 typeInfoType(descriptor: ClassDescriptor): LLVMTypeRef = descriptor.llvmTypeInfoPtr.getLlvmType()
|
||||||
fun typeInfoValue(descriptor: ClassDescriptor): LLVMValueRef = descriptor.llvmTypeInfoPtr.getLlvmValue()!!
|
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 param(fn: FunctionDescriptor?, i: Int): LLVMValueRef? = LLVMGetParam(fn!!.llvmFunction.getLlvmValue(), i)
|
||||||
|
|
||||||
fun indexInClass(p:PropertyDescriptor):Int = (p.containingDeclaration as ClassDescriptor).fields.indexOf(p)
|
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.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
internal fun getLLVMType(type: KotlinType): LLVMTypeRef {
|
internal fun ContextUtils.getLLVMType(type: KotlinType): LLVMTypeRef {
|
||||||
return when {
|
return when {
|
||||||
KotlinBuiltIns.isBoolean(type) -> LLVMInt1Type()
|
KotlinBuiltIns.isBoolean(type) -> LLVMInt1Type()
|
||||||
KotlinBuiltIns.isByte(type) -> LLVMInt8Type()
|
KotlinBuiltIns.isByte(type) -> LLVMInt8Type()
|
||||||
@@ -14,7 +14,8 @@ internal fun getLLVMType(type: KotlinType): LLVMTypeRef {
|
|||||||
KotlinBuiltIns.isUnit(type) -> LLVMVoidType() // TODO: handle Unit parameter case
|
KotlinBuiltIns.isUnit(type) -> LLVMVoidType() // TODO: handle Unit parameter case
|
||||||
KotlinBuiltIns.isFloat(type) -> LLVMFloatType()
|
KotlinBuiltIns.isFloat(type) -> LLVMFloatType()
|
||||||
KotlinBuiltIns.isDouble(type) -> LLVMDoubleType()
|
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")
|
else -> throw NotImplementedError(type.toString() + " is not supported")
|
||||||
}!!
|
}!!
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-38
@@ -227,7 +227,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
codegen.prologue(constructorDeclaration)
|
codegen.prologue(constructorDeclaration)
|
||||||
val constructorDescriptor = constructorDeclaration.descriptor
|
val constructorDescriptor = constructorDeclaration.descriptor
|
||||||
val classDescriptor = DescriptorUtils.getContainingClass(constructorDescriptor)
|
val classDescriptor = DescriptorUtils.getContainingClass(constructorDescriptor)
|
||||||
val thisPtr = codegen.load(codegen.thisVariable(), codegen.newVar())
|
|
||||||
|
|
||||||
using(FunctionScope(constructorDeclaration)) {
|
using(FunctionScope(constructorDeclaration)) {
|
||||||
|
|
||||||
@@ -253,7 +252,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
override fun visitField(fieldDeclaration: IrField) {
|
override fun visitField(fieldDeclaration: IrField) {
|
||||||
|
|
||||||
val fieldDescriptor = fieldDeclaration.descriptor
|
val fieldDescriptor = fieldDeclaration.descriptor
|
||||||
val fieldPtr = fieldPtrOfClass(thisPtr, fieldDescriptor)
|
val fieldPtr = fieldPtrOfClass(codegen.thisVariable(), fieldDescriptor)
|
||||||
var value: LLVMValueRef? = null
|
var value: LLVMValueRef? = null
|
||||||
if (constructorDescriptor.valueParameters.any { it.name == fieldDescriptor.name }) {
|
if (constructorDescriptor.valueParameters.any { it.name == fieldDescriptor.name }) {
|
||||||
val variable = codegen.variable(fieldDescriptor.name.asString())
|
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)
|
codegen.epilogue(constructorDeclaration)
|
||||||
logger.log("visitConstructor : ${ir2string(constructorDeclaration)}")
|
logger.log("visitConstructor : ${ir2string(constructorDeclaration)}")
|
||||||
}
|
}
|
||||||
@@ -353,7 +357,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
= codegen.call(function, args, result)
|
= codegen.call(function, args, result)
|
||||||
|
|
||||||
override fun genThrow(exception: LLVMValueRef) {
|
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)
|
val args = listOf(objHeaderPtr)
|
||||||
codegen.call(context.throwExceptionFunction, args, "")
|
codegen.call(context.throwExceptionFunction, args, "")
|
||||||
codegen.unreachable()
|
codegen.unreachable()
|
||||||
@@ -474,7 +478,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
logger.log("visitField : ${ir2string(expression)}")
|
logger.log("visitField : ${ir2string(expression)}")
|
||||||
val descriptor = expression.descriptor
|
val descriptor = expression.descriptor
|
||||||
if (descriptor.containingDeclaration is PackageFragmentDescriptor) {
|
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))
|
LLVMSetInitializer(globalProperty, evaluateExpression("", expression.initializer))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -583,7 +587,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
code(null)
|
code(null)
|
||||||
}
|
}
|
||||||
} else {
|
} 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 {
|
private val handler by lazy {
|
||||||
using(outerContext) {
|
using(outerContext) {
|
||||||
continuationBlock(kInt8Ptr) { exception ->
|
continuationBlock(codegen.kObjHeaderPtr) { exception ->
|
||||||
genHandler(exception)
|
genHandler(exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -686,16 +690,16 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
val exceptionRawPtr = call(beginCatch, listOf(exceptionRecord), "")
|
val exceptionRawPtr = call(beginCatch, listOf(exceptionRecord), "")
|
||||||
|
|
||||||
// Pointer to KotlinException instance:
|
// Pointer to KotlinException instance:
|
||||||
val exceptionPtr = bitcast(pointerType(int8TypePtr), exceptionRawPtr, "")
|
val exceptionPtrPtr = bitcast(codegen.kObjHeaderPtrPtr, exceptionRawPtr, "")
|
||||||
|
|
||||||
// Pointer to Kotlin exception object:
|
// 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.
|
// __cxa_end_catch performs some C++ cleanup, including calling `KotlinException` class destructor.
|
||||||
val endCatch = externalFunction("__cxa_end_catch", functionType(voidType, false))
|
val endCatch = externalFunction("__cxa_end_catch", functionType(voidType, false))
|
||||||
call(endCatch, listOf(), "")
|
call(endCatch, listOf(), "")
|
||||||
|
|
||||||
jumpToHandler(exception)
|
jumpToHandler(exceptionPtr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -893,7 +897,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
is LazyClassReceiverParameterDescriptor,
|
is LazyClassReceiverParameterDescriptor,
|
||||||
is ReceiverParameterDescriptor -> {
|
is ReceiverParameterDescriptor -> {
|
||||||
if (value.descriptor.name.asString() == "<this>") {
|
if (value.descriptor.name.asString() == "<this>") {
|
||||||
return codegen.load(codegen.thisVariable(), tmpVariableName)
|
return codegen.thisVariable()
|
||||||
}
|
}
|
||||||
TODO("${ir2string(value)}")
|
TODO("${ir2string(value)}")
|
||||||
}
|
}
|
||||||
@@ -943,7 +947,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
val bbTrue = codegen.basicBlock()!!
|
val bbTrue = codegen.basicBlock()!!
|
||||||
val bbFalse = codegen.basicBlock()!!
|
val bbFalse = codegen.basicBlock()!!
|
||||||
val bbExit = 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)
|
val condition = evaluateInstanceOf(codegen.newVar(), value)
|
||||||
codegen.condBr(condition, bbTrue, bbFalse)
|
codegen.condBr(condition, bbTrue, bbFalse)
|
||||||
@@ -954,7 +958,8 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
codegen.br(bbExit)
|
codegen.br(bbExit)
|
||||||
|
|
||||||
codegen.positionAtEnd(bbFalse)
|
codegen.positionAtEnd(bbFalse)
|
||||||
val nullResult = kNullPtr
|
val nullResult = if (KotlinBuiltIns.isArray(value.type)) codegen.kNullArrayHeaderPtr
|
||||||
|
else codegen.kNullObjHeaderPtr
|
||||||
codegen.store(nullResult, result)
|
codegen.store(nullResult, result)
|
||||||
codegen.br(bbExit)
|
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 dstDescriptor = TypeUtils.getClassDescriptor(value.type) // Get class descriptor for dst type.
|
||||||
val dstTypeInfo = codegen.typeInfoValue(dstDescriptor!!) // Get TypeInfo for dst type.
|
val dstTypeInfo = codegen.typeInfoValue(dstDescriptor!!) // Get TypeInfo for dst type.
|
||||||
val srcArg = evaluateExpression(codegen.newVar(), value.argument)!! // Evaluate src expression.
|
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.
|
val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
|
||||||
currentCodeContext.genCall(context.checkInstanceFunction, args, "") // Check if dst is subclass of src.
|
currentCodeContext.genCall(context.checkInstanceFunction, args, "") // Check if dst is subclass of src.
|
||||||
return srcArg
|
return srcArg
|
||||||
@@ -1002,7 +1007,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
private fun genInstanceOf(tmpVariableName: String, obj: LLVMValueRef, type: KotlinType): LLVMValueRef {
|
private fun genInstanceOf(tmpVariableName: String, obj: LLVMValueRef, type: KotlinType): LLVMValueRef {
|
||||||
val dstDescriptor = TypeUtils.getClassDescriptor(type) // Get class descriptor for dst type.
|
val dstDescriptor = TypeUtils.getClassDescriptor(type) // Get class descriptor for dst type.
|
||||||
val dstTypeInfo = codegen.typeInfoValue(dstDescriptor!!) // Get TypeInfo 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 args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
|
||||||
|
|
||||||
val result = currentCodeContext.genCall( // Check if dst is subclass of src.
|
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 {
|
private fun evaluateGetField(value: IrGetField): LLVMValueRef {
|
||||||
logger.log("evaluateGetField : ${ir2string(value)}")
|
logger.log("evaluateGetField : ${ir2string(value)}")
|
||||||
if (value.descriptor.dispatchReceiverParameter != null) {
|
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())
|
return codegen.load(fieldPtrOfClass(thisPtr, value.descriptor)!!, codegen.newVar())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1038,7 +1043,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
logger.log("evaluateSetField : ${ir2string(value)}")
|
logger.log("evaluateSetField : ${ir2string(value)}")
|
||||||
val valueToAssign = evaluateExpression(codegen.newVar(), value.value)!!
|
val valueToAssign = evaluateExpression(codegen.newVar(), value.value)!!
|
||||||
if (value.descriptor.dispatchReceiverParameter != null) {
|
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)!!)
|
return codegen.store(valueToAssign, fieldPtrOfClass(thisPtr, value.descriptor)!!)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1082,7 +1087,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
private fun fieldPtrOfClass(thisPtr: LLVMValueRef, value: PropertyDescriptor): LLVMValueRef? {
|
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))
|
val typePtr = pointerType(codegen.classType(value.containingDeclaration as ClassDescriptor))
|
||||||
memScoped {
|
memScoped {
|
||||||
val args = allocArrayOf(kImmOne)
|
val args = allocArrayOf(kImmOne)
|
||||||
@@ -1098,7 +1103,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
private fun evaluateConst(value: IrConst<*>): LLVMValueRef? {
|
private fun evaluateConst(value: IrConst<*>): LLVMValueRef? {
|
||||||
logger.log("evaluateConst : ${ir2string(value)}")
|
logger.log("evaluateConst : ${ir2string(value)}")
|
||||||
when (value.kind) {
|
when (value.kind) {
|
||||||
IrConstKind.Null -> return kNullPtr
|
IrConstKind.Null -> return codegen.kNullObjHeaderPtr
|
||||||
IrConstKind.Boolean -> when (value.value) {
|
IrConstKind.Boolean -> when (value.value) {
|
||||||
true -> return kTrue
|
true -> return kTrue
|
||||||
false -> return kFalse
|
false -> return kFalse
|
||||||
@@ -1212,7 +1217,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
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())
|
||||||
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 {
|
} else {
|
||||||
currentCodeContext.genCall(context.allocInstanceFunction, listOf(typeInfo, allocHint), variableName)
|
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 bbEq2 = codegen.basicBlock() // Block to process "eqeq".
|
||||||
val bbEq3 = codegen.basicBlock() // Block to process "eqeqeq".
|
val bbEq3 = codegen.basicBlock() // Block to process "eqeqeq".
|
||||||
val bbExit = codegen.basicBlock() // Exit block for feather generation.
|
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.condBr(condition, bbEq3, bbEq2) // If (arg0 == null) bbEq3 else bbEq2.
|
||||||
|
|
||||||
codegen.positionAtEnd(bbEq3) // Get generation to bbEq3.
|
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 {
|
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 thisI8PtrPtr = codegen.bitcast(kInt8PtrPtr, args[0], codegen.newVar()) // Cast "this (i8*)" to i8**.
|
||||||
val typeInfoI8Ptr = codegen.load(thisI8PtrPtr, codegen.newVar()) // Load TypeInfo address.
|
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 methodHash = codegen.functionHash(descriptor) // Calculate hash of the method to be invoked
|
||||||
val lookupArgs = listOf(typeInfoPtr, methodHash) // Prepare args for lookup
|
val lookupArgs = listOf(typeInfoPtr, methodHash) // Prepare args for lookup
|
||||||
val llvmMethod = currentCodeContext.genCall(
|
val llvmMethod = currentCodeContext.genCall(
|
||||||
@@ -1401,7 +1396,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
lookupArgs,
|
lookupArgs,
|
||||||
codegen.newVar()) // 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(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
|
val function = codegen.bitcast(functionPtrType, llvmMethod, codegen.newVar()) // Cast method address to the type
|
||||||
return call(descriptor, function, args, result) // Invoke the method
|
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 {
|
fun superCall(result:String, descriptor:ClassConstructorDescriptor, args:List<LLVMValueRef> ): LLVMValueRef {
|
||||||
val tmp = codegen.load(codegen.thisVariable(), codegen.newVar())
|
val rargs = listOf(codegen.thisVariable(), *args.toTypedArray())
|
||||||
val rargs = listOf(tmp, *args.toTypedArray())
|
|
||||||
return callDirect(descriptor, rargs, result)
|
return callDirect(descriptor, rargs, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+25
-2
@@ -97,13 +97,36 @@ internal val int8TypePtr = pointerType(int8Type)
|
|||||||
|
|
||||||
internal val voidType = LLVMVoidType()
|
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 pointerType(pointeeType: LLVMTypeRef?) = LLVMPointerType(pointeeType, 0)!!
|
||||||
|
|
||||||
internal fun structType(vararg types: LLVMTypeRef?): LLVMTypeRef = memScoped {
|
internal fun structType(vararg types: LLVMTypeRef?): LLVMTypeRef = memScoped {
|
||||||
LLVMStructType(allocArrayOf(*types)[0].ptr, types.size, 0)!!
|
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 returnType = getLLVMType(function.returnType!!)
|
||||||
val params = function.dispatchReceiverParameter.singletonOrEmptyList() +
|
val params = function.dispatchReceiverParameter.singletonOrEmptyList() +
|
||||||
function.extensionReceiverParameter.singletonOrEmptyList() +
|
function.extensionReceiverParameter.singletonOrEmptyList() +
|
||||||
@@ -111,7 +134,7 @@ internal fun getLlvmFunctionType(function: FunctionDescriptor): LLVMTypeRef? {
|
|||||||
|
|
||||||
var extraParam = listOf<LLVMTypeRef?>()
|
var extraParam = listOf<LLVMTypeRef?>()
|
||||||
if (function is ClassConstructorDescriptor) {
|
if (function is ClassConstructorDescriptor) {
|
||||||
extraParam += pointerType(LLVMInt8Type())
|
extraParam += kObjHeaderPtr
|
||||||
}
|
}
|
||||||
val paramTypes:List<LLVMTypeRef?> = params.map { getLLVMType(it.type) }
|
val paramTypes:List<LLVMTypeRef?> = params.map { getLLVMType(it.type) }
|
||||||
extraParam += paramTypes
|
extraParam += paramTypes
|
||||||
|
|||||||
Reference in New Issue
Block a user