CODEGEN: implementation of global fields initialization.
This commit is contained in:
committed by
vvlevchenko
parent
bca03288f6
commit
86bb5477c5
+4
-19
@@ -18,7 +18,6 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
|||||||
|
|
||||||
val descriptor = declaration.descriptor
|
val descriptor = declaration.descriptor
|
||||||
if (currentFunction == descriptor) return
|
if (currentFunction == descriptor) return
|
||||||
variableIndex = 0
|
|
||||||
currentFunction = declaration.descriptor
|
currentFunction = declaration.descriptor
|
||||||
val fn = declaration.descriptor.llvmFunction
|
val fn = declaration.descriptor.llvmFunction
|
||||||
prologueBb = LLVMAppendBasicBlock(fn, "prologue")
|
prologueBb = LLVMAppendBasicBlock(fn, "prologue")
|
||||||
@@ -35,15 +34,6 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
|||||||
|
|
||||||
fun fields(descriptor: ClassDescriptor):List<PropertyDescriptor> = descriptor.fields
|
fun fields(descriptor: ClassDescriptor):List<PropertyDescriptor> = descriptor.fields
|
||||||
|
|
||||||
fun newVar():String = currentFunction!!.tmpVariable()
|
|
||||||
|
|
||||||
private var variableIndex:Int = 0
|
|
||||||
private var FunctionDescriptor.tmpVariableIndex: Int
|
|
||||||
get() = variableIndex
|
|
||||||
set(i:Int) { variableIndex = i}
|
|
||||||
|
|
||||||
fun FunctionDescriptor.tmpVariable():String = "tmp_${tmpVariableIndex++}"
|
|
||||||
|
|
||||||
private var prologueBb: LLVMBasicBlockRef? = null
|
private var prologueBb: LLVMBasicBlockRef? = null
|
||||||
private var entryBb: LLVMBasicBlockRef? = null
|
private var entryBb: LLVMBasicBlockRef? = null
|
||||||
|
|
||||||
@@ -143,14 +133,8 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
|||||||
fun indexInClass(p:PropertyDescriptor):Int = (p.containingDeclaration as ClassDescriptor).fields.indexOf(p)
|
fun indexInClass(p:PropertyDescriptor):Int = (p.containingDeclaration as ClassDescriptor).fields.indexOf(p)
|
||||||
|
|
||||||
|
|
||||||
fun basicBlock(name: String = "label_"): LLVMBasicBlockRef =
|
fun basicBlock(function: LLVMValueRef, name: String = "label_"): LLVMBasicBlockRef =
|
||||||
LLVMAppendBasicBlock(currentFunction!!.llvmFunction, name)!!
|
LLVMAppendBasicBlock(function, name)!!
|
||||||
|
|
||||||
fun basicBlock(name: String, code: () -> Unit) = basicBlock(name).apply {
|
|
||||||
appendingTo(this) {
|
|
||||||
code()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun lastBasicBlock(): LLVMBasicBlockRef? = LLVMGetLastBasicBlock(currentFunction!!.llvmFunction)
|
fun lastBasicBlock(): LLVMBasicBlockRef? = LLVMGetLastBasicBlock(currentFunction!!.llvmFunction)
|
||||||
|
|
||||||
@@ -192,9 +176,10 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
|||||||
inner class PositionHolder {
|
inner class PositionHolder {
|
||||||
private val builder: LLVMBuilderRef = LLVMCreateBuilder()!!
|
private val builder: LLVMBuilderRef = LLVMCreateBuilder()!!
|
||||||
|
|
||||||
|
|
||||||
fun getBuilder(): LLVMBuilderRef {
|
fun getBuilder(): LLVMBuilderRef {
|
||||||
if (isAfterTerminator) {
|
if (isAfterTerminator) {
|
||||||
positionAtEnd(basicBlock("unreachable"))
|
positionAtEnd(basicBlock(currentFunction!!.llvmFunction, "unreachable"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder
|
return builder
|
||||||
|
|||||||
+6
@@ -8,6 +8,7 @@ import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -190,6 +191,8 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
|||||||
|
|
||||||
private fun importRtFunction(name: String) = importFunction(name, runtime.llvmModule)
|
private fun importRtFunction(name: String) = importFunction(name, runtime.llvmModule)
|
||||||
|
|
||||||
|
var globalInitIndex:Int = 0
|
||||||
|
|
||||||
val allocInstanceFunction = importRtFunction("AllocInstance")
|
val allocInstanceFunction = importRtFunction("AllocInstance")
|
||||||
val initInstanceFunction = importRtFunction("InitInstance")
|
val initInstanceFunction = importRtFunction("InitInstance")
|
||||||
val allocArrayFunction = importRtFunction("AllocArrayInstance")
|
val allocArrayFunction = importRtFunction("AllocArrayInstance")
|
||||||
@@ -200,5 +203,8 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
|||||||
val isInstanceFunction = importRtFunction("IsInstance")
|
val isInstanceFunction = importRtFunction("IsInstance")
|
||||||
val checkInstanceFunction = importRtFunction("CheckInstance")
|
val checkInstanceFunction = importRtFunction("CheckInstance")
|
||||||
val throwExceptionFunction = importRtFunction("ThrowException")
|
val throwExceptionFunction = importRtFunction("ThrowException")
|
||||||
|
val appendToInitalizersTail = importRtFunction("AppendToInitializersTail")
|
||||||
val usedFunctions = mutableListOf<LLVMValueRef>()
|
val usedFunctions = mutableListOf<LLVMValueRef>()
|
||||||
|
val staticInitializers = mutableListOf<LLVMValueRef>()
|
||||||
|
val fileInitializers = mutableListOf<IrElement>()
|
||||||
}
|
}
|
||||||
|
|||||||
+170
-10
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
||||||
|
|
||||||
|
|
||||||
internal fun emitLLVM(context: Context) {
|
internal fun emitLLVM(context: Context) {
|
||||||
@@ -157,6 +158,21 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
* @return the requested value
|
* @return the requested value
|
||||||
*/
|
*/
|
||||||
fun genGetValue(descriptor: ValueDescriptor, result: String = ""): LLVMValueRef
|
fun genGetValue(descriptor: ValueDescriptor, result: String = ""): LLVMValueRef
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates name for local llvm variable.
|
||||||
|
*
|
||||||
|
* @return the requested value
|
||||||
|
*/
|
||||||
|
fun newVar():String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns owning function scope.
|
||||||
|
*
|
||||||
|
* @return the requested value
|
||||||
|
*/
|
||||||
|
fun functionScope(): CodeContext
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,7 +181,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
* During function code generation [FunctionScope] should be set up.
|
* During function code generation [FunctionScope] should be set up.
|
||||||
*/
|
*/
|
||||||
private object TopLevelCodeContext : CodeContext {
|
private object TopLevelCodeContext : CodeContext {
|
||||||
|
|
||||||
private fun unsupported(any: Any? = null): Nothing = throw UnsupportedOperationException(any?.toString() ?: "")
|
private fun unsupported(any: Any? = null): Nothing = throw UnsupportedOperationException(any?.toString() ?: "")
|
||||||
|
|
||||||
override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) = unsupported(target)
|
override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) = unsupported(target)
|
||||||
@@ -183,6 +198,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
override fun getDeclaredVariable(descriptor: VariableDescriptor) = null
|
override fun getDeclaredVariable(descriptor: VariableDescriptor) = null
|
||||||
|
|
||||||
override fun genGetValue(descriptor: ValueDescriptor, result: String) = unsupported(descriptor)
|
override fun genGetValue(descriptor: ValueDescriptor, result: String) = unsupported(descriptor)
|
||||||
|
|
||||||
|
override fun newVar(): String = unsupported()
|
||||||
|
override fun functionScope(): CodeContext = unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -219,9 +237,80 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
override fun visitModuleFragment(module: IrModuleFragment) {
|
override fun visitModuleFragment(module: IrModuleFragment) {
|
||||||
logger.log("visitModule : ${ir2string(module)}")
|
logger.log("visitModule : ${ir2string(module)}")
|
||||||
module.acceptChildrenVoid(this)
|
|
||||||
|
|
||||||
appendLlvmUsed(context.llvm.usedFunctions)
|
module.acceptChildrenVoid(this)
|
||||||
|
appendLlvmUsed(context.llvm.usedFunctions)
|
||||||
|
appendStaticInitializers(context.llvm.staticInitializers)
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
val kVoidFuncType = LLVMFunctionType(LLVMVoidType(), null, 0, 0)
|
||||||
|
val kNodeInitType = LLVMGetTypeByName(context.llvmModule, "struct.InitNode")!!
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
fun createInitBody(initName: String) {
|
||||||
|
val initFunction = LLVMAddFunction(context.llvmModule, initName, kVoidFuncType)!! // create LLVM function
|
||||||
|
using(FunctionScope(initFunction)) {
|
||||||
|
val bbEnter = LLVMAppendBasicBlock(initFunction, "label_enter")!!
|
||||||
|
codegen.positionAtEnd(bbEnter)
|
||||||
|
|
||||||
|
context.llvm.fileInitializers.forEachIndexed {
|
||||||
|
i, it ->
|
||||||
|
val irField = it as IrField
|
||||||
|
val descriptor = irField.descriptor
|
||||||
|
val initialization = evaluateExpression("\$init_var_$i", irField.initializer)
|
||||||
|
val globalPtr = LLVMGetNamedGlobal(context.llvmModule, descriptor.symbolName)
|
||||||
|
codegen.store(initialization!!, globalPtr!!)
|
||||||
|
}
|
||||||
|
codegen.ret(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
// Creates static struct InitNode $nodeName = {$initName, NULL};
|
||||||
|
|
||||||
|
fun createInitNode(initName: String, nodeName: String) {
|
||||||
|
memScoped {
|
||||||
|
val initFunction = LLVMGetNamedFunction(context.llvmModule, initName)!! // Get initialization function.
|
||||||
|
val nextInitNode = LLVMConstNull(pointerType(kNodeInitType)) // Set InitNode.next = NULL.
|
||||||
|
val argList = allocArrayOf(initFunction, nextInitNode)[0].ptr // Allocate array of args.
|
||||||
|
val initNode = LLVMConstNamedStruct(kNodeInitType, argList, 2)!! // Create static object of class InitNode.
|
||||||
|
context.llvm.staticData.placeGlobal(nodeName, constPointer(initNode)).llvmGlobal // Put the object in global var with name "nodeName".
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
fun createInitCtor(ctorName: String, nodeName: String) {
|
||||||
|
val ctorFunction = LLVMAddFunction(context.llvmModule, ctorName, kVoidFuncType)!! // Create constructor function.
|
||||||
|
val bbEnter = LLVMAppendBasicBlock(ctorFunction, "label_enter")!! // Create basic block.
|
||||||
|
|
||||||
|
codegen.positionAtEnd(bbEnter)
|
||||||
|
val initNodePtr = LLVMGetNamedGlobal(context.llvmModule, nodeName)!! // Get LLVM function initializing globals of current file.
|
||||||
|
codegen.call(context.llvm.appendToInitalizersTail, initNodePtr.singletonList(), "") // Add node to the tail of initializers list.
|
||||||
|
codegen.ret(null)
|
||||||
|
|
||||||
|
context.llvm.staticInitializers.add(ctorFunction) // Push newly created constructor in staticInitializers list.
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitFile(declaration: IrFile) {
|
||||||
|
|
||||||
|
context.llvm.fileInitializers.clear()
|
||||||
|
super.visitFile(declaration)
|
||||||
|
|
||||||
|
if (context.llvm.fileInitializers.isEmpty())
|
||||||
|
return
|
||||||
|
val fileName = declaration.name.takeLastWhile { it != '/' }.dropLastWhile { it != '.' }.dropLast(1)
|
||||||
|
val initName = "${fileName}_init_${context.llvm.globalInitIndex}"
|
||||||
|
val nodeName = "${fileName}_node_${context.llvm.globalInitIndex}"
|
||||||
|
val ctorName = "${fileName}_ctor_${context.llvm.globalInitIndex++}"
|
||||||
|
|
||||||
|
createInitBody(initName)
|
||||||
|
createInitNode(initName, nodeName)
|
||||||
|
createInitCtor(ctorName, nodeName)
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
@@ -470,10 +559,24 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
/**
|
/**
|
||||||
* The [CodeContext] enclosing the entire function body.
|
* The [CodeContext] enclosing the entire function body.
|
||||||
*/
|
*/
|
||||||
private inner class FunctionScope(val declaration: IrFunction) :
|
private inner class FunctionScope (val declaration: IrFunction?) :
|
||||||
ParameterScope(bindParameters(declaration.descriptor)) {
|
ParameterScope(bindParameters(declaration?.descriptor)) {
|
||||||
|
constructor(llvmFunction:LLVMValueRef):this(null) {
|
||||||
|
this.llvmFunction = llvmFunction
|
||||||
|
}
|
||||||
|
|
||||||
|
var llvmFunction:LLVMValueRef? = declaration?.let{
|
||||||
|
codegen.llvmFunction(declaration.descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
var tmpVariableCount = 0
|
||||||
|
override fun newVar(): String = "tmp_${tmpVariableCount++}"
|
||||||
|
|
||||||
override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) {
|
override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) {
|
||||||
|
if (declaration == null) {
|
||||||
|
codegen.ret(value)
|
||||||
|
return
|
||||||
|
}
|
||||||
if (target == declaration.descriptor) {
|
if (target == declaration.descriptor) {
|
||||||
codegen.ret(value)
|
codegen.ret(value)
|
||||||
} else {
|
} else {
|
||||||
@@ -490,12 +593,15 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
codegen.call(context.llvm.throwExceptionFunction, args, "")
|
codegen.call(context.llvm.throwExceptionFunction, args, "")
|
||||||
codegen.unreachable()
|
codegen.unreachable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun functionScope(): CodeContext = this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binds LLVM function parameters to IR parameter descriptors.
|
* Binds LLVM function parameters to IR parameter descriptors.
|
||||||
*/
|
*/
|
||||||
private fun bindParameters(descriptor: FunctionDescriptor): Map<ParameterDescriptor, LLVMValueRef> {
|
private fun bindParameters(descriptor: FunctionDescriptor?): Map<ParameterDescriptor, LLVMValueRef> {
|
||||||
|
if (descriptor == null) return emptyMap()
|
||||||
val paramDescriptors = descriptor.allValueParameters
|
val paramDescriptors = descriptor.allValueParameters
|
||||||
|
|
||||||
assert(paramDescriptors.size == codegen.countParams(descriptor))
|
assert(paramDescriptors.size == codegen.countParams(descriptor))
|
||||||
@@ -606,12 +712,14 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
val descriptor = expression.descriptor
|
val descriptor = expression.descriptor
|
||||||
if (descriptor.containingDeclaration is PackageFragmentDescriptor) {
|
if (descriptor.containingDeclaration is PackageFragmentDescriptor) {
|
||||||
val globalProperty = LLVMAddGlobal(context.llvmModule, codegen.getLLVMType(descriptor.type), descriptor.symbolName)
|
val globalProperty = LLVMAddGlobal(context.llvmModule, codegen.getLLVMType(descriptor.type), descriptor.symbolName)
|
||||||
LLVMSetInitializer(globalProperty, evaluateExpression("", expression.initializer))
|
if (expression.initializer!!.expression is IrConst<*>) {
|
||||||
|
LLVMSetInitializer(globalProperty, evaluateExpression("", expression.initializer))
|
||||||
|
} else {
|
||||||
|
LLVMSetInitializer(globalProperty, codegen.kNullObjHeaderPtr)
|
||||||
|
context.llvm.fileInitializers.add(expression)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//super.visitField(expression)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
@@ -1971,4 +2079,56 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
LLVMSetSection(llvmUsedGlobal.llvmGlobal, "llvm.metadata");
|
LLVMSetSection(llvmUsedGlobal.llvmGlobal, "llvm.metadata");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
// Create type { i32, void ()*, i8* }
|
||||||
|
|
||||||
|
val kCtorType = memScoped {
|
||||||
|
val ctorType = LLVMPointerType(kVoidFuncType, 0)
|
||||||
|
val typeList = allocArrayOf(LLVMInt32Type(), ctorType, kInt8Ptr)[0].ptr
|
||||||
|
LLVMStructType(typeList, 3, 0)
|
||||||
|
}!!
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
// Create object { i32, void ()*, i8* } { i32 1, void ()* @ctorFunction, i8* null }
|
||||||
|
|
||||||
|
fun createGlobalCtor(ctorFunction: LLVMValueRef) = memScoped {
|
||||||
|
val priority = kImmInt32One
|
||||||
|
val data = kNullInt8Ptr
|
||||||
|
val argList = allocArrayOf(priority, ctorFunction, data)[0].ptr
|
||||||
|
val ctorItem = LLVMConstNamedStruct(kCtorType, argList, 3)!!
|
||||||
|
constPointer(ctorItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
// Append initializers of global variables in "llvm.global_ctors" array
|
||||||
|
|
||||||
|
fun appendStaticInitializers(initializers: List<LLVMValueRef>) {
|
||||||
|
if (initializers.isEmpty()) return
|
||||||
|
|
||||||
|
val ctorList = initializers.map { it -> createGlobalCtor(it) }
|
||||||
|
val globalCtors = context.llvm.staticData.placeGlobalArray("llvm.global_ctors", kCtorType, ctorList)
|
||||||
|
LLVMSetLinkage(globalCtors.llvmGlobal, LLVMLinkage.LLVMAppendingLinkage)
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
/**
|
||||||
|
* This block is devoted to coming codegen refactoring:
|
||||||
|
* removing [Codegenerator.currentFunction] of [FunctionDesctiptor]
|
||||||
|
* and working with local variables with [FunctionScope] and other enhancements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fun CodeGenerator.newVar() = currentCodeContext.newVar()
|
||||||
|
|
||||||
|
fun CodeGenerator.basicBlock(name: String = "label_"): LLVMBasicBlockRef {
|
||||||
|
val functionScope:FunctionScope = currentCodeContext.functionScope() as FunctionScope
|
||||||
|
return basicBlock(functionScope.llvmFunction!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun CodeGenerator.basicBlock(name: String, code: () -> Unit) = basicBlock(name).apply {
|
||||||
|
appendingTo(this) {
|
||||||
|
code()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
@@ -123,6 +123,7 @@ internal val kInt1 = LLVMInt1Type()!!
|
|||||||
internal val kBoolean = kInt1
|
internal val kBoolean = kInt1
|
||||||
internal val kInt8Ptr = pointerType(int8Type)
|
internal val kInt8Ptr = pointerType(int8Type)
|
||||||
internal val kInt8PtrPtr = pointerType(kInt8Ptr)
|
internal val kInt8PtrPtr = pointerType(kInt8Ptr)
|
||||||
|
internal val kNullInt8Ptr = LLVMConstNull(kInt8Ptr)
|
||||||
internal val kImmInt32One = Int32(1).llvm
|
internal val kImmInt32One = Int32(1).llvm
|
||||||
internal val kImmInt64One = Int64(1).llvm
|
internal val kImmInt64One = Int64(1).llvm
|
||||||
internal val ContextUtils.kNullObjHeaderPtr: LLVMValueRef
|
internal val ContextUtils.kNullObjHeaderPtr: LLVMValueRef
|
||||||
|
|||||||
+1
@@ -1,6 +1,7 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.llvm
|
package org.jetbrains.kotlin.backend.konan.llvm
|
||||||
|
|
||||||
import llvm.*
|
import llvm.*
|
||||||
|
import org.jetbrains.kotlin.backend.konan.KonanPlatform
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||||
|
|||||||
@@ -753,6 +753,7 @@ task initializers1(type: RunKonanTest) {
|
|||||||
source = "runtime/basic/initializers1.kt"
|
source = "runtime/basic/initializers1.kt"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
task concatenation(type: RunKonanTest) {
|
task concatenation(type: RunKonanTest) {
|
||||||
goldValue = "Hello world 1 2\nHello, a\nHello, b\n"
|
goldValue = "Hello world 1 2\nHello, a\nHello, b\n"
|
||||||
source = "codegen/basics/concatenation.kt"
|
source = "codegen/basics/concatenation.kt"
|
||||||
@@ -823,3 +824,8 @@ task lambda13(type: RunKonanTest) {
|
|||||||
goldValue = "foo\n"
|
goldValue = "foo\n"
|
||||||
source = "codegen/lambda/lambda13.kt"
|
source = "codegen/lambda/lambda13.kt"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task initializers2(type: RunKonanTest) {
|
||||||
|
goldValue = "1\nA\nB\n"
|
||||||
|
source = "runtime/basic/initializers2.kt"
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,29 @@
|
|||||||
#include "Natives.h"
|
#include "Natives.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
//--- Init global variables ---------------------------------------------------//
|
||||||
|
|
||||||
|
typedef void (*Initializer)();
|
||||||
|
struct InitNode;
|
||||||
|
|
||||||
|
struct InitNode {
|
||||||
|
Initializer init;
|
||||||
|
struct InitNode* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InitNode initHeadNode;
|
||||||
|
struct InitNode* initTailNode = &initHeadNode;
|
||||||
|
|
||||||
|
void InitGlobalVariables() {
|
||||||
|
struct InitNode *currNode = initHeadNode.next;
|
||||||
|
while(currNode) {
|
||||||
|
currNode->init();
|
||||||
|
currNode = currNode->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- Setup args --------------------------------------------------------------//
|
||||||
|
|
||||||
ObjHeader* setupArgs(int argc, char** argv) {
|
ObjHeader* setupArgs(int argc, char** argv) {
|
||||||
// The count is one less, because we skip argv[0] which is the binary name.
|
// The count is one less, because we skip argv[0] which is the binary name.
|
||||||
ObjHeader* args = AllocArrayInstance(theArrayTypeInfo, SCOPE_GLOBAL, argc-1);
|
ObjHeader* args = AllocArrayInstance(theArrayTypeInfo, SCOPE_GLOBAL, argc-1);
|
||||||
@@ -15,13 +38,17 @@ ObjHeader* setupArgs(int argc, char** argv) {
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--- main --------------------------------------------------------------------//
|
||||||
|
|
||||||
extern "C" void Konan_start(ObjHeader* );
|
extern "C" void Konan_start(ObjHeader* );
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
InitMemory();
|
InitMemory();
|
||||||
|
InitGlobalVariables();
|
||||||
|
|
||||||
ObjHeader* args = setupArgs(argc, argv);
|
ObjHeader* args = setupArgs(argc, argv);
|
||||||
|
|
||||||
Konan_start(args);
|
Konan_start(args);
|
||||||
|
|
||||||
// Yes, we have to follow Java convention and return zero.
|
// Yes, we have to follow Java convention and return zero.
|
||||||
|
|||||||
Reference in New Issue
Block a user