@@ -12,14 +12,19 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
12
12
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
13
13
import org.jetbrains.kotlin.config.AnalysisFlags
14
14
import org.jetbrains.kotlin.config.languageVersionSettings
15
+ import org.jetbrains.kotlin.descriptors.ClassKind
16
+ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
15
17
import org.jetbrains.kotlin.ir.backend.js.lower.calls.EnumIntrinsicsUtils
16
18
import org.jetbrains.kotlin.ir.backend.js.utils.erasedUpperBound
17
19
import org.jetbrains.kotlin.ir.backend.js.utils.isEqualsInheritedFromAny
18
20
import org.jetbrains.kotlin.ir.builders.*
21
+ import org.jetbrains.kotlin.ir.declarations.IrConstructor
19
22
import org.jetbrains.kotlin.ir.declarations.IrFile
20
23
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
21
24
import org.jetbrains.kotlin.ir.expressions.IrCall
22
25
import org.jetbrains.kotlin.ir.expressions.IrExpression
26
+ import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
27
+ import org.jetbrains.kotlin.ir.expressions.putClassTypeArgument
23
28
import org.jetbrains.kotlin.ir.util.toIrConst
24
29
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
25
30
import org.jetbrains.kotlin.ir.types.*
@@ -157,35 +162,35 @@ class BuiltInsLowering(val context: WasmBackendContext) : FileLoweringPass {
157
162
val newSymbol = irBuiltins.suspendFunctionN(arity).getSimpleFunction(" invoke" )!!
158
163
return irCall(call, newSymbol, argumentsAsReceivers = true )
159
164
}
160
- symbols .reflectionSymbols.getClassData -> {
165
+ context .reflectionSymbols.getKClass -> {
161
166
val type = call.getTypeArgument(0 )!!
162
167
val klass = type.classOrNull?.owner ? : error(" Invalid type" )
163
168
164
- val typeId = builder.irCall(symbols.wasmTypeId).also {
165
- it.putTypeArgument(0 , type)
169
+ val constructorArgument: IrExpression
170
+ val kclassConstructor: IrConstructor
171
+ if (klass.isEffectivelyExternal()) {
172
+ check(context.configuration.get(JSConfigurationKeys .WASM_TARGET , WasmTarget .JS ) == WasmTarget .JS ) { " External classes reflection in WASI mode are not supported" }
173
+ kclassConstructor = symbols.jsRelatedSymbols.kExternalClassImpl.owner.constructors.first()
174
+ constructorArgument = getExternalKClassCtorArgument(type, builder)
175
+ } else {
176
+ kclassConstructor = symbols.reflectionSymbols.kClassImpl.owner.constructors.first()
177
+ constructorArgument = getKClassCtorArgument(type, builder)
166
178
}
167
179
168
- if (! klass.isInterface) {
169
- return builder.irCall(context.wasmSymbols.reflectionSymbols.getTypeInfoTypeDataByPtr).also {
170
- it.putValueArgument(0 , typeId)
171
- }
172
- } else {
173
- val infoDataCtor = symbols.reflectionSymbols.wasmTypeInfoData.constructors.first()
174
- val fqName = type.classFqName!!
175
- val fqnShouldBeEmitted =
176
- context.configuration.languageVersionSettings.getFlag(AnalysisFlags .allowFullyQualifiedNameInKClass)
177
- val packageName = if (fqnShouldBeEmitted) fqName.parentOrNull()?.asString() ? : " " else " "
178
- val typeName = fqName.shortName().asString()
179
-
180
- return with (builder) {
181
- irCallConstructor(infoDataCtor, emptyList()).also {
182
- it.putValueArgument(0 , typeId)
183
- it.putValueArgument(1 , packageName.toIrConst(context.irBuiltIns.stringType))
184
- it.putValueArgument(2 , typeName.toIrConst(context.irBuiltIns.stringType))
185
- }
186
- }
180
+ return IrConstructorCallImpl (
181
+ startOffset = UNDEFINED_OFFSET ,
182
+ endOffset = UNDEFINED_OFFSET ,
183
+ type = kclassConstructor.returnType,
184
+ symbol = kclassConstructor.symbol,
185
+ typeArgumentsCount = 1 ,
186
+ valueArgumentsCount = 1 ,
187
+ constructorTypeArgumentsCount = 0
188
+ ).also {
189
+ it.putClassTypeArgument(0 , type)
190
+ it.putValueArgument(0 , constructorArgument)
187
191
}
188
192
}
193
+
189
194
symbols.enumValueOfIntrinsic ->
190
195
return EnumIntrinsicsUtils .transformEnumValueOfIntrinsic(call)
191
196
symbols.enumValuesIntrinsic ->
@@ -197,6 +202,40 @@ class BuiltInsLowering(val context: WasmBackendContext) : FileLoweringPass {
197
202
return call
198
203
}
199
204
205
+ private fun getKClassCtorArgument (type : IrType , builder : DeclarationIrBuilder ): IrExpression {
206
+ val klass = type.classOrNull?.owner ? : error(" Invalid type" )
207
+
208
+ val typeId = builder.irCall(symbols.wasmTypeId).also {
209
+ it.putTypeArgument(0 , type)
210
+ }
211
+
212
+ if (! klass.isInterface) {
213
+ return builder.irCall(context.wasmSymbols.reflectionSymbols.getTypeInfoTypeDataByPtr).also {
214
+ it.putValueArgument(0 , typeId)
215
+ }
216
+ } else {
217
+ val fqName = type.classFqName!!
218
+ val fqnShouldBeEmitted =
219
+ context.configuration.languageVersionSettings.getFlag(AnalysisFlags .allowFullyQualifiedNameInKClass)
220
+ val packageName = if (fqnShouldBeEmitted) fqName.parentOrNull()?.asString() ? : " " else " "
221
+ val typeName = fqName.shortName().asString()
222
+
223
+ return builder.irCallConstructor(symbols.reflectionSymbols.wasmTypeInfoData.constructors.first(), emptyList()).also {
224
+ it.putValueArgument(0 , typeId)
225
+ it.putValueArgument(1 , packageName.toIrConst(context.irBuiltIns.stringType))
226
+ it.putValueArgument(2 , typeName.toIrConst(context.irBuiltIns.stringType))
227
+ }
228
+ }
229
+ }
230
+
231
+ private fun getExternalKClassCtorArgument (type : IrType , builder : DeclarationIrBuilder ): IrExpression {
232
+ val klass = type.classOrNull?.owner ? : error(" Invalid type" )
233
+ check(klass.kind != ClassKind .INTERFACE ) { " External interface must not be a class literal" }
234
+ val classGetClassFunction = context.mapping.wasmGetJsClass[klass]!!
235
+ val wrappedGetClassIfAny = context.mapping.wasmJsInteropFunctionToWrapper[classGetClassFunction] ? : classGetClassFunction
236
+ return builder.irCall(wrappedGetClassIfAny)
237
+ }
238
+
200
239
override fun lower (irFile : IrFile ) {
201
240
val builder = context.createIrBuilder(irFile.symbol)
202
241
irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext () {
0 commit comments