CODEGEN: spread element implementation
This commit is contained in:
committed by
vvlevchenko
parent
d8fe22cfb8
commit
68e324c207
+1
@@ -26,6 +26,7 @@ internal class Context(val irModule: IrModuleFragment, val runtime: Runtime, val
|
||||
val initInstanceFunction = importRtFunction("InitInstance")
|
||||
val allocArrayFunction = importRtFunction("AllocArrayInstance")
|
||||
val setArrayFunction = importRtFunction("Kotlin_Array_set")
|
||||
val copyImplArrayFunction = importRtFunction("Kotlin_Array_copyImpl")
|
||||
val lookupFieldOffset = importRtFunction("LookupFieldOffset")
|
||||
val lookupOpenMethodFunction = importRtFunction("LookupOpenMethod")
|
||||
val isInstanceFunction = importRtFunction("IsInstance")
|
||||
|
||||
+30
-15
@@ -727,30 +727,45 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun evaluateVararg(tmpVariableName: String, value: IrVararg): LLVMValueRef? {
|
||||
val arguments = value.elements.map {
|
||||
assert (it !is IrSpreadElement)
|
||||
evaluateExpression(codegen.newVar(), it)!!
|
||||
var oneSizedElementsCount = 0
|
||||
data class Element(val exp: LLVMValueRef, val size: LLVMValueRef?, val isArray: Boolean)
|
||||
|
||||
val elements = value.elements.map {
|
||||
if (it is IrSpreadElement) {
|
||||
val exp = evaluateExpression(codegen.newVar(), it.expression)!!
|
||||
val array = codegen.bitcast(codegen.kArrayHeaderPtr, exp, codegen.newVar())
|
||||
val sizePtr = LLVMBuildStructGEP(codegen.builder, array, 1, codegen.newVar())
|
||||
return@map Element(exp, codegen.load(sizePtr!!, codegen.newVar()), true)
|
||||
}
|
||||
val exp = evaluateExpression(codegen.newVar(), it)!!
|
||||
oneSizedElementsCount++
|
||||
return@map Element(exp, null, false)
|
||||
}
|
||||
|
||||
return genCreateArray(tmpVariableName, value.type, arguments)
|
||||
}
|
||||
|
||||
private fun genCreateArray(tmpVariableName: String,
|
||||
arrayType: KotlinType, elements: List<LLVMValueRef>): LLVMValueRef {
|
||||
|
||||
if (elements.all { codegen.isConst(it) }) {
|
||||
if (elements.all { codegen.isConst(it.exp) && !it.isArray }) {
|
||||
// Note: even if all elements are const, they aren't guaranteed to be statically initialized.
|
||||
// E.g. an element may be a pointer to lazy-initialized object (aka singleton).
|
||||
// However it is guaranteed that all elements are already initialized at this point.
|
||||
return codegen.staticData.createKotlinArray(arrayType, elements)
|
||||
return codegen.staticData.createKotlinArray(value.type, elements.map { it.exp })
|
||||
}
|
||||
|
||||
val typeInfo = codegen.typeInfoValue(arrayType)!!
|
||||
val length = LLVMConstInt(LLVMInt32Type(), oneSizedElementsCount.toLong(), 0)
|
||||
val finalLength = elements.filter { it.isArray }.fold(length) { sum, (_, size, _) ->
|
||||
codegen.plus(sum!!, size!!, codegen.newVar())
|
||||
}
|
||||
|
||||
val arrayCreationArgs = listOf(typeInfo, kImmInt32One, Int32(elements.size).llvm)
|
||||
val typeInfo = codegen.typeInfoValue(value.type)!!
|
||||
val arrayCreationArgs = listOf(typeInfo, kImmInt32One, finalLength!!)
|
||||
val array = currentCodeContext.genCall(context.allocArrayFunction, arrayCreationArgs, tmpVariableName)
|
||||
elements.forEachIndexed { i, it ->
|
||||
currentCodeContext.genCall(context.setArrayFunction, listOf(array, Int32(i).llvm, it), "")
|
||||
|
||||
elements.fold(kImmZero) { sum, (exp, size, isArray) ->
|
||||
if (!isArray) {
|
||||
currentCodeContext.genCall(context.setArrayFunction, listOf(array, sum, exp), "")
|
||||
return@fold codegen.plus(sum, kImmOne, codegen.newVar())
|
||||
} else {
|
||||
currentCodeContext.genCall(context.copyImplArrayFunction, listOf(exp, kImmZero, array, sum, size!!), "")
|
||||
return@fold codegen.plus(sum, size, codegen.newVar())
|
||||
}
|
||||
}
|
||||
return array
|
||||
}
|
||||
|
||||
+4
@@ -112,6 +112,10 @@ internal val ContextUtils.kObjHeaderPtr: LLVMTypeRef
|
||||
get() = pointerType(kObjHeader)
|
||||
internal val ContextUtils.kObjHeaderPtrPtr: LLVMTypeRef
|
||||
get() = pointerType(kObjHeaderPtr)
|
||||
internal val ContextUtils.kArrayHeader: LLVMTypeRef
|
||||
get() = LLVMGetTypeByName(context.llvmModule, "struct.ArrayHeader")!!
|
||||
internal val ContextUtils.kArrayHeaderPtr: LLVMTypeRef
|
||||
get() = pointerType(kArrayHeader)
|
||||
internal val ContextUtils.kTypeInfoPtr: LLVMTypeRef
|
||||
get() = pointerType(kTypeInfo)
|
||||
internal val kInt1 = LLVMInt1Type()!!
|
||||
|
||||
Reference in New Issue
Block a user