Removed Javascript serializer from Konan.
Introduced our own serializer.
This commit is contained in:
committed by
alexander-gorshenev
parent
2950921bd1
commit
a1786614ea
@@ -13,6 +13,7 @@ buildscript {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String protobufVersion = '2.6.1'
|
||||||
apply plugin: "com.google.protobuf"
|
apply plugin: "com.google.protobuf"
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
apply plugin: 'kotlin'
|
apply plugin: 'kotlin'
|
||||||
@@ -45,7 +46,10 @@ allprojects {
|
|||||||
sourceSets {
|
sourceSets {
|
||||||
compiler {
|
compiler {
|
||||||
proto.srcDir 'compiler/ir/backend.native/src/'
|
proto.srcDir 'compiler/ir/backend.native/src/'
|
||||||
java.srcDirs 'compiler/ir/backend.native/src/', 'build/generated/source/proto/compiler/java/'
|
java {
|
||||||
|
srcDir 'compiler/ir/backend.native/src/'
|
||||||
|
srcDir 'build/renamed/source/proto/compiler/java'
|
||||||
|
}
|
||||||
kotlin.srcDir 'compiler/ir/backend.native/src/'
|
kotlin.srcDir 'compiler/ir/backend.native/src/'
|
||||||
}
|
}
|
||||||
cli_bc {
|
cli_bc {
|
||||||
@@ -58,12 +62,28 @@ sourceSets {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The protobuf plugin specifies this dependency for java by itself,
|
|
||||||
// but not for Kotlin.
|
|
||||||
compileCompilerKotlin {
|
compileCompilerKotlin {
|
||||||
|
dependsOn('renamePackage')
|
||||||
|
// The protobuf plugin specifies this dependency for java by itself,
|
||||||
|
// but not for Kotlin.
|
||||||
dependsOn('generateCompilerProto')
|
dependsOn('generateCompilerProto')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compileCompilerJava {
|
||||||
|
doFirst {
|
||||||
|
delete 'build/generated'
|
||||||
|
}
|
||||||
|
dependsOn('renamePackage')
|
||||||
|
}
|
||||||
|
|
||||||
|
task renamePackage(type: Copy) {
|
||||||
|
dependsOn('generateCompilerProto')
|
||||||
|
from 'build/generated/source/proto/compiler/java'
|
||||||
|
into 'build/renamed/source/proto/compiler/java'
|
||||||
|
filter {line -> line.replaceAll("com.google.protobuf", "org.jetbrains.kotlin.protobuf")}
|
||||||
|
outputs.files('build/renamed')
|
||||||
|
}
|
||||||
|
|
||||||
List<String> llvmLinkerOpts() {
|
List<String> llvmLinkerOpts() {
|
||||||
// TODO: cannot use llvm-config because it can be inaccessible during project configuration
|
// TODO: cannot use llvm-config because it can be inaccessible during project configuration
|
||||||
final List<String> libs = [
|
final List<String> libs = [
|
||||||
@@ -145,7 +165,7 @@ configurations {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
compilerCompile "com.google.protobuf:protobuf-java:3.0.0"
|
compilerCompile "com.google.protobuf:protobuf-java:${protobufVersion}"
|
||||||
|
|
||||||
compilerCompile kotlinCompilerModule
|
compilerCompile kotlinCompilerModule
|
||||||
compilerCompile kotlinNativeInterop['llvm'].configuration
|
compilerCompile kotlinNativeInterop['llvm'].configuration
|
||||||
@@ -239,7 +259,7 @@ task jars(type: Jar) {
|
|||||||
task external_jars(type: Copy) {
|
task external_jars(type: Copy) {
|
||||||
from configurations.compilerCompile {
|
from configurations.compilerCompile {
|
||||||
|
|
||||||
include 'protobuf-java-3.0.0.jar'
|
include "protobuf-java-${protobufVersion}.jar"
|
||||||
|
|
||||||
include 'kotlin-compiler*.jar'
|
include 'kotlin-compiler*.jar'
|
||||||
rename 'kotlin-compiler(.*).jar', 'kotlin-compiler.jar'
|
rename 'kotlin-compiler(.*).jar', 'kotlin-compiler.jar'
|
||||||
@@ -250,7 +270,7 @@ task external_jars(type: Copy) {
|
|||||||
|
|
||||||
protobuf {
|
protobuf {
|
||||||
protoc {
|
protoc {
|
||||||
artifact = 'com.google.protobuf:protoc:3.0.0'
|
artifact = "com.google.protobuf:protoc:${protobufVersion}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,14 +56,16 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
|||||||
|
|
||||||
configuration.addKotlinSourceRoots(arguments.freeArgs)
|
configuration.addKotlinSourceRoots(arguments.freeArgs)
|
||||||
|
|
||||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, "main")
|
// This is a decision we could change
|
||||||
|
configuration.put(CommonConfigurationKeys.MODULE_NAME, arguments.outputFile)
|
||||||
|
|
||||||
val libraries = arguments.libraries.toNonNullList()
|
|
||||||
configuration.put(KonanConfigKeys.LIBRARY_FILES,
|
configuration.put(KonanConfigKeys.LIBRARY_FILES,
|
||||||
arguments.libraries.toNonNullList())
|
arguments.libraries.toNonNullList())
|
||||||
configuration.put(KonanConfigKeys.RUNTIME_FILE, arguments.runtimeFile)
|
configuration.put(KonanConfigKeys.RUNTIME_FILE, arguments.runtimeFile)
|
||||||
configuration.put(KonanConfigKeys.OUTPUT_FILE, arguments.outputFile)
|
configuration.put(KonanConfigKeys.OUTPUT_FILE, arguments.outputFile)
|
||||||
|
|
||||||
|
configuration.put(KonanConfigKeys.ABI_VERSION, 1)
|
||||||
|
|
||||||
configuration.put(KonanConfigKeys.PRINT_IR, arguments.printIr)
|
configuration.put(KonanConfigKeys.PRINT_IR, arguments.printIr)
|
||||||
configuration.put(KonanConfigKeys.PRINT_DESCRIPTORS, arguments.printDescriptors)
|
configuration.put(KonanConfigKeys.PRINT_DESCRIPTORS, arguments.printDescriptors)
|
||||||
configuration.put(KonanConfigKeys.PRINT_BITCODE, arguments.printBitCode)
|
configuration.put(KonanConfigKeys.PRINT_BITCODE, arguments.printBitCode)
|
||||||
|
|||||||
+6
-6
@@ -1,20 +1,20 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan
|
package org.jetbrains.kotlin.backend.konan
|
||||||
|
|
||||||
import llvm.*
|
import llvm.*
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.Ir
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.ModuleIndex
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.Runtime
|
import org.jetbrains.kotlin.backend.konan.llvm.Runtime
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.getFunctionType
|
import org.jetbrains.kotlin.backend.konan.llvm.getFunctionType
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.StaticData
|
import org.jetbrains.kotlin.backend.konan.llvm.StaticData
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.Llvm
|
import org.jetbrains.kotlin.backend.konan.llvm.Llvm
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanPhase
|
import org.jetbrains.kotlin.backend.konan.KonanPhase
|
||||||
import org.jetbrains.kotlin.backend.konan.ModuleIndex
|
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanConfig
|
import org.jetbrains.kotlin.backend.konan.KonanConfig
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.backend.konan.DeepPrintVisitor
|
import org.jetbrains.kotlin.backend.konan.descriptors.deepPrint
|
||||||
import org.jetbrains.kotlin.backend.konan.PrintVisitor
|
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.verifyModule
|
import org.jetbrains.kotlin.backend.konan.llvm.verifyModule
|
||||||
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
|
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
|
||||||
import java.lang.System.out
|
import java.lang.System.out
|
||||||
@@ -32,10 +32,10 @@ internal final class Context(val config: KonanConfig,
|
|||||||
}
|
}
|
||||||
field = module!!
|
field = module!!
|
||||||
|
|
||||||
moduleIndex = ModuleIndex(irModule!!)
|
ir = Ir(this, module)
|
||||||
}
|
}
|
||||||
|
|
||||||
lateinit var moduleIndex: ModuleIndex
|
lateinit var ir: Ir
|
||||||
|
|
||||||
var llvmModule: LLVMModuleRef? = null
|
var llvmModule: LLVMModuleRef? = null
|
||||||
set(module: LLVMModuleRef?) {
|
set(module: LLVMModuleRef?) {
|
||||||
@@ -61,7 +61,7 @@ internal final class Context(val config: KonanConfig,
|
|||||||
|
|
||||||
fun printDescriptors() {
|
fun printDescriptors() {
|
||||||
separator("Descriptors after: ${phase?.description}")
|
separator("Descriptors after: ${phase?.description}")
|
||||||
moduleDescriptor!!.accept(DeepPrintVisitor(PrintVisitor()), 0)
|
moduleDescriptor!!.deepPrint()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun verifyIr() {
|
fun verifyIr() {
|
||||||
|
|||||||
+20
-39
@@ -2,6 +2,7 @@ package org.jetbrains.kotlin.backend.konan
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanPlatform
|
import org.jetbrains.kotlin.backend.konan.KonanPlatform
|
||||||
|
import org.jetbrains.kotlin.backend.konan.llvm.loadMetadata
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||||
@@ -9,61 +10,41 @@ import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
|||||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
|
import java.io.File
|
||||||
import org.jetbrains.kotlin.serialization.js.JsModuleDescriptor
|
|
||||||
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
|
|
||||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.KotlinKonanMetadata
|
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.KotlinKonanMetadataUtils
|
|
||||||
|
|
||||||
class KonanConfig(val project: Project, val configuration: CompilerConfiguration) {
|
class KonanConfig(val project: Project, val configuration: CompilerConfiguration) {
|
||||||
|
|
||||||
private val storageManager = LockBasedStorageManager()
|
|
||||||
|
|
||||||
private val libraries = configuration.getList(KonanConfigKeys.LIBRARY_FILES)
|
private val libraries = configuration.getList(KonanConfigKeys.LIBRARY_FILES)
|
||||||
|
|
||||||
private val metadata = KotlinKonanMetadataUtils.loadLibMetadata(libraries)
|
private val loadedDescriptors = loadLibMetadata(libraries)
|
||||||
|
|
||||||
val moduleId: String
|
val moduleId: String
|
||||||
get() = configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)
|
get() = configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)
|
||||||
|
|
||||||
val moduleKind: ModuleKind
|
fun loadLibMetadata(libraries: List<String>): List<ModuleDescriptorImpl> {
|
||||||
get() = configuration.get(KonanConfigKeys.MODULE_KIND)!!
|
|
||||||
|
|
||||||
// We reuse JsModuleDescriptor for serialization for now, as we haven't got one for Konan yet.
|
val allMetadata = mutableListOf<ModuleDescriptorImpl>()
|
||||||
internal val moduleDescriptors: MutableList<JsModuleDescriptor<ModuleDescriptorImpl>> by lazy {
|
|
||||||
|
|
||||||
val jsDescriptors = mutableListOf<JsModuleDescriptor<ModuleDescriptorImpl>>()
|
for (path in libraries) {
|
||||||
val descriptors = mutableListOf<ModuleDescriptorImpl>()
|
val filePath = File(path)
|
||||||
|
if (!filePath.exists()) {
|
||||||
|
error("Path '" + path + "' does not exist");
|
||||||
|
}
|
||||||
|
|
||||||
for (metadataEntry in metadata) {
|
val moduleDescriptor = loadMetadata(configuration, filePath);
|
||||||
val descriptor = createModuleDescriptor(metadataEntry)
|
|
||||||
jsDescriptors.add(descriptor)
|
allMetadata.add(moduleDescriptor);
|
||||||
descriptors.add(descriptor.data)
|
|
||||||
}
|
}
|
||||||
|
return allMetadata;
|
||||||
for (module in jsDescriptors) {
|
|
||||||
setDependencies(module.data, descriptors)
|
|
||||||
}
|
|
||||||
|
|
||||||
jsDescriptors
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createModuleDescriptor(metadata: KotlinKonanMetadata): JsModuleDescriptor<ModuleDescriptorImpl> {
|
internal val moduleDescriptors: List<ModuleDescriptorImpl> by lazy {
|
||||||
|
for (module in loadedDescriptors) {
|
||||||
|
// Yes, just to all of them.
|
||||||
|
setDependencies(module, loadedDescriptors)
|
||||||
|
}
|
||||||
|
|
||||||
val moduleDescriptor = ModuleDescriptorImpl(
|
loadedDescriptors
|
||||||
Name.special("<" + metadata.moduleName + ">"), storageManager, KonanPlatform.builtIns)
|
|
||||||
|
|
||||||
val rawDescriptor = KotlinJavascriptSerializationUtil.readModule(
|
|
||||||
metadata.body, storageManager, moduleDescriptor, CompilerDeserializationConfiguration(
|
|
||||||
configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, LanguageVersionSettingsImpl.DEFAULT)))
|
|
||||||
|
|
||||||
val provider = rawDescriptor.data
|
|
||||||
moduleDescriptor.initialize(provider ?: PackageFragmentProvider.Empty)
|
|
||||||
|
|
||||||
return rawDescriptor.copy(moduleDescriptor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+2
@@ -11,6 +11,8 @@ class KonanConfigKeys {
|
|||||||
= CompilerConfigurationKey.create("runtime file path");
|
= CompilerConfigurationKey.create("runtime file path");
|
||||||
val OUTPUT_FILE: CompilerConfigurationKey<String>
|
val OUTPUT_FILE: CompilerConfigurationKey<String>
|
||||||
= CompilerConfigurationKey.create("output file path");
|
= CompilerConfigurationKey.create("output file path");
|
||||||
|
val ABI_VERSION: CompilerConfigurationKey<Int>
|
||||||
|
= CompilerConfigurationKey.create("current abi version");
|
||||||
|
|
||||||
val SOURCE_MAP: CompilerConfigurationKey<List<String>>
|
val SOURCE_MAP: CompilerConfigurationKey<List<String>>
|
||||||
= CompilerConfigurationKey.create("generate source map");
|
= CompilerConfigurationKey.create("generate source map");
|
||||||
|
|||||||
+1
-1
@@ -40,7 +40,7 @@ object TopDownAnalyzerFacadeForKonan {
|
|||||||
// Make sure the compiler produced BuiltIns module comes in last
|
// Make sure the compiler produced BuiltIns module comes in last
|
||||||
context.setDependencies(
|
context.setDependencies(
|
||||||
listOf(context.module) +
|
listOf(context.module) +
|
||||||
config.moduleDescriptors.map { it.data } +
|
config.moduleDescriptors +
|
||||||
listOf(compilerBuiltInsModule)
|
listOf(compilerBuiltInsModule)
|
||||||
)
|
)
|
||||||
return analyzeFilesWithGivenTrace(files, BindingTraceContext(), context, config)
|
return analyzeFilesWithGivenTrace(files, BindingTraceContext(), context, config)
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan
|
package org.jetbrains.kotlin.backend.konan.descriptors
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||||
import org.jetbrains.kotlin.renderer.*
|
import org.jetbrains.kotlin.renderer.*
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan
|
package org.jetbrains.kotlin.backend.konan.descriptors
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
+17
-1
@@ -1,9 +1,11 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.descriptors
|
package org.jetbrains.kotlin.backend.konan.descriptors
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
fun ClassDescriptor?.getter2Descriptor(methodName: Name) = this?.let {
|
fun ClassDescriptor?.getter2Descriptor(methodName: Name) = this?.let {
|
||||||
@@ -26,4 +28,18 @@ fun ClassDescriptor?.signature2Descriptor(methodName: Name, signature:Array<Kotl
|
|||||||
return@any p.type == signature[index]
|
return@any p.type == signature[index]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val PropertyDescriptor.backingField: PropertyDescriptor?
|
||||||
|
get() {
|
||||||
|
val backingFieldAnnotation = FqName("konan.internal.HasBackingField")
|
||||||
|
if (this.annotations.findAnnotation(backingFieldAnnotation) != null) {
|
||||||
|
return this
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DeclarationDescriptor.deepPrint() {
|
||||||
|
this!!.accept(DeepPrintVisitor(PrintVisitor()), 0)
|
||||||
|
}
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package org.jetbrains.kotlin.backend.konan.ir
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
|
||||||
|
// This is what Context collects about IR.
|
||||||
|
internal class Ir(val context: Context, val irModule: IrModuleFragment) {
|
||||||
|
val propertiesWithBackingFields = mutableSetOf<PropertyDescriptor>()
|
||||||
|
|
||||||
|
val moduleIndex = ModuleIndex(irModule!!)
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan
|
package org.jetbrains.kotlin.backend.konan.ir
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
-17
@@ -1,17 +0,0 @@
|
|||||||
|
|
||||||
syntax="proto2";
|
|
||||||
package org.jetbrains.kotlin.backend.konan.llvm;
|
|
||||||
|
|
||||||
option java_outer_classname = "BinaryLinkdata";
|
|
||||||
|
|
||||||
message TypeLinkdata {
|
|
||||||
required string name = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message FunLinkdata {
|
|
||||||
required string hash = 1;
|
|
||||||
required string name = 2;
|
|
||||||
required TypeLinkdata returnType = 3;
|
|
||||||
repeated TypeLinkdata arg = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
+30
-5
@@ -5,11 +5,13 @@ import llvm.*
|
|||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.hash.GlobalHash
|
import org.jetbrains.kotlin.backend.konan.hash.GlobalHash
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
||||||
|
import org.jetbrains.kotlin.backend.konan.descriptors.backingField
|
||||||
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.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
@@ -55,11 +57,35 @@ internal interface ContextUtils {
|
|||||||
*/
|
*/
|
||||||
val ClassDescriptor.declaredFields: List<PropertyDescriptor>
|
val ClassDescriptor.declaredFields: List<PropertyDescriptor>
|
||||||
get() {
|
get() {
|
||||||
// TODO: do not use IR to get fields
|
// TODO: Here's what is going on here:
|
||||||
val irClass = context.moduleIndex.classes[this.classId] ?:
|
// The existence of a backing field for a property is only described in the IR,
|
||||||
throw IllegalArgumentException("Class ${this.fqNameSafe} is not found in current module")
|
// but not in the property descriptor.
|
||||||
|
// That works, while we process the IR, but not for deserialized descriptors.
|
||||||
|
//
|
||||||
|
// So to have something in deserialized descriptors,
|
||||||
|
// while we still see the IR, we mark the property with an annotation.
|
||||||
|
//
|
||||||
|
// We could apply the annotation during IR rewite, but we still are not
|
||||||
|
// that far in the rewriting infrastructure. So we postpone
|
||||||
|
// the annotation until the serializer.
|
||||||
|
//
|
||||||
|
// In this function we check the presence of the backing filed
|
||||||
|
// two ways: first we check IR, then we check the annotation.
|
||||||
|
|
||||||
return irClass.declarations.mapNotNull { (it as? IrProperty)?.backingField?.descriptor }
|
val irClass = context.ir.moduleIndex.classes[this.classId]
|
||||||
|
if (irClass != null) {
|
||||||
|
val irProperties = irClass.declarations
|
||||||
|
|
||||||
|
return irProperties.mapNotNull {
|
||||||
|
(it as? IrProperty)?.backingField?.descriptor
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val properties = this.unsubstitutedMemberScope.
|
||||||
|
getContributedDescriptors().
|
||||||
|
filterIsInstance<PropertyDescriptor>()
|
||||||
|
|
||||||
|
return properties.mapNotNull{ it.backingField }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,7 +191,6 @@ internal interface ContextUtils {
|
|||||||
get() = this.toString().localHash
|
get() = this.toString().localHash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
||||||
|
|
||||||
private fun importFunction(name: String, otherModule: LLVMModuleRef): LLVMValueRef {
|
private fun importFunction(name: String, otherModule: LLVMModuleRef): LLVMValueRef {
|
||||||
|
|||||||
+15
-2
@@ -21,15 +21,28 @@ internal fun globalHash(data: ByteArray, retValPlacement: NativePlacement): Glob
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun base64Encode(data: ByteArray): String {
|
public fun base64Encode(data: ByteArray): String {
|
||||||
memScoped {
|
memScoped {
|
||||||
val resultSize = 4 * data.size / 3 + 3 + 1
|
val resultSize = 4 * data.size / 3 + 3 + 1
|
||||||
val result = allocArray<CInt8Var>(resultSize)
|
val result = allocArray<CInt8Var>(resultSize)
|
||||||
val bytes = allocArrayOf(data)
|
val bytes = allocArrayOf(data)
|
||||||
Base64Encode(bytes.ptr, data.size, result.ptr, resultSize)
|
EncodeBase64(bytes.ptr, data.size, result.ptr, resultSize)
|
||||||
// TODO: any better way to do that without two copies?
|
// TODO: any better way to do that without two copies?
|
||||||
return CString.fromArray(result).toString()
|
return CString.fromArray(result).toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun base64Decode(encoded: String): ByteArray {
|
||||||
|
memScoped {
|
||||||
|
val bufferSize: Int = 3 * encoded.length / 4
|
||||||
|
val result = allocArray<CInt8Var>(bufferSize)
|
||||||
|
val resultSize = allocArray<uint32_tVar>(1)
|
||||||
|
resultSize[0].value = bufferSize
|
||||||
|
val errorCode = DecodeBase64(encoded, encoded.length, result[0].ptr, resultSize[0].ptr)
|
||||||
|
if (errorCode != 0) throw Error("Non-zero exit code of DecodeBase64: ${errorCode}")
|
||||||
|
val realSize = resultSize[0].value!!
|
||||||
|
return ByteArray(realSize, {i -> result[i].value!!})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal class LocalHash(val value: Long) : ConstValue by Int64(value)
|
internal class LocalHash(val value: Long) : ConstValue by Int64(value)
|
||||||
|
|||||||
+8
-2
@@ -103,9 +103,15 @@ internal class MetadatorVisitor(val context: Context) : IrElementVisitorVoid {
|
|||||||
element.acceptChildrenVoid(this)
|
element.acceptChildrenVoid(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitProperty(declaration: IrProperty) {
|
||||||
|
declaration.acceptChildrenVoid(this)
|
||||||
|
metadator.property(declaration)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitModuleFragment(module: IrModuleFragment) {
|
override fun visitModuleFragment(module: IrModuleFragment) {
|
||||||
module.acceptChildrenVoid(this)
|
module.acceptChildrenVoid(this)
|
||||||
metadator.endModule(module)
|
metadator.endModule(module)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,7 +405,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
|
|
||||||
LLVMSetInitializer(objectPtr, codegen.kNullObjHeaderPtr)
|
LLVMSetInitializer(objectPtr, codegen.kNullObjHeaderPtr)
|
||||||
}
|
}
|
||||||
val irOfCurrentClass = context.moduleIndex.classes[classDescriptor.classId]
|
val irOfCurrentClass = context.ir.moduleIndex.classes[classDescriptor.classId]
|
||||||
irOfCurrentClass!!.acceptChildrenVoid(object : IrElementVisitorVoid {
|
irOfCurrentClass!!.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||||
override fun visitElement(element: IrElement) {
|
override fun visitElement(element: IrElement) {
|
||||||
element.acceptChildrenVoid(this)
|
element.acceptChildrenVoid(this)
|
||||||
|
|||||||
-116
@@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// this file has been adapted from the corresponding piece of Javascript compiler
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan.llvm
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
|
||||||
import java.io.File
|
|
||||||
import javax.xml.bind.DatatypeConverter.parseBase64Binary
|
|
||||||
import javax.xml.bind.DatatypeConverter.printBase64Binary
|
|
||||||
|
|
||||||
|
|
||||||
class KotlinKonanMetadata(val abiVersion: Int, val moduleName: String, val body: ByteArray) {
|
|
||||||
val isAbiVersionCompatible: Boolean = KotlinKonanMetadataUtils.isAbiVersionCompatible(abiVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
class JsBinaryVersion(vararg numbers: Int) : BinaryVersion(*numbers) {
|
|
||||||
override fun isCompatible() = this.isCompatibleTo(INSTANCE)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val INSTANCE = JsBinaryVersion(0, 5, 0)
|
|
||||||
|
|
||||||
val INVALID_VERSION = JsBinaryVersion()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object KotlinKonanMetadataUtils {
|
|
||||||
private val KOTLIN_JAVASCRIPT_METHOD_NAME = "kotlin_module_metadata"
|
|
||||||
private val KOTLIN_JAVASCRIPT_METHOD_NAME_PATTERN = "\\.kotlin_module_metadata\\(".toPattern()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matches string like <name>.kotlin_module_metadata(<abi version>, <module name>, <base64 data>)
|
|
||||||
*/
|
|
||||||
private val METADATA_PATTERN = "(?m)\\w+\\.$KOTLIN_JAVASCRIPT_METHOD_NAME\\((\\d+),\\s*(['\"])([^'\"]*)\\2,\\s*(['\"])([^'\"]*)\\4\\)".toPattern()
|
|
||||||
|
|
||||||
val ABI_VERSION: Int = JsBinaryVersion.INSTANCE.minor
|
|
||||||
|
|
||||||
fun isAbiVersionCompatible(abiVersion: Int): Boolean = abiVersion == ABI_VERSION
|
|
||||||
|
|
||||||
fun hasMetadata(text: String): Boolean =
|
|
||||||
KOTLIN_JAVASCRIPT_METHOD_NAME_PATTERN.matcher(text).find() && METADATA_PATTERN.matcher(text).find()
|
|
||||||
|
|
||||||
fun formatMetadataAsString(moduleName: String, content: ByteArray): String =
|
|
||||||
"// Kotlin.$KOTLIN_JAVASCRIPT_METHOD_NAME($ABI_VERSION, \"$moduleName\", \"${printBase64Binary(content)}\");\n"
|
|
||||||
|
|
||||||
fun loadMetadata(file: File): List<KotlinKonanMetadata> {
|
|
||||||
assert(file.exists()) { "Library $file not found" }
|
|
||||||
val metadataList = arrayListOf<KotlinKonanMetadata>()
|
|
||||||
val content = readModuleMetadata(file)
|
|
||||||
parseMetadata(content, metadataList)
|
|
||||||
|
|
||||||
return metadataList
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadMetadata(path: String): List<KotlinKonanMetadata> = loadMetadata(File(path))
|
|
||||||
|
|
||||||
fun parseMetadata(text: String, metadataList: MutableList<KotlinKonanMetadata>) {
|
|
||||||
// Check for literal pattern first in order to reduce time for large files without metadata
|
|
||||||
if (!KOTLIN_JAVASCRIPT_METHOD_NAME_PATTERN.matcher(text).find()) return
|
|
||||||
|
|
||||||
val matcher = METADATA_PATTERN.matcher(text)
|
|
||||||
while (matcher.find()) {
|
|
||||||
val abiVersion = matcher.group(1).toInt()
|
|
||||||
val moduleName = matcher.group(3)
|
|
||||||
val data = matcher.group(5)
|
|
||||||
metadataList.add(KotlinKonanMetadata(abiVersion, moduleName, parseBase64Binary(data)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadLibMetadata(libraries: List<String>): List<KotlinKonanMetadata> {
|
|
||||||
|
|
||||||
val allMetadata = mutableListOf<KotlinKonanMetadata>()
|
|
||||||
|
|
||||||
for (path in libraries) {
|
|
||||||
val filePath = File(path)
|
|
||||||
if (!filePath.exists()) {
|
|
||||||
// TODO: should we throw here?
|
|
||||||
println("Path '" + path + "' does not exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
val metadataList = loadMetadata(filePath);
|
|
||||||
|
|
||||||
if (metadataList.isEmpty()) {
|
|
||||||
// TODO: should we throw here?
|
|
||||||
println("'" + path + "' is not a valid Kotlin Native library");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (metadata in metadataList) {
|
|
||||||
if (!metadata.isAbiVersionCompatible) {
|
|
||||||
// TODO: should we throw here?
|
|
||||||
println("File '" + path + "' was compiled with an incompatible version of Kotlin. " +
|
|
||||||
"Its ABI version is " + metadata.abiVersion +
|
|
||||||
", expected version is " + ABI_VERSION);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allMetadata.addAll(metadataList);
|
|
||||||
}
|
|
||||||
return allMetadata;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+62
-102
@@ -2,28 +2,52 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
|||||||
|
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.backend.konan.ir.Ir
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.BinaryLinkdata.*
|
import org.jetbrains.kotlin.backend.konan.serialization.*
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
|
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
|
|
||||||
import org.jetbrains.kotlin.serialization.js.*
|
|
||||||
import org.jetbrains.kotlin.utils.*
|
|
||||||
import java.io.*
|
import java.io.*
|
||||||
|
|
||||||
fun readModuleMetadata(file: File): String {
|
fun loadMetadata(configuration: CompilerConfiguration, file: File): ModuleDescriptorImpl {
|
||||||
|
|
||||||
val reader = MetadataReader(file)
|
val reader = MetadataReader(file)
|
||||||
|
|
||||||
|
var metadataAsString: String? = null
|
||||||
|
var moduleName: String? = null
|
||||||
|
val currentAbiVersion = configuration.get(KonanConfigKeys.ABI_VERSION)
|
||||||
|
|
||||||
reader.use {
|
reader.use {
|
||||||
val metadataNode = reader.namedMetadataNode("kmetadata", 0);
|
val (nodeCount, kmetadataNodeArg) = reader.namedMetadataNode("kmetadata")
|
||||||
val stringNode = reader.metadataOperand(metadataNode, 0)
|
|
||||||
return reader.string(stringNode)
|
if (nodeCount != 1) {
|
||||||
|
throw Error("Unknown metadata format. The 'kmetadata' node has ${nodeCount} arguments. Don't know what to do.")
|
||||||
|
}
|
||||||
|
|
||||||
|
val operands = reader.metadataNodeOperands(kmetadataNodeArg)
|
||||||
|
|
||||||
|
val abiNode = operands[0]
|
||||||
|
val nameNode = operands[1]
|
||||||
|
val dataNode = operands[2]
|
||||||
|
|
||||||
|
val abiVersion = reader.string(abiNode).toInt()
|
||||||
|
|
||||||
|
if (abiVersion != currentAbiVersion) {
|
||||||
|
throw Error("Expected ABI version ${currentAbiVersion}, but the binary is ${abiVersion}")
|
||||||
|
}
|
||||||
|
moduleName = reader.string(nameNode)
|
||||||
|
|
||||||
|
metadataAsString = reader.string(dataNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val moduleDescriptor =
|
||||||
|
deserializeModule(configuration, metadataAsString!!, moduleName!!)
|
||||||
|
|
||||||
|
return moduleDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
class MetadataReader(file: File) : Closeable {
|
class MetadataReader(file: File) : Closeable {
|
||||||
@@ -62,25 +86,25 @@ class MetadataReader(file: File) : Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun namedMetadataNode(name: String, index: Int): LLVMValueRef {
|
fun namedMetadataNode(name: String): Pair<Int, LLVMValueRef> {
|
||||||
memScoped {
|
memScoped {
|
||||||
val nodeCount = LLVMGetNamedMetadataNumOperands(llvmModule, "kmetadata")
|
val nodeCount = LLVMGetNamedMetadataNumOperands(llvmModule, name)
|
||||||
val nodeArray = allocArray<LLVMValueRefVar>(nodeCount)
|
val nodeArray = allocArray<LLVMValueRefVar>(nodeCount)
|
||||||
|
|
||||||
LLVMGetNamedMetadataOperands(llvmModule, "kmetadata", nodeArray[0].ptr)
|
LLVMGetNamedMetadataOperands(llvmModule, "kmetadata", nodeArray[0].ptr)
|
||||||
|
|
||||||
return nodeArray[0].value!!
|
return Pair(nodeCount, nodeArray[0].value!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun metadataOperand(metadataNode: LLVMValueRef, index: Int): LLVMValueRef {
|
fun metadataNodeOperands(metadataNode: LLVMValueRef): Array<LLVMValueRef> {
|
||||||
memScoped {
|
memScoped {
|
||||||
val operandCount = LLVMGetMDNodeNumOperands(metadataNode)
|
val operandCount = LLVMGetMDNodeNumOperands(metadataNode)
|
||||||
val operandArray = allocArray<LLVMValueRefVar>(operandCount)
|
val operandArray = allocArray<LLVMValueRefVar>(operandCount)
|
||||||
|
|
||||||
LLVMGetMDNodeOperands(metadataNode, operandArray[0].ptr)
|
LLVMGetMDNodeOperands(metadataNode, operandArray[0].ptr)
|
||||||
|
|
||||||
return operandArray[0].value!!
|
return Array(operandCount, {index -> operandArray[index].value!!})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,13 +114,8 @@ class MetadataReader(file: File) : Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal class MetadataGenerator(override val context: Context): ContextUtils {
|
internal class MetadataGenerator(override val context: Context): ContextUtils {
|
||||||
|
|
||||||
private fun metadataString(str: String): LLVMValueRef {
|
|
||||||
return LLVMMDString(str, str.length)!!
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun metadataNode(args: List<LLVMValueRef?>): LLVMValueRef {
|
private fun metadataNode(args: List<LLVMValueRef?>): LLVMValueRef {
|
||||||
memScoped {
|
memScoped {
|
||||||
val references = allocArrayOf(args)
|
val references = allocArrayOf(args)
|
||||||
@@ -110,92 +129,33 @@ internal class MetadataGenerator(override val context: Context): ContextUtils {
|
|||||||
return md
|
return md
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun property(declaration: IrProperty) {
|
||||||
|
if (declaration.backingField == null) return
|
||||||
|
assert(declaration.backingField!!.descriptor == declaration.descriptor)
|
||||||
|
|
||||||
|
context.ir.propertiesWithBackingFields.add(declaration.descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
private fun emitModuleMetadata(name: String, md: LLVMValueRef?) {
|
private fun emitModuleMetadata(name: String, md: LLVMValueRef?) {
|
||||||
LLVMAddNamedMetadataOperand(context.llvmModule, name, md)
|
LLVMAddNamedMetadataOperand(context.llvmModule, name, md)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun protobufType(type:KotlinType): TypeLinkdata {
|
private fun metadataString(str: String): LLVMValueRef {
|
||||||
val builder = TypeLinkdata.newBuilder()
|
return LLVMMDString(str, str.length)!!
|
||||||
val name = type.toString()
|
|
||||||
val proto = builder
|
|
||||||
.setName(name)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
return proto
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun serializeFunSignature(declaration: IrFunction): String {
|
|
||||||
val func = declaration.descriptor
|
|
||||||
|
|
||||||
val hash = "0x123456 some hash"
|
|
||||||
val name = func.name.asString()
|
|
||||||
|
|
||||||
val kotlinType = func.getReturnType()!!
|
|
||||||
val returnType = protobufType(kotlinType)
|
|
||||||
|
|
||||||
val parameters = func.getValueParameters()
|
|
||||||
val argumentTypes = parameters.map{ protobufType(it.getType()) }
|
|
||||||
|
|
||||||
val proto = FunLinkdata.newBuilder()
|
|
||||||
.setHash(hash)
|
|
||||||
.setName(name)
|
|
||||||
.setReturnType(returnType)
|
|
||||||
.addAllArg(argumentTypes)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
// Convert it to ProtoBuf's TextFormat representation.
|
|
||||||
// Use TextFormat.merge(str, builder) to parse it back
|
|
||||||
val str = proto.toString()
|
|
||||||
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun function(declaration: IrFunction) {
|
|
||||||
val fn = declaration.descriptor.llvmFunction!!
|
|
||||||
|
|
||||||
val proto = serializeFunSignature(declaration)
|
|
||||||
|
|
||||||
val md = metadataFun(fn, proto)
|
|
||||||
emitModuleMetadata("kfun", md);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Quick check consistency
|
|
||||||
private fun debug_blob(blob: String) {
|
|
||||||
val metadataList = mutableListOf<KotlinKonanMetadata>()
|
|
||||||
KotlinKonanMetadataUtils.parseMetadata(blob, metadataList)
|
|
||||||
|
|
||||||
val body = metadataList.first().body
|
|
||||||
val gzipInputStream = java.util.zip.GZIPInputStream(ByteArrayInputStream(body))
|
|
||||||
val content = JsProtoBuf.Library.parseFrom(gzipInputStream)
|
|
||||||
gzipInputStream.close()
|
|
||||||
|
|
||||||
println(content.toString())
|
|
||||||
println(blob)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun serializeModule(moduleDescriptor: ModuleDescriptor): String {
|
|
||||||
|
|
||||||
val description = JsModuleDescriptor(
|
|
||||||
name = "foo",
|
|
||||||
kind = ModuleKind.PLAIN,
|
|
||||||
imported = listOf(),
|
|
||||||
data = moduleDescriptor
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: eliminate this dependency on JavaScript compiler
|
|
||||||
val blobString = KotlinJavascriptSerializationUtil.metadataAsString(
|
|
||||||
context.bindingContext, description)
|
|
||||||
if (false) {
|
|
||||||
debug_blob(blobString)
|
|
||||||
}
|
|
||||||
return blobString
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun endModule(module: IrModuleFragment) {
|
internal fun endModule(module: IrModuleFragment) {
|
||||||
val moduleAsString = serializeModule(module.descriptor)
|
val abiVersion = context.config.configuration.get(KonanConfigKeys.ABI_VERSION)
|
||||||
val stringNode = metadataString(moduleAsString)
|
val abiNode = metadataString("$abiVersion")
|
||||||
emitModuleMetadata("kmetadata", stringNode)
|
|
||||||
|
val moduleName = metadataString(module.descriptor.name.asString())
|
||||||
|
|
||||||
|
val serializer = KonanSerializationUtil(context)
|
||||||
|
val moduleAsString = serializer.serializeModule(module.descriptor)
|
||||||
|
val dataNode = metadataString(moduleAsString)
|
||||||
|
|
||||||
|
val kmetadataArg = metadataNode(listOf(abiNode, moduleName, dataNode))
|
||||||
|
emitModuleMetadata("kmetadata", kmetadataArg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
package org.jetbrains.kotlin.backend.konan.serialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
|
import org.jetbrains.kotlin.serialization.ClassData
|
||||||
|
import org.jetbrains.kotlin.serialization.ClassDataWithSource
|
||||||
|
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||||
|
import org.jetbrains.kotlin.serialization.KonanLinkData
|
||||||
|
import org.jetbrains.kotlin.serialization.StringTable
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder
|
||||||
|
|
||||||
|
class KonanClassDataFinder(
|
||||||
|
private val fragment: KonanLinkData.PackageFragment,
|
||||||
|
private val nameResolver: NameResolver
|
||||||
|
) : ClassDataFinder {
|
||||||
|
override fun findClassData(classId: ClassId): ClassDataWithSource? {
|
||||||
|
val proto = fragment.classes
|
||||||
|
val classList = proto.getClassesList()
|
||||||
|
val nameList = proto.getClassNameList()
|
||||||
|
|
||||||
|
val index = nameList.indexOfFirst({
|
||||||
|
nameResolver.getClassId(it) == classId })
|
||||||
|
if (index == -1)
|
||||||
|
error("Could not find serialized class ${classId}")
|
||||||
|
|
||||||
|
val foundClass = proto.getClasses(index)
|
||||||
|
if (foundClass == null)
|
||||||
|
error("Could not find data for serialized class ${classId}")
|
||||||
|
|
||||||
|
return ClassDataWithSource(ClassData(nameResolver, foundClass), SourceElement.NO_SOURCE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
+73
@@ -0,0 +1,73 @@
|
|||||||
|
|
||||||
|
syntax = "proto2";
|
||||||
|
package org.jetbrains.kotlin.serialization;
|
||||||
|
|
||||||
|
// This, an all the rest of the included proto files have ".proto1" extension.
|
||||||
|
// That allows us to construct the current file,
|
||||||
|
// but protoc will skip .class files for them.
|
||||||
|
// The issue here is that we need to co-exist with the big Kotlin,
|
||||||
|
// in the same namespace of renamed org.jetbrains.kotlin.protobuf packages.
|
||||||
|
// In case we merge to the main Kotlin workspace the scheme will be simplified.
|
||||||
|
import "org/jetbrains/kotlin/backend/konan/serialization/descriptors.proto1";
|
||||||
|
|
||||||
|
option java_outer_classname = "KonanLinkData";
|
||||||
|
option optimize_for = LITE_RUNTIME;
|
||||||
|
|
||||||
|
// Konan extensions to the "descriptors" protobuf.
|
||||||
|
|
||||||
|
extend Class {
|
||||||
|
repeated Annotation class_annotation = 170;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend Constructor {
|
||||||
|
repeated Annotation constructor_annotation = 170;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend Function {
|
||||||
|
repeated Annotation function_annotation = 170;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend Property {
|
||||||
|
repeated Annotation property_annotation = 170;
|
||||||
|
optional Annotation.Argument.Value compile_time_value = 171;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend EnumEntry {
|
||||||
|
repeated Annotation enum_entry_annotation = 170;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend ValueParameter {
|
||||||
|
repeated Annotation parameter_annotation = 170;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend Type {
|
||||||
|
repeated Annotation type_annotation = 170;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend TypeParameter {
|
||||||
|
repeated Annotation type_parameter_annotation = 170;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Konan Binary Linkdata structures.
|
||||||
|
|
||||||
|
message PackageFragment {
|
||||||
|
// Make if an index?
|
||||||
|
required string fq_name = 1;
|
||||||
|
required Package package = 4;
|
||||||
|
required Classes classes = 5;
|
||||||
|
|
||||||
|
// To construct name resolver
|
||||||
|
required QualifiedNameTable name_table = 2;
|
||||||
|
required StringTable string_table = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Classes {
|
||||||
|
// Index in the QualifiedNameIndex table.
|
||||||
|
repeated int32 class_name = 1;
|
||||||
|
repeated Class classes = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Library {
|
||||||
|
repeated PackageFragment package_fragment = 2;
|
||||||
|
}
|
||||||
|
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
package org.jetbrains.kotlin.backend.konan.serialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.serialization.KonanLinkData
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.DeserializedPackageFragment
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
|
||||||
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
|
|
||||||
|
class KonanPackageFragment( private val proto: KonanLinkData.PackageFragment,
|
||||||
|
storageManager: StorageManager, module: ModuleDescriptor) :
|
||||||
|
DeserializedPackageFragment(FqName(proto.getFqName()),
|
||||||
|
storageManager, module) {
|
||||||
|
|
||||||
|
private val nameResolver =
|
||||||
|
NameResolverImpl(proto.getStringTable(), proto.getNameTable())
|
||||||
|
|
||||||
|
override val classDataFinder = KonanClassDataFinder(proto, nameResolver)
|
||||||
|
|
||||||
|
override fun computeMemberScope(): DeserializedPackageMemberScope {
|
||||||
|
val packageProto = proto.getPackage()
|
||||||
|
|
||||||
|
return DeserializedPackageMemberScope( this, packageProto,
|
||||||
|
nameResolver, /* containerSource = */ null,
|
||||||
|
components, {loadClassNames()} )
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadClassNames(): Collection<Name> {
|
||||||
|
|
||||||
|
val classNameList = proto.getClasses().getClassNameList()
|
||||||
|
|
||||||
|
val names = classNameList.mapNotNull {
|
||||||
|
val classId = nameResolver.getClassId(it)
|
||||||
|
val shortName = classId.getShortClassName()
|
||||||
|
if (!classId.isNestedClass) shortName else null
|
||||||
|
}
|
||||||
|
|
||||||
|
return names ?: listOf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+208
@@ -0,0 +1,208 @@
|
|||||||
|
package org.jetbrains.kotlin.backend.konan.serialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
|
import org.jetbrains.kotlin.backend.konan.KonanPlatform
|
||||||
|
import org.jetbrains.kotlin.backend.konan.llvm.base64Encode
|
||||||
|
import org.jetbrains.kotlin.backend.konan.llvm.base64Decode
|
||||||
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
|
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl;
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
|
import org.jetbrains.kotlin.serialization.AnnotationSerializer
|
||||||
|
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||||
|
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||||
|
import org.jetbrains.kotlin.serialization.StringTableImpl
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.*
|
||||||
|
import org.jetbrains.kotlin.serialization.KonanLinkData
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeDeserializer
|
||||||
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.SimpleType
|
||||||
|
import org.jetbrains.kotlin.utils.*
|
||||||
|
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||||
|
|
||||||
|
/* ------------ Deserializer part ------------------------------------------*/
|
||||||
|
|
||||||
|
object NullFlexibleTypeDeserializer : FlexibleTypeDeserializer {
|
||||||
|
override fun create(proto: ProtoBuf.Type, flexibleId: String,
|
||||||
|
lowerBound: SimpleType, upperBound: SimpleType): KotlinType {
|
||||||
|
error("Illegal use of flexible type deserializer.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createKonanPackageFragmentProvider(
|
||||||
|
fragments: List<KonanLinkData.PackageFragment>,
|
||||||
|
storageManager: StorageManager, module: ModuleDescriptor,
|
||||||
|
configuration: DeserializationConfiguration): PackageFragmentProvider {
|
||||||
|
|
||||||
|
val packageFragments = fragments.map {
|
||||||
|
KonanPackageFragment(it, storageManager, module)
|
||||||
|
}
|
||||||
|
val provider = PackageFragmentProviderImpl(packageFragments)
|
||||||
|
|
||||||
|
val notFoundClasses = NotFoundClasses(storageManager, module)
|
||||||
|
|
||||||
|
val annotationAndConstantLoader = AnnotationAndConstantLoaderImpl(module, notFoundClasses, KonanSerializerProtocol)
|
||||||
|
|
||||||
|
val components = DeserializationComponents(
|
||||||
|
storageManager, module, configuration,
|
||||||
|
DeserializedClassDataFinder(provider),
|
||||||
|
annotationAndConstantLoader,
|
||||||
|
provider,
|
||||||
|
LocalClassifierTypeSettings.Default,
|
||||||
|
ErrorReporter.DO_NOTHING,
|
||||||
|
LookupTracker.DO_NOTHING, NullFlexibleTypeDeserializer,
|
||||||
|
emptyList(), notFoundClasses)
|
||||||
|
|
||||||
|
for (packageFragment in packageFragments) {
|
||||||
|
packageFragment.components = components
|
||||||
|
}
|
||||||
|
|
||||||
|
return provider
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun deserializeModule(configuration: CompilerConfiguration,
|
||||||
|
base64: String, moduleName: String): ModuleDescriptorImpl {
|
||||||
|
|
||||||
|
val storageManager = LockBasedStorageManager()
|
||||||
|
val moduleDescriptor = ModuleDescriptorImpl(
|
||||||
|
Name.special(moduleName), storageManager, KonanPlatform.builtIns)
|
||||||
|
val deserialization_config = CompilerDeserializationConfiguration(
|
||||||
|
configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, LanguageVersionSettingsImpl.DEFAULT))
|
||||||
|
|
||||||
|
|
||||||
|
val libraryAsByteArray = base64Decode(base64)
|
||||||
|
val libraryProto = KonanLinkData.Library.parseFrom(
|
||||||
|
libraryAsByteArray, KonanSerializerProtocol.extensionRegistry)
|
||||||
|
|
||||||
|
val provider = createKonanPackageFragmentProvider(
|
||||||
|
libraryProto.packageFragmentList, storageManager,
|
||||||
|
moduleDescriptor, deserialization_config)
|
||||||
|
|
||||||
|
moduleDescriptor.initialize(provider ?: PackageFragmentProvider.Empty)
|
||||||
|
|
||||||
|
return moduleDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------ Serializer part ------------------------------------------*/
|
||||||
|
|
||||||
|
internal class KonanSerializationUtil(val context: Context) {
|
||||||
|
|
||||||
|
val serializerExtension = KonanSerializerExtension(context)
|
||||||
|
val serializer = DescriptorSerializer.createTopLevel(serializerExtension)
|
||||||
|
|
||||||
|
fun serializeClass(packageName: FqName,
|
||||||
|
builder: KonanLinkData.Classes.Builder,
|
||||||
|
classDescriptor: ClassDescriptor,
|
||||||
|
skip: (DeclarationDescriptor) -> Boolean) {
|
||||||
|
|
||||||
|
if (skip(classDescriptor)) return
|
||||||
|
|
||||||
|
val classProto = serializer.classProto(classDescriptor).build()
|
||||||
|
?: error("Class not serialized: $classDescriptor")
|
||||||
|
|
||||||
|
builder.addClasses(classProto)
|
||||||
|
val index = serializer.stringTable.getFqNameIndex(classDescriptor)
|
||||||
|
builder.addClassName(index)
|
||||||
|
|
||||||
|
serializeClasses(packageName, builder,
|
||||||
|
classDescriptor.unsubstitutedInnerClassesScope
|
||||||
|
.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS), skip)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun serializeClasses(packageName: FqName,
|
||||||
|
builder: KonanLinkData.Classes.Builder,
|
||||||
|
descriptors: Collection<DeclarationDescriptor>,
|
||||||
|
skip: (DeclarationDescriptor) -> Boolean) {
|
||||||
|
|
||||||
|
for (descriptor in descriptors) {
|
||||||
|
if (descriptor is ClassDescriptor) {
|
||||||
|
serializeClass(packageName, builder, descriptor, skip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun serializePackage(fqName: FqName, module: ModuleDescriptor) :
|
||||||
|
KonanLinkData.PackageFragment {
|
||||||
|
|
||||||
|
val packageView = module.getPackage(fqName)
|
||||||
|
|
||||||
|
// TODO: ModuleDescriptor should be able to return
|
||||||
|
// the package only with the contents of that module, without dependencies
|
||||||
|
val skip: (DeclarationDescriptor) -> Boolean =
|
||||||
|
{ DescriptorUtils.getContainingModule(it) != module }
|
||||||
|
|
||||||
|
val classifierDescriptors = DescriptorSerializer.sort(packageView.memberScope.getContributedDescriptors(
|
||||||
|
DescriptorKindFilter.CLASSIFIERS))
|
||||||
|
|
||||||
|
val classesBuilder = KonanLinkData.Classes.newBuilder()
|
||||||
|
|
||||||
|
serializeClasses(fqName, classesBuilder, classifierDescriptors, skip)
|
||||||
|
val classesProto = classesBuilder.build()
|
||||||
|
|
||||||
|
val fragments = packageView.fragments
|
||||||
|
val members = fragments
|
||||||
|
.flatMap { fragment -> DescriptorUtils.getAllDescriptors(fragment.getMemberScope()) }
|
||||||
|
.filterNot(skip)
|
||||||
|
val packageProto = serializer.packagePartProto(members).build()
|
||||||
|
?: error("Package fragments not serialized: $fragments")
|
||||||
|
|
||||||
|
|
||||||
|
val strings = serializerExtension.stringTable
|
||||||
|
val (stringTableProto, nameTableProto) = strings.buildProto()
|
||||||
|
|
||||||
|
val fragmentBuilder = KonanLinkData.PackageFragment.newBuilder()
|
||||||
|
|
||||||
|
val fragmentProto = fragmentBuilder
|
||||||
|
.setPackage(packageProto)
|
||||||
|
.setFqName(fqName.asString())
|
||||||
|
.setClasses(classesProto)
|
||||||
|
.setStringTable(stringTableProto)
|
||||||
|
.setNameTable(nameTableProto)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
return fragmentProto
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getPackagesFqNames(module: ModuleDescriptor): Set<FqName> {
|
||||||
|
val fqNames = mutableSetOf<FqName>(FqName.ROOT)
|
||||||
|
getSubPackagesFqNames(module.getPackage(FqName.ROOT), fqNames)
|
||||||
|
return fqNames
|
||||||
|
}
|
||||||
|
private fun getSubPackagesFqNames(packageView: PackageViewDescriptor, result: MutableSet<FqName>) {
|
||||||
|
val fqName = packageView.fqName
|
||||||
|
if (!fqName.isRoot) {
|
||||||
|
result.add(fqName)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (descriptor in packageView.memberScope.getContributedDescriptors(
|
||||||
|
DescriptorKindFilter.PACKAGES, MemberScope.ALL_NAME_FILTER)) {
|
||||||
|
if (descriptor is PackageViewDescriptor) {
|
||||||
|
getSubPackagesFqNames(descriptor, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun serializeModule(moduleDescriptor: ModuleDescriptor): String {
|
||||||
|
val library = KonanLinkData.Library.newBuilder()
|
||||||
|
|
||||||
|
getPackagesFqNames(moduleDescriptor).forEach {
|
||||||
|
val packageProto = serializePackage(it, moduleDescriptor)
|
||||||
|
library.addPackageFragment(packageProto)
|
||||||
|
}
|
||||||
|
|
||||||
|
val libraryAsByteArray = library.build().toByteArray()
|
||||||
|
val base64 = base64Encode(libraryAsByteArray)
|
||||||
|
return base64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.konan.serialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
|
import org.jetbrains.kotlin.backend.konan.getKonanInternalClass
|
||||||
|
import org.jetbrains.kotlin.serialization.Flags
|
||||||
|
import org.jetbrains.kotlin.serialization.KonanLinkData
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.*
|
||||||
|
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
|
||||||
|
import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase
|
||||||
|
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||||
|
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
|
||||||
|
import org.jetbrains.kotlin.types.FlexibleType
|
||||||
|
|
||||||
|
internal class KonanSerializerExtension(val context: Context) :
|
||||||
|
KotlinSerializerExtensionBase(KonanSerializerProtocol) {
|
||||||
|
|
||||||
|
private val backingFieldClass =
|
||||||
|
context.builtIns.getKonanInternalClass("HasBackingField").getDefaultType()
|
||||||
|
|
||||||
|
private val backingFieldAnnotation = AnnotationDescriptorImpl(
|
||||||
|
backingFieldClass, emptyMap(), SourceElement.NO_SOURCE)
|
||||||
|
|
||||||
|
override fun serializeProperty(descriptor: PropertyDescriptor, proto: ProtoBuf.Property.Builder) {
|
||||||
|
super.serializeProperty(descriptor, proto)
|
||||||
|
|
||||||
|
if (context.ir.propertiesWithBackingFields.contains(descriptor)) {
|
||||||
|
proto.addExtension(KonanLinkData.propertyAnnotation,
|
||||||
|
annotationSerializer.serializeAnnotation(backingFieldAnnotation))
|
||||||
|
|
||||||
|
proto.flags = proto.flags or Flags.HAS_ANNOTATIONS.toFlags(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object KonanSerializerProtocol : SerializerExtensionProtocol(
|
||||||
|
ExtensionRegistryLite.newInstance().apply {
|
||||||
|
KonanLinkData.registerAllExtensions(this)
|
||||||
|
},
|
||||||
|
KonanLinkData.constructorAnnotation,
|
||||||
|
KonanLinkData.classAnnotation,
|
||||||
|
KonanLinkData.functionAnnotation,
|
||||||
|
KonanLinkData.propertyAnnotation,
|
||||||
|
KonanLinkData.enumEntryAnnotation,
|
||||||
|
KonanLinkData.compileTimeValue,
|
||||||
|
KonanLinkData.parameterAnnotation,
|
||||||
|
KonanLinkData.typeAnnotation,
|
||||||
|
KonanLinkData.typeParameterAnnotation
|
||||||
|
)
|
||||||
+387
@@ -0,0 +1,387 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
syntax = "proto2";
|
||||||
|
package org.jetbrains.kotlin.serialization;
|
||||||
|
|
||||||
|
import "org/jetbrains/kotlin/backend/konan/serialization/ext_options.proto1";
|
||||||
|
|
||||||
|
option java_outer_classname = "ProtoBuf";
|
||||||
|
option optimize_for = LITE_RUNTIME;
|
||||||
|
|
||||||
|
message StringTable {
|
||||||
|
repeated string string = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message QualifiedNameTable {
|
||||||
|
message QualifiedName {
|
||||||
|
optional int32 parent_qualified_name = 1 [default = -1];
|
||||||
|
// id in the StringTable
|
||||||
|
required int32 short_name = 2;
|
||||||
|
optional Kind kind = 3 [default = PACKAGE];
|
||||||
|
|
||||||
|
enum Kind {
|
||||||
|
CLASS = 0;
|
||||||
|
PACKAGE = 1;
|
||||||
|
LOCAL = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repeated QualifiedName qualified_name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Annotation {
|
||||||
|
message Argument {
|
||||||
|
message Value {
|
||||||
|
enum Type {
|
||||||
|
BYTE = 0;
|
||||||
|
CHAR = 1;
|
||||||
|
SHORT = 2;
|
||||||
|
INT = 3;
|
||||||
|
LONG = 4;
|
||||||
|
FLOAT = 5;
|
||||||
|
DOUBLE = 6;
|
||||||
|
BOOLEAN = 7;
|
||||||
|
|
||||||
|
STRING = 8;
|
||||||
|
CLASS = 9;
|
||||||
|
ENUM = 10;
|
||||||
|
ANNOTATION = 11;
|
||||||
|
ARRAY = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: a *Value* has a Type, not an Argument! This is done for future language features which may involve using arrays
|
||||||
|
// of elements of different types. Such entries are allowed in the constant pool of JVM class files.
|
||||||
|
// However, to save space, this field is optional: in case of homogeneous arrays, only the type of the first element is required
|
||||||
|
optional Type type = 1;
|
||||||
|
|
||||||
|
// Only one of the following values should be present
|
||||||
|
|
||||||
|
optional sint64 int_value = 2;
|
||||||
|
optional float float_value = 3;
|
||||||
|
optional double double_value = 4;
|
||||||
|
|
||||||
|
optional int32 string_value = 5 [(string_id_in_table) = true];
|
||||||
|
|
||||||
|
// If type = CLASS, FQ name of the referenced class; if type = ENUM, FQ name of the enum class
|
||||||
|
optional int32 class_id = 6 [(fq_name_id_in_table) = true];
|
||||||
|
|
||||||
|
optional int32 enum_value_id = 7 [(name_id_in_table) = true];
|
||||||
|
|
||||||
|
optional Annotation annotation = 8;
|
||||||
|
|
||||||
|
repeated Value array_element = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
required int32 name_id = 1 [(name_id_in_table) = true];
|
||||||
|
required Value value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
required int32 id = 1 [(fq_name_id_in_table) = true];
|
||||||
|
|
||||||
|
repeated Argument argument = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Type {
|
||||||
|
message Argument {
|
||||||
|
enum Projection {
|
||||||
|
IN = 0;
|
||||||
|
OUT = 1;
|
||||||
|
INV = 2;
|
||||||
|
STAR = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional Projection projection = 1 [default = INV];
|
||||||
|
|
||||||
|
// When projection is STAR, no type is written, otherwise type must be specified
|
||||||
|
optional Type type = 2;
|
||||||
|
optional int32 type_id = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
repeated Argument argument = 2;
|
||||||
|
|
||||||
|
optional bool nullable = 3 [default = false];
|
||||||
|
|
||||||
|
// If this field is set, the type is flexible.
|
||||||
|
// All the other fields and extensions represent its lower bound, and flexible_upper_bound must be set and represents its upper bound.
|
||||||
|
optional int32 flexible_type_capabilities_id = 4 [(string_id_in_table) = true];
|
||||||
|
|
||||||
|
optional Type flexible_upper_bound = 5;
|
||||||
|
optional int32 flexible_upper_bound_id = 8;
|
||||||
|
|
||||||
|
// Only one of the following values should be present
|
||||||
|
|
||||||
|
optional int32 class_name = 6 [(fq_name_id_in_table) = true];
|
||||||
|
optional int32 type_parameter = 7; // id of the type parameter
|
||||||
|
// Name of the type parameter in the immediate owner
|
||||||
|
optional int32 type_parameter_name = 9 [(name_id_in_table) = true];
|
||||||
|
|
||||||
|
// Note that this may be present only for abbreviated_type
|
||||||
|
// Top level types are always fully expanded
|
||||||
|
optional int32 type_alias_name = 12 [(fq_name_id_in_table) = true];
|
||||||
|
|
||||||
|
optional Type outer_type = 10;
|
||||||
|
optional int32 outer_type_id = 11;
|
||||||
|
|
||||||
|
optional Type abbreviated_type = 13;
|
||||||
|
optional int32 abbreviated_type_id = 14;
|
||||||
|
|
||||||
|
extensions 100 to 199;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TypeParameter {
|
||||||
|
required int32 id = 1;
|
||||||
|
|
||||||
|
required int32 name = 2 [(name_id_in_table) = true];
|
||||||
|
|
||||||
|
optional bool reified = 3 [default = false];
|
||||||
|
|
||||||
|
enum Variance {
|
||||||
|
IN = 0;
|
||||||
|
OUT = 1;
|
||||||
|
INV = 2;
|
||||||
|
}
|
||||||
|
optional Variance variance = 4 [default = INV];
|
||||||
|
|
||||||
|
repeated Type upper_bound = 5;
|
||||||
|
repeated int32 upper_bound_id = 6;
|
||||||
|
|
||||||
|
extensions 100 to 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Class {
|
||||||
|
enum Kind {
|
||||||
|
// 3 bits
|
||||||
|
CLASS = 0;
|
||||||
|
INTERFACE = 1;
|
||||||
|
ENUM_CLASS = 2;
|
||||||
|
ENUM_ENTRY = 3;
|
||||||
|
ANNOTATION_CLASS = 4;
|
||||||
|
OBJECT = 5;
|
||||||
|
COMPANION_OBJECT = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
hasAnnotations
|
||||||
|
Visibility
|
||||||
|
Modality
|
||||||
|
ClassKind
|
||||||
|
isInner
|
||||||
|
isData
|
||||||
|
*/
|
||||||
|
optional int32 flags = 1 [default = 6 /* public final class, no annotations */];
|
||||||
|
|
||||||
|
required int32 fq_name = 3 [(fq_name_id_in_table) = true];
|
||||||
|
|
||||||
|
optional int32 companion_object_name = 4 [(name_id_in_table) = true];
|
||||||
|
|
||||||
|
repeated TypeParameter type_parameter = 5;
|
||||||
|
|
||||||
|
repeated Type supertype = 6;
|
||||||
|
repeated int32 supertype_id = 2 [packed = true];
|
||||||
|
|
||||||
|
repeated int32 nested_class_name = 7 [packed = true, (name_id_in_table) = true];
|
||||||
|
|
||||||
|
repeated Constructor constructor = 8;
|
||||||
|
repeated Function function = 9;
|
||||||
|
repeated Property property = 10;
|
||||||
|
repeated TypeAlias type_alias = 11;
|
||||||
|
|
||||||
|
repeated EnumEntry enum_entry = 13;
|
||||||
|
|
||||||
|
optional TypeTable type_table = 30;
|
||||||
|
|
||||||
|
extensions 100 to 199;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Package {
|
||||||
|
repeated Function function = 3;
|
||||||
|
repeated Property property = 4;
|
||||||
|
repeated TypeAlias type_alias = 5;
|
||||||
|
|
||||||
|
optional TypeTable type_table = 30;
|
||||||
|
|
||||||
|
extensions 100 to 199;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TypeTable {
|
||||||
|
repeated Type type = 1;
|
||||||
|
|
||||||
|
// Index starting from which all types are nullable, or nothing if all types in this table are non-null.
|
||||||
|
// Note that the 'nullable' field of Type messages is ignored and shouldn't be written because it wastes too much space
|
||||||
|
optional int32 first_nullable = 2 [default = -1];
|
||||||
|
}
|
||||||
|
|
||||||
|
message Constructor {
|
||||||
|
/*
|
||||||
|
hasAnnotations
|
||||||
|
Visibility
|
||||||
|
isSecondary
|
||||||
|
*/
|
||||||
|
optional int32 flags = 1 [default = 6 /* public constructor, no annotations */];
|
||||||
|
|
||||||
|
repeated ValueParameter value_parameter = 2;
|
||||||
|
|
||||||
|
extensions 100 to 199;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Function {
|
||||||
|
/*
|
||||||
|
hasAnnotations
|
||||||
|
Visibility
|
||||||
|
Modality
|
||||||
|
MemberKind
|
||||||
|
isOperator
|
||||||
|
isInfix
|
||||||
|
isInline
|
||||||
|
isTailrec
|
||||||
|
isExternal
|
||||||
|
*/
|
||||||
|
optional int32 flags = 9 [default = 6 /* public final function, no annotations */];
|
||||||
|
optional int32 old_flags = 1 [default = 6];
|
||||||
|
|
||||||
|
required int32 name = 2 [(name_id_in_table) = true];
|
||||||
|
|
||||||
|
optional Type return_type = 3;
|
||||||
|
optional int32 return_type_id = 7;
|
||||||
|
|
||||||
|
repeated TypeParameter type_parameter = 4;
|
||||||
|
|
||||||
|
optional Type receiver_type = 5;
|
||||||
|
optional int32 receiver_type_id = 8;
|
||||||
|
|
||||||
|
repeated ValueParameter value_parameter = 6;
|
||||||
|
|
||||||
|
optional TypeTable type_table = 30;
|
||||||
|
|
||||||
|
extensions 100 to 199;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Property {
|
||||||
|
/*
|
||||||
|
hasAnnotations
|
||||||
|
Visibility
|
||||||
|
Modality
|
||||||
|
MemberKind
|
||||||
|
isVar
|
||||||
|
hasGetter
|
||||||
|
hasSetter
|
||||||
|
isConst
|
||||||
|
lateinit
|
||||||
|
hasConstant
|
||||||
|
*/
|
||||||
|
optional int32 flags = 11 [default = 518 /* public (6) final property with getter (512) */];
|
||||||
|
optional int32 old_flags = 1 [default = 2054];
|
||||||
|
|
||||||
|
required int32 name = 2 [(name_id_in_table) = true];
|
||||||
|
|
||||||
|
optional Type return_type = 3;
|
||||||
|
optional int32 return_type_id = 9;
|
||||||
|
|
||||||
|
repeated TypeParameter type_parameter = 4;
|
||||||
|
|
||||||
|
optional Type receiver_type = 5;
|
||||||
|
optional int32 receiver_type_id = 10;
|
||||||
|
|
||||||
|
optional ValueParameter setter_value_parameter = 6;
|
||||||
|
|
||||||
|
/*
|
||||||
|
hasAnnotations
|
||||||
|
Visibility
|
||||||
|
Modality
|
||||||
|
isNotDefault
|
||||||
|
isExternal
|
||||||
|
isInline
|
||||||
|
*/
|
||||||
|
optional int32 getter_flags = 7 /* absent => same as property */;
|
||||||
|
optional int32 setter_flags = 8 /* absent => same as property */;
|
||||||
|
|
||||||
|
extensions 100 to 199;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ValueParameter {
|
||||||
|
/*
|
||||||
|
declaresDefault
|
||||||
|
hasAnnotations
|
||||||
|
isCrossinline
|
||||||
|
isNoinline
|
||||||
|
*/
|
||||||
|
optional int32 flags = 1 [default = 0];
|
||||||
|
|
||||||
|
required int32 name = 2 [(name_id_in_table) = true];
|
||||||
|
|
||||||
|
optional Type type = 3;
|
||||||
|
optional int32 type_id = 5;
|
||||||
|
|
||||||
|
optional Type vararg_element_type = 4;
|
||||||
|
optional int32 vararg_element_type_id = 6;
|
||||||
|
|
||||||
|
extensions 100 to 199;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TypeAlias {
|
||||||
|
/*
|
||||||
|
hasAnnotations
|
||||||
|
Visibility
|
||||||
|
*/
|
||||||
|
optional int32 flags = 1 [default = 6 /* public, no annotations */];
|
||||||
|
|
||||||
|
required int32 name = 2 [(name_id_in_table) = true];
|
||||||
|
|
||||||
|
repeated TypeParameter type_parameter = 3;
|
||||||
|
|
||||||
|
optional Type underlying_type = 4;
|
||||||
|
optional int32 underlying_type_id = 5;
|
||||||
|
|
||||||
|
optional Type expanded_type = 6;
|
||||||
|
optional int32 expanded_type_id = 7;
|
||||||
|
|
||||||
|
repeated Annotation annotation = 8;
|
||||||
|
|
||||||
|
extensions 100 to 199;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EnumEntry {
|
||||||
|
optional int32 name = 1 [(name_id_in_table) = true];
|
||||||
|
|
||||||
|
extensions 100 to 199;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Modality {
|
||||||
|
// 2 bits
|
||||||
|
FINAL = 0;
|
||||||
|
OPEN = 1;
|
||||||
|
ABSTRACT = 2;
|
||||||
|
SEALED = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Visibility {
|
||||||
|
// 3 bits
|
||||||
|
INTERNAL = 0;
|
||||||
|
PRIVATE = 1;
|
||||||
|
PROTECTED = 2;
|
||||||
|
PUBLIC = 3;
|
||||||
|
PRIVATE_TO_THIS = 4;
|
||||||
|
LOCAL = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MemberKind {
|
||||||
|
// 2 bits
|
||||||
|
DECLARATION = 0;
|
||||||
|
FAKE_OVERRIDE = 1;
|
||||||
|
DELEGATION = 2;
|
||||||
|
SYNTHESIZED = 3;
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
syntax = "proto2";
|
||||||
|
package org.jetbrains.kotlin.serialization;
|
||||||
|
|
||||||
|
import "org/jetbrains/kotlin/backend/konan/serialization/google_descriptor.proto1";
|
||||||
|
|
||||||
|
option java_outer_classname = "ExtOptionsProtoBuf";
|
||||||
|
|
||||||
|
extend google.protobuf.FieldOptions {
|
||||||
|
optional bool skip_in_comparison = 50000;
|
||||||
|
optional bool name_id_in_table = 50001;
|
||||||
|
optional bool fq_name_id_in_table = 50002;
|
||||||
|
optional bool string_id_in_table = 50003;
|
||||||
|
}
|
||||||
+621
@@ -0,0 +1,621 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// http://code.google.com/p/protobuf/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
//
|
||||||
|
// The messages in this file describe the definitions found in .proto files.
|
||||||
|
// A valid .proto file can be translated directly to a FileDescriptorProto
|
||||||
|
// without any other information (e.g. without reading its imports).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
syntax = "proto2";
|
||||||
|
package google.protobuf;
|
||||||
|
option java_package = "com.google.protobuf";
|
||||||
|
option java_outer_classname = "DescriptorProtos";
|
||||||
|
|
||||||
|
// descriptor.proto must be optimized for speed because reflection-based
|
||||||
|
// algorithms don't work during bootstrapping.
|
||||||
|
option optimize_for = SPEED;
|
||||||
|
|
||||||
|
// The protocol compiler can output a FileDescriptorSet containing the .proto
|
||||||
|
// files it parses.
|
||||||
|
message FileDescriptorSet {
|
||||||
|
repeated FileDescriptorProto file = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a complete .proto file.
|
||||||
|
message FileDescriptorProto {
|
||||||
|
optional string name = 1; // file name, relative to root of source tree
|
||||||
|
optional string package = 2; // e.g. "foo", "foo.bar", etc.
|
||||||
|
|
||||||
|
// Names of files imported by this file.
|
||||||
|
repeated string dependency = 3;
|
||||||
|
// Indexes of the public imported files in the dependency list above.
|
||||||
|
repeated int32 public_dependency = 10;
|
||||||
|
// Indexes of the weak imported files in the dependency list.
|
||||||
|
// For Google-internal migration only. Do not use.
|
||||||
|
repeated int32 weak_dependency = 11;
|
||||||
|
|
||||||
|
// All top-level definitions in this file.
|
||||||
|
repeated DescriptorProto message_type = 4;
|
||||||
|
repeated EnumDescriptorProto enum_type = 5;
|
||||||
|
repeated ServiceDescriptorProto service = 6;
|
||||||
|
repeated FieldDescriptorProto extension = 7;
|
||||||
|
|
||||||
|
optional FileOptions options = 8;
|
||||||
|
|
||||||
|
// This field contains optional information about the original source code.
|
||||||
|
// You may safely remove this entire field whithout harming runtime
|
||||||
|
// functionality of the descriptors -- the information is needed only by
|
||||||
|
// development tools.
|
||||||
|
optional SourceCodeInfo source_code_info = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a message type.
|
||||||
|
message DescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
|
||||||
|
repeated FieldDescriptorProto field = 2;
|
||||||
|
repeated FieldDescriptorProto extension = 6;
|
||||||
|
|
||||||
|
repeated DescriptorProto nested_type = 3;
|
||||||
|
repeated EnumDescriptorProto enum_type = 4;
|
||||||
|
|
||||||
|
message ExtensionRange {
|
||||||
|
optional int32 start = 1;
|
||||||
|
optional int32 end = 2;
|
||||||
|
}
|
||||||
|
repeated ExtensionRange extension_range = 5;
|
||||||
|
|
||||||
|
optional MessageOptions options = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a field within a message.
|
||||||
|
message FieldDescriptorProto {
|
||||||
|
enum Type {
|
||||||
|
// 0 is reserved for errors.
|
||||||
|
// Order is weird for historical reasons.
|
||||||
|
TYPE_DOUBLE = 1;
|
||||||
|
TYPE_FLOAT = 2;
|
||||||
|
// Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if
|
||||||
|
// negative values are likely.
|
||||||
|
TYPE_INT64 = 3;
|
||||||
|
TYPE_UINT64 = 4;
|
||||||
|
// Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if
|
||||||
|
// negative values are likely.
|
||||||
|
TYPE_INT32 = 5;
|
||||||
|
TYPE_FIXED64 = 6;
|
||||||
|
TYPE_FIXED32 = 7;
|
||||||
|
TYPE_BOOL = 8;
|
||||||
|
TYPE_STRING = 9;
|
||||||
|
TYPE_GROUP = 10; // Tag-delimited aggregate.
|
||||||
|
TYPE_MESSAGE = 11; // Length-delimited aggregate.
|
||||||
|
|
||||||
|
// New in version 2.
|
||||||
|
TYPE_BYTES = 12;
|
||||||
|
TYPE_UINT32 = 13;
|
||||||
|
TYPE_ENUM = 14;
|
||||||
|
TYPE_SFIXED32 = 15;
|
||||||
|
TYPE_SFIXED64 = 16;
|
||||||
|
TYPE_SINT32 = 17; // Uses ZigZag encoding.
|
||||||
|
TYPE_SINT64 = 18; // Uses ZigZag encoding.
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Label {
|
||||||
|
// 0 is reserved for errors
|
||||||
|
LABEL_OPTIONAL = 1;
|
||||||
|
LABEL_REQUIRED = 2;
|
||||||
|
LABEL_REPEATED = 3;
|
||||||
|
// TODO(sanjay): Should we add LABEL_MAP?
|
||||||
|
};
|
||||||
|
|
||||||
|
optional string name = 1;
|
||||||
|
optional int32 number = 3;
|
||||||
|
optional Label label = 4;
|
||||||
|
|
||||||
|
// If type_name is set, this need not be set. If both this and type_name
|
||||||
|
// are set, this must be either TYPE_ENUM or TYPE_MESSAGE.
|
||||||
|
optional Type type = 5;
|
||||||
|
|
||||||
|
// For message and enum types, this is the name of the type. If the name
|
||||||
|
// starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
|
||||||
|
// rules are used to find the type (i.e. first the nested types within this
|
||||||
|
// message are searched, then within the parent, on up to the root
|
||||||
|
// namespace).
|
||||||
|
optional string type_name = 6;
|
||||||
|
|
||||||
|
// For extensions, this is the name of the type being extended. It is
|
||||||
|
// resolved in the same manner as type_name.
|
||||||
|
optional string extendee = 2;
|
||||||
|
|
||||||
|
// For numeric types, contains the original text representation of the value.
|
||||||
|
// For booleans, "true" or "false".
|
||||||
|
// For strings, contains the default text contents (not escaped in any way).
|
||||||
|
// For bytes, contains the C escaped value. All bytes >= 128 are escaped.
|
||||||
|
// TODO(kenton): Base-64 encode?
|
||||||
|
optional string default_value = 7;
|
||||||
|
|
||||||
|
optional FieldOptions options = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes an enum type.
|
||||||
|
message EnumDescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
|
||||||
|
repeated EnumValueDescriptorProto value = 2;
|
||||||
|
|
||||||
|
optional EnumOptions options = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a value within an enum.
|
||||||
|
message EnumValueDescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
optional int32 number = 2;
|
||||||
|
|
||||||
|
optional EnumValueOptions options = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a service.
|
||||||
|
message ServiceDescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
repeated MethodDescriptorProto method = 2;
|
||||||
|
|
||||||
|
optional ServiceOptions options = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a method of a service.
|
||||||
|
message MethodDescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
|
||||||
|
// Input and output type names. These are resolved in the same way as
|
||||||
|
// FieldDescriptorProto.type_name, but must refer to a message type.
|
||||||
|
optional string input_type = 2;
|
||||||
|
optional string output_type = 3;
|
||||||
|
|
||||||
|
optional MethodOptions options = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Options
|
||||||
|
|
||||||
|
// Each of the definitions above may have "options" attached. These are
|
||||||
|
// just annotations which may cause code to be generated slightly differently
|
||||||
|
// or may contain hints for code that manipulates protocol messages.
|
||||||
|
//
|
||||||
|
// Clients may define custom options as extensions of the *Options messages.
|
||||||
|
// These extensions may not yet be known at parsing time, so the parser cannot
|
||||||
|
// store the values in them. Instead it stores them in a field in the *Options
|
||||||
|
// message called uninterpreted_option. This field must have the same name
|
||||||
|
// across all *Options messages. We then use this field to populate the
|
||||||
|
// extensions when we build a descriptor, at which point all protos have been
|
||||||
|
// parsed and so all extensions are known.
|
||||||
|
//
|
||||||
|
// Extension numbers for custom options may be chosen as follows:
|
||||||
|
// * For options which will only be used within a single application or
|
||||||
|
// organization, or for experimental options, use field numbers 50000
|
||||||
|
// through 99999. It is up to you to ensure that you do not use the
|
||||||
|
// same number for multiple options.
|
||||||
|
// * For options which will be published and used publicly by multiple
|
||||||
|
// independent entities, e-mail protobuf-global-extension-registry@google.com
|
||||||
|
// to reserve extension numbers. Simply provide your project name (e.g.
|
||||||
|
// Object-C plugin) and your porject website (if available) -- there's no need
|
||||||
|
// to explain how you intend to use them. Usually you only need one extension
|
||||||
|
// number. You can declare multiple options with only one extension number by
|
||||||
|
// putting them in a sub-message. See the Custom Options section of the docs
|
||||||
|
// for examples:
|
||||||
|
// http://code.google.com/apis/protocolbuffers/docs/proto.html#options
|
||||||
|
// If this turns out to be popular, a web service will be set up
|
||||||
|
// to automatically assign option numbers.
|
||||||
|
|
||||||
|
|
||||||
|
message FileOptions {
|
||||||
|
|
||||||
|
// Sets the Java package where classes generated from this .proto will be
|
||||||
|
// placed. By default, the proto package is used, but this is often
|
||||||
|
// inappropriate because proto packages do not normally start with backwards
|
||||||
|
// domain names.
|
||||||
|
optional string java_package = 1;
|
||||||
|
|
||||||
|
|
||||||
|
// If set, all the classes from the .proto file are wrapped in a single
|
||||||
|
// outer class with the given name. This applies to both Proto1
|
||||||
|
// (equivalent to the old "--one_java_file" option) and Proto2 (where
|
||||||
|
// a .proto always translates to a single class, but you may want to
|
||||||
|
// explicitly choose the class name).
|
||||||
|
optional string java_outer_classname = 8;
|
||||||
|
|
||||||
|
// If set true, then the Java code generator will generate a separate .java
|
||||||
|
// file for each top-level message, enum, and service defined in the .proto
|
||||||
|
// file. Thus, these types will *not* be nested inside the outer class
|
||||||
|
// named by java_outer_classname. However, the outer class will still be
|
||||||
|
// generated to contain the file's getDescriptor() method as well as any
|
||||||
|
// top-level extensions defined in the file.
|
||||||
|
optional bool java_multiple_files = 10 [default=false];
|
||||||
|
|
||||||
|
// If set true, then the Java code generator will generate equals() and
|
||||||
|
// hashCode() methods for all messages defined in the .proto file. This is
|
||||||
|
// purely a speed optimization, as the AbstractMessage base class includes
|
||||||
|
// reflection-based implementations of these methods.
|
||||||
|
optional bool java_generate_equals_and_hash = 20 [default=false];
|
||||||
|
|
||||||
|
// Generated classes can be optimized for speed or code size.
|
||||||
|
enum OptimizeMode {
|
||||||
|
SPEED = 1; // Generate complete code for parsing, serialization,
|
||||||
|
// etc.
|
||||||
|
CODE_SIZE = 2; // Use ReflectionOps to implement these methods.
|
||||||
|
LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
|
||||||
|
}
|
||||||
|
optional OptimizeMode optimize_for = 9 [default=SPEED];
|
||||||
|
|
||||||
|
// Sets the Go package where structs generated from this .proto will be
|
||||||
|
// placed. There is no default.
|
||||||
|
optional string go_package = 11;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Should generic services be generated in each language? "Generic" services
|
||||||
|
// are not specific to any particular RPC system. They are generated by the
|
||||||
|
// main code generators in each language (without additional plugins).
|
||||||
|
// Generic services were the only kind of service generation supported by
|
||||||
|
// early versions of proto2.
|
||||||
|
//
|
||||||
|
// Generic services are now considered deprecated in favor of using plugins
|
||||||
|
// that generate code specific to your particular RPC system. Therefore,
|
||||||
|
// these default to false. Old code which depends on generic services should
|
||||||
|
// explicitly set them to true.
|
||||||
|
optional bool cc_generic_services = 16 [default=false];
|
||||||
|
optional bool java_generic_services = 17 [default=false];
|
||||||
|
optional bool py_generic_services = 18 [default=false];
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MessageOptions {
|
||||||
|
// Set true to use the old proto1 MessageSet wire format for extensions.
|
||||||
|
// This is provided for backwards-compatibility with the MessageSet wire
|
||||||
|
// format. You should not use this for any other reason: It's less
|
||||||
|
// efficient, has fewer features, and is more complicated.
|
||||||
|
//
|
||||||
|
// The message must be defined exactly as follows:
|
||||||
|
// message Foo {
|
||||||
|
// option message_set_wire_format = true;
|
||||||
|
// extensions 4 to max;
|
||||||
|
// }
|
||||||
|
// Note that the message cannot have any defined fields; MessageSets only
|
||||||
|
// have extensions.
|
||||||
|
//
|
||||||
|
// All extensions of your type must be singular messages; e.g. they cannot
|
||||||
|
// be int32s, enums, or repeated messages.
|
||||||
|
//
|
||||||
|
// Because this is an option, the above two restrictions are not enforced by
|
||||||
|
// the protocol compiler.
|
||||||
|
optional bool message_set_wire_format = 1 [default=false];
|
||||||
|
|
||||||
|
// Disables the generation of the standard "descriptor()" accessor, which can
|
||||||
|
// conflict with a field of the same name. This is meant to make migration
|
||||||
|
// from proto1 easier; new code should avoid fields named "descriptor".
|
||||||
|
optional bool no_standard_descriptor_accessor = 2 [default=false];
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FieldOptions {
|
||||||
|
// The ctype option instructs the C++ code generator to use a different
|
||||||
|
// representation of the field than it normally would. See the specific
|
||||||
|
// options below. This option is not yet implemented in the open source
|
||||||
|
// release -- sorry, we'll try to include it in a future version!
|
||||||
|
optional CType ctype = 1 [default = STRING];
|
||||||
|
enum CType {
|
||||||
|
// Default mode.
|
||||||
|
STRING = 0;
|
||||||
|
|
||||||
|
CORD = 1;
|
||||||
|
|
||||||
|
STRING_PIECE = 2;
|
||||||
|
}
|
||||||
|
// The packed option can be enabled for repeated primitive fields to enable
|
||||||
|
// a more efficient representation on the wire. Rather than repeatedly
|
||||||
|
// writing the tag and type for each element, the entire array is encoded as
|
||||||
|
// a single length-delimited blob.
|
||||||
|
optional bool packed = 2;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Should this field be parsed lazily? Lazy applies only to message-type
|
||||||
|
// fields. It means that when the outer message is initially parsed, the
|
||||||
|
// inner message's contents will not be parsed but instead stored in encoded
|
||||||
|
// form. The inner message will actually be parsed when it is first accessed.
|
||||||
|
//
|
||||||
|
// This is only a hint. Implementations are free to choose whether to use
|
||||||
|
// eager or lazy parsing regardless of the value of this option. However,
|
||||||
|
// setting this option true suggests that the protocol author believes that
|
||||||
|
// using lazy parsing on this field is worth the additional bookkeeping
|
||||||
|
// overhead typically needed to implement it.
|
||||||
|
//
|
||||||
|
// This option does not affect the public interface of any generated code;
|
||||||
|
// all method signatures remain the same. Furthermore, thread-safety of the
|
||||||
|
// interface is not affected by this option; const methods remain safe to
|
||||||
|
// call from multiple threads concurrently, while non-const methods continue
|
||||||
|
// to require exclusive access.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Note that implementations may choose not to check required fields within
|
||||||
|
// a lazy sub-message. That is, calling IsInitialized() on the outher message
|
||||||
|
// may return true even if the inner message has missing required fields.
|
||||||
|
// This is necessary because otherwise the inner message would have to be
|
||||||
|
// parsed in order to perform the check, defeating the purpose of lazy
|
||||||
|
// parsing. An implementation which chooses not to check required fields
|
||||||
|
// must be consistent about it. That is, for any particular sub-message, the
|
||||||
|
// implementation must either *always* check its required fields, or *never*
|
||||||
|
// check its required fields, regardless of whether or not the message has
|
||||||
|
// been parsed.
|
||||||
|
optional bool lazy = 5 [default=false];
|
||||||
|
|
||||||
|
// Is this field deprecated?
|
||||||
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
|
// for accessors, or it will be completely ignored; in the very least, this
|
||||||
|
// is a formalization for deprecating fields.
|
||||||
|
optional bool deprecated = 3 [default=false];
|
||||||
|
|
||||||
|
// EXPERIMENTAL. DO NOT USE.
|
||||||
|
// For "map" fields, the name of the field in the enclosed type that
|
||||||
|
// is the key for this map. For example, suppose we have:
|
||||||
|
// message Item {
|
||||||
|
// required string name = 1;
|
||||||
|
// required string value = 2;
|
||||||
|
// }
|
||||||
|
// message Config {
|
||||||
|
// repeated Item items = 1 [experimental_map_key="name"];
|
||||||
|
// }
|
||||||
|
// In this situation, the map key for Item will be set to "name".
|
||||||
|
// TODO: Fully-implement this, then remove the "experimental_" prefix.
|
||||||
|
optional string experimental_map_key = 9;
|
||||||
|
|
||||||
|
// For Google-internal migration only. Do not use.
|
||||||
|
optional bool weak = 10 [default=false];
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EnumOptions {
|
||||||
|
|
||||||
|
// Set this option to false to disallow mapping different tag names to a same
|
||||||
|
// value.
|
||||||
|
optional bool allow_alias = 2 [default=true];
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EnumValueOptions {
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ServiceOptions {
|
||||||
|
|
||||||
|
// Note: Field numbers 1 through 32 are reserved for Google's internal RPC
|
||||||
|
// framework. We apologize for hoarding these numbers to ourselves, but
|
||||||
|
// we were already using them long before we decided to release Protocol
|
||||||
|
// Buffers.
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MethodOptions {
|
||||||
|
|
||||||
|
// Note: Field numbers 1 through 32 are reserved for Google's internal RPC
|
||||||
|
// framework. We apologize for hoarding these numbers to ourselves, but
|
||||||
|
// we were already using them long before we decided to release Protocol
|
||||||
|
// Buffers.
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// A message representing a option the parser does not recognize. This only
|
||||||
|
// appears in options protos created by the compiler::Parser class.
|
||||||
|
// DescriptorPool resolves these when building Descriptor objects. Therefore,
|
||||||
|
// options protos in descriptor objects (e.g. returned by Descriptor::options(),
|
||||||
|
// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
|
||||||
|
// in them.
|
||||||
|
message UninterpretedOption {
|
||||||
|
// The name of the uninterpreted option. Each string represents a segment in
|
||||||
|
// a dot-separated name. is_extension is true iff a segment represents an
|
||||||
|
// extension (denoted with parentheses in options specs in .proto files).
|
||||||
|
// E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
|
||||||
|
// "foo.(bar.baz).qux".
|
||||||
|
message NamePart {
|
||||||
|
required string name_part = 1;
|
||||||
|
required bool is_extension = 2;
|
||||||
|
}
|
||||||
|
repeated NamePart name = 2;
|
||||||
|
|
||||||
|
// The value of the uninterpreted option, in whatever type the tokenizer
|
||||||
|
// identified it as during parsing. Exactly one of these should be set.
|
||||||
|
optional string identifier_value = 3;
|
||||||
|
optional uint64 positive_int_value = 4;
|
||||||
|
optional int64 negative_int_value = 5;
|
||||||
|
optional double double_value = 6;
|
||||||
|
optional bytes string_value = 7;
|
||||||
|
optional string aggregate_value = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Optional source code info
|
||||||
|
|
||||||
|
// Encapsulates information about the original source file from which a
|
||||||
|
// FileDescriptorProto was generated.
|
||||||
|
message SourceCodeInfo {
|
||||||
|
// A Location identifies a piece of source code in a .proto file which
|
||||||
|
// corresponds to a particular definition. This information is intended
|
||||||
|
// to be useful to IDEs, code indexers, documentation generators, and similar
|
||||||
|
// tools.
|
||||||
|
//
|
||||||
|
// For example, say we have a file like:
|
||||||
|
// message Foo {
|
||||||
|
// optional string foo = 1;
|
||||||
|
// }
|
||||||
|
// Let's look at just the field definition:
|
||||||
|
// optional string foo = 1;
|
||||||
|
// ^ ^^ ^^ ^ ^^^
|
||||||
|
// a bc de f ghi
|
||||||
|
// We have the following locations:
|
||||||
|
// span path represents
|
||||||
|
// [a,i) [ 4, 0, 2, 0 ] The whole field definition.
|
||||||
|
// [a,b) [ 4, 0, 2, 0, 4 ] The label (optional).
|
||||||
|
// [c,d) [ 4, 0, 2, 0, 5 ] The type (string).
|
||||||
|
// [e,f) [ 4, 0, 2, 0, 1 ] The name (foo).
|
||||||
|
// [g,h) [ 4, 0, 2, 0, 3 ] The number (1).
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
// - A location may refer to a repeated field itself (i.e. not to any
|
||||||
|
// particular index within it). This is used whenever a set of elements are
|
||||||
|
// logically enclosed in a single code segment. For example, an entire
|
||||||
|
// extend block (possibly containing multiple extension definitions) will
|
||||||
|
// have an outer location whose path refers to the "extensions" repeated
|
||||||
|
// field without an index.
|
||||||
|
// - Multiple locations may have the same path. This happens when a single
|
||||||
|
// logical declaration is spread out across multiple places. The most
|
||||||
|
// obvious example is the "extend" block again -- there may be multiple
|
||||||
|
// extend blocks in the same scope, each of which will have the same path.
|
||||||
|
// - A location's span is not always a subset of its parent's span. For
|
||||||
|
// example, the "extendee" of an extension declaration appears at the
|
||||||
|
// beginning of the "extend" block and is shared by all extensions within
|
||||||
|
// the block.
|
||||||
|
// - Just because a location's span is a subset of some other location's span
|
||||||
|
// does not mean that it is a descendent. For example, a "group" defines
|
||||||
|
// both a type and a field in a single declaration. Thus, the locations
|
||||||
|
// corresponding to the type and field and their components will overlap.
|
||||||
|
// - Code which tries to interpret locations should probably be designed to
|
||||||
|
// ignore those that it doesn't understand, as more types of locations could
|
||||||
|
// be recorded in the future.
|
||||||
|
repeated Location location = 1;
|
||||||
|
message Location {
|
||||||
|
// Identifies which part of the FileDescriptorProto was defined at this
|
||||||
|
// location.
|
||||||
|
//
|
||||||
|
// Each element is a field number or an index. They form a path from
|
||||||
|
// the root FileDescriptorProto to the place where the definition. For
|
||||||
|
// example, this path:
|
||||||
|
// [ 4, 3, 2, 7, 1 ]
|
||||||
|
// refers to:
|
||||||
|
// file.message_type(3) // 4, 3
|
||||||
|
// .field(7) // 2, 7
|
||||||
|
// .name() // 1
|
||||||
|
// This is because FileDescriptorProto.message_type has field number 4:
|
||||||
|
// repeated DescriptorProto message_type = 4;
|
||||||
|
// and DescriptorProto.field has field number 2:
|
||||||
|
// repeated FieldDescriptorProto field = 2;
|
||||||
|
// and FieldDescriptorProto.name has field number 1:
|
||||||
|
// optional string name = 1;
|
||||||
|
//
|
||||||
|
// Thus, the above path gives the location of a field name. If we removed
|
||||||
|
// the last element:
|
||||||
|
// [ 4, 3, 2, 7 ]
|
||||||
|
// this path refers to the whole field declaration (from the beginning
|
||||||
|
// of the label to the terminating semicolon).
|
||||||
|
repeated int32 path = 1 [packed=true];
|
||||||
|
|
||||||
|
// Always has exactly three or four elements: start line, start column,
|
||||||
|
// end line (optional, otherwise assumed same as start line), end column.
|
||||||
|
// These are packed into a single field for efficiency. Note that line
|
||||||
|
// and column numbers are zero-based -- typically you will want to add
|
||||||
|
// 1 to each before displaying to a user.
|
||||||
|
repeated int32 span = 2 [packed=true];
|
||||||
|
|
||||||
|
// If this SourceCodeInfo represents a complete declaration, these are any
|
||||||
|
// comments appearing before and after the declaration which appear to be
|
||||||
|
// attached to the declaration.
|
||||||
|
//
|
||||||
|
// A series of line comments appearing on consecutive lines, with no other
|
||||||
|
// tokens appearing on those lines, will be treated as a single comment.
|
||||||
|
//
|
||||||
|
// Only the comment content is provided; comment markers (e.g. //) are
|
||||||
|
// stripped out. For block comments, leading whitespace and an asterisk
|
||||||
|
// will be stripped from the beginning of each line other than the first.
|
||||||
|
// Newlines are included in the output.
|
||||||
|
//
|
||||||
|
// Examples:
|
||||||
|
//
|
||||||
|
// optional int32 foo = 1; // Comment attached to foo.
|
||||||
|
// // Comment attached to bar.
|
||||||
|
// optional int32 bar = 2;
|
||||||
|
//
|
||||||
|
// optional string baz = 3;
|
||||||
|
// // Comment attached to baz.
|
||||||
|
// // Another line attached to baz.
|
||||||
|
//
|
||||||
|
// // Comment attached to qux.
|
||||||
|
// //
|
||||||
|
// // Another line attached to qux.
|
||||||
|
// optional double qux = 4;
|
||||||
|
//
|
||||||
|
// optional string corge = 5;
|
||||||
|
// /* Block comment attached
|
||||||
|
// * to corge. Leading asterisks
|
||||||
|
// * will be removed. */
|
||||||
|
// /* Block comment attached to
|
||||||
|
// * grault. */
|
||||||
|
// optional int32 grault = 6;
|
||||||
|
optional string leading_comments = 3;
|
||||||
|
optional string trailing_comments = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ allprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
convention.plugins.clangFlags = new ClangFlags(new PlatformInfo(), "$llvmDir")
|
convention.plugins.clangFlags = new ClangFlags(new PlatformInfo(), "$llvmDir")
|
||||||
ext.clangPath = ["$llvmDir/bin"]
|
ext.clangPath = ["$llvmDir/bin"]
|
||||||
ext.clangArgs = []
|
ext.clangArgs = []
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ static const unsigned char kDecode[] = {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int Base64Encode(
|
int EncodeBase64(
|
||||||
const void* dataBuf, uint32_t dataLength, void* resultBuf, uint32_t resultSize) {
|
const void* dataBuf, uint32_t dataLength, void* resultBuf, uint32_t resultSize) {
|
||||||
char *result = reinterpret_cast<char*>(resultBuf);
|
char *result = reinterpret_cast<char*>(resultBuf);
|
||||||
const uint8_t *data = reinterpret_cast<const uint8_t*>(dataBuf);
|
const uint8_t *data = reinterpret_cast<const uint8_t*>(dataBuf);
|
||||||
@@ -113,7 +113,7 @@ int Base64Encode(
|
|||||||
return 0; /* indicate success */
|
return 0; /* indicate success */
|
||||||
}
|
}
|
||||||
|
|
||||||
int Base64Decode(
|
int DecodeBase64(
|
||||||
const char *in, uint32_t inLen, void* outBuf, uint32_t* outLen) {
|
const char *in, uint32_t inLen, void* outBuf, uint32_t* outLen) {
|
||||||
uint8_t* out = reinterpret_cast<uint8_t*>(outBuf);
|
uint8_t* out = reinterpret_cast<uint8_t*>(outBuf);
|
||||||
const char* end = in + inLen;
|
const char* end = in + inLen;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ constexpr uint32_t PrintableBase64Size(uint32_t input_length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PrintableBase64(const uint8_t* data, uint32_t data_length, char* base64) {
|
void PrintableBase64(const uint8_t* data, uint32_t data_length, char* base64) {
|
||||||
int rv = Base64Encode(data, data_length, base64, PrintableBase64Size(data_length));
|
int rv = EncodeBase64(data, data_length, base64, PrintableBase64Size(data_length));
|
||||||
assert(rv == 0);
|
assert(rv == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int Base64Encode(
|
int EncodeBase64(
|
||||||
const void* input, uint32_t inputLen, void* output, uint32_t outputLen);
|
const void* input, uint32_t inputLen, void* output, uint32_t outputLen);
|
||||||
|
|
||||||
int Base64Decode(
|
int DecodeBase64(
|
||||||
const char* input, uint32_t inputLen, void* output, uint32_t* outputLen);
|
const char* input, uint32_t inputLen, void* output, uint32_t* outputLen);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -10,4 +10,9 @@ package konan.internal
|
|||||||
*/
|
*/
|
||||||
//@Target(AnnotationTarget.FUNCTION)
|
//@Target(AnnotationTarget.FUNCTION)
|
||||||
//@Retention(AnnotationRetention.SOURCE)
|
//@Retention(AnnotationRetention.SOURCE)
|
||||||
annotation class ExportForCppRuntime(val name: String = "")
|
annotation class ExportForCppRuntime(val name: String = "")
|
||||||
|
|
||||||
|
// This one is used internally to mark the presence of a backing field
|
||||||
|
// in the absence of IR.
|
||||||
|
annotation class HasBackingField
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user