Rework variable management for memory management's sake. (#156)
This commit is contained in:
+7
-2
@@ -8,7 +8,6 @@ import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
@@ -17,6 +16,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
val returns: MutableMap<LLVMBasicBlockRef, LLVMValueRef> = mutableMapOf()
|
||||
// TODO: remove, to make CodeGenerator descriptor-agnostic.
|
||||
var constructedClass: ClassDescriptor? = null
|
||||
val vars = VariableManager(this)
|
||||
|
||||
fun prologue(descriptor: FunctionDescriptor) {
|
||||
prologue(llvmFunction(descriptor),
|
||||
@@ -46,10 +46,14 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
appendingTo(epilogueBb!!) {
|
||||
when {
|
||||
returnType == voidType -> LLVMBuildRetVoid(builder)
|
||||
returnType == voidType -> {
|
||||
vars.releaseVars()
|
||||
LLVMBuildRetVoid(builder)
|
||||
}
|
||||
returns.size > 0 -> {
|
||||
val returnPhi = phi(returnType!!)
|
||||
addPhiIncoming(returnPhi, *returns.toList().toTypedArray())
|
||||
vars.releaseVars()
|
||||
LLVMBuildRet(builder, returnPhi)
|
||||
}
|
||||
// Do nothing, all paths throw.
|
||||
@@ -58,6 +62,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
}
|
||||
|
||||
returns.clear()
|
||||
vars.clear()
|
||||
}
|
||||
|
||||
private var prologueBb: LLVMBasicBlockRef? = null
|
||||
|
||||
+86
-103
@@ -12,14 +12,12 @@ import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltinOperatorDescriptorBase
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBinaryPrimitiveImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetterCallImpl
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
@@ -116,6 +114,47 @@ internal class MetadatorVisitor(val context: Context) : IrElementVisitorVoid {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines how to generate context-dependent operations.
|
||||
*/
|
||||
interface CodeContext {
|
||||
|
||||
fun genReturn(target: CallableDescriptor, value: LLVMValueRef?)
|
||||
|
||||
fun genBreak(destination: IrBreak)
|
||||
|
||||
fun genContinue(destination: IrContinue)
|
||||
|
||||
fun genCall(function: LLVMValueRef, args: List<LLVMValueRef>): LLVMValueRef
|
||||
|
||||
fun genThrow(exception: LLVMValueRef)
|
||||
|
||||
/**
|
||||
* Declares the variable.
|
||||
* @return index of declared variable.
|
||||
*/
|
||||
fun genDeclareVariable(descriptor: VariableDescriptor, value: LLVMValueRef?): Int
|
||||
|
||||
/**
|
||||
* @return index of variable declared before, or -1 if no such variable has been declared yet.
|
||||
*/
|
||||
fun getDeclaredVariable(descriptor: VariableDescriptor): Int
|
||||
|
||||
/**
|
||||
* Generates the code to obtain a value available in this context.
|
||||
*
|
||||
* @return the requested value
|
||||
*/
|
||||
fun genGetValue(descriptor: ValueDescriptor): LLVMValueRef
|
||||
|
||||
/**
|
||||
* Returns owning function scope.
|
||||
*
|
||||
* @return the requested value
|
||||
*/
|
||||
fun functionScope(): CodeContext
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
@@ -128,47 +167,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
// TODO: consider eliminating mutable state
|
||||
private var currentCodeContext: CodeContext = TopLevelCodeContext
|
||||
|
||||
/**
|
||||
* Defines how to generate context-dependent operations.
|
||||
*/
|
||||
private interface CodeContext {
|
||||
|
||||
fun genReturn(target: CallableDescriptor, value: LLVMValueRef?)
|
||||
|
||||
fun genBreak(destination: IrBreak)
|
||||
|
||||
fun genContinue(destination: IrContinue)
|
||||
|
||||
fun genCall(function: LLVMValueRef, args: List<LLVMValueRef>): LLVMValueRef
|
||||
|
||||
fun genThrow(exception: LLVMValueRef)
|
||||
|
||||
/**
|
||||
* Declares the variable.
|
||||
* @return pointer to the declared variable.
|
||||
*/
|
||||
fun genDeclareVariable(descriptor: VariableDescriptor): LLVMValueRef
|
||||
|
||||
/**
|
||||
* @return pointer to the variable declared before, or `null` if no such variable has been declared yet.
|
||||
*/
|
||||
fun getDeclaredVariable(descriptor: VariableDescriptor): LLVMValueRef?
|
||||
|
||||
/**
|
||||
* Generates the code to obtain a value available in this context.
|
||||
*
|
||||
* @return the requested value
|
||||
*/
|
||||
fun genGetValue(descriptor: ValueDescriptor, result: String = ""): LLVMValueRef
|
||||
|
||||
/**
|
||||
* Returns owning function scope.
|
||||
*
|
||||
* @return the requested value
|
||||
*/
|
||||
fun functionScope(): CodeContext
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fake [CodeContext] that doesn't support any operation.
|
||||
@@ -188,11 +186,11 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
override fun genThrow(exception: LLVMValueRef) = unsupported()
|
||||
|
||||
override fun genDeclareVariable(descriptor: VariableDescriptor) = unsupported(descriptor)
|
||||
override fun genDeclareVariable(descriptor: VariableDescriptor, value: LLVMValueRef?) = unsupported(descriptor)
|
||||
|
||||
override fun getDeclaredVariable(descriptor: VariableDescriptor) = null
|
||||
override fun getDeclaredVariable(descriptor: VariableDescriptor) = -1
|
||||
|
||||
override fun genGetValue(descriptor: ValueDescriptor, result: String) = unsupported(descriptor)
|
||||
override fun genGetValue(descriptor: ValueDescriptor) = unsupported(descriptor)
|
||||
|
||||
override fun functionScope(): CodeContext = unsupported()
|
||||
}
|
||||
@@ -294,6 +292,8 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
if (context.llvm.fileInitializers.isEmpty())
|
||||
return
|
||||
|
||||
// Create global initialization records.
|
||||
val fileName = declaration.name.takeLastWhile { it != '/' }.dropLastWhile { it != '.' }.dropLast(1)
|
||||
val initName = "${fileName}_init_${context.llvm.globalInitIndex}"
|
||||
val nodeName = "${fileName}_node_${context.llvm.globalInitIndex}"
|
||||
@@ -324,14 +324,14 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
val loopExit = codegen.basicBlock()
|
||||
|
||||
override fun genBreak(destination: IrBreak) {
|
||||
if (destination.label == loop.label)
|
||||
if (destination.label == null || destination.label == loop.label)
|
||||
codegen.br(loopExit)
|
||||
else
|
||||
super.genBreak(destination)
|
||||
}
|
||||
|
||||
override fun genContinue(destination: IrContinue) {
|
||||
if (destination.label == loop.label)
|
||||
if (destination.label == null || destination.label == loop.label)
|
||||
codegen.br(loopCheck)
|
||||
else
|
||||
super.genContinue(destination)
|
||||
@@ -380,7 +380,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
using(FunctionScope(constructorDeclaration)) {
|
||||
|
||||
val thisPtr = currentCodeContext.genGetValue(classDescriptor.thisAsReceiverParameter, "this")
|
||||
val thisPtr = currentCodeContext.genGetValue(classDescriptor.thisAsReceiverParameter)
|
||||
|
||||
/**
|
||||
* IR for kotlin.Any is:
|
||||
@@ -494,30 +494,21 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
*/
|
||||
private inner class VariableScope : InnerScopeImpl() {
|
||||
|
||||
private val variables = mutableMapOf<ValueDescriptor, LLVMValueRef>()
|
||||
|
||||
override fun genDeclareVariable(descriptor: VariableDescriptor): LLVMValueRef {
|
||||
// Check that the variable is not declared yet:
|
||||
assert (this.getDeclaredVariable(descriptor) == null)
|
||||
|
||||
val res = codegen.alloca(descriptor.type, descriptor.name.asString())
|
||||
|
||||
val previous = variables.put(descriptor, res)
|
||||
assert (previous == null)
|
||||
|
||||
return res
|
||||
override fun genDeclareVariable(descriptor: VariableDescriptor, value: LLVMValueRef?): Int {
|
||||
return codegen.vars.createVariable(descriptor to this, value)
|
||||
}
|
||||
|
||||
override fun getDeclaredVariable(descriptor: VariableDescriptor): LLVMValueRef? {
|
||||
return variables[descriptor] ?: super.getDeclaredVariable(descriptor)
|
||||
override fun getDeclaredVariable(descriptor: VariableDescriptor): Int {
|
||||
val index = codegen.vars.indexOf(descriptor to this)
|
||||
return if (index < 0) super.getDeclaredVariable(descriptor) else return index
|
||||
}
|
||||
|
||||
override fun genGetValue(descriptor: ValueDescriptor, result: String): LLVMValueRef {
|
||||
val variable = variables[descriptor]
|
||||
if (variable != null) {
|
||||
return codegen.load(variable, result)
|
||||
override fun genGetValue(descriptor: ValueDescriptor): LLVMValueRef {
|
||||
val index = codegen.vars.indexOf(descriptor to this)
|
||||
if (index < 0) {
|
||||
return super.genGetValue(descriptor)
|
||||
} else {
|
||||
return super.genGetValue(descriptor, result)
|
||||
return codegen.vars.load(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -526,23 +517,24 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
* The scope of parameter visibility.
|
||||
*/
|
||||
private open inner class ParameterScope(
|
||||
private val parameters: Map<ParameterDescriptor, LLVMValueRef>): InnerScopeImpl() {
|
||||
parameters: Map<ParameterDescriptor, LLVMValueRef>): InnerScopeImpl() {
|
||||
|
||||
// Note: it is possible to generate access to a parameter without any variables,
|
||||
// however variables are named and thus the resulting bitcode can be more readable.
|
||||
|
||||
private val parameterVars = parameters.map { (descriptor, value) ->
|
||||
val variable = codegen.alloca(descriptor.type, descriptor.name.asString())
|
||||
codegen.store(value, variable)
|
||||
descriptor to variable
|
||||
}.toMap()
|
||||
init {
|
||||
parameters.map { (descriptor, value) ->
|
||||
codegen.vars.createImmutable(descriptor to this, value)
|
||||
}
|
||||
|
||||
override fun genGetValue(descriptor: ValueDescriptor, result: String): LLVMValueRef {
|
||||
val variable = parameterVars[descriptor]
|
||||
if (variable != null) {
|
||||
return codegen.load(variable, result)
|
||||
}
|
||||
|
||||
override fun genGetValue(descriptor: ValueDescriptor): LLVMValueRef {
|
||||
val index = codegen.vars.indexOf(descriptor to this)
|
||||
if (index < 0) {
|
||||
return super.genGetValue(descriptor)
|
||||
} else {
|
||||
return super.genGetValue(descriptor, result)
|
||||
return codegen.vars.load(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1082,7 +1074,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
codegen.appendingTo(body) {
|
||||
using(VariableScope()) {
|
||||
createVariable(it.parameter, exception)
|
||||
currentCodeContext.genDeclareVariable(it.parameter, exception)
|
||||
evaluateExpressionAndJump(it.result, success)
|
||||
}
|
||||
}
|
||||
@@ -1250,7 +1242,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
val isUnit = KotlinBuiltIns.isUnit(expression.type)
|
||||
val isNothing = KotlinBuiltIns.isNothing(expression.type)
|
||||
val neitherUnitNorNothing = !isNothing && !isUnit
|
||||
val tmpLlvmVariablePtr = if (!isUnit) codegen.alloca(expression.type) else null
|
||||
val tmpLlvmVariable = if (!isUnit) codegen.vars.createAnonymousMutable(expression.type) else -1
|
||||
|
||||
expression.branches.forEach { // Iterate through "when" branches (clauses).
|
||||
var bbNext = bbExit // For last clause bbNext coincides with bbExit.
|
||||
@@ -1258,10 +1250,10 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
bbNext = codegen.basicBlock() // Create new basic block for next clause.
|
||||
val isUnitBranch = KotlinBuiltIns.isUnit(it.result.type)
|
||||
val isNothingBranch = KotlinBuiltIns.isNothing(it.result.type)
|
||||
generateWhenCase(isUnitBranch, isNothingBranch, tmpLlvmVariablePtr, it, bbNext, bbExit) // Generate code for current clause.
|
||||
generateWhenCase(isUnitBranch, isNothingBranch, tmpLlvmVariable, it, bbNext, bbExit) // Generate code for current clause.
|
||||
}
|
||||
if (neitherUnitNorNothing) // If result hasn't Unit type and block doesn't end with return
|
||||
return codegen.load(tmpLlvmVariablePtr!!) // load value from variable.
|
||||
return codegen.vars.load(tmpLlvmVariable) // load value from variable.
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -1319,8 +1311,8 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
private fun evaluateSetVariable(value: IrSetVariable): LLVMValueRef? {
|
||||
context.log("evaluateSetVariable : ${ir2string(value)}")
|
||||
val ret = evaluateExpression(value.value)!!
|
||||
val variable = currentCodeContext.getDeclaredVariable(value.descriptor)!!
|
||||
codegen.store(ret, variable)
|
||||
val variable = currentCodeContext.getDeclaredVariable(value.descriptor)
|
||||
codegen.vars.store(ret, variable)
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -1329,20 +1321,10 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
private fun evaluateVariable(value: IrVariable): LLVMValueRef? {
|
||||
context.log("evaluateVariable : ${ir2string(value)}")
|
||||
val ret = value.initializer?.let { evaluateExpression(it)!! }
|
||||
createVariable(value.descriptor, ret)
|
||||
currentCodeContext.genDeclareVariable(value.descriptor, ret)
|
||||
return null
|
||||
}
|
||||
|
||||
private fun createVariable(descriptor: VariableDescriptor, value: LLVMValueRef? = null): LLVMValueRef {
|
||||
|
||||
val newVariable = currentCodeContext.genDeclareVariable(descriptor)
|
||||
|
||||
if (value != null) {
|
||||
codegen.store(value, newVariable)
|
||||
}
|
||||
return newVariable
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun evaluateTypeOperator(value: IrTypeOperatorCall): LLVMValueRef? {
|
||||
@@ -1366,23 +1348,23 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
val bbExit = codegen.basicBlock()
|
||||
|
||||
val resultLlvmType = codegen.getLLVMType(value.type)
|
||||
val result = codegen.alloca(resultLlvmType)
|
||||
val result = codegen.vars.createAnonymousMutable(resultLlvmType)
|
||||
|
||||
val condition = evaluateInstanceOf(value)
|
||||
codegen.condBr(condition, bbTrue, bbFalse)
|
||||
|
||||
codegen.positionAtEnd(bbTrue)
|
||||
val castResult = evaluateExpression(value.argument)
|
||||
codegen.store(castResult!!, result)
|
||||
codegen.vars.store(castResult!!, result)
|
||||
codegen.br(bbExit)
|
||||
|
||||
codegen.positionAtEnd(bbFalse)
|
||||
val nullResult = LLVMConstNull(resultLlvmType)!!
|
||||
codegen.store(nullResult, result)
|
||||
codegen.vars.store(nullResult, result)
|
||||
codegen.br(bbExit)
|
||||
|
||||
codegen.positionAtEnd(bbExit)
|
||||
return codegen.load(result)
|
||||
return codegen.vars.load(result)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -1870,13 +1852,14 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun generateWhenCase(isUnit:Boolean, isNothing:Boolean, resultPtr: LLVMValueRef?, branch: IrBranch, bbNext: LLVMBasicBlockRef?, bbExit: LLVMBasicBlockRef?) {
|
||||
private fun generateWhenCase(isUnit:Boolean, isNothing:Boolean, resultPtr: Int,
|
||||
branch: IrBranch, bbNext: LLVMBasicBlockRef?, bbExit: LLVMBasicBlockRef?) {
|
||||
val neitherUnitNorNothing = !isNothing && !isUnit // If branches doesn't end with 'return' either result hasn't got 'unit' type.
|
||||
val branchResult = branch.result
|
||||
if (isUnconditional(branch)) { // It is the "else" clause.
|
||||
val brResult = evaluateExpression(branchResult) // Generate clause body.
|
||||
if (neitherUnitNorNothing) // If nor unit neither result ends with return
|
||||
codegen.store(brResult!!, resultPtr!!) // we store result to temporal variable.
|
||||
codegen.vars.store(brResult!!, resultPtr) // we store result to temporal variable.
|
||||
if (bbExit == null) return // If 'bbExit' isn't defined just return
|
||||
codegen.br(bbExit) // Generate branch to bbExit.
|
||||
codegen.positionAtEnd(bbExit) // Switch generation to bbExit.
|
||||
@@ -1887,7 +1870,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
codegen.positionAtEnd(bbCurr) // Switch generation to block for clause body.
|
||||
val brResult = evaluateExpression(branch.result) // Generate clause body.
|
||||
if (neitherUnitNorNothing) // If nor unit neither result ends with return
|
||||
codegen.store(brResult!!, resultPtr!!) // we store result to temporal variable.
|
||||
codegen.vars.store(brResult!!, resultPtr) // we store result to temporal variable.
|
||||
if (!isNothing) // If basic block doesn't end with 'return'
|
||||
codegen.br(bbExit!!) // generate branch to bbExit.
|
||||
codegen.positionAtEnd(bbNext!!) // Switch generation to bbNextClause.
|
||||
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.types.*
|
||||
|
||||
|
||||
internal class VariableManager(val codegen: CodeGenerator) {
|
||||
internal interface Record {
|
||||
fun load() : LLVMValueRef
|
||||
fun store(value: LLVMValueRef)
|
||||
fun address() : LLVMValueRef
|
||||
fun isRefSlot() : Boolean
|
||||
}
|
||||
|
||||
inner class SlotRecord(val address: LLVMValueRef, val refSlot: Boolean) : Record {
|
||||
override fun load() : LLVMValueRef {
|
||||
return codegen.load(address)
|
||||
}
|
||||
override fun store(value: LLVMValueRef) {
|
||||
codegen.store(value, address)
|
||||
}
|
||||
override fun address() : LLVMValueRef {
|
||||
return this.address
|
||||
}
|
||||
override fun isRefSlot() = this.refSlot
|
||||
|
||||
override fun toString() = (if (refSlot) "refslot" else "slot") + " for ${address}"
|
||||
}
|
||||
|
||||
class ValueRecord(val value: LLVMValueRef, val descriptor: ValueDescriptor) : Record {
|
||||
override fun load() : LLVMValueRef {
|
||||
return value
|
||||
}
|
||||
override fun store(value: LLVMValueRef) {
|
||||
throw Error("writing to immutable: ${descriptor}")
|
||||
}
|
||||
override fun address() : LLVMValueRef {
|
||||
throw Error("no address for: ${descriptor}")
|
||||
}
|
||||
override fun isRefSlot() : Boolean = false
|
||||
|
||||
override fun toString() = "value of ${value} from ${descriptor}"
|
||||
}
|
||||
|
||||
val variables: ArrayList<Record> = arrayListOf()
|
||||
val descriptors: HashMap<Pair<ValueDescriptor, CodeContext>, Int> = hashMapOf()
|
||||
|
||||
// Clears inner state of variable manager.
|
||||
fun clear() {
|
||||
variables.clear()
|
||||
descriptors.clear()
|
||||
}
|
||||
|
||||
fun releaseVars() {
|
||||
// This function is called by codegen to cleanup local references when leaving frame.
|
||||
}
|
||||
|
||||
fun createVariable(scoped: Pair<VariableDescriptor, CodeContext>, value: LLVMValueRef? = null) : Int {
|
||||
// TODO: fix, due to the bug in frontend, we shall always create stack slot for variable now.
|
||||
// Note that we always create slot for object references for memory management.
|
||||
val descriptor = scoped.first
|
||||
if (descriptor.isVar() || isObjectType(codegen.getLLVMType(descriptor.type)) || true) {
|
||||
return createMutable(scoped, value)
|
||||
} else {
|
||||
return createImmutable(scoped, value!!)
|
||||
}
|
||||
}
|
||||
|
||||
fun createMutable(scoped: Pair<VariableDescriptor, CodeContext>, value: LLVMValueRef? = null) : Int {
|
||||
val descriptor = scoped.first
|
||||
assert(descriptors.get(scoped) == null)
|
||||
val index = variables.size
|
||||
val type = codegen.getLLVMType(descriptor.type)
|
||||
val slot = codegen.alloca(type, descriptor.name.asString())
|
||||
if (value != null)
|
||||
codegen.store(value, slot)
|
||||
variables.add(SlotRecord(slot, isObjectType(type)))
|
||||
descriptors[scoped] = index
|
||||
return index
|
||||
}
|
||||
|
||||
// Creates anonymous mutable variable.
|
||||
fun createAnonymousMutable(type: KotlinType, value: LLVMValueRef? = null) : Int {
|
||||
return createAnonymousMutable(codegen.getLLVMType(type), value)
|
||||
}
|
||||
|
||||
fun createAnonymousMutable(type: LLVMTypeRef, value: LLVMValueRef? = null) : Int {
|
||||
val index = variables.size
|
||||
val slot = codegen.alloca(type)
|
||||
if (value != null)
|
||||
codegen.store(value, slot)
|
||||
variables.add(SlotRecord(slot, isObjectType(type)))
|
||||
return index
|
||||
}
|
||||
|
||||
fun createImmutable(scoped: Pair<ValueDescriptor, CodeContext>, value: LLVMValueRef) : Int {
|
||||
val descriptor = scoped.first
|
||||
assert(descriptors.get(scoped) == null)
|
||||
val index = variables.size
|
||||
variables.add(ValueRecord(value, descriptor))
|
||||
descriptors[scoped] = index
|
||||
return index
|
||||
}
|
||||
|
||||
fun indexOf(scoped: Pair<ValueDescriptor, CodeContext>) : Int {
|
||||
return descriptors.getOrElse(scoped) { -1 }
|
||||
}
|
||||
|
||||
fun addressOf(index: Int): LLVMValueRef {
|
||||
return variables[index].address()
|
||||
}
|
||||
|
||||
fun load(index: Int): LLVMValueRef {
|
||||
return variables[index].load()
|
||||
}
|
||||
|
||||
fun store(value: LLVMValueRef, index: Int) {
|
||||
variables[index].store(value)
|
||||
}
|
||||
|
||||
private fun isObjectType(type: LLVMTypeRef) : Boolean {
|
||||
return type == codegen.kObjHeaderPtr || type == codegen.kArrayHeaderPtr
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user