translator: class allocation
This commit is contained in:
Generated
+5
-1
@@ -1,5 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="CidrRootsConfiguration">
|
||||||
|
<sourceRoots />
|
||||||
|
<libraryRoots />
|
||||||
|
<excludeRoots />
|
||||||
|
</component>
|
||||||
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
|
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
|
||||||
<OptionsSetting value="true" id="Add" />
|
<OptionsSetting value="true" id="Add" />
|
||||||
<OptionsSetting value="true" id="Remove" />
|
<OptionsSetting value="true" id="Remove" />
|
||||||
@@ -10,7 +15,6 @@
|
|||||||
<ConfirmationsSetting value="0" id="Add" />
|
<ConfirmationsSetting value="0" id="Add" />
|
||||||
<ConfirmationsSetting value="0" id="Remove" />
|
<ConfirmationsSetting value="0" id="Remove" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_3" default="true" assert-keyword="false" jdk-15="false" />
|
|
||||||
<component name="masterDetails">
|
<component name="masterDetails">
|
||||||
<states>
|
<states>
|
||||||
<state key="ProjectJDKs.UI">
|
<state key="ProjectJDKs.UI">
|
||||||
|
|||||||
@@ -1,78 +1,33 @@
|
|||||||
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_static(i32)
|
||||||
attributes #0 = { nounwind "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+hwdiv,+strict-align" }
|
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
|
%class.Simple = type { i32 }
|
||||||
@PROGRAM_DURATIOH_MS = global i32 3000, align 4
|
define void @Simple(%class.Simple* %classvariable.this, i32 %i) #0
|
||||||
@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
|
|
||||||
{
|
{
|
||||||
%instance.addr = alloca %class.MyClass, align 4
|
%classvariable.this.addr = alloca %class.Simple, align 4
|
||||||
%i.addr = alloca i32, align 4
|
%i.addr = alloca i32, align 4
|
||||||
store i32 %i, i32* %i.addr, 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
|
%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
|
store i32 %var1, i32* %var2, align 4
|
||||||
%var3 = load i16* %j.addr, align 2
|
%var3 = bitcast %class.Simple* %classvariable.this to i8*
|
||||||
%var4 = getelementptr inbounds %class.MyClass* %instance.addr, i32 0, i32 1
|
%var4 = bitcast %class.Simple* %classvariable.this.addr to i8*
|
||||||
store i16 %var3, i16* %var4, align 2
|
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var3, i8* %var4, i64 4, i32 4, i1 false)
|
||||||
%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)
|
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
declare void @wait(i32 %i) #0
|
define void @a() #0
|
||||||
define void @engine_program() #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
|
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
|
define void @kotlin_main() #0
|
||||||
{
|
{
|
||||||
call void @time_init()
|
%var6 = call i8* @malloc_static(i32 4)
|
||||||
call void @engine_program()
|
%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
|
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" }
|
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
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
if $darwin; then
|
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
|
fi
|
||||||
|
|
||||||
# For Cygwin, switch paths to Windows format before running java
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
package org.kotlinnative.translator
|
package org.kotlinnative.translator
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
import org.jetbrains.kotlin.psi.KtClass
|
||||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
import org.jetbrains.kotlin.psi.KtUserType
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.annotations.argumentValue
|
|
||||||
import org.kotlinnative.translator.exceptions.TranslationException
|
import org.kotlinnative.translator.exceptions.TranslationException
|
||||||
import org.kotlinnative.translator.llvm.*
|
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.*
|
import java.util.*
|
||||||
|
|
||||||
class ClassCodegen(val state: TranslationState, val variableManager: VariableManager, val clazz: KtClass, val codeBuilder: LLVMBuilder) {
|
class ClassCodegen(val state: TranslationState, val variableManager: VariableManager, val clazz: KtClass, val codeBuilder: LLVMBuilder) {
|
||||||
|
|
||||||
val annotation: Boolean
|
val annotation: Boolean
|
||||||
val native: Boolean
|
val plain: Boolean = false // TODO
|
||||||
val fields = ArrayList<LLVMVariable>()
|
val fields = ArrayList<LLVMVariable>()
|
||||||
val fieldsIndex = HashMap<String, LLVMClassVariable>()
|
val fieldsIndex = HashMap<String, LLVMClassVariable>()
|
||||||
val type: LLVMType = LLVMReferenceType(clazz.name.toString(), "class", byRef = true)
|
val type: LLVMType = LLVMReferenceType(clazz.name.toString(), "class", byRef = true)
|
||||||
@@ -33,8 +33,7 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
|
|||||||
|
|
||||||
if (!annotation) {
|
if (!annotation) {
|
||||||
for (field in parameterList) {
|
for (field in parameterList) {
|
||||||
val type = getNativeType(field) ?: parseLLVMType((field.typeReference?.typeElement as KtUserType).referencedName!!)
|
val item = resolveType(field)
|
||||||
val item = LLVMClassVariable(field.name!!, type, offset)
|
|
||||||
|
|
||||||
fields.add(item)
|
fields.add(item)
|
||||||
fieldsIndex[item.label] = item
|
fieldsIndex[item.label] = item
|
||||||
@@ -44,7 +43,6 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
native = isNative(descriptor.annotations)
|
|
||||||
size = currentSize
|
size = currentSize
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +63,7 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
|
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
|
||||||
variableManager.addVariable("this", classVal, 0);
|
variableManager.addVariable("this", classVal, 0)
|
||||||
for (function in methods.values) {
|
for (function in methods.values) {
|
||||||
function.generate(classVal)
|
function.generate(classVal)
|
||||||
}
|
}
|
||||||
@@ -84,7 +82,7 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
|
|||||||
refType.byRef = true
|
refType.byRef = true
|
||||||
|
|
||||||
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
|
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
|
||||||
variableManager.addVariable("this", classVal, 0);
|
variableManager.addVariable("this", classVal, 0)
|
||||||
|
|
||||||
argFields.add(classVal)
|
argFields.add(classVal)
|
||||||
argFields.addAll(fields)
|
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 dst = LLVMVariable("classvariable.this", type, scope = LLVMRegisterScope(), pointer = 1)
|
||||||
val src = LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1)
|
val src = LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1)
|
||||||
|
|
||||||
val castedDst = codeBuilder.bitcast(dst, LLVMCharType())
|
val castedDst = codeBuilder.bitcast(dst, LLVMVariable("", LLVMCharType(), pointer = 1))
|
||||||
val castedSrc = codeBuilder.bitcast(src, LLVMCharType())
|
val castedSrc = codeBuilder.bitcast(src, LLVMVariable("", LLVMCharType(), pointer = 1))
|
||||||
|
|
||||||
codeBuilder.memcpy(castedDst, castedSrc, size)
|
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) {
|
for (annotation in field.annotationEntries) {
|
||||||
val annotationDescriptor = state.bindingContext.get(BindingContext.ANNOTATION, annotation)
|
val annotationDescriptor = state.bindingContext.get(BindingContext.ANNOTATION, annotation)
|
||||||
val type = annotationDescriptor?.type.toString()
|
val type = annotationDescriptor?.type.toString()
|
||||||
if (type == "Native") {
|
|
||||||
return parseLLVMType(annotationDescriptor!!.argumentValue("type").toString())
|
result.add(type)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return result
|
||||||
}
|
|
||||||
|
|
||||||
private fun isNative(annotations: Annotations?): Boolean {
|
|
||||||
annotations ?: return false
|
|
||||||
|
|
||||||
for (i in annotations) {
|
|
||||||
if (i.type.toString() == "Native") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
|
|||||||
|
|
||||||
if (state.classes.containsKey(function)) {
|
if (state.classes.containsKey(function)) {
|
||||||
val descriptor = state.classes[function] ?: return null
|
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)
|
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())
|
codeBuilder.addLLVMCode(LLVMCall(LLVMVoidType(), function.toString(), names).toString())
|
||||||
}
|
}
|
||||||
is LLVMReferenceType -> {
|
is LLVMReferenceType -> {
|
||||||
val result = codeBuilder.getNewVariable(returnType)
|
val result = codeBuilder.getNewVariable(returnType, pointer = 1)
|
||||||
codeBuilder.allocVar(result)
|
codeBuilder.allocStaticVar(result)
|
||||||
result.pointer = 1
|
|
||||||
|
|
||||||
val args = ArrayList<LLVMSingleValue>()
|
val args = ArrayList<LLVMSingleValue>()
|
||||||
args.add(result)
|
args.add(result)
|
||||||
@@ -276,7 +275,7 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
|
|||||||
codeBuilder.addAssignment(result, LLVMCall(returnType, function.toString(), names))
|
codeBuilder.addAssignment(result, LLVMCall(returnType, function.toString(), names))
|
||||||
|
|
||||||
val resultPtr = codeBuilder.getNewVariable(returnType)
|
val resultPtr = codeBuilder.getNewVariable(returnType)
|
||||||
codeBuilder.allocVar(resultPtr)
|
codeBuilder.allocStackVar(resultPtr)
|
||||||
resultPtr.pointer = 1
|
resultPtr.pointer = 1
|
||||||
codeBuilder.storeVariable(resultPtr, result)
|
codeBuilder.storeVariable(resultPtr, result)
|
||||||
return resultPtr
|
return resultPtr
|
||||||
@@ -286,10 +285,9 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateConstructorCallExpression(name: String, names: ArrayList<LLVMSingleValue>, retType: LLVMType): LLVMSingleValue? {
|
private fun evaluateConstructorCallExpression(function: LLVMVariable, names: ArrayList<LLVMSingleValue>): LLVMSingleValue? {
|
||||||
val result = codeBuilder.getNewVariable(retType)
|
val result = codeBuilder.getNewVariable(function.type, pointer = 1)
|
||||||
codeBuilder.allocVar(result)
|
codeBuilder.allocStaticVar(result)
|
||||||
result.pointer = 1
|
|
||||||
|
|
||||||
val args = ArrayList<LLVMSingleValue>()
|
val args = ArrayList<LLVMSingleValue>()
|
||||||
args.add(result)
|
args.add(result)
|
||||||
@@ -297,7 +295,7 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
|
|||||||
|
|
||||||
codeBuilder.addLLVMCode(LLVMCall(
|
codeBuilder.addLLVMCode(LLVMCall(
|
||||||
LLVMVoidType(),
|
LLVMVoidType(),
|
||||||
name,
|
function.toString(),
|
||||||
args
|
args
|
||||||
).toString())
|
).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? {
|
private fun evaluateLeafPsiElement(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? {
|
||||||
return when (element.elementType) {
|
return when (element.elementType) {
|
||||||
KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element, scopeDepth)
|
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? {
|
private fun executeIfExpression(condition: KtBinaryExpression, thenExpression: PsiElement, elseExpression: PsiElement?, scopeDepth: Int): LLVMVariable? {
|
||||||
val conditionResult: LLVMVariable = evaluateBinaryExpression(condition, scopeDepth + 1)
|
val conditionResult: LLVMVariable = evaluateBinaryExpression(condition, scopeDepth + 1)
|
||||||
val variable = codeBuilder.getNewVariable(LLVMIntType(), pointer = 1)
|
val variable = codeBuilder.getNewVariable(LLVMIntType(), pointer = 1)
|
||||||
codeBuilder.allocVar(variable)
|
codeBuilder.allocStackVar(variable)
|
||||||
val thenLabel = codeBuilder.getNewLabel(prefix = "if")
|
val thenLabel = codeBuilder.getNewLabel(prefix = "if")
|
||||||
val elseLabel = codeBuilder.getNewLabel(prefix = "if")
|
val elseLabel = codeBuilder.getNewLabel(prefix = "if")
|
||||||
val endLabel = codeBuilder.getNewLabel(prefix = "if")
|
val endLabel = codeBuilder.getNewLabel(prefix = "if")
|
||||||
@@ -462,7 +456,7 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
|
|||||||
when (assignExpression) {
|
when (assignExpression) {
|
||||||
is LLVMVariable -> {
|
is LLVMVariable -> {
|
||||||
val allocVar = variableManager.receiveVariable(identifier!!.text, assignExpression.type, LLVMRegisterScope(), pointer = 1)
|
val allocVar = variableManager.receiveVariable(identifier!!.text, assignExpression.type, LLVMRegisterScope(), pointer = 1)
|
||||||
codeBuilder.allocVar(allocVar)
|
codeBuilder.allocStackVar(allocVar)
|
||||||
variableManager.addVariable(identifier.text, allocVar, scopeDepth)
|
variableManager.addVariable(identifier.text, allocVar, scopeDepth)
|
||||||
copyVariable(assignExpression, allocVar)
|
copyVariable(assignExpression, allocVar)
|
||||||
}
|
}
|
||||||
@@ -485,8 +479,8 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
|
|||||||
|
|
||||||
when (returnType.type) {
|
when (returnType.type) {
|
||||||
is LLVMReferenceType -> {
|
is LLVMReferenceType -> {
|
||||||
val src = codeBuilder.bitcast(retVar as LLVMVariable, LLVMCharType())
|
val src = codeBuilder.bitcast(retVar as LLVMVariable, LLVMVariable("", LLVMCharType(), pointer = 1))
|
||||||
val dst = codeBuilder.bitcast(returnType, LLVMCharType())
|
val dst = codeBuilder.bitcast(returnType, LLVMVariable("", LLVMCharType(), pointer = 1))
|
||||||
val size = state.classes[(retVar.type as LLVMReferenceType).type]!!.size
|
val size = state.classes[(retVar.type as LLVMReferenceType).type]!!.size
|
||||||
codeBuilder.memcpy(dst, src, size)
|
codeBuilder.memcpy(dst, src, size)
|
||||||
codeBuilder.addAnyReturn(LLVMVoidType())
|
codeBuilder.addAnyReturn(LLVMVoidType())
|
||||||
|
|||||||
@@ -2,13 +2,16 @@ package org.kotlinnative.translator.llvm
|
|||||||
|
|
||||||
import com.intellij.psi.tree.IElementType
|
import com.intellij.psi.tree.IElementType
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
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.LLVMIntType
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMStringType
|
import org.kotlinnative.translator.llvm.types.LLVMStringType
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||||
|
|
||||||
class LLVMBuilder(val arm: Boolean) {
|
class LLVMBuilder(val arm: Boolean) {
|
||||||
private var llvmLocalCode: StringBuilder = StringBuilder()
|
private val POINTER_SIZE = 4
|
||||||
private var llvmGlobalCode: StringBuilder = StringBuilder()
|
|
||||||
|
private var localCode: StringBuilder = StringBuilder()
|
||||||
|
private var globalCode: StringBuilder = StringBuilder()
|
||||||
private var variableCount = 0
|
private var variableCount = 0
|
||||||
private var labelCount = 0
|
private var labelCount = 0
|
||||||
|
|
||||||
@@ -17,12 +20,15 @@ class LLVMBuilder(val arm: Boolean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initBuilder() {
|
private fun initBuilder() {
|
||||||
val memcpy = "declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)"
|
val declares = arrayOf(
|
||||||
val funcAttributes = """attributes #0 = { nounwind "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+hwdiv,+strict-align" }"""
|
"declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)",
|
||||||
llvmLocalCode.appendln(memcpy)
|
"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) {
|
if (arm) {
|
||||||
llvmLocalCode.appendln(funcAttributes)
|
globalCode.appendln(funcAttributes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,15 +43,15 @@ class LLVMBuilder(val arm: Boolean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun addLLVMCode(code: String) {
|
fun addLLVMCode(code: String) {
|
||||||
llvmLocalCode.appendln(code)
|
localCode.appendln(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addStartExpression() {
|
fun addStartExpression() {
|
||||||
llvmLocalCode.appendln("{")
|
localCode.appendln("{")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addEndExpression() {
|
fun addEndExpression() {
|
||||||
llvmLocalCode.appendln("}")
|
localCode.appendln("}")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun receiveNativeValue(firstOp: LLVMSingleValue): LLVMSingleValue = when (firstOp) {
|
fun receiveNativeValue(firstOp: LLVMSingleValue): LLVMSingleValue = when (firstOp) {
|
||||||
@@ -81,65 +87,66 @@ class LLVMBuilder(val arm: Boolean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun clean() {
|
fun clean() {
|
||||||
llvmLocalCode = StringBuilder()
|
localCode = StringBuilder()
|
||||||
|
globalCode = StringBuilder()
|
||||||
initBuilder()
|
initBuilder()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addAssignment(llvmVariable: LLVMVariable, rhs: LLVMNode) {
|
fun addAssignment(llvmVariable: LLVMVariable, rhs: LLVMNode) {
|
||||||
llvmLocalCode.appendln("$llvmVariable = $rhs")
|
localCode.appendln("$llvmVariable = $rhs")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addReturnOperator(llvmVariable: LLVMSingleValue) {
|
fun addReturnOperator(llvmVariable: LLVMSingleValue) {
|
||||||
llvmLocalCode.appendln("ret ${llvmVariable.type} $llvmVariable")
|
localCode.appendln("ret ${llvmVariable.type} $llvmVariable")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addAnyReturn(type: LLVMType, value: String = type.defaultValue) {
|
fun addAnyReturn(type: LLVMType, value: String = type.defaultValue) {
|
||||||
llvmLocalCode.appendln("ret $type $value")
|
localCode.appendln("ret $type $value")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addStringConstant(variable: LLVMVariable, value: String) {
|
fun addStringConstant(variable: LLVMVariable, value: String) {
|
||||||
val type = variable.type as LLVMStringType
|
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) {
|
fun storeString(target: LLVMVariable, source: LLVMVariable, offset: Int) {
|
||||||
val stringType = source.type as LLVMStringType
|
val stringType = source.type as LLVMStringType
|
||||||
val code = "store ${target.type} getelementptr inbounds (${stringType.fullType()}, " +
|
val code = "store ${target.type} getelementptr inbounds (${stringType.fullType()}, " +
|
||||||
"${stringType.fullType()}* $source, i32 0, i32 $offset), ${target.getType()} $target, align ${stringType.align}"
|
"${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) {
|
fun loadClassField(target: LLVMVariable, source: LLVMVariable, offset: Int) {
|
||||||
val code = "$target = getelementptr inbounds ${source.type}* $source, i32 0, i32 $offset"
|
val code = "$target = getelementptr inbounds ${source.type}* $source, i32 0, i32 $offset"
|
||||||
llvmLocalCode.appendln(code)
|
localCode.appendln(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun markWithLabel(label: LLVMLabel?) {
|
fun markWithLabel(label: LLVMLabel?) {
|
||||||
if (label != null)
|
if (label != null)
|
||||||
llvmLocalCode.appendln("${label.label}:")
|
localCode.appendln("${label.label}:")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addNopInstruction() {
|
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) {
|
fun storeVariable(target: LLVMVariable, source: LLVMSingleValue) {
|
||||||
val code = "store ${source.type} $source, ${target.getType()} $target, align ${source.type?.align!!}"
|
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) {
|
fun loadVariableOffset(target: LLVMVariable, source: LLVMVariable, index: LLVMConstant) {
|
||||||
val code = "$target = getelementptr inbounds ${source.type} $source, ${index.type} ${index.value}"
|
val code = "$target = getelementptr inbounds ${source.type} $source, ${index.type} ${index.value}"
|
||||||
llvmLocalCode.appendln(code)
|
localCode.appendln(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun copyVariableValue(target: LLVMVariable, source: LLVMVariable) {
|
fun copyVariableValue(target: LLVMVariable, source: LLVMVariable) {
|
||||||
var from = source
|
var from = source
|
||||||
if (source.pointer > 0) {
|
if (source.pointer > 0) {
|
||||||
from = getNewVariable(source.type, source.pointer)
|
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 {
|
fun loadArgument(llvmVariable: LLVMVariable, store: Boolean = true): LLVMVariable {
|
||||||
@@ -150,62 +157,73 @@ class LLVMBuilder(val arm: Boolean) {
|
|||||||
|
|
||||||
fun loadVariable(target: LLVMVariable, source: LLVMVariable) {
|
fun loadVariable(target: LLVMVariable, source: LLVMVariable) {
|
||||||
val code = "$target = load ${source.getType()} $source, align ${target.type.align}"
|
val code = "$target = load ${source.getType()} $source, align ${target.type.align}"
|
||||||
llvmLocalCode.appendln(code)
|
localCode.appendln(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun allocVar(target: LLVMVariable) {
|
fun allocStackVar(target: LLVMVariable) {
|
||||||
llvmLocalCode.appendln("$target = alloca ${target.type}, align ${target.type.align}")
|
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) {
|
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) {
|
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) {
|
fun addConstant(allocVariable: LLVMVariable, constantValue: LLVMConstant) {
|
||||||
llvmLocalCode.appendln("$allocVariable = alloca ${allocVariable.type}, align ${allocVariable.type.align}")
|
localCode.appendln("$allocVariable = alloca ${allocVariable.type}, align ${allocVariable.type.align}")
|
||||||
llvmLocalCode.appendln("store ${allocVariable.type} $constantValue, ${allocVariable.getType()} $allocVariable, 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) {
|
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 {
|
fun loadAndGetVariable(source: LLVMVariable): LLVMVariable {
|
||||||
assert(source.pointer > 0)
|
assert(source.pointer > 0)
|
||||||
val target = getNewVariable(source.type, source.pointer, source.kotlinName)
|
val target = getNewVariable(source.type, source.pointer, source.kotlinName)
|
||||||
val code = "$target = load ${source.getType()} $source, align ${target.type.align}"
|
val code = "$target = load ${source.getType()} $source, align ${target.type.align}"
|
||||||
llvmLocalCode.appendln(code)
|
localCode.appendln(code)
|
||||||
return target
|
return target
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addCondition(condition: LLVMSingleValue, thenLabel: LLVMLabel, elseLabel: LLVMLabel) {
|
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) {
|
fun addUnconditionalJump(label: LLVMLabel) {
|
||||||
llvmLocalCode.appendln("br label $label")
|
localCode.appendln("br label $label")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createClass(name: String, fields: List<LLVMVariable>) {
|
fun createClass(name: String, fields: List<LLVMVariable>) {
|
||||||
val code = "%class.$name = type { ${fields.map { it.type }.joinToString()} }"
|
val code = "%class.$name = type { ${fields.map { it.getType() }.joinToString()} }"
|
||||||
llvmLocalCode.appendln(code)
|
localCode.appendln(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bitcast(src: LLVMVariable, llvmType: LLVMType): LLVMVariable {
|
fun bitcast(src: LLVMVariable, llvmType: LLVMVariable): LLVMVariable {
|
||||||
val empty = getNewVariable(llvmType, pointer = 1)
|
val empty = getNewVariable(llvmType.type, pointer = llvmType.pointer)
|
||||||
val code = "$empty = bitcast ${src.getType()} $src to $llvmType*"
|
val code = "$empty = bitcast ${src.getType()} $src to ${llvmType.getType()}"
|
||||||
llvmLocalCode.appendln(code)
|
localCode.appendln(code)
|
||||||
return empty
|
return empty
|
||||||
}
|
}
|
||||||
|
|
||||||
fun memcpy(castedDst: LLVMVariable, castedSrc: LLVMVariable, size: Int, align: Int = 4, volatile: Boolean = false) {
|
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)"
|
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
|
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.toString() == "Double" -> LLVMVariable(name, LLVMDoubleType(), type.toString(), scope)
|
||||||
type.isUnit() -> LLVMVariable("", LLVMVoidType(), "", scope)
|
type.isUnit() -> LLVMVariable("", LLVMVoidType(), "", scope)
|
||||||
else -> LLVMVariable(name, LLVMReferenceType("$type"), name, scope, pointer = 1)
|
else -> LLVMVariable(name, LLVMReferenceType("$type"), name, scope, pointer = 1)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user