translator: class allocation
This commit is contained in:
Generated
+5
-1
@@ -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">
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)"}
|
||||
|
||||
Vendored
+1
-1
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user