Constructor (w/o body) (#74)
This commit is contained in:
committed by
Nikolay Igotti
parent
0e1ac89dbf
commit
5161155934
+2
-26
@@ -43,31 +43,7 @@ internal class CodeGenerator(override val context:Context) : ContextUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/* HACK: */
|
||||
var currentClass:ClassDescriptor? = null
|
||||
/* constructor */
|
||||
fun initFunction(declaration: IrConstructor) {
|
||||
function(declaration)
|
||||
val thisPtr = bitcast(pointerType(classType(declaration.descriptor.containingDeclaration)), load(thisVariable(), newVar()), newVar())
|
||||
|
||||
/**
|
||||
* TODO: check shadowing.
|
||||
*/
|
||||
declaration.descriptor.containingDeclaration.fields.forEachIndexed { i, descriptor ->
|
||||
val name = descriptor.name.asString()
|
||||
|
||||
if (!declaration.descriptor.valueParameters.any { it -> it.name.asString() == name })
|
||||
return@forEachIndexed
|
||||
|
||||
val ptr = LLVMBuildStructGEP(context.llvmBuilder, thisPtr, i, newVar())
|
||||
val value = load(variable(name)!!, newVar())
|
||||
|
||||
val typePtr = bitcast(pointerType(LLVMTypeOf(value)), ptr!!, newVar())
|
||||
store(value, typePtr!!)
|
||||
}
|
||||
currentClass = declaration.descriptor.constructedClass
|
||||
}
|
||||
|
||||
fun fields(descriptor: ClassDescriptor):List<PropertyDescriptor> = descriptor.fields
|
||||
|
||||
private fun prolog(declaration: IrFunction): LLVMOpaqueValue? {
|
||||
variableIndex = 0
|
||||
@@ -171,7 +147,7 @@ internal class CodeGenerator(override val context:Context) : ContextUtils {
|
||||
fun thisVariable() = variable("this")!!
|
||||
fun param(fn: FunctionDescriptor?, i: Int): LLVMOpaqueValue? = LLVMGetParam(fn!!.llvmFunction.getLlvmValue(), i)
|
||||
|
||||
fun indexInClass(p:PropertyDescriptor):Int = currentClass!!.fields.indexOf(p)
|
||||
fun indexInClass(p:PropertyDescriptor):Int = (p.containingDeclaration as ClassDescriptor).fields.indexOf(p)
|
||||
|
||||
|
||||
fun basicBlock(): LLVMOpaqueBasicBlock? = LLVMAppendBasicBlock(currentFunction!!.llvmFunction.getLlvmValue(), currentFunction!!.bbLabel())
|
||||
|
||||
+29
-17
@@ -148,17 +148,28 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor) {
|
||||
codegen.initFunction(declaration)
|
||||
val thisValue = codegen.variable("this")
|
||||
//super.visitConstructor(declaration)
|
||||
/**
|
||||
* %this = alloca i8*
|
||||
* store i8* %0, i8** %this <- prolog
|
||||
*
|
||||
* %tmp0 = load i8*, i8** %this <- epilog
|
||||
* ret i8* %tmp0
|
||||
*/
|
||||
codegen.ret(codegen.load(thisValue!!, codegen.newVar()))
|
||||
codegen.function(declaration)
|
||||
val classDescriptor = DescriptorUtils.getContainingClass(declaration.descriptor)
|
||||
val thisPtr = codegen.load(codegen.thisVariable(), codegen.newVar())
|
||||
val typeOfClass = classDescriptor!!.defaultType
|
||||
val names = typeOfClass.memberScope.getVariableNames()
|
||||
val fields = codegen.fields(classDescriptor).toSet()
|
||||
declaration.descriptor.valueParameters
|
||||
.filter { names.contains(it.name) } // selects only parameters that match with declared class variables
|
||||
.map { // maps parameter to list descriptors
|
||||
val variables = typeOfClass.memberScope.getContributedVariables(it.name, NoLookupLocation.FROM_BACKEND)
|
||||
assert(variables.size == 1)
|
||||
variables.first() }
|
||||
.filter {fields.contains(it)} // filter only fields that contains backing store
|
||||
.forEach { // store parameters to backing storage
|
||||
val fieldPtr = fieldPtrOfClass(thisPtr, it)
|
||||
val variable = codegen.variable(it.name.asString())
|
||||
val value = codegen.load(variable!!, codegen.newVar())
|
||||
codegen.store(value, fieldPtr!!)
|
||||
}
|
||||
|
||||
/* TODO: body */
|
||||
codegen.ret(thisPtr)
|
||||
logger.log("visitConstructor : ${ir2string(declaration)}")
|
||||
}
|
||||
|
||||
@@ -450,7 +461,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
logger.log("evaluateGetField : ${ir2string(value)}")
|
||||
if (value.descriptor.dispatchReceiverParameter != null) {
|
||||
val thisPtr = codegen.load(codegen.thisVariable(), codegen.newVar())
|
||||
return codegen.load(fieldPtrOfClass(thisPtr, value)!!, codegen.newVar())
|
||||
return codegen.load(fieldPtrOfClass(thisPtr, value.descriptor)!!, codegen.newVar())
|
||||
}
|
||||
else {
|
||||
val ptr = LLVMGetNamedGlobal(context.llvmModule, value.descriptor.symbolName)!!
|
||||
@@ -465,7 +476,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
val valueToAssign = evaluateExpression(codegen.newVar(), value.value)!!
|
||||
if (value.descriptor.dispatchReceiverParameter != null) {
|
||||
val thisPtr = codegen.load(codegen.thisVariable(), codegen.newVar())
|
||||
return codegen.store(valueToAssign, fieldPtrOfClass(thisPtr, value)!!)
|
||||
return codegen.store(valueToAssign, fieldPtrOfClass(thisPtr, value.descriptor)!!)
|
||||
}
|
||||
else {
|
||||
val globalValue = LLVMGetNamedGlobal(context.llvmModule, value.descriptor.symbolName)
|
||||
@@ -507,14 +518,14 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
}
|
||||
|
||||
*/
|
||||
private fun fieldPtrOfClass(thisPtr: LLVMOpaqueValue, value: IrFieldAccessExpression): LLVMOpaqueValue? {
|
||||
private fun fieldPtrOfClass(thisPtr: LLVMOpaqueValue, value: PropertyDescriptor): LLVMOpaqueValue? {
|
||||
val objHeaderPtr = codegen.bitcast(kObjHeaderPtr, thisPtr, codegen.newVar())
|
||||
val typePtr = pointerType(codegen.classType(codegen.currentClass!!))
|
||||
val typePtr = pointerType(codegen.classType(value.containingDeclaration as ClassDescriptor))
|
||||
memScoped {
|
||||
val args = allocNativeArrayOf(LLVMOpaqueValue, Int32(1).getLlvmValue())
|
||||
val args = allocNativeArrayOf(LLVMOpaqueValue, kImmOne)
|
||||
val objectPtr = LLVMBuildGEP(codegen.context.llvmBuilder, objHeaderPtr, args[0], 1, codegen.newVar())
|
||||
val typedObjPtr = codegen.bitcast(typePtr, objectPtr!!, codegen.newVar())
|
||||
val fieldPtr = LLVMBuildStructGEP(codegen.context.llvmBuilder, typedObjPtr, codegen.indexInClass(value.descriptor), codegen.newVar())
|
||||
val fieldPtr = LLVMBuildStructGEP(codegen.context.llvmBuilder, typedObjPtr, codegen.indexInClass(value), codegen.newVar())
|
||||
return fieldPtr
|
||||
}
|
||||
}
|
||||
@@ -643,6 +654,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
private val kLteq0 = Name.identifier("LTEQ0")
|
||||
private val kNot = Name.identifier("NOT")
|
||||
private val kImmZero = LLVMConstInt(LLVMInt32Type(), 0, 1)!!
|
||||
private val kImmOne = LLVMConstInt(LLVMInt32Type(), 1, 1)!!
|
||||
private val kTrue = LLVMConstInt(LLVMInt1Type(), 1, 1)!!
|
||||
private val kFalse = LLVMConstInt(LLVMInt1Type(), 0, 1)!!
|
||||
|
||||
|
||||
@@ -209,18 +209,23 @@ task run() {
|
||||
task sum (type:UnitKonanTest) {
|
||||
source = "codegen/function/sum.kt"
|
||||
}
|
||||
// FIXME (https://github.com/JetBrains/kotlin-native/pull/74)
|
||||
//task method_call(type: UnitKonanTest) {
|
||||
// source = "codegen/object/method_call.kt"
|
||||
//}
|
||||
|
||||
task method_call(type: UnitKonanTest) {
|
||||
source = "codegen/object/method_call.kt"
|
||||
}
|
||||
|
||||
task fields(type: UnitKonanTest) {
|
||||
source = "codegen/object/fields.kt"
|
||||
}
|
||||
|
||||
/*task objectInitialization(type: UnitKonanTest) {
|
||||
|
||||
task constructor(type: UnitKonanTest) {
|
||||
source = "codegen/object/constructor.kt"
|
||||
}
|
||||
|
||||
task objectInitialization(type: UnitKonanTest) {
|
||||
source = "codegen/object/initialization.kt"
|
||||
}*/
|
||||
}
|
||||
|
||||
/* task objectBasic(type: KonanTest) {
|
||||
source = "$codegen/klass/basic.kt"
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#include <stdint.h>
|
||||
|
||||
extern void *resolve_symbol(const char*);
|
||||
extern void *AllocInstance(void *, int32_t);
|
||||
|
||||
#define CHECK_OBJ(obj, info) if ((uintptr_t)*(obj) != (uintptr_t)(info)) return 1;
|
||||
#define MAGIC0 0xdeadbeef
|
||||
#define MAGIC1 0xcafebabe
|
||||
#define MAGIC2 0xabadbabe
|
||||
|
||||
int
|
||||
run_test() {
|
||||
void *a_type_info = resolve_symbol("ktype:A");
|
||||
void *(*a_init)(void *) = resolve_symbol("kfun:A.<init>()");
|
||||
void *b_type_info = resolve_symbol("ktype:B");
|
||||
void *(*b_init)(void *, int) = resolve_symbol("kfun:B.<init>(Int)");
|
||||
int (*b_get_a)(void *) = resolve_symbol("kfun:B.<get-a>()");
|
||||
void *c_type_info = resolve_symbol("ktype:C");
|
||||
void *(*c_init)(void *, int, int) = resolve_symbol("kfun:C.<init>(Int;Int)");
|
||||
int (*c_get_a)(void *) = resolve_symbol("kfun:C.<get-a>()");
|
||||
|
||||
void **a = (void **)AllocInstance(a_type_info, 1);
|
||||
CHECK_OBJ(a, a_type_info)
|
||||
|
||||
void **b = (void **)AllocInstance(b_type_info, 1);
|
||||
CHECK_OBJ(b, b_type_info)
|
||||
void *b_obj = b_init((void *)b, MAGIC0);
|
||||
CHECK_OBJ(b, b_type_info)
|
||||
if (b_get_a(b_obj) != MAGIC0) return 1;
|
||||
|
||||
|
||||
void **c = (void **)AllocInstance(c_type_info, 1);
|
||||
CHECK_OBJ(c, c_type_info)
|
||||
void *c_obj = c_init((void *)c, 0xcafebabe, 0xabadbabe);
|
||||
CHECK_OBJ(c, c_type_info)
|
||||
if (c_get_a(c_obj) != MAGIC1) return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class A()
|
||||
|
||||
class B(val a:Int)
|
||||
|
||||
class C(val a:Int, b:Int)
|
||||
Reference in New Issue
Block a user