backend: partially port code to new interop

This commit is contained in:
Svyatoslav Scherbina
2016-11-22 12:52:21 +07:00
parent f0df5f9435
commit 8a486d7fae
12 changed files with 91 additions and 91 deletions
@@ -1,7 +1,7 @@
package org.jetbrains.kotlin.backend.konan.llvm
import kotlin_native.interop.*
import kotlin_.cinterop.*
import llvm.*
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
@@ -118,9 +118,8 @@ internal class CodeGenerator(override val context:Context) : ContextUtils {
fun call(llvmFunction: LLVMOpaqueValue?, args: List<LLVMOpaqueValue?>, result: String?): LLVMOpaqueValue? {
if (args.size == 0) return LLVMBuildCall(context.llvmBuilder, llvmFunction, null, 0, result)
memScoped {
val rargs = alloc(array[args.size](Ref to LLVMOpaqueValue))
args.forEachIndexed { i, llvmOpaqueValue -> rargs[i].value = args[i] }
return LLVMBuildCall(context.llvmBuilder, llvmFunction, rargs[0], args.size, result)
val rargs = allocArrayOf(args)
return LLVMBuildCall(context.llvmBuilder, llvmFunction, rargs[0].ptr, args.size, result)
}
}
@@ -4,12 +4,12 @@ import llvm.*
import org.jetbrains.kotlin.backend.konan.ModuleIndex
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
internal class Context(val irModule: IrModuleFragment, val runtime: Runtime, val llvmModule: LLVMOpaqueModule) {
internal class Context(val irModule: IrModuleFragment, val runtime: Runtime, val llvmModule: LLVMModuleRef) {
val moduleIndex = ModuleIndex(irModule)
val llvmBuilder = LLVMCreateBuilder()
private fun importFunction(name: String, otherModule: LLVMOpaqueModule): LLVMOpaqueValue {
private fun importFunction(name: String, otherModule: LLVMModuleRef): LLVMValueRef {
if (LLVMGetNamedFunction(llvmModule, name) != null) {
throw IllegalArgumentException("function $name already exists")
}
@@ -1,6 +1,6 @@
package org.jetbrains.kotlin.backend.konan.llvm
import kotlin_native.interop.*
import kotlin_.cinterop.*
import llvm.*
import org.jetbrains.kotlin.backend.konan.hash.GlobalHash
import org.jetbrains.kotlin.descriptors.ClassDescriptor
@@ -22,7 +22,7 @@ internal interface ContextUtils {
val runtime: Runtime
get() = context.runtime
val llvmTargetData: LLVMOpaqueTargetData
val llvmTargetData: LLVMTargetDataRef
get() = runtime.targetData
val staticData: StaticData
@@ -4,7 +4,7 @@ import llvm.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.types.KotlinType
internal fun getLLVMType(type: KotlinType): LLVMOpaqueType {
internal fun getLLVMType(type: KotlinType): LLVMTypeRef {
return when {
KotlinBuiltIns.isBoolean(type) -> LLVMInt1Type()
KotlinBuiltIns.isByte(type) -> LLVMInt8Type()
@@ -1,22 +1,22 @@
package org.jetbrains.kotlin.backend.konan.llvm
import kotlin_native.interop.*
import kotlin_.cinterop.*
import org.jetbrains.kotlin.backend.konan.hash.*
internal fun localHash(data: ByteArray): Long {
memScoped {
val hashBox = alloc(Int64Box)
val bytes = allocNativeArrayOf(data)
MakeLocalHash(bytes.ptr, data.size, hashBox)
return hashBox.value
val res = alloc<LocalHashVar>()
val bytes = allocArrayOf(data)
MakeLocalHash(bytes[0].ptr, data.size, res.ptr)
return res.value
}
}
internal fun globalHash(data: ByteArray, retValPlacement: Placement): GlobalHash {
val res = retValPlacement.alloc(GlobalHash)
internal fun globalHash(data: ByteArray, retValPlacement: NativePlacement): GlobalHash {
val res = retValPlacement.alloc<GlobalHash>()
memScoped {
val bytes = allocNativeArrayOf(data)
MakeGlobalHash(bytes.ptr, data.size, res)
val bytes = allocArrayOf(data)
MakeGlobalHash(bytes[0].ptr, data.size, res.ptr)
}
return res
}
@@ -24,8 +24,8 @@ internal fun globalHash(data: ByteArray, retValPlacement: Placement): GlobalHash
internal fun base64Encode(data: ByteArray): String {
memScoped {
val resultSize = 4 * data.size / 3 + 3 + 1
val result = alloc(NativeArray of Int8Box length resultSize)
val bytes = allocNativeArrayOf(data)
val result = allocArray<CInt8Var>(resultSize)
val bytes = allocArrayOf(data)
Base64Encode(bytes.ptr, data.size, result.ptr, resultSize)
// TODO: any better way to do that without two copies?
return CString.fromArray(result).toString()
@@ -1,6 +1,6 @@
package org.jetbrains.kotlin.backend.konan.llvm
import kotlin_native.interop.*
import kotlin_.cinterop.*
import llvm.*
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
@@ -36,10 +36,10 @@ fun emitLLVM(module: IrModuleFragment, runtimeFile: String, outFile: String) {
println("\n--- Generate bitcode ------------------------------------------------------\n")
module.acceptVoid(CodeGeneratorVisitor(context))
memScoped {
val errorRef = alloc(Int8Box.ref)
val errorRef = allocPointerTo<CInt8Var>()
// TODO: use LLVMDisposeMessage() on errorRef, once possible in interop.
if (LLVMVerifyModule(
llvmModule, LLVMVerifierFailureAction.LLVMPrintMessageAction, errorRef) == 1) {
llvmModule, LLVMVerifierFailureAction.LLVMPrintMessageAction, errorRef.ptr) == 1) {
LLVMDumpModule(llvmModule)
throw Error("Invalid module");
}
@@ -532,8 +532,8 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val objHeaderPtr = codegen.bitcast(kObjHeaderPtr, thisPtr, codegen.newVar())
val typePtr = pointerType(codegen.classType(value.containingDeclaration as ClassDescriptor))
memScoped {
val args = allocNativeArrayOf(LLVMOpaqueValue, kImmOne)
val objectPtr = LLVMBuildGEP(codegen.context.llvmBuilder, objHeaderPtr, args[0], 1, codegen.newVar())
val args = allocArrayOf(kImmOne)
val objectPtr = LLVMBuildGEP(codegen.context.llvmBuilder, objHeaderPtr, args[0].ptr, 1, codegen.newVar())
val typedObjPtr = codegen.bitcast(typePtr, objectPtr!!, codegen.newVar())
val fieldPtr = LLVMBuildStructGEP(codegen.context.llvmBuilder, typedObjPtr, codegen.indexInClass(value), codegen.newVar())
return fieldPtr
@@ -1,6 +1,6 @@
package org.jetbrains.kotlin.backend.konan.llvm
import kotlin_native.interop.*
import kotlin_.cinterop.*
import llvm.*
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -11,9 +11,9 @@ import org.jetbrains.kotlin.utils.singletonOrEmptyList
*/
internal interface ConstValue {
fun getLlvmValue(): LLVMOpaqueValue?
fun getLlvmValue(): LLVMValueRef?
fun getLlvmType(): LLVMOpaqueType {
fun getLlvmType(): LLVMTypeRef {
return LLVMTypeOf(getLlvmValue())!!
}
@@ -23,45 +23,45 @@ internal interface ConstPointer : ConstValue {
fun getElementPtr(index: Int): ConstPointer = ConstGetElementPtr(this, index)
}
internal fun constPointer(value: LLVMOpaqueValue?) = object : ConstPointer {
internal fun constPointer(value: LLVMValueRef?) = object : ConstPointer {
override fun getLlvmValue() = value
}
private class ConstGetElementPtr(val pointer: ConstPointer, val index: Int) : ConstPointer {
override fun getLlvmValue(): LLVMOpaqueValue? {
override fun getLlvmValue(): LLVMValueRef? {
// TODO: probably it should be computed once when initialized?
// TODO: squash multiple GEPs
val indices = intArrayOf(0, index).map { Int32(it).getLlvmValue() }
memScoped {
val indicesArray = allocNativeArrayOf(LLVMOpaqueValue, indices)
return LLVMConstInBoundsGEP(pointer.getLlvmValue(), indicesArray[0], indices.size)
val indicesArray = allocArrayOf(indices)
return LLVMConstInBoundsGEP(pointer.getLlvmValue(), indicesArray[0].ptr, indices.size)
}
}
}
internal fun ConstPointer.bitcast(toType: LLVMOpaqueType) = constPointer(LLVMConstBitCast(this.getLlvmValue(), toType))
internal fun ConstPointer.bitcast(toType: LLVMTypeRef) = constPointer(LLVMConstBitCast(this.getLlvmValue(), toType))
internal class ConstArray(val elemType: LLVMOpaqueType?, val elements: List<ConstValue>) : ConstValue {
internal class ConstArray(val elemType: LLVMTypeRef?, val elements: List<ConstValue>) : ConstValue {
override fun getLlvmValue(): LLVMOpaqueValue? {
override fun getLlvmValue(): LLVMValueRef? {
val values = elements.map { it.getLlvmValue() }.toTypedArray()
memScoped {
val valuesNativeArrayPtr = allocNativeArrayOf(LLVMOpaqueValue, *values)[0]
val valuesNativeArrayPtr = allocArrayOf(*values)[0].ptr
return LLVMConstArray(elemType, valuesNativeArrayPtr, values.size)
}
}
}
internal open class Struct(val type: LLVMOpaqueType?, val elements: List<ConstValue>) : ConstValue {
internal open class Struct(val type: LLVMTypeRef?, val elements: List<ConstValue>) : ConstValue {
constructor(type: LLVMOpaqueType?, vararg elements: ConstValue) : this(type, elements.toList())
constructor(type: LLVMTypeRef?, vararg elements: ConstValue) : this(type, elements.toList())
override fun getLlvmValue(): LLVMOpaqueValue? {
override fun getLlvmValue(): LLVMValueRef? {
val values = elements.map { it.getLlvmValue() }.toTypedArray()
memScoped {
val valuesNativeArrayPtr = allocNativeArrayOf(LLVMOpaqueValue, *values)[0]
val valuesNativeArrayPtr = allocArrayOf(*values)[0].ptr
return LLVMConstNamedStruct(type, valuesNativeArrayPtr, values.size)
}
}
@@ -79,43 +79,43 @@ internal class Int64(val value: Long) : ConstValue {
override fun getLlvmValue() = LLVMConstInt(LLVMInt64Type(), value, 1)
}
internal class Zero(val type: LLVMOpaqueType?) : ConstValue {
internal class Zero(val type: LLVMTypeRef?) : ConstValue {
override fun getLlvmValue() = LLVMConstNull(type)
}
internal class NullPointer(val pointeeType: LLVMOpaqueType?): ConstPointer {
internal class NullPointer(val pointeeType: LLVMTypeRef?): ConstPointer {
override fun getLlvmValue() = LLVMConstNull(pointerType(pointeeType))
}
internal fun constValue(value: LLVMOpaqueValue?) = object : ConstValue {
internal fun constValue(value: LLVMValueRef?) = object : ConstValue {
override fun getLlvmValue() = value
}
internal val int8Type = LLVMInt8Type()
internal val int32Type = LLVMInt32Type()
internal fun pointerType(pointeeType: LLVMOpaqueType?) = LLVMPointerType(pointeeType, 0)
internal fun pointerType(pointeeType: LLVMTypeRef?) = LLVMPointerType(pointeeType, 0)
internal fun structType(vararg types: LLVMOpaqueType?): LLVMOpaqueType = memScoped {
LLVMStructType(allocNativeArrayOf(LLVMOpaqueType, *types)[0], types.size, 0)!!
internal fun structType(vararg types: LLVMTypeRef?): LLVMTypeRef = memScoped {
LLVMStructType(allocArrayOf(*types)[0].ptr, types.size, 0)!!
}
internal fun getLlvmFunctionType(function: FunctionDescriptor): LLVMOpaqueType? {
internal fun getLlvmFunctionType(function: FunctionDescriptor): LLVMTypeRef? {
val returnType = getLLVMType(function.returnType!!)
val params = function.dispatchReceiverParameter.singletonOrEmptyList() +
function.extensionReceiverParameter.singletonOrEmptyList() +
function.valueParameters
var extraParam = listOf<LLVMOpaqueType?>()
var extraParam = listOf<LLVMTypeRef?>()
if (function is ClassConstructorDescriptor) {
extraParam += pointerType(LLVMInt8Type())
}
val paramTypes:List<LLVMOpaqueType?> = params.map { getLLVMType(it.type) }
val paramTypes:List<LLVMTypeRef?> = params.map { getLLVMType(it.type) }
extraParam += paramTypes
if (extraParam.size == 0) return LLVMFunctionType(returnType, null, 0, 0)
memScoped {
val paramTypesPtr = allocNativeArrayOf(LLVMOpaqueType, *extraParam.toTypedArray())[0] // TODO: dispose
val paramTypesPtr = allocArrayOf(extraParam)[0].ptr
return LLVMFunctionType(returnType, paramTypesPtr, extraParam.size, 0)
}
}
@@ -123,10 +123,10 @@ internal fun getLlvmFunctionType(function: FunctionDescriptor): LLVMOpaqueType?
/**
* Reads [size] bytes contained in this array.
*/
internal fun NativeArray<Int8Box>.getBytes(size: Int) =
internal fun CArray<CInt8Var>.getBytes(size: Long) =
(0 .. size-1).map { this[it].value }.toByteArray()
internal fun getFunctionType(ptrToFunction: LLVMOpaqueValue?): LLVMOpaqueType {
internal fun getFunctionType(ptrToFunction: LLVMValueRef?): LLVMTypeRef {
val typeOfPtrToFunction = LLVMTypeOf(ptrToFunction)
return LLVMGetElementType(typeOfPtrToFunction)!!
}
@@ -1,11 +1,7 @@
package org.jetbrains.kotlin.backend.konan.llvm
import kotlin_native.interop.asCString
import llvm.LLVMPrintModuleToString
import llvm.LLVMPrintValueToString
import llvm.LLVMOpaqueValue
import org.jetbrains.kotlin.backend.konan.llvm.Context
import org.jetbrains.kotlin.backend.konan.llvm.ContextUtils
import kotlin_.cinterop.*
import llvm.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
import java.io.StringWriter
@@ -1,7 +1,7 @@
package org.jetbrains.kotlin.backend.konan.llvm
import kotlin_native.interop.*
import kotlin_.cinterop.*
import llvm.*
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
@@ -33,21 +33,21 @@ fun readModuleMetadata(file: File): String {
class MetadataReader(file: File) {
lateinit var llvmModule: LLVMOpaqueModule
lateinit var llvmContext: LLVMOpaqueContext
lateinit var llvmModule: LLVMModuleRef
lateinit var llvmContext: LLVMContextRef
init {
memScoped {
val bufRef = alloc(LLVMOpaqueMemoryBuffer.ref)
val errorRef = alloc(Int8Box.ref)
val res = LLVMCreateMemoryBufferWithContentsOfFile(file.toString(), bufRef, errorRef)
val bufRef = alloc<LLVMMemoryBufferRefVar>()
val errorRef = allocPointerTo<CInt8Var>()
val res = LLVMCreateMemoryBufferWithContentsOfFile(file.toString(), bufRef.ptr, errorRef.ptr)
if (res != 0) {
throw Error(errorRef.value?.asCString()?.toString())
}
llvmContext = LLVMContextCreate()!!
val moduleRef = alloc(LLVMOpaqueModule.ref)
val parseResult = LLVMParseBitcodeInContext2(llvmContext, bufRef.value, moduleRef)
val moduleRef = alloc<LLVMModuleRefVar>()
val parseResult = LLVMParseBitcodeInContext2(llvmContext, bufRef.value, moduleRef.ptr)
if (parseResult != 0) {
throw Error(parseResult.toString())
}
@@ -59,8 +59,8 @@ class MetadataReader(file: File) {
fun string(node: LLVMOpaqueValue): String {
memScoped {
val len = alloc(Int32Box)
val str1 = LLVMGetMDString(node, len)!!
val len = alloc<CInt32Var>()
val str1 = LLVMGetMDString(node, len.ptr)!!
val str = str1.asCString().toString()
return str
@@ -70,9 +70,9 @@ class MetadataReader(file: File) {
fun namedMetadataNode(name: String, index: Int): LLVMOpaqueValue {
memScoped {
val nodeCount = LLVMGetNamedMetadataNumOperands(llvmModule, "kmetadata")!!
val nodeArray = alloc(array[nodeCount](Ref to LLVMOpaqueValue))
val nodeArray = allocArray<LLVMValueRefVar>(nodeCount)
LLVMGetNamedMetadataOperands(llvmModule, "kmetadata", nodeArray[0])!!
LLVMGetNamedMetadataOperands(llvmModule, "kmetadata", nodeArray[0].ptr)!!
return nodeArray[0].value!!
}
@@ -81,9 +81,9 @@ class MetadataReader(file: File) {
fun metadataOperand(metadataNode: LLVMOpaqueValue, index: Int): LLVMOpaqueValue {
memScoped {
val operandCount = LLVMGetMDNodeNumOperands(metadataNode)!!
val operandArray = alloc(array[operandCount](Ref to LLVMOpaqueValue))
val operandArray = allocArray<LLVMValueRefVar>(operandCount)
LLVMGetMDNodeOperands(metadataNode, operandArray[0])!!
LLVMGetMDNodeOperands(metadataNode, operandArray[0].ptr)!!
return operandArray[0].value!!
}
@@ -104,9 +104,8 @@ internal class MetadataGenerator(override val context: Context): ContextUtils {
private fun metadataNode(args: List<LLVMOpaqueValue?>): LLVMOpaqueValue {
memScoped {
val references = alloc(array[args.size](Ref to LLVMOpaqueValue))
args.forEachIndexed { i, llvmOpaqueValue -> references[i].value = args[i]}
return LLVMMDNode(references[0], args.size)!!
val references = allocArrayOf(args)
return LLVMMDNode(references[0].ptr, args.size)!!
}
}
@@ -1,8 +1,7 @@
package org.jetbrains.kotlin.backend.konan.llvm
import kotlin_native.interop.allocNativeArrayOf
import kotlin_native.interop.memScoped
import kotlin_.cinterop.*
import llvm.*
import org.jetbrains.kotlin.backend.konan.implementation
import org.jetbrains.kotlin.backend.konan.implementedInterfaces
@@ -66,7 +65,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
memScoped {
val fieldTypesNativeArrayPtr = if (fieldTypes.size > 0) {
allocNativeArrayOf(LLVMOpaqueType, *fieldTypes)[0]
allocArrayOf(*fieldTypes)[0].ptr
} else {
null
}
@@ -1,32 +1,28 @@
package org.jetbrains.kotlin.backend.konan.llvm
import kotlin_native.interop.*
import kotlin_.cinterop.*
import llvm.*
class Runtime(private val bitcodeFile: String) {
val llvmModule: LLVMOpaqueModule
val llvmModule: LLVMModuleRef
init {
val arena = Arena()
try {
llvmModule = memScoped {
val bufRef = arena.alloc(LLVMOpaqueMemoryBuffer.ref)
val errorRef = arena.alloc(Int8Box.ref)
val res = LLVMCreateMemoryBufferWithContentsOfFile(bitcodeFile, bufRef, errorRef)
val bufRef = allocPointerTo<LLVMOpaqueMemoryBuffer>()
val errorRef = allocPointerTo<CInt8Var>()
val res = LLVMCreateMemoryBufferWithContentsOfFile(bitcodeFile, bufRef.ptr, errorRef.ptr)
if (res != 0) {
throw Error(errorRef.value?.asCString()?.toString())
}
val moduleRef = arena.alloc(LLVMOpaqueModule.ref)
val parseRes = LLVMParseBitcode2(bufRef.value, moduleRef)
val moduleRef = alloc<LLVMModuleRefVar>()
val parseRes = LLVMParseBitcode2(bufRef.value, moduleRef.ptr)
if (parseRes != 0) {
throw Error(parseRes.toString())
}
llvmModule = moduleRef.value!!
} finally {
arena.clear()
moduleRef.value!!
}
}
@@ -0,0 +1,11 @@
package org.jetbrains.kotlin.backend.konan.llvm
import kotlin_.cinterop.CPointer
import kotlin_.cinterop.CPointerVarWithValueMappedTo
// TODO: the definitions below are required to perform smooth migration to new interop;
// remove after replacing with LLVM*Ref typedefs
typealias LLVMOpaqueValue = CPointer<llvm.LLVMOpaqueValue>
typealias LLVMOpaqueType = CPointer<llvm.LLVMOpaqueType>
typealias LLVMOpaqueBasicBlock = CPointer<llvm.LLVMOpaqueBasicBlock>