Move singleton support from IR visitor to code generator
This commit is contained in:
committed by
SvyatoslavScherbina
parent
d4f39f8142
commit
f986a0cb10
+64
@@ -21,6 +21,7 @@ import kotlinx.cinterop.*
|
|||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
||||||
|
import org.jetbrains.kotlin.backend.konan.descriptors.isUnit
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.stdlibModule
|
import org.jetbrains.kotlin.backend.konan.descriptors.stdlibModule
|
||||||
import org.jetbrains.kotlin.backend.konan.isObjCClass
|
import org.jetbrains.kotlin.backend.konan.isObjCClass
|
||||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||||
@@ -49,6 +50,32 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
|||||||
fun functionLlvmValue(descriptor: FunctionDescriptor) = descriptor.llvmFunction
|
fun functionLlvmValue(descriptor: FunctionDescriptor) = descriptor.llvmFunction
|
||||||
fun functionEntryPointAddress(descriptor: FunctionDescriptor) = descriptor.entryPointAddress.llvm
|
fun functionEntryPointAddress(descriptor: FunctionDescriptor) = descriptor.entryPointAddress.llvm
|
||||||
fun functionHash(descriptor: FunctionDescriptor): LLVMValueRef = descriptor.functionName.localHash.llvm
|
fun functionHash(descriptor: FunctionDescriptor): LLVMValueRef = descriptor.functionName.localHash.llvm
|
||||||
|
|
||||||
|
fun getObjectInstanceStorage(descriptor: ClassDescriptor): LLVMValueRef {
|
||||||
|
assert (!descriptor.isUnit())
|
||||||
|
val llvmGlobal = if (!isExternal(descriptor)) {
|
||||||
|
context.llvmDeclarations.forSingleton(descriptor).instanceFieldRef
|
||||||
|
} else {
|
||||||
|
val llvmType = getLLVMType(descriptor.defaultType)
|
||||||
|
importGlobal(
|
||||||
|
descriptor.objectInstanceFieldSymbolName,
|
||||||
|
llvmType,
|
||||||
|
origin = descriptor.llvmSymbolOrigin,
|
||||||
|
threadLocal = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
context.llvm.objects += llvmGlobal
|
||||||
|
return llvmGlobal
|
||||||
|
}
|
||||||
|
|
||||||
|
fun typeInfoForAllocation(constructedClass: ClassDescriptor): LLVMValueRef {
|
||||||
|
val descriptorForTypeInfo = if (constructedClass.isObjCClass()) {
|
||||||
|
context.interopBuiltIns.objCPointerHolder
|
||||||
|
} else {
|
||||||
|
constructedClass
|
||||||
|
}
|
||||||
|
return typeInfoValue(descriptorForTypeInfo)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class ExceptionHandler {
|
internal sealed class ExceptionHandler {
|
||||||
@@ -352,6 +379,9 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
return call(context.llvm.allocInstanceFunction, listOf(typeInfo), lifetime)
|
return call(context.llvm.allocInstanceFunction, listOf(typeInfo), lifetime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun allocInstance(descriptor: ClassDescriptor, lifetime: Lifetime): LLVMValueRef =
|
||||||
|
allocInstance(codegen.typeInfoForAllocation(descriptor), lifetime)
|
||||||
|
|
||||||
fun allocArray(
|
fun allocArray(
|
||||||
typeInfo: LLVMValueRef, count: LLVMValueRef, lifetime: Lifetime): LLVMValueRef {
|
typeInfo: LLVMValueRef, count: LLVMValueRef, lifetime: Lifetime): LLVMValueRef {
|
||||||
return call(context.llvm.allocArrayFunction, listOf(typeInfo, count), lifetime)
|
return call(context.llvm.allocArrayFunction, listOf(typeInfo, count), lifetime)
|
||||||
@@ -532,6 +562,40 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
return bitcast(functionPtrType, llvmMethod) // Cast method address to the type
|
return bitcast(functionPtrType, llvmMethod) // Cast method address to the type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getObjectValue(
|
||||||
|
descriptor: ClassDescriptor,
|
||||||
|
exceptionHandler: ExceptionHandler,
|
||||||
|
locationInfo: LocationInfo?
|
||||||
|
): LLVMValueRef {
|
||||||
|
if (descriptor.isUnit()) {
|
||||||
|
return codegen.theUnitInstanceRef.llvm
|
||||||
|
}
|
||||||
|
|
||||||
|
val objectPtr = codegen.getObjectInstanceStorage(descriptor)
|
||||||
|
val bbCurrent = currentBlock
|
||||||
|
val bbInit = basicBlock("label_init", locationInfo)
|
||||||
|
val bbExit = basicBlock("label_continue", locationInfo)
|
||||||
|
val objectVal = loadSlot(objectPtr, false)
|
||||||
|
val condition = icmpNe(objectVal, codegen.kNullObjHeaderPtr)
|
||||||
|
condBr(condition, bbExit, bbInit)
|
||||||
|
|
||||||
|
positionAtEnd(bbInit)
|
||||||
|
val typeInfo = codegen.typeInfoForAllocation(descriptor)
|
||||||
|
val initFunction = descriptor.constructors.first { it.valueParameters.size == 0 }
|
||||||
|
val ctor = codegen.llvmFunction(initFunction)
|
||||||
|
val args = listOf(objectPtr, typeInfo, ctor)
|
||||||
|
val newValue = call(context.llvm.initInstanceFunction, args, Lifetime.GLOBAL, exceptionHandler)
|
||||||
|
val bbInitResult = currentBlock
|
||||||
|
br(bbExit)
|
||||||
|
|
||||||
|
positionAtEnd(bbExit)
|
||||||
|
val valuePhi = phi(codegen.getLLVMType(descriptor.defaultType))
|
||||||
|
addPhiIncoming(valuePhi,
|
||||||
|
bbCurrent to objectVal, bbInitResult to newValue)
|
||||||
|
|
||||||
|
return valuePhi
|
||||||
|
}
|
||||||
|
|
||||||
fun resetDebugLocation() {
|
fun resetDebugLocation() {
|
||||||
if (!context.shouldContainDebugInfo()) return
|
if (!context.shouldContainDebugInfo()) return
|
||||||
if (!currentPositionHolder.isAfterTerminator)
|
if (!currentPositionHolder.isAfterTerminator)
|
||||||
|
|||||||
+1
@@ -439,6 +439,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
|||||||
val compilerUsedGlobals = mutableListOf<LLVMValueRef>()
|
val compilerUsedGlobals = mutableListOf<LLVMValueRef>()
|
||||||
val staticInitializers = mutableListOf<LLVMValueRef>()
|
val staticInitializers = mutableListOf<LLVMValueRef>()
|
||||||
val fileInitializers = mutableListOf<IrField>()
|
val fileInitializers = mutableListOf<IrField>()
|
||||||
|
val objects = mutableSetOf<LLVMValueRef>()
|
||||||
|
|
||||||
private object lazyRtFunction {
|
private object lazyRtFunction {
|
||||||
operator fun provideDelegate(
|
operator fun provideDelegate(
|
||||||
|
|||||||
+12
-65
@@ -332,7 +332,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
val address = context.llvmDeclarations.forStaticField(descriptor).storage
|
val address = context.llvmDeclarations.forStaticField(descriptor).storage
|
||||||
storeAny(codegen.kNullObjHeaderPtr, address)
|
storeAny(codegen.kNullObjHeaderPtr, address)
|
||||||
}
|
}
|
||||||
objects.forEach { storeAny(codegen.kNullObjHeaderPtr, it) }
|
context.llvm.objects.forEach { storeAny(codegen.kNullObjHeaderPtr, it) }
|
||||||
ret(null)
|
ret(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,12 +378,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
override fun visitFile(declaration: IrFile) {
|
override fun visitFile(declaration: IrFile) {
|
||||||
// TODO: collect those two in one place.
|
// TODO: collect those two in one place.
|
||||||
context.llvm.fileInitializers.clear()
|
context.llvm.fileInitializers.clear()
|
||||||
objects.clear()
|
context.llvm.objects.clear()
|
||||||
|
|
||||||
using(FileScope(declaration)) {
|
using(FileScope(declaration)) {
|
||||||
declaration.acceptChildrenVoid(this)
|
declaration.acceptChildrenVoid(this)
|
||||||
|
|
||||||
if (context.llvm.fileInitializers.isEmpty() && objects.isEmpty())
|
if (context.llvm.fileInitializers.isEmpty() && context.llvm.objects.isEmpty())
|
||||||
return
|
return
|
||||||
|
|
||||||
// Create global initialization records.
|
// Create global initialization records.
|
||||||
@@ -449,7 +449,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
if (constructorDescriptor.isPrimary) {
|
if (constructorDescriptor.isPrimary) {
|
||||||
if (DescriptorUtils.isObject(classDescriptor)) {
|
if (DescriptorUtils.isObject(classDescriptor)) {
|
||||||
if (!classDescriptor.isUnit()) {
|
if (!classDescriptor.isUnit()) {
|
||||||
val objectPtr = getObjectInstanceStorage(classDescriptor)
|
val objectPtr = codegen.getObjectInstanceStorage(classDescriptor)
|
||||||
|
|
||||||
LLVMSetInitializer(objectPtr, codegen.kNullObjHeaderPtr)
|
LLVMSetInitializer(objectPtr, codegen.kNullObjHeaderPtr)
|
||||||
}
|
}
|
||||||
@@ -730,35 +730,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private fun evaluateGetObjectValue(value: IrGetObjectValue): LLVMValueRef {
|
private fun evaluateGetObjectValue(value: IrGetObjectValue): LLVMValueRef =
|
||||||
if (value.descriptor.isUnit()) {
|
functionGenerationContext.getObjectValue(
|
||||||
return codegen.theUnitInstanceRef.llvm
|
value.descriptor,
|
||||||
}
|
currentCodeContext.exceptionHandler,
|
||||||
|
value.startLocation
|
||||||
val objectPtr = getObjectInstanceStorage(value.descriptor)
|
)
|
||||||
val bbCurrent = functionGenerationContext.currentBlock
|
|
||||||
val bbInit = functionGenerationContext.basicBlock("label_init", value.startLocation)
|
|
||||||
val bbExit = functionGenerationContext.basicBlock("label_continue", value.startLocation)
|
|
||||||
val objectVal = functionGenerationContext.loadSlot(objectPtr, false)
|
|
||||||
val condition = functionGenerationContext.icmpNe(objectVal, codegen.kNullObjHeaderPtr)
|
|
||||||
functionGenerationContext.condBr(condition, bbExit, bbInit)
|
|
||||||
|
|
||||||
functionGenerationContext.positionAtEnd(bbInit)
|
|
||||||
val typeInfo = typeInfoForAllocation(value.descriptor)
|
|
||||||
val initFunction = value.descriptor.constructors.first { it.valueParameters.size == 0 }
|
|
||||||
val ctor = codegen.llvmFunction(initFunction)
|
|
||||||
val args = listOf(objectPtr, typeInfo, ctor)
|
|
||||||
val newValue = call(context.llvm.initInstanceFunction, args, Lifetime.GLOBAL)
|
|
||||||
val bbInitResult = functionGenerationContext.currentBlock
|
|
||||||
functionGenerationContext.br(bbExit)
|
|
||||||
|
|
||||||
functionGenerationContext.positionAtEnd(bbExit)
|
|
||||||
val valuePhi = functionGenerationContext.phi(codegen.getLLVMType(value.type))
|
|
||||||
functionGenerationContext.addPhiIncoming(valuePhi,
|
|
||||||
bbCurrent to objectVal, bbInitResult to newValue)
|
|
||||||
|
|
||||||
return valuePhi
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
@@ -1300,27 +1277,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private val objects = mutableSetOf<LLVMValueRef>()
|
|
||||||
|
|
||||||
private fun getObjectInstanceStorage(descriptor: ClassDescriptor): LLVMValueRef {
|
|
||||||
assert (!descriptor.isUnit())
|
|
||||||
val llvmGlobal = if (!codegen.isExternal(descriptor)) {
|
|
||||||
context.llvmDeclarations.forSingleton(descriptor).instanceFieldRef
|
|
||||||
} else {
|
|
||||||
val llvmType = codegen.getLLVMType(descriptor.defaultType)
|
|
||||||
codegen.importGlobal(
|
|
||||||
descriptor.objectInstanceFieldSymbolName,
|
|
||||||
llvmType,
|
|
||||||
origin = descriptor.llvmSymbolOrigin,
|
|
||||||
threadLocal = true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
objects += llvmGlobal
|
|
||||||
return llvmGlobal
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
private fun evaluateSetField(value: IrSetField): LLVMValueRef {
|
private fun evaluateSetField(value: IrSetField): LLVMValueRef {
|
||||||
context.log{"evaluateSetField : ${ir2string(value)}"}
|
context.log{"evaluateSetField : ${ir2string(value)}"}
|
||||||
val valueToAssign = evaluateExpression(value.value)
|
val valueToAssign = evaluateExpression(value.value)
|
||||||
@@ -1947,7 +1903,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
callDirect(context.interopBuiltIns.allocObjCObject, listOf(genGetObjCClass(constructedClass)),
|
callDirect(context.interopBuiltIns.allocObjCObject, listOf(genGetObjCClass(constructedClass)),
|
||||||
resultLifetime(callee))
|
resultLifetime(callee))
|
||||||
} else {
|
} else {
|
||||||
functionGenerationContext.allocInstance(typeInfoForAllocation(constructedClass), resultLifetime(callee))
|
functionGenerationContext.allocInstance(constructedClass, resultLifetime(callee))
|
||||||
}
|
}
|
||||||
evaluateSimpleFunctionCall(callee.descriptor,
|
evaluateSimpleFunctionCall(callee.descriptor,
|
||||||
listOf(thisValue) + args, Lifetime.IRRELEVANT /* constructor doesn't return anything */)
|
listOf(thisValue) + args, Lifetime.IRRELEVANT /* constructor doesn't return anything */)
|
||||||
@@ -1955,15 +1911,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun typeInfoForAllocation(constructedClass: ClassDescriptor): LLVMValueRef {
|
|
||||||
val descriptorForTypeInfo = if (constructedClass.isObjCClass()) {
|
|
||||||
context.interopBuiltIns.objCPointerHolder
|
|
||||||
} else {
|
|
||||||
constructedClass
|
|
||||||
}
|
|
||||||
return codegen.typeInfoValue(descriptorForTypeInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private fun evaluateIntrinsicCall(callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
private fun evaluateIntrinsicCall(callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
||||||
@@ -2064,7 +2011,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
val typeParameterT = context.ir.symbols.createUninitializedInstance.descriptor.typeParameters[0]
|
val typeParameterT = context.ir.symbols.createUninitializedInstance.descriptor.typeParameters[0]
|
||||||
val enumClass = callee.getTypeArgument(typeParameterT)!!
|
val enumClass = callee.getTypeArgument(typeParameterT)!!
|
||||||
val enumClassDescriptor = enumClass.constructor.declarationDescriptor as ClassDescriptor
|
val enumClassDescriptor = enumClass.constructor.declarationDescriptor as ClassDescriptor
|
||||||
functionGenerationContext.allocInstance(typeInfoForAllocation(enumClassDescriptor), resultLifetime(callee))
|
functionGenerationContext.allocInstance(enumClassDescriptor, resultLifetime(callee))
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> TODO(callee.descriptor.original.toString())
|
else -> TODO(callee.descriptor.original.toString())
|
||||||
|
|||||||
Reference in New Issue
Block a user