[KLIB] Implement special encoding for Klib data
This commit is contained in:
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.serialization.encodings
|
||||
|
||||
inline class BinaryCoordinates(private val decoded: BinaryLattice) {
|
||||
private fun diff(): Int = decoded.second
|
||||
|
||||
val startOffset: Int get() = decoded.first
|
||||
val endOffset: Int get() = startOffset + diff()
|
||||
|
||||
companion object {
|
||||
fun encode(startOffset: Int, endOffset: Int): Long {
|
||||
assert(startOffset <= endOffset)
|
||||
return BinaryLattice.encode(startOffset, endOffset - startOffset)
|
||||
}
|
||||
|
||||
fun decode(code: Long) = BinaryCoordinates(BinaryLattice.decode(code)).also { assert(it.startOffset <= it.endOffset) }
|
||||
}
|
||||
}
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.serialization.encodings
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
inline class ClassFlags(val flags: Long) {
|
||||
|
||||
val modality: Modality get() = ProtoEnumFlags.modality(Flags.MODALITY.get(flags.toInt()))
|
||||
val visibility: Visibility get() = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags.toInt()))
|
||||
val kind: ClassKind get() = ProtoEnumFlags.classKind(Flags.CLASS_KIND.get(flags.toInt()))
|
||||
|
||||
val isCompanion: Boolean get() = Flags.CLASS_KIND.get(flags.toInt()) == ProtoBuf.Class.Kind.COMPANION_OBJECT
|
||||
val isInner: Boolean get() = Flags.IS_INNER.get(flags.toInt())
|
||||
val isData: Boolean get() = Flags.IS_DATA.get(flags.toInt())
|
||||
val isInline: Boolean get() = Flags.IS_INLINE_CLASS.get(flags.toInt())
|
||||
val isExpect: Boolean get() = Flags.IS_EXPECT_CLASS.get(flags.toInt())
|
||||
val isExternal: Boolean get() = Flags.IS_EXTERNAL_CLASS.get(flags.toInt())
|
||||
val isFun: Boolean get() = Flags.IS_FUN_INTERFACE.get(flags.toInt())
|
||||
|
||||
companion object {
|
||||
fun encode(clazz: IrClass): Long {
|
||||
return clazz.run {
|
||||
val hasAnnotation = annotations.isNotEmpty()
|
||||
val visibility = ProtoEnumFlags.visibility(visibility)
|
||||
val modality = ProtoEnumFlags.modality(modality)
|
||||
val kind = ProtoEnumFlags.classKind(kind, isCompanion)
|
||||
|
||||
val flags =
|
||||
Flags.getClassFlags(hasAnnotation, visibility, modality, kind, isInner, isData, isExternal, isExpect, isInline, isFun)
|
||||
|
||||
flags.toLong()
|
||||
}
|
||||
}
|
||||
|
||||
fun decode(code: Long) = ClassFlags(code)
|
||||
}
|
||||
}
|
||||
|
||||
inline class FunctionFlags(val flags: Long) {
|
||||
|
||||
val modality: Modality get() = ProtoEnumFlags.modality(Flags.MODALITY.get(flags.toInt()))
|
||||
val visibility: Visibility get() = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags.toInt()))
|
||||
|
||||
val isOperator: Boolean get() = Flags.IS_OPERATOR.get(flags.toInt())
|
||||
val isInline: Boolean get() = Flags.IS_INLINE.get(flags.toInt())
|
||||
val isTailrec: Boolean get() = Flags.IS_TAILREC.get(flags.toInt())
|
||||
val isExternal: Boolean get() = Flags.IS_EXTERNAL_FUNCTION.get(flags.toInt())
|
||||
val isSuspend: Boolean get() = Flags.IS_SUSPEND.get(flags.toInt())
|
||||
val isExpect: Boolean get() = Flags.IS_EXPECT_FUNCTION.get(flags.toInt())
|
||||
val isFakeOverride: Boolean get() = kind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE
|
||||
|
||||
val isPrimary: Boolean get() = Flags.IS_PRIMARY.get(flags.toInt())
|
||||
|
||||
private fun kind(): CallableMemberDescriptor.Kind = ProtoEnumFlags.memberKind(Flags.MEMBER_KIND.get(flags.toInt()))
|
||||
|
||||
companion object {
|
||||
fun encode(function: IrSimpleFunction): Long {
|
||||
function.run {
|
||||
val hasAnnotation = annotations.isNotEmpty()
|
||||
val visibility = ProtoEnumFlags.visibility(visibility)
|
||||
val modality = ProtoEnumFlags.modality(modality)
|
||||
val kind = if (isFakeOverride) ProtoBuf.MemberKind.FAKE_OVERRIDE else ProtoBuf.MemberKind.DECLARATION
|
||||
|
||||
|
||||
val flags = Flags.getFunctionFlags(
|
||||
hasAnnotation, visibility, modality, kind,
|
||||
isOperator, false, isInline, isTailrec, isExternal, isSuspend, isExpect
|
||||
)
|
||||
|
||||
return flags.toLong()
|
||||
}
|
||||
}
|
||||
|
||||
fun encode(constructor: IrConstructor): Long {
|
||||
constructor.run {
|
||||
val hasAnnotation = annotations.isNotEmpty()
|
||||
val visibility = ProtoEnumFlags.visibility(visibility)
|
||||
val flags = Flags.getConstructorFlags(hasAnnotation, visibility, isInline, isExternal, isExpect, isPrimary)
|
||||
|
||||
return flags.toLong()
|
||||
}
|
||||
}
|
||||
|
||||
fun decode(code: Long) = FunctionFlags(code)
|
||||
}
|
||||
}
|
||||
|
||||
inline class PropertyFlags(val flags: Long) {
|
||||
|
||||
val modality: Modality get() = ProtoEnumFlags.modality(Flags.MODALITY.get(flags.toInt()))
|
||||
val visibility: Visibility get() = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags.toInt()))
|
||||
|
||||
val isVar: Boolean get() = Flags.IS_VAR.get(flags.toInt())
|
||||
val isConst: Boolean get() = Flags.IS_CONST.get(flags.toInt())
|
||||
val isLateinit: Boolean get() = Flags.IS_LATEINIT.get(flags.toInt())
|
||||
val isExternal: Boolean get() = Flags.IS_EXTERNAL_PROPERTY.get(flags.toInt())
|
||||
val isDelegated: Boolean get() = Flags.IS_DELEGATED.get(flags.toInt())
|
||||
val isExpect: Boolean get() = Flags.IS_EXPECT_PROPERTY.get(flags.toInt())
|
||||
val isFakeOverride: Boolean get() = kind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE
|
||||
|
||||
private fun kind(): CallableMemberDescriptor.Kind = ProtoEnumFlags.memberKind(Flags.MEMBER_KIND.get(flags.toInt()))
|
||||
|
||||
companion object {
|
||||
fun encode(property: IrProperty): Long {
|
||||
return property.run {
|
||||
val hasAnnotation = annotations.isNotEmpty()
|
||||
val visibility = ProtoEnumFlags.visibility(visibility)
|
||||
val modality = ProtoEnumFlags.modality(modality)
|
||||
val kind = if (isFakeOverride) ProtoBuf.MemberKind.FAKE_OVERRIDE else ProtoBuf.MemberKind.DECLARATION
|
||||
val hasGetter = getter != null
|
||||
val hasSetter = setter != null
|
||||
|
||||
val flags = Flags.getPropertyFlags(
|
||||
hasAnnotation, visibility, modality, kind,
|
||||
isVar, hasGetter, hasSetter, false, isConst, isLateinit, isExternal, isDelegated, isExpect
|
||||
)
|
||||
|
||||
flags.toLong()
|
||||
}
|
||||
}
|
||||
|
||||
fun decode(code: Long) = PropertyFlags(code)
|
||||
}
|
||||
}
|
||||
|
||||
inline class ValueParameterFlags(val flags: Long) {
|
||||
|
||||
val isCrossInline: Boolean get() = Flags.IS_CROSSINLINE.get(flags.toInt())
|
||||
val isNoInline: Boolean get() = Flags.IS_NOINLINE.get(flags.toInt())
|
||||
|
||||
companion object {
|
||||
fun encode(param: IrValueParameter): Long {
|
||||
return param.run {
|
||||
Flags.getValueParameterFlags(annotations.isNotEmpty(), defaultValue != null, isCrossinline, isNoinline).toLong()
|
||||
}
|
||||
}
|
||||
|
||||
fun decode(code: Long) = ValueParameterFlags(code)
|
||||
}
|
||||
}
|
||||
|
||||
inline class TypeAliasFlags(val flags: Long) {
|
||||
|
||||
val visibility: Visibility get() = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags.toInt()))
|
||||
val isActual: Boolean get() = Flags.IS_ACTUAL.get(flags.toInt())
|
||||
|
||||
companion object {
|
||||
fun encode(typeAlias: IrTypeAlias): Long {
|
||||
return typeAlias.run {
|
||||
val visibility = ProtoEnumFlags.visibility(visibility)
|
||||
Flags.getTypeAliasFlags(annotations.isNotEmpty(), visibility, isActual).toLong()
|
||||
}
|
||||
}
|
||||
|
||||
fun decode(code: Long) = TypeAliasFlags(code)
|
||||
}
|
||||
}
|
||||
|
||||
inline class TypeParameterFlags(val flags: Long) {
|
||||
|
||||
val variance: Variance get() = ProtoEnumFlags.variance(Flags.VARIANCE.get(flags.toInt()))
|
||||
val isReified: Boolean get() = Flags.IS_REIFIED.get(flags.toInt())
|
||||
|
||||
companion object {
|
||||
fun encode(typeParameter: IrTypeParameter): Long {
|
||||
return typeParameter.run {
|
||||
val variance = ProtoEnumFlags.variance(variance)
|
||||
Flags.getTypeParameterFlags(annotations.isNotEmpty(), variance, isReified).toLong()
|
||||
}
|
||||
}
|
||||
|
||||
fun decode(code: Long) = TypeParameterFlags(code)
|
||||
}
|
||||
}
|
||||
|
||||
inline class FieldFlags(val flags: Long) {
|
||||
|
||||
val visibility: Visibility get() = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags.toInt()))
|
||||
val isFinal: Boolean get() = Flags.IS_FINAL.get(flags.toInt())
|
||||
val isExternal: Boolean get() = Flags.IS_EXTERNAL_FIELD.get(flags.toInt())
|
||||
val isStatic: Boolean get() = Flags.IS_STATIC.get(flags.toInt())
|
||||
val isFakeOverride: Boolean get() = Flags.IS_FAKE_OVERRIDE.get(flags.toInt())
|
||||
|
||||
companion object {
|
||||
fun encode(field: IrField): Long {
|
||||
return field.run {
|
||||
val visibility = ProtoEnumFlags.visibility(visibility)
|
||||
Flags.getFieldFlags(annotations.isNotEmpty(), visibility, isFinal, isExternal, isStatic, isFakeOverride).toLong()
|
||||
}
|
||||
}
|
||||
|
||||
fun decode(code: Long) = FieldFlags(code)
|
||||
}
|
||||
}
|
||||
|
||||
inline class LocalVariableFlags(val flags: Long) {
|
||||
|
||||
val isVar: Boolean get() = Flags.IS_LOCAL_VAR.get(flags.toInt())
|
||||
val isConst: Boolean get() = Flags.IS_LOCAL_CONST.get(flags.toInt())
|
||||
val isLateinit: Boolean get() = Flags.IS_LOCAL_LATEINIT.get(flags.toInt())
|
||||
|
||||
companion object {
|
||||
fun encode(variable: IrVariable): Long {
|
||||
return variable.run {
|
||||
Flags.getLocalFlags(annotations.isNotEmpty(), isVar, isConst, isLateinit).toLong()
|
||||
}
|
||||
}
|
||||
|
||||
fun encode(delegate: IrLocalDelegatedProperty): Long {
|
||||
return delegate.run {
|
||||
Flags.getLocalFlags(annotations.isNotEmpty(), isVar, false, false).toLong()
|
||||
}
|
||||
}
|
||||
|
||||
fun decode(code: Long) = LocalVariableFlags(code)
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.serialization.encodings
|
||||
|
||||
inline class BinaryLattice(private val code: Long) {
|
||||
|
||||
val first: Int get() = decodeInt(code)
|
||||
val second: Int get() = decodeInt(code ushr 1)
|
||||
|
||||
companion object {
|
||||
|
||||
private fun interleaveBits(input: Int): Long {
|
||||
var word = input.toLong() and 0x0FFFFFFFFL
|
||||
word = word xor (word shl 16) and 0x0000ffff0000ffffL
|
||||
word = word xor (word shl 8) and 0x00ff00ff00ff00ffL
|
||||
word = word xor (word shl 4) and 0x0f0f0f0f0f0f0f0fL
|
||||
word = word xor (word shl 2) and 0x3333333333333333L
|
||||
word = word xor (word shl 1) and 0x5555555555555555L
|
||||
return word
|
||||
}
|
||||
|
||||
private fun decodeInt(xx: Long): Int {
|
||||
var x = xx
|
||||
x = x and 0x5555555555555555L
|
||||
x = x xor (x shr 1) and 0x3333333333333333L
|
||||
x = x xor (x shr 2) and 0x0f0f0f0f0f0f0f0fL
|
||||
x = x xor (x shr 4) and 0x00ff00ff00ff00ffL
|
||||
x = x xor (x shr 8) and 0x0000ffff0000ffffL
|
||||
x = x xor (x shr 16) and 0x00000000FFFFFFFFL
|
||||
return x.toInt()
|
||||
}
|
||||
|
||||
fun encode(f: Int, s: Int): Long {
|
||||
return interleaveBits(f) or (interleaveBits(s) shl 1)
|
||||
}
|
||||
|
||||
fun decode(code: Long) = BinaryLattice(code)
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.serialization.encodings
|
||||
|
||||
inline class BinaryNameAndType(private val decoded: BinaryLattice) {
|
||||
val nameIndex: Int get() = decoded.first
|
||||
val typeIndex: Int get() = decoded.second
|
||||
|
||||
companion object {
|
||||
fun encode(nameIndex: Int, typeIndex: Int): Long = BinaryLattice.encode(nameIndex, typeIndex)
|
||||
fun decode(code: Long) = BinaryNameAndType(BinaryLattice.decode(code))
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.serialization.encodings
|
||||
|
||||
inline class BinarySymbolData(val code: Long) {
|
||||
enum class SymbolKind {
|
||||
FUNCTION_SYMBOL,
|
||||
CONSTRUCTOR_SYMBOL,
|
||||
ENUM_ENTRY_SYMBOL,
|
||||
FIELD_SYMBOL,
|
||||
VALUE_PARAMETER_SYMBOL,
|
||||
RETURNABLE_BLOCK_SYMBOL,
|
||||
CLASS_SYMBOL,
|
||||
TYPE_PARAMETER_SYMBOL,
|
||||
VARIABLE_SYMBOL,
|
||||
ANONYMOUS_INIT_SYMBOL,
|
||||
STANDALONE_FIELD_SYMBOL, // For fields without properties. WrappedFieldDescriptor, rather than WrappedPropertyDescriptor.
|
||||
RECEIVER_PARAMETER_SYMBOL, // ReceiverParameterDescriptor rather than ValueParameterDescriptor.
|
||||
PROPERTY_SYMBOL,
|
||||
LOCAL_DELEGATED_PROPERTY_SYMBOL,
|
||||
TYPEALIAS_SYMBOL;
|
||||
}
|
||||
|
||||
private fun symbolKindId(): Int = (code and 0xFF).toInt()
|
||||
|
||||
val signatureId: Int get() = (code ushr 8).toInt()
|
||||
val kind: SymbolKind
|
||||
get() = SymbolKind.values()[symbolKindId()]
|
||||
|
||||
companion object {
|
||||
fun encode(kind: SymbolKind, signatureId: Int): Long {
|
||||
val kindId = kind.ordinal
|
||||
return (signatureId.toLong() shl 8) or kindId.toLong()
|
||||
}
|
||||
|
||||
fun decode(code: Long) = BinarySymbolData(code)
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.serialization.encodings
|
||||
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
inline class BinaryTypeProjection(val code: Long) {
|
||||
|
||||
private fun varianceId(): Int = (code and 0x3L).toInt() - 1
|
||||
|
||||
val isStarProjection: Boolean get() = code == 0L
|
||||
|
||||
val variance: Variance
|
||||
get() {
|
||||
assert(!isStarProjection)
|
||||
return Variance.values()[varianceId()]
|
||||
}
|
||||
|
||||
val typeIndex: Int get() = (code ushr 2).toInt()
|
||||
|
||||
companion object {
|
||||
fun encodeType(variance: Variance, typeIndex: Int): Long {
|
||||
val vId = variance.ordinal + 1
|
||||
return (typeIndex.toLong() shl 2) or vId.toLong()
|
||||
}
|
||||
|
||||
fun decode(code: Long) = BinaryTypeProjection(code)
|
||||
|
||||
const val STAR_CODE = 0L
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user