translator: class allocation

This commit is contained in:
e5l
2016-07-18 16:08:37 +03:00
parent 3080970362
commit 8369cecda5
10 changed files with 128 additions and 165 deletions
+5 -1
View File
@@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CidrRootsConfiguration">
<sourceRoots />
<libraryRoots />
<excludeRoots />
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
@@ -10,7 +15,6 @@
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_3" default="true" assert-keyword="false" jdk-15="false" />
<component name="masterDetails">
<states>
<state key="ProjectJDKs.UI">
+16 -61
View File
@@ -1,78 +1,33 @@
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)
declare i8* @malloc_static(i32)
attributes #0 = { nounwind "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+hwdiv,+strict-align" }
@CAR_MODE_REMOTE_CONTROL = global i32 1, align 4
@PROGRAM_DURATIOH_MS = global i32 3000, align 4
@CAR_MODE_LAST = global i32 2, align 4
@CAR_MODE_PROGRAMMED = global i32 0, align 4
%class.MyClass = type { i32, i16, i8 }
define void @MyClass(%class.MyClass* %instance, i32 %i, i16 %j, i8 %k) #0
%class.Simple = type { i32 }
define void @Simple(%class.Simple* %classvariable.this, i32 %i) #0
{
%instance.addr = alloca %class.MyClass, align 4
%classvariable.this.addr = alloca %class.Simple, align 4
%i.addr = alloca i32, align 4
store i32 %i, i32* %i.addr, align 4
%j.addr = alloca i16, align 2
store i16 %j, i16* %j.addr, align 2
%k.addr = alloca i8, align 1
store i8 %k, i8* %k.addr, align 1
%var1 = load i32* %i.addr, align 4
%var2 = getelementptr inbounds %class.MyClass* %instance.addr, i32 0, i32 0
%var2 = getelementptr inbounds %class.Simple* %classvariable.this.addr, i32 0, i32 0
store i32 %var1, i32* %var2, align 4
%var3 = load i16* %j.addr, align 2
%var4 = getelementptr inbounds %class.MyClass* %instance.addr, i32 0, i32 1
store i16 %var3, i16* %var4, align 2
%var5 = load i8* %k.addr, align 1
%var6 = getelementptr inbounds %class.MyClass* %instance.addr, i32 0, i32 2
store i8 %var5, i8* %var6, align 1
%var7 = bitcast %class.MyClass* %instance to i8*
%var8 = bitcast %class.MyClass* %instance.addr to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var7, i8* %var8, i64 7, i32 4, i1 false)
%var3 = bitcast %class.Simple* %classvariable.this to i8*
%var4 = bitcast %class.Simple* %classvariable.this.addr to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var3, i8* %var4, i64 4, i32 4, i1 false)
ret void
}
declare void @wait(i32 %i) #0
define void @engine_program() #0
define void @a() #0
{
call void @engine_init()
br label %label.while.1
label.while.1:
%var9 = icmp slt i32 2, 3
br i1 %var9, label %label.while.2, label %label.while.3
label.while.2:
call void @engine_forward()
%var10 = load i32* @PROGRAM_DURATIOH_MS, align 4
call void @wait(i32 %var10)
call void @engine_stop()
call void @engine_backward()
%var11 = load i32* @PROGRAM_DURATIOH_MS, align 4
call void @wait(i32 %var11)
call void @engine_stop()
call void @engine_turn_right()
%var12 = load i32* @PROGRAM_DURATIOH_MS, align 4
call void @wait(i32 %var12)
call void @engine_stop()
call void @engine_turn_right()
%var13 = load i32* @PROGRAM_DURATIOH_MS, align 4
call void @wait(i32 %var13)
call void @engine_stop()
br label %label.while.1
label.while.3:
ret void
}
declare void @time_init() #0
declare void @leds_init() #0
declare void @engine_init() #0
declare void @run_rc_car(void ()* %i) #0
declare void @engine_backward() #0
define void @kotlin_main() #0
{
call void @time_init()
call void @engine_program()
%var6 = call i8* @malloc_static(i32 4)
%var5 = bitcast i8* %var6 to %class.Simple*
call void @Simple(%class.Simple* %var5, i32 5)
%managed.s.1 = alloca %class.Simple, align 4
%var7 = load %class.Simple* %var5, align 4
store %class.Simple %var7, %class.Simple* %managed.s.1, align 4
call void @a()
ret void
}
declare void @VCP_init() #0
declare void @engine_stop() #0
declare void @user_brn_init(void ()* %i) #0
declare void @engine_forward() #0
declare void @run_programmed_car(void ()* %i) #0
declare void @engine_turn_left() #0
declare void @engine_turn_right() #0
-6
View File
@@ -81,9 +81,3 @@ define i8* @malloc_dynamic(i32 %size) #0 {
attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.module.flags = !{!0, !1}
!llvm.ident = !{!2}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 1, !"min_enum_size", i32 4}
!2 = !{!"Ubuntu clang version 3.6.2-3ubuntu2 (tags/RELEASE_362/final) (based on LLVM 3.6.2)"}
+1 -1
View File
@@ -102,7 +102,7 @@ fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:function=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
@@ -1,22 +1,22 @@
package org.kotlinnative.translator
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.KtUserType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.annotations.argumentValue
import org.kotlinnative.translator.exceptions.TranslationException
import org.kotlinnative.translator.llvm.*
import org.kotlinnative.translator.llvm.types.*
import org.kotlinnative.translator.llvm.types.LLVMCharType
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
import org.kotlinnative.translator.llvm.types.LLVMType
import org.kotlinnative.translator.llvm.types.LLVMVoidType
import java.util.*
class ClassCodegen(val state: TranslationState, val variableManager: VariableManager, val clazz: KtClass, val codeBuilder: LLVMBuilder) {
val annotation: Boolean
val native: Boolean
val plain: Boolean = false // TODO
val fields = ArrayList<LLVMVariable>()
val fieldsIndex = HashMap<String, LLVMClassVariable>()
val type: LLVMType = LLVMReferenceType(clazz.name.toString(), "class", byRef = true)
@@ -33,8 +33,7 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
if (!annotation) {
for (field in parameterList) {
val type = getNativeType(field) ?: parseLLVMType((field.typeReference?.typeElement as KtUserType).referencedName!!)
val item = LLVMClassVariable(field.name!!, type, offset)
val item = resolveType(field)
fields.add(item)
fieldsIndex[item.label] = item
@@ -44,7 +43,6 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
}
}
native = isNative(descriptor.annotations)
size = currentSize
}
@@ -65,7 +63,7 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
}
}
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
variableManager.addVariable("this", classVal, 0);
variableManager.addVariable("this", classVal, 0)
for (function in methods.values) {
function.generate(classVal)
}
@@ -84,7 +82,7 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
refType.byRef = true
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
variableManager.addVariable("this", classVal, 0);
variableManager.addVariable("this", classVal, 0)
argFields.add(classVal)
argFields.addAll(fields)
@@ -124,34 +122,40 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
val dst = LLVMVariable("classvariable.this", type, scope = LLVMRegisterScope(), pointer = 1)
val src = LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1)
val castedDst = codeBuilder.bitcast(dst, LLVMCharType())
val castedSrc = codeBuilder.bitcast(src, LLVMCharType())
val castedDst = codeBuilder.bitcast(dst, LLVMVariable("", LLVMCharType(), pointer = 1))
val castedSrc = codeBuilder.bitcast(src, LLVMVariable("", LLVMCharType(), pointer = 1))
codeBuilder.memcpy(castedDst, castedSrc, size)
}
private fun getNativeType(field: KtParameter): LLVMType? {
private fun resolveType(field: KtParameter): LLVMClassVariable {
val annotations = parseFieldAnnotations(field)
val ktType = state.bindingContext.get(BindingContext.TYPE, field.typeReference)!!
val result = LLVMMapStandardType(field.name!!, ktType, LLVMRegisterScope())
if (result.type is LLVMReferenceType) {
(result.type as LLVMReferenceType).prefix = "class"
}
if (annotations.contains("Plain")) {
result.pointer = 0
}
return LLVMClassVariable(result.label, result.type, result.pointer)
}
private fun parseFieldAnnotations(field: KtParameter): Set<String> {
val result = HashSet<String>()
for (annotation in field.annotationEntries) {
val annotationDescriptor = state.bindingContext.get(BindingContext.ANNOTATION, annotation)
val type = annotationDescriptor?.type.toString()
if (type == "Native") {
return parseLLVMType(annotationDescriptor!!.argumentValue("type").toString())
}
result.add(type)
}
return null
}
private fun isNative(annotations: Annotations?): Boolean {
annotations ?: return false
for (i in annotations) {
if (i.type.toString() == "Native") {
return true
}
}
return false
return result
}
}
@@ -228,7 +228,7 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
if (state.classes.containsKey(function)) {
val descriptor = state.classes[function] ?: return null
return evaluateConstructorCallExpression(function, names, descriptor.type)
return evaluateConstructorCallExpression(LLVMVariable(function, descriptor.type, scope = LLVMVariableScope()), names)
}
val localFunction = variableManager.getLLVMvalue(function)
@@ -259,9 +259,8 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
codeBuilder.addLLVMCode(LLVMCall(LLVMVoidType(), function.toString(), names).toString())
}
is LLVMReferenceType -> {
val result = codeBuilder.getNewVariable(returnType)
codeBuilder.allocVar(result)
result.pointer = 1
val result = codeBuilder.getNewVariable(returnType, pointer = 1)
codeBuilder.allocStaticVar(result)
val args = ArrayList<LLVMSingleValue>()
args.add(result)
@@ -276,7 +275,7 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
codeBuilder.addAssignment(result, LLVMCall(returnType, function.toString(), names))
val resultPtr = codeBuilder.getNewVariable(returnType)
codeBuilder.allocVar(resultPtr)
codeBuilder.allocStackVar(resultPtr)
resultPtr.pointer = 1
codeBuilder.storeVariable(resultPtr, result)
return resultPtr
@@ -286,10 +285,9 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
return null
}
private fun evaluateConstructorCallExpression(name: String, names: ArrayList<LLVMSingleValue>, retType: LLVMType): LLVMSingleValue? {
val result = codeBuilder.getNewVariable(retType)
codeBuilder.allocVar(result)
result.pointer = 1
private fun evaluateConstructorCallExpression(function: LLVMVariable, names: ArrayList<LLVMSingleValue>): LLVMSingleValue? {
val result = codeBuilder.getNewVariable(function.type, pointer = 1)
codeBuilder.allocStaticVar(result)
val args = ArrayList<LLVMSingleValue>()
args.add(result)
@@ -297,7 +295,7 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
codeBuilder.addLLVMCode(LLVMCall(
LLVMVoidType(),
name,
function.toString(),
args
).toString())
@@ -356,10 +354,6 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
}
}
private fun evaluateTypeReferenceAssignment(type: KtUserType, expr: KtConstantExpression) {
}
private fun evaluateLeafPsiElement(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? {
return when (element.elementType) {
KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element, scopeDepth)
@@ -414,7 +408,7 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
private fun executeIfExpression(condition: KtBinaryExpression, thenExpression: PsiElement, elseExpression: PsiElement?, scopeDepth: Int): LLVMVariable? {
val conditionResult: LLVMVariable = evaluateBinaryExpression(condition, scopeDepth + 1)
val variable = codeBuilder.getNewVariable(LLVMIntType(), pointer = 1)
codeBuilder.allocVar(variable)
codeBuilder.allocStackVar(variable)
val thenLabel = codeBuilder.getNewLabel(prefix = "if")
val elseLabel = codeBuilder.getNewLabel(prefix = "if")
val endLabel = codeBuilder.getNewLabel(prefix = "if")
@@ -462,7 +456,7 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
when (assignExpression) {
is LLVMVariable -> {
val allocVar = variableManager.receiveVariable(identifier!!.text, assignExpression.type, LLVMRegisterScope(), pointer = 1)
codeBuilder.allocVar(allocVar)
codeBuilder.allocStackVar(allocVar)
variableManager.addVariable(identifier.text, allocVar, scopeDepth)
copyVariable(assignExpression, allocVar)
}
@@ -485,8 +479,8 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
when (returnType.type) {
is LLVMReferenceType -> {
val src = codeBuilder.bitcast(retVar as LLVMVariable, LLVMCharType())
val dst = codeBuilder.bitcast(returnType, LLVMCharType())
val src = codeBuilder.bitcast(retVar as LLVMVariable, LLVMVariable("", LLVMCharType(), pointer = 1))
val dst = codeBuilder.bitcast(returnType, LLVMVariable("", LLVMCharType(), pointer = 1))
val size = state.classes[(retVar.type as LLVMReferenceType).type]!!.size
codeBuilder.memcpy(dst, src, size)
codeBuilder.addAnyReturn(LLVMVoidType())
@@ -2,13 +2,16 @@ package org.kotlinnative.translator.llvm
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.lexer.KtTokens
import org.kotlinnative.translator.llvm.types.LLVMCharType
import org.kotlinnative.translator.llvm.types.LLVMIntType
import org.kotlinnative.translator.llvm.types.LLVMStringType
import org.kotlinnative.translator.llvm.types.LLVMType
class LLVMBuilder(val arm: Boolean) {
private var llvmLocalCode: StringBuilder = StringBuilder()
private var llvmGlobalCode: StringBuilder = StringBuilder()
private val POINTER_SIZE = 4
private var localCode: StringBuilder = StringBuilder()
private var globalCode: StringBuilder = StringBuilder()
private var variableCount = 0
private var labelCount = 0
@@ -17,12 +20,15 @@ class LLVMBuilder(val arm: Boolean) {
}
private fun initBuilder() {
val memcpy = "declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)"
val funcAttributes = """attributes #0 = { nounwind "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+hwdiv,+strict-align" }"""
llvmLocalCode.appendln(memcpy)
val declares = arrayOf(
"declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)",
"declare i8* @malloc_static(i32)")
declares.forEach { globalCode.appendln(it) }
val funcAttributes = """attributes #0 = { nounwind "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+hwdiv,+strict-align" }"""
if (arm) {
llvmLocalCode.appendln(funcAttributes)
globalCode.appendln(funcAttributes)
}
}
@@ -37,15 +43,15 @@ class LLVMBuilder(val arm: Boolean) {
}
fun addLLVMCode(code: String) {
llvmLocalCode.appendln(code)
localCode.appendln(code)
}
fun addStartExpression() {
llvmLocalCode.appendln("{")
localCode.appendln("{")
}
fun addEndExpression() {
llvmLocalCode.appendln("}")
localCode.appendln("}")
}
fun receiveNativeValue(firstOp: LLVMSingleValue): LLVMSingleValue = when (firstOp) {
@@ -81,65 +87,66 @@ class LLVMBuilder(val arm: Boolean) {
}
fun clean() {
llvmLocalCode = StringBuilder()
localCode = StringBuilder()
globalCode = StringBuilder()
initBuilder()
}
fun addAssignment(llvmVariable: LLVMVariable, rhs: LLVMNode) {
llvmLocalCode.appendln("$llvmVariable = $rhs")
localCode.appendln("$llvmVariable = $rhs")
}
fun addReturnOperator(llvmVariable: LLVMSingleValue) {
llvmLocalCode.appendln("ret ${llvmVariable.type} $llvmVariable")
localCode.appendln("ret ${llvmVariable.type} $llvmVariable")
}
fun addAnyReturn(type: LLVMType, value: String = type.defaultValue) {
llvmLocalCode.appendln("ret $type $value")
localCode.appendln("ret $type $value")
}
fun addStringConstant(variable: LLVMVariable, value: String) {
val type = variable.type as LLVMStringType
llvmGlobalCode.appendln("$variable = private unnamed_addr constant ${type.fullType()} c\"$value\\00\", align 1")
globalCode.appendln("$variable = private unnamed_addr constant ${type.fullType()} c\"$value\\00\", align 1")
}
fun storeString(target: LLVMVariable, source: LLVMVariable, offset: Int) {
val stringType = source.type as LLVMStringType
val code = "store ${target.type} getelementptr inbounds (${stringType.fullType()}, " +
"${stringType.fullType()}* $source, i32 0, i32 $offset), ${target.getType()} $target, align ${stringType.align}"
llvmLocalCode.appendln(code)
localCode.appendln(code)
}
fun loadClassField(target: LLVMVariable, source: LLVMVariable, offset: Int) {
val code = "$target = getelementptr inbounds ${source.type}* $source, i32 0, i32 $offset"
llvmLocalCode.appendln(code)
localCode.appendln(code)
}
fun markWithLabel(label: LLVMLabel?) {
if (label != null)
llvmLocalCode.appendln("${label.label}:")
localCode.appendln("${label.label}:")
}
fun addNopInstruction() {
llvmLocalCode.appendln(getNewVariable(LLVMIntType()).toString() + " = add i1 0, 0 ; nop instruction")
localCode.appendln(getNewVariable(LLVMIntType()).toString() + " = add i1 0, 0 ; nop instruction")
}
fun storeVariable(target: LLVMVariable, source: LLVMSingleValue) {
val code = "store ${source.type} $source, ${target.getType()} $target, align ${source.type?.align!!}"
llvmLocalCode.appendln(code)
localCode.appendln(code)
}
fun loadVariableOffset(target: LLVMVariable, source: LLVMVariable, index: LLVMConstant) {
val code = "$target = getelementptr inbounds ${source.type} $source, ${index.type} ${index.value}"
llvmLocalCode.appendln(code)
localCode.appendln(code)
}
fun copyVariableValue(target: LLVMVariable, source: LLVMVariable) {
var from = source
if (source.pointer > 0) {
from = getNewVariable(source.type, source.pointer)
llvmLocalCode.appendln("$from = load ${source.getType()} $source, align ${from.type.align}")
localCode.appendln("$from = load ${source.getType()} $source, align ${from.type.align}")
}
llvmLocalCode.appendln("store ${target.type} $from, ${target.getType()} $target, align ${from.type.align}")
localCode.appendln("store ${target.type} $from, ${target.getType()} $target, align ${from.type.align}")
}
fun loadArgument(llvmVariable: LLVMVariable, store: Boolean = true): LLVMVariable {
@@ -150,62 +157,73 @@ class LLVMBuilder(val arm: Boolean) {
fun loadVariable(target: LLVMVariable, source: LLVMVariable) {
val code = "$target = load ${source.getType()} $source, align ${target.type.align}"
llvmLocalCode.appendln(code)
localCode.appendln(code)
}
fun allocVar(target: LLVMVariable) {
llvmLocalCode.appendln("$target = alloca ${target.type}, align ${target.type.align}")
fun allocStackVar(target: LLVMVariable) {
localCode.appendln("$target = alloca ${target.type}, align ${target.type.align}")
}
fun allocStaticVar(target: LLVMVariable) {
val allocedVar = getNewVariable(LLVMCharType(), pointer = 1)
val size = if (target.pointer > 0) POINTER_SIZE else target.type.size
val alloc = "$allocedVar = call i8* @malloc_static(i32 $size)"
localCode.appendln(alloc)
val cast = "$target = bitcast ${allocedVar.getType()} $allocedVar to ${target.getType()}"
localCode.appendln(cast)
}
fun addVariableByRef(targetVariable: LLVMVariable, sourceVariable: LLVMVariable, store: Boolean) {
llvmLocalCode.appendln("$targetVariable = alloca ${sourceVariable.type}${"*".repeat(sourceVariable.pointer)}, align ${sourceVariable.type.align}")
localCode.appendln("$targetVariable = alloca ${sourceVariable.type}${"*".repeat(sourceVariable.pointer)}, align ${sourceVariable.type.align}")
if (store) {
llvmLocalCode.appendln("store ${sourceVariable.getType()} $sourceVariable, ${targetVariable.getType()} $targetVariable, align ${targetVariable.type.align}")
localCode.appendln("store ${sourceVariable.getType()} $sourceVariable, ${targetVariable.getType()} $targetVariable, align ${targetVariable.type.align}")
}
}
fun addConstant(allocVariable: LLVMVariable, constantValue: LLVMConstant) {
llvmLocalCode.appendln("$allocVariable = alloca ${allocVariable.type}, align ${allocVariable.type.align}")
llvmLocalCode.appendln("store ${allocVariable.type} $constantValue, ${allocVariable.getType()} $allocVariable, align ${allocVariable.type.align}")
localCode.appendln("$allocVariable = alloca ${allocVariable.type}, align ${allocVariable.type.align}")
localCode.appendln("store ${allocVariable.type} $constantValue, ${allocVariable.getType()} $allocVariable, align ${allocVariable.type.align}")
}
fun declareGlobalVariable(variable: LLVMVariable, defaultValue: String = variable.type.defaultValue) {
llvmLocalCode.appendln("$variable = global ${variable.type} $defaultValue, align ${variable.type.align}")
localCode.appendln("$variable = global ${variable.type} $defaultValue, align ${variable.type.align}")
}
fun loadAndGetVariable(source: LLVMVariable): LLVMVariable {
assert(source.pointer > 0)
val target = getNewVariable(source.type, source.pointer, source.kotlinName)
val code = "$target = load ${source.getType()} $source, align ${target.type.align}"
llvmLocalCode.appendln(code)
localCode.appendln(code)
return target
}
fun addCondition(condition: LLVMSingleValue, thenLabel: LLVMLabel, elseLabel: LLVMLabel) {
llvmLocalCode.appendln("br ${condition.getType()} $condition, label $thenLabel, label $elseLabel")
localCode.appendln("br ${condition.getType()} $condition, label $thenLabel, label $elseLabel")
}
fun addUnconditionalJump(label: LLVMLabel) {
llvmLocalCode.appendln("br label $label")
localCode.appendln("br label $label")
}
fun createClass(name: String, fields: List<LLVMVariable>) {
val code = "%class.$name = type { ${fields.map { it.type }.joinToString()} }"
llvmLocalCode.appendln(code)
val code = "%class.$name = type { ${fields.map { it.getType() }.joinToString()} }"
localCode.appendln(code)
}
fun bitcast(src: LLVMVariable, llvmType: LLVMType): LLVMVariable {
val empty = getNewVariable(llvmType, pointer = 1)
val code = "$empty = bitcast ${src.getType()} $src to $llvmType*"
llvmLocalCode.appendln(code)
fun bitcast(src: LLVMVariable, llvmType: LLVMVariable): LLVMVariable {
val empty = getNewVariable(llvmType.type, pointer = llvmType.pointer)
val code = "$empty = bitcast ${src.getType()} $src to ${llvmType.getType()}"
localCode.appendln(code)
return empty
}
fun memcpy(castedDst: LLVMVariable, castedSrc: LLVMVariable, size: Int, align: Int = 4, volatile: Boolean = false) {
val code = "call void @llvm.memcpy.p0i8.p0i8.i64(i8* $castedDst, i8* $castedSrc, i64 $size, i32 $align, i1 $volatile)"
llvmLocalCode.appendln(code)
localCode.appendln(code)
}
override fun toString() = llvmGlobalCode.toString() + llvmLocalCode.toString()
override fun toString() = globalCode.toString() + localCode.toString()
}
@@ -3,4 +3,4 @@ package org.kotlinnative.translator.llvm
import org.kotlinnative.translator.llvm.types.LLVMType
class LLVMClassVariable(label: String, type: LLVMType, val offset: Int = 0) : LLVMVariable(label, type)
class LLVMClassVariable(label: String, type: LLVMType, pointer: Int = 0, val offset: Int = 0) : LLVMVariable(label, type, pointer = pointer)
@@ -1,6 +0,0 @@
package org.kotlinnative.translator.llvm
import org.kotlinnative.translator.llvm.types.LLVMType
class LLVMConstructorCall(override val type: LLVMType, val call: (LLVMVariable) -> LLVMCall) : LLVMSingleValue()
@@ -18,4 +18,4 @@ fun LLVMMapStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMR
type.toString() == "Double" -> LLVMVariable(name, LLVMDoubleType(), type.toString(), scope)
type.isUnit() -> LLVMVariable("", LLVMVoidType(), "", scope)
else -> LLVMVariable(name, LLVMReferenceType("$type"), name, scope, pointer = 1)
}
}