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 org.jetbrains.kotlin.backend.konan.Context
|
||||
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.isObjCClass
|
||||
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 functionEntryPointAddress(descriptor: FunctionDescriptor) = descriptor.entryPointAddress.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 {
|
||||
@@ -352,6 +379,9 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
return call(context.llvm.allocInstanceFunction, listOf(typeInfo), lifetime)
|
||||
}
|
||||
|
||||
fun allocInstance(descriptor: ClassDescriptor, lifetime: Lifetime): LLVMValueRef =
|
||||
allocInstance(codegen.typeInfoForAllocation(descriptor), lifetime)
|
||||
|
||||
fun allocArray(
|
||||
typeInfo: LLVMValueRef, count: LLVMValueRef, lifetime: Lifetime): LLVMValueRef {
|
||||
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
|
||||
}
|
||||
|
||||
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() {
|
||||
if (!context.shouldContainDebugInfo()) return
|
||||
if (!currentPositionHolder.isAfterTerminator)
|
||||
|
||||
+1
@@ -439,6 +439,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
||||
val compilerUsedGlobals = mutableListOf<LLVMValueRef>()
|
||||
val staticInitializers = mutableListOf<LLVMValueRef>()
|
||||
val fileInitializers = mutableListOf<IrField>()
|
||||
val objects = mutableSetOf<LLVMValueRef>()
|
||||
|
||||
private object lazyRtFunction {
|
||||
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
|
||||
storeAny(codegen.kNullObjHeaderPtr, address)
|
||||
}
|
||||
objects.forEach { storeAny(codegen.kNullObjHeaderPtr, it) }
|
||||
context.llvm.objects.forEach { storeAny(codegen.kNullObjHeaderPtr, it) }
|
||||
ret(null)
|
||||
}
|
||||
|
||||
@@ -378,12 +378,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
override fun visitFile(declaration: IrFile) {
|
||||
// TODO: collect those two in one place.
|
||||
context.llvm.fileInitializers.clear()
|
||||
objects.clear()
|
||||
context.llvm.objects.clear()
|
||||
|
||||
using(FileScope(declaration)) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
|
||||
if (context.llvm.fileInitializers.isEmpty() && objects.isEmpty())
|
||||
if (context.llvm.fileInitializers.isEmpty() && context.llvm.objects.isEmpty())
|
||||
return
|
||||
|
||||
// Create global initialization records.
|
||||
@@ -449,7 +449,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
if (constructorDescriptor.isPrimary) {
|
||||
if (DescriptorUtils.isObject(classDescriptor)) {
|
||||
if (!classDescriptor.isUnit()) {
|
||||
val objectPtr = getObjectInstanceStorage(classDescriptor)
|
||||
val objectPtr = codegen.getObjectInstanceStorage(classDescriptor)
|
||||
|
||||
LLVMSetInitializer(objectPtr, codegen.kNullObjHeaderPtr)
|
||||
}
|
||||
@@ -730,35 +730,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun evaluateGetObjectValue(value: IrGetObjectValue): LLVMValueRef {
|
||||
if (value.descriptor.isUnit()) {
|
||||
return codegen.theUnitInstanceRef.llvm
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
private fun evaluateGetObjectValue(value: IrGetObjectValue): LLVMValueRef =
|
||||
functionGenerationContext.getObjectValue(
|
||||
value.descriptor,
|
||||
currentCodeContext.exceptionHandler,
|
||||
value.startLocation
|
||||
)
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -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 {
|
||||
context.log{"evaluateSetField : ${ir2string(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)),
|
||||
resultLifetime(callee))
|
||||
} else {
|
||||
functionGenerationContext.allocInstance(typeInfoForAllocation(constructedClass), resultLifetime(callee))
|
||||
functionGenerationContext.allocInstance(constructedClass, resultLifetime(callee))
|
||||
}
|
||||
evaluateSimpleFunctionCall(callee.descriptor,
|
||||
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 {
|
||||
@@ -2064,7 +2011,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val typeParameterT = context.ir.symbols.createUninitializedInstance.descriptor.typeParameters[0]
|
||||
val enumClass = callee.getTypeArgument(typeParameterT)!!
|
||||
val enumClassDescriptor = enumClass.constructor.declarationDescriptor as ClassDescriptor
|
||||
functionGenerationContext.allocInstance(typeInfoForAllocation(enumClassDescriptor), resultLifetime(callee))
|
||||
functionGenerationContext.allocInstance(enumClassDescriptor, resultLifetime(callee))
|
||||
}
|
||||
|
||||
else -> TODO(callee.descriptor.original.toString())
|
||||
|
||||
Reference in New Issue
Block a user