tranlator: nested classes declaration
This commit is contained in:
@@ -1,40 +1,39 @@
|
|||||||
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)
|
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)
|
||||||
declare i8* @malloc(i32)
|
declare i8* @malloc(i32)
|
||||||
%class.MyAwesomeClass = type { i32 }
|
%class.Outer = type { }
|
||||||
define void @MyAwesomeClass(%class.MyAwesomeClass* %classvariable.this, i32 %i)
|
define void @Outer(%class.Outer* %classvariable.this)
|
||||||
{
|
{
|
||||||
%classvariable.this.addr = alloca %class.MyAwesomeClass, align 4
|
%classvariable.this.addr = alloca %class.Outer, align 4
|
||||||
%i.addr = alloca i32, align 4
|
%var1 = bitcast %class.Outer* %classvariable.this to i8*
|
||||||
store i32 %i, i32* %i.addr, align 4
|
%var2 = bitcast %class.Outer* %classvariable.this.addr to i8*
|
||||||
%var1 = load i32* %i.addr, align 4
|
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var1, i8* %var2, i64 0, i32 4, i1 false)
|
||||||
%var2 = getelementptr inbounds %class.MyAwesomeClass* %classvariable.this.addr, i32 0, i32 0
|
|
||||||
store i32 %var1, i32* %var2, align 4
|
|
||||||
%var3 = bitcast %class.MyAwesomeClass* %classvariable.this to i8*
|
|
||||||
%var4 = bitcast %class.MyAwesomeClass* %classvariable.this.addr to i8*
|
|
||||||
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var3, i8* %var4, i64 4, i32 4, i1 false)
|
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
define i32 @nullable_test(i32 %i)
|
define void @Outer.main(%class.Outer* %instance, %class.Outer* %classvariable.this)
|
||||||
{
|
{
|
||||||
%i.addr = alloca i32, align 4
|
%var4 = call i8* @malloc(i32 0)
|
||||||
store i32 %i, i32* %i.addr, align 4
|
%var3 = bitcast i8* %var4 to %class.Outer*
|
||||||
%var6 = call i8* @malloc(i32 4)
|
call void @Outer(%class.Outer* %var3)
|
||||||
%var5 = bitcast i8* %var6 to %class.MyAwesomeClass*
|
%var5 = bitcast %class.Outer* %var3 to i8*
|
||||||
call void @MyAwesomeClass(%class.MyAwesomeClass* %var5, i32 1)
|
%var6 = bitcast %class.Outer* %instance to i8*
|
||||||
%var8 = call i8* @malloc(i32 4)
|
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var6, i8* %var5, i64 0, i32 4, i1 false)
|
||||||
%var7 = bitcast i8* %var8 to %class.MyAwesomeClass*
|
ret void
|
||||||
call void @MyAwesomeClass(%class.MyAwesomeClass* %var7, i32 2)
|
|
||||||
%var9 = load %class.MyAwesomeClass* %var5, align 4
|
|
||||||
%var10 = load %class.MyAwesomeClass* %var7, align 4
|
|
||||||
%var11 = getelementptr inbounds %class.MyAwesomeClass* %var7, i32 0, i32 0
|
|
||||||
%var12 = load i32* %var11, align 4
|
|
||||||
ret i32 %var12
|
|
||||||
}
|
}
|
||||||
define void @main()
|
%class.Outer_Nested = type { i32 }
|
||||||
|
define void @Outer_Nested(%class_Outer.Nested* %classvariable.this)
|
||||||
|
{
|
||||||
|
%classvariable.this.addr = alloca %class_Outer.Nested, align 4
|
||||||
|
%var7 = bitcast %class_Outer.Nested* %classvariable.this to i8*
|
||||||
|
%var8 = bitcast %class_Outer.Nested* %classvariable.this.addr to i8*
|
||||||
|
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var7, i8* %var8, i64 4, i32 4, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
define void @Outer.Nested.main(%class_Outer.Nested* %classvariable.this)
|
||||||
|
{
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
define void @test()
|
||||||
{
|
{
|
||||||
%var13 = call i32 @nullable_test(i32 0)
|
|
||||||
%var14 = alloca i32, align 4
|
|
||||||
store i32 %var13, i32* %var14, align 4
|
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ for i in $( ls "$DIRECTORY/input"); do
|
|||||||
clang-3.6 -S -emit-llvm $DIRECTORY/linked/main.c -o $DIRECTORY/linked/main.ll -Wno-implicit-function-declaration
|
clang-3.6 -S -emit-llvm $DIRECTORY/linked/main.c -o $DIRECTORY/linked/main.ll -Wno-implicit-function-declaration
|
||||||
rm -f $DIRECTORY/linked/main.c
|
rm -f $DIRECTORY/linked/main.c
|
||||||
|
|
||||||
cp /home/user/Kotlin/carkot/translator/src/main/resources/kotllib/* $DIRECTORY/linked/
|
cp ./src/main/resources/kotllib/* $DIRECTORY/linked/
|
||||||
|
|
||||||
if [ -f "$DIRECTORY/c/$TEST.c" ]
|
if [ -f "$DIRECTORY/c/$TEST.c" ]
|
||||||
then
|
then
|
||||||
|
|||||||
@@ -89,10 +89,22 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
|||||||
|
|
||||||
private fun evaluateDotExpression(expr: KtDotQualifiedExpression, scopeDepth: Int): LLVMSingleValue? {
|
private fun evaluateDotExpression(expr: KtDotQualifiedExpression, scopeDepth: Int): LLVMSingleValue? {
|
||||||
val receiverName = expr.receiverExpression.text
|
val receiverName = expr.receiverExpression.text
|
||||||
val selectorName = expr.selectorExpression!!.text
|
val selectorName = expr.selectorExpression!!.text!!
|
||||||
|
|
||||||
val receiver = variableManager.getLLVMvalue(receiverName)!!
|
val receiver = variableManager.getLLVMvalue(receiverName)
|
||||||
|
if (receiver != null) {
|
||||||
|
return evaluateMemberMethodOrField(receiver, selectorName, scopeDepth, expr.lastChild)
|
||||||
|
}
|
||||||
|
|
||||||
|
val clazz = state.classes.get(receiverName) ?: return null
|
||||||
|
return evaluateClassScopedDotExpression(clazz, selectorName, scopeDepth)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun evaluateClassScopedDotExpression(clazz: ClassCodegen, selectorName: String, scopeDepth: Int): LLVMSingleValue? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun evaluateMemberMethodOrField(receiver: LLVMVariable, selectorName: String, scopeDepth: Int, call: PsiElement): LLVMSingleValue? {
|
||||||
val clazz = state.classes[(receiver.type as LLVMReferenceType).type] ?: state.objects[(receiver.type as LLVMReferenceType).type]!!
|
val clazz = state.classes[(receiver.type as LLVMReferenceType).type] ?: state.objects[(receiver.type as LLVMReferenceType).type]!!
|
||||||
val field = clazz.fieldsIndex[selectorName]
|
val field = clazz.fieldsIndex[selectorName]
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
@@ -104,7 +116,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
|||||||
val method = clazz.methods[methodName]!!
|
val method = clazz.methods[methodName]!!
|
||||||
val returnType = clazz.methods[methodName]!!.returnType!!.type
|
val returnType = clazz.methods[methodName]!!.returnType!!.type
|
||||||
|
|
||||||
val names = parseArgList(expr.lastChild as KtCallExpression, scopeDepth)
|
val names = parseArgList(call as KtCallExpression, scopeDepth)
|
||||||
val loadedArgs = loadArgsIfRequired(names, method.args)
|
val loadedArgs = loadArgsIfRequired(names, method.args)
|
||||||
val callArgs = mutableListOf<LLVMSingleValue>(receiver)
|
val callArgs = mutableListOf<LLVMSingleValue>(receiver)
|
||||||
callArgs.addAll(loadedArgs)
|
callArgs.addAll(loadedArgs)
|
||||||
|
|||||||
@@ -10,25 +10,33 @@ import org.kotlinnative.translator.llvm.LLVMBuilder
|
|||||||
import org.kotlinnative.translator.llvm.LLVMClassVariable
|
import org.kotlinnative.translator.llvm.LLVMClassVariable
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMEnumItemType
|
import org.kotlinnative.translator.llvm.types.LLVMEnumItemType
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
|
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
|
||||||
|
|
||||||
class ClassCodegen(override val state: TranslationState, override val variableManager: VariableManager, val clazz: KtClass, override val codeBuilder: LLVMBuilder) :
|
class ClassCodegen(override val state: TranslationState,
|
||||||
StructCodegen(state, variableManager, clazz, state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException(), codeBuilder) {
|
override val variableManager: VariableManager,
|
||||||
|
val clazz: KtClass,
|
||||||
|
override val codeBuilder: LLVMBuilder,
|
||||||
|
prefix: String = "") :
|
||||||
|
|
||||||
|
StructCodegen(state, variableManager, clazz, state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException(), codeBuilder, prefix) {
|
||||||
|
|
||||||
val annotation: Boolean
|
val annotation: Boolean
|
||||||
|
|
||||||
override var size: Int = 0
|
override var size: Int = 0
|
||||||
override val structName: String
|
override val structName: String
|
||||||
override val type: LLVMType = LLVMReferenceType(clazz.name.toString(), "class", byRef = true)
|
override val type: LLVMReferenceType = LLVMReferenceType(clazz.name.toString(), "class", byRef = true)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
structName = clazz.name.toString()
|
structName = clazz.name!!
|
||||||
val descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException()
|
val descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException()
|
||||||
val parameterList = clazz.getPrimaryConstructorParameterList()?.parameters ?: listOf()
|
val parameterList = clazz.getPrimaryConstructorParameterList()?.parameters ?: listOf()
|
||||||
|
|
||||||
annotation = descriptor.kind == ClassKind.ANNOTATION_CLASS
|
annotation = descriptor.kind == ClassKind.ANNOTATION_CLASS
|
||||||
indexFields(descriptor, parameterList)
|
indexFields(descriptor, parameterList)
|
||||||
generateInnerFields(clazz.declarations)
|
generateInnerFields(clazz.declarations)
|
||||||
|
|
||||||
|
if (prefix.length > 0) {
|
||||||
|
type.prefix = "${type.prefix}_$prefix"
|
||||||
|
}
|
||||||
type.size = size
|
type.size = size
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,6 +72,7 @@ class ClassCodegen(override val state: TranslationState, override val variableMa
|
|||||||
}
|
}
|
||||||
|
|
||||||
generate(clazz.declarations)
|
generate(clazz.declarations)
|
||||||
|
nestedClasses.forEach { x, classCodegen -> classCodegen.generate() }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ class FileTranslator(val state: TranslationState, val file: KtFile) {
|
|||||||
property.generate()
|
property.generate()
|
||||||
}
|
}
|
||||||
|
|
||||||
for (objectDeclaration in state.objects.values) {
|
for (objectCodegen in state.objects.values) {
|
||||||
objectDeclaration.generate()
|
objectCodegen.generate()
|
||||||
}
|
}
|
||||||
|
|
||||||
for (clazz in state.classes.values) {
|
for (clazz in state.classes.values) {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class ObjectCodegen(override val state: TranslationState, override val variableM
|
|||||||
codeBuilder) {
|
codeBuilder) {
|
||||||
override var size: Int = 0
|
override var size: Int = 0
|
||||||
override val structName: String
|
override val structName: String
|
||||||
override val type: LLVMType = LLVMReferenceType(objectDeclaration.name.toString(), "class", byRef = true)
|
override val type: LLVMReferenceType = LLVMReferenceType(objectDeclaration.name.toString(), "class", byRef = true)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
structName = objectDeclaration.name!!
|
structName = objectDeclaration.name!!
|
||||||
|
|||||||
@@ -12,19 +12,26 @@ import org.kotlinnative.translator.llvm.types.LLVMType
|
|||||||
import org.kotlinnative.translator.llvm.types.LLVMVoidType
|
import org.kotlinnative.translator.llvm.types.LLVMVoidType
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
abstract class StructCodegen(open val state: TranslationState, open val variableManager: VariableManager, open val classOrObject: KtClassOrObject,
|
abstract class StructCodegen(open val state: TranslationState,
|
||||||
|
open val variableManager: VariableManager,
|
||||||
|
open val classOrObject: KtClassOrObject,
|
||||||
val classDescriptor: ClassDescriptor,
|
val classDescriptor: ClassDescriptor,
|
||||||
open val codeBuilder: LLVMBuilder) {
|
open val codeBuilder: LLVMBuilder,
|
||||||
|
val prefix: String = "") {
|
||||||
|
|
||||||
val fields = ArrayList<LLVMVariable>()
|
val fields = ArrayList<LLVMVariable>()
|
||||||
val fieldsIndex = HashMap<String, LLVMClassVariable>()
|
val fieldsIndex = HashMap<String, LLVMClassVariable>()
|
||||||
|
val nestedClasses = HashMap<String, ClassCodegen>()
|
||||||
|
|
||||||
val constructorFields = ArrayList<LLVMVariable>()
|
val constructorFields = ArrayList<LLVMVariable>()
|
||||||
|
|
||||||
abstract val type: LLVMType
|
abstract val type: LLVMReferenceType
|
||||||
abstract var size: Int
|
abstract var size: Int
|
||||||
var methods = HashMap<String, FunctionCodegen>()
|
var methods = HashMap<String, FunctionCodegen>()
|
||||||
abstract val structName: String
|
abstract val structName: String
|
||||||
|
val fullName: String
|
||||||
|
get() = "${if (prefix.length > 0) "${prefix}_" else ""}$structName"
|
||||||
|
|
||||||
|
|
||||||
fun generate(declarations: List<KtDeclaration>) {
|
fun generate(declarations: List<KtDeclaration>) {
|
||||||
generateStruct()
|
generateStruct()
|
||||||
@@ -60,14 +67,19 @@ abstract class StructCodegen(open val state: TranslationState, open val variable
|
|||||||
fieldsIndex[field.label] = field
|
fieldsIndex[field.label] = field
|
||||||
size += field.type.size
|
size += field.type.size
|
||||||
}
|
}
|
||||||
|
is KtClass -> {
|
||||||
|
nestedClasses.put(declaration.name!!,
|
||||||
|
ClassCodegen(state,
|
||||||
|
VariableManager(state.globalVariableCollection),
|
||||||
|
declaration, codeBuilder,
|
||||||
|
fullName))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateStruct() {
|
private fun generateStruct() {
|
||||||
val name = classDescriptor.name.identifier
|
codeBuilder.createClass(fullName, fields)
|
||||||
|
|
||||||
codeBuilder.createClass(name, fields)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generatePrimaryConstructor() {
|
private fun generatePrimaryConstructor() {
|
||||||
@@ -82,7 +94,7 @@ abstract class StructCodegen(open val state: TranslationState, open val variable
|
|||||||
argFields.add(classVal)
|
argFields.add(classVal)
|
||||||
argFields.addAll(constructorFields)
|
argFields.addAll(constructorFields)
|
||||||
|
|
||||||
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(classDescriptor.name.identifier, argFields, LLVMVoidType(), arm = state.arm))
|
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(fullName, argFields, LLVMVoidType(), arm = state.arm))
|
||||||
|
|
||||||
codeBuilder.addStartExpression()
|
codeBuilder.addStartExpression()
|
||||||
generateLoadArguments(classVal)
|
generateLoadArguments(classVal)
|
||||||
|
|||||||
Reference in New Issue
Block a user