Compare commits

..

195 Commits

Author SHA1 Message Date
Ilya Gorbunov
4fd6dcd063 Turn progressive mode on with the gradle parameter test.progressive.mode 2018-07-03 05:10:24 +03:00
Ilya Gorbunov
3c86e40bcb Fix WITH_UNSIGNED directive in noBoxingOperationsOnNonTrivialSpread 2018-07-03 03:52:18 +03:00
Ilya Gorbunov
16fb5f6901 Set language and api versions automatically for unsigned types box tests
Remove InlineClasses feature directive from tests
2018-07-03 03:52:18 +03:00
Ilya Gorbunov
181a8d7d6a Extract default language version settings for diagnostics tests
And override it in unsigned types diagnostics tests.
Remove InlineClasses feature directive from tests, because it's already
enabled in that language version.
2018-07-03 03:52:18 +03:00
Ilya Gorbunov
3349976279 Make MIN_VALUE and MAX_VALUE of unsigned types actual constants 2018-07-03 03:52:18 +03:00
Ilya Gorbunov
7a208c3e01 Simplify unsigned array constructor functions 2018-07-03 03:52:18 +03:00
Ilya Gorbunov
615f57f2fc Compile unsigned types sourceset with 1.3 and annotate them with SinceKotlin("1.3") 2018-07-03 03:52:18 +03:00
Ilya Gorbunov
a72ad8b267 Advance bootstrap to 1.2.70-dev-23 2018-07-03 03:52:18 +03:00
Alexey Tsvetkov
1dea01a479 Build: remove testRuntime dependency on ":kotlin-compiler:dist" 2018-07-02 22:36:35 +03:00
Alexey Sedunov
03ed4e39e3 Search Everywhere: Recover original behavior for non-functions
#KT-25189 Fixed
2018-07-02 20:18:21 +03:00
Alexander Udalov
e4af8dc7d8 Improve reflection error message when function/property is not found 2018-07-02 18:49:09 +02:00
Alexander Udalov
4f2fdd1c01 Load all resources in RuntimePackagePartProvider; optimize code
The issue was reproducible when the same package is present in different
modules with the same -module-name (which is a popular case of src/test
roots in simple IDEA projects). The problem was in the fact that several
resource files containing package name mapping with the same name were
present in the classpath, but RuntimePackagePartProvider only considered
the first one. The fix is to use getResources instead of
getResourceAsStream and handle each returned resource.

Also, optimize internal representation to store the mapping in the form
which is the most convenient for findPackageParts, which should be
faster than registerModule because in theory, it's called more often.

 #KT-21973 Fixed
 #KT-24651
2018-07-02 18:49:09 +02:00
Alexander Udalov
8ccbbf71ec Remove obsolete BuiltInFunction and mapIntrinsicFunctionSignature
This is now fully covered by the JVM signature mapping, introduced in
the previous commit. The change in KDeclarationContainerImpl.methodOwner
is needed because primitive classes have no methods on JVM; and when
we're looking for "Int.equals", we'll now look it up in the Class object
for java.lang.Integer, not for the primitive int.
2018-07-02 18:49:08 +02:00
Alexander Udalov
4266e50be8 Use manual type mapping in reflection for members from built-ins
There are cases when members deserialized from JVM classes have no JVM
signature in the proto. For example, if a member is inherited from a
built-in class (such as Map.getOrDefault in some Map implementations),
or if a member is synthesized in the compiler front-end and back-end
separately (such as enum values/valueOf). In these cases, we'll use the
naive type mapping to try to recover the signature.

 #KT-16616 Fixed
 #KT-17542 Fixed
2018-07-02 18:49:08 +02:00
Alexander Udalov
a7c80f2df1 Reformat module reflection.jvm, fix inspections/warnings 2018-07-02 18:49:08 +02:00
Alexander Udalov
25ee67a644 Catch SecurityException when reading system property in BitEncoding
This does not fix KT-15167 though because the exception from KT-20575 is
thrown shortly afterwards

 #KT-15167
2018-07-02 18:49:08 +02:00
Alexander Udalov
42de05f3fa Improve diagnostic for missing BuiltInsLoader implementation
Also initialize it lazily to avoid wrapping the exception into
ExceptionInInitializerError

 #KT-20575
2018-07-02 18:49:08 +02:00
Alexander Udalov
50c515deca Do not serialize constructors for anonymous objects
The only client of this data is reflection, and since anonymous objects
do not have constructors in the source code, they shouldn't in
reflection as well

 #KT-20442 Fixed
2018-07-02 18:49:08 +02:00
Alexander Udalov
17fc41e0f9 Do not create primary constructor for enum entry synthetic class
The change in DescriptorSerializer is needed so that serialized protos
of enum entry classes which are resolved in sources
(LazyClassDescriptor) and are deserialized from binaries
(EnumEntrySyntheticClassDescriptor) are the same. There are tests on
incremental compilation in JS that check that the serialized proto is
exactly the same after rebuild and after an incremental build.

 #KT-22048 Fixed
2018-07-02 18:49:08 +02:00
Alexey Sedunov
b52b07ec79 Test Support: KT-22306
Do not show run markers in JS modules when no relevant run configurations are available

 #KT-22306 Fixed
