translator: function struct arguments, resolve references
This commit is contained in:
@@ -1,60 +1,9 @@
|
|||||||
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)
|
|
||||||
attributes #0 = { nounwind "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+hwdiv,+strict-align" }
|
|
||||||
declare void @wait(i32 %loops) #0
|
|
||||||
define void @programRotationRight() #0
|
|
||||||
{
|
|
||||||
call void @engine_turn_right()
|
|
||||||
call void @wait(i32 10)
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
define void @setCurProgram(i32 %program) #0
|
|
||||||
{
|
|
||||||
%program.addr = alloca i32, align 4
|
|
||||||
store i32 %program, i32* %program.addr, align 4
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
define void @programBackward() #0
|
|
||||||
{
|
|
||||||
call void @engine_backward()
|
|
||||||
call void @wait(i32 10)
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
declare void @leds_init() #0
|
|
||||||
define void @programForward(i32 %delay) #0
|
|
||||||
{
|
|
||||||
%delay.addr = alloca i32, align 4
|
|
||||||
store i32 %delay, i32* %delay.addr, align 4
|
|
||||||
call void @engine_forward()
|
|
||||||
call void @wait(i32 10)
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
define void @procNextProgramPending() #0
|
|
||||||
{
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
declare void @engine_init() #0
|
|
||||||
declare void @user_btn_init(void ()* %program) #0
|
|
||||||
define void @setNextProgramPending() #0
|
|
||||||
{
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
declare void @engine_backward() #0
|
|
||||||
define void @programRotationLeft() #0
|
|
||||||
{
|
|
||||||
call void @engine_turn_left()
|
|
||||||
call void @wait(i32 10)
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
define void @kotlin_main() #0
|
|
||||||
{
|
|
||||||
call void @leds_init()
|
|
||||||
call void @engine_init()
|
|
||||||
call void @user_btn_init(void ()* @setNextProgramPending)
|
|
||||||
call void @setCurProgram(i32 0)
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
declare void @engine_stop() #0
|
|
||||||
declare void @engine_forward() #0
|
|
||||||
declare void @engine_turn_left() #0
|
|
||||||
declare void @engine_turn_right() #0
|
|
||||||
|
|
||||||
|
Exception in thread "main" org.kotlinnative.translator.exceptions.TranslationException
|
||||||
|
at org.kotlinnative.translator.TranslationStateKt.parseAndAnalyze(TranslationState.kt:50)
|
||||||
|
at MainKt.main(main.kt:13)
|
||||||
|
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|
||||||
|
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
|
||||||
|
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
|
||||||
|
at java.lang.reflect.Method.invoke(Method.java:498)
|
||||||
|
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val disposer = Disposer.newDisposable()
|
val disposer = Disposer.newDisposable()
|
||||||
val state = parseAndAnalyze(args.asList(), disposer, true)
|
val state = parseAndAnalyze(args.asList(), disposer, arm = false)
|
||||||
|
|
||||||
val files = state.environment.getSourceFiles()
|
val files = state.environment.getSourceFiles()
|
||||||
if (files.isEmpty()) {
|
if (files.isEmpty()) {
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuil
|
|||||||
val argFields = ArrayList<LLVMVariable>()
|
val argFields = ArrayList<LLVMVariable>()
|
||||||
val refType = type.makeClone() as LLVMReferenceType
|
val refType = type.makeClone() as LLVMReferenceType
|
||||||
refType.addParam("sret")
|
refType.addParam("sret")
|
||||||
|
refType.isReturn = true
|
||||||
|
|
||||||
val thisField = LLVMVariable("instance", refType, clazz.name, pointer = true)
|
val thisField = LLVMVariable("instance", refType, clazz.name, pointer = true)
|
||||||
|
|
||||||
|
|||||||
@@ -18,17 +18,30 @@ import java.util.*
|
|||||||
class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction, val codeBuilder: LLVMBuilder) {
|
class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction, val codeBuilder: LLVMBuilder) {
|
||||||
|
|
||||||
var name = function.fqName.toString()
|
var name = function.fqName.toString()
|
||||||
var returnType: LLVMType
|
var returnType: LLVMVariable
|
||||||
var args: List<LLVMVariable>?
|
var args = ArrayList<LLVMVariable>()
|
||||||
val variableManager = state.variableManager
|
val variableManager = state.variableManager
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val descriptor = state.bindingContext.get(BindingContext.FUNCTION, function)!!
|
val descriptor = state.bindingContext.get(BindingContext.FUNCTION, function)!!
|
||||||
args = descriptor.valueParameters.map {
|
args.addAll(descriptor.valueParameters.map {
|
||||||
LLVMMapStandardType(it.name.toString(), it.type)
|
LLVMMapStandardType(it.name.toString(), it.type)
|
||||||
}
|
})
|
||||||
|
|
||||||
returnType = LLVMMapStandardType("", descriptor.returnType!!).type
|
returnType = LLVMMapStandardType("instance", descriptor.returnType!!)
|
||||||
|
val retType = returnType.type
|
||||||
|
when (retType) {
|
||||||
|
is LLVMReferenceType -> {
|
||||||
|
if (state.classes.containsKey(retType.type)) {
|
||||||
|
retType.prefix = "class"
|
||||||
|
}
|
||||||
|
|
||||||
|
retType.isReturn = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (retType is LLVMReferenceType && state.classes.containsKey(retType.type)) {
|
||||||
|
retType.prefix = "class"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generate() {
|
fun generate() {
|
||||||
@@ -41,7 +54,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
|||||||
evaluateCodeBlock(function.bodyExpression)
|
evaluateCodeBlock(function.bodyExpression)
|
||||||
|
|
||||||
|
|
||||||
if (returnType is LLVMVoidType) {
|
if (returnType.type is LLVMVoidType) {
|
||||||
codeBuilder.addVoidReturn()
|
codeBuilder.addVoidReturn()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +64,13 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
|||||||
private fun generateDeclaration(): Boolean {
|
private fun generateDeclaration(): Boolean {
|
||||||
var external = false
|
var external = false
|
||||||
|
|
||||||
|
args.forEach {
|
||||||
|
val type = it.type
|
||||||
|
if (type is LLVMReferenceType && state.classes.containsKey(type.type)) {
|
||||||
|
type.prefix = "class"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var keyword = function.firstChild
|
var keyword = function.firstChild
|
||||||
while (keyword != null) {
|
while (keyword != null) {
|
||||||
if (keyword.text == "external") {
|
if (keyword.text == "external") {
|
||||||
@@ -61,15 +81,29 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
|||||||
keyword = keyword.getNextSiblingIgnoringWhitespaceAndComments()
|
keyword = keyword.getNextSiblingIgnoringWhitespaceAndComments()
|
||||||
}
|
}
|
||||||
|
|
||||||
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(function.fqName.toString(), args, returnType, external, state.arm))
|
var actualReturnType: LLVMType = returnType.type
|
||||||
|
val actualArgs = ArrayList<LLVMVariable>()
|
||||||
|
|
||||||
|
if (returnType.pointer) {
|
||||||
|
actualReturnType = LLVMVoidType()
|
||||||
|
actualArgs.add(returnType)
|
||||||
|
}
|
||||||
|
|
||||||
|
actualArgs.addAll(args)
|
||||||
|
|
||||||
|
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(function.fqName.toString(), actualArgs, actualReturnType, external, state.arm))
|
||||||
return external
|
return external
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateLoadArguments() {
|
private fun generateLoadArguments() {
|
||||||
args?.forEach {
|
args.forEach {
|
||||||
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMLocalScope(), false)
|
if (it.type !is LLVMReferenceType || (it.type as LLVMReferenceType).isReturn) {
|
||||||
val allocVar = codeBuilder.loadArgument(loadVariable)
|
val loadVariable = LLVMVariable("${it.label}", it.type, it.label, LLVMLocalScope(), pointer = false)
|
||||||
variableManager.addVariable(it.label, allocVar, 2)
|
val allocVar = codeBuilder.loadArgument(loadVariable)
|
||||||
|
variableManager.addVariable(it.label, allocVar, 2)
|
||||||
|
} else {
|
||||||
|
variableManager.addVariable(it.label, LLVMVariable(it.label, it.type, it.label, LLVMLocalScope(), pointer = true), 2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,10 +118,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
|||||||
is KtBlockExpression -> expressionWalker(expr.firstChild, scopeDepth + 1)
|
is KtBlockExpression -> expressionWalker(expr.firstChild, scopeDepth + 1)
|
||||||
is KtProperty -> evaluateLeafPsiElement(expr.firstChild as LeafPsiElement, scopeDepth)
|
is KtProperty -> evaluateLeafPsiElement(expr.firstChild as LeafPsiElement, scopeDepth)
|
||||||
is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth)
|
is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth)
|
||||||
is KtCallExpression -> {
|
is KtCallExpression -> evaluateCallExpression(expr, scopeDepth)
|
||||||
val expression = evaluateCallExpression(expr, scopeDepth) as LLVMCall
|
|
||||||
codeBuilder.addLLVMCode(expression.toString())
|
|
||||||
}
|
|
||||||
is PsiElement -> evaluateExpression(expr.firstChild, scopeDepth + 1)
|
is PsiElement -> evaluateExpression(expr.firstChild, scopeDepth + 1)
|
||||||
null -> {
|
null -> {
|
||||||
variableManager.pullUpwardsLevel(scopeDepth)
|
variableManager.pullUpwardsLevel(scopeDepth)
|
||||||
@@ -104,9 +135,10 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
|||||||
is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth)
|
is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth)
|
||||||
is KtConstantExpression -> evaluateConstantExpression(expr)
|
is KtConstantExpression -> evaluateConstantExpression(expr)
|
||||||
is KtCallExpression -> evaluateCallExpression(expr, scopeDepth)
|
is KtCallExpression -> evaluateCallExpression(expr, scopeDepth)
|
||||||
|
is KtCallableReferenceExpression -> evaluateCallableReferenceExpression(expr)
|
||||||
is KtReferenceExpression -> evaluateReferenceExpression(expr)
|
is KtReferenceExpression -> evaluateReferenceExpression(expr)
|
||||||
is KtIfExpression -> evaluateIfOperator(expr.firstChild as LeafPsiElement, scopeDepth + 1, true)
|
is KtIfExpression -> evaluateIfOperator(expr.firstChild as LeafPsiElement, scopeDepth + 1, true)
|
||||||
is KtDotQualifiedExpression -> evaluateDotExpression(expr, scopeDepth)
|
is KtDotQualifiedExpression -> evaluateDotExpression(expr)
|
||||||
is PsiWhiteSpace -> null
|
is PsiWhiteSpace -> null
|
||||||
is KtStringTemplateExpression -> evaluateStringTemplateExpression(expr, scopeDepth + 1)
|
is KtStringTemplateExpression -> evaluateStringTemplateExpression(expr, scopeDepth + 1)
|
||||||
is PsiElement -> evaluatePsiElement(expr, scopeDepth)
|
is PsiElement -> evaluatePsiElement(expr, scopeDepth)
|
||||||
@@ -124,7 +156,12 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
|||||||
return variable
|
return variable
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateDotExpression(expr: KtDotQualifiedExpression, scopeDepth: Int): LLVMSingleValue? {
|
private fun evaluateCallableReferenceExpression(expr: KtCallableReferenceExpression): LLVMSingleValue? {
|
||||||
|
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!!
|
||||||
|
return LLVMMapStandardType(expr.text.substring(2), kotlinType)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun evaluateDotExpression(expr: KtDotQualifiedExpression): LLVMSingleValue? {
|
||||||
val receiverName = expr.receiverExpression.text
|
val receiverName = expr.receiverExpression.text
|
||||||
val selectorName = expr.selectorExpression!!.text
|
val selectorName = expr.selectorExpression!!.text
|
||||||
|
|
||||||
@@ -161,31 +198,90 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
|||||||
val function = expr.firstChild.firstChild
|
val function = expr.firstChild.firstChild
|
||||||
val descriptor = state.classes[function.text] ?: return null
|
val descriptor = state.classes[function.text] ?: return null
|
||||||
val names = parseArgList(expr, scopeDepth).mapIndexed { i: Int, v: LLVMSingleValue ->
|
val names = parseArgList(expr, scopeDepth).mapIndexed { i: Int, v: LLVMSingleValue ->
|
||||||
LLVMVariable(v.toString(), descriptor.fields[i].type, pointer = descriptor.fields[i].pointer)
|
when (v) {
|
||||||
|
is LLVMVariable -> LLVMVariable(v.toString(), descriptor.fields[i].type, pointer = descriptor.fields[i].pointer)
|
||||||
|
else -> v
|
||||||
|
}
|
||||||
}.toList()
|
}.toList()
|
||||||
|
|
||||||
return LLVMConstructorCall(
|
val result = codeBuilder.getNewVariable(returnType.type)
|
||||||
descriptor.type, fun(thisVar): LLVMCall {
|
codeBuilder.allocVar(result)
|
||||||
val args = ArrayList<LLVMVariable>()
|
result.pointer = true
|
||||||
args.add(thisVar)
|
|
||||||
args.addAll(names)
|
val args = ArrayList<LLVMSingleValue>()
|
||||||
return LLVMCall(LLVMVoidType(), descriptor.constructorName, args)
|
args.add(result)
|
||||||
})
|
args.addAll(names)
|
||||||
|
|
||||||
|
codeBuilder.addLLVMCode(LLVMCall(
|
||||||
|
LLVMVoidType(),
|
||||||
|
descriptor.constructorName,
|
||||||
|
args
|
||||||
|
).toString())
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateFunctionCallExpression(expr: KtCallExpression, scopeDepth: Int): LLVMSingleValue? {
|
private fun evaluateFunctionCallExpression(expr: KtCallExpression, scopeDepth: Int): LLVMSingleValue? {
|
||||||
val function = expr.firstChild.firstChild
|
val function = expr.firstChild.firstChild
|
||||||
|
|
||||||
val descriptor = state.functions[function.text] ?: return null
|
val descriptor = state.functions[function.text] ?: return null
|
||||||
val names = parseArgList(expr, scopeDepth)
|
val names = parseArgList(expr, scopeDepth).mapIndexed(fun(i: Int, llvmSingleValue: LLVMSingleValue): LLVMSingleValue {
|
||||||
|
var result = llvmSingleValue
|
||||||
|
|
||||||
return LLVMCall(descriptor.returnType, "@${descriptor.name}", descriptor.args?.mapIndexed {
|
if (result.pointer && !descriptor.args[i].pointer) {
|
||||||
i: Int, variable: LLVMVariable ->
|
result = codeBuilder.getNewVariable(descriptor.args[i].type)
|
||||||
LLVMVariable(names[i].toString(), variable.type, pointer = variable.pointer)
|
codeBuilder.loadVariable(result, llvmSingleValue as LLVMVariable)
|
||||||
} ?: listOf())
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}).toList()
|
||||||
|
|
||||||
|
val returnType = descriptor.returnType.type
|
||||||
|
when (returnType) {
|
||||||
|
is LLVMVoidType -> {
|
||||||
|
codeBuilder.addLLVMCode(LLVMCall(
|
||||||
|
LLVMVoidType(),
|
||||||
|
"@${descriptor.name}",
|
||||||
|
names
|
||||||
|
).toString())
|
||||||
|
}
|
||||||
|
is LLVMReferenceType -> {
|
||||||
|
val result = codeBuilder.getNewVariable(returnType)
|
||||||
|
codeBuilder.allocVar(result)
|
||||||
|
result.pointer = true
|
||||||
|
|
||||||
|
val args = ArrayList<LLVMSingleValue>()
|
||||||
|
args.add(result)
|
||||||
|
args.addAll(names)
|
||||||
|
|
||||||
|
codeBuilder.addLLVMCode(LLVMCall(
|
||||||
|
LLVMVoidType(),
|
||||||
|
"@${descriptor.name}",
|
||||||
|
args
|
||||||
|
).toString())
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val result = codeBuilder.getNewVariable(returnType)
|
||||||
|
codeBuilder.addAssignment(result, LLVMCall(
|
||||||
|
returnType,
|
||||||
|
"@${descriptor.name}",
|
||||||
|
names
|
||||||
|
))
|
||||||
|
|
||||||
|
val resultPtr = codeBuilder.getNewVariable(returnType)
|
||||||
|
codeBuilder.allocVar(resultPtr)
|
||||||
|
resultPtr.pointer = true
|
||||||
|
codeBuilder.storeVariable(resultPtr, result)
|
||||||
|
return resultPtr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseArgList(expr: KtCallExpression, scopeDepth: Int): List<LLVMSingleValue> {
|
private fun parseArgList(expr: KtCallExpression, scopeDepth: Int): ArrayList<LLVMSingleValue> {
|
||||||
val args = expr.getValueArgumentsInParentheses()
|
val args = expr.getValueArgumentsInParentheses()
|
||||||
val result = ArrayList<LLVMSingleValue>()
|
val result = ArrayList<LLVMSingleValue>()
|
||||||
|
|
||||||
@@ -247,17 +343,17 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun executeWhileBlock(condition: KtBinaryExpression, bodyExpression: PsiElement, scopeDepth: Int): LLVMVariable? {
|
private fun executeWhileBlock(condition: KtBinaryExpression, bodyExpression: PsiElement, scopeDepth: Int): LLVMVariable? {
|
||||||
val conditionLable = codeBuilder.getNewLabel(prefix = "while")
|
val conditionLabel = codeBuilder.getNewLabel(prefix = "while")
|
||||||
val bodyLable = codeBuilder.getNewLabel(prefix = "while")
|
val bodyLabel = codeBuilder.getNewLabel(prefix = "while")
|
||||||
val exitLable = codeBuilder.getNewLabel(prefix = "while")
|
val exitLabel = codeBuilder.getNewLabel(prefix = "while")
|
||||||
|
|
||||||
codeBuilder.addUnconditionJump(conditionLable)
|
codeBuilder.addUnconditionJump(conditionLabel)
|
||||||
codeBuilder.markWithLabel(conditionLable)
|
codeBuilder.markWithLabel(conditionLabel)
|
||||||
val conditionResult = evaluateBinaryExpression(condition, scopeDepth + 1)
|
val conditionResult = evaluateBinaryExpression(condition, scopeDepth + 1)
|
||||||
|
|
||||||
codeBuilder.addCondition(conditionResult, bodyLable, exitLable)
|
codeBuilder.addCondition(conditionResult, bodyLabel, exitLabel)
|
||||||
evaluateCodeBlock(bodyExpression, bodyLable, conditionLable, scopeDepth + 1)
|
evaluateCodeBlock(bodyExpression, bodyLabel, conditionLabel, scopeDepth + 1)
|
||||||
codeBuilder.markWithLabel(exitLable)
|
codeBuilder.markWithLabel(exitLabel)
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -338,15 +434,8 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
|||||||
codeBuilder.addConstant(newVar, assignExpression)
|
codeBuilder.addConstant(newVar, assignExpression)
|
||||||
variableManager.addVariable(identifier.text, newVar, scopeDepth)
|
variableManager.addVariable(identifier.text, newVar, scopeDepth)
|
||||||
}
|
}
|
||||||
is LLVMConstructorCall -> {
|
|
||||||
val result = variableManager.receiveVariable(identifier!!.text, assignExpression.type, LLVMLocalScope(), pointer = false)
|
|
||||||
codeBuilder.allocVar(result)
|
|
||||||
result.pointer = true
|
|
||||||
codeBuilder.addLLVMCode(assignExpression.call(result).toString())
|
|
||||||
variableManager.addVariable(identifier.text, result, scopeDepth)
|
|
||||||
}
|
|
||||||
else -> {
|
else -> {
|
||||||
codeBuilder.addAssignment(LLVMVariable(identifier!!.text, LLVMIntType(), identifier.text, LLVMLocalScope()), assignExpression)
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
@@ -355,9 +444,21 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
|||||||
private fun evaluateReturnInstruction(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? {
|
private fun evaluateReturnInstruction(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? {
|
||||||
val next = element.getNextSiblingIgnoringWhitespaceAndComments()
|
val next = element.getNextSiblingIgnoringWhitespaceAndComments()
|
||||||
val retVar = evaluateExpression(next, scopeDepth) as LLVMSingleValue
|
val retVar = evaluateExpression(next, scopeDepth) as LLVMSingleValue
|
||||||
val retNativeValue = codeBuilder.receiveNativeValue(retVar)
|
|
||||||
|
|
||||||
codeBuilder.addReturnOperator(retNativeValue)
|
when (returnType.type) {
|
||||||
|
is LLVMReferenceType -> {
|
||||||
|
val src = codeBuilder.bitcast(retVar as LLVMVariable, LLVMCharType())
|
||||||
|
val dst = codeBuilder.bitcast(returnType, LLVMCharType())
|
||||||
|
val size = state.classes[(retVar.type as LLVMReferenceType).type]!!.size
|
||||||
|
codeBuilder.memcpy(dst, src, size)
|
||||||
|
codeBuilder.addVoidReturn()
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val retNativeValue = codeBuilder.receiveNativeValue(retVar)
|
||||||
|
codeBuilder.addReturnOperator(retNativeValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,11 +190,10 @@ class LLVMBuilder(val arm: Boolean) {
|
|||||||
llvmLocalCode.appendln(code)
|
llvmLocalCode.appendln(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bitcast(dst: LLVMVariable, llvmType: LLVMType): LLVMVariable {
|
fun bitcast(src: LLVMVariable, llvmType: LLVMType): LLVMVariable {
|
||||||
val empty = getNewVariable(llvmType, true)
|
val empty = getNewVariable(llvmType, true)
|
||||||
val code = "$empty = bitcast ${dst.getType()} $dst to $llvmType*"
|
val code = "$empty = bitcast ${src.getType()} $src to $llvmType*"
|
||||||
llvmLocalCode.appendln(code)
|
llvmLocalCode.appendln(code)
|
||||||
|
|
||||||
return empty
|
return empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ package org.kotlinnative.translator.llvm
|
|||||||
|
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||||
|
|
||||||
class LLVMCall(val returnType: LLVMType, val name: String, val arguments: List<LLVMVariable>) : LLVMSingleValue(returnType) {
|
class LLVMCall(val returnType: LLVMType, val name: String, val arguments: List<LLVMSingleValue>) : LLVMSingleValue(returnType) {
|
||||||
|
|
||||||
override fun toString(): String =
|
override fun toString(): String =
|
||||||
"call $returnType $name(${arguments.joinToString { "${it.getType()} ${it.label}" }})"
|
"call $returnType $name(${arguments.joinToString { "${it.getType()} ${it.toString()}" }})"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import org.kotlinnative.translator.llvm.types.*
|
|||||||
fun LLVMFunctionDescriptor(name: String, argTypes: List<LLVMVariable>?, returnType: LLVMType, declare: Boolean = false, arm: Boolean = false) =
|
fun LLVMFunctionDescriptor(name: String, argTypes: List<LLVMVariable>?, returnType: LLVMType, declare: Boolean = false, arm: Boolean = false) =
|
||||||
"${if (declare) "declare" else "define"} $returnType @$name(${
|
"${if (declare) "declare" else "define"} $returnType @$name(${
|
||||||
argTypes?.mapIndexed { i: Int, s: LLVMVariable ->
|
argTypes?.mapIndexed { i: Int, s: LLVMVariable ->
|
||||||
"${s.getType()} %${s.label}"
|
"${s.getType()} ${if (s.type is LLVMReferenceType && !(s.type as LLVMReferenceType).isReturn) "byval" else ""} %${s.label}"
|
||||||
}?.joinToString() }) ${ if (arm) "#0" else ""}"
|
}?.joinToString() }) ${ if (arm) "#0" else ""}"
|
||||||
|
|
||||||
fun LLVMMapStandardType(name: String, type: KotlinType): LLVMVariable = when {
|
fun LLVMMapStandardType(name: String, type: KotlinType): LLVMVariable = when {
|
||||||
@@ -17,5 +17,5 @@ fun LLVMMapStandardType(name: String, type: KotlinType): LLVMVariable = when {
|
|||||||
type.toString() == "Int" -> LLVMVariable(name, LLVMIntType(), type.toString())
|
type.toString() == "Int" -> LLVMVariable(name, LLVMIntType(), type.toString())
|
||||||
type.toString() == "Double" -> LLVMVariable(name, LLVMDoubleType(), type.toString())
|
type.toString() == "Double" -> LLVMVariable(name, LLVMDoubleType(), type.toString())
|
||||||
type.isUnit() -> LLVMVariable("", LLVMVoidType())
|
type.isUnit() -> LLVMVariable("", LLVMVoidType())
|
||||||
else -> LLVMVariable(name, LLVMReferenceType("%$type"), name, pointer = true)
|
else -> LLVMVariable(name, LLVMReferenceType("$type"), name, pointer = true)
|
||||||
}
|
}
|
||||||
+4
-3
@@ -2,12 +2,13 @@ package org.kotlinnative.translator.llvm.types
|
|||||||
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class LLVMReferenceType(val type: String, val prefix: String = "") : LLVMType() {
|
class LLVMReferenceType(val type: String, var prefix: String = "", var isReturn: Boolean = false) : LLVMType() {
|
||||||
|
|
||||||
|
override val defaultValue: String = ""
|
||||||
|
|
||||||
override val defaultValue = throw UnsupportedOperationException()
|
|
||||||
override val align = 4
|
override val align = 4
|
||||||
override val size: Byte = 4
|
override val size: Byte = 4
|
||||||
override fun toString() = "%$prefix.$type"
|
override fun toString() = "%$prefix${if (prefix.length > 0) "." else ""}$type"
|
||||||
|
|
||||||
private val params = ArrayList<String>()
|
private val params = ArrayList<String>()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user