translator: elvis operator, fix includes in build system, gradle jar build

This commit is contained in:
e5l
2016-07-21 13:31:34 +03:00
parent df89bcc490
commit a24cc9732f
13 changed files with 179 additions and 138 deletions
+64 -71
View File
@@ -1,86 +1,72 @@
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.MyClass = type { i32 }
define void @MyClass(%class.MyClass* %classvariable.this, i32 %i)
{
%classvariable.this.addr = alloca %class.MyClass, align 4
%i.addr = alloca i32, align 4
store i32 %i, i32* %i.addr, align 4
%var1 = load i32* %i.addr, align 4
%var2 = getelementptr inbounds %class.MyClass* %classvariable.this.addr, i32 0, i32 0
store i32 %var1, i32* %var2, align 4
%var3 = bitcast %class.MyClass* %classvariable.this to i8*
%var4 = bitcast %class.MyClass* %classvariable.this.addr to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var3, i8* %var4, i64 4, i32 4, i1 false)
ret void
}
%class.ByteArray = type { i32, i32 } %class.ByteArray = type { i32, i32 }
define void @ByteArray(%class.ByteArray* %classvariable.this, i32 %size) define void @ByteArray(%class.ByteArray* %classvariable.this, i32 %size)
{ {
%classvariable.this.addr = alloca %class.ByteArray, align 4 %classvariable.this.addr = alloca %class.ByteArray, align 4
%size.addr = alloca i32, align 4 %size.addr = alloca i32, align 4
store i32 %size, i32* %size.addr, align 4 store i32 %size, i32* %size.addr, align 4
%var5 = load i32* %size.addr, align 4 %var1 = load i32* %size.addr, align 4
%var6 = getelementptr inbounds %class.ByteArray* %classvariable.this.addr, i32 0, i32 0 %var2 = getelementptr inbounds %class.ByteArray* %classvariable.this.addr, i32 0, i32 0
store i32 %var5, i32* %var6, align 4 store i32 %var1, i32* %var2, align 4
%var7 = bitcast %class.ByteArray* %classvariable.this to i8* %var3 = bitcast %class.ByteArray* %classvariable.this to i8*
%var8 = bitcast %class.ByteArray* %classvariable.this.addr to i8* %var4 = bitcast %class.ByteArray* %classvariable.this.addr to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var7, i8* %var8, i64 8, i32 4, i1 false) call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var3, i8* %var4, i64 8, i32 4, i1 false)
%var9 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 1 %var5 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 1
%var10 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 0 %var6 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 0
%var11 = load i32* %var10, align 4 %var7 = load i32* %var6, align 4
%var12 = call i32 @malloc_array(i32 %var11) %var8 = call i32 @malloc_array(i32 %var7)
%var13 = alloca i32, align 4 %var9 = alloca i32, align 4
store i32 %var12, i32* %var13, align 4 store i32 %var8, i32* %var9, align 4
%var14 = load i32* %var9, align 4 %var10 = load i32* %var5, align 4
%var15 = load i32* %var13, align 4 %var11 = load i32* %var9, align 4
store i32 %var15, i32* %var9, align 4 store i32 %var11, i32* %var5, align 4
ret void ret void
} }
define i8 @ByteArray.get(%class.ByteArray* %classvariable.this, i32 %index) define i8 @ByteArray.get(%class.ByteArray* %classvariable.this, i32 %index)
{ {
%index.addr = alloca i32, align 4 %index.addr = alloca i32, align 4
store i32 %index, i32* %index.addr, align 4 store i32 %index, i32* %index.addr, align 4
%var16 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 1 %var12 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 1
%var17 = load i32* %var16, align 4 %var13 = load i32* %var12, align 4
%var18 = load i32* %index.addr, align 4 %var14 = load i32* %index.addr, align 4
%var19 = call i8 @kotlinclib_get_byte(i32 %var17, i32 %var18) %var15 = call i8 @kotlinclib_get_byte(i32 %var13, i32 %var14)
%var20 = alloca i8, align 1 %var16 = alloca i8, align 1
store i8 %var19, i8* %var20, align 1 store i8 %var15, i8* %var16, align 1
%var21 = load i8* %var20, align 1 %var17 = load i8* %var16, align 1
ret i8 %var21 ret i8 %var17
} }
define void @ByteArray.clone(%class.ByteArray** %instance, %class.ByteArray* %classvariable.this) define void @ByteArray.clone(%class.ByteArray** %instance, %class.ByteArray* %classvariable.this)
{ {
%var22 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 0 %var18 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 0
%var23 = load i32* %var22, align 4 %var19 = load i32* %var18, align 4
%var25 = call i8* @malloc(i32 8) %var21 = call i8* @malloc(i32 8)
%var24 = bitcast i8* %var25 to %class.ByteArray* %var20 = bitcast i8* %var21 to %class.ByteArray*
call void @ByteArray(%class.ByteArray* %var24, i32 %var23) call void @ByteArray(%class.ByteArray* %var20, i32 %var19)
%managed.index.1 = alloca i32, align 4 %managed.index.1 = alloca i32, align 4
store i32 0, i32* %managed.index.1, align 4 store i32 0, i32* %managed.index.1, align 4
br label %label.while.1 br label %label.while.1
label.while.1: label.while.1:
%var26 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 0 %var22 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 0
%var27 = load i32* %managed.index.1, align 4 %var23 = load i32* %managed.index.1, align 4
%var28 = load i32* %var26, align 4 %var24 = load i32* %var22, align 4
%var29 = icmp slt i32 %var27, %var28 %var25 = icmp slt i32 %var23, %var24
br i1 %var29, label %label.while.2, label %label.while.3 br i1 %var25, label %label.while.2, label %label.while.3
label.while.2: label.while.2:
%var30 = load i32* %managed.index.1, align 4 %var26 = load i32* %managed.index.1, align 4
%var31 = call i8 @ByteArray.get(%class.ByteArray* %classvariable.this, i32 %var30) %var27 = call i8 @ByteArray.get(%class.ByteArray* %classvariable.this, i32 %var26)
%var32 = alloca i8, align 1 %var28 = alloca i8, align 1
store i8 %var31, i8* %var32, align 1 store i8 %var27, i8* %var28, align 1
%var29 = load i32* %managed.index.1, align 4
%var30 = load i8* %var28, align 1
call void @ByteArray.set(%class.ByteArray* %var20, i32 %var29, i8 %var30)
%var31 = load i32* %managed.index.1, align 4
%var32 = add nsw i32 %var31, 1
%var33 = load i32* %managed.index.1, align 4 %var33 = load i32* %managed.index.1, align 4
%var34 = load i8* %var32, align 1 store i32 %var32, i32* %managed.index.1, align 4
call void @ByteArray.set(%class.ByteArray* %var24, i32 %var33, i8 %var34)
%var35 = load i32* %managed.index.1, align 4
%var36 = add nsw i32 %var35, 1
%var37 = load i32* %managed.index.1, align 4
store i32 %var36, i32* %managed.index.1, align 4
br label %label.while.1 br label %label.while.1
label.while.3: label.while.3:
store %class.ByteArray* %var24, %class.ByteArray** %instance, align 4 store %class.ByteArray* %var20, %class.ByteArray** %instance, align 4
ret void ret void
} }
define void @ByteArray.set(%class.ByteArray* %classvariable.this, i32 %index, i8 %value) define void @ByteArray.set(%class.ByteArray* %classvariable.this, i32 %index, i8 %value)
@@ -89,22 +75,29 @@ define void @ByteArray.set(%class.ByteArray* %classvariable.this, i32 %index,
store i32 %index, i32* %index.addr, align 4 store i32 %index, i32* %index.addr, align 4
%value.addr = alloca i8, align 1 %value.addr = alloca i8, align 1
store i8 %value, i8* %value.addr, align 1 store i8 %value, i8* %value.addr, align 1
%var38 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 1 %var34 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 1
%var39 = load i32* %var38, align 4 %var35 = load i32* %var34, align 4
%var40 = load i32* %index.addr, align 4 %var36 = load i32* %index.addr, align 4
%var41 = load i8* %value.addr, align 1 %var37 = load i8* %value.addr, align 1
call void @kotlinclib_set_byte(i32 %var39, i32 %var40, i8 %var41) call void @kotlinclib_set_byte(i32 %var35, i32 %var36, i8 %var37)
ret void ret void
} }
declare i8 @kotlinclib_get_byte(i32 %src, i32 %index) declare i8 @kotlinclib_get_byte(i32 %src, i32 %index)
define i8 @bytearray_1(i8 %x)
{
%x.addr = alloca i8, align 1
store i8 %x, i8* %x.addr, align 1
%var39 = call i8* @malloc(i32 8)
%var38 = bitcast i8* %var39 to %class.ByteArray*
call void @ByteArray(%class.ByteArray* %var38, i32 10)
%var40 = load i8* %x.addr, align 1
call void @ByteArray.set(%class.ByteArray* %var38, i32 1, i8 %var40)
%var41 = call i8 @ByteArray.get(%class.ByteArray* %var38, i32 1)
%var42 = alloca i8, align 1
store i8 %var41, i8* %var42, align 1
%var43 = load i8* %var42, align 1
ret i8 %var43
}
declare i32 @malloc_array(i32 %size) declare i32 @malloc_array(i32 %size)
declare void @kotlinclib_set_byte(i32 %src, i32 %index, i8 %value) declare void @kotlinclib_set_byte(i32 %src, i32 %index, i8 %value)
define void @createMyClass(%class.MyClass** %instance)
{
%var43 = call i8* @malloc(i32 4)
%var42 = bitcast i8* %var43 to %class.MyClass*
call void @MyClass(%class.MyClass* %var42, i32 1)
store %class.MyClass* %var42, %class.MyClass** %instance, align 4
ret void
}
Binary file not shown.
+1
View File
@@ -10,6 +10,7 @@
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="ast-kotlin_main" />
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib:1.0.1" level="project" /> <orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib:1.0.1" level="project" />
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-compiler:1.0.3" level="project" /> <orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-compiler:1.0.3" level="project" />
<orderEntry type="library" name="Gradle: junit:junit:4.11" level="project" /> <orderEntry type="library" name="Gradle: junit:junit:4.11" level="project" />
+14 -2
View File
@@ -2,16 +2,19 @@ group 'ast-kotlin'
version '1.0-SNAPSHOT' version '1.0-SNAPSHOT'
buildscript { buildscript {
ext.kotlin_version = '1.0.3'
repositories { repositories {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.1" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.2"
} }
} }
apply plugin: 'java' apply plugin: 'java'
apply plugin: 'kotlin' apply plugin: 'kotlin'
apply plugin: 'application'
repositories { repositories {
mavenCentral() mavenCentral()
@@ -19,7 +22,16 @@ repositories {
dependencies { dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:1.0.1" compile "org.jetbrains.kotlin:kotlin-stdlib:1.0.1"
// https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-compiler
compile group: 'org.jetbrains.kotlin', name: 'kotlin-compiler', version: '1.0.3' compile group: 'org.jetbrains.kotlin', name: 'kotlin-compiler', version: '1.0.3'
testCompile group: 'junit', name: 'junit', version: '4.11' testCompile group: 'junit', name: 'junit', version: '4.11'
} }
jar {
manifest {
attributes 'Main-Class': 'MainKt'
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
mainClassName = 'MainKt'
+1 -2
View File
@@ -1,4 +1,3 @@
#!/bin/bash #!/bin/bash
java -jar build/libs/ast-kotlin-1.0-SNAPSHOT.jar $1 > $2
/usr/lib/jvm/default-java/bin/java -Didea.launcher.port=7533 -Didea.launcher.bin.path=/opt/idea-IU-145.1617.8/bin -Dfile.encoding=UTF-8 -classpath /usr/lib/jvm/default-java/jre/lib/charsets.jar:/usr/lib/jvm/default-java/jre/lib/ext/cldrdata.jar:/usr/lib/jvm/default-java/jre/lib/ext/dnsns.jar:/usr/lib/jvm/default-java/jre/lib/ext/icedtea-sound.jar:/usr/lib/jvm/default-java/jre/lib/ext/jaccess.jar:/usr/lib/jvm/default-java/jre/lib/ext/localedata.jar:/usr/lib/jvm/default-java/jre/lib/ext/nashorn.jar:/usr/lib/jvm/default-java/jre/lib/ext/sunec.jar:/usr/lib/jvm/default-java/jre/lib/ext/sunjce_provider.jar:/usr/lib/jvm/default-java/jre/lib/ext/sunpkcs11.jar:/usr/lib/jvm/default-java/jre/lib/ext/zipfs.jar:/usr/lib/jvm/default-java/jre/lib/jce.jar:/usr/lib/jvm/default-java/jre/lib/jsse.jar:/usr/lib/jvm/default-java/jre/lib/management-agent.jar:/usr/lib/jvm/default-java/jre/lib/resources.jar:/usr/lib/jvm/default-java/jre/lib/rt.jar:/home/user/Kotlin/carkot/translator/build/classes/main:/home/user/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.0.1/68cddd9aec83d23f789f72bfdc933db245c4a635/kotlin-stdlib-1.0.1.jar:/home/user/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-compiler/1.0.3/5dbeb14062996a5c2208861d6364cc97a21b06b8/kotlin-compiler-1.0.3.jar:/home/user/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-runtime/1.0.1/124852ea8cdd3d89827923b5e79627e8a7c314b2/kotlin-runtime-1.0.1.jar:/opt/idea-IU-145.1617.8/lib/idea_rt.jar com.intellij.rt.execution.application.AppMain MainKt $1 > $2
+3 -5
View File
@@ -14,11 +14,9 @@ fun main(args: Array<String>) {
val analyzedFiles = ArrayList<String>() val analyzedFiles = ArrayList<String>()
val kotlib = ClassLoader.getSystemClassLoader().getResources("kotlib/kotlin") val kotlib = File("build/resources/main/kotlib/kotlin").listFiles()
for (resource in kotlib) { for (resourse in kotlib) {
for (app in File(resource.toURI()).listFiles()) { analyzedFiles.add(resourse.absolutePath)
analyzedFiles.add(app.absoluteFile.toString())
}
} }
analyzedFiles.addAll(args.toList()) analyzedFiles.addAll(args.toList())
@@ -67,6 +67,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
is KtReferenceExpression -> evaluateReferenceExpression(expr, scopeDepth) is KtReferenceExpression -> evaluateReferenceExpression(expr, scopeDepth)
is KtIfExpression -> evaluateIfOperator(expr.firstChild as LeafPsiElement, scopeDepth + 1, true) is KtIfExpression -> evaluateIfOperator(expr.firstChild as LeafPsiElement, scopeDepth + 1, true)
is KtStringTemplateExpression -> evaluateStringTemplateExpression(expr) is KtStringTemplateExpression -> evaluateStringTemplateExpression(expr)
is KtReturnExpression -> evaluateReturnInstruction(expr.firstChild, scopeDepth)
is PsiWhiteSpace -> null is PsiWhiteSpace -> null
is PsiElement -> evaluatePsiElement(expr, scopeDepth) is PsiElement -> evaluatePsiElement(expr, scopeDepth)
null -> null null -> null
@@ -175,7 +176,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
private fun evaluateReferenceExpression(expr: KtReferenceExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? = when (expr) { private fun evaluateReferenceExpression(expr: KtReferenceExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? = when (expr) {
is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1) is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1)
else -> if ((expr is KtNameReferenceExpression) && (classScope != null)) evaluatenameReferenceExpression(expr, scopeDepth + 1, classScope) else -> if ((expr is KtNameReferenceExpression) && (classScope != null)) evaluatenameReferenceExpression(expr, scopeDepth + 1, classScope)
else variableManager.getLLVMvalue(expr.firstChild.text) else variableManager.getLLVMvalue(expr.firstChild.text)
} }
private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? { private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? {
@@ -217,9 +218,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
callArgs.addAll(loadedArgs) callArgs.addAll(loadedArgs)
return evaluateFunctionCallExpression(LLVMVariable(methodFullName, returnType, scope = LLVMVariableScope()), callArgs) return evaluateFunctionCallExpression(LLVMVariable(methodFullName, returnType, scope = LLVMVariableScope()), callArgs)
} }
} }
val nestedConstructor = classScope?.nestedClasses?.get(expr.calleeExpression!!.text) val nestedConstructor = classScope?.nestedClasses?.get(expr.calleeExpression!!.text)
@@ -306,15 +305,19 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
} }
private fun evaluateBinaryExpression(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable { private fun evaluateBinaryExpression(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable {
val operator = expr.operationToken
if (operator == KtTokens.ELVIS) {
return evaluateElvisOperator(expr, scopeDepth)
}
val left = evaluateExpression(expr.firstChild, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary exception") val left = evaluateExpression(expr.firstChild, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary exception")
val right = evaluateExpression(expr.lastChild, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary exception") val right = evaluateExpression(expr.lastChild, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary exception")
val operator = expr.operationToken
return executeBinaryExpression(operator, expr.operationReference, left, right, scopeDepth) return executeBinaryExpression(operator, expr.operationReference, left, right, scopeDepth)
} }
private fun executeBinaryExpression(operator: IElementType, referenceName: KtSimpleNameExpression?, left: LLVMSingleValue, right: LLVMSingleValue, scopeDepth: Int): LLVMVariable { private fun executeBinaryExpression(operator: IElementType, referenceName: KtSimpleNameExpression?, left: LLVMSingleValue, right: LLVMSingleValue, scopeDepth: Int): LLVMVariable {
val result = codeBuilder.addPrimitiveBinaryOperation(operator, referenceName, left, right) val result = addPrimitiveBinaryOperation(operator, referenceName, left, right)
if (left.type is LLVMReferenceType && left.pointer > 0 && right.pointer > 0) { if (left.type is LLVMReferenceType && left.pointer > 0 && right.pointer > 0) {
variableManager.addVariable((left as LLVMVariable).kotlinName!!, result, scopeDepth) variableManager.addVariable((left as LLVMVariable).kotlinName!!, result, scopeDepth)
@@ -323,6 +326,80 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
return result return result
} }
private fun evaluateElvisOperator(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable {
val left = evaluateExpression(expr.firstChild, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary exception")
val condition = left.type!!.operatorEq(left, LLVMVariable("", LLVMNullType()))
val conditionResult = codeBuilder.getNewVariable(condition.variableType)
codeBuilder.addAssignment(conditionResult, condition)
val elvisResult = codeBuilder.getNewVariable(left.type!!, pointer = left.pointer)
codeBuilder.allocStackVar(elvisResult)
elvisResult.pointer++
val thenLabel = codeBuilder.getNewLabel(prefix = "elvis")
val elseLabel = codeBuilder.getNewLabel(prefix = "elvis")
val endLabel = codeBuilder.getNewLabel(prefix = "elvis")
codeBuilder.addCondition(conditionResult, thenLabel, elseLabel)
codeBuilder.markWithLabel(thenLabel)
codeBuilder.storeVariable(elvisResult, left)
codeBuilder.addUnconditionalJump(endLabel)
codeBuilder.markWithLabel(elseLabel)
val right = evaluateExpression(expr.lastChild, scopeDepth + 1)
if (right != null) {
codeBuilder.storeVariable(elvisResult, right)
}
codeBuilder.addUnconditionalJump(endLabel)
codeBuilder.markWithLabel(endLabel)
return elvisResult
}
private fun addPrimitiveBinaryOperation(operator: IElementType, referenceName: KtSimpleNameExpression?, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMVariable {
val firstNativeOp = codeBuilder.receiveNativeValue(firstOp)
val secondNativeOp = codeBuilder.receiveNativeValue(secondOp)
val llvmExpression = when (operator) {
KtTokens.PLUS -> firstOp.type!!.operatorPlus(firstNativeOp, secondNativeOp)
KtTokens.MINUS -> firstOp.type!!.operatorMinus(firstNativeOp, secondNativeOp)
KtTokens.MUL -> firstOp.type!!.operatorTimes(firstNativeOp, secondNativeOp)
KtTokens.LT -> firstOp.type!!.operatorLt(firstNativeOp, secondNativeOp)
KtTokens.GT -> firstOp.type!!.operatorGt(firstNativeOp, secondNativeOp)
KtTokens.LTEQ -> firstOp.type!!.operatorLeq(firstNativeOp, secondNativeOp)
KtTokens.GTEQ -> firstOp.type!!.operatorGeq(firstNativeOp, secondNativeOp)
KtTokens.EQEQ ->
if (firstOp.type is LLVMReferenceType)
firstOp.type!!.operatorEq(firstOp, secondOp)
else
firstOp.type!!.operatorEq(firstNativeOp, secondNativeOp)
KtTokens.EXCLEQ -> firstOp.type!!.operatorNeq(firstNativeOp, secondNativeOp)
KtTokens.EQ -> {
if (secondOp.type is LLVMNullType) {
val result = codeBuilder.getNewVariable(firstOp.type!!, firstOp.pointer)
codeBuilder.allocStackVar(result)
result.pointer++
codeBuilder.storeNull(result)
return result
}
if (firstOp.type is LLVMReferenceType && firstOp.pointer > 0 && secondOp.pointer > 0) {
return secondOp as LLVMVariable
}
val result = firstOp as LLVMVariable
codeBuilder.storeVariable(result, secondNativeOp)
return result
}
else -> codeBuilder.addPrimitiveReferenceOperation(referenceName!!, firstNativeOp, secondNativeOp)
}
val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType)
codeBuilder.addAssignment(resultOp, llvmExpression)
return resultOp
}
private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMConstant { private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMConstant {
val node = expr.node val node = expr.node
@@ -535,17 +612,21 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
return null return null
} }
private fun evaluateReturnInstruction(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? { private fun evaluateReturnInstruction(element: PsiElement, scopeDepth: Int): LLVMVariable? {
val next = element.getNextSiblingIgnoringWhitespaceAndComments() val next = element.getNextSiblingIgnoringWhitespaceAndComments()
val retVar = evaluateExpression(next, scopeDepth) as LLVMSingleValue val retVar = evaluateExpression(next, scopeDepth)
val type = retVar?.type ?: LLVMVoidType()
when (returnType!!.type) { when (type) {
is LLVMReferenceType -> { is LLVMReferenceType -> {
codeBuilder.storeVariable(returnType!!, retVar) codeBuilder.storeVariable(returnType!!, retVar!!)
codeBuilder.addAnyReturn(LLVMVoidType())
}
is LLVMVoidType -> {
codeBuilder.addAnyReturn(LLVMVoidType()) codeBuilder.addAnyReturn(LLVMVoidType())
} }
else -> { else -> {
val retNativeValue = codeBuilder.receiveNativeValue(retVar) val retNativeValue = codeBuilder.receiveNativeValue(retVar!!)
codeBuilder.addReturnOperator(retNativeValue) codeBuilder.addReturnOperator(retNativeValue)
} }
} }
@@ -70,57 +70,14 @@ class LLVMBuilder(val arm: Boolean) {
} }
} }
fun addPrimitiveBinaryOperation(operation: IElementType, referenceName: KtSimpleNameExpression?, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMVariable {
val firstNativeOp = receiveNativeValue(firstOp)
val secondNativeOp = receiveNativeValue(secondOp)
val llvmExpression = when (operation) {
KtTokens.PLUS -> firstOp.type!!.operatorPlus(firstNativeOp, secondNativeOp)
KtTokens.MINUS -> firstOp.type!!.operatorMinus(firstNativeOp, secondNativeOp)
KtTokens.MUL -> firstOp.type!!.operatorTimes(firstNativeOp, secondNativeOp)
KtTokens.LT -> firstOp.type!!.operatorLt(firstNativeOp, secondNativeOp)
KtTokens.GT -> firstOp.type!!.operatorGt(firstNativeOp, secondNativeOp)
KtTokens.LTEQ -> firstOp.type!!.operatorLeq(firstNativeOp, secondNativeOp)
KtTokens.GTEQ -> firstOp.type!!.operatorGeq(firstNativeOp, secondNativeOp)
KtTokens.EQEQ ->
if (firstOp.type is LLVMReferenceType)
firstOp.type!!.operatorEq(firstOp, secondOp)
else
firstOp.type!!.operatorEq(firstNativeOp, secondNativeOp)
KtTokens.EXCLEQ -> firstOp.type!!.operatorNeq(firstNativeOp, secondNativeOp)
KtTokens.EQ -> {
if (secondOp.type is LLVMNullType) {
val result = getNewVariable(firstOp.type!!, firstOp.pointer)
allocStackVar(result)
result.pointer++
storeNull(result)
return result
}
if (firstOp.type is LLVMReferenceType && firstOp.pointer > 0 && secondOp.pointer > 0) {
return secondOp as LLVMVariable
}
val result = firstOp as LLVMVariable
storeVariable(result, secondNativeOp)
return result
}
else -> addPrimitiveReferenceOperation(referenceName!!, firstNativeOp, secondNativeOp)
}
val resultOp = getNewVariable(llvmExpression.variableType)
addAssignment(resultOp, llvmExpression)
return resultOp
}
fun clean() { fun clean() {
localCode = StringBuilder() localCode = StringBuilder()
globalCode = StringBuilder() globalCode = StringBuilder()
initBuilder() initBuilder()
} }
fun addAssignment(llvmVariable: LLVMVariable, rhs: LLVMNode) { fun addAssignment(lhs: LLVMVariable, rhs: LLVMNode) {
localCode.appendln("$llvmVariable = $rhs") localCode.appendln("$lhs = $rhs")
} }
fun addReturnOperator(llvmVariable: LLVMSingleValue) { fun addReturnOperator(llvmVariable: LLVMSingleValue) {
@@ -8,11 +8,11 @@ fun if_test_1(x: Int): Int {
return a return a
} }
class MyClass(i: Int) class MyClass2(i: Int)
fun if_test_null(x: Int): Int { fun if_test_null(x: Int): Int {
val y: MyClass? = null val y: MyClass2? = null
if (y == null) { if (y == null) {
return 1 return 1
} else { } else {
@@ -21,7 +21,7 @@ fun if_test_null(x: Int): Int {
} }
fun if_test_null_2(x: Int): Int { fun if_test_null_2(x: Int): Int {
val y: MyClass? = MyClass(1) val y: MyClass2? = MyClass2(1)
if (y == null) { if (y == null) {
return 1 return 1