2018-07-02 19:15:52 +03:00
Alexey Sedunov
3e91346240 Rename: Fix processing of references to synthetic Java properties
Fixes for non-master-bunch plugin.xml
2018-07-02 19:15:51 +03:00
Alexey Sedunov
22d74276a0 Misc: Configure stdlib in failing tests 2018-07-02 19:08:10 +03:00
Alexey Sedunov
65dad5eb74 Misc: Fix test assertion 2018-07-02 19:08:10 +03:00
Mikhail Zarechenskiy
59567c8012 Improve exception message to detect actual problem
This relates to EA-120082, EA-119637
2018-07-02 16:12:39 +03:00
Mikhail Zarechenskiy
2e88f5c47d Prohibit operator mod as declaration and calls that resolved via it
#KT-24197 Fixed
2018-07-02 16:12:36 +03:00
Roman Artemev
c887b88ed9 Fix coroutine test generator 2018-07-02 15:35:02 +03:00
Nikolay Krasko
f1a44ed1a4 Allow to disable bad format inspection for unchanged files (KT-25199)
#KT-25199 Fixed
2018-07-02 15:06:47 +03:00
Nikolay Krasko
30a2969887 Move KotlinCleanupInspection to Migration group 2018-07-02 15:06:47 +03:00
Denis Zharkov
3b968351bb Load Java overrides of Kotlin suspend functions as suspend, too
There's still some blind spots:
- Covariant overrides in Java (KT-25036)
- Current implementation assumes that when language version is 1.3 every suspend function
reference only release-coroutines-package Continuation
(we need to check if it's a correct statement)

 #KT-24848 Fixed
 #KT-25036 Open
2018-07-02 14:14:59 +03:00
Denis Zharkov
0fc9bb3f4a Minor. Reformat LazyJavaClassMemberScope.kt 2018-07-02 14:14:59 +03:00
Mikhail Zarechenskiy
de60c9b635 Fix language features in tests for gradual migration to 1.3 version 2018-07-02 12:13:11 +03:00
Vyacheslav Gerasimov
931ebb4c3c as32: Limit until-build to prevent installation on AS 3.3 2018-07-01 00:09:21 +03:00
Alexey Tsvetkov
ece991639e Do not compile jps tests for android studio
I accidentally enabled compilation in one of my previous commits
2018-06-29 20:16:53 +03:00
Ilya Gorbunov
bed26dc700 Fix local delegated property smartcast usage 2018-06-29 20:11:03 +03:00
Nicolay Mitropolsky
80f022c3d5 182: IDEA sdk set to 182.3458.5 2018-06-29 16:42:44 +03:00
Dmitry Petrov
bbcb12ea4b samAdapter test doesn't actually need FULL_JDK 2018-06-29 14:27:57 +03:00
Dmitry Petrov
92430fc63a Update testData for JS_IR tests 2018-06-29 14:23:09 +03:00
Dmitry Petrov
38e9c86443 Update testData for irCfg and sourceRanges tests 2018-06-29 14:01:54 +03:00
Dmitry Petrov
f0050930b5 Add ":compiler:ir.backend.common" to compilerModules 2018-06-29 11:24:46 +03:00
Mikhael Bogdanov
da0a966d65 Initialize return type and use unit type in IrDelegationConstructorCall
(cherry picked from commit faac924)
2018-06-29 11:24:46 +03:00
Mikhael Bogdanov
7bd5031eaf Fix array check
(cherry picked from commit e662f82)
2018-06-29 11:24:46 +03:00
Dmitry Petrov
b1d0a5e807 Fix delegated function body generation 2018-06-29 11:24:46 +03:00
Dmitry Petrov
71c5bf0b97 Fix annotation copying for IrValueParameters 2018-06-29 11:24:46 +03:00
Dmitry Petrov
799fcc2606 Fix IrType rendering, update testData 2018-06-29 11:24:46 +03:00
Dmitry Petrov
7fd3fac122 Minor: fix after rebase 2018-06-29 11:24:46 +03:00
Mikhael Bogdanov
2a721ea0f6 Fix EnumClassLowering
(cherry picked from commit 1aa7e1a)
2018-06-29 11:24:46 +03:00
Mikhael Bogdanov
95d72d0a32 Fix unbound symbol problem
Make property initialization non-lazy to bind owner by general mechanism

(cherry picked from commit eec6c18)
2018-06-29 11:24:46 +03:00
Mikhael Bogdanov
ba9f12b617 Use original descriptor for property stub generation
(cherry picked from commit 1a9f242)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
068859eece Minor: use right type for null literal
(cherry picked from commit 88c824b)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
56bf1f895c Mute failed test for JS IR BE
(cherry picked from commit 6d379a6)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
15f33dd94a Unmute some tests for JS IR BE
(cherry picked from commit 04a9622)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
bf2aa5263e JS IR BE: migrate to IR types
(cherry picked from commit 064f47b)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
952163b2fb IR: define references to Throwable, KCallable and KProperty classes inside IrBuiltIns
(cherry picked from commit f92bda0)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
92407c509f IR BE common: add KotlinType based utils
(cherry picked from commit d8be3a6)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
686a3d631c IR BE common: provide type arguments count explicitly for ir calls to reduce dependency on descriptors
(cherry picked from commit af76ae2)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
f002e6030a IR BE common: use another ctor of IrGetValueImpl in LocalDeclarationsLowering
(cherry picked from commit 7e34d6e)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
d5906dd584 IR BE common: fix InnerClassesLowering
(cherry picked from commit 4239a5f)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
072804af52 ir.tree: uncomment and fix IrFunction.createParameterDeclarations
(cherry picked from commit af8b4be)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
6bc86bd42f IR: add ClassifierDescriptor.toIrType and KotlinType.toIrType
(cherry picked from commit 3e09659)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
fa51b962b8 IR: return original KotlinType from IrTupe.toKotlinType() when it possible instead of creating new one
(cherry picked from commit e3b921a)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
1c2ac364c7 IR: add more predicates on IrType
(cherry picked from commit 5cf136c)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
17454d3f9c ir.tree: fix return type of IrMemberAccessExpression.getTypeArgumentOrDefault
(cherry picked from commit 9e7661f)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
576dfda3a8 IrTypes: fix translating for Dynamic type
(cherry picked from commit bd04b46)
2018-06-29 11:24:46 +03:00
Mikhael Bogdanov
ecb5d29130 Add additional IrFunction constructor with custom visibility and modality
(cherry picked from commit 0664d77)
2018-06-29 11:24:46 +03:00
Mikhael Bogdanov
3063de82aa Fix JVM BE IR part
(cherry picked from commit 5e55040)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
1d67cd3b97 IR: add ir.backend.common to jvm backend dependencies
(cherry picked from commit 0776e3d)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
9bcc3cae79 IR Tree: add overloads for irCall and IrGetValueImpl
(cherry picked from commit 1420fc5)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
80b6d84c72 Add dependency: backend.js -> ir.backend.common
(cherry picked from commit a8b02f8)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
7e9cf64754 KJS: don't use onlyIf from ir/backend.common
(cherry picked from commit 34574a9)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
49f2598907 IrTypes: fix ir2cfg
(cherry picked from commit cf162c7)
2018-06-29 11:24:46 +03:00
Zalim Bashorov
ea7b344b80 Use IrType in IrSuspensionPointImpl and IrSuspendableExpressionImpl
(cherry picked from commit 06e1728)
2018-06-29 11:24:46 +03:00
Dmitry Petrov
d5286874bd Fix circular dependency: TypeTranslator <-> ConstantValueGenerator
TODO proper DI?
2018-06-29 11:24:46 +03:00
Dmitry Petrov
ede3a34baa Temporary fix for IR2CFG: use originalKotlinType 2018-06-29 11:24:46 +03:00
Dmitry Petrov
15eafc1513 IrTypes: IrSuspensionPoint, IrSuspendableExpression update 2018-06-29 11:24:46 +03:00
Svyatoslav Scherbina
b11abeed6a IrTypes: migrate some code from backend.common
(cherry picked from commit 3788130)
2018-06-29 11:24:46 +03:00
Svyatoslav Scherbina
f1bdb48a76 IrTypes: comment backend.common code to be migrated by someone else
(cherry picked from commit 0491fc4)
2018-06-29 11:24:46 +03:00
Svyatoslav Scherbina
25d0c57194 backend.common: remove obsolete lowerings
(cherry picked from commit 5d6b9c7)
2018-06-29 11:24:46 +03:00
Svyatoslav Scherbina
17312a305b psi2ir: fix type for IrGetField(delegate) when generating delegation
(cherry picked from commit 7601cc2)
2018-06-29 11:24:46 +03:00
Svyatoslav Scherbina
56fdf2c735 psi2ir: fix null support in 'promoteToPrimitiveNumericType'
(cherry picked from commit 9b2a637)
2018-06-29 11:24:46 +03:00
Svyatoslav Scherbina
0b4d9513eb psi2ir: fix generating fake override for property with type parameters
(cherry picked from commit 2051177)
2018-06-29 11:24:46 +03:00
Svyatoslav Scherbina
be413e4fab psi2ir: don't generate accessor type parameter supertypes twice
(cherry picked from commit 22e6d5f)
2018-06-29 11:24:46 +03:00
Dmitry Petrov
a9d0e6d3da IrTypes: generateAnnotationConstructorCall -> ConstantValueGenerator 2018-06-29 11:24:46 +03:00
Dmitry Petrov
3a11767fae IrTypes: use proper scope for type parameters in stub generation 2018-06-29 11:24:46 +03:00
Svyatoslav Scherbina
f837537cb6 IrTypes: fix multiple issues in psi2ir 2018-06-29 11:24:46 +03:00
Svyatoslav Scherbina
35cf7c4db3 Expose transformAnnotations from DeepCopyIrTree 2018-06-29 11:24:46 +03:00
Dmitry Petrov
d1b6e8901a Minor: IrTypes: fix after rebase 2018-06-29 11:24:46 +03:00
Dmitry Petrov
2d9ae6e93e IrTypes: approximate only non-denotable Kotlin types 2018-06-29 11:24:46 +03:00
Dmitry Petrov
93f4a4da10 IrTypes: star projections
Initial implementation, mostly to avoid infinite recursion in cases such
as 'Enum<*>'.
2018-06-29 11:24:46 +03:00
Dmitry Petrov
5b3947da11 IrTypes: Fix type arguments mapping for properties 2018-06-29 11:24:46 +03:00
Dmitry Petrov
7497372f65 IrTypes: IrProperty has no type of its own
Within the current scheme, type parameters for IrProperty become type
parameters for getter and setter (and, since only extension properties
can have type parameters, backing field's type can't depend on type
parameters; see also KT-24643). Either properties themselves can have
type parameters of their own (for the sake of representing the property
type), or properties don't have types and don't have type parameters.
2018-06-29 11:24:46 +03:00
Dmitry Petrov
ad65fa8c45 IrTypes: IrTypeParameter.superTypes can depend on type parameters
IrTypeParameter.superTypes can depend on type parameters and thus should
be initialized with type parameters in scope.
2018-06-29 11:24:46 +03:00
Dmitry Petrov
eb6f652763 IrTypes: IrClass.superTypes can depend on type parameters
IrClass.superTypes can depend on type parameters of a class and thus
should be initialized after type parameters are in put in scope.
2018-06-29 11:24:46 +03:00
Dmitry Petrov
8ae17ecbcb IrTypes: IrFunction.returnType can depend on type parameters
Function return type can depend on function type parameters and should
be initialized with type parameters in scope.
2018-06-29 11:24:46 +03:00
Dmitry Petrov
847223683e Minor: IrTypes: fix after rebase 2018-06-29 11:24:46 +03:00
Dmitry Petrov
0ffef64428 IrTypes: IrClass.superTypes, IrTypeParameter.superTypes 2018-06-29 11:24:46 +03:00
Dmitry Petrov
353076f596 compiler/ir/backend.common is NOT a part of compiler/backend-common 2018-06-29 11:24:46 +03:00
Dmitry Petrov
25a66916a6 IrTypes: minor: pass generator context where required 2018-06-29 11:24:46 +03:00
Dmitry Petrov
6649ef2740 IrTypes required to declare symbol 2018-06-29 11:24:46 +03:00
Dmitry Petrov
609a6ca9bb IrTypes: dummy implementation of IrType.render 2018-06-29 11:24:46 +03:00
Dmitry Petrov
4eb2fc66d0 IrTypes: deep copy with symbols
Preliminary implementation of type remapper (does nothing).
2018-06-29 11:24:46 +03:00
Dmitry Petrov
062c4bf41d IrTypes: make old DeepCopy compile
Lots of TODOs, should figure out proper type mapping strategy
(or simply drop this frankenstein code, finally).
2018-06-29 11:24:46 +03:00
Dmitry Petrov
62a42130c8 Add dependency: ir.tree -> intellij
AnnotationGenerator looks into PsiElement
2018-06-29 11:24:46 +03:00
Dmitry Petrov
c22f6dee4a IrTypes: update minor utilities 2018-06-29 11:24:46 +03:00
Dmitry Petrov
e8fe788df6 IrTypes: Implicit casts, take 1
Keep KotlinType along with IrTypes created by psi2ir.
2018-06-29 11:24:46 +03:00
Dmitry Petrov
54e9a2bb7b IrTypes in psi2ir: generators (seem to be) complete 2018-06-29 11:24:46 +03:00
Dmitry Petrov
5f4f6ef863 IrTypes in psi2ir (work in progress) 2018-06-29 11:24:46 +03:00
Dmitry Petrov
0774ca415c Rebase + reformat 2018-06-29 11:24:46 +03:00
Dmitry Petrov
0f718ec2d8 IrTypes: Fix up some back-end code 2018-06-29 11:24:46 +03:00
Dmitry Petrov
326e4a160f IrTypes in psi2ir (work in progress) 2018-06-29 11:24:46 +03:00
Dmitry Petrov
0e34ee5270 IrTypes: basic built-in types 2018-06-29 11:24:46 +03:00
Dmitry Petrov
c97697d7a9 psi2ir: translate types in StatementGenerator
TODO: DI
2018-06-29 11:24:46 +03:00
Dmitry Petrov
372f280578 DeclarationStubGenerator uses IrTypes 2018-06-29 11:24:46 +03:00
Dmitry Petrov
1353cf879c IR: Drop obsolete builders (should be rewritten) 2018-06-29 11:24:46 +03:00
Dmitry Petrov
f66f3c1fed psi2ir: cleanup TypeTranslator 2018-06-29 11:24:46 +03:00
Dmitry Petrov
4bd2504367 IR declarations: KotlinType -> IrType 2018-06-29 11:24:46 +03:00
Dmitry Petrov
4992ca9179 IR expressions: KotlinType -> IrType 2018-06-29 11:24:46 +03:00
Dmitry Petrov
c28877d23c psi2ir: approximate types in TypeTranslator 2018-06-29 11:24:46 +03:00
Dmitry Petrov
1be28d6032 IrType -> IrDynamicType, IrErrorType, IrSimpleType 2018-06-29 11:24:46 +03:00
Mikhail Glukhikh
fdc0335b4a Add actual: handle (incorrect) case with expect function with body
So #KT-23326 Fixed
2018-06-29 10:54:37 +03:00
Mikhail Glukhikh
0fb183e302 Add actual: handle parameters with val/var as compatible with property
So #KT-23762 Fixed
2018-06-29 10:54:36 +03:00
Mikhail Glukhikh
dd0b267531 Add actual: handle primary & secondary constructors as compatible
So #KT-23686 Fixed
2018-06-29 10:54:35 +03:00
Mikhail Glukhikh
082c3e6767 Reformat: AddActualFix 2018-06-29 10:54:33 +03:00
Mikhail Glukhikh
16c6d63b10 Create actual: do not generate default parameter values
So #KT-23105 Fixed
2018-06-29 10:54:32 +03:00
Mikhail Glukhikh
b13e4535f5 Safe delete: add dialog asking about expect / actual declarations
Related to KT-15666
2018-06-29 10:54:30 +03:00
Mikhail Glukhikh
aac71bf904 Safe delete: when invoking on actual, delete expect & actual neighbors
So #KT-15666 Fixed
2018-06-29 10:54:24 +03:00
Mikhail Glukhikh
50e70e4638 Safe delete: when invoking on expect, delete also relevant actual
Partial fix of KT-15666
2018-06-29 10:53:43 +03:00
Mikhail Glukhikh
465d5c077e Safe delete: search for actual declarations more accurately 2018-06-29 10:53:42 +03:00
Mikhail Glukhikh
5bdaef4983 Cleanup: KotlinSafeDeleteProcessor 2018-06-29 10:53:42 +03:00
Alexey Tsvetkov
8848d7a043 Remove groovy plugin from kotlin-gradle-plugin build script 2018-06-28 22:03:11 +03:00
Alexey Tsvetkov
22c1907167 Track project version in ":kotlin-gradle-plugin:processResources"
Before the change consecutive incremental builds with different project versions
produced kotlin-gradle-plugin with the same project.version in project.properties file
2018-06-28 22:03:11 +03:00
Alexey Tsvetkov
3a7c674957 Fix test dependencies in jps-plugin
Otherwise tests fail on clean checkout
2018-06-28 22:03:10 +03:00
Alexey Sedunov
a63aa5b7ca Misc: Restore utility functions misplaced in a previous commit 2018-06-28 20:39:16 +03:00
Alexey Sedunov
76ac65f723 Configuration: Use soft references to keep library kind cache
#KT-24943 Fixed
2018-06-28 18:22:28 +03:00
Alexey Sedunov
60583e557f PSI: Do not delete package directive for file in default package
#KT-24968 Fixed
2018-06-28 18:22:28 +03:00
Alexey Sedunov
e2a632e326 Misc: Add "refactoring exit" message
This allows executing mandatory code at the end of particular refactoring.
Also this fixes memory leak due to listener not being disposed

 #KT-17235 Fixed
2018-06-28 18:22:28 +03:00
Alexey Sedunov
ba2f28720f Introduce Parameter: Fix exceptions caused by write actions in dialogs
#KT-24992 Fixed
2018-06-28 18:22:27 +03:00
Alexey Sedunov
ed597e2da5 Extract Function: Make compliant with PublicApiImplicitTypeInspection 2018-06-28 18:22:27 +03:00
Alexey Sedunov
633c67ebf0 Misc: Use KtToken to represent visibility in ExtractableCodeDescriptor 2018-06-28 18:22:27 +03:00
Mikhael Bogdanov
b1693acfcd Unmute smap test in ir 2018-06-28 17:12:09 +02:00
Alexey Sedunov
83745010ba Search Everywhere: Update renderer to reflect changes in IDEA
#KT-24812 Fixed
2018-06-28 17:52:05 +03:00
Alexey Sedunov
31d248c42d Search Everywhere: Use Kotlin renderer for Kotlin elements only 2018-06-28 17:52:05 +03:00
Alexey Sedunov
bede2e1c16 Extract Interface: Fix type import when converting parameter to property
#KT-18736 Fixed
2018-06-28 17:52:05 +03:00
Alexey Sedunov
9b7450cfdb Extract Superclass: Report private members used in abstracted members
#KT-16284 Fixed
2018-06-28 17:52:04 +03:00
Alexey Sedunov
bd88e02172 Extract Superclass: Fix visibility lifting when moving to interface
#KT-16281 Fixed
2018-06-28 17:52:04 +03:00
Alexey Sedunov
b0e0460ee6 Extract Superclass: Allow extraction to existing file
#KT-15351 Fixed
2018-06-28 17:52:04 +03:00
Alexey Sedunov
5ef54a2f03 Extract Superclass: Run refactoring inside of transaction
#KT-18555 Fixed
2018-06-28 17:52:03 +03:00
Nikolay Krasko
87f4d0c5a4 Move "Copy Current File As Diagnostic Test" action to internal (KT-25164)
#KT-25164 Fixed
2018-06-28 16:02:14 +03:00
Nikolay Krasko
c68284030d Check files is valid before searching for children (EA-113417) 2018-06-28 16:02:14 +03:00
Alexander Udalov
8c8d0eefbb Relocate package org.jetbrains.kotlin in kotlinx-metadata-jvm
To prevent clashes in scenarios where it's used together with the Kotlin
compiler (e.g. in annotation processing)

 #KT-24945 Fixed
2018-06-28 14:39:53 +02:00
Mikhail Zarechenskiy
173bcd90df Simplify lexer rule for typed integers 2018-06-28 13:32:10 +03:00
Mikhael Bogdanov
e149cbe852 Mute failed jvm ir tests 2018-06-28 12:26:41 +02:00
Mikhael Bogdanov
a10c06eb4d Regenerate ir tests with JVM_IR target 2018-06-28 12:26:41 +02:00
Mikhail Zarechenskiy
dc7678a700 Use smartcast info that related to call in change signature quick fix
There is an inconsistency on how we record smartcasts in old and new
 inference, but we definitely should use all possible information about
 smartcasts in quick-fixes

 #KT-25144 Fixed
2018-06-28 13:14:18 +03:00
Nicolay Mitropolsky
698096f13e Uast: fix for creating an UClass for invalid object-literals (EA-122644, KT-20056) 2018-06-28 10:29:47 +03:00
Alexey Tsvetkov
25e6b76238 Build: disable jar compression for local builds
This speeds ups jar creation twice, which is significant for local
incremental builds when jar creation can dominate compilation time.

Changes in stripMetadata are required because putting entry from not-stripped
jar caused failures when compression was disabled (because size and crc
are actually changed during metadata removal; don't know why it works
with compression).
2018-06-27 23:56:26 +03:00
Alexey Tsvetkov
3dc38fe2f8 Build: enable Java incremental compilation for local builds 2018-06-27 23:56:26 +03:00
Alexey Tsvetkov
c73657b38d Build: disable incremental compilation for non-TC build
This should bring small performance improvements for CI builds
(since they are not incremental anyway).
2018-06-27 23:56:26 +03:00
Nico Mandery
5c16633175 fix typos in documentation of JsQualifier annotation (#1733) 2018-06-27 19:34:27 +03:00
Lucas Smaira
5820656aae Find Kotlin class with alternative resolve enabled
Kotlin run configurations are failing non-deterministically in Android
Studio due to not finding the class while in dumb mode (while AS invokes
Gradle build or in indexing after that).

Fix that by finding class in KotlinRunConfiguration with alternative
resolve enabled.
2018-06-27 16:38:44 +03:00
Vyacheslav Gerasimov
abd3ac4e96 UAST: Reformat KotlinUObjectLiteralExpression.kt 2018-06-27 16:04:41 +03:00
Vyacheslav Gerasimov
a829251690 UAST: Fix possible TypeCastException when creating KotlinUNamedExpression 2018-06-27 16:04:40 +03:00
Vyacheslav Gerasimov
23ee463053 Check if module disposed when getting modules with kotlin files 2018-06-27 16:04:40 +03:00
Vyacheslav Gerasimov
16b4d25c1d Reformat ConfigureKotlinInProjectUtils 2018-06-27 16:04:40 +03:00
Vyacheslav Gerasimov
62c0d37d45 UAST: Do not log PCE in DeclarationDescriptor.toSource 2018-06-27 16:03:16 +03:00
Nikolay Krasko
8ea19eda73 as32: Minor: use full sentences for reasons 2018-06-27 15:11:08 +03:00
Nikolay Krasko
17d4961760 as32: Use full sentences for reasons 2018-06-27 15:11:08 +03:00
Nikolay Krasko
099f3f3ddf Move isEap and isDev utility functions to idea module 2018-06-27 15:11:08 +03:00
Nikolay Krasko
54bb09a5fb Make disabled verification visible in UI 2018-06-27 15:11:07 +03:00
Alexander Udalov
0c45f20515 Minor, fix several CLI argument descriptions 2018-06-27 13:25:30 +02:00
Mikhail Zarechenskiy
a765ee41d7 Introduce uL/UL suffix to represent numbers of unsigned long type
#KT-24663 Fixed
2018-06-27 14:21:12 +03:00
Mikhail Zarechenskiy
7c44992016 Allow any case for u suffix
#KT-24663 In Progress
2018-06-27 14:21:07 +03:00
Alexander Udalov
984e37c7f1 Prohibit explicit usage of kotlin.Metadata as annotation 2018-06-27 12:37:18 +02:00
Alexander Udalov
8d124eb77f Minor, use array literal syntax in kotlin.Metadata 2018-06-27 12:20:03 +02:00
Dmitry Petrov
46a3f7420c When in debugger context, access private companion object directly 2018-06-26 16:46:55 +03:00
Nicolay Mitropolsky
bef3d4ace2 Uast: proper identifiers for KotlinUBinaryExpression (KT-25092) 2018-06-26 16:39:47 +03:00
Mikhail Glukhikh
eb92b7ed7f Unused symbol: don't suggest actual declaration used in another platform
Related to KT-17512
Related to KT-15666
2018-06-26 15:36:10 +03:00
Mikhail Glukhikh
30327aa9cc Do not mark kotlin.test.Test annotated declarations as unused
So #KT-20523 Fixed
2018-06-26 15:36:09 +03:00
Mikhail Glukhikh
7e0e7dc983 Unused symbol: remove forced "used" from actual declarations
Now we really check whether actual declaration has usages
(in expect or actual code) or not
Related to KT-17512
Related to KT-15666
2018-06-26 15:36:07 +03:00
Mikhail Glukhikh
e885e54233 Implement search from expect element in KotlinReferenceSearcher
So mostly #KT-17512 Fixed
2018-06-26 15:36:06 +03:00
Mikhail Glukhikh
97d158d833 Find property usages dialog: rename all check-boxes as in other dialogs 2018-06-26 15:36:05 +03:00
Mikhail Glukhikh
abbfea357a Add find usages option: search expected 2018-06-26 15:36:04 +03:00
Mikhail Glukhikh
69e420991a KotlinFindMemberUsagesHandler: get rid of deprecation 2018-06-26 15:36:03 +03:00
Mikhail Glukhikh
0a36edcf20 Cleanup: KotlinReferenceSearcher 2018-06-26 15:36:01 +03:00
Mikhail Glukhikh
ea7db42af6 Cleanup: findUsagesOptions 2018-06-26 15:36:00 +03:00
Mikhail Glukhikh
a46e4f3142 Cleanup: KotlinFindMemberUsagesHandler 2018-06-26 15:35:59 +03:00
Mikhail Glukhikh
cc2869988f Test for KT-17512 (yet with incorrect results) 2018-06-26 15:35:58 +03:00
Mikhail Zarechenskiy
600d135786 Fix internal compiler error on importing invisible fake reference
Note that this is not relevant for LOCAL/INHERITED visibilities:
  - for LOCAL visibility it's impossible to have a qualifier
  - INHERITED is an intermediate visibility, we enhance it later
    (see resolveUnknownVisibilityForMember)

 #KT-20356 Fixed
2018-06-26 14:18:21 +03:00
Nikolay Krasko
84b26fc61d Show kotlin internal information only in internal builds 2018-06-26 11:35:22 +03:00
Nikolay Krasko
5df0879538 Fix NPE in replaceImports() (EA-109700) 2018-06-26 11:35:21 +03:00
Alexander Udalov
1951d38f40 Retain optional expected annotations when compiling platform code
After this change, optional expected annotations will be compiled to
physical class files on JVM, and stored to metadata on other platforms,
to allow their usages from dependent platform modules. For example:

    @OptionalExpectation
    expect annotation class A

When compiling this code on JVM, A.class will be produced as if the
class A did neither have the 'expect' modifier, nor had it been
annotated with OptionalExpectation. Note that if there's no actual
annotation class for A, then usages (which can only be usages as
annotation entries) are simply skipped.

Class A will be public from Kotlin's point of view (since it should
be possible to use it in Kotlin sources), but _package-private_ in Java
to disallow its usages outside of the declaring module.

 #KT-18882 Fixed
 #KT-24617 Fixed
2018-06-26 10:23:55 +02:00
Alexander Udalov
4e217b180a Pass BindingContext to CodegenUtil.getActualDeclarations
Will be used in a subsequent commit. Also rename getActualDeclarations
-> getDeclarationsToGenerate
2018-06-26 10:23:55 +02:00
Mikhail Zarechenskiy
ba6da7c40a Support varargs of inline class types with non-trivial spread
#KT-24880 In Progress
2018-06-25 17:15:50 +03:00
Mikhail Zarechenskiy
333411c57d Associate vararg of unsigned types with corresponding arrays
This is a first step, full support will be added later

 #KT-24880 In Progress
2018-06-25 17:15:47 +03:00
Mikhail Zarechenskiy
3e45a1529c Allow to declare vararg parameters of unsigned types
varargs inside annotations will be supported later when
 constant evaluation of more complex expressions of unsigned types
 will be ready

 #KT-24880 In Progress
2018-06-25 17:15:44 +03:00
Mikhail Zarechenskiy
3f462659d2 Determine underlying property of inline class by its name
Previous way to distinguish "primary constructor properties" from other
 properties wasn't correct for deserialized properties, because currently
 we don't have special information about this in metadata
2018-06-25 17:11:59 +03:00
2895 changed files with 553827 additions and 24546 deletions

View File

@@ -15,6 +15,6 @@
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<method v="2" />
<method />
</configuration>
</component>

View File

@@ -5,6 +5,7 @@ import java.util.*
import java.io.File
import org.gradle.api.tasks.bundling.Jar
import org.gradle.plugins.ide.idea.model.IdeaModel
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
import proguard.gradle.ProGuardTask
@@ -12,7 +13,7 @@ import proguard.gradle.ProGuardTask
buildscript {
extra["defaultSnapshotVersion"] = "1.2-SNAPSHOT"
kotlinBootstrapFrom(BootstrapOption.TeamCity("1.2.60-dev-980", onlySuccessBootstrap = false))
kotlinBootstrapFrom(BootstrapOption.TeamCity("1.2.70-dev-23", onlySuccessBootstrap = false))
val mirrorRepo: String? = findProperty("maven.repository.mirror")?.toString()
@@ -22,7 +23,6 @@ buildscript {
"https://jcenter.bintray.com/",
"https://plugins.gradle.org/m2",
"http://dl.bintray.com/kotlin/kotlinx",
"https://jetbrains.bintray.com/kotlin-native-dependencies",
"https://repo.gradle.org/gradle/ext-releases-local", // for native-platform
"https://jetbrains.bintray.com/intellij-third-party-dependencies", // for jflex
"https://dl.bintray.com/jetbrains/markdown" // for org.jetbrains:markdown
@@ -206,6 +206,7 @@ extra["compilerModules"] = arrayOf(
":compiler:daemon",
":compiler:ir.tree",
":compiler:ir.psi2ir",
":compiler:ir.backend.common",
":compiler:backend.js",
":compiler:backend-common",
":compiler:backend",
@@ -306,7 +307,7 @@ allprojects {
configureJvmProject(javaHome!!, jvmTarget!!)
val commonCompilerArgs = listOf("-Xallow-kotlin-package", "-Xread-deserialized-contracts")
val commonCompilerArgs = listOfNotNull("-Xallow-kotlin-package", "-Xread-deserialized-contracts", "-Xprogressive".takeIf { hasProperty("test.progressive.mode") })
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>> {
kotlinOptions {
@@ -371,6 +372,22 @@ allprojects {
}
}
if (!isTeamcityBuild) {
gradle.taskGraph.whenReady {
for (project in allprojects) {
for (task in project.tasks) {
when (task) {
is AbstractKotlinCompile<*> -> task.incremental = true
is JavaCompile -> task.options.isIncremental = true
is org.gradle.jvm.tasks.Jar -> task.entryCompression = ZipEntryCompression.STORED
}
}
}
logger.warn("Local build profile is active (IC is on, proguard is off). Use -Pteamcity=true to reproduce TC build")
}
}
val dist by task<Copy> {
val childDistTasks = getTasksByName("dist", true) - this@task
dependsOn(childDistTasks)

View File

@@ -1,94 +0,0 @@
buildscript {
val buildSrcKotlinVersion: String by extra(findProperty("buildSrc.kotlin.version")?.toString() ?: embeddedKotlinVersion)
val buildSrcKotlinRepo: String? by extra(findProperty("buildSrc.kotlin.repo") as String?)
extra["versions.shadow"] = "2.0.2"
extra["versions.native-platform"] = "0.14"
repositories {
buildSrcKotlinRepo?.let {
maven(url = it)
}
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$buildSrcKotlinVersion")
classpath("org.jetbrains.kotlin:kotlin-sam-with-receiver:$buildSrcKotlinVersion")
}
}
logger.info("buildSrcKotlinVersion: " + extra["buildSrcKotlinVersion"])
logger.info("buildSrc kotlin compiler version: " + org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION)
logger.info("buildSrc stdlib version: " + KotlinVersion.CURRENT)
apply {
plugin("kotlin")
plugin("kotlin-sam-with-receiver")
}
plugins {
`kotlin-dsl`
`java-gradle-plugin`
}
gradlePlugin {
(plugins) {
"pill-configurable" {
id = "pill-configurable"
implementationClass = "org.jetbrains.kotlin.pill.PillConfigurablePlugin"
}
"jps-compatible" {
id = "jps-compatible"
implementationClass = "org.jetbrains.kotlin.pill.JpsCompatiblePlugin"
}
}
}
fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)?.let {
val v = it.toString()
if (v.isBlank()) true
else v.toBoolean()
}
rootProject.apply {
from(rootProject.file("../versions.gradle.kts"))
}
val isTeamcityBuild = project.hasProperty("teamcity") || System.getenv("TEAMCITY_VERSION") != null
val intellijUltimateEnabled by extra(project.getBooleanProperty("intellijUltimateEnabled") ?: isTeamcityBuild)
val intellijSeparateSdks by extra(project.getBooleanProperty("intellijSeparateSdks") ?: false)
extra["intellijRepo"] = "https://www.jetbrains.com/intellij-repository"
extra["intellijReleaseType"] = "snapshots" // or "snapshots"
extra["versions.androidDxSources"] = "5.0.0_r2"
extra["customDepsOrg"] = "kotlin.build.custom.deps"
repositories {
extra["buildSrcKotlinRepo"]?.let {
maven(url = it)
}
maven(url = "https://repo.gradle.org/gradle/ext-releases-local") // for native-platform
jcenter()
}
dependencies {
compile("net.rubygrapefruit:native-platform:${property("versions.native-platform")}")
compile("net.rubygrapefruit:native-platform-windows-amd64:${property("versions.native-platform")}")
compile("net.rubygrapefruit:native-platform-windows-i386:${property("versions.native-platform")}")
compile("com.jakewharton.dex:dex-method-list:3.0.0")
// TODO: adding the dep to the plugin breaks the build unexpectedly, resolve and uncomment
// compile("org.jetbrains.kotlin:kotlin-gradle-plugin:${rootProject.extra["bootstrap_kotlin_version"]}")
// Shadow plugin is used in many projects of the main build. Once it's no longer used in buildSrc, please move this dependency to the root project
compile("com.github.jengelman.gradle.plugins:shadow:${property("versions.shadow")}")
compile("org.ow2.asm:asm-all:6.0_BETA")
}
samWithReceiver {
annotation("org.gradle.api.HasImplicitReceiver")
}
fun Project.`samWithReceiver`(configure: org.jetbrains.kotlin.samWithReceiver.gradle.SamWithReceiverExtension.() -> Unit): Unit =
extensions.configure("samWithReceiver", configure)
tasks["build"].dependsOn(":prepare-deps:android-dx:build", ":prepare-deps:intellij-sdk:build")

View File

@@ -6,6 +6,7 @@ import java.io.BufferedOutputStream
import java.io.File
import java.io.FileOutputStream
import java.util.jar.JarFile
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
/**
@@ -47,8 +48,8 @@ fun stripMetadata(logger: Logger, classNamePattern: String, inFile: File, outFil
error("Size increased for ${entry.name}: was ${inBytes.size} bytes, became ${outBytes.size} bytes")
}
entry.compressedSize = -1L
outJar.putNextEntry(entry)
val newEntry = ZipEntry(entry.name)
outJar.putNextEntry(newEntry)
outJar.write(outBytes)
outJar.closeEntry()
}

View File

@@ -18,7 +18,6 @@ dependencies {
sourceSets {
"main" {
projectDefault()
java.srcDir("../ir/backend.common/src")
}
"test" {}
}

View File

@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
import org.jetbrains.kotlin.types.KotlinType
@@ -167,9 +168,24 @@ object CodegenUtil {
return KtPsiFactory(project, markGenerated = false).createExpression(fakeFunctionCall) as KtCallExpression
}
/**
* Returns declarations in the given [file] which should be generated by the back-end. This includes all declarations
* minus all expected declarations (except annotation classes annotated with @OptionalExpectation).
*/
@JvmStatic
fun getActualDeclarations(file: KtFile): List<KtDeclaration> =
file.declarations.filterNot(KtDeclaration::hasExpectModifier)
fun getDeclarationsToGenerate(file: KtFile, bindingContext: BindingContext): List<KtDeclaration> =
file.declarations.filter(fun(declaration: KtDeclaration): Boolean {
if (!declaration.hasExpectModifier()) return true
if (declaration is KtClass) {
val descriptor = bindingContext.get(BindingContext.CLASS, declaration)
if (descriptor != null && ExpectedActualDeclarationChecker.shouldGenerateExpectClass(descriptor)) {
return true
}
}
return false
})
@JvmStatic
fun findExpectedFunctionForActual(descriptor: FunctionDescriptor): FunctionDescriptor? {

View File

@@ -13,6 +13,7 @@ dependencies {
compile(project(":compiler:frontend.java"))
compile(project(":compiler:ir.tree"))
compile(project(":compiler:ir.psi2ir"))
compile(project(":compiler:ir.backend.common"))
compile(project(":compiler:serialization"))
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
compileOnly(intellijDep()) { includeJars("annotations", "asm-all", "trove4j", "guava", rootProject = rootProject) }

View File

@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.AnnotationChecker;
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker;
import org.jetbrains.kotlin.resolve.constants.*;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.types.FlexibleType;
@@ -300,7 +301,10 @@ public abstract class AnnotationCodegen {
return null;
}
if (classDescriptor.isExpect()) {
// We do not generate annotations whose classes are optional (annotated with `@OptionalExpectation`) because if an annotation entry
// is resolved to the expected declaration, this means that annotation has no actual class, and thus should not be generated.
// (Otherwise we would've resolved the entry to the actual annotation class.)
if (ExpectedActualDeclarationChecker.isOptionalAnnotationClass(classDescriptor)) {
return null;
}

View File

@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker;
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
@@ -278,6 +279,9 @@ public class AsmUtil {
if (descriptor instanceof SyntheticClassDescriptorForLambda) {
return getVisibilityAccessFlagForAnonymous(descriptor);
}
if (ExpectedActualDeclarationChecker.isOptionalAnnotationClass(descriptor)) {
return NO_FLAG_PACKAGE_PRIVATE;
}
if (descriptor.getVisibility() == Visibilities.PUBLIC ||
descriptor.getVisibility() == Visibilities.PROTECTED ||
// TODO: should be package private, but for now Kotlin's reflection can't access members of such classes

View File

@@ -1707,11 +1707,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
boolean isUnderlyingPropertyOfInlineClass =
InlineClassesUtilsKt.isInlineClass(propertyDescriptor.getContainingDeclaration()) &&
JvmCodegenUtil.hasBackingField(propertyDescriptor, contextKind(), bindingContext);
if (isUnderlyingPropertyOfInlineClass) {
if (InlineClassesUtilsKt.isUnderlyingPropertyOfInlineClass(propertyDescriptor)) {
KotlinType propertyType = propertyDescriptor.getType();
return StackValue.underlyingValueOfInlineClass(typeMapper.mapType(propertyType), propertyType, receiver);
}
@@ -2655,12 +2651,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
"Containing declaration of the companion object " + companionObjectDescriptor +
": expected a class, actual: " + hostClassDescriptor;
CodegenContext hostClassContext = context;
while (hostClassContext.getContextDescriptor() != hostClassDescriptor) {
hostClassContext = hostClassContext.getParentContext();
assert hostClassContext != null :
"Host class context for " + hostClassDescriptor + " not found in context hierarchy for " + context;
}
CodegenContext hostClassContext = context.findParentContextWithDescriptor(hostClassDescriptor);
assert hostClassContext != null :
"Host class context for " + hostClassDescriptor + " not found in context hierarchy for " + context;
hostClassContext.markCompanionObjectDescriptorWithAccessorRequired(companionObjectDescriptor);
@@ -2902,6 +2895,18 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
KotlinType argumentKotlinType = kotlinType(argumentExpression);
if (argument.getSpreadElement() != null) {
gen(argumentExpression, OBJECT_TYPE, argumentKotlinType);
if (argumentKotlinType != null && InlineClassesUtilsKt.isInlineClassType(argumentKotlinType)) {
// we're going to pass value of inline class type to j/l/Object, which would result in boxing and then
// will cause check cast error on toArray() call. To mitigate this problem, we unbox this value and pass
// primitive array to the method. Note that bytecode optimisations will remove box/unbox calls.
StackValue.coerce(
OBJECT_TYPE, argumentKotlinType,
asmType(argumentKotlinType), argumentKotlinType,
v
);
}
v.invokevirtual(owner, "addSpread", "(Ljava/lang/Object;)V", false);
}
else {

View File

@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.codegen.coroutines.SuspendFunctionGenerationStrategy
import org.jetbrains.kotlin.codegen.coroutines.SuspendInlineFunctionGenerationStrategy;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.codegen.state.TypeMapperUtilsKt;
import org.jetbrains.kotlin.config.JvmDefaultMode;
import org.jetbrains.kotlin.config.JvmTarget;
import org.jetbrains.kotlin.config.LanguageFeature;
@@ -295,8 +294,7 @@ public class FunctionCodegen {
// descriptor corresponds to the underlying value
if (functionDescriptor instanceof PropertyAccessorDescriptor) {
PropertyDescriptor property = ((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty();
// property for the underlying value
if (JvmCodegenUtil.hasBackingField(property, contextKind, bindingContext)) {
if (InlineClassesUtilsKt.isUnderlyingPropertyOfInlineClass(property)) {
return false;
}
}

View File

@@ -16,17 +16,42 @@
package org.jetbrains.kotlin.codegen;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.output.OutputFile;
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.Base64;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.Manifest;
public class GeneratedClassLoader extends URLClassLoader {
private static final URLStreamHandler FAKE_BASE64_URL_HANDLER = new URLStreamHandler() {
@Override
protected URLConnection openConnection(URL url) {
return new URLConnection(url) {
@Override
public void connect() {
}
@Override
public InputStream getInputStream() {
return new ByteArrayInputStream(Base64.getDecoder().decode(url.getPath()));
}
};
}
};
private ClassFileFactory factory;
public GeneratedClassLoader(@NotNull ClassFileFactory factory, ClassLoader parentClassLoader, URL... urls) {
@@ -43,6 +68,39 @@ public class GeneratedClassLoader extends URLClassLoader {
return super.getResourceAsStream(name);
}
@Override
public Enumeration<URL> findResources(String name) throws IOException {
Enumeration<URL> fromParent = super.findResources(name);
URL url = createFakeURLForResource(name);
if (url == null) return fromParent;
List<URL> fromMe = Collections.singletonList(url);
List<URL> result = fromParent.hasMoreElements()
? CollectionsKt.plus(fromMe, Collections.list(fromParent))
: fromMe;
return Collections.enumeration(result);
}
@Override
public URL findResource(String name) {
URL url = createFakeURLForResource(name);
return url != null ? url : super.findResource(name);
}
@Nullable
private URL createFakeURLForResource(@NotNull String name) {
try {
OutputFile outputFile = factory.get(name);
// Encode the byte array in the URL path to prevent creating unneeded temporary files
return outputFile == null
? null
: new URL(null, "bytes:" + Base64.getEncoder().encodeToString(outputFile.asByteArray()), FAKE_BASE64_URL_HANDLER);
} catch (IOException e) {
throw ExceptionUtilsKt.rethrow(e);
}
}
@NotNull
@Override
protected Class<?> findClass(@NotNull String name) throws ClassNotFoundException {

View File

@@ -159,6 +159,10 @@ public class JvmCodegenUtil {
return true;
}
if (isDebuggerContext(contextBeforeInline)) {
return true;
}
CodegenContext context = contextBeforeInline.getFirstCrossInlineOrNonInlineContext();
if (context.isInlineMethodContext()) {
// Inline method can be called from a nested class.

View File

@@ -85,7 +85,7 @@ class MultifileClassCodegenImpl(
private val partInternalNamesSorted = run {
val partInternalNamesSet = hashSetOf<String>()
for (file in files) {
if (file.hasDeclarationsForPartClass()) {
if (file.hasDeclarationsForPartClass(state.bindingContext)) {
partInternalNamesSet.add(JvmFileClassUtil.getFileClassInternalName(file))
}
}
@@ -122,7 +122,7 @@ class MultifileClassCodegenImpl(
val singleSourceFile =
if (previouslyCompiledCallables.isEmpty())
files.singleOrNull { it.hasDeclarationsForPartClass() }
files.singleOrNull { it.hasDeclarationsForPartClass(state.bindingContext) }
else
null
@@ -209,7 +209,9 @@ class MultifileClassCodegenImpl(
generateNonPartClassDeclarations(file, partContext)
if (!state.generateDeclaredClassFilter.shouldGeneratePackagePart(file) || !file.hasDeclarationsForPartClass()) return
if (!state.generateDeclaredClassFilter.shouldGeneratePackagePart(file) ||
!file.hasDeclarationsForPartClass(state.bindingContext)
) return
packagePartRegistry.addPart(partType.internalName, facadeClassType.internalName)
@@ -243,7 +245,7 @@ class MultifileClassCodegenImpl(
private fun addDelegateGenerationTasksForDeclarationsInFile(file: KtFile, packageFragment: PackageFragmentDescriptor, partType: Type) {
val facadeContext = state.rootContext.intoMultifileClass(packageFragment, facadeClassType, partType)
val memberCodegen = createCodegenForDelegatesInMultifileFacade(facadeContext)
for (declaration in CodegenUtil.getActualDeclarations(file)) {
for (declaration in CodegenUtil.getDeclarationsToGenerate(file, state.bindingContext)) {
if (declaration is KtNamedFunction || declaration is KtProperty || declaration is KtTypeAlias) {
val descriptor = state.bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration)
if (descriptor !is MemberDescriptor) {
@@ -375,8 +377,8 @@ class MultifileClassCodegenImpl(
return fragments.firstOrNull()
}
private fun KtFile.hasDeclarationsForPartClass() =
CodegenUtil.getActualDeclarations(this).any { it is KtProperty || it is KtFunction || it is KtTypeAlias }
private fun KtFile.hasDeclarationsForPartClass(bindingContext: BindingContext) =
CodegenUtil.getDeclarationsToGenerate(this, bindingContext).any { it is KtProperty || it is KtFunction || it is KtTypeAlias }
private fun getCompiledPackageFragment(
facadeFqName: FqName, state: GenerationState

View File

@@ -132,7 +132,7 @@ class MultifileClassPartCodegen(
}
override fun generateBody() {
for (declaration in CodegenUtil.getActualDeclarations(element)) {
for (declaration in CodegenUtil.getDeclarationsToGenerate(element, state.bindingContext)) {
if (declaration is KtNamedFunction || declaration is KtProperty || declaration is KtTypeAlias) {
genSimpleMember(declaration)
}

View File

@@ -98,7 +98,7 @@ public class PackageCodegenImpl implements PackageCodegen {
List<KtClassOrObject> classOrObjects = new ArrayList<>();
for (KtDeclaration declaration : CodegenUtil.getActualDeclarations(file)) {
for (KtDeclaration declaration : CodegenUtil.getDeclarationsToGenerate(file, state.getBindingContext())) {
if (isFilePartDeclaration(declaration)) {
generatePackagePart = true;
}

View File

@@ -90,7 +90,7 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
@Override
protected void generateBody() {
for (KtDeclaration declaration : CodegenUtil.getActualDeclarations(element)) {
for (KtDeclaration declaration : CodegenUtil.getDeclarationsToGenerate(element, state.getBindingContext())) {
if (declaration instanceof KtNamedFunction || declaration instanceof KtProperty || declaration instanceof KtTypeAlias) {
genSimpleMember(declaration);
}
@@ -123,7 +123,8 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
@NotNull Type packagePartType
) {
BindingContext bindingContext = codegen.bindingContext;
List<DeclarationDescriptor> members = CollectionsKt.mapNotNull(CodegenUtil.getActualDeclarations(codegen.element), declaration -> {
List<KtDeclaration> allDeclarations = CodegenUtil.getDeclarationsToGenerate(codegen.element, bindingContext);
List<DeclarationDescriptor> members = CollectionsKt.mapNotNull(allDeclarations, declaration -> {
if (declaration instanceof KtNamedFunction) {
return bindingContext.get(BindingContext.FUNCTION, declaration);
}

View File

@@ -193,8 +193,10 @@ public class SamWrapperCodegen {
@NotNull KtFile containingFile,
CallableMemberDescriptor contextDescriptor
) {
boolean hasPackagePartClass =
CollectionsKt.any(CodegenUtil.getActualDeclarations(containingFile), PackageCodegenImpl::isFilePartDeclaration);
boolean hasPackagePartClass = CollectionsKt.any(
CodegenUtil.getDeclarationsToGenerate(containingFile, state.getBindingContext()),
PackageCodegenImpl::isFilePartDeclaration
);
FqName filePartFqName = JvmFileClassUtil.getFileClassInfoNoResolve(containingFile).getFileClassFqName();
FqName outermostOwner;

View File

@@ -19,8 +19,8 @@ import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.codegen.topLevelClassAsmType
import org.jetbrains.kotlin.codegen.topLevelClassInternalName
import org.jetbrains.kotlin.coroutines.isSuspendLambda
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.coroutines.isSuspendLambda
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
@@ -240,7 +240,7 @@ fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(
setReturnType(function.builtIns.nullableAnyType)
setValueParameters(it.valueParameters + continuationParameter)
if (dropSuspend) {
setDropSuspend()
setIsSuspend(false)
}
putUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION, it)
}
@@ -475,4 +475,4 @@ fun FunctionDescriptor.isSuspendLambdaOrLocalFunction() = this.isSuspend && when
is AnonymousFunctionDescriptor -> this.isSuspendLambda
is SimpleFunctionDescriptor -> this.visibility == Visibilities.LOCAL
else -> false
}
}

View File

@@ -144,7 +144,7 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
@Argument(
value = "-Xuse-experimental",
valueDescription = "<fq.name>",
description = "Enable usages of COMPILATION-affecting experimental API for marker annotation with the given fully qualified name"
description = "Enable, but don't propagate usages of experimental API for marker annotation with the given fully qualified name"
)
var useExperimental: Array<String>? by FreezableVar(null)

View File

@@ -231,7 +231,7 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
"-Xjvm-default=enable Allow usages of @JvmDefault; only generate the default method\n" +
" in the interface (annotating an existing method can break binary compatibility)\n" +
"-Xjvm-default=compatibility Allow usages of @JvmDefault; generate a compatibility accessor\n" +
" in the 'DefaultImpls' class in addition to the interface method\n"
" in the 'DefaultImpls' class in addition to the interface method"
)
var jvmDefault: String by FreezableVar(JvmDefaultMode.DEFAULT.description)

View File

@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.load.java.InternalFlexibleTypeTransformer
import org.jetbrains.kotlin.load.java.JavaClassFinderImpl
import org.jetbrains.kotlin.load.java.JavaClassesTracker
import org.jetbrains.kotlin.load.java.components.*
import org.jetbrains.kotlin.load.java.lazy.JavaResolverSettings
import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolver
import org.jetbrains.kotlin.load.kotlin.DeserializationComponentsForJava
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory
@@ -115,6 +116,9 @@ fun createContainerForLazyResolveWithJava(
}
useInstance(javaClassTracker ?: JavaClassesTracker.Default)
useInstance(
JavaResolverSettings.create(isReleaseCoroutines = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines))
)
targetEnvironment.configure(this)

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.resolve.jvm.checkers
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.resolve.AdditionalAnnotationChecker
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
object ExplicitMetadataChecker : AdditionalAnnotationChecker {
private val METADATA_FQ_NAME = FqName("kotlin.Metadata")
override fun checkEntries(entries: List<KtAnnotationEntry>, actualTargets: List<KotlinTarget>, trace: BindingTrace) {
for (entry in entries) {
val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue
if (descriptor.fqName == METADATA_FQ_NAME) {
trace.report(ErrorsJvm.EXPLICIT_METADATA_IS_DISALLOWED.on(entry))
}
}
}
}

View File

@@ -141,6 +141,7 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
MAP.put(JVM_DEFAULT_THROUGH_INHERITANCE, "Inheritance from an interface with '@JvmDefault' members is only allowed with -Xjvm-default option");
MAP.put(USAGE_OF_JVM_DEFAULT_THROUGH_SUPER_CALL, "Super calls of '@JvmDefault' members are only allowed with -Xjvm-default option");
MAP.put(NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT, "Non-@JvmDefault interface method cannot override default Java method. Please annotate this method with @JvmDefault");
MAP.put(EXPLICIT_METADATA_IS_DISALLOWED, "Explicit @Metadata is disallowed");
}
@NotNull

View File

@@ -123,6 +123,8 @@ public interface ErrorsJvm {
DiagnosticFactory0<KtDeclaration> NON_JVM_DEFAULT_OVERRIDES_JAVA_DEFAULT = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE);
DiagnosticFactory0<KtAnnotationEntry> EXPLICIT_METADATA_IS_DISALLOWED = DiagnosticFactory0.create(ERROR);
enum NullabilityInformationSource {
KOTLIN {
@NotNull

View File

@@ -71,7 +71,8 @@ object JvmPlatformConfigurator : PlatformConfigurator(
additionalAnnotationCheckers = listOf(
RepeatableAnnotationChecker,
FileClassAnnotationsChecker
FileClassAnnotationsChecker,
ExplicitMetadataChecker
),
identifierChecker = JvmSimpleNameBacktickChecker,

View File

@@ -747,7 +747,9 @@ public interface Errors {
DiagnosticFactory2<KtBinaryExpression, KotlinType, KotlinType> FORBIDDEN_IDENTITY_EQUALS = DiagnosticFactory2.create(ERROR);
DiagnosticFactory2<PsiElement, FunctionDescriptor, String> DEPRECATED_BINARY_MOD = DiagnosticFactory2.create(WARNING);
DiagnosticFactory2<PsiElement, FunctionDescriptor, String> FORBIDDEN_BINARY_MOD = DiagnosticFactory2.create(ERROR);
DiagnosticFactory2<PsiElement, FunctionDescriptor, String> DEPRECATED_BINARY_MOD_AS_REM = DiagnosticFactory2.create(WARNING);
DiagnosticFactory2<PsiElement, FunctionDescriptor, String> FORBIDDEN_BINARY_MOD_AS_REM = DiagnosticFactory2.create(ERROR);
DiagnosticFactory0<KtArrayAccessExpression> NO_GET_METHOD = DiagnosticFactory0.create(ERROR, ARRAY_ACCESS);
DiagnosticFactory0<KtArrayAccessExpression> NO_SET_METHOD = DiagnosticFactory0.create(ERROR, ARRAY_ACCESS);

View File

@@ -396,7 +396,9 @@ public class DefaultErrorMessages {
MAP.put(FORBIDDEN_IDENTITY_EQUALS, "Identity equality for arguments of types {0} and {1} is forbidden", RENDER_TYPE, RENDER_TYPE);
MAP.put(DEPRECATED_BINARY_MOD, "Deprecated convention for ''{0}''. Use ''{1}''", NAME, STRING);
MAP.put(FORBIDDEN_BINARY_MOD, "Convention for ''{0}'' is forbidden. Use ''{1}''", NAME, STRING);
MAP.put(DEPRECATED_BINARY_MOD_AS_REM, "''%'' is resolved to deprecated ''{0}'' operator. Replace with ''.{0}'' or add operator ''{1}''", NAME, STRING);
MAP.put(FORBIDDEN_BINARY_MOD_AS_REM, "''%'' is resolved to forbidden ''{0}'' operator. Replace with ''.{0}'' or add operator ''{1}''", NAME, STRING);
MAP.put(NO_GET_METHOD, "No get method providing array access");
MAP.put(NO_SET_METHOD, "No set method providing array access");

View File

@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve
import com.google.common.collect.ImmutableSet
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
@@ -921,7 +922,9 @@ class DeclarationsChecker(
val nullableNothing = callableDescriptor.builtIns.nullableNothingType
for (parameter in varargParameters) {
val varargElementType = parameter.varargElementType!!.upperIfFlexible()
if (KotlinTypeChecker.DEFAULT.isSubtypeOf(varargElementType, nullableNothing) || varargElementType.isInlineClassType()) {
if (KotlinTypeChecker.DEFAULT.isSubtypeOf(varargElementType, nullableNothing) ||
(varargElementType.isInlineClassType() && !UnsignedTypes.isUnsignedType(varargElementType))
) {
val parameterDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(parameter) as? KtParameter ?: continue
trace.report(FORBIDDEN_VARARG_PARAMETER_TYPE.on(parameterDeclaration, varargElementType))
}

View File

@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.resolve
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -50,10 +51,18 @@ object OperatorModifierChecker {
checkSupportsFeature(LanguageFeature.OperatorProvideDelegate, languageVersionSettings, diagnosticHolder, modifier)
}
if (functionDescriptor.name in REM_TO_MOD_OPERATION_NAMES.values
&& languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)) {
if (functionDescriptor.name in REM_TO_MOD_OPERATION_NAMES.values &&
languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)
) {
val diagnosticFactory = if (!KotlinBuiltIns.isUnderKotlinPackage(descriptor) &&
languageVersionSettings.supportsFeature(LanguageFeature.ProhibitOperatorMod)
)
Errors.FORBIDDEN_BINARY_MOD
else
Errors.DEPRECATED_BINARY_MOD
val newNameConvention = REM_TO_MOD_OPERATION_NAMES.inverse()[functionDescriptor.name]
diagnosticHolder.report(Errors.DEPRECATED_BINARY_MOD.on(modifier, functionDescriptor, newNameConvention!!.asString()))
diagnosticHolder.report(diagnosticFactory.on(modifier, functionDescriptor, newNameConvention!!.asString()))
}
return

View File

@@ -117,16 +117,26 @@ private fun checkModConvention(
if (KotlinBuiltIns.isUnderKotlinPackage(descriptor)) {
if (shouldWarnAboutDeprecatedModFromBuiltIns(languageVersionSettings)) {
addWarningAboutDeprecatedMod(descriptor, diagnosticHolder, modifier)
warnAboutDeprecatedOrForbiddenMod(descriptor, diagnosticHolder, modifier, languageVersionSettings)
}
} else {
if (languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)) {
addWarningAboutDeprecatedMod(descriptor, diagnosticHolder, modifier)
warnAboutDeprecatedOrForbiddenMod(descriptor, diagnosticHolder, modifier, languageVersionSettings)
}
}
}
private fun addWarningAboutDeprecatedMod(descriptor: FunctionDescriptor, diagnosticHolder: DiagnosticSink, reportOn: PsiElement) {
private fun warnAboutDeprecatedOrForbiddenMod(
descriptor: FunctionDescriptor,
diagnosticHolder: DiagnosticSink,
reportOn: PsiElement,
languageVersionSettings: LanguageVersionSettings
) {
val diagnosticFactory = if (languageVersionSettings.supportsFeature(LanguageFeature.ProhibitOperatorMod))
Errors.FORBIDDEN_BINARY_MOD_AS_REM
else
Errors.DEPRECATED_BINARY_MOD_AS_REM
val newNameConvention = OperatorConventions.REM_TO_MOD_OPERATION_NAMES.inverse()[descriptor.name]
diagnosticHolder.report(Errors.DEPRECATED_BINARY_MOD_AS_REM.on(reportOn, descriptor, newNameConvention!!.asString()))
diagnosticHolder.report(diagnosticFactory.on(reportOn, descriptor, newNameConvention!!.asString()))
}

View File

@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.psi.Call;
import org.jetbrains.kotlin.psi.ValueArgument;
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace;
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilKt;
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
@@ -196,7 +197,14 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
@Override
public void setResultingSubstitutor(@NotNull TypeSubstitutor substitutor) {
resultingDescriptor = (D) candidateDescriptor.substitute(substitutor);
assert resultingDescriptor != null : candidateDescriptor;
//noinspection ConstantConditions
if (resultingDescriptor == null) {
throw new AssertionError(
"resultingDescriptor shouldn't be null:\n" +
"candidateDescriptor: " + DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.render(candidateDescriptor) + "\n" +
"substitution: " + substitutor.getSubstitution()
);
}
for (TypeParameterDescriptor typeParameter : candidateDescriptor.getTypeParameters()) {
TypeProjection typeArgumentProjection = substitutor.getSubstitution().get(typeParameter.getDefaultType());

View File

@@ -92,8 +92,25 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
}
}
internal fun isOptionalAnnotationClass(descriptor: DeclarationDescriptor): Boolean {
return descriptor.annotations.hasAnnotation(OPTIONAL_EXPECTATION_FQ_NAME)
@JvmStatic
fun isOptionalAnnotationClass(descriptor: DeclarationDescriptor): Boolean =
descriptor is ClassDescriptor &&
descriptor.kind == ClassKind.ANNOTATION_CLASS &&
descriptor.isExpect &&
descriptor.annotations.hasAnnotation(OPTIONAL_EXPECTATION_FQ_NAME)
// TODO: move to some other place which is accessible both from backend-common and js.serializer
@JvmStatic
fun shouldGenerateExpectClass(descriptor: ClassDescriptor): Boolean {
assert(descriptor.isExpect) { "Not an expected class: $descriptor" }
if (ExpectedActualDeclarationChecker.isOptionalAnnotationClass(descriptor)) {
with(ExpectedActualResolver) {
return descriptor.findCompatibleActualForExpected(descriptor.module).isEmpty()
}
}
return false
}
private fun ExpectActualTracker.reportExpectActual(expected: MemberDescriptor, actualMembers: Sequence<MemberDescriptor>) {
@@ -135,7 +152,7 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
if (compatibility.allStrongIncompatibilities()) return
if (Compatible in compatibility) {
if (checkActual && requireActualModifier(descriptor, trace)) {
if (checkActual && requireActualModifier(descriptor)) {
trace.report(Errors.ACTUAL_MISSING.on(reportOn))
}
@@ -204,16 +221,14 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
// - annotation constructors, because annotation classes can only have one constructor
// - inline class primary constructors, because inline class must have primary constructor
// - value parameter inside primary constructor of inline class, because inline class must have one value parameter
private fun requireActualModifier(descriptor: MemberDescriptor, trace: BindingTrace): Boolean {
private fun requireActualModifier(descriptor: MemberDescriptor): Boolean {
return !descriptor.isAnnotationConstructor() &&
!descriptor.isPrimaryConstructorOfInlineClass() &&
!isMainPropertyOfInlineClass(descriptor, trace)
!isUnderlyingPropertyOfInlineClass(descriptor)
}
private fun isMainPropertyOfInlineClass(descriptor: MemberDescriptor, trace: BindingTrace): Boolean {
if (descriptor !is PropertyDescriptor) return false
if (!descriptor.containingDeclaration.isInlineClass()) return false
return trace.bindingContext[BindingContext.BACKING_FIELD_REQUIRED, descriptor] == true
private fun isUnderlyingPropertyOfInlineClass(descriptor: MemberDescriptor): Boolean {
return descriptor is PropertyDescriptor && descriptor.isUnderlyingPropertyOfInlineClass()
}
// This should ideally be handled by CallableMemberDescriptor.Kind, but default constructors have kind DECLARATION and non-empty source.

View File

@@ -387,15 +387,19 @@ private class ConstantExpressionEvaluatorVisitor(
}
}
val isUnsigned = hasUnsignedSuffix(text)
val typedConstant = nodeElementType == KtNodeTypes.INTEGER_CONSTANT && (hasLongSuffix(text) || isUnsigned)
val isIntegerConstant = nodeElementType == KtNodeTypes.INTEGER_CONSTANT
val isUnsignedLong = isIntegerConstant && hasUnsignedLongSuffix(text)
val isUnsigned = isUnsignedLong || hasUnsignedSuffix(text)
val isTyped = isUnsigned || hasLongSuffix(text)
return createConstant(
result,
expectedType,
CompileTimeConstant.Parameters(
canBeUsedInAnnotation = true,
isPure = !typedConstant,
isPure = !isTyped,
isUnsignedNumberLiteral = isUnsigned,
isUnsignedLongNumberLiteral = isUnsignedLong,
usesVariableAsConstant = false,
usesNonConstValAsConstant = false
)
@@ -443,6 +447,7 @@ private class ConstantExpressionEvaluatorVisitor(
CompileTimeConstant.Parameters(
isPure = false,
isUnsignedNumberLiteral = false,
isUnsignedLongNumberLiteral = false,
canBeUsedInAnnotation = canBeUsedInAnnotation,
usesVariableAsConstant = usesVariableAsConstant,
usesNonConstValAsConstant = usesNonConstantVariableAsConstant
@@ -506,6 +511,7 @@ private class ConstantExpressionEvaluatorVisitor(
canBeUsedInAnnotation = true,
isPure = false,
isUnsignedNumberLiteral = false,
isUnsignedLongNumberLiteral = false,
usesVariableAsConstant = leftConstant.usesVariableAsConstant || rightConstant.usesVariableAsConstant,
usesNonConstValAsConstant = leftConstant.usesNonConstValAsConstant || rightConstant.usesNonConstValAsConstant
)
@@ -553,7 +559,7 @@ private class ConstantExpressionEvaluatorVisitor(
CompileTimeConstant.Parameters(
canBeUsedInAnnotation,
!isNumberConversionMethod && isArgumentPure,
false,
false, false,
usesVariableAsConstant, usesNonConstValAsConstant
)
)
@@ -586,7 +592,7 @@ private class ConstantExpressionEvaluatorVisitor(
val usesNonConstValAsConstant =
usesNonConstValAsConstant(argumentForReceiver.expression) || usesNonConstValAsConstant(argumentForParameter.expression)
val parameters = CompileTimeConstant.Parameters(
canBeUsedInAnnotation, areArgumentsPure, false, usesVariableAsConstant, usesNonConstValAsConstant
canBeUsedInAnnotation, areArgumentsPure, false, false, usesVariableAsConstant, usesNonConstValAsConstant
)
return when (resultingDescriptorName) {
OperatorNameConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression)?.wrap(parameters)
@@ -708,6 +714,7 @@ private class ConstantExpressionEvaluatorVisitor(
canBeUsedInAnnotation = isPropertyCompileTimeConstant(callableDescriptor),
isPure = false,
isUnsignedNumberLiteral = false,
isUnsignedLongNumberLiteral = false,
usesVariableAsConstant = true,
usesNonConstValAsConstant = !callableDescriptor.isConst
)
@@ -934,10 +941,16 @@ private class ConstantExpressionEvaluatorVisitor(
parameters: CompileTimeConstant.Parameters,
expectedType: KotlinType
): CompileTimeConstant<*>? {
if (parameters.isUnsignedLongNumberLiteral) {
return ULongValue(value).wrap(parameters)
}
if (TypeUtils.noExpectedType(expectedType) || expectedType.isError) {
return createIntegerValueTypeConstant(value, constantExpressionEvaluator.module, parameters)
}
val integerValue = ConstantValueFactory.createIntegerConstantValue(value, expectedType, parameters.isUnsignedNumberLiteral)
val integerValue = ConstantValueFactory.createIntegerConstantValue(
value, expectedType, parameters.isUnsignedNumberLiteral
)
if (integerValue != null) {
return integerValue.wrap(parameters)
}
@@ -962,14 +975,22 @@ private class ConstantExpressionEvaluatorVisitor(
canBeUsedInAnnotation: Boolean = this !is NullValue,
isPure: Boolean = false,
isUnsigned: Boolean = false,
isUnsignedLong: Boolean = false,
usesVariableAsConstant: Boolean = false,
usesNonConstValAsConstant: Boolean = false
): TypedCompileTimeConstant<T> =
wrap(CompileTimeConstant.Parameters(canBeUsedInAnnotation, isPure, isUnsigned, usesVariableAsConstant, usesNonConstValAsConstant))
wrap(
CompileTimeConstant.Parameters(
canBeUsedInAnnotation, isPure, isUnsigned, isUnsignedLong, usesVariableAsConstant, usesNonConstValAsConstant
)
)
}
private fun hasLongSuffix(text: String) = text.endsWith('l') || text.endsWith('L')
private fun hasUnsignedSuffix(text: String) = text.endsWith('u')
private fun hasUnsignedSuffix(text: String) = text.endsWith('u') || text.endsWith('U')
private fun hasUnsignedLongSuffix(text: String) =
text.endsWith("ul") || text.endsWith("uL") ||
text.endsWith("Ul") || text.endsWith("UL")
private fun parseNumericLiteral(text: String, type: IElementType): Any? {
val canonicalText = LiteralFormatUtil.removeUnderscores(text)
@@ -981,13 +1002,33 @@ private fun parseNumericLiteral(text: String, type: IElementType): Any? {
}
private fun parseLong(text: String): Long? {
return try {
val hasUnsignedSuffix = hasUnsignedSuffix(text)
val hasLongSuffix = hasLongSuffix(text)
val textWithoutSuffix = if (hasUnsignedSuffix || hasLongSuffix) text.substring(0, text.length - 1) else text
val (number, radix) = extractRadix(textWithoutSuffix)
fun String.removeSuffix(i: Int): String = this.substring(0, this.length - i)
if (hasUnsignedSuffix) {
return try {
val isUnsigned: Boolean
val numberWithoutSuffix: String
when {
hasUnsignedLongSuffix(text) -> {
isUnsigned = true
numberWithoutSuffix = text.removeSuffix(2)
}
hasUnsignedSuffix(text) -> {
isUnsigned = true
numberWithoutSuffix = text.removeSuffix(1)
}
hasLongSuffix(text) -> {
isUnsigned = false
numberWithoutSuffix = text.removeSuffix(1)
}
else -> {
isUnsigned = false
numberWithoutSuffix = text
}
}
val (number, radix) = extractRadix(numberWithoutSuffix)
if (isUnsigned) {
java.lang.Long.parseUnsignedLong(number, radix)
} else {
java.lang.Long.parseLong(number, radix)

View File

@@ -0,0 +1,20 @@
plugins {
kotlin("jvm")
id("jps-compatible")
}
jvmTarget = "1.6"
dependencies {
compile(project(":compiler:util"))
compile(project(":compiler:frontend"))
compile(project(":compiler:backend-common"))
compile(project(":compiler:ir.tree"))
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
}
sourceSets {
"main" { projectDefault() }
"test" {}
}

View File

@@ -22,10 +22,11 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.isAnnotationClass
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.makeNullable
typealias ReportError = (element: IrElement, message: String) -> Unit
@@ -43,8 +44,9 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor
}
private fun IrExpression.ensureTypeIs(expectedType: KotlinType) {
if (expectedType != type) {
reportError(this, "unexpected expression.type: expected $expectedType, got ${type}")
// TODO: compare IR types instead.
if (expectedType != type.toKotlinType()) {
reportError(this, "unexpected expression.type: expected $expectedType, got ${type.toKotlinType()}")
}
}
@@ -154,9 +156,9 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor
IrTypeOperator.IMPLICIT_CAST,
IrTypeOperator.IMPLICIT_NOTNULL,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
IrTypeOperator.IMPLICIT_INTEGER_COERCION -> typeOperand
IrTypeOperator.IMPLICIT_INTEGER_COERCION -> typeOperand.toKotlinType()
IrTypeOperator.SAFE_CAST -> typeOperand.makeNullable()
IrTypeOperator.SAFE_CAST -> typeOperand.makeNullable().toKotlinType()
IrTypeOperator.INSTANCEOF, IrTypeOperator.NOT_INSTANCEOF -> builtIns.booleanType
}

View File

@@ -20,7 +20,8 @@ import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.expressions.IrLoop
import org.jetbrains.kotlin.ir.util.DeepCopySymbolsRemapper
import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper
import org.jetbrains.kotlin.ir.util.DeepCopyTypeRemapper
import org.jetbrains.kotlin.ir.util.DescriptorsRemapper
import org.jetbrains.kotlin.ir.visitors.acceptVoid
@@ -38,11 +39,13 @@ fun <T : IrElement> T.deepCopyWithVariables(): T {
)
}
val symbolsRemapper = DeepCopySymbolsRemapper(descriptorsRemapper)
val symbolsRemapper = DeepCopySymbolRemapper(descriptorsRemapper)
acceptVoid(symbolsRemapper)
val typesRemapper = DeepCopyTypeRemapper(symbolsRemapper)
return this.transform(
object : DeepCopyIrTreeWithReturnableBlockSymbols(symbolsRemapper) {
object : DeepCopyIrTreeWithReturnableBlockSymbols(symbolsRemapper, typesRemapper) {
override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop {
return irLoop
}

View File

@@ -5,6 +5,7 @@ import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.renderer.*
import org.jetbrains.kotlin.types.KotlinType
@@ -285,7 +286,7 @@ class DumpIrTreeWithDescriptorsVisitor(out: Appendable): IrElementVisitor<Unit,
for (typeParameter in expression.descriptor.original.typeParameters) {
val typeArgument = expression.getTypeArgument(typeParameter) ?: continue
val renderedParameter = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.render(typeParameter)
val renderedType = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.renderType(typeArgument)
val renderedType = typeArgument.render()
printer.println("$renderedParameter: $renderedType")
}
}

View File

@@ -25,10 +25,12 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols
import org.jetbrains.kotlin.ir.util.SymbolRemapper
import org.jetbrains.kotlin.ir.util.TypeRemapper
open class DeepCopyIrTreeWithReturnableBlockSymbols(
private val symbolRemapper: SymbolRemapper
) : DeepCopyIrTreeWithSymbols(symbolRemapper) {
symbolRemapper: SymbolRemapper,
typeRemapper: TypeRemapper
) : DeepCopyIrTreeWithSymbols(symbolRemapper, typeRemapper) {
private inline fun <reified T : IrElement> T.transform() =
transform(this@DeepCopyIrTreeWithReturnableBlockSymbols, null) as T

View File

@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.backend.common.ir
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -26,14 +25,12 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.ir.util.defaultType
import java.io.StringWriter
@@ -77,75 +74,62 @@ fun FunctionDescriptor.createOverriddenDescriptor(owner: ClassDescriptor, final:
}
}
fun ClassDescriptor.createSimpleDelegatingConstructorDescriptor(
superConstructorDescriptor: ClassConstructorDescriptor,
isPrimary: Boolean = false
)
: ClassConstructorDescriptor {
val constructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized(
/* containingDeclaration = */ this,
/* annotations = */ Annotations.EMPTY,
/* isPrimary = */ isPrimary,
/* source = */ SourceElement.NO_SOURCE
)
val valueParameters = superConstructorDescriptor.valueParameters.map {
it.copy(constructorDescriptor, it.name, it.index)
}
constructorDescriptor.initialize(valueParameters, superConstructorDescriptor.visibility)
constructorDescriptor.returnType = superConstructorDescriptor.returnType
return constructorDescriptor
}
fun IrClass.addSimpleDelegatingConstructor(
superConstructorSymbol: IrConstructorSymbol,
constructorDescriptor: ClassConstructorDescriptor,
origin: IrDeclarationOrigin
)
: IrConstructor {
superConstructor: IrConstructor,
irBuiltIns: IrBuiltIns,
origin: IrDeclarationOrigin,
isPrimary: Boolean = false
): IrConstructor {
val superConstructorDescriptor = superConstructor.descriptor
val constructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized(
/* containingDeclaration = */ this.descriptor,
/* annotations = */ Annotations.EMPTY,
/* isPrimary = */ isPrimary,
/* source = */ SourceElement.NO_SOURCE
)
val valueParameters = superConstructor.valueParameters.map {
val descriptor = it.descriptor as ValueParameterDescriptor
val newDescriptor = descriptor.copy(constructorDescriptor, descriptor.name, descriptor.index)
IrValueParameterImpl(
startOffset,
endOffset,
IrDeclarationOrigin.DEFINED,
newDescriptor,
it.type,
it.varargElementType
)
}
constructorDescriptor.initialize(
valueParameters.map { it.descriptor as ValueParameterDescriptor },
superConstructorDescriptor.visibility
)
constructorDescriptor.returnType = superConstructorDescriptor.returnType
return IrConstructorImpl(startOffset, endOffset, origin, constructorDescriptor).also { constructor ->
constructor.createParameterDeclarations()
assert(superConstructor.dispatchReceiverParameter == null) // Inner classes aren't supported.
constructor.valueParameters += valueParameters
constructor.returnType = this.defaultType
constructor.body = IrBlockBodyImpl(
startOffset, endOffset,
listOf(
IrDelegatingConstructorCallImpl(
startOffset, endOffset,
superConstructorSymbol, superConstructorSymbol.descriptor
).apply {
constructor.valueParameters.forEachIndexed { idx, parameter ->
putValueArgument(idx, IrGetValueImpl(startOffset, endOffset, parameter.symbol))
}
},
IrInstanceInitializerCallImpl(startOffset, endOffset, this.symbol)
)
startOffset, endOffset,
listOf(
IrDelegatingConstructorCallImpl(
startOffset, endOffset, irBuiltIns.unitType,
superConstructor.symbol, superConstructor.descriptor
).apply {
constructor.valueParameters.forEachIndexed { idx, parameter ->
putValueArgument(idx, IrGetValueImpl(startOffset, endOffset, parameter.type, parameter.symbol))
}
},
IrInstanceInitializerCallImpl(startOffset, endOffset, this.symbol, irBuiltIns.unitType)
)
)
constructor.parent = this
this.declarations.add(constructor)
}
}
fun CommonBackendContext.createArrayOfExpression(
arrayElementType: KotlinType,
arrayElements: List<IrExpression>,
startOffset: Int, endOffset: Int
): IrExpression {
val genericArrayOfFunSymbol = ir.symbols.arrayOf
val genericArrayOfFun = genericArrayOfFunSymbol.descriptor
val typeParameter0 = genericArrayOfFun.typeParameters[0]
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameter0.typeConstructor to TypeProjectionImpl(arrayElementType)))
val substitutedArrayOfFun = genericArrayOfFun.substitute(typeSubstitutor)!!
val typeArguments = mapOf(typeParameter0 to arrayElementType)
val valueParameter0 = substitutedArrayOfFun.valueParameters[0]
val arg0VarargType = valueParameter0.type
val arg0VarargElementType = valueParameter0.varargElementType!!
val arg0 = IrVarargImpl(startOffset, endOffset, arg0VarargType, arg0VarargElementType, arrayElements)
return IrCallImpl(startOffset, endOffset, genericArrayOfFunSymbol, substitutedArrayOfFun, typeArguments).apply {
putValueArgument(0, arg0)
}
}

View File

@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.lower
@@ -21,7 +10,6 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
@@ -33,8 +21,8 @@ import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
@@ -42,18 +30,13 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
import org.jetbrains.kotlin.resolve.calls.components.isVararg
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.builtIns
open class DefaultArgumentStubGenerator constructor(val context: CommonBackendContext, private val skipInlineMethods: Boolean = true) :
DeclarationContainerLoweringPass {
@@ -82,34 +65,31 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
log { "detected ${functionDescriptor.name.asString()} has got #${bodies.size} default expressions" }
functionDescriptor.overriddenDescriptors.forEach { context.log { "DEFAULT-REPLACER: $it" } }
if (bodies.isNotEmpty()) {
val newIrFunction = functionDescriptor.generateDefaultsFunction(context)
val newIrFunction = irFunction.generateDefaultsFunction(context)
newIrFunction.parent = irFunction.parent
val descriptor = newIrFunction.descriptor
log { "$functionDescriptor -> $descriptor" }
val builder = context.createIrBuilder(newIrFunction.symbol)
newIrFunction.body = builder.irBlockBody(newIrFunction) {
val params = mutableListOf<IrVariableSymbol>()
val variables = mutableMapOf<ValueDescriptor, IrValueSymbol>()
val params = mutableListOf<IrVariable>()
val variables = mutableMapOf<ValueDescriptor, IrValueDeclaration>()
irFunction.dispatchReceiverParameter?.let {
variables[it.descriptor] = newIrFunction.dispatchReceiverParameter!!.symbol
variables[it.descriptor] = newIrFunction.dispatchReceiverParameter!!
}
if (descriptor.extensionReceiverParameter != null) {
variables[functionDescriptor.extensionReceiverParameter!!] =
newIrFunction.extensionReceiverParameter!!.symbol
newIrFunction.extensionReceiverParameter!!
}
for (valueParameter in functionDescriptor.valueParameters) {
val parameterSymbol = newIrFunction.valueParameters[valueParameter.index].symbol
val temporaryVariableSymbol =
IrVariableSymbolImpl(scope.createTemporaryVariableDescriptor(parameterSymbol.descriptor))
params.add(temporaryVariableSymbol)
variables.put(valueParameter, temporaryVariableSymbol)
if (valueParameter.hasDefaultValue()) {
val kIntAnd = symbols.intAnd
val parameter = newIrFunction.valueParameters[valueParameter.index]
val argument = if (valueParameter.hasDefaultValue()) {
val kIntAnd = symbols.intAnd.owner
val condition = irNotEquals(irCall(kIntAnd).apply {
dispatchReceiver = irGet(maskParameterSymbol(newIrFunction, valueParameter.index / 32))
dispatchReceiver = irGet(maskParameter(newIrFunction, valueParameter.index / 32))
putValueArgument(0, irInt(1 shl (valueParameter.index % 32)))
}, irInt(0))
val expressionBody = getDefaultParameterExpressionBody(irFunction, valueParameter)
@@ -122,41 +102,41 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
return irGet(valueSymbol)
}
})
val variableInitialization = irIfThenElse(
type = temporaryVariableSymbol.descriptor.type,
irIfThenElse(
type = parameter.type,
condition = condition,
thenPart = expressionBody.expression,
elsePart = irGet(parameterSymbol)
)
+scope.createTemporaryVariable(
symbol = temporaryVariableSymbol,
initializer = variableInitialization
elsePart = irGet(parameter)
)
/* Mapping calculated values with its origin variables. */
} else {
+scope.createTemporaryVariable(
symbol = temporaryVariableSymbol,
initializer = irGet(parameterSymbol)
)
irGet(parameter)
}
val temporaryVariable = irTemporary(argument, nameHint = parameter.name.asString())
params.add(temporaryVariable)
variables.put(valueParameter, temporaryVariable)
}
if (irFunction is IrConstructor) {
+IrDelegatingConstructorCallImpl(
startOffset = irFunction.startOffset,
endOffset = irFunction.endOffset,
symbol = irFunction.symbol, descriptor = irFunction.symbol.descriptor
type = context.irBuiltIns.unitType,
symbol = irFunction.symbol, descriptor = irFunction.symbol.descriptor,
typeArgumentsCount = irFunction.typeParameters.size
).apply {
params.forEachIndexed { i, variable ->
putValueArgument(i, irGet(variable))
}
if (functionDescriptor.dispatchReceiverParameter != null) {
dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol)
dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!)
}
}
} else {
+irReturn(irCall(irFunction.symbol).apply {
+irReturn(irCall(irFunction).apply {
if (functionDescriptor.dispatchReceiverParameter != null) {
dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol)
dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!)
}
if (functionDescriptor.extensionReceiverParameter != null) {
extensionReceiver = irGet(variables[functionDescriptor.extensionReceiverParameter!!]!!)
@@ -181,50 +161,29 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
private fun log(msg: () -> String) = context.log { "DEFAULT-REPLACER: ${msg()}" }
}
private fun Scope.createTemporaryVariableDescriptor(parameterDescriptor: ParameterDescriptor?): VariableDescriptor =
IrTemporaryVariableDescriptorImpl(
containingDeclaration = this.scopeOwner,
name = parameterDescriptor!!.name.asString().synthesizedName,
outType = parameterDescriptor.type,
isMutable = false
)
private fun Scope.createTemporaryVariable(symbol: IrVariableSymbol, initializer: IrExpression) =
IrVariableImpl(
startOffset = initializer.startOffset,
endOffset = initializer.endOffset,
origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
symbol = symbol
).apply {
this.initializer = initializer
}
private fun getDefaultParameterExpressionBody(irFunction: IrFunction, valueParameter: ValueParameterDescriptor): IrExpressionBody {
return irFunction.getDefault(valueParameter) ?: TODO("FIXME!!!")
}
private fun maskParameterDescriptor(function: IrFunction, number: Int) =
maskParameterSymbol(function, number).descriptor as ValueParameterDescriptor
maskParameter(function, number).descriptor as ValueParameterDescriptor
private fun maskParameterSymbol(function: IrFunction, number: Int) =
function.valueParameters.single { it.descriptor.name == parameterMaskName(number) }.symbol
private fun maskParameter(function: IrFunction, number: Int) =
function.valueParameters.single { it.descriptor.name == parameterMaskName(number) }
private fun markerParameterDescriptor(descriptor: FunctionDescriptor) =
descriptor.valueParameters.single { it.name == kConstructorMarkerName }
private fun nullConst(expression: IrElement, type: KotlinType): IrExpression? {
when {
KotlinBuiltIns.isFloat(type) -> return IrConstImpl.float(expression.startOffset, expression.endOffset, type, 0.0F)
KotlinBuiltIns.isDouble(type) -> return IrConstImpl.double(expression.startOffset, expression.endOffset, type, 0.0)
KotlinBuiltIns.isBoolean(type) -> return IrConstImpl.boolean(expression.startOffset, expression.endOffset, type, false)
KotlinBuiltIns.isByte(type) -> return IrConstImpl.byte(expression.startOffset, expression.endOffset, type, 0)
KotlinBuiltIns.isChar(type) -> return IrConstImpl.char(expression.startOffset, expression.endOffset, type, 0.toChar())
KotlinBuiltIns.isShort(type) -> return IrConstImpl.short(expression.startOffset, expression.endOffset, type, 0)
KotlinBuiltIns.isInt(type) -> return IrConstImpl.int(expression.startOffset, expression.endOffset, type, 0)
KotlinBuiltIns.isLong(type) -> return IrConstImpl.long(expression.startOffset, expression.endOffset, type, 0)
else -> return IrConstImpl.constNull(expression.startOffset, expression.endOffset, type.builtIns.nullableNothingType)
}
private fun nullConst(expression: IrElement, type: IrType, context: CommonBackendContext) = when {
type.isFloat() -> IrConstImpl.float(expression.startOffset, expression.endOffset, type, 0.0F)
type.isDouble() -> IrConstImpl.double(expression.startOffset, expression.endOffset, type, 0.0)
type.isBoolean() -> IrConstImpl.boolean(expression.startOffset, expression.endOffset, type, false)
type.isByte() -> IrConstImpl.byte(expression.startOffset, expression.endOffset, type, 0)
type.isChar() -> IrConstImpl.char(expression.startOffset, expression.endOffset, type, 0.toChar())
type.isShort() -> IrConstImpl.short(expression.startOffset, expression.endOffset, type, 0)
type.isInt() -> IrConstImpl.int(expression.startOffset, expression.endOffset, type, 0)
type.isLong() -> IrConstImpl.long(expression.startOffset, expression.endOffset, type, 0)
else -> IrConstImpl.constNull(expression.startOffset, expression.endOffset, context.irBuiltIns.nothingNType)
}
class DefaultParameterInjector constructor(val context: CommonBackendContext, private val skipInline: Boolean = true) : BodyLoweringPass {
@@ -240,11 +199,14 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
if (argumentsCount == descriptor.valueParameters.size)
return expression
val (symbolForCall, params) = parametersForCall(expression)
symbolForCall as IrConstructorSymbol
return IrDelegatingConstructorCallImpl(
startOffset = expression.startOffset,
endOffset = expression.endOffset,
symbol = symbolForCall as IrConstructorSymbol,
descriptor = symbolForCall.descriptor
type = context.irBuiltIns.unitType,
symbol = symbolForCall,
descriptor = symbolForCall.descriptor,
typeArgumentsCount = symbolForCall.owner.typeParameters.size
)
.apply {
params.forEach {
@@ -273,13 +235,14 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
return IrCallImpl(
startOffset = expression.startOffset,
endOffset = expression.endOffset,
type = symbol.owner.returnType,
symbol = symbol,
descriptor = descriptor,
typeArguments = expression.descriptor.typeParameters.map {
it to (expression.getTypeArgument(it) ?: it.defaultType)
}.toMap()
typeArgumentsCount = expression.typeArgumentsCount
)
.apply {
this.copyTypeArgumentsFrom(expression)
params.forEach {
log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" }
putValueArgument(it.first.index, it.second)
@@ -310,8 +273,7 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
private fun parametersForCall(expression: IrFunctionAccessExpression): Pair<IrFunctionSymbol, List<Pair<ValueParameterDescriptor, IrExpression?>>> {
val descriptor = expression.descriptor
val keyFunction = expression.symbol.owner.findSuperMethodWithDefaultArguments()!!
val keyDescriptor = keyFunction.descriptor
val realFunction = keyDescriptor.generateDefaultsFunction(context)
val realFunction = keyFunction.generateDefaultsFunction(context)
realFunction.parent = keyFunction.parent
val realDescriptor = realFunction.descriptor
@@ -325,15 +287,18 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
maskValues[maskIndex] = maskValues[maskIndex] or (1 shl (i % 32))
}
val valueParameterDescriptor = realDescriptor.valueParameters[i]
val defaultValueArgument =
if (valueParameterDescriptor.isVararg) null else nullConst(expression, valueParameterDescriptor.type)
val defaultValueArgument = if (valueParameterDescriptor.isVararg) {
null
} else {
nullConst(expression, realFunction.valueParameters[i].type, context)
}
valueParameterDescriptor to (valueArgument ?: defaultValueArgument)
})
maskValues.forEachIndexed { i, maskValue ->
params += maskParameterDescriptor(realFunction, i) to IrConstImpl.int(
startOffset = irBody.startOffset,
endOffset = irBody.endOffset,
type = descriptor.builtIns.intType,
type = context.irBuiltIns.intType,
value = maskValue
)
}
@@ -347,7 +312,7 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
)
} else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) {
params += realDescriptor.valueParameters.last() to
IrConstImpl.constNull(irBody.startOffset, irBody.endOffset, context.builtIns.any.defaultType)
IrConstImpl.constNull(irBody.startOffset, irBody.endOffset, context.irBuiltIns.nothingNType)
}
params.forEach {
log { "descriptor::${realDescriptor.name.asString()}#${it.first.index}: ${it.first.name.asString()}" }
@@ -366,7 +331,7 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
private fun CallableMemberDescriptor.needsDefaultArgumentsLowering(skipInlineMethods: Boolean) =
valueParameters.any { it.hasDefaultValue() } && !(this is FunctionDescriptor && isInline && skipInlineMethods)
private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendContext): IrFunction {
private fun IrFunction.generateDefaultsFunction(context: CommonBackendContext): IrFunction = with(this.descriptor) {
return context.ir.defaultParameterDeclarationsCache.getOrPut(this) {
val descriptor = when (this) {
is ClassConstructorDescriptor ->
@@ -389,8 +354,10 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
}
}
val function = this@generateDefaultsFunction
val syntheticParameters = MutableList((valueParameters.size + 31) / 32) { i ->
valueParameter(descriptor, valueParameters.size + i, parameterMaskName(i), descriptor.builtIns.intType)
valueParameter(descriptor, valueParameters.size + i, parameterMaskName(i), context.irBuiltIns.intType)
}
if (this is ClassConstructorDescriptor) {
syntheticParameters += valueParameter(
@@ -402,10 +369,29 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
syntheticParameters += valueParameter(
descriptor, syntheticParameters.last().index + 1,
"handler".synthesizedName,
context.ir.symbols.any.owner.defaultType
context.irBuiltIns.anyType
)
}
val newValueParameters = function.valueParameters.map {
val parameterDescriptor = ValueParameterDescriptorImpl(
containingDeclaration = descriptor,
original = null, /* ValueParameterDescriptorImpl::copy do not save original. */
index = it.index,
annotations = it.descriptor.annotations,
name = it.name,
outType = it.descriptor.type,
declaresDefaultValue = false,
isCrossinline = it.isCrossinline,
isNoinline = it.isNoinline,
varargElementType = (it.descriptor as ValueParameterDescriptor).varargElementType,
source = it.descriptor.source
)
it.copy(parameterDescriptor)
} + syntheticParameters
descriptor.initialize(
/* receiverParameterType = */ extensionReceiverParameter?.type,
/* dispatchReceiverParameter = */ dispatchReceiverParameter,
@@ -425,24 +411,11 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
setInitialized()
}
},
/* unsubstitutedValueParameters = */ valueParameters.map {
ValueParameterDescriptorImpl(
containingDeclaration = descriptor,
original = null, /* ValueParameterDescriptorImpl::copy do not save original. */
index = it.index,
annotations = it.annotations,
name = it.name,
outType = it.type,
declaresDefaultValue = false,
isCrossinline = it.isCrossinline,
isNoinline = it.isNoinline,
varargElementType = it.varargElementType,
source = it.source
)
} + syntheticParameters,
/* unsubstitutedValueParameters = */ newValueParameters.map { it.descriptor as ValueParameterDescriptor },
/* unsubstitutedReturnType = */ returnType,
/* modality = */ Modality.FINAL,
/* visibility = */ this.visibility)
/* visibility = */ this.visibility
)
descriptor.isSuspend = this.isSuspend
context.log { "adds to cache[$this] = $descriptor" }
@@ -463,7 +436,29 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
)
}
result.createParameterDeclarations()
result.returnType = function.returnType
function.typeParameters.mapTo(result.typeParameters) {
assert(function.descriptor.typeParameters[it.index] == it.descriptor)
IrTypeParameterImpl(
startOffset, endOffset, origin, descriptor.typeParameters[it.index]
).apply { this.superTypes += it.superTypes }
}
result.parent = function.parent
result.createDispatchReceiverParameter()
function.extensionReceiverParameter?.let {
result.extensionReceiverParameter = IrValueParameterImpl(
it.startOffset,
it.endOffset,
it.origin,
descriptor.extensionReceiverParameter!!,
it.type,
it.varargElementType
).apply { parent = result }
}
result.valueParameters += newValueParameters.also { it.forEach { it.parent = result } }
result
}
@@ -472,20 +467,28 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
object DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER :
IrDeclarationOriginImpl("DEFAULT_PARAMETER_EXTENT")
private fun valueParameter(descriptor: FunctionDescriptor, index: Int, name: Name, type: KotlinType): ValueParameterDescriptor {
return ValueParameterDescriptorImpl(
private fun IrFunction.valueParameter(descriptor: FunctionDescriptor, index: Int, name: Name, type: IrType): IrValueParameter {
val parameterDescriptor = ValueParameterDescriptorImpl(
containingDeclaration = descriptor,
original = null,
index = index,
annotations = Annotations.EMPTY,
name = name,
outType = type,
outType = type.toKotlinType(),
declaresDefaultValue = false,
isCrossinline = false,
isNoinline = false,
varargElementType = null,
source = SourceElement.NO_SOURCE
)
return IrValueParameterImpl(
startOffset,
endOffset,
IrDeclarationOrigin.DEFINED,
parameterDescriptor,
type,
null
)
}
internal val kConstructorMarkerName = "marker".synthesizedName

View File

@@ -68,7 +68,7 @@ class InitializersLowering(
if (declaration.descriptor.dispatchReceiverParameter != null) // TODO isStaticField
IrGetValueImpl(
irFieldInitializer.startOffset, irFieldInitializer.endOffset,
irClass.thisReceiver!!.symbol
irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol
)
else null
val irSetField = IrSetFieldImpl(
@@ -76,6 +76,7 @@ class InitializersLowering(
declaration.symbol,
receiver,
irFieldInitializer,
context.irBuiltIns.unitType,
null, null
)
@@ -93,7 +94,7 @@ class InitializersLowering(
fun transformInstanceInitializerCallsInConstructors(irClass: IrClass) {
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression {
return IrBlockImpl(irClass.startOffset, irClass.endOffset, context.builtIns.unitType, null,
return IrBlockImpl(irClass.startOffset, irClass.endOffset, context.irBuiltIns.unitType, null,
instanceInitializerStatements.map { it.copy(irClass) })
}
})

View File

@@ -20,7 +20,10 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
import java.util.*
@@ -67,12 +70,14 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
}
private fun createOuterThisField() {
val fieldSymbol = context.descriptorsFactory.getOuterThisFieldSymbol(irClass)
irClass.declarations.add(
IrFieldImpl(
irClass.startOffset, irClass.endOffset,
FIELD_FOR_OUTER_THIS,
context.descriptorsFactory.getOuterThisFieldSymbol(irClass)
).also {
fieldSymbol,
irClass.defaultType
).also {
outerThisField = it
}
)
@@ -97,7 +102,10 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
irConstructor.origin, // TODO special origin for lowered inner class constructors?
newSymbol,
null
)
).apply {
returnType = irConstructor.returnType
}
loweredConstructor.createParameterDeclarations()
val outerThisValueParameter = loweredConstructor.valueParameters[0].symbol
@@ -115,7 +123,8 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
IrSetFieldImpl(
startOffset, endOffset, outerThisField.symbol,
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
IrGetValueImpl(startOffset, endOffset, outerThisValueParameter)
IrGetValueImpl(startOffset, endOffset, outerThisValueParameter),
context.irBuiltIns.unitType
)
)
} else {
@@ -166,7 +175,7 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
}
val outerThisField = context.descriptorsFactory.getOuterThisFieldSymbol(innerClass)
irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField, irThis, origin)
irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField, innerClass.defaultType, irThis, origin)
val outer = innerClass.parent
innerClass = outer as? IrClass ?:
@@ -204,8 +213,8 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe
val newCallee = context.descriptorsFactory.getInnerClassConstructorWithOuterThisParameter(callee.owner)
val newCall = IrCallImpl(
expression.startOffset, expression.endOffset, newCallee, newCallee.descriptor,
null, // TODO type arguments map
expression.startOffset, expression.endOffset, expression.type, newCallee, newCallee.descriptor,
0, // TODO type arguments map
expression.origin
)
@@ -226,7 +235,7 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe
val newCallee = context.descriptorsFactory.getInnerClassConstructorWithOuterThisParameter(classConstructor)
val newCall = IrDelegatingConstructorCallImpl(
expression.startOffset, expression.endOffset, newCallee, newCallee.descriptor,
expression.startOffset, expression.endOffset, context.irBuiltIns.unitType, newCallee, newCallee.descriptor,
classConstructor.typeParameters.size
).apply { copyTypeArgumentsFrom(expression) }

View File

@@ -16,26 +16,8 @@
package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
abstract class SymbolWithIrBuilder<out S: IrSymbol, out D: IrDeclaration> {
@@ -62,155 +44,3 @@ abstract class SymbolWithIrBuilder<out S: IrSymbol, out D: IrDeclaration> {
return builtIr
}
}
fun BackendContext.createPropertyGetterBuilder(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin,
fieldSymbol: IrFieldSymbol, type: KotlinType)
= object: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
PropertyGetterDescriptorImpl(
/* correspondingProperty = */ fieldSymbol.descriptor,
/* annotations = */ Annotations.EMPTY,
/* modality = */ Modality.FINAL,
/* visibility = */ Visibilities.PRIVATE,
/* isDefault = */ false,
/* isExternal = */ false,
/* isInline = */ false,
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
/* original = */ null,
/* source = */ SourceElement.NO_SOURCE
)
)
override fun doInitialize() {
val descriptor = symbol.descriptor as PropertyGetterDescriptorImpl
descriptor.apply {
initialize(type)
}
}
override fun buildIr() = IrFunctionImpl(
startOffset = startOffset,
endOffset = endOffset,
origin = origin,
symbol = symbol).apply {
createParameterDeclarations()
body = createIrBuilder(this.symbol, startOffset, endOffset).irBlockBody {
+irReturn(irGetField(irGet(this@apply.dispatchReceiverParameter!!.symbol), fieldSymbol))
}
}
}
private fun BackendContext.createPropertySetterBuilder(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin,
fieldSymbol: IrFieldSymbol, type: KotlinType)
= object: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
PropertySetterDescriptorImpl(
/* correspondingProperty = */ fieldSymbol.descriptor,
/* annotations = */ Annotations.EMPTY,
/* modality = */ Modality.FINAL,
/* visibility = */ Visibilities.PRIVATE,
/* isDefault = */ false,
/* isExternal = */ false,
/* isInline = */ false,
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
/* original = */ null,
/* source = */ SourceElement.NO_SOURCE
)
)
lateinit var valueParameterDescriptor: ValueParameterDescriptor
override fun doInitialize() {
val descriptor = symbol.descriptor as PropertySetterDescriptorImpl
descriptor.apply {
valueParameterDescriptor = ValueParameterDescriptorImpl(
containingDeclaration = this,
original = null,
index = 0,
annotations = Annotations.EMPTY,
name = Name.identifier("value"),
outType = type,
declaresDefaultValue = false,
isCrossinline = false,
isNoinline = false,
varargElementType = null,
source = SourceElement.NO_SOURCE
)
initialize(valueParameterDescriptor)
}
}
override fun buildIr() = IrFunctionImpl(
startOffset = startOffset,
endOffset = endOffset,
origin = origin,
symbol = symbol).apply {
createParameterDeclarations()
body = createIrBuilder(this.symbol, startOffset, endOffset).irBlockBody {
+irSetField(irGet(this@apply.dispatchReceiverParameter!!.symbol), fieldSymbol, irGet(this@apply.valueParameters.single().symbol))
}
}
}
fun BackendContext.createPropertyWithBackingFieldBuilder(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin,
owner: ClassDescriptor, name: Name, type: KotlinType, isMutable: Boolean)
= object: SymbolWithIrBuilder<IrFieldSymbol, IrProperty>() {
private lateinit var getterBuilder: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>
private var setterBuilder: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>? = null
override fun buildSymbol() = IrFieldSymbolImpl(
PropertyDescriptorImpl.create(
/* containingDeclaration = */ owner,
/* annotations = */ Annotations.EMPTY,
/* modality = */ Modality.FINAL,
/* visibility = */ Visibilities.PRIVATE,
/* isVar = */ isMutable,
/* name = */ name,
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
/* source = */ SourceElement.NO_SOURCE,
/* lateInit = */ false,
/* isConst = */ false,
/* isExpect = */ false,
/* isActual = */ false,
/* isExternal = */ false,
/* isDelegated = */ false
)
)
override fun doInitialize() {
val descriptor = symbol.descriptor as PropertyDescriptorImpl
getterBuilder = createPropertyGetterBuilder(startOffset, endOffset, origin, symbol, type).apply { initialize() }
if (isMutable)
setterBuilder = createPropertySetterBuilder(startOffset, endOffset, origin, symbol, type).apply { initialize() }
descriptor.initialize(
/* getter = */ getterBuilder.symbol.descriptor as PropertyGetterDescriptorImpl,
/* setter = */ setterBuilder?.symbol?.descriptor as? PropertySetterDescriptorImpl)
val receiverType: KotlinType? = null
descriptor.setType(type, emptyList(), owner.thisAsReceiverParameter, receiverType)
}
override fun buildIr(): IrProperty {
val backingField = IrFieldImpl(
startOffset = startOffset,
endOffset = endOffset,
origin = origin,
symbol = symbol)
return IrPropertyImpl(
startOffset = startOffset,
endOffset = endOffset,
origin = origin,
isDelegated = false,
descriptor = symbol.descriptor,
backingField = backingField,
getter = getterBuilder.ir,
setter = setterBuilder?.ir)
}
}

View File

@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.builtins.getFunctionalClassKind
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.builders.IrGeneratorContextBase
import org.jetbrains.kotlin.ir.builders.Scope
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.IrCall
@@ -58,7 +58,7 @@ private class KCallableNamePropertyTransformer(val lower: KCallableNamePropertyL
return lower.context.createIrBuilder(expression.symbol, expression.startOffset, expression.endOffset).run {
IrCompositeImpl(startOffset, endOffset, context.builtIns.stringType).apply {
IrCompositeImpl(startOffset, endOffset, context.irBuiltIns.stringType).apply {
receiver?.let {
//put receiver for bound callable reference
statements.add(it)
@@ -68,7 +68,7 @@ private class KCallableNamePropertyTransformer(val lower: KCallableNamePropertyL
IrConstImpl.string(
expression.startOffset,
expression.endOffset,
context.builtIns.stringType,
context.irBuiltIns.stringType,
callableReference.descriptor.name.asString()
)
)
@@ -104,5 +104,5 @@ private class KCallableNamePropertyTransformer(val lower: KCallableNamePropertyL
endOffset
)
class IrLoweringContext(backendContext: BackendContext) : IrGeneratorContext(backendContext.irBuiltIns)
class IrLoweringContext(backendContext: BackendContext) : IrGeneratorContextBase(backendContext.irBuiltIns)
}

View File

@@ -27,6 +27,8 @@ import org.jetbrains.kotlin.ir.expressions.IrBlock
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isPrimitiveType
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.types.KotlinType
@@ -45,20 +47,20 @@ class LateinitLowering(
private fun transformGetter(backingField: IrField, getter: IrFunction) {
val type = backingField.type
assert(!KotlinBuiltIns.isPrimitiveType(type)) { "'lateinit' modifier is not allowed on primitive types" }
assert(!type.isPrimitiveType()) { "'lateinit' modifier is not allowed on primitive types" }
val startOffset = getter.startOffset
val endOffset = getter.endOffset
val irBuilder = context.createIrBuilder(getter.symbol, startOffset, endOffset)
irBuilder.run {
val block = irBlock(type)
val resultVar = scope.createTemporaryVariable(
irGetField(getter.dispatchReceiverParameter?.let { irGet(it.symbol) }, backingField.symbol)
irGetField(getter.dispatchReceiverParameter?.let { irGet(it) }, backingField)
)
block.statements.add(resultVar)
val throwIfNull = irIfThenElse(
context.builtIns.nothingType,
irNotEquals(irGet(resultVar.symbol), irNull()),
irReturn(irGet(resultVar.symbol)),
context.irBuiltIns.nothingType,
irNotEquals(irGet(resultVar), irNull()),
irReturn(irGet(resultVar)),
throwUninitializedPropertyAccessException(backingField)
)
block.statements.add(throwIfNull)
@@ -76,15 +78,15 @@ class LateinitLowering(
IrConstImpl.string(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
context.builtIns.stringType,
context.irBuiltIns.stringType,
backingField.name.asString()
)
)
}
}
private val throwErrorFunction = context.ir.symbols.ThrowUninitializedPropertyAccessException
private val throwErrorFunction = context.ir.symbols.ThrowUninitializedPropertyAccessException.owner
private fun IrBuilderWithScope.irBlock(type: KotlinType): IrBlock = IrBlockImpl(startOffset, endOffset, type)
private fun IrBuilderWithScope.irBlock(type: IrType): IrBlock = IrBlockImpl(startOffset, endOffset, type)
}

View File

@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.lower
@@ -21,21 +10,25 @@ import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.*
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.parents
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
import org.jetbrains.kotlin.types.KotlinType
import java.util.*
interface LocalNameProvider {
@@ -99,12 +92,12 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
abstract val transformedDescriptor: FunctionDescriptor
abstract val transformedDeclaration: IrFunction
val capturedValueToParameter: MutableMap<ValueDescriptor, IrValueParameterSymbol> = HashMap()
val capturedValueToParameter: MutableMap<ValueDescriptor, IrValueParameter> = HashMap()
override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? {
val newSymbol = capturedValueToParameter[descriptor] ?: return null
val parameter = capturedValueToParameter[descriptor] ?: return null
return IrGetValueImpl(startOffset, endOffset, newSymbol)
return IrGetValueImpl(startOffset, endOffset, parameter.type, parameter.symbol)
}
}
@@ -142,9 +135,10 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? {
val field = capturedValueToField[descriptor] ?: return null
val receiver = declaration.thisReceiver!!
return IrGetFieldImpl(
startOffset, endOffset, field.symbol,
receiver = IrGetValueImpl(startOffset, endOffset, declaration.thisReceiver!!.symbol)
startOffset, endOffset, field.symbol, field.type,
receiver = IrGetValueImpl(startOffset, endOffset, receiver.type, receiver.symbol)
)
}
@@ -156,9 +150,10 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? {
val field = classContext.capturedValueToField[descriptor] ?: return null
val receiver = member.dispatchReceiverParameter!!
return IrGetFieldImpl(
startOffset, endOffset, field.symbol,
receiver = IrGetValueImpl(startOffset, endOffset, member.dispatchReceiverParameter!!.symbol)
startOffset, endOffset, field.symbol, field.type,
receiver = IrGetValueImpl(startOffset, endOffset, receiver.type, receiver.symbol)
)
}
@@ -169,12 +164,12 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val localClasses: MutableMap<ClassDescriptor, LocalClassContext> = LinkedHashMap()
val localClassConstructors: MutableMap<ClassConstructorDescriptor, LocalClassConstructorContext> = LinkedHashMap()
val transformedDeclarations = mutableMapOf<DeclarationDescriptor, IrSymbol>()
val transformedDeclarations = mutableMapOf<DeclarationDescriptor, IrDeclaration>()
val FunctionDescriptor.transformed: IrFunctionSymbol?
get() = transformedDeclarations[this] as IrFunctionSymbol?
val FunctionDescriptor.transformed: IrFunction?
get() = transformedDeclarations[this] as IrFunction?
val oldParameterToNew: MutableMap<ParameterDescriptor, IrValueParameterSymbol> = HashMap()
val oldParameterToNew: MutableMap<ParameterDescriptor, IrValueParameter> = HashMap()
val newParameterToOld: MutableMap<ParameterDescriptor, ParameterDescriptor> = HashMap()
val newParameterToCaptured: MutableMap<ValueParameterDescriptor, IrValueSymbol> = HashMap()
@@ -201,7 +196,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
original.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument ->
val body = original.getDefault(argument)!!
oldParameterToNew[argument]!!.owner.defaultValue = body
oldParameterToNew[argument]!!.defaultValue = body
}
}
}
@@ -219,7 +214,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
override fun visitClass(declaration: IrClass): IrStatement {
if (declaration.descriptor in localClasses) {
// Replace local class definition with an empty composite.
return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.builtIns.unitType)
return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.irBuiltIns.unitType)
} else {
return super.visitClass(declaration)
}
@@ -228,7 +223,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
override fun visitFunction(declaration: IrFunction): IrStatement {
if (declaration.descriptor in localFunctions) {
// Replace local function definition with an empty composite.
return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.builtIns.unitType)
return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.irBuiltIns.unitType)
} else {
if (localContext is LocalClassContext && declaration.parent == localContext.declaration) {
return declaration.apply {
@@ -251,7 +246,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
declaration.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument ->
val body = declaration.getDefault(argument)!!
oldParameterToNew[argument]!!.owner.defaultValue = body
oldParameterToNew[argument]!!.defaultValue = body
}
}
} else {
@@ -267,7 +262,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
}
oldParameterToNew[descriptor]?.let {
return IrGetValueImpl(expression.startOffset, expression.endOffset, it)
return IrGetValueImpl(expression.startOffset, expression.endOffset, it.type, it.symbol)
}
return expression
@@ -288,14 +283,18 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
expression.transformChildrenVoid(this)
val oldCallee = expression.descriptor.original
val newCallee = transformedDeclarations[oldCallee] as IrConstructorSymbol? ?: return expression
val newCallee = transformedDeclarations[oldCallee] as IrConstructor? ?: return expression
return IrDelegatingConstructorCallImpl(
expression.startOffset, expression.endOffset,
newCallee,
context.irBuiltIns.unitType,
newCallee.symbol,
newCallee.descriptor,
remapTypeArguments(expression, newCallee.descriptor)
).fillArguments(expression)
expression.typeArgumentsCount
).also {
it.fillArguments(expression)
it.copyTypeArgumentsFrom(expression)
}
}
private fun <T : IrMemberAccessExpression> T.fillArguments(oldExpression: IrMemberAccessExpression): T {
@@ -311,16 +310,17 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
newParameterToCaptured[newValueParameterDescriptor]
?: throw AssertionError("Non-mapped parameter $newValueParameterDescriptor")
val capturedValue = capturedValueSymbol.owner
val capturedValueDescriptor = capturedValueSymbol.descriptor
localContext?.irGet(
oldExpression.startOffset, oldExpression.endOffset,
capturedValueDescriptor
) ?:
// Captured value is directly available for the caller.
IrGetValueImpl(
oldExpression.startOffset, oldExpression.endOffset,
oldParameterToNew[capturedValueDescriptor] ?: capturedValueSymbol
)
) ?: run {
// Captured value is directly available for the caller.
val value = oldParameterToNew[capturedValueDescriptor] ?: capturedValue
IrGetValueImpl(oldExpression.startOffset, oldExpression.endOffset, value.symbol)
}
}
}
@@ -340,11 +340,14 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val newCallableReference = IrFunctionReferenceImpl(
expression.startOffset, expression.endOffset,
expression.type, // TODO functional type for transformed descriptor
newCallee,
newCallee.symbol,
newCallee.descriptor,
remapTypeArguments(expression, newCallee.descriptor),
expression.typeArgumentsCount,
expression.origin
).fillArguments(expression)
).also {
it.fillArguments(expression)
it.copyTypeArgumentsFrom(expression)
}
return newCallableReference
}
@@ -355,7 +358,11 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val oldReturnTarget = expression.returnTarget
val newReturnTarget = oldReturnTarget.transformed ?: return expression
return IrReturnImpl(expression.startOffset, expression.endOffset, newReturnTarget, expression.value)
return IrReturnImpl(
expression.startOffset, expression.endOffset,
context.irBuiltIns.nothingType,
newReturnTarget.symbol, expression.value
)
}
override fun visitDeclarationReference(expression: IrDeclarationReference): IrExpression {
@@ -400,7 +407,9 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
IrSetFieldImpl(
startOffset, endOffset, field.symbol,
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
capturedValueExpression, STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE
capturedValueExpression,
context.irBuiltIns.unitType,
STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE
)
)
}
@@ -423,31 +432,20 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
rewriteFunctionBody(memberDeclaration, null)
}
private fun createNewCall(oldCall: IrCall, newCallee: IrFunctionSymbol) =
private fun createNewCall(oldCall: IrCall, newCallee: IrFunction) =
if (oldCall is IrCallWithShallowCopy)
oldCall.shallowCopy(oldCall.origin, newCallee, oldCall.superQualifierSymbol)
oldCall.shallowCopy(oldCall.origin, newCallee.symbol, oldCall.superQualifierSymbol)
else
IrCallImpl(
oldCall.startOffset, oldCall.endOffset,
newCallee,
newCallee.returnType,
newCallee.symbol,
newCallee.descriptor,
remapTypeArguments(oldCall, newCallee.descriptor),
oldCall.typeArgumentsCount,
oldCall.origin, oldCall.superQualifierSymbol
)
private fun remapTypeArguments(
oldExpression: IrMemberAccessExpression,
newCallee: CallableDescriptor
): Map<TypeParameterDescriptor, KotlinType>? {
val oldCallee = oldExpression.descriptor.original
return if (oldCallee.typeParameters.isEmpty())
null
else oldCallee.typeParameters.associateBy(
{ newCallee.typeParameters[it.index] },
{ oldExpression.getTypeArgumentOrDefault(it) }
)
}
).also {
it.copyTypeArgumentsFrom(oldCall)
}
private fun transformDescriptors() {
localFunctions.values.forEach {
@@ -520,7 +518,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
oldDescriptor.extensionReceiverParameter?.type,
newDispatchReceiverParameter,
newTypeParameters,
newValueParameters,
newValueParameters.map { it.descriptor as ValueParameterDescriptor },
oldDescriptor.returnType,
Modality.FINAL,
Visibilities.PRIVATE
@@ -534,9 +532,26 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
IrFunctionImpl(startOffset, endOffset, origin, newDescriptor)
}.apply {
parent = memberDeclaration.parent
createParameterDeclarations()
returnType = localFunctionContext.declaration.returnType
localFunctionContext.declaration.typeParameters.mapTo(this.typeParameters) {
IrTypeParameterImpl(it.startOffset, it.endOffset, it.origin, it.descriptor)
.apply { superTypes += it.superTypes }
}
localFunctionContext.declaration.extensionReceiverParameter?.let {
this.extensionReceiverParameter = IrValueParameterImpl(
it.startOffset,
it.endOffset,
it.origin,
descriptor.extensionReceiverParameter!!,
it.type,
null
)
}
this.valueParameters += newValueParameters
recordTransformedValueParameters(localFunctionContext)
transformedDeclarations[oldDescriptor] = this.symbol
transformedDeclarations[oldDescriptor] = this
}
}
@@ -544,7 +559,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
localContext: LocalContextWithClosureAsParameters,
capturedValues: List<IrValueSymbol>
)
: List<ValueParameterDescriptor> {
: List<IrValueParameter> {
val oldDescriptor = localContext.descriptor
val newDescriptor = localContext.transformedDescriptor
@@ -552,17 +567,23 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val closureParametersCount = capturedValues.size
val newValueParametersCount = closureParametersCount + oldDescriptor.valueParameters.size
val newValueParameters = ArrayList<ValueParameterDescriptor>(newValueParametersCount).apply {
val newValueParameters = ArrayList<IrValueParameter>(newValueParametersCount).apply {
capturedValues.mapIndexedTo(this) { i, capturedValue ->
createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValue.descriptor, i).apply {
val parameterDescriptor = createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValue.descriptor, i).apply {
newParameterToCaptured[this] = capturedValue
}
capturedValue.owner.copy(parameterDescriptor)
}
oldDescriptor.valueParameters.mapIndexedTo(this) { i, oldValueParameterDescriptor ->
createUnsubstitutedParameter(newDescriptor, oldValueParameterDescriptor, closureParametersCount + i).apply {
newParameterToOld.putAbsentOrSame(this, oldValueParameterDescriptor)
localContext.declaration.valueParameters.mapIndexedTo(this) { i, oldValueParameter ->
val parameterDescriptor = createUnsubstitutedParameter(
newDescriptor,
oldValueParameter.descriptor as ValueParameterDescriptor,
closureParametersCount + i
).apply {
newParameterToOld.putAbsentOrSame(this, oldValueParameter.descriptor)
}
oldValueParameter.copy(parameterDescriptor)
}
}
return newValueParameters
@@ -573,14 +594,14 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
valueParameters.forEach {
val capturedValue = newParameterToCaptured[it.descriptor]
if (capturedValue != null) {
localContext.capturedValueToParameter[capturedValue.descriptor] = it.symbol
localContext.capturedValueToParameter[capturedValue.descriptor] = it
}
}
(listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).forEach {
val oldParameter = newParameterToOld[it.descriptor]
if (oldParameter != null) {
oldParameterToNew.putAbsentOrSame(oldParameter, it.symbol)
oldParameterToNew.putAbsentOrSame(oldParameter, it)
}
}
@@ -604,7 +625,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val newValueParameters = createTransformedValueParameters(constructorContext, capturedValues)
newDescriptor.initialize(
newValueParameters,
newValueParameters.map { it.descriptor as ValueParameterDescriptor },
Visibilities.PRIVATE,
newTypeParameters
)
@@ -619,12 +640,23 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
}
constructorContext.transformedDeclaration = with(constructorContext.declaration) {
IrConstructorImpl(startOffset, endOffset, origin, newDescriptor)
IrConstructorImpl(startOffset, endOffset, origin, newDescriptor).also { it.returnType = returnType }
}.apply {
parent = constructorContext.declaration.parent
createParameterDeclarations()
constructorContext.declaration.dispatchReceiverParameter?.let {
this.dispatchReceiverParameter = IrValueParameterImpl(
it.startOffset,
it.endOffset,
it.origin,
descriptor.dispatchReceiverParameter!!,
it.type,
null
)
}
this.valueParameters += newValueParameters
recordTransformedValueParameters(constructorContext)
transformedDeclarations[oldDescriptor] = this.symbol
transformedDeclarations[oldDescriptor] = this
}
}
@@ -663,7 +695,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
localClassContext.capturedValueToField[capturedValue.descriptor] = IrFieldImpl(
localClassContext.declaration.startOffset, localClassContext.declaration.endOffset,
DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE,
fieldDescriptor
fieldDescriptor, capturedValue.owner.type
).apply {
parent = localClassContext.declaration
}
@@ -776,4 +808,13 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
}
}
}
}
private fun IrValueDeclaration.copy(newDescriptor: ParameterDescriptor): IrValueParameter = IrValueParameterImpl(
startOffset,
endOffset,
IrDeclarationOrigin.DEFINED,
newDescriptor,
type,
(this as? IrValueParameter)?.varargElementType
)

View File

@@ -1,372 +0,0 @@
/*
* 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.common.lower
import org.jetbrains.kotlin.backend.common.AbstractClosureAnnotator
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.Closure
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
import org.jetbrains.kotlin.types.KotlinType
import java.util.*
class LocalFunctionsLowering(val context: BackendContext): DeclarationContainerLoweringPass {
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
irDeclarationContainer.declarations.transformFlat { memberDeclaration ->
if (memberDeclaration is IrFunction)
LocalFunctionsTransformer(memberDeclaration).lowerLocalFunctions()
else
null
}
}
private class LocalFunctionContext(val declaration: IrFunction) {
lateinit var closure: Closure
val closureParametersCount: Int get() = closure.capturedValues.size
lateinit var transformedDescriptor: FunctionDescriptor
val old2new: MutableMap<ValueDescriptor, ParameterDescriptor> = HashMap()
var index: Int = -1
override fun toString(): String =
"LocalFunctionContext for ${declaration.descriptor}"
}
private inner class LocalFunctionsTransformer(val memberFunction: IrFunction) {
val localFunctions: MutableMap<FunctionDescriptor, LocalFunctionContext> = LinkedHashMap()
val new2old: MutableMap<ParameterDescriptor, ValueDescriptor> = HashMap()
fun lowerLocalFunctions(): List<IrDeclaration>? {
collectLocalFunctions()
if (localFunctions.isEmpty()) return null
collectClosures()
transformDescriptors()
rewriteBodies()
return collectRewrittenDeclarations()
}
private fun collectRewrittenDeclarations(): ArrayList<IrDeclaration> =
ArrayList<IrDeclaration>(localFunctions.size + 1).apply {
add(memberFunction)
localFunctions.values.mapTo(this) {
val original = it.declaration
IrFunctionImpl(
original.startOffset, original.endOffset, original.origin,
it.transformedDescriptor,
original.body
)
}
}
private inner class FunctionBodiesRewriter(val localFunctionContext: LocalFunctionContext?) : IrElementTransformerVoid() {
override fun visitClass(declaration: IrClass): IrStatement {
// ignore local classes for now
return declaration
}
override fun visitFunction(declaration: IrFunction): IrStatement {
// replace local function definition with an empty composite
return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.builtIns.unitType)
}
override fun visitGetValue(expression: IrGetValue): IrExpression {
val remapped = localFunctionContext?.let { it.old2new[expression.descriptor] }
return if (remapped == null)
expression
else
IrGetValueImpl(expression.startOffset, expression.endOffset, remapped, expression.origin)
}
override fun visitCall(expression: IrCall): IrExpression {
expression.transformChildrenVoid(this)
val oldCallee = expression.descriptor.original
val localFunctionData = localFunctions[oldCallee] ?: return expression
val newCallee = localFunctionData.transformedDescriptor
return createNewCall(expression, newCallee).fillArguments(localFunctionData, expression)
}
private fun <T : IrMemberAccessExpression> T.fillArguments(calleeContext: LocalFunctionContext, oldExpression: IrMemberAccessExpression): T {
val closureParametersCount = calleeContext.closureParametersCount
mapValueParametersIndexed { index, newValueParameterDescriptor ->
val capturedValueDescriptor = new2old[newValueParameterDescriptor] ?:
throw AssertionError("Non-mapped parameter $newValueParameterDescriptor")
if (index >= closureParametersCount)
oldExpression.getValueArgument(capturedValueDescriptor as ValueParameterDescriptor)
else {
val remappedValueDescriptor = localFunctionContext?.let { it.old2new[capturedValueDescriptor] }
IrGetValueImpl(oldExpression.startOffset, oldExpression.endOffset,
remappedValueDescriptor ?: capturedValueDescriptor)
}
}
dispatchReceiver = oldExpression.dispatchReceiver
extensionReceiver = oldExpression.extensionReceiver
return this
}
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
expression.transformChildrenVoid(this)
val oldCallee = expression.descriptor.original
val localFunctionData = localFunctions[oldCallee] ?: return expression
val newCallee = localFunctionData.transformedDescriptor
return IrFunctionReferenceImpl(
expression.startOffset, expression.endOffset,
expression.type, // TODO functional type for transformed descriptor
newCallee,
remapTypeArguments(expression, newCallee),
expression.origin
).fillArguments(localFunctionData, expression)
}
override fun visitReturn(expression: IrReturn): IrExpression {
expression.transformChildrenVoid(this)
val oldReturnTarget = expression.returnTarget
val localFunctionData = localFunctions[oldReturnTarget] ?: return expression
val newReturnTarget = localFunctionData.transformedDescriptor
return IrReturnImpl(expression.startOffset, expression.endOffset,
newReturnTarget,
expression.value)
}
}
private fun rewriteFunctionDeclaration(irFunction: IrFunction, localFunctionContext: LocalFunctionContext?) {
irFunction.transformChildrenVoid(FunctionBodiesRewriter(localFunctionContext))
}
private fun rewriteBodies() {
localFunctions.values.forEach {
rewriteFunctionDeclaration(it.declaration, it)
}
rewriteFunctionDeclaration(memberFunction, null)
}
private fun createNewCall(oldCall: IrCall, newCallee: FunctionDescriptor) =
when (oldCall) {
is IrCallWithShallowCopy ->
oldCall.shallowCopy(oldCall.origin, newCallee, oldCall.superQualifier)
else ->
IrCallImpl(
oldCall.startOffset, oldCall.endOffset,
newCallee,
remapTypeArguments(oldCall, newCallee),
oldCall.origin, oldCall.superQualifier
)
}
private fun remapTypeArguments(oldExpression: IrMemberAccessExpression, newCallee: FunctionDescriptor): Map<TypeParameterDescriptor, KotlinType>? {
val oldCallee = oldExpression.descriptor
return if (oldCallee.typeParameters.isEmpty())
null
else oldCallee.original.typeParameters.associateBy(
{ newCallee.typeParameters[it.index] },
{ oldExpression.getTypeArgument(it)!! }
)
}
private fun transformDescriptors() {
localFunctions.values.forEach {
it.transformedDescriptor = createTransformedDescriptor(it)
}
}
private fun suggestLocalName(descriptor: DeclarationDescriptor): String {
val localFunctionContext = localFunctions[descriptor]
return if (localFunctionContext != null && localFunctionContext.index >= 0)
"lambda-${localFunctionContext.index}"
else
descriptor.name.asString()
}
private fun generateNameForLiftedFunction(functionDescriptor: FunctionDescriptor): Name =
Name.identifier(
functionDescriptor.parentsWithSelf
.takeWhile { it is FunctionDescriptor }
.toList().reversed()
.joinToString(separator = "$") { suggestLocalName(it) }
)
private fun createTransformedDescriptor(localFunctionContext: LocalFunctionContext): FunctionDescriptor {
val oldDescriptor = localFunctionContext.declaration.descriptor
val memberOwner = memberFunction.descriptor.containingDeclaration
val newDescriptor = SimpleFunctionDescriptorImpl.create(
memberOwner,
oldDescriptor.annotations,
generateNameForLiftedFunction(oldDescriptor),
CallableMemberDescriptor.Kind.SYNTHESIZED,
oldDescriptor.source
)
val closureParametersCount = localFunctionContext.closureParametersCount
val newValueParametersCount = closureParametersCount + oldDescriptor.valueParameters.size
val newDispatchReceiverParameter =
if (memberOwner is ClassDescriptor && oldDescriptor.dispatchReceiverParameter != null)
memberOwner.thisAsReceiverParameter
else
null
// Do not substitute type parameters for now.
val newTypeParameters = oldDescriptor.typeParameters
val newValueParameters = ArrayList<ValueParameterDescriptor>(newValueParametersCount).apply {
localFunctionContext.closure.capturedValues.mapIndexedTo(this) { i, capturedValueDescriptor ->
createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValueDescriptor, i).apply {
localFunctionContext.recordRemapped(capturedValueDescriptor, this)
}
}
oldDescriptor.valueParameters.mapIndexedTo(this) { i, oldValueParameterDescriptor ->
createUnsubstitutedParameter(newDescriptor, oldValueParameterDescriptor, closureParametersCount + i).apply {
localFunctionContext.recordRemapped(oldValueParameterDescriptor, this)
}
}
}
newDescriptor.initialize(
oldDescriptor.extensionReceiverParameter?.type,
newDispatchReceiverParameter,
newTypeParameters,
newValueParameters,
oldDescriptor.returnType,
Modality.FINAL,
Visibilities.PRIVATE
)
oldDescriptor.extensionReceiverParameter?.let {
localFunctionContext.recordRemapped(it, newDescriptor.extensionReceiverParameter!!)
}
return newDescriptor
}
private fun LocalFunctionContext.recordRemapped(oldDescriptor: ValueDescriptor, newDescriptor: ParameterDescriptor): ParameterDescriptor {
old2new[oldDescriptor] = newDescriptor
new2old[newDescriptor] = oldDescriptor
return newDescriptor
}
private fun suggestNameForCapturedValueParameter(valueDescriptor: ValueDescriptor): Name =
if (valueDescriptor.name.isSpecial) {
val oldNameStr = valueDescriptor.name.asString()
Name.identifier("$" + oldNameStr.substring(1, oldNameStr.length - 1))
}
else
valueDescriptor.name
private fun createUnsubstitutedCapturedValueParameter(
newParameterOwner: CallableMemberDescriptor,
valueDescriptor: ValueDescriptor,
index: Int
): ValueParameterDescriptor =
ValueParameterDescriptorImpl(
newParameterOwner, null, index,
valueDescriptor.annotations,
suggestNameForCapturedValueParameter(valueDescriptor),
valueDescriptor.type,
false, false, false, null, valueDescriptor.source
)
private fun createUnsubstitutedParameter(
newParameterOwner: CallableMemberDescriptor,
valueParameterDescriptor: ValueParameterDescriptor,
newIndex: Int
): ValueParameterDescriptor =
valueParameterDescriptor.copy(newParameterOwner, valueParameterDescriptor.name, newIndex)
private fun collectClosures() {
memberFunction.acceptChildrenVoid(object : AbstractClosureAnnotator() {
override fun visitClass(declaration: IrClass) {
// ignore local classes for now
return
}
override fun recordFunctionClosure(functionDescriptor: FunctionDescriptor, closure: Closure) {
localFunctions[functionDescriptor]?.closure = closure
}
override fun recordClassClosure(classDescriptor: ClassDescriptor, closure: Closure) {
// ignore local classes for now
}
})
}
private fun collectLocalFunctions() {
memberFunction.acceptChildrenVoid(object : IrElementVisitorVoid {
var lambdasCount = 0
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitFunction(declaration: IrFunction) {
declaration.acceptChildrenVoid(this)
val localFunctionContext = LocalFunctionContext(declaration)
localFunctions[declaration.descriptor] = localFunctionContext
if (declaration.descriptor.name.isSpecial) {
localFunctionContext.index = lambdasCount++
}
}
override fun visitClass(declaration: IrClass) {
// ignore local classes for now
}
})
}
}
}

View File

@@ -28,8 +28,8 @@ import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -39,10 +39,9 @@ import org.jetbrains.kotlin.resolve.OverridingUtil
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.Printer
class IrLoweringContext(backendContext: BackendContext) : IrGeneratorContext(backendContext.irBuiltIns)
class IrLoweringContext(backendContext: BackendContext) : IrGeneratorContextBase(backendContext.irBuiltIns)
class DeclarationIrBuilder(
backendContext: BackendContext,
@@ -60,7 +59,7 @@ abstract class AbstractVariableRemapper : IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression =
remapVariable(expression.descriptor)?.let {
IrGetValueImpl(expression.startOffset, expression.endOffset, it.symbol, expression.origin)
IrGetValueImpl(expression.startOffset, expression.endOffset, it.type, it.symbol, expression.origin)
} ?: expression
}
@@ -84,7 +83,7 @@ fun <T : IrBuilder> T.at(element: IrElement) = this.at(element.startOffset, elem
*/
inline fun IrGeneratorWithScope.irBlock(
expression: IrExpression, origin: IrStatementOrigin? = null,
resultType: KotlinType? = expression.type,
resultType: IrType? = expression.type,
body: IrBlockBuilder.() -> Unit
) =
this.irBlock(expression.startOffset, expression.endOffset, origin, resultType, body)
@@ -93,13 +92,15 @@ inline fun IrGeneratorWithScope.irBlockBody(irElement: IrElement, body: IrBlockB
this.irBlockBody(irElement.startOffset, irElement.endOffset, body)
fun IrBuilderWithScope.irIfThen(condition: IrExpression, thenPart: IrExpression) =
IrIfThenElseImpl(startOffset, endOffset, context.builtIns.unitType, condition, thenPart, null)
IrIfThenElseImpl(startOffset, endOffset, context.irBuiltIns.unitType).apply {
branches += IrBranchImpl(condition, thenPart)
}
fun IrBuilderWithScope.irNot(arg: IrExpression) =
primitiveOp1(startOffset, endOffset, context.irBuiltIns.booleanNotSymbol, IrStatementOrigin.EXCL, arg)
fun IrBuilderWithScope.irThrow(arg: IrExpression) =
IrThrowImpl(startOffset, endOffset, context.builtIns.nothingType, arg)
IrThrowImpl(startOffset, endOffset, context.irBuiltIns.nothingType, arg)
fun IrBuilderWithScope.irCatch(catchParameter: IrVariable) =
IrCatchImpl(
@@ -107,21 +108,12 @@ fun IrBuilderWithScope.irCatch(catchParameter: IrVariable) =
catchParameter
)
fun IrBuilderWithScope.irCast(arg: IrExpression, type: KotlinType, typeOperand: KotlinType) =
IrTypeOperatorCallImpl(startOffset, endOffset, type, IrTypeOperator.CAST, typeOperand, arg)
fun IrBuilderWithScope.irImplicitCoercionToUnit(arg: IrExpression) =
IrTypeOperatorCallImpl(
startOffset, endOffset, context.builtIns.unitType,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, context.builtIns.unitType, arg
startOffset, endOffset, context.irBuiltIns.unitType,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, context.irBuiltIns.unitType, context.irBuiltIns.unitClass, arg
)
fun IrBuilderWithScope.irGetField(receiver: IrExpression, symbol: IrFieldSymbol) =
IrGetFieldImpl(startOffset, endOffset, symbol, receiver)
fun IrBuilderWithScope.irSetField(receiver: IrExpression, symbol: IrFieldSymbol, value: IrExpression) =
IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value)
open class IrBuildingTransformer(private val context: BackendContext) : IrElementTransformerVoid() {
private var currentBuilder: IrBuilderWithScope? = null

View File

@@ -27,10 +27,12 @@ import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irTemporary
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrSymbolDeclaration
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.isNullableAny
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
@@ -60,33 +62,33 @@ private class StringConcatenationTransformer(val lower: StringConcatenationLower
private val nameToString = Name.identifier("toString")
private val nameAppend = Name.identifier("append")
private val stringBuilder = context.ir.symbols.stringBuilder
private val stringBuilder = context.ir.symbols.stringBuilder.owner
//TODO: calculate and pass string length to the constructor.
private val constructor = stringBuilder.constructors.single {
it.owner.valueParameters.size == 0
it.valueParameters.size == 0
}
private val toStringFunction = stringBuilder.functions.single {
it.owner.valueParameters.size == 0 && it.descriptor.name == nameToString
it.valueParameters.size == 0 && it.name == nameToString
}
private val defaultAppendFunction = stringBuilder.functions.single {
it.descriptor.name == nameAppend &&
it.owner.valueParameters.size == 1 &&
it.owner.valueParameters.single().type == builtIns.nullableAnyType
it.valueParameters.size == 1 &&
it.valueParameters.single().type.isNullableAny()
}
private val appendFunctions: Map<KotlinType, IrFunctionSymbol?> =
private val appendFunctions: Map<KotlinType, IrSimpleFunction?> =
typesWithSpecialAppendFunction.map { type ->
type to stringBuilder.functions.toList().atMostOne {
it.descriptor.name == nameAppend &&
it.owner.valueParameters.size == 1 &&
it.owner.valueParameters.single().type == type
it.valueParameters.size == 1 &&
it.valueParameters.single().type.toKotlinType() == type
}
}.toMap()
private fun typeToAppendFunction(type: KotlinType): IrFunctionSymbol {
private fun typeToAppendFunction(type: KotlinType): IrSimpleFunction {
return appendFunctions[type] ?: defaultAppendFunction
}
@@ -96,9 +98,9 @@ private class StringConcatenationTransformer(val lower: StringConcatenationLower
expression.transformChildrenVoid(this)
val blockBuilder = buildersStack.last()
return blockBuilder.irBlock(expression) {
val stringBuilderImpl = irTemporary(irCall(constructor)).symbol
val stringBuilderImpl = irTemporary(irCall(constructor))
expression.arguments.forEach { arg ->
val appendFunction = typeToAppendFunction(arg.type)
val appendFunction = typeToAppendFunction(arg.type.toKotlinType())
+irCall(appendFunction).apply {
dispatchReceiver = irGet(stringBuilderImpl)
putValueArgument(0, arg)

View File

@@ -18,14 +18,12 @@ package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.util.explicitParameters
import org.jetbrains.kotlin.ir.util.getArgumentsWithSymbols
import org.jetbrains.kotlin.ir.util.getArgumentsWithIr
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -55,7 +53,7 @@ private fun lowerTailRecursionCalls(context: BackendContext, irFunction: IrFunct
irFunction.body = builder.irBlockBody {
// Define variables containing current values of parameters:
val parameterToVariable = parameters.associate {
it to irTemporaryVar(irGet(it), nameHint = it.suggestVariableName()).symbol
it to irTemporaryVar(irGet(it), nameHint = it.symbol.suggestVariableName())
}
// (these variables are to be updated on any tail call).
@@ -63,11 +61,11 @@ private fun lowerTailRecursionCalls(context: BackendContext, irFunction: IrFunct
val loop = this
condition = irTrue()
body = irBlock(startOffset, endOffset, resultType = context.builtIns.unitType) {
body = irBlock(startOffset, endOffset, resultType = context.irBuiltIns.unitType) {
// Read variables containing current values of parameters:
val parameterToNew = parameters.associate {
val variable = parameterToVariable[it]!!
it to irTemporary(irGet(variable), nameHint = it.suggestVariableName()).symbol
it to irTemporary(irGet(variable), nameHint = it.symbol.suggestVariableName())
}
val transformer = BodyTransformer(
@@ -89,8 +87,8 @@ private class BodyTransformer(
val builder: IrBuilderWithScope,
val irFunction: IrFunction,
val loop: IrLoop,
val parameterToNew: Map<IrValueParameterSymbol, IrValueSymbol>,
val parameterToVariable: Map<IrValueParameterSymbol, IrVariableSymbol>,
val parameterToNew: Map<IrValueParameter, IrValueDeclaration>,
val parameterToVariable: Map<IrValueParameter, IrVariable>,
val tailRecursionCalls: Set<IrCall>
) : IrElementTransformerVoid() {
@@ -98,7 +96,7 @@ private class BodyTransformer(
override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid(this)
val value = parameterToNew[expression.symbol] ?: return expression
val value = parameterToNew[expression.symbol.owner] ?: return expression
return builder.at(expression).irGet(value)
}
@@ -113,7 +111,7 @@ private class BodyTransformer(
private fun IrBuilderWithScope.genTailCall(expression: IrCall) = this.irBlock(expression) {
// Get all specified arguments:
val parameterToArgument = expression.getArgumentsWithSymbols().map { (parameter, argument) ->
val parameterToArgument = expression.getArgumentsWithIr().map { (parameter, argument) ->
parameter to argument
}
@@ -122,7 +120,7 @@ private class BodyTransformer(
at(argument)
// Note that argument can use values of parameters, so it is important that
// references to parameters are mapped using `parameterToNew`, not `parameterToVariable`.
+irSetVar(parameterToVariable[parameter]!!, argument)
+irSetVar(parameterToVariable[parameter]!!.symbol, argument)
}
val specifiedParameters = parameterToArgument.map { (parameter, _) -> parameter }.toSet()
@@ -130,7 +128,7 @@ private class BodyTransformer(
// For each unspecified argument set the corresponding variable to default:
parameters.filter { it !in specifiedParameters }.forEach { parameter ->
val originalDefaultValue = parameter.owner.defaultValue?.expression ?: throw Error("no argument specified for $parameter")
val originalDefaultValue = parameter.defaultValue?.expression ?: throw Error("no argument specified for $parameter")
// Copy default value, mapping parameters to variables containing freshly computed arguments:
val defaultValue = originalDefaultValue
@@ -140,15 +138,15 @@ private class BodyTransformer(
override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid(this)
val variableSymbol = parameterToVariable[expression.symbol] ?: return expression
val variable = parameterToVariable[expression.symbol.owner] ?: return expression
return IrGetValueImpl(
expression.startOffset, expression.endOffset,
variableSymbol, expression.origin
expression.startOffset, expression.endOffset, variable.type,
variable.symbol, expression.origin
)
}
}, data = null)
+irSetVar(parameterToVariable[parameter]!!, defaultValue)
+irSetVar(parameterToVariable[parameter]!!.symbol, defaultValue)
}
// Jump to the entry:

View File

@@ -32,14 +32,10 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.getPropertyGetter
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -68,20 +64,25 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
element?.transformChildrenVoid(object: IrElementTransformerVoid() {
val transformer = this
private fun replaceEmptyParameterWithEmptyArray(expression: IrMemberAccessExpression) {
private fun replaceEmptyParameterWithEmptyArray(expression: IrFunctionAccessExpression) {
log { "call of: ${expression.descriptor}" }
context.createIrBuilder(owner, expression.startOffset, expression.endOffset).apply {
expression.descriptor.valueParameters.forEach {
log { "varargElementType: ${it.varargElementType} expr: ${ir2string(expression.getValueArgument(it))}" }
}
expression.descriptor.valueParameters.filter { it.varargElementType != null && expression.getValueArgument(it) == null }.forEach {
expression.putValueArgument(it.index,
IrVarargImpl(startOffset = startOffset,
endOffset = endOffset,
type = it.type,
varargElementType = it.varargElementType!!)
)
}
expression.symbol.owner.valueParameters
.filter { it.varargElementType != null && expression.getValueArgument(it.index) == null }
.forEach {
expression.putValueArgument(
it.index,
IrVarargImpl(
startOffset = startOffset,
endOffset = endOffset,
type = it.type,
varargElementType = it.varargElementType!!
)
)
}
}
expression.transformChildrenVoid(this)
}
@@ -99,28 +100,27 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
override fun visitVararg(expression: IrVararg): IrExpression {
expression.transformChildrenVoid(transformer)
val hasSpreadElement = hasSpreadElement(expression)
if (!hasSpreadElement && expression.elements.all { it is IrConst<*> && KotlinBuiltIns.isString(it.type) }) {
if (!hasSpreadElement && expression.elements.all { it is IrConst<*> && it.type.isString() }) {
log { "skipped vararg expression because it's string array literal" }
return expression
}
val irBuilder = context.createIrBuilder(owner, expression.startOffset, expression.endOffset)
irBuilder.run {
val type = expression.varargElementType
log { "$expression: array type:$type, is array of primitives ${!KotlinBuiltIns.isArray(expression.type)}" }
log { "$expression: array type:$type, is array of primitives ${!expression.type.isArray()}" }
val arrayHandle = arrayType(expression.type)
val arrayConstructor = arrayHandle.arraySymbol.constructors.find { it.owner.valueParameters.size == 1 }!!
val block = irBlock(arrayHandle.arraySymbol.owner.defaultType)
val arrayConstructorCall = if (arrayConstructor.owner.typeParameters.isEmpty()) {
irCall(arrayConstructor)
} else {
irCall(arrayConstructor, listOf(type))
}
val arrayConstructor = arrayHandle.arraySymbol.owner.constructors.find { it.valueParameters.size == 1 }!!
val block = irBlock(expression.type)
val arrayConstructorCall = irCall(arrayConstructor)
if (arrayConstructor.typeParameters.isNotEmpty()) {
arrayConstructorCall.putTypeArgument(0, expression.varargElementType)
}
val vars = expression.elements.map {
val initVar = scope.createTemporaryVariable(
(it as? IrSpreadElement)?.expression ?: it as IrExpression,
"elem".synthesizedString, true)
(it as? IrSpreadElement)?.expression ?: it as IrExpression,
"elem".synthesizedString, true)
block.statements.add(initVar)
it to initVar
}.toMap()
@@ -138,32 +138,31 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
log { "element:$i> ${ir2string(element)}" }
val dst = vars[element]!!
if (element !is IrSpreadElement) {
val setArrayElementCall = irCall(arrayHandle.setMethodSymbol)
setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable.symbol)
setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable.symbol) else irConstInt(i))
setArrayElementCall.putValueArgument(1, irGet(dst.symbol))
val setArrayElementCall = irCall(arrayHandle.setMethodSymbol.owner)
setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable)
setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable) else irConstInt(i))
setArrayElementCall.putValueArgument(1, irGet(dst))
block.statements.add(setArrayElementCall)
if (hasSpreadElement) {
block.statements.add(incrementVariable(indexTmpVariable.symbol, kIntOne))
block.statements.add(incrementVariable(indexTmpVariable, kIntOne))
}
} else {
val arraySizeVariable = scope.createTemporaryVariable(irArraySize(arrayHandle, irGet(dst.symbol)), "length".synthesizedString)
val arraySizeVariable = scope.createTemporaryVariable(irArraySize(arrayHandle, irGet(dst)), "length".synthesizedString)
block.statements.add(arraySizeVariable)
val copyCall = irCall(arrayHandle.copyRangeToSymbol).apply {
extensionReceiver = irGet(dst.symbol)
putValueArgument(0, irGet(arrayTmpVariable.symbol)) /* destination */
val copyCall = irCall(arrayHandle.copyRangeToSymbol.owner).apply {
extensionReceiver = irGet(dst)
putValueArgument(0, irGet(arrayTmpVariable)) /* destination */
putValueArgument(1, kIntZero) /* fromIndex */
putValueArgument(2, irGet(arraySizeVariable.symbol)) /* toIndex */
putValueArgument(3, irGet(indexTmpVariable.symbol)) /* destinationIndex */
putValueArgument(2, irGet(arraySizeVariable)) /* toIndex */
putValueArgument(3, irGet(indexTmpVariable)) /* destinationIndex */
}
block.statements.add(copyCall)
block.statements.add(incrementVariable(indexTmpVariable.symbol,
irGet(arraySizeVariable.symbol)))
block.statements.add(incrementVariable(indexTmpVariable, irGet(arraySizeVariable)))
log { "element:$i:spread element> ${ir2string(element.expression)}" }
}
}
}
block.statements.add(irGet(arrayTmpVariable.symbol))
block.statements.add(irGet(arrayTmpVariable))
return block
}
}
@@ -171,24 +170,21 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
}
private val symbols = context.ir.symbols
private val intPlusInt = symbols.intPlusInt
private val intPlusInt = symbols.intPlusInt.owner
private fun arrayType(type: KotlinType): ArrayHandle = when {
KotlinBuiltIns.isPrimitiveArray(type) -> {
val primitiveType = KotlinBuiltIns.getPrimitiveArrayType(type.constructor.declarationDescriptor!!)
when (primitiveType) {
PrimitiveType.BYTE -> kByteArrayHandler
PrimitiveType.SHORT -> kShortArrayHandler
PrimitiveType.CHAR -> kCharArrayHandler
PrimitiveType.INT -> kIntArrayHandler
PrimitiveType.LONG -> kLongArrayHandler
PrimitiveType.FLOAT -> kFloatArrayHandler
PrimitiveType.DOUBLE -> kDoubleArrayHandler
PrimitiveType.BOOLEAN -> kBooleanArrayHandler
else -> TODO("unsupported type: $primitiveType")
}
private fun arrayType(type: IrType): ArrayHandle {
val primitiveType = KotlinBuiltIns.getPrimitiveArrayType(type.classifierOrFail.descriptor)
return when (primitiveType) {
PrimitiveType.BYTE -> kByteArrayHandler
PrimitiveType.SHORT -> kShortArrayHandler
PrimitiveType.CHAR -> kCharArrayHandler
PrimitiveType.INT -> kIntArrayHandler
PrimitiveType.LONG -> kLongArrayHandler
PrimitiveType.FLOAT -> kFloatArrayHandler
PrimitiveType.DOUBLE -> kDoubleArrayHandler
PrimitiveType.BOOLEAN -> kBooleanArrayHandler
else -> kArrayHandler
}
else -> kArrayHandler
}
private fun IrBuilderWithScope.intPlus() = irCall(intPlusInt)
@@ -199,9 +195,9 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
}
}
private fun IrBuilderWithScope.incrementVariable(symbol: IrVariableSymbol, value: IrExpression): IrExpression {
return irSetVar(symbol, intPlus().apply {
dispatchReceiver = irGet(symbol)
private fun IrBuilderWithScope.incrementVariable(variable: IrVariable, value: IrExpression): IrExpression {
return irSetVar(variable.symbol, intPlus().apply {
dispatchReceiver = irGet(variable)
putValueArgument(0, value)
})
}
@@ -212,14 +208,14 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
val notSpreadElementCount = expression.elements.filter { it !is IrSpreadElement}.size
val initialValue = irConstInt(notSpreadElementCount) as IrExpression
return vars.filter{it.key is IrSpreadElement}.toList().fold( initial = initialValue) { result, it ->
val arraySize = irArraySize(arrayHandle, irGet(it.second.symbol))
val arraySize = irArraySize(arrayHandle, irGet(it.second))
increment(result, arraySize)
}
}
}
private fun IrBuilderWithScope.irArraySize(arrayHandle: ArrayHandle, expression: IrExpression): IrExpression {
val arraySize = irCall(arrayHandle.sizeGetterSymbol).apply {
val arraySize = irCall(arrayHandle.sizeGetterSymbol.owner).apply {
dispatchReceiver = expression
}
return arraySize
@@ -256,7 +252,8 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
}
private fun IrBuilderWithScope.irConstInt(value: Int): IrConst<Int> = IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, value)
private fun IrBuilderWithScope.irBlock(type: KotlinType): IrBlock = IrBlockImpl(startOffset, endOffset, type)
private fun IrBuilderWithScope.irConstInt(value: Int): IrConst<Int> =
IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, value)
private fun IrBuilderWithScope.irBlock(type: IrType): IrBlock = IrBlockImpl(startOffset, endOffset, type)
private val IrBuilderWithScope.kIntZero get() = irConstInt(0)
private val IrBuilderWithScope.kIntOne get() = irConstInt(1)

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.utils
import org.jetbrains.kotlin.backend.common.descriptors.isFunctionOrKFunctionType
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.toIrType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.types.CommonSupertypes
import org.jetbrains.kotlin.types.isNullable
import org.jetbrains.kotlin.types.typeUtil.isInterface
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
fun IrType.isNullable() = toKotlinType().isNullable()
fun IrType.isInterface() = toKotlinType().isInterface()
fun IrType.isPrimitiveArray() = KotlinBuiltIns.isPrimitiveArray(toKotlinType())
fun IrType.isTypeParameter() = toKotlinType().isTypeParameter()
fun IrType.isFunctionOrKFunction() = toKotlinType().isFunctionOrKFunctionType
fun IrType.isFunctionTypeOrSubtype() = toKotlinType().isFunctionTypeOrSubtype
fun List<IrType>.commonSupertype() = CommonSupertypes.commonSupertype(map(IrType::toKotlinType)).toIrType()!!
fun IrType.isSubtypeOf(superType: IrType) = toKotlinType().isSubtypeOf(superType.toKotlinType())
fun IrType.isSubtypeOfClass(superClass: IrClassSymbol) = DescriptorUtils.isSubtypeOfClass(toKotlinType(), superClass.descriptor)

View File

@@ -16,39 +16,20 @@
package org.jetbrains.kotlin.ir.builders
import org.jetbrains.kotlin.backend.common.descriptors.substitute
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrLoop
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
fun IrBuilderWithScope.irWhile(origin: IrStatementOrigin? = null) =
IrWhileLoopImpl(startOffset, endOffset, context.builtIns.unitType, origin)
IrWhileLoopImpl(startOffset, endOffset, context.irBuiltIns.unitType, origin)
fun IrBuilderWithScope.irBreak(loop: IrLoop) =
IrBreakImpl(startOffset, endOffset, context.builtIns.nothingType, loop)
IrBreakImpl(startOffset, endOffset, context.irBuiltIns.nothingType, loop)
fun IrBuilderWithScope.irContinue(loop: IrLoop) =
IrContinueImpl(startOffset, endOffset, context.builtIns.nothingType, loop)
fun IrBuilderWithScope.irTrue() = IrConstImpl.boolean(startOffset, endOffset, context.builtIns.booleanType, true)
fun IrBuilderWithScope.irFalse() = IrConstImpl.boolean(startOffset, endOffset, context.builtIns.booleanType, false)
fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: Map<TypeParameterDescriptor, KotlinType>) =
IrCallImpl(this.startOffset, this.endOffset, symbol, symbol.descriptor.substitute(typeArguments), typeArguments)
fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: List<KotlinType>) =
irCall(symbol, symbol.descriptor.typeParameters.zip(typeArguments).toMap())
IrContinueImpl(startOffset, endOffset, context.irBuiltIns.nothingType, loop)
fun IrBuilderWithScope.irGetObject(classSymbol: IrClassSymbol) =
IrGetObjectValueImpl(startOffset, endOffset, classSymbol.owner.defaultType, classSymbol)
fun IrBuilderWithScope.irGetField(receiver: IrExpression?, symbol: IrFieldSymbol) =
IrGetFieldImpl(startOffset, endOffset, symbol, receiver)
IrGetObjectValueImpl(startOffset, endOffset, IrSimpleTypeImpl(classSymbol, false, emptyList(), emptyList()), classSymbol)

View File

@@ -11,6 +11,7 @@ dependencies {
compile(project(":compiler:backend-common"))
compile(project(":compiler:ir.tree"))
compile(project(":compiler:ir.psi2ir"))
compile(project(":compiler:ir.backend.common"))
compile(project(":js:js.ast"))
compile(project(":js:js.frontend"))

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.js
@@ -29,6 +18,7 @@ import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.name.Name
@@ -64,7 +54,7 @@ class JsDescriptorsFactory : DescriptorsFactory {
false
).apply {
setType(
outerClass.defaultType,
outerClass.defaultType.toKotlinType(),
emptyList(),
innerClass.descriptor.thisAsReceiverParameter,
null as? ReceiverParameterDescriptor

View File

@@ -25,7 +25,7 @@ class JsIntrinsics(
context: JsIrBackendContext
) {
private val stubBuilder = DeclarationStubGenerator(context.symbolTable, JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB)
private val stubBuilder = DeclarationStubGenerator(module, context.symbolTable, JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB)
// Equality operations:

View File

@@ -15,8 +15,8 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
import org.jetbrains.kotlin.ir.backend.js.lower.inline.ModuleIndex
import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
@@ -25,6 +25,8 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -59,7 +61,7 @@ class JsIrBackendContext(
val secondaryConstructorsMap = mutableMapOf<IrConstructorSymbol, SecondaryCtorPair>()
fun getOperatorByName(name: Name, type: KotlinType) = operatorMap[name]?.get(type)
fun getOperatorByName(name: Name, type: IrType) = operatorMap[name]?.get(type.toKotlinType())
val originalModuleIndex = ModuleIndex(irModuleFragment)
@@ -109,6 +111,7 @@ class JsIrBackendContext(
}
private fun referenceOperators() = OperatorNames.ALL.map { name ->
// TODO to replace KotlinType with IrType we need right equals on IrType
name to irBuiltIns.primitiveTypes.fold(mutableMapOf<KotlinType, IrFunctionSymbol>()) { m, t ->
val function = t.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).singleOrNull()
function?.let { m.put(t, symbolTable.referenceSimpleFunction(it)) }

View File

@@ -40,24 +40,28 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack
false, false, variableDescriptor.isLateInit, variableDescriptor.source
)
val valueType = originalDeclaration.descriptor.type
val valueType = originalDeclaration.type
val boxConstructor = closureBoxConstructorTypeDescriptor
val boxConstructorSymbol = closureBoxConstructorTypeSymbol
val constructorTypeParam = closureBoxConstructorTypeDescriptor.typeParameters[0]
val boxConstructorTypeArgument = mapOf(constructorTypeParam to valueType)
val initializer = originalDeclaration.initializer ?: IrConstImpl.constNull(
originalDeclaration.startOffset,
originalDeclaration.endOffset,
valueType
)
// TODO use buildCall?
val constructorCall = IrCallImpl(
originalDeclaration.startOffset,
originalDeclaration.endOffset,
// TODO wrong type
originalDeclaration.type,
boxConstructorSymbol,
boxConstructor,
boxConstructorTypeArgument,
1,
JsLoweredDeclarationOrigin.JS_CLOSURE_BOX_CLASS
).apply { putValueArgument(0, initializer) }
).apply {
putTypeArgument(0, valueType)
putValueArgument(0, initializer)
}
return IrVariableImpl(
@@ -65,6 +69,8 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack
originalDeclaration.endOffset,
originalDeclaration.origin,
sharedVariableDescriptor,
// TODO wrong type ?
originalDeclaration.type,
constructorCall
)
}
@@ -75,9 +81,11 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack
IrGetFieldImpl(
originalGet.startOffset, originalGet.endOffset,
closureBoxFieldSymbol,
originalGet.type,
IrGetValueImpl(
originalGet.startOffset,
originalGet.endOffset,
originalGet.type,
sharedVariableSymbol
),
originalGet.origin
@@ -90,9 +98,11 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack
IrGetValueImpl(
originalSet.startOffset,
originalSet.endOffset,
originalSet.type,
sharedVariableSymbol
),
originalSet.value,
originalSet.type,
originalSet.origin
)

View File

@@ -45,7 +45,8 @@ fun compile(
moduleFragment
)
ExternalDependenciesGenerator(psi2IrContext.symbolTable, psi2IrContext.irBuiltIns).generateUnboundSymbolsAsDependencies(moduleFragment)
ExternalDependenciesGenerator(psi2IrContext.moduleDescriptor, psi2IrContext.symbolTable, psi2IrContext.irBuiltIns)
.generateUnboundSymbolsAsDependencies(moduleFragment)
context.performInlining(moduleFragment)

View File

@@ -41,7 +41,7 @@ class JsIrArithBuilder(val context: JsIrBackendContext) {
fun inv(v: IrExpression): IrExpression = buildUnaryOperator(OperatorNames.INV, v)
fun andand(l: IrExpression, r: IrExpression) = // if (l) r else false
JsIrBuilder.buildIfElse(context.builtIns.booleanType, l, r, JsIrBuilder.buildBoolean(context.builtIns.booleanType, false))
JsIrBuilder.buildIfElse(context.irBuiltIns.booleanType, l, r, JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, false))
fun oror(l: IrExpression, r: IrExpression) = // if (l) true else r
JsIrBuilder.buildIfElse(context.builtIns.booleanType, l, JsIrBuilder.buildBoolean(context.builtIns.booleanType, true), r)
JsIrBuilder.buildIfElse(context.irBuiltIns.booleanType, l, JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true), r)
}

View File

@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.ir
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
@@ -15,76 +15,103 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.ir.types.IrType
object JsIrBuilder {
object SYNTHESIZED_STATEMENT : IrStatementOriginImpl("SYNTHESIZED_STATEMENT")
object SYNTHESIZED_DECLARATION : IrDeclarationOriginImpl("SYNTHESIZED_DECLARATION")
fun buildCall(target: IrFunctionSymbol, type: KotlinType? = null, typeArguments: Map<TypeParameterDescriptor, KotlinType>? = null) =
fun buildCall(target: IrFunctionSymbol, type: IrType? = null, typeArguments: List<IrType>? = null): IrCall =
IrCallImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
type ?: target.descriptor.returnType!!,
type ?: target.owner.returnType,
target,
target.descriptor,
typeArguments,
target.owner.typeParameters.size,
SYNTHESIZED_STATEMENT
)
).apply {
typeArguments?.let {
assert(typeArguments.size == typeArgumentsCount)
it.withIndex().forEach { (i, t) -> putTypeArgument(i, t) }
}
}
fun buildReturn(targetSymbol: IrFunctionSymbol, value: IrExpression) =
IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, targetSymbol, value)
fun buildReturn(targetSymbol: IrFunctionSymbol, value: IrExpression, context: BackendContext) =
IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.nothingType, targetSymbol, value)
fun buildThrow(type: KotlinType, value: IrExpression) = IrThrowImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, value)
fun buildThrow(type: IrType, value: IrExpression) = IrThrowImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, value)
fun buildValueParameter(symbol: IrValueParameterSymbol) =
IrValueParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol)
fun buildValueParameter(symbol: IrValueParameterSymbol, type: IrType? = null) =
IrValueParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol, type ?: symbol.owner.type, null)
fun buildFunction(symbol: IrSimpleFunctionSymbol) = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol)
fun buildFunction(symbol: IrSimpleFunctionSymbol, returnType: IrType) =
IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol).apply {
this.returnType = returnType
}
fun buildGetObjectValue(type: KotlinType, classSymbol: IrClassSymbol) =
fun buildGetObjectValue(type: IrType, classSymbol: IrClassSymbol) =
IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, classSymbol)
fun buildGetClass(expression: IrExpression, type: KotlinType) = IrGetClassImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, expression)
fun buildGetClass(expression: IrExpression, type: IrType) = IrGetClassImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, expression)
fun buildGetValue(symbol: IrValueSymbol) = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, SYNTHESIZED_STATEMENT)
fun buildSetVariable(symbol: IrVariableSymbol, value: IrExpression) =
IrSetVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, value, SYNTHESIZED_STATEMENT)
fun buildGetValue(symbol: IrValueSymbol) = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol.owner.type, symbol, SYNTHESIZED_STATEMENT)
fun buildSetVariable(symbol: IrVariableSymbol, value: IrExpression, type: IrType) =
IrSetVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, symbol, value, SYNTHESIZED_STATEMENT)
fun buildGetField(symbol: IrFieldSymbol, receiver: IrExpression?, superQualifierSymbol: IrClassSymbol? = null) =
IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, receiver, SYNTHESIZED_STATEMENT, superQualifierSymbol)
IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, symbol.owner.type, receiver, SYNTHESIZED_STATEMENT, superQualifierSymbol)
fun buildSetField(symbol: IrFieldSymbol, receiver: IrExpression?, value: IrExpression, superQualifierSymbol: IrClassSymbol? = null) =
IrSetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, receiver, value, SYNTHESIZED_STATEMENT, superQualifierSymbol)
fun buildSetField(symbol: IrFieldSymbol, receiver: IrExpression?, value: IrExpression, type: IrType, superQualifierSymbol: IrClassSymbol? = null) =
IrSetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, receiver, value, type, SYNTHESIZED_STATEMENT, superQualifierSymbol)
fun buildBlockBody(statements: List<IrStatement>) = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, statements)
fun buildBlock(type: KotlinType) = IrBlockImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, SYNTHESIZED_STATEMENT)
fun buildBlock(type: KotlinType, statements: List<IrStatement>) =
fun buildBlock(type: IrType) = IrBlockImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, SYNTHESIZED_STATEMENT)
fun buildBlock(type: IrType, statements: List<IrStatement>) =
IrBlockImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, SYNTHESIZED_STATEMENT, statements)
fun buildFunctionReference(type: KotlinType, symbol: IrFunctionSymbol) =
IrFunctionReferenceImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, symbol, symbol.descriptor)
fun buildFunctionReference(type: IrType, symbol: IrFunctionSymbol) =
IrFunctionReferenceImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, symbol, symbol.descriptor, 0, null)
fun buildVar(symbol: IrVariableSymbol, initializer: IrExpression? = null) =
IrVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol).apply { this.initializer = initializer }
fun buildVar(symbol: IrVariableSymbol, initializer: IrExpression? = null, type: IrType?) =
IrVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol, type ?: symbol.owner.type).apply { this.initializer = initializer }
fun buildBreak(type: KotlinType, loop: IrLoop) = IrBreakImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, loop)
fun buildContinue(type: KotlinType, loop: IrLoop) = IrContinueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, loop)
fun buildBreak(type: IrType, loop: IrLoop) = IrBreakImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, loop)
fun buildContinue(type: IrType, loop: IrLoop) = IrContinueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, loop)
fun buildIfElse(type: KotlinType, cond: IrExpression, thenBranch: IrExpression, elseBranch: IrExpression? = null) = IrIfThenElseImpl(
fun buildIfElse(type: IrType, cond: IrExpression, thenBranch: IrExpression, elseBranch: IrExpression? = null): IrWhen = buildIfElse(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, cond, thenBranch, elseBranch, SYNTHESIZED_STATEMENT
)
fun buildWhen(type: KotlinType, branches: List<IrBranch>) =
fun buildIfElse(
startOffset: Int,
endOffset: Int,
type: IrType,
cond: IrExpression,
thenBranch: IrExpression,
elseBranch: IrExpression? = null,
origin: IrStatementOrigin? = null
): IrWhen {
val element = IrIfThenElseImpl(startOffset, endOffset, type, origin)
element.branches.add(IrBranchImpl(cond, thenBranch))
if (elseBranch != null) {
val irTrue = IrConstImpl.boolean(UNDEFINED_OFFSET, UNDEFINED_OFFSET, cond.type, true)
element.branches.add(IrElseBranchImpl(irTrue, elseBranch))
}
return element
}
fun buildWhen(type: IrType, branches: List<IrBranch>) =
IrWhenImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, SYNTHESIZED_STATEMENT, branches)
fun buildTypeOperator(type: KotlinType, operator: IrTypeOperator, argument: IrExpression, toType: KotlinType, symbol: IrClassifierSymbol) =
IrTypeOperatorCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, operator, toType, argument, symbol)
fun buildTypeOperator(type: IrType, operator: IrTypeOperator, argument: IrExpression, toType: IrType, symbol: IrClassifierSymbol) =
IrTypeOperatorCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, operator, toType, symbol, argument)
fun buildNull(type: KotlinType) = IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type)
fun buildBoolean(type: KotlinType, v: Boolean) = IrConstImpl.boolean(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, v)
fun buildInt(type: KotlinType, v: Int) = IrConstImpl.int(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, v)
fun buildString(type: KotlinType, s: String) = IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, s)
}
fun buildNull(type: IrType) = IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type)
fun buildBoolean(type: IrType, v: Boolean) = IrConstImpl.boolean(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, v)
fun buildInt(type: IrType, v: Int) = IrConstImpl.int(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, v)
fun buildString(type: IrType, s: String) = IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, s)
}

View File

@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
@@ -17,9 +16,11 @@ import org.jetbrains.kotlin.ir.backend.js.utils.Namer
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isUnit
import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
private typealias VisitData = Nothing?
@@ -30,15 +31,20 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
private val statementVisitor = StatementVisitor()
private val expressionVisitor = ExpressionVisitor()
private val constTrue = JsIrBuilder.buildBoolean(context.builtIns.booleanType, true)
private val constFalse = JsIrBuilder.buildBoolean(context.builtIns.booleanType, false)
private val nothingType = context.builtIns.nullableNothingType
private val constTrue = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true)
private val constFalse = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, false)
private val nothingType get() = context.irBuiltIns.nothingType
private val unitType get() = context.irBuiltIns.unitType
private val unitType = context.builtIns.unitType
private val unitValue = JsIrBuilder.buildGetObjectValue(unitType, context.symbolTable.referenceClass(context.builtIns.unit))
private val unreachableFunction =
JsSymbolBuilder.buildSimpleFunction(context.module, Namer.UNREACHABLE_NAME).initialize(type = nothingType)
private val unreachableFunction = JsIrBuilder.buildFunction(
JsSymbolBuilder.buildSimpleFunction(
context.module,
Namer.UNREACHABLE_NAME
).initialize(returnType = nothingType),
nothingType
)
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
irDeclarationContainer.declarations.transformFlat { declaration ->
@@ -61,17 +67,18 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
fun lower(irField: IrField, container: IrDeclarationContainer): List<IrDeclaration> {
irField.initializer?.apply {
val returnType = expression.type
val initFnSymbol = JsSymbolBuilder.buildSimpleFunction(
(container as IrSymbolOwner).symbol.descriptor,
irField.name.asString() + "\$init\$"
).initialize(type = expression.type)
).initialize(returnType = returnType)
val newBody = IrBlockBodyImpl(expression.startOffset, expression.endOffset).apply {
statements += JsIrBuilder.buildReturn(initFnSymbol, expression)
statements += JsIrBuilder.buildReturn(initFnSymbol, expression, context)
}
val initFn = JsIrBuilder.buildFunction(initFnSymbol).apply {
val initFn = JsIrBuilder.buildFunction(initFnSymbol, returnType).apply {
body = newBody
}
@@ -314,15 +321,15 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
expression.type,
expression.operator,
expression.typeOperand,
resultValue,
expression.typeOperandClassifier
expression.typeOperandClassifier,
resultValue
)
val resValue: IrExpression
if (!KotlinBuiltIns.isUnit(expression.type)) {
if (!expression.type.isUnit()) {
val resVar = makeTempVar(expression.type)
statements += JsIrBuilder.buildVar(resVar, newOperator)
statements += JsIrBuilder.buildVar(resVar, newOperator, type = expression.type)
resValue = JsIrBuilder.buildGetValue(resVar)
} else {
statements += newOperator
@@ -364,7 +371,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
}
if (needNew) {
newStatements += JsIrBuilder.buildSetField(expression.symbol, newReceiver, newValue, expression.superQualifierSymbol)
newStatements += JsIrBuilder.buildSetField(expression.symbol, newReceiver, newValue, unitType, expression.superQualifierSymbol)
return DecomposedResult(newStatements, unitValue)
}
@@ -375,7 +382,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
val valueResult = expression.value.accept(expressionVisitor, data)
return valueResult.runIfChanged {
statements += JsIrBuilder.buildSetVariable(expression.symbol, resultValue)
statements += JsIrBuilder.buildSetVariable(expression.symbol, resultValue, unitType)
DecomposedResult(statements, unitValue)
}
}
@@ -400,7 +407,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
// val x = x_tmp
override fun visitContainerExpression(expression: IrContainerExpression, data: VisitData): VisitResult {
val variable = makeTempVar(expression.type)
val varDeclaration = JsIrBuilder.buildVar(variable)
val varDeclaration = JsIrBuilder.buildVar(variable, type = expression.type)
val blockStatements = expression.statements
val lastStatement: IrStatement? = blockStatements.lastOrNull()
@@ -434,7 +441,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
collectingList += statements
resultValue
}
collectingList += JsIrBuilder.buildSetVariable(variable, result)
collectingList += JsIrBuilder.buildSetVariable(variable, result, unitType)
if (body is IrComposite) {
DecomposedResult(mutableListOf(varDeclaration, *collectingList.toTypedArray()) , JsIrBuilder.buildGetValue(variable))
} else {
@@ -463,7 +470,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
private fun prepareArgument(arg: IrExpression, needWrap: Boolean, statements: MutableList<IrStatement>): IrExpression {
return if (needWrap) {
val wrapVar = makeTempVar(arg.type)
statements += JsIrBuilder.buildVar(wrapVar, arg)
statements += JsIrBuilder.buildVar(wrapVar, arg, type = arg.type)
JsIrBuilder.buildGetValue(wrapVar)
} else arg
}
@@ -543,21 +550,21 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
val resultVar = makeTempVar(expression.type)
// TODO: get rid of temporary variable
newStatements += JsIrBuilder.buildVar(resultVar, expression)
newStatements += JsIrBuilder.buildVar(resultVar, expression, type = expression.type)
return DecomposedResult(newStatements, JsIrBuilder.buildGetValue(resultVar))
}
override fun visitWhen(expression: IrWhen, data: VisitData): VisitResult {
val collectiveVar = makeTempVar(expression.type)
val varDeclaration = JsIrBuilder.buildVar(collectiveVar)
val varDeclaration = JsIrBuilder.buildVar(collectiveVar, type = expression.type)
val newWhen = processWhen(expression, data, this, this) { visitResult, original ->
val resultList = mutableListOf<IrStatement>()
val newResult = visitResult.runIfChangedOrDefault(original as IrExpression) {
resultList += statements
resultValue
}
resultList.apply { add(JsIrBuilder.buildSetVariable(collectiveVar, newResult)) }
resultList.apply { add(JsIrBuilder.buildSetVariable(collectiveVar, newResult, unitType)) }
}
if (newWhen != expression) {
@@ -587,7 +594,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
resultValue
}
val wrapVar = makeTempVar(expression.varargElementType)
newStatements += JsIrBuilder.buildVar(wrapVar).apply { initializer = newExpression }
newStatements += JsIrBuilder.buildVar(wrapVar, type = expression.type).apply { initializer = newExpression }
val newValue = JsIrBuilder.buildGetValue(wrapVar)
if (original is IrSpreadElement) {
IrSpreadElementImpl(original.startOffset, original.endOffset, newValue)
@@ -641,7 +648,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
newStatements += instantiater(returnValue)
return TerminatedResult(newStatements, JsIrBuilder.buildCall(unreachableFunction))
return TerminatedResult(newStatements, JsIrBuilder.buildCall(unreachableFunction.symbol))
}
@@ -658,7 +665,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
)
override fun visitBreakContinue(jump: IrBreakContinue, data: VisitData): VisitResult {
return DecomposedResult(jump, JsIrBuilder.buildCall(unreachableFunction))
return DecomposedResult(jump, JsIrBuilder.buildCall(unreachableFunction.symbol))
}
override fun visitTry(aTry: IrTry, data: VisitData): VisitResult {
@@ -669,10 +676,10 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
finallyResult?.run { assert(status == VisitStatus.KEPT) }
val resultSymbol = makeTempVar(aTry.type)
val resultDeclaration = JsIrBuilder.buildVar(resultSymbol)
val resultDeclaration = JsIrBuilder.buildVar(resultSymbol, type = aTry.type)
val newTryValue = tryResult.runIfChangedOrDefault(aTry.tryResult) { resultValue }
val trySetResult = JsIrBuilder.buildSetVariable(resultSymbol, newTryValue) as IrStatement
val trySetResult = JsIrBuilder.buildSetVariable(resultSymbol, newTryValue, unitType) as IrStatement
val tryBlock = IrBlockImpl(aTry.tryResult.startOffset, aTry.tryResult.endOffset, unitType).apply {
statements += tryResult.runIfChangedOrDefault(listOf(trySetResult)) { statements + trySetResult }
@@ -680,7 +687,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
val catchBlocks = catchResults.map { (original, result) ->
val newCatchResult = result.runIfChangedOrDefault(original.result) { resultValue }
val catchSetResult = JsIrBuilder.buildSetVariable(resultSymbol, newCatchResult) as IrStatement
val catchSetResult = JsIrBuilder.buildSetVariable(resultSymbol, newCatchResult, unitType) as IrStatement
val catchBlock = IrBlockImpl(original.result.startOffset, original.result.endOffset, unitType)
catchBlock.statements += result.runIfChangedOrDefault(listOf(catchSetResult)) { statements + catchSetResult }
IrCatchImpl(original.startOffset, original.endOffset, original.catchParameter, catchBlock)
@@ -713,7 +720,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
}
}
fun makeTempVar(type: KotlinType) =
fun makeTempVar(type: IrType) =
JsSymbolBuilder.buildTempVar(function.symbol, type, "tmp\$dcms\$${tmpVarCounter++}", true)
fun makeLoopLabel() = "\$l\$${tmpVarCounter++}"
@@ -782,7 +789,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
JsIrBuilder.buildBlock(unitType).also {
val elseBlock = if (originalBranch is IrElseBranch) null else it
val ifElseNode = IrIfThenElseImpl(
val ifElseNode = JsIrBuilder.buildIfElse(
originalBranch.startOffset,
originalBranch.endOffset,
unitType,

View File

@@ -24,6 +24,8 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.toIrType
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
@@ -39,9 +41,9 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
private val callableToGetterFunction = mutableMapOf<CallableReferenceKey, IrFunction>()
private val collectedReferenceMap = mutableMapOf<CallableReferenceKey, IrCallableReference>()
private val callableNameConst = JsIrBuilder.buildString(context.irBuiltIns.string, Namer.KCALLABLE_NAME)
private val getterConst = JsIrBuilder.buildString(context.irBuiltIns.string, Namer.KPROPERTY_GET)
private val setterConst = JsIrBuilder.buildString(context.irBuiltIns.string, Namer.KPROPERTY_SET)
private val callableNameConst = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KCALLABLE_NAME)
private val getterConst = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KPROPERTY_GET)
private val setterConst = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KPROPERTY_SET)
private val newDeclarations = mutableListOf<IrDeclaration>()
@@ -97,7 +99,13 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
}
private fun redirectToFunction(callable: IrCallableReference, newTarget: IrFunction) =
IrCallImpl(callable.startOffset, callable.endOffset, newTarget.symbol, callable.origin).apply {
IrCallImpl(
callable.startOffset, callable.endOffset,
newTarget.symbol.owner.returnType,
newTarget.symbol,
newTarget.symbol.descriptor,
callable.origin
).apply {
copyTypeArgumentsFrom(callable)
var index = 0
callable.dispatchReceiver?.let { putValueArgument(index++, it) }
@@ -156,13 +164,13 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
val additionalDeclarations = generateGetterBodyWithGuard(refGetFunction) {
val irClosureReference = JsIrBuilder.buildFunctionReference(functionReference.type, refClosureFunction.symbol)
val irVarSymbol = JsSymbolBuilder.buildTempVar(refGetFunction.symbol, irClosureReference.type)
val irVar = JsIrBuilder.buildVar(irVarSymbol, irClosureReference)
val irVar = JsIrBuilder.buildVar(irVarSymbol, irClosureReference, type = irClosureReference.type)
// TODO: fill other fields of callable reference (returnType, parameters, isFinal, etc.)
val irSetName = JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply {
putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol))
putValueArgument(1, callableNameConst)
putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.string, getReferenceName(declaration.descriptor)))
putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.stringType, getReferenceName(declaration.descriptor)))
}
Pair(listOf(irVar, irSetName), irVarSymbol)
}
@@ -203,10 +211,11 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
val statements = mutableListOf<IrStatement>()
val getterFunctionType = context.builtIns.getFunction(getterFunction.valueParameters.size + 1)
val irGetReference = JsIrBuilder.buildFunctionReference(getterFunctionType.defaultType, getterFunction.symbol)
val irVarSymbol = JsSymbolBuilder.buildTempVar(refGetFunction.symbol, getterFunctionType.defaultType)
val type = getterFunctionType.toIrType()
val irGetReference = JsIrBuilder.buildFunctionReference(type, getterFunction.symbol)
val irVarSymbol = JsSymbolBuilder.buildTempVar(refGetFunction.symbol, type)
statements += JsIrBuilder.buildVar(irVarSymbol, irGetReference)
statements += JsIrBuilder.buildVar(irVarSymbol, irGetReference, type = type)
statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply {
putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol))
@@ -216,7 +225,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
if (setterFunction != null) {
val setterFunctionType = context.builtIns.getFunction(setterFunction.valueParameters.size + 1)
val irSetReference = JsIrBuilder.buildFunctionReference(setterFunctionType.defaultType, setterFunction.symbol)
val irSetReference = JsIrBuilder.buildFunctionReference(setterFunctionType.toIrType(), setterFunction.symbol)
statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply {
putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol))
putValueArgument(1, setterConst)
@@ -228,7 +237,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply {
putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol))
putValueArgument(1, callableNameConst)
putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.string, getReferenceName(propertyReference.descriptor)))
putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.stringType, getReferenceName(propertyReference.descriptor)))
}
Pair(statements, irVarSymbol)
@@ -255,22 +264,23 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
// }
//
val cacheName = "${getterFunction.name}_${Namer.KCALLABLE_CACHE_SUFFIX}"
val type = getterFunction.returnType
val cacheVarSymbol =
JsSymbolBuilder.buildVar(getterFunction.descriptor.containingDeclaration, getterFunction.returnType, cacheName, true)
val irNull = JsIrBuilder.buildNull(cacheVarSymbol.descriptor.type)
val irCacheDeclaration = JsIrBuilder.buildVar(cacheVarSymbol)
JsSymbolBuilder.buildVar(getterFunction.descriptor.containingDeclaration, type, cacheName, true)
val irNull = JsIrBuilder.buildNull(context.irBuiltIns.nothingNType)
val irCacheDeclaration = JsIrBuilder.buildVar(cacheVarSymbol, irNull, type = type)
val irCacheValue = JsIrBuilder.buildGetValue(cacheVarSymbol)
val irIfCondition = JsIrBuilder.buildCall(context.irBuiltIns.eqeqSymbol).apply {
putValueArgument(0, irCacheValue)
putValueArgument(1, irNull)
}
val irSetCache = JsIrBuilder.buildSetVariable(cacheVarSymbol, JsIrBuilder.buildGetValue(varSymbol))
val irSetCache = JsIrBuilder.buildSetVariable(cacheVarSymbol, JsIrBuilder.buildGetValue(varSymbol), context.irBuiltIns.unitType)
val thenStatements = mutableListOf<IrStatement>().apply {
addAll(bodyStatements)
add(irSetCache)
}
val irThenBranch = JsIrBuilder.buildBlock(context.irBuiltIns.unit, thenStatements)
val irIfNode = JsIrBuilder.buildIfElse(context.irBuiltIns.unit, irIfCondition, irThenBranch)
val irThenBranch = JsIrBuilder.buildBlock(context.irBuiltIns.unitType, thenStatements)
val irIfNode = JsIrBuilder.buildIfElse(context.irBuiltIns.unitType, irIfCondition, irThenBranch)
statements += irIfNode
returnValue = irCacheValue
returnStatements = listOf(irCacheDeclaration)
@@ -280,7 +290,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
returnStatements = emptyList()
}
statements += JsIrBuilder.buildReturn(getterFunction.symbol, returnValue)
statements += JsIrBuilder.buildReturn(getterFunction.symbol, returnValue, context)
getterFunction.body = JsIrBuilder.buildBlockBody(statements)
return returnStatements
@@ -314,8 +324,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
private fun buildGetFunction(declaration: IrFunction, reference: IrCallableReference, getterName: String): IrSimpleFunction {
val callableType = reference.type
val closureParams = callableType.arguments.dropLast(1) // drop return type
var kFunctionValueParamsCount = closureParams.size
var kFunctionValueParamsCount = (callableType as? IrSimpleType)?.arguments?.size?.minus(1) ?: 0
if (declaration.dispatchReceiverParameter != null && reference.dispatchReceiver == null) {
kFunctionValueParamsCount--
@@ -342,14 +351,22 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
val refGetSymbol = JsSymbolBuilder.buildSimpleFunction(declaration.descriptor.containingDeclaration, getterName).apply {
initialize(
valueParameters = getterValueParameters.mapIndexed { i, p -> p.descriptor.copyAsValueParameter(descriptor, i) },
type = callableType
returnType = callableType
)
}
return JsIrBuilder.buildFunction(refGetSymbol).apply {
return JsIrBuilder.buildFunction(refGetSymbol, callableType).apply {
for (i in 0 until getterValueParameters.size) {
val p = getterValueParameters[i]
valueParameters += IrValueParameterImpl(p.startOffset, p.endOffset, p.origin, refGetSymbol.descriptor.valueParameters[i])
valueParameters +=
IrValueParameterImpl(
p.startOffset,
p.endOffset,
p.origin,
refGetSymbol.descriptor.valueParameters[i],
p.type,
p.varargElementType
)
}
}
}
@@ -366,15 +383,18 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
val closureParamSymbols = generateSignatureForClosure(declaration, refGetFunction, refClosureSymbol, reference)
val closureParamDescriptors = closureParamSymbols.map { it.descriptor as ValueParameterDescriptor }
refClosureSymbol.initialize(valueParameters = closureParamDescriptors, type = declaration.returnType)
val returnType = declaration.returnType
refClosureSymbol.initialize(valueParameters = closureParamDescriptors, returnType = returnType)
val closureFunction = JsIrBuilder.buildFunction(refClosureSymbol)
val closureFunction = JsIrBuilder.buildFunction(refClosureSymbol, returnType)
for (it in closureParamSymbols) {
closureFunction.valueParameters += JsIrBuilder.buildValueParameter(it)
for (param in closureParamSymbols) {
// TODO always take type from param
val type = if (param.isBound) param.owner.type else context.irBuiltIns.anyType
closureFunction.valueParameters += JsIrBuilder.buildValueParameter(param, type)
}
val irCall = JsIrBuilder.buildCall(declaration.symbol)
val irCall = JsIrBuilder.buildCall(declaration.symbol, type = returnType)
var cp = 0
var gp = 0
@@ -401,7 +421,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
irCall.putValueArgument(j++, JsIrBuilder.buildGetValue(closureParamSymbols[i]))
}
val irClosureReturn = JsIrBuilder.buildReturn(closureFunction.symbol, irCall)
val irClosureReturn = JsIrBuilder.buildReturn(closureFunction.symbol, irCall, context)
closureFunction.body = JsIrBuilder.buildBlockBody(listOf(irClosureReturn))

View File

@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.backend.common.utils.isSubtypeOfClass
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
@@ -19,10 +19,10 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SimpleType
class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileLoweringPass {
@@ -33,16 +33,13 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
private val symbolToIrFunction: Map<IrFunctionSymbol, IrSimpleFunction>
private val nameToIrTransformer: Map<Name, (IrCall) -> IrCall>
val kCallable = context.builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.kCallable.toSafe())
val kProperty = context.builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.kProperty.asSingleFqName())
init {
memberToIrFunction = mutableMapOf()
symbolToIrFunction = mutableMapOf()
memberToTransformer = mutableMapOf()
nameToIrTransformer = mutableMapOf()
val primitiveNumbers = context.irBuiltIns.run { listOf(int, short, byte, float, double) }
val primitiveNumbers = context.irBuiltIns.run { listOf(intType, shortType, byteType, floatType, doubleType) }
memberToIrFunction.run {
for (type in primitiveNumbers) {
@@ -57,11 +54,11 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
op(type, OperatorNames.REM, context.intrinsics.jsMod)
}
context.irBuiltIns.string.let {
context.irBuiltIns.stringType.let {
op(it, OperatorNames.ADD, context.intrinsics.jsPlus)
}
context.irBuiltIns.int.let {
context.irBuiltIns.intType.let {
op(it, OperatorNames.SHL, context.intrinsics.jsBitShiftL)
op(it, OperatorNames.SHR, context.intrinsics.jsBitShiftR)
op(it, OperatorNames.SHRU, context.intrinsics.jsBitShiftRU)
@@ -71,7 +68,7 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
op(it, OperatorNames.INV, context.intrinsics.jsBitNot)
}
context.irBuiltIns.bool.let {
context.irBuiltIns.booleanType.let {
op(it, OperatorNames.AND, context.intrinsics.jsBitAnd)
op(it, OperatorNames.OR, context.intrinsics.jsBitOr)
op(it, OperatorNames.NOT, context.intrinsics.jsNot)
@@ -99,12 +96,12 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
// TODO: use increment and decrement when it's possible
op(type, OperatorNames.INC) {
irCall(it, context.intrinsics.jsPlus.symbol, dispatchReceiverAsFirstArgument = true).apply {
putValueArgument(1, JsIrBuilder.buildInt(context.irBuiltIns.int, 1))
putValueArgument(1, JsIrBuilder.buildInt(context.irBuiltIns.intType, 1))
}
}
op(type, OperatorNames.DEC) {
irCall(it, context.intrinsics.jsMinus.symbol, dispatchReceiverAsFirstArgument = true).apply {
putValueArgument(1, JsIrBuilder.buildInt(context.irBuiltIns.int, 1))
putValueArgument(1, JsIrBuilder.buildInt(context.irBuiltIns.intType, 1))
}
}
}
@@ -113,18 +110,18 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
nameToIrTransformer.run {
addWithPredicate(
Name.special(Namer.KCALLABLE_GET_NAME),
{ call -> call.symbol.owner.dispatchReceiverParameter?.run { DescriptorUtils.isSubtypeOfClass(type, kCallable) } ?: false },
{ call -> call.symbol.owner.dispatchReceiverParameter?.run { type.isSubtypeOfClass(context.irBuiltIns.kCallableClass) } ?: false },
{ call -> irCall(call, context.intrinsics.jsName.symbol, dispatchReceiverAsFirstArgument = true) })
addWithPredicate(
Name.identifier(Namer.KPROPERTY_GET),
{ call -> call.symbol.owner.dispatchReceiverParameter?.run { DescriptorUtils.isSubtypeOfClass(type, kProperty) } ?: false },
{ call -> call.symbol.owner.dispatchReceiverParameter?.run { type.isSubtypeOfClass(context.irBuiltIns.kPropertyClass) } ?: false },
{ call -> irCall(call, context.intrinsics.jsPropertyGet.symbol, dispatchReceiverAsFirstArgument = true)}
)
addWithPredicate(
Name.identifier(Namer.KPROPERTY_SET),
{ call -> call.symbol.owner.dispatchReceiverParameter?.run { DescriptorUtils.isSubtypeOfClass(type, kProperty) } ?: false},
{ call -> call.symbol.owner.dispatchReceiverParameter?.run { type.isSubtypeOfClass(context.irBuiltIns.kPropertyClass) } ?: false},
{ call -> irCall(call, context.intrinsics.jsPropertySet.symbol, dispatchReceiverAsFirstArgument = true)}
)
}
@@ -207,12 +204,11 @@ private fun IrCall.copyTypeAndValueArgumentsFrom(call: IrCall, dispatchReceiverA
}
}
private fun <V> MutableMap<SimpleMemberKey, V>.op(type: KotlinType, name: Name, v: V) {
private fun <V> MutableMap<SimpleMemberKey, V>.op(type: IrType, name: Name, v: V) {
put(SimpleMemberKey(type, name), v)
}
// TODO issue: marked as unused, but used; rename works wrongly.
private fun <V> MutableMap<SimpleMemberKey, V>.op(type: KotlinType, name: String, v: V) {
private fun <V> MutableMap<SimpleMemberKey, V>.op(type: IrType, name: String, v: V) {
put(SimpleMemberKey(type, Name.identifier(name)), v)
}
@@ -232,4 +228,23 @@ private fun <K> MutableMap<K, (IrCall) -> IrCall>.addWithPredicate(from: K, pred
private inline fun <T> select(crossinline predicate: () -> Boolean, crossinline ifTrue: () -> T, crossinline ifFalse: () -> T): T = if (predicate()) ifTrue() else ifFalse()
private data class SimpleMemberKey(val klass: KotlinType, val name: Name)
private class SimpleMemberKey(val klass: IrType, val name: Name) {
// TODO drop custom equals and hashCode when IrTypes will have right equals
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as SimpleMemberKey
if (name != other.name) return false
if (klass.originalKotlinType != other.klass.originalKotlinType) return false
return true
}
override fun hashCode(): Int {
var result = klass.originalKotlinType?.hashCode() ?: 0
result = 31 * result + name.hashCode()
return result
}
}

View File

@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.utils.commonSupertype
import org.jetbrains.kotlin.backend.common.utils.isSubtypeOf
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
@@ -18,11 +20,10 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCatchImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrElseBranchImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrTryImpl
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.types.IrDynamicType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.types.CommonSupertypes
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isDynamic
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
/**
* Since JS does not support multiple catch blocks by default we should replace them with similar `when` statement, so
@@ -49,9 +50,9 @@ import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
*/
class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPass {
val litTrue = JsIrBuilder.buildBoolean(context.irBuiltIns.bool, true)
val unitType = context.irBuiltIns.unit
val nothingType = context.irBuiltIns.nothing
val litTrue = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true)
val unitType = context.irBuiltIns.unitType
val nothingType = context.irBuiltIns.nothingType
override fun lower(irFile: IrFile) {
irFile.transformChildren(object : IrElementTransformer<IrDeclaration?> {
@@ -67,7 +68,7 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas
val commonType = mergeTypes(aTry.catches.map { it.catchParameter.type })
val pendingExceptionSymbol = JsSymbolBuilder.buildVar(data!!.descriptor, commonType, "\$pending\$", false)
val pendingExceptionDeclaration = JsIrBuilder.buildVar(pendingExceptionSymbol)
val pendingExceptionDeclaration = JsIrBuilder.buildVar(pendingExceptionSymbol, type = commonType)
val pendingException = JsIrBuilder.buildGetValue(pendingExceptionSymbol)
val branches = mutableListOf<IrBranch>()
@@ -75,24 +76,27 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas
for (catch in aTry.catches) {
assert(!catch.catchParameter.isVar) { "caught exception parameter has to immutable" }
val type = catch.catchParameter.type
val typeSymbol = context.symbolTable.referenceClassifier(type.constructor.declarationDescriptor!!)
val castedPendingException = buildImplicitCast(pendingException, type, typeSymbol)
val typeSymbol = type.classifierOrNull
val catchBody = catch.result.transform(object : IrElementTransformer<VariableDescriptor> {
override fun visitGetValue(expression: IrGetValue, data: VariableDescriptor) =
if (expression.descriptor == data) castedPendingException else expression
if (typeSymbol != null && expression.descriptor == data)
// TODO how is it good to generate implicit cast for each access?
buildImplicitCast(pendingException, type, typeSymbol)
else
expression
}, catch.parameter)
if (type.isDynamic()) {
if (type is IrDynamicType) {
branches += IrElseBranchImpl(catch.startOffset, catch.endOffset, litTrue, catchBody)
break
} else {
val typeCheck = buildIsCheck(pendingException, type, typeSymbol)
val typeCheck = buildIsCheck(pendingException, type, typeSymbol!!)
branches += IrBranchImpl(catch.startOffset, catch.endOffset, typeCheck, catchBody)
}
}
if (!commonType.isDynamic()) {
if (commonType !is IrDynamicType) {
val throwStatement = JsIrBuilder.buildThrow(nothingType, pendingException)
branches += IrElseBranchImpl(litTrue, JsIrBuilder.buildBlock(nothingType, listOf(throwStatement)))
}
@@ -106,14 +110,14 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas
return aTry.run { IrTryImpl(startOffset, endOffset, type, tryResult, listOf(newCatch), finallyExpression) }
}
private fun buildIsCheck(value: IrExpression, toType: KotlinType, toTypeSymbol: IrClassifierSymbol) =
JsIrBuilder.buildTypeOperator(context.irBuiltIns.bool, IrTypeOperator.INSTANCEOF, value, toType, toTypeSymbol)
private fun buildIsCheck(value: IrExpression, toType: IrType, toTypeSymbol: IrClassifierSymbol) =
JsIrBuilder.buildTypeOperator(context.irBuiltIns.booleanType, IrTypeOperator.INSTANCEOF, value, toType, toTypeSymbol)
private fun buildImplicitCast(value: IrExpression, toType: KotlinType, toTypeSymbol: IrClassifierSymbol) =
private fun buildImplicitCast(value: IrExpression, toType: IrType, toTypeSymbol: IrClassifierSymbol) =
JsIrBuilder.buildTypeOperator(toType, IrTypeOperator.IMPLICIT_CAST, value, toType, toTypeSymbol)
private fun mergeTypes(types: List<KotlinType>) = CommonSupertypes.commonSupertype(types).also {
assert(it.isSubtypeOf(context.builtIns.throwable.defaultType) || it.isDynamic())
private fun mergeTypes(types: List<IrType>) = types.commonSupertype().also {
assert(it.isSubtypeOf(context.irBuiltIns.throwableType) || it is IrDynamicType)
}
}, null)

View File

@@ -26,6 +26,8 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
@@ -72,8 +74,9 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
// val t = Object.create(Foo.prototype);
// return Foo_init_$Init$(..., t)
// }
val newInitConstructor = createInitConstructor(declaration, constructorName)
val newCreateConstructor = createCreateConstructor(declaration, newInitConstructor, constructorName)
val newInitConstructor = createInitConstructor(declaration, constructorName, irClass.defaultType)
val newCreateConstructor = createCreateConstructor(declaration, newInitConstructor, constructorName, irClass.defaultType)
oldCtorToNewMap[declaration.symbol] =
JsIrBackendContext.SecondaryCtorPair(newInitConstructor.symbol, newCreateConstructor.symbol)
@@ -95,14 +98,16 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
override fun visitReturn(expression: IrReturn): IrExpression = IrReturnImpl(
expression.startOffset,
expression.endOffset,
expression.type,
function,
IrGetValueImpl(expression.startOffset, expression.endOffset, thisSymbol)
IrGetValueImpl(expression.startOffset, expression.endOffset, thisSymbol.owner.type, thisSymbol)
)
override fun visitGetValue(expression: IrGetValue): IrExpression =
if (expression.descriptor.name.isSpecial && expression.descriptor.name.asString() == Namer.THIS_SPECIAL_NAME) IrGetValueImpl(
expression.startOffset,
expression.endOffset,
expression.type,
thisSymbol,
expression.origin
) else {
@@ -110,28 +115,32 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
}
}
private fun createInitConstructor(declaration: IrConstructor, name: String): IrSimpleFunction =
private fun createInitConstructor(
declaration: IrConstructor,
name: String,
type: IrType
): IrSimpleFunction =
JsSymbolBuilder.copyFunctionSymbol(declaration.symbol, "${name}_\$Init\$").let {
val thisSymbol =
JsSymbolBuilder.buildValueParameter(it, declaration.valueParameters.size, declaration.returnType, "\$this")
JsSymbolBuilder.buildValueParameter(it, declaration.valueParameters.size, type, "\$this")
it.initialize(
dispatchParameterDescriptor = declaration.descriptor.dispatchReceiverParameter,
typeParameters = declaration.descriptor.typeParameters,
valueParameters = declaration.descriptor.valueParameters + thisSymbol.descriptor as ValueParameterDescriptor,
type = declaration.descriptor.returnType,
returnType = type,
modality = declaration.descriptor.modality,
visibility = declaration.descriptor.visibility
)
val thisParam = JsIrBuilder.buildValueParameter(thisSymbol)
val thisParam = JsIrBuilder.buildValueParameter(thisSymbol, type)
return IrFunctionImpl(
declaration.startOffset, declaration.endOffset,
declaration.origin, it
).apply {
val retStmt = JsIrBuilder.buildReturn(it, JsIrBuilder.buildGetValue(thisSymbol))
val retStmt = JsIrBuilder.buildReturn(it, JsIrBuilder.buildGetValue(thisSymbol), context)
val statements = (declaration.body as IrStatementContainer).statements
valueParameters += (declaration.valueParameters + thisParam)
@@ -145,13 +154,13 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
}
private fun createCreateConstructor(ctorOrig: IrConstructor, ctorImpl: IrSimpleFunction, name: String): IrSimpleFunction =
private fun createCreateConstructor(ctorOrig: IrConstructor, ctorImpl: IrSimpleFunction, name: String, type: IrType): IrSimpleFunction =
JsSymbolBuilder.copyFunctionSymbol(ctorOrig.symbol, "${name}_\$Create\$").let {
it.initialize(
dispatchParameterDescriptor = ctorOrig.descriptor.dispatchReceiverParameter,
typeParameters = ctorOrig.descriptor.typeParameters,
valueParameters = ctorOrig.descriptor.valueParameters,
type = ctorOrig.returnType,
returnType = type,
modality = ctorOrig.descriptor.modality,
visibility = ctorOrig.visibility
)
@@ -165,14 +174,14 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
typeParameters += ctorOrig.typeParameters
// parent = ctorOrig.parent
val returnType = ctorOrig.returnType
val returnType = type
val createFunctionIntrinsic = context.intrinsics.jsObjectCreate
val irCreateCall = JsIrBuilder.buildCall(
createFunctionIntrinsic.symbol,
returnType,
mapOf(createFunctionIntrinsic.typeParameters[0].descriptor to returnType)
listOf(returnType)
)
val irDelegateCall = JsIrBuilder.buildCall(ctorImpl.symbol).also {
val irDelegateCall = JsIrBuilder.buildCall(ctorImpl.symbol, type).also {
for (i in 0 until valueParameters.size) {
it.putValueArgument(i, JsIrBuilder.buildGetValue(valueParameters[i].symbol))
}
@@ -181,7 +190,7 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
// typeParameters.mapIndexed { i, t -> ctorImpl.typeParameters[i].descriptor -> }
}
val irReturn = JsIrBuilder.buildReturn(it, irDelegateCall)
val irReturn = JsIrBuilder.buildReturn(it, irDelegateCall, context)
body = JsIrBuilder.buildBlockBody(listOf(irReturn))
@@ -233,10 +242,11 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
IrGetValueImpl(
expression.startOffset,
expression.endOffset,
expression.type,
IrValueParameterSymbolImpl(LazyClassReceiverParameterDescriptor(target.descriptor.containingDeclaration))
)
} else {
IrGetValueImpl(expression.startOffset, expression.endOffset, ownerFunc.valueParameters.last().symbol)
IrGetValueImpl(expression.startOffset, expression.endOffset, expression.type, ownerFunc.valueParameters.last().symbol)
}
newCall.putValueArgument(expression.valueArgumentsCount, readThis)
@@ -247,7 +257,7 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
private fun redirectCall(
call: IrFunctionAccessExpression,
newTarget: IrSimpleFunctionSymbol
) = IrCallImpl(call.startOffset, call.endOffset, newTarget).apply {
) = IrCallImpl(call.startOffset, call.endOffset, call.type, newTarget).apply {
copyTypeArgumentsFrom(call)

View File

@@ -6,35 +6,34 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.descriptors.isFunctionOrKFunctionType
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.backend.common.utils.*
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrArithBuilder
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.symbols.JsSymbolBuilder
import org.jetbrains.kotlin.ir.backend.js.utils.isReified
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isNullable
import org.jetbrains.kotlin.types.typeUtil.*
class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
private val unit = context.builtIns.unit
private val unitValue = JsIrBuilder.buildGetObjectValue(unit.defaultType, context.symbolTable.referenceClass(unit))
private val unit = context.irBuiltIns.unitType
private val unitValue = JsIrBuilder.buildGetObjectValue(unit, unit.classifierOrFail as IrClassSymbol)
private val lit24 = JsIrBuilder.buildInt(context.builtIns.intType, 24)
private val lit16 = JsIrBuilder.buildInt(context.builtIns.intType, 16)
private val lit24 = JsIrBuilder.buildInt(context.irBuiltIns.intType, 24)
private val lit16 = JsIrBuilder.buildInt(context.irBuiltIns.intType, 16)
private val byteMask = JsIrBuilder.buildInt(context.builtIns.intType, 0xFF)
private val shortMask = JsIrBuilder.buildInt(context.builtIns.intType, 0xFFFF)
private val byteMask = JsIrBuilder.buildInt(context.irBuiltIns.intType, 0xFF)
private val shortMask = JsIrBuilder.buildInt(context.irBuiltIns.intType, 0xFFFF)
private val calculator = JsIrArithBuilder(context)
@@ -53,13 +52,13 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
private val typeOfIntrinsicSymbol = context.intrinsics.jsTypeOf.symbol
private val toJSTypeIntrinsicSymbol = context.intrinsics.jsToJsType.symbol
private val stringMarker = JsIrBuilder.buildString(context.irBuiltIns.string, "string")
private val booleanMarker = JsIrBuilder.buildString(context.irBuiltIns.string, "boolean")
private val functionMarker = JsIrBuilder.buildString(context.irBuiltIns.string, "function")
private val numberMarker = JsIrBuilder.buildString(context.irBuiltIns.string, "number")
private val stringMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "string")
private val booleanMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "boolean")
private val functionMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "function")
private val numberMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "number")
private val litTrue: IrExpression = JsIrBuilder.buildBoolean(context.irBuiltIns.bool, true)
private val litNull: IrExpression = JsIrBuilder.buildNull(context.builtIns.nullableNothingType)
private val litTrue: IrExpression = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true)
private val litNull: IrExpression = JsIrBuilder.buildNull(context.irBuiltIns.nothingNType)
private fun getInternalFunction(name: String) = context.symbolTable.referenceSimpleFunction(context.getInternalFunctions(name).single())
@@ -126,16 +125,21 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
}
// Note: native `instanceOf` is not used which is important because of null-behaviour
private fun advancedCheckRequired(type: KotlinType) = type.isInterface() ||
KotlinBuiltIns.isArray(type) ||
KotlinBuiltIns.isPrimitiveArray(type) ||
private fun advancedCheckRequired(type: IrType) = type.isInterface() ||
type.isArray() ||
type.isPrimitiveArray() ||
isTypeOfCheckingType(type)
private fun isTypeOfCheckingType(type: KotlinType) =
((type.isPrimitiveNumberType() || KotlinBuiltIns.isNumber(type)) && !type.isLong() && !type.isChar()) ||
private fun isTypeOfCheckingType(type: IrType) =
type.isByte() ||
type.isShort() ||
type.isInt() ||
type.isFloat() ||
type.isDouble() ||
type.isNumber() ||
type.isBoolean() ||
type.isFunctionOrKFunctionType ||
KotlinBuiltIns.isString(type)
type.isFunctionOrKFunction() ||
type.isString()
fun lowerInstanceOf(
expression: IrTypeOperatorCall,
@@ -146,7 +150,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
assert((expression.operator == IrTypeOperator.NOT_INSTANCEOF) == inverted)
val toType = expression.typeOperand
val isCopyRequired = expression.argument.type.isNullable() && advancedCheckRequired(toType.makeNotNullable())
val isCopyRequired = expression.argument.type.isNullable() && advancedCheckRequired(toType.makeNotNull())
val newStatements = mutableListOf<IrStatement>()
val argument =
@@ -167,12 +171,12 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
private fun cacheValue(value: IrExpression, newStatements: MutableList<IrStatement>, cd: DeclarationDescriptor): IrExpression {
val varSymbol = JsSymbolBuilder.buildTempVar(cd, value.type, mutable = false)
newStatements += JsIrBuilder.buildVar(varSymbol, value)
newStatements += JsIrBuilder.buildVar(varSymbol, value, value.type)
return JsIrBuilder.buildGetValue(varSymbol)
}
private fun generateTypeCheck(argument: IrExpression, toType: KotlinType): IrExpression {
val toNotNullable = toType.makeNotNullable()
private fun generateTypeCheck(argument: IrExpression, toType: IrType): IrExpression {
val toNotNullable = toType.makeNotNull()
val instanceCheck = generateTypeCheckNonNull(argument, toNotNullable)
val isFromNullable = argument.type.isNullable()
val isToNullable = toType.isNullable()
@@ -190,14 +194,14 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
}
}
private fun generateTypeCheckNonNull(argument: IrExpression, toType: KotlinType): IrExpression {
assert(!toType.isMarkedNullable)
private fun generateTypeCheckNonNull(argument: IrExpression, toType: IrType): IrExpression {
assert(!toType.isMarkedNullable())
return when {
KotlinBuiltIns.isAny(toType) -> generateIsObjectCheck(argument)
toType.isAny() -> generateIsObjectCheck(argument)
isTypeOfCheckingType(toType) -> generateTypeOfCheck(argument, toType)
toType.isChar() -> generateCheckForChar(argument)
KotlinBuiltIns.isArray(toType) -> generateGenericArrayCheck(argument)
KotlinBuiltIns.isPrimitiveArray(toType) -> generatePrimitiveArrayTypeCheck(argument, toType)
toType.isArray() -> generateGenericArrayCheck(argument)
toType.isPrimitiveArray() -> generatePrimitiveArrayTypeCheck(argument, toType)
toType.isTypeParameter() -> generateTypeCheckWithTypeParameter(argument, toType)
toType.isInterface() -> generateInterfaceCheck(argument, toType)
else -> generateNativeInstanceOf(argument, toType)
@@ -208,12 +212,14 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
putValueArgument(0, argument)
}
private fun generateTypeCheckWithTypeParameter(argument: IrExpression, toType: KotlinType): IrExpression {
val typeParameterDescriptor = toType.constructor.declarationDescriptor as TypeParameterDescriptor
assert(!typeParameterDescriptor.isReified) { "reified parameters have to be lowered before" }
private fun generateTypeCheckWithTypeParameter(argument: IrExpression, toType: IrType): IrExpression {
val typeParameter =
(toType.classifierOrNull as? IrTypeParameterSymbol)?.owner ?: error("expected type parameter, but $toType")
return typeParameterDescriptor.upperBounds.fold(litTrue) { r, t ->
val check = generateTypeCheckNonNull(argument, t.makeNotNullable())
assert(!typeParameter.isReified) { "reified parameters have to be lowered before" }
return typeParameter.superTypes.fold(litTrue) { r, t ->
val check = generateTypeCheckNonNull(argument, t.makeNotNull())
calculator.and(r, check)
}
}
@@ -221,11 +227,11 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
private fun generateCheckForChar(argument: IrExpression) =
JsIrBuilder.buildCall(isCharSymbol).apply { dispatchReceiver = argument }
private fun generateTypeOfCheck(argument: IrExpression, toType: KotlinType): IrExpression {
private fun generateTypeOfCheck(argument: IrExpression, toType: IrType): IrExpression {
val marker = when {
toType.isFunctionOrKFunctionType -> functionMarker
toType.isFunctionOrKFunction() -> functionMarker
toType.isBoolean() -> booleanMarker
KotlinBuiltIns.isString(toType) -> stringMarker
toType.isString() -> stringMarker
else -> numberMarker
}
@@ -236,17 +242,17 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
}
}
private fun wrapTypeReference(toType: KotlinType) =
private fun wrapTypeReference(toType: IrType) =
JsIrBuilder.buildCall(toJSTypeIntrinsicSymbol).apply { putTypeArgument(0, toType) }
private fun generateGenericArrayCheck(argument: IrExpression) =
JsIrBuilder.buildCall(isArraySymbol).apply { putValueArgument(0, argument) }
private fun generatePrimitiveArrayTypeCheck(argument: IrExpression, toType: KotlinType): IrExpression {
private fun generatePrimitiveArrayTypeCheck(argument: IrExpression, toType: IrType): IrExpression {
TODO("Implement Typed Array check")
}
private fun generateInterfaceCheck(argument: IrExpression, toType: KotlinType): IrExpression {
private fun generateInterfaceCheck(argument: IrExpression, toType: IrType): IrExpression {
val irType = wrapTypeReference(toType)
return JsIrBuilder.buildCall(isInterfaceSymbol).apply {
putValueArgument(0, argument)
@@ -254,7 +260,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
}
}
private fun generateNativeInstanceOf(argument: IrExpression, toType: KotlinType): IrExpression {
private fun generateNativeInstanceOf(argument: IrExpression, toType: IrType): IrExpression {
val irType = wrapTypeReference(toType)
return JsIrBuilder.buildCall(instanceOfIntrinsicSymbol).apply {
putValueArgument(0, argument)
@@ -264,12 +270,12 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
private fun lowerCoercionToUnit(expression: IrTypeOperatorCall): IrExpression {
assert(expression.operator === IrTypeOperator.IMPLICIT_COERCION_TO_UNIT)
return expression.run { IrCompositeImpl(startOffset, endOffset, unit.defaultType, null, listOf(argument, unitValue)) }
return expression.run { IrCompositeImpl(startOffset, endOffset, unit, null, listOf(argument, unitValue)) }
}
private fun lowerIntegerCoercion(expression: IrTypeOperatorCall, containingDeclaration: DeclarationDescriptor): IrExpression {
assert(expression.operator === IrTypeOperator.IMPLICIT_INTEGER_COERCION)
assert(KotlinBuiltIns.isInt(expression.argument.type))
assert(expression.argument.type.isInt())
val isNullable = expression.argument.type.isNullable()
val toType = expression.typeOperand
@@ -284,9 +290,9 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
if (isNullable) cacheValue(expression.argument, newStatements, containingDeclaration) else expression.argument
val casted = when {
KotlinBuiltIns.isByte(toType) -> maskOp(argument, byteMask, lit24)
KotlinBuiltIns.isShort(toType) -> maskOp(argument, shortMask, lit16)
KotlinBuiltIns.isLong(toType) -> TODO("Long coercion")
toType.isByte() -> maskOp(argument, byteMask, lit24)
toType.isShort() -> maskOp(argument, shortMask, lit16)
toType.isLong() -> TODO("Long coercion")
else -> error("Unreachable execution (coercion to non-Integer type")
}

View File

@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.impl.createClassSymbolOrNull
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.DeepCopyIrTree
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -34,7 +35,6 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.typeUtil.makeNullable
// backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DeepCopyIrTreeWithDescriptors.kt
@@ -479,7 +479,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
return IrCallImpl(
startOffset = expression.startOffset,
endOffset = expression.endOffset,
type = newDescriptor.returnType!!,
type = newDescriptor.returnType?.toIrType()!!,
descriptor = newDescriptor,
typeArgumentsCount = expression.typeArgumentsCount,
origin = expression.origin,
@@ -517,7 +517,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
//---------------------------------------------------------------------//
fun getTypeOperatorReturnType(operator: IrTypeOperator, type: KotlinType) : KotlinType {
fun getTypeOperatorReturnType(operator: IrTypeOperator, type: IrType) : IrType {
return when (operator) {
IrTypeOperator.CAST,
IrTypeOperator.IMPLICIT_CAST,
@@ -526,7 +526,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
IrTypeOperator.IMPLICIT_INTEGER_COERCION -> type
IrTypeOperator.SAFE_CAST -> type.makeNullable()
IrTypeOperator.INSTANCEOF,
IrTypeOperator.NOT_INSTANCEOF -> context.builtIns.booleanType
IrTypeOperator.NOT_INSTANCEOF -> context.irBuiltIns.booleanType
}
}
@@ -541,7 +541,8 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
type = returnType,
operator = expression.operator,
typeOperand = typeOperand,
argument = expression.argument.transform(this, null)
argument = expression.argument.transform(this, null),
typeOperandClassifier = typeOperand.classifierOrFail
)
}
@@ -610,6 +611,8 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
//-------------------------------------------------------------------------//
private fun substituteType(oldType: IrType?): IrType? = substituteType(oldType?.toKotlinType())?.toIrType()
private fun substituteType(oldType: KotlinType?): KotlinType? {
if (typeSubstitutor == null) return oldType
if (oldType == null) return oldType
@@ -699,7 +702,8 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap<
endOffset = declaration.endOffset,
origin = declaration.origin,
descriptor = newDescriptor,
initializer = declaration.initializer
initializer = declaration.initializer,
type = declaration.type
)
}
@@ -715,7 +719,8 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap<
startOffset = expression.startOffset,
endOffset = expression.endOffset,
origin = expression.origin,
symbol = createValueSymbol(newDescriptor)
symbol = createValueSymbol(newDescriptor),
type = expression.type
)
}
@@ -732,7 +737,7 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap<
return IrCallImpl(
startOffset = oldExpression.startOffset,
endOffset = oldExpression.endOffset,
type = newDescriptor.returnType!!,
type = oldExpression.type,
symbol = createFunctionSymbol(newDescriptor),
descriptor = newDescriptor,
typeArgumentsCount = oldExpression.typeArgumentsCount,
@@ -763,4 +768,3 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap<
return oldExpression.shallowCopy(oldExpression.origin, createFunctionSymbol(newDescriptor), oldExpression.superQualifierSymbol)
}
}

View File

@@ -23,14 +23,16 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.getDefault
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.TypeProjection
@@ -149,8 +151,8 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, startOffset, endOffset)
irBuilder.run {
val constructorDescriptor = delegatingConstructorCall.descriptor.original
val constructorCall = irCall(delegatingConstructorCall.symbol,
constructorDescriptor.typeParameters.associate { it to delegatingConstructorCall.getTypeArgument(it)!! }).apply {
val constructorCall = irCall(delegatingConstructorCall.symbol).apply {
constructorDescriptor.typeParameters.forEach() { putTypeArgument(it.index, delegatingConstructorCall.getTypeArgument(it)!!) }
constructorDescriptor.valueParameters.forEach { putValueArgument(it, delegatingConstructorCall.getValueArgument(it)) }
}
val oldThis = delegatingConstructorCall.descriptor.constructedClass.thisAsReceiverParameter
@@ -159,12 +161,12 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
nameHint = delegatingConstructorCall.descriptor.fqNameSafe.toString() + ".this"
)
statements[0] = newThis
substituteMap[oldThis] = irGet(newThis.symbol)
statements.add(irReturn(irGet(newThis.symbol)))
substituteMap[oldThis] = irGet(newThis)
statements.add(irReturn(irGet(newThis)))
}
}
val returnType = copyFunctionDeclaration.descriptor.returnType!! // Substituted return type.
val returnType = copyFunctionDeclaration.returnType // Substituted return type.
val sourceFileName = context.originalModuleIndex.declarationToFile[caller.descriptor.original] ?: ""
val inlineFunctionBody = IrReturnableBlockImpl( // Create new IR element to replace "call".
startOffset = startOffset,
@@ -248,7 +250,7 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
val substitutionContext = mutableMapOf<TypeConstructor, TypeProjection>()
for (index in 0 until irCall.typeArgumentsCount) {
val typeArgument = irCall.getTypeArgument(index) ?: continue
substitutionContext[typeParameters[index].typeConstructor] = TypeProjectionImpl(typeArgument)
substitutionContext[typeParameters[index].typeConstructor] = TypeProjectionImpl(typeArgument.toKotlinType())
}
return TypeSubstitutor.create(substitutionContext)
}
@@ -309,7 +311,8 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
}
val parametersWithDefaultToArgument = mutableListOf<ParameterToArgument>()
functionDescriptor.valueParameters.forEach { parameterDescriptor -> // Iterate value parameter descriptors.
irFunction.valueParameters.forEach { parameter -> // Iterate value parameter descriptors.
val parameterDescriptor = parameter.descriptor as ValueParameterDescriptor
val argument = valueArguments[parameterDescriptor.index] // Get appropriate argument from call site.
when {
argument != null -> { // Argument is good enough.
@@ -331,8 +334,8 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
val emptyArray = IrVarargImpl(
startOffset = irCall.startOffset,
endOffset = irCall.endOffset,
type = parameterDescriptor.type,
varargElementType = parameterDescriptor.varargElementType!!
type = parameter.type,
varargElementType = parameter.varargElementType!!
)
parameterToArgument += ParameterToArgument(
parameterDescriptor = parameterDescriptor,
@@ -377,7 +380,8 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
val getVal = IrGetValueImpl( // Create new expression, representing access the new variable.
startOffset = currentScope.irElement.startOffset,
endOffset = currentScope.irElement.endOffset,
symbol = createValueSymbol(newVariable.descriptor)
type = newVariable.type,
symbol = newVariable.symbol
)
substituteMap[parameterDescriptor] = getVal // Parameter will be replaced with the new variable.
}

View File

@@ -11,12 +11,13 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.lower.inline.addChildren
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrReturnTargetSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.toIrType
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.visitors.*
@@ -51,7 +52,11 @@ internal fun IrModuleFragment.replaceUnboundSymbols(context: JsIrBackendContext)
// Generate missing external stubs:
// TODO: ModuleGenerator::generateUnboundSymbolsAsDependencies(IRModuleFragment) is private function :/
@Suppress("DEPRECATION")
ExternalDependenciesGenerator(symbolTable = context.symbolTable, irBuiltIns = context.irBuiltIns).generateUnboundSymbolsAsDependencies(this)
ExternalDependenciesGenerator(
descriptor,
symbolTable = context.symbolTable,
irBuiltIns = context.irBuiltIns
).generateUnboundSymbolsAsDependencies(this)
// Merge duplicated module and package declarations:
this.acceptVoid(object : IrElementVisitorVoid {
@@ -161,7 +166,7 @@ private class IrUnboundSymbolReplacer(
expression.transformChildrenVoid(this)
return with(expression) {
IrGetValueImpl(startOffset, endOffset, symbol, origin)
IrGetValueImpl(startOffset, endOffset, expression.type, symbol, origin)
}
}
@@ -170,13 +175,13 @@ private class IrUnboundSymbolReplacer(
expression.transformChildrenVoid(this)
return with(expression) {
IrSetVariableImpl(startOffset, endOffset, symbol, value, origin)
IrSetVariableImpl(startOffset, endOffset, expression.type, symbol, value, origin)
}
}
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
val symbol = expression.symbol.replace(SymbolTable::referenceClass) ?:
return super.visitGetObjectValue(expression)
return super.visitGetObjectValue(expression)
expression.transformChildrenVoid(this)
return with(expression) {
@@ -186,7 +191,7 @@ private class IrUnboundSymbolReplacer(
override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression {
val symbol = expression.symbol.replace(SymbolTable::referenceEnumEntry) ?:
return super.visitGetEnumValue(expression)
return super.visitGetEnumValue(expression)
expression.transformChildrenVoid(this)
return with(expression) {
@@ -200,17 +205,11 @@ private class IrUnboundSymbolReplacer(
expression.transformChildrenVoid(this)
return with(expression) {
IrClassReferenceImpl(startOffset, endOffset, type, symbol, symbol.descriptor.defaultType)
IrClassReferenceImpl(startOffset, endOffset, type, symbol, symbol.descriptor.toIrType())
}
}
override fun visitClass(declaration: IrClass): IrStatement {
declaration.superClasses.forEachIndexed { index, symbol ->
val newSymbol = symbol.replace(SymbolTable::referenceClass)
if (newSymbol != null) {
declaration.superClasses[index] = newSymbol
}
}
withLocal(declaration.thisReceiver?.symbol) {
return super.visitClass(declaration)
}
@@ -227,7 +226,7 @@ private class IrUnboundSymbolReplacer(
expression.transformChildrenVoid(this)
return with(expression) {
IrGetFieldImpl(startOffset, endOffset, symbol, receiver, origin, superQualifierSymbol)
IrGetFieldImpl(startOffset, endOffset, symbol, type, receiver, origin, superQualifierSymbol)
}
}
@@ -242,11 +241,13 @@ private class IrUnboundSymbolReplacer(
expression.transformChildrenVoid(this)
return with(expression) {
IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value, origin, superQualifierSymbol)
IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value, type /*wrong*/, origin, superQualifierSymbol)
}
}
override fun visitCall(expression: IrCall): IrExpression {
expression.replaceTypeArguments()
val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?: expression.symbol
val superQualifierSymbol = expression.superQualifierSymbol?.replaceOrSame(SymbolTable::referenceClass)
@@ -257,17 +258,21 @@ private class IrUnboundSymbolReplacer(
expression.transformChildrenVoid()
return with(expression) {
IrCallImpl(startOffset, endOffset, symbol, descriptor,
getTypeArgumentsMap(),
origin, superQualifierSymbol).also {
IrCallImpl(startOffset, endOffset, type, symbol, descriptor,
typeArgumentsCount,
origin, superQualifierSymbol).also {
it.copyArgumentsFrom(this)
it.copyTypeArgumentsFrom(this)
}
}
}
private fun IrMemberAccessExpression.getTypeArgumentsMap() =
descriptor.original.typeParameters.associate { it to getTypeArgumentOrDefault(it) }
private fun IrMemberAccessExpression.replaceTypeArguments() {
repeat(typeArgumentsCount) {
putTypeArgument(it, getTypeArgument(it)/*?.toKotlinType()?.let { context.ir.translateErased(it) }*/)
}
}
private fun IrMemberAccessExpressionBase.copyArgumentsFrom(original: IrMemberAccessExpression) {
dispatchReceiver = original.dispatchReceiver
@@ -279,40 +284,48 @@ private class IrUnboundSymbolReplacer(
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression {
val symbol = expression.symbol.replace(SymbolTable::referenceConstructor) ?:
return super.visitEnumConstructorCall(expression)
return super.visitEnumConstructorCall(expression)
return with(expression) {
IrEnumConstructorCallImpl(startOffset, endOffset, symbol, null).also {
IrEnumConstructorCallImpl(startOffset, endOffset, expression.type, symbol, 0).also {
it.copyArgumentsFrom(this)
}
}
}
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
expression.replaceTypeArguments()
val symbol = expression.symbol.replace(SymbolTable::referenceConstructor) ?:
return super.visitDelegatingConstructorCall(expression)
return super.visitDelegatingConstructorCall(expression)
expression.transformChildrenVoid()
return with(expression) {
IrDelegatingConstructorCallImpl(startOffset, endOffset, symbol, descriptor, getTypeArgumentsMap()).also {
IrDelegatingConstructorCallImpl(startOffset, endOffset, type, symbol, descriptor, typeArgumentsCount).also {
it.copyArgumentsFrom(this)
it.copyTypeArgumentsFrom(this)
}
}
}
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
expression.replaceTypeArguments()
val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?:
return super.visitFunctionReference(expression)
return super.visitFunctionReference(expression)
expression.transformChildrenVoid(this)
return with(expression) {
IrFunctionReferenceImpl(startOffset, endOffset, type, symbol, descriptor, getTypeArgumentsMap()).also {
IrFunctionReferenceImpl(startOffset, endOffset, type, symbol, descriptor, 0).also {
it.copyArgumentsFrom(this)
it.copyTypeArgumentsFrom(this)
}
}
}
override fun visitPropertyReference(expression: IrPropertyReference): IrExpression {
expression.replaceTypeArguments()
val field = expression.field?.replaceOrSame(SymbolTable::referenceField)
val getter = expression.getter?.replace(SymbolTable::referenceFunction) ?: expression.getter
val setter = expression.setter?.replace(SymbolTable::referenceFunction) ?: expression.setter
@@ -323,13 +336,14 @@ private class IrUnboundSymbolReplacer(
expression.transformChildrenVoid(this)
return with(expression) {
IrPropertyReferenceImpl(startOffset, endOffset, type, descriptor,
field,
getter,
setter,
getTypeArgumentsMap(), origin).also {
IrPropertyReferenceImpl(startOffset, endOffset, type, descriptor, 0,
field,
getter,
setter,
origin).also {
it.copyArgumentsFrom(this)
it.copyTypeArgumentsFrom(this)
}
}
}
@@ -346,7 +360,7 @@ private class IrUnboundSymbolReplacer(
expression.transformChildrenVoid(this)
return with(expression) {
IrLocalDelegatedPropertyReferenceImpl(startOffset, endOffset, type, descriptor,
delegate, getter, setter, origin).also {
delegate, getter, setter, origin).also {
it.copyArgumentsFrom(this)
}
@@ -406,12 +420,24 @@ private class IrUnboundSymbolReplacer(
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression {
val classSymbol = expression.classSymbol.replace(SymbolTable::referenceClass) ?:
return super.visitInstanceInitializerCall(expression)
return super.visitInstanceInitializerCall(expression)
expression.transformChildrenVoid(this)
return with(expression) {
IrInstanceInitializerCallImpl(startOffset, endOffset, classSymbol)
IrInstanceInitializerCallImpl(startOffset, endOffset, classSymbol, type)
}
}
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression {
expression.transformChildrenVoid(this)
return with(expression) {
val newTypeOperand = typeOperand /*context.ir.translateErased(typeOperand.toKotlinType())*/
IrTypeOperatorCallImpl(startOffset, endOffset, type, operator, newTypeOperand).also {
it.argument = argument
it.typeOperandClassifier = newTypeOperand.classifierOrFail
}
}
}
}

View File

@@ -5,10 +5,11 @@
package org.jetbrains.kotlin.ir.backend.js.lower.inline
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
@@ -19,21 +20,6 @@ fun IrSimpleFunction.setOverrides(symbolTable: SymbolTable) {
this.descriptor.overriddenDescriptors.mapTo(this.overriddenSymbols) {
symbolTable.referenceSimpleFunction(it.original)
}
this.typeParameters.forEach { it.setSupers(symbolTable) }
}
fun IrTypeParameter.setSupers(symbolTable: SymbolTable) {
assert(this.superClassifiers.isEmpty())
this.descriptor.upperBounds.mapNotNullTo(this.superClassifiers) {
it.constructor.declarationDescriptor?.let {
if (it is TypeParameterDescriptor) {
IrTypeParameterSymbolImpl(it) // Workaround for deserialized inline functions
} else {
symbolTable.referenceClassifier(it)
}
}
}
}
fun IrDeclarationContainer.addChildren(declarations: List<IrDeclaration>) {

View File

@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.getTypeArgumentOrDefault
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -43,6 +45,10 @@ fun IrModuleFragment.referenceAllTypeExternalClassifiers(symbolTable: SymbolTabl
}
}
fun IrType.referenceAllClassifiers() {
this.toKotlinType().referenceAllClassifiers()
}
val visitor = object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
@@ -125,4 +131,4 @@ fun IrModuleFragment.referenceAllTypeExternalClassifiers(symbolTable: SymbolTabl
it.acceptVoid(visitor)
}
}
}
}

View File

@@ -10,14 +10,18 @@ import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.symbols.JsSymbolBuilder
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
import org.jetbrains.kotlin.ir.expressions.IrContainerExpression
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrReturn
import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrDoWhileLoopImpl
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
/**
* Replaces returnable blocks and `return`'s with loops and `break`'s correspondingly.
@@ -93,7 +97,7 @@ private class ReturnableBlockTransformer(
return super.visitDeclaration(declaration, data)
}
private val constFalse = JsIrBuilder.buildBoolean(context.builtIns.booleanType, false)
private val constFalse = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, false)
override fun visitContainerExpression(expression: IrContainerExpression, data: ReturnableBlockLoweringContext): IrExpression {
if (expression !is IrReturnableBlock) return super.visitContainerExpression(expression, data)
@@ -111,7 +115,7 @@ private class ReturnableBlockTransformer(
IrDoWhileLoopImpl(
expression.startOffset,
expression.endOffset,
context.builtIns.unitType,
context.irBuiltIns.unitType,
expression.origin
).apply {
label = "l\$ret\$${data.labelCnt++}"
@@ -127,10 +131,10 @@ private class ReturnableBlockTransformer(
IrCompositeImpl(
returnExpression.startOffset,
returnExpression.endOffset,
context.builtIns.unitType
context.irBuiltIns.unitType
).apply {
statements += JsIrBuilder.buildSetVariable(variable, returnExpression.value)
statements += JsIrBuilder.buildBreak(context.builtIns.unitType, loop)
statements += JsIrBuilder.buildSetVariable(variable, returnExpression.value, context.irBuiltIns.unitType)
statements += JsIrBuilder.buildBreak(context.irBuiltIns.unitType, loop)
}
}
@@ -138,7 +142,7 @@ private class ReturnableBlockTransformer(
if (i == expression.statements.lastIndex && s is IrReturn && s.returnTargetSymbol == expression.symbol) {
s.transformChildren(this, data)
if (!hasReturned) s.value else {
JsIrBuilder.buildSetVariable(variable, s.value)
JsIrBuilder.buildSetVariable(variable, s.value, context.irBuiltIns.unitType)
}
} else {
s.transform(this, data)
@@ -159,7 +163,7 @@ private class ReturnableBlockTransformer(
loop.body = IrBlockImpl(
expression.startOffset,
expression.endOffset,
context.builtIns.unitType,
context.irBuiltIns.unitType,
expression.origin,
newStatements
)
@@ -170,7 +174,7 @@ private class ReturnableBlockTransformer(
expression.type,
expression.origin
).apply {
statements += JsIrBuilder.buildVar(variable)
statements += JsIrBuilder.buildVar(variable, type = expression.type)
statements += loop
statements += JsIrBuilder.buildGetValue(variable)
}

View File

@@ -18,12 +18,13 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
object JsSymbolBuilder {
fun buildValueParameter(containingSymbol: IrSimpleFunctionSymbol, index: Int, type: KotlinType, name: String? = null) =
IrValueParameterSymbolImpl(createValueParameter(containingSymbol.descriptor, index, name ?: "param$index", type))
fun buildValueParameter(containingSymbol: IrSimpleFunctionSymbol, index: Int, type: IrType, name: String? = null) =
IrValueParameterSymbolImpl(createValueParameter(containingSymbol.descriptor, index, name ?: "param$index", type.toKotlinType()))
fun buildSimpleFunction(
containingDeclaration: DeclarationDescriptor,
@@ -53,7 +54,7 @@ object JsSymbolBuilder {
fun buildVar(
containingDeclaration: DeclarationDescriptor,
type: KotlinType,
type: IrType,
name: String,
mutable: Boolean = false
) = IrVariableSymbolImpl(
@@ -61,42 +62,42 @@ object JsSymbolBuilder {
containingDeclaration,
Annotations.EMPTY,
Name.identifier(name),
type,
type.toKotlinType(),
mutable,
false,
SourceElement.NO_SOURCE
)
)
fun buildTempVar(containingSymbol: IrSymbol, type: KotlinType, name: String? = null, mutable: Boolean = false) =
fun buildTempVar(containingSymbol: IrSymbol, type: IrType, name: String? = null, mutable: Boolean = false) =
buildTempVar(containingSymbol.descriptor, type, name, mutable)
fun buildTempVar(containingDeclaration: DeclarationDescriptor, type: KotlinType, name: String? = null, mutable: Boolean = false) =
fun buildTempVar(containingDeclaration: DeclarationDescriptor, type: IrType, name: String? = null, mutable: Boolean = false) =
IrVariableSymbolImpl(
IrTemporaryVariableDescriptorImpl(
containingDeclaration,
Name.identifier(name ?: "tmp"),
type, mutable
type.toKotlinType(), mutable
)
)
}
fun IrSimpleFunctionSymbol.initialize(
receiverParameterType: KotlinType? = null,
receiverParameterType: IrType? = null,
dispatchParameterDescriptor: ReceiverParameterDescriptor? = null,
typeParameters: List<TypeParameterDescriptor> = emptyList(),
valueParameters: List<ValueParameterDescriptor> = emptyList(),
type: KotlinType? = null,
returnType: IrType? = null,
modality: Modality = Modality.FINAL,
visibility: Visibility = Visibilities.LOCAL
) = this.apply {
(descriptor as FunctionDescriptorImpl).initialize(
receiverParameterType,
receiverParameterType?.toKotlinType(),
dispatchParameterDescriptor,
typeParameters,
valueParameters,
type,
returnType?.toKotlinType(),
modality,
visibility
)

View File

@@ -5,15 +5,15 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.backend.common.utils.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.types.isUnit
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.util.OperatorNameConventions
class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsExpression, JsGenerationContext> {
@@ -158,7 +158,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
val arguments = translateCallArguments(expression, context)
if (dispatchReceiver != null &&
dispatchReceiver.type.isFunctionTypeOrSubtype && symbol.owner.name == OperatorNameConventions.INVOKE
dispatchReceiver.type.isFunctionTypeOrSubtype() && symbol.owner.name == OperatorNameConventions.INVOKE
) {
return JsInvocation(jsDispatchReceiver!!, arguments)
}

View File

@@ -11,12 +11,14 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
import org.jetbrains.kotlin.ir.backend.js.utils.isAny
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.isAny
import org.jetbrains.kotlin.ir.util.isInterface
import org.jetbrains.kotlin.ir.util.isReal
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
@@ -26,8 +28,8 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
private val className = context.getNameForSymbol(irClass.symbol)
private val classNameRef = className.makeRef()
private val baseClass = irClass.superClasses.firstOrNull { !it.owner.isInterface }
private val baseClassName = baseClass?.let { context.getNameForSymbol(it) }
private val baseClass = irClass.superTypes.firstOrNull { !it.classifierOrFail.isInterface }
private val baseClassName = baseClass?.let { context.getNameForSymbol(it.classifierOrFail) }
private val classPrototypeRef = prototypeOf(classNameRef)
private val classBlock = JsGlobalBlock()
private val classModel = JsClassModel(className, baseClassName)
@@ -130,7 +132,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
}
private fun generateInheritanceCode(): List<JsStatement> {
if (baseClass == null || baseClass.isAny) {
if (baseClass == null || baseClass.isAny()) {
return emptyList()
}
@@ -158,7 +160,13 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
private fun generateSuperClasses(): JsPropertyInitializer = JsPropertyInitializer(
JsNameRef(Namer.METADATA_INTERFACES),
JsArrayLiteral(irClass.superClasses.filter { it.owner.isInterface }.map { JsNameRef(context.getNameForSymbol(it.owner.symbol)) })
JsArrayLiteral(
irClass.superTypes.mapNotNull {
val symbol = it.classifierOrFail
if (symbol.isInterface) JsNameRef(context.getNameForSymbol(symbol)) else null
}
)
)
}
private val IrClassifierSymbol.isInterface get() = (owner as? IrClass)?.isInterface == true

View File

@@ -5,14 +5,13 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.js.backend.ast.*
typealias IrCallTransformer = (IrCall, context: JsGenerationContext) -> JsExpression
@@ -69,7 +68,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
add(intrinsics.jsObjectCreate) { call, context ->
val classToCreate = call.getTypeArgument(0)!!
val className = context.getNameForSymbol(IrClassSymbolImpl(classToCreate.constructor.declarationDescriptor as ClassDescriptor))
val className = context.getNameForSymbol(classToCreate.classifierOrFail)
val prototype = prototypeOf(className.makeRef())
JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototype)
}
@@ -86,8 +85,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
}
add(intrinsics.jsToJsType) { call, context ->
val typeParameter = call.getTypeArgument(0)!!
val typeName = context.getNameForSymbol(IrClassSymbolImpl(typeParameter.constructor.declarationDescriptor as ClassDescriptor))
val typeName = context.getNameForSymbol(call.getTypeArgument(0)!!.classifierOrFail)
typeName.makeRef()
}

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm
@@ -46,7 +35,7 @@ class JvmBackendContext(
) : CommonBackendContext {
override val builtIns = state.module.builtIns
override val descriptorsFactory: JvmDescriptorsFactory = JvmDescriptorsFactory(psiSourceManager, builtIns)
override val sharedVariablesManager = JvmSharedVariablesManager(builtIns)
override val sharedVariablesManager = JvmSharedVariablesManager(builtIns, irBuiltIns)
override val reflectionTypes: ReflectionTypes by lazy(LazyThreadSafetyMode.PUBLICATION) {
ReflectionTypes(state.module, FqName("kotlin.reflect.jvm.internal"))
@@ -73,8 +62,8 @@ class JvmBackendContext(
context.getInternalFunctions("ThrowTypeCastException").single()
)
override val ThrowUninitializedPropertyAccessException
get () = symbolTable.referenceSimpleFunction(
override val ThrowUninitializedPropertyAccessException =
symbolTable.referenceSimpleFunction(
context.getInternalFunctions("ThrowUninitializedPropertyAccessException").single()
)

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm
@@ -44,7 +33,11 @@ object JvmBackendFacade {
state, psi2irContext.sourceManager, psi2irContext.irBuiltIns, irModuleFragment, psi2irContext.symbolTable
)
//TODO
ExternalDependenciesGenerator(psi2irContext.symbolTable, psi2irContext.irBuiltIns).generateUnboundSymbolsAsDependencies(irModuleFragment)
ExternalDependenciesGenerator(
irModuleFragment.descriptor,
psi2irContext.symbolTable,
psi2irContext.irBuiltIns
).generateUnboundSymbolsAsDependencies(irModuleFragment)
val jvmBackend = JvmBackend(jvmBackendContext)

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
@@ -23,9 +23,13 @@ import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrTypeAlias
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
@@ -176,7 +180,7 @@ class ExpressionCodegen(
//coerceNotToUnit(r.type, Type.VOID_TYPE)
exp.accept(this, data)
}
return coerceNotToUnit(result.type, expression.type)
return coerceNotToUnit(result.type, expression.type.toKotlinType())
}
override fun visitMemberAccess(expression: IrMemberAccessExpression, data: BlockInfo): StackValue {
@@ -212,7 +216,7 @@ class ExpressionCodegen(
if (args.size == 1) {
val sizeExpression = expression.getValueArgument(0)!!
gen(sizeExpression, Type.INT_TYPE, data)
newArrayInstruction(expression.type)
newArrayInstruction(expression.type.toKotlinType())
return expression.onStack
}
@@ -298,6 +302,8 @@ class ExpressionCodegen(
mv.athrow()
} else if (expression.descriptor !is ConstructorDescriptor) {
return returnType?.run { coerceNotToUnit(callable.returnType, this) } ?: onStack(callable.returnType)
} else {
return none()
}
return expression.onStack
@@ -440,7 +446,7 @@ class ExpressionCodegen(
val hasSpread = arguments.firstIsInstanceOrNull<IrSpreadElement>() != null
if (hasSpread) {
val arrayOfReferences = KotlinBuiltIns.isArray(outType)
val arrayOfReferences = KotlinBuiltIns.isArray(outType.toKotlinType()!!)
if (size == 1) {
// Arrays.copyOf(receiverValue, newLength)
val argument = (arguments[0] as IrSpreadElement).expression
@@ -488,7 +494,7 @@ class ExpressionCodegen(
if (arrayOfReferences) {
mv.dup()
mv.invokevirtual(owner, "size", "()I", false)
newArrayInstruction(outType)
newArrayInstruction(outType.toKotlinType())
mv.invokevirtual(owner, "toArray", toArrayDescriptor, false)
mv.checkcast(type)
} else {
@@ -497,8 +503,8 @@ class ExpressionCodegen(
}
} else {
mv.iconst(size)
newArrayInstruction(expression.type)
val elementKotlinType = outType.constructor.builtIns.getArrayElementType(outType)
newArrayInstruction(expression.type.toKotlinType())
val elementKotlinType = classCodegen.context.builtIns.getArrayElementType(outType.toKotlinType()!!)
for ((i, element) in expression.elements.withIndex()) {
mv.dup()
StackValue.constant(i, Type.INT_TYPE).put(Type.INT_TYPE, mv)
@@ -507,7 +513,7 @@ class ExpressionCodegen(
.arrayElement(
elementType,
elementKotlinType,
StackValue.onStack(elementType, outType),
StackValue.onStack(elementType, outType.toKotlinType()),
StackValue.onStack(Type.INT_TYPE)
)
.store(rightSide, mv)
@@ -547,7 +553,7 @@ class ExpressionCodegen(
override fun visitWhen(expression: IrWhen, data: BlockInfo): StackValue =
genIfWithBranches(expression.branches[0], data, expression.type, expression.branches.drop(1))
genIfWithBranches(expression.branches[0], data, expression.type.toKotlinType(), expression.branches.drop(1))
private fun genIfWithBranches(branch: IrBranch, data: BlockInfo, type: KotlinType, otherBranches: List<IrBranch>): StackValue {
@@ -582,7 +588,7 @@ class ExpressionCodegen(
override fun visitTypeOperator(expression: IrTypeOperatorCall, data: BlockInfo): StackValue {
val asmType = expression.typeOperand.asmType
val asmType = expression.typeOperand.toKotlinType().asmType
when (expression.operator) {
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT -> {
val result = expression.argument.accept(this, data)
@@ -601,14 +607,14 @@ class ExpressionCodegen(
StackValue.putUnitInstance(mv)
}
val boxedType = boxType(asmType)
generateAsCast(mv, expression.typeOperand, boxedType, expression.operator == IrTypeOperator.SAFE_CAST)
generateAsCast(mv, expression.typeOperand.toKotlinType(), boxedType, expression.operator == IrTypeOperator.SAFE_CAST)
return onStack(boxedType)
}
IrTypeOperator.INSTANCEOF, IrTypeOperator.NOT_INSTANCEOF -> {
gen(expression.argument, OBJECT_TYPE, data)
val type = boxType(asmType)
generateIsCheck(mv, expression.typeOperand, type)
generateIsCheck(mv, expression.typeOperand.toKotlinType(), type)
if (IrTypeOperator.NOT_INSTANCEOF == expression.operator) {
StackValue.not(StackValue.onStack(Type.BOOLEAN_TYPE)).put(Type.BOOLEAN_TYPE, mv)
}
@@ -627,7 +633,7 @@ class ExpressionCodegen(
IrTypeOperator.IMPLICIT_INTEGER_COERCION -> {
gen(expression.argument, Type.INT_TYPE, data)
StackValue.coerce(Type.INT_TYPE, typeMapper.mapType(expression.type), mv)
StackValue.coerce(Type.INT_TYPE, typeMapper.mapType(expression.type.toKotlinType()), mv)
}
}
return expression.onStack
@@ -937,7 +943,7 @@ class ExpressionCodegen(
assert(classReference is IrGetClass)
JavaClassProperty.generateImpl(mv, gen((classReference as IrGetClass).argument, data))
} else {
val type = classReference.classType
val type = classReference.classType.toKotlinType()
if (TypeUtils.isTypeParameter(type)) {
assert(TypeUtils.isReifiedTypeParameter(type)) { "Non-reified type parameter under ::class should be rejected by type checker: " + type }
putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.JAVA_CLASS, mv, this)
@@ -962,7 +968,7 @@ class ExpressionCodegen(
}
val IrExpression.asmType: Type
get() = typeMapper.mapType(this.type)
get() = typeMapper.mapType(this.type.toKotlinType())
val IrExpression.onStack: StackValue
get() = StackValue.onStack(this.asmType)

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.codegen
@@ -25,6 +14,7 @@ import org.jetbrains.kotlin.codegen.FunctionCodegen
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.util.isAnnotationClass
@@ -155,7 +145,7 @@ private fun createFrameMapWithReceivers(
}
for (parameter in irFunction.valueParameters) {
frameMap.enter(parameter, state.typeMapper.mapType(parameter.type))
frameMap.enter(parameter, state.typeMapper.mapType(parameter.type.toKotlinType()))
}
return frameMap

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.descriptors
@@ -31,6 +20,7 @@ import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.load.java.JavaVisibilities
@@ -74,7 +64,7 @@ class JvmDescriptorsFactory(
IrFieldSymbolImpl(
JvmPropertyDescriptorImpl.createFinalField(
Name.identifier("this$0"), outerClass.defaultType, innerClass.descriptor,
Name.identifier("this$0"), outerClass.defaultType.toKotlinType(), innerClass.descriptor,
Annotations.EMPTY, JavaVisibilities.PACKAGE_VISIBILITY, Opcodes.ACC_SYNTHETIC, SourceElement.NO_SOURCE
)
)

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.descriptors
@@ -29,17 +18,22 @@ import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.IrSetVariable
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.types.toIrType
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.*
class JvmSharedVariablesManager(val builtIns: KotlinBuiltIns) : SharedVariablesManager {
class JvmSharedVariablesManager(
val builtIns: KotlinBuiltIns,
val irBuiltIns: IrBuiltIns
) : SharedVariablesManager {
private val kotlinJvmInternalPackage = KnownPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.jvm.internal"))
private val refNamespaceClass =
KnownClassDescriptor.createClass(Name.identifier("Ref"), kotlinJvmInternalPackage, listOf(builtIns.anyType))
@@ -148,11 +142,12 @@ class JvmSharedVariablesManager(val builtIns: KotlinBuiltIns) : SharedVariablesM
val refConstructorCall = IrCallImpl(
originalDeclaration.startOffset, originalDeclaration.endOffset,
refConstructor, refConstructorTypeArguments
refConstructor.constructedClass.defaultType.toIrType()!!,
refConstructor, refConstructorTypeArguments?.size ?: 0
)
return IrVariableImpl(
originalDeclaration.startOffset, originalDeclaration.endOffset, originalDeclaration.origin,
sharedVariableDescriptor, refConstructorCall
sharedVariableDescriptor, sharedVariableDescriptor.type.toIrType()!!, refConstructorCall
)
}
@@ -172,11 +167,12 @@ class JvmSharedVariablesManager(val builtIns: KotlinBuiltIns) : SharedVariablesM
initializer.startOffset, initializer.endOffset,
elementPropertyDescriptor,
IrGetValueImpl(initializer.startOffset, initializer.endOffset, sharedVariableDeclaration.symbol),
initializer
initializer,
originalDeclaration.type
)
return IrCompositeImpl(
originalDeclaration.startOffset, originalDeclaration.endOffset, builtIns.unitType, null,
originalDeclaration.startOffset, originalDeclaration.endOffset, irBuiltIns.unitType, null,
listOf(sharedVariableDeclaration, sharedVariableInitialization)
)
}
@@ -196,6 +192,7 @@ class JvmSharedVariablesManager(val builtIns: KotlinBuiltIns) : SharedVariablesM
originalGet.endOffset,
sharedVariableSymbol
),
originalGet.type,
originalGet.origin
)
@@ -209,6 +206,7 @@ class JvmSharedVariablesManager(val builtIns: KotlinBuiltIns) : SharedVariablesM
sharedVariableSymbol
),
originalSet.value,
originalSet.type,
originalSet.origin
)

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.intrinsics
@@ -24,6 +13,7 @@ import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
@@ -42,8 +32,9 @@ class Equals(val operator: IElementType) : IntrinsicMethod() {
val receiverAndArgs = expression.receiverAndArgs().apply {
assert(size == 2) { "Equals expects 2 arguments, but ${joinToString()}" }
}
var leftType = context.state.typeMapper.mapType(receiverAndArgs.first().type)
var rightType = context.state.typeMapper.mapType(receiverAndArgs.last().type)
var leftType = context.state.typeMapper.mapType(receiverAndArgs.first().type.toKotlinType())
var rightType = context.state.typeMapper.mapType(receiverAndArgs.last().type.toKotlinType())
if (isPrimitive(leftType) != isPrimitive(rightType)) {
leftType = boxType(leftType)
@@ -90,10 +81,10 @@ class Ieee754Equals(val operandType: Type) : IntrinsicMethod() {
}
}
val arg0Type = expression.getValueArgument(0)!!.type
val arg0Type = expression.getValueArgument(0)!!.type.toKotlinType()
if (!arg0Type.isPrimitiveNumberOrNullableType()) throw AssertionError("Should be primitive or nullable primitive type: $arg0Type")
val arg1Type = expression.getValueArgument(1)!!.type
val arg1Type = expression.getValueArgument(1)!!.type.toKotlinType()
if (!arg1Type.isPrimitiveNumberOrNullableType()) throw AssertionError("Should be primitive or nullable primitive type: $arg1Type")
val arg0isNullable = arg0Type.isMarkedNullable

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.intrinsics
@@ -21,6 +10,7 @@ import org.jetbrains.kotlin.codegen.Callable
import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.Method
@@ -41,11 +31,11 @@ abstract class IntrinsicMethod {
companion object {
fun calcReceiverType(call: IrMemberAccessExpression, context: JvmBackendContext): Type {
return context.state.typeMapper.mapType(call.dispatchReceiver?.type ?: call.extensionReceiver!!.type)
return context.state.typeMapper.mapType((call.dispatchReceiver?.type ?: call.extensionReceiver!!.type).toKotlinType())
}
fun expressionType(expression: IrExpression, context: JvmBackendContext): Type {
return context.state.typeMapper.mapType(expression.type)
return context.state.typeMapper.mapType(expression.type.toKotlinType())
}
fun JvmMethodSignature.newReturnType(type: Type): JvmMethodSignature {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
@@ -15,6 +15,9 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.toIrType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.resolve.calls.components.isVararg
@@ -25,7 +28,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.util.*
private class IrEmptyVarargExpression(
override val type: KotlinType,
override val type: IrType,
override val startOffset: Int,
override val endOffset: Int
) : IrExpression {
@@ -86,13 +89,13 @@ open class IrIntrinsicFunction(
val args = listOfNotNull(expression.dispatchReceiver, expression.extensionReceiver) +
expression.descriptor.valueParameters.mapIndexed { i, descriptor ->
expression.getValueArgument(i) ?: if (descriptor.isVararg)
IrEmptyVarargExpression(descriptor.type, UNDEFINED_OFFSET, UNDEFINED_OFFSET)
IrEmptyVarargExpression(descriptor.type.toIrType()!!, UNDEFINED_OFFSET, UNDEFINED_OFFSET)
else error("Unknown parameter: $descriptor in $expression")
}
args.forEachIndexed { i, irExpression ->
if (irExpression is IrEmptyVarargExpression) {
val parameterType = codegen.typeMapper.mapType(irExpression.type)
val parameterType = codegen.typeMapper.mapType(irExpression.type.toKotlinType())
StackValue.operation(parameterType) {
it.aconst(0)
it.newarray(AsmUtil.correctElementType(parameterType))
@@ -122,13 +125,11 @@ open class IrIntrinsicFunction(
}
}
fun createWithResult(
expression: IrMemberAccessExpression,
signature: JvmMethodSignature,
context: JvmBackendContext,
argsTypes: List<Type> = expression.argTypes(context),
invokeInstruction: IrIntrinsicFunction.(InstructionAdapter) -> Type
): IrIntrinsicFunction {
fun createWithResult(expression: IrMemberAccessExpression,
signature: JvmMethodSignature,
context: JvmBackendContext,
argsTypes: List<Type> = expression.argTypes(context),
invokeInstruction: IrIntrinsicFunction.(InstructionAdapter) -> Type): IrIntrinsicFunction {
return object : IrIntrinsicFunction(expression, signature, context, argsTypes) {
override fun genInvokeInstructionWithResult(v: InstructionAdapter) = invokeInstruction(v)
@@ -161,5 +162,5 @@ fun IrMemberAccessExpression.receiverAndArgs(): List<IrExpression> {
}
fun List<IrExpression>.asmTypes(context: JvmBackendContext): List<Type> {
return map { context.state.typeMapper.mapType(it.type) }
return map { context.state.typeMapper.mapType(it.type.toKotlinType()) }
}

View File

@@ -1,23 +1,13 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.types.Variance
@@ -33,7 +23,7 @@ class IsArrayOf : IntrinsicMethod() {
}
/*TODO original?*/
val elementType = expression.getTypeArgument(descriptor.original.typeParameters.first().index)!!
val arrayKtType = builtIns.getArrayType(Variance.INVARIANT, elementType)
val arrayKtType = builtIns.getArrayType(Variance.INVARIANT, elementType.toKotlinType())
val arrayType = typeMapper.mapType(arrayKtType)
return IrIntrinsicFunction.create(expression, signature, context) {

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.intrinsics
@@ -21,6 +10,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -31,7 +21,7 @@ class NewArray : IntrinsicMethod() {
return object : IrIntrinsicFunction(expression, signature, context) {
override fun invoke(v: InstructionAdapter, codegen: ExpressionCodegen, data: BlockInfo): StackValue {
super.invoke(v, codegen, data)
codegen.newArrayInstruction(ktType)
codegen.newArrayInstruction(ktType.toKotlinType())
return StackValue.onStack(returnType)
}

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.lower
@@ -23,7 +12,6 @@ import org.jetbrains.kotlin.backend.common.bridges.findInterfaceImplementation
import org.jetbrains.kotlin.backend.common.bridges.generateBridgesForFunctionDescriptor
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
import org.jetbrains.kotlin.backend.common.lower.irIfThen
import org.jetbrains.kotlin.backend.common.lower.irNot
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredStatementOrigin
@@ -53,11 +41,12 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
import org.jetbrains.kotlin.ir.expressions.typeParametersCount
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.types.toIrType
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.*
import org.jetbrains.kotlin.load.java.getOverriddenBuiltinReflectingJvmDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor
@@ -214,6 +203,7 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
)
val irFunction = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.BRIDGE, bridgeDescriptorForIrFunction)
irFunction.returnType = bridgeDescriptorForIrFunction.returnType!!.toIrType()!!
irFunction.createParameterDeclarations()
context.createIrBuilder(irFunction.symbol).irBlockBody(irFunction) {
@@ -226,8 +216,10 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
val implementation = if (isSpecialBridge) delegateTo.copyAsDeclaration() else delegateTo.descriptor
val call = IrCallImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
implementation.returnType!!.toIrType()!!,
implementation,
null, JvmLoweredStatementOrigin.BRIDGE_DELEGATION,
implementation.typeParametersCount,
JvmLoweredStatementOrigin.BRIDGE_DELEGATION,
if (isStubDeclarationWithDelegationToSuper) getSuperClassDescriptor(
descriptor.containingDeclaration as ClassDescriptor
) else null
@@ -257,7 +249,7 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
)
)
}
+IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.symbol, call)
+IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.returnType, irFunction.symbol, call)
}.apply {
irFunction.body = this
}
@@ -292,7 +284,7 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
if (delegateParameterTypes == null || OBJECT_TYPE == delegateParameterTypes[i]) {
irNotEquals(checkValue, irNull())
} else {
irIs(checkValue, overrideDescriptor.valueParameters[i].type)
irIs(checkValue, overrideDescriptor.valueParameters[i].type.toIrType()!!)
}
}
@@ -301,21 +293,25 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
context.andand(arg, result)
}
+irIfThen(irNot(condition), irBlock {
+irIfThen(context.irBuiltIns.unitType, irNot(condition), irBlock {
+irReturn(
when (typeSafeBarrierDescription) {
MAP_GET_OR_DEFAULT -> irGet(IrVariableSymbolImpl(bridgeDescriptor.valueParameters[1]))
BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.NULL -> irNull()
INDEX -> IrConstImpl.int(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.builtIns.intType, typeSafeBarrierDescription.defaultValue as Int
BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.MAP_GET_OR_DEFAULT -> irGet(
bridgeDescriptor.valueParameters[1].type.toIrType()!!,
IrVariableSymbolImpl(
bridgeDescriptor.valueParameters[1]
)
)
FALSE -> irFalse()
BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.NULL -> irNull()
BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.INDEX -> IrConstImpl.int(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.intType, typeSafeBarrierDescription.defaultValue as Int
)
BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.FALSE -> irFalse()
}
)
}
)
}
}

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.lower
@@ -69,6 +58,7 @@ class ConstAndJvmFieldPropertiesLowering : IrElementTransformerVoid(), FileLower
descriptor.correspondingProperty,
expression.dispatchReceiver,
expression.getValueArgument(descriptor.valueParameters.lastIndex)!!,
expression.type,
expression.origin,
expression.superQualifier
)
@@ -80,6 +70,7 @@ class ConstAndJvmFieldPropertiesLowering : IrElementTransformerVoid(), FileLower
expression.endOffset,
descriptor.correspondingProperty,
expression.dispatchReceiver,
expression.type,
expression.origin,
expression.superQualifier
)

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.lower
@@ -33,6 +22,8 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.types.toIrType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -61,14 +52,20 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameter0.typeConstructor to TypeProjectionImpl(arrayElementType)))
val substitutedArrayOfFun = unsubstitutedArrayOfFun.substitute(typeSubstitutor)!!
val typeArguments = mapOf(typeParameter0 to arrayElementType)
val valueParameter0 = substitutedArrayOfFun.valueParameters[0]
val arg0VarargType = valueParameter0.type
val arg0VarargElementType = valueParameter0.varargElementType!!
val arg0 = IrVarargImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, arg0VarargType, arg0VarargElementType, arrayElements)
val arg0 =
IrVarargImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, arg0VarargType.toIrType()!!, arg0VarargElementType.toIrType()!!, arrayElements)
return IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, substitutedArrayOfFun, typeArguments).apply {
return IrCallImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
substitutedArrayOfFun.returnType!!.toIrType()!!,
substitutedArrayOfFun,
substitutedArrayOfFun.typeParametersCount
).apply {
putValueArgument(0, arg0)
}
}
@@ -127,6 +124,7 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
enumConstructor.body!! // will be transformed later
).apply {
parent = enumClass
returnType = loweredConstructorDescriptor.returnType.toIrType()!!
createParameterDeclarations()
loweredEnumConstructors[constructorDescriptor] = this
constructorDescriptor.valueParameters.forEach {
@@ -193,7 +191,7 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
return IrFieldImpl(
enumEntry.startOffset, enumEntry.endOffset, JvmLoweredDeclarationOrigin.FIELD_FOR_ENUM_ENTRY,
fieldSymbol
fieldSymbol, enumEntry.initializerExpression!!.type
).also {
it.initializer = IrExpressionBodyImpl(enumEntry.initializerExpression!!)
enumEntryFields.add(it)
@@ -227,15 +225,16 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
return IrFieldImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.FIELD_FOR_ENUM_VALUES,
createSyntheticValuesFieldDescriptor(valuesArrayType),
valuesArrayType.toIrType()!!,
IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irValuesInitializer)
).also { valuesField = it }
}
private fun createSyntheticValuesFieldInitializerExpression(): IrExpression =
createArrayOfExpression(
irClass.defaultType,
irClass.defaultType.toKotlinType(),
enumEntryFields.map { irField ->
IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irField.symbol)
IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irField.symbol, irField.symbol.owner.type)
})
private fun createSyntheticValuesFieldDescriptor(valuesArrayType: SimpleType): PropertyDescriptorImpl {
@@ -263,6 +262,7 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
val result = IrDelegatingConstructorCallImpl(
startOffset,
endOffset,
context.irBuiltIns.unitType,
enumConstructorCall.symbol,
enumConstructorCall.descriptor,
enumConstructorCall.typeArgumentsCount
@@ -298,6 +298,7 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
val result = IrDelegatingConstructorCallImpl(
startOffset,
endOffset,
context.irBuiltIns.unitType,
loweredDelegatedConstructor.symbol,
loweredDelegatedConstructor.descriptor,
loweredDelegatedConstructor.typeParameters.size
@@ -330,8 +331,8 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
val result = createConstructorCall(startOffset, endOffset, loweredConstructor)
result.putValueArgument(0, IrConstImpl.string(startOffset, endOffset, context.builtIns.stringType, name))
result.putValueArgument(1, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, ordinal))
result.putValueArgument(0, IrConstImpl.string(startOffset, endOffset, context.irBuiltIns.stringType, name))
result.putValueArgument(1, IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, ordinal))
descriptor.valueParameters.forEach { valueParameter ->
val i = valueParameter.index
@@ -357,6 +358,7 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
IrDelegatingConstructorCallImpl(
startOffset,
endOffset,
context.irBuiltIns.unitType,
loweredConstructor.symbol,
loweredConstructor.descriptor,
loweredConstructor.typeParameters.size
@@ -368,6 +370,7 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
IrCallImpl(
startOffset,
endOffset,
loweredConstructor.symbol.owner.parentAsClass.defaultType,
loweredConstructor.symbol
)
}
@@ -468,27 +471,49 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
val substitutedValueOf = unsubstitutedValueOf.substitute(typeSubstitutor)!!
val irValueOfCall =
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, substitutedValueOf, mapOf(typeParameterT to enumClassType))
IrCallImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
substitutedValueOf.returnType!!.toIrType()!!,
substitutedValueOf,
substitutedValueOf.typeParametersCount
)
irValueOfCall.putValueArgument(
0, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valueOfFunction.valueParameters[0].symbol)
)
return IrBlockBodyImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
listOf(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valueOfFunction.symbol, irValueOfCall))
listOf(
IrReturnImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
valueOfFunction.returnType,
valueOfFunction.symbol,
irValueOfCall
)
)
)
}
private fun createEnumValuesBody(valuesField: IrField): IrBody {
val cloneFun = valuesField.type.memberScope.findSingleFunction(Name.identifier("clone"))
val cloneFun = valuesField.type.toKotlinType().memberScope.findSingleFunction(Name.identifier("clone"))
val irCloneValues = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, cloneFun).apply {
dispatchReceiver = IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valuesField.symbol)
val irCloneValues = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, cloneFun.returnType!!.toIrType()!!, cloneFun, 0).apply {
dispatchReceiver = IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valuesField.symbol, valuesField.symbol.owner.type)
}
return IrBlockBodyImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
listOf(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valuesFunction.symbol, irCloneValues))
listOf(
IrReturnImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
valuesFunction.symbol.owner.returnType,
valuesFunction.symbol,
irCloneValues
)
)
)
}
}

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.lower
@@ -34,6 +23,8 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
import org.jetbrains.kotlin.ir.expressions.typeParametersCount
import org.jetbrains.kotlin.ir.types.toIrType
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -80,10 +71,25 @@ class InterfaceDelegationLowering(val state: GenerationState) : IrElementTransfo
val defaultImpls = InterfaceLowering.createDefaultImplsClassDescriptor(interfaceDescriptor)
val defaultImplFun =
InterfaceLowering.createDefaultImplFunDescriptor(defaultImpls, interfaceFun.original, interfaceDescriptor, state.typeMapper)
irFunction.returnType = defaultImplFun.returnType!!.toIrType()!!
val irCallImpl =
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, defaultImplFun, null, JvmLoweredStatementOrigin.DEFAULT_IMPLS_DELEGATION)
irBody.statements.add(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.symbol, irCallImpl))
IrCallImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
defaultImplFun.returnType!!.toIrType()!!,
defaultImplFun,
defaultImplFun.typeParametersCount,
JvmLoweredStatementOrigin.DEFAULT_IMPLS_DELEGATION
)
irBody.statements.add(
IrReturnImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
irFunction.returnType,
irFunction.symbol,
irCallImpl
)
)
var offset = 0
irFunction.dispatchReceiverParameter?.let {

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.lower

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.lower
@@ -20,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.codegen.JvmCodegenUtil.isCompanionObjectInInterfaceNotIntrinsic
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
@@ -32,9 +22,10 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.codegen.JvmCodegenUtil.isCompanionObjectInInterfaceNotIntrinsic
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.isObject
class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass {
@@ -72,38 +63,42 @@ class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformer
false
) as PropertyDescriptor
privateInstance.name
val field = createInstanceFieldWithInitializer(IrFieldSymbolImpl(privateInstance), constructor, irClass)
val field = createInstanceFieldWithInitializer(IrFieldSymbolImpl(privateInstance), constructor, irClass, irClass.defaultType)
createFieldWithCustomInitializer(
publicInstance,
IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, field.symbol),
publicInstanceOwner
IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, field.symbol, irClass.defaultType),
publicInstanceOwner,
irClass.defaultType
)
} else {
createInstanceFieldWithInitializer(publicInstance, constructor, publicInstanceOwner)
createInstanceFieldWithInitializer(publicInstance, constructor, publicInstanceOwner, irClass.defaultType)
}
}
private fun createInstanceFieldWithInitializer(
fieldSymbol: IrFieldSymbol,
constructor: ClassConstructorDescriptor,
instanceOwner: IrDeclarationContainer
instanceOwner: IrDeclarationContainer,
objectType: IrType
): IrField =
createFieldWithCustomInitializer(
fieldSymbol,
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, constructor),
instanceOwner
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, objectType, constructor, 0),
instanceOwner,
objectType
)
private fun createFieldWithCustomInitializer(
fieldSymbol: IrFieldSymbol,
instanceInitializer: IrExpression,
instanceOwner: IrDeclarationContainer
instanceOwner: IrDeclarationContainer,
objectType: IrType
): IrField =
IrFieldImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE,
fieldSymbol,
IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, instanceInitializer)
fieldSymbol, objectType
).also {
it.initializer = IrExpressionBodyImpl(instanceInitializer)
pendingTransformations.add { instanceOwner.declarations.add(it) }
}
}

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.lower
@@ -33,11 +22,11 @@ class SingletonReferencesLowering(val context: JvmBackendContext) : BodyLowering
override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression {
val entrySymbol = context.descriptorsFactory.getSymbolForEnumEntry(expression.symbol)
return IrGetFieldImpl(expression.startOffset, expression.endOffset, entrySymbol)
return IrGetFieldImpl(expression.startOffset, expression.endOffset, entrySymbol, expression.type)
}
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
val instanceField = context.descriptorsFactory.getSymbolForObjectInstance(expression.symbol)
return IrGetFieldImpl(expression.startOffset, expression.endOffset, instanceField)
return IrGetFieldImpl(expression.startOffset, expression.endOffset, instanceField, expression.type)
}
}

View File

@@ -1,17 +1,6 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.lower
@@ -44,7 +33,9 @@ import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
import org.jetbrains.kotlin.ir.types.toIrType
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.usesDefaultArguments
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.name.Name
@@ -182,13 +173,16 @@ class SyntheticAccessorLowering(val context: JvmBackendContext) : FileLoweringPa
IrDelegatingConstructorCallImpl(
expression.startOffset,
expression.endOffset,
accessorForIr as ClassConstructorDescriptor
context.irBuiltIns.unitType,
accessorForIr as ClassConstructorDescriptor,
0
)
else IrCallImpl(
expression.startOffset,
expression.endOffset,
expression.type,
accessorForIr,
emptyMap(),
0,
expression.origin/*TODO super*/
)
//copyAllArgsToValueParams(call, expression)
@@ -202,7 +196,7 @@ class SyntheticAccessorLowering(val context: JvmBackendContext) : FileLoweringPa
IrConstImpl.constNull(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
context.ir.symbols.defaultConstructorMarker.descriptor.defaultType
context.ir.symbols.defaultConstructorMarker.owner.defaultType
)
)
}
@@ -246,23 +240,29 @@ class SyntheticAccessorLowering(val context: JvmBackendContext) : FileLoweringPa
UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
accessorForIr, body
)
syntheticFunction.returnType = accessor.calleeDescriptor.returnType!!.toIrType()!!
syntheticFunction.createParameterDeclarations()
val calleeDescriptor = accessor.calleeDescriptor as FunctionDescriptor
val delegationCall =
if (!isConstructor)
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, calleeDescriptor)
else IrDelegatingConstructorCallImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
createFunctionSymbol(accessor.calleeDescriptor) as IrConstructorSymbol,
accessor.calleeDescriptor as ClassConstructorDescriptor
)
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, calleeDescriptor.returnType!!.toIrType()!!, calleeDescriptor, 0)
else {
val delegationConstructor = createFunctionSymbol(accessor.calleeDescriptor)
IrDelegatingConstructorCallImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
context.irBuiltIns.unitType,
delegationConstructor as IrConstructorSymbol,
accessor.calleeDescriptor as ClassConstructorDescriptor
)
}
copyAllArgsToValueParams(delegationCall, syntheticFunction)
body.statements.add(
if (isConstructor) delegationCall else IrReturnImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
syntheticFunction.returnType,
syntheticFunction.symbol,
delegationCall
)

View File

@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.types.toIrType
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.name.FqName
@@ -85,7 +86,7 @@ class ToArrayLowering(private val context: JvmBackendContext) : ClassLoweringPas
irFunction.body = context.createIrBuilder(irFunction.symbol).irBlockBody {
+irReturn(
irCall(IrSimpleFunctionSymbolImpl(toArrayUtilDescriptor)).apply {
irCall(IrSimpleFunctionSymbolImpl(toArrayUtilDescriptor), toArrayUtilDescriptor.returnType!!.toIrType()!!).apply {
putValueArgument(
0,
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.dispatchReceiverParameter!!.symbol)
@@ -143,7 +144,7 @@ class ToArrayLowering(private val context: JvmBackendContext) : ClassLoweringPas
irFunction.body = context.createIrBuilder(irFunction.symbol).irBlockBody {
+irReturn(
irCall(IrSimpleFunctionSymbolImpl(toArrayUtilDescriptor)).apply {
irCall(IrSimpleFunctionSymbolImpl(toArrayUtilDescriptor), toArrayUtilDescriptor.returnType!!.toIrType()!!).apply {
putValueArgument(
0,
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.dispatchReceiverParameter!!.symbol)

View File

@@ -1,27 +1,16 @@
/*
* 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.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir2cfg.generators
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.isNothing
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.ir2cfg.graph.ControlFlowGraph
@@ -66,7 +55,7 @@ class FunctionGenerator(val function: IrFunction) {
return result
}
private fun IrElement?.isNothing() = this is IrExpression && KotlinBuiltIns.isNothing(type)
private fun IrElement?.isNothing() = this is IrExpression && type.isNothing()
override fun visitBlockBody(body: IrBlockBody, data: Boolean): IrStatement? {
return body.process()
@@ -81,8 +70,7 @@ class FunctionGenerator(val function: IrFunction) {
return if (data) {
builder.add(declaration)
declaration
}
else null
} else null
}
override fun visitReturn(expression: IrReturn, data: Boolean): IrStatement? {
@@ -121,8 +109,7 @@ class FunctionGenerator(val function: IrFunction) {
builder.move(branch.condition)
if (!result.process().isNothing()) {
builder.jump(whenExit)
}
else {
} else {
builder.move(branch.condition)
}
}

Some files were not shown because too many files have changed in this diff Show More