| // Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| package com.android.tools.r8.ir.desugar.backports; |
| |
| import com.android.tools.r8.cf.code.CfArrayStore; |
| import com.android.tools.r8.cf.code.CfConstNumber; |
| import com.android.tools.r8.cf.code.CfInstruction; |
| import com.android.tools.r8.cf.code.CfInvoke; |
| import com.android.tools.r8.cf.code.CfLoad; |
| import com.android.tools.r8.cf.code.CfNew; |
| import com.android.tools.r8.cf.code.CfNewArray; |
| import com.android.tools.r8.cf.code.CfReturn; |
| import com.android.tools.r8.cf.code.CfStackInstruction; |
| import com.android.tools.r8.dex.Constants; |
| import com.android.tools.r8.graph.CfCode; |
| import com.android.tools.r8.graph.DexMethod; |
| import com.android.tools.r8.graph.DexType; |
| import com.android.tools.r8.ir.code.MemberType; |
| import com.android.tools.r8.ir.code.ValueType; |
| import com.android.tools.r8.utils.InternalOptions; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableList.Builder; |
| import org.objectweb.asm.Opcodes; |
| |
| public final class CollectionMethodGenerators { |
| |
| private CollectionMethodGenerators() {} |
| |
| public static CfCode generateListOf(InternalOptions options, DexMethod method, int formalCount) { |
| return generateFixedMethods(options, method, formalCount, options.itemFactory.listType); |
| } |
| |
| public static CfCode generateSetOf(InternalOptions options, DexMethod method, int formalCount) { |
| return generateFixedMethods(options, method, formalCount, options.itemFactory.setType); |
| } |
| |
| private static CfCode generateFixedMethods( |
| InternalOptions options, DexMethod method, int formalCount, DexType returnType) { |
| Builder<CfInstruction> builder = ImmutableList.builder(); |
| builder.add( |
| new CfConstNumber(formalCount, ValueType.INT), |
| new CfNewArray(options.itemFactory.objectArrayType)); |
| |
| for (int i = 0; i < formalCount; i++) { |
| builder.add( |
| new CfStackInstruction(CfStackInstruction.Opcode.Dup), |
| new CfConstNumber(i, ValueType.INT), |
| new CfLoad(ValueType.OBJECT, i), |
| new CfArrayStore(MemberType.OBJECT)); |
| } |
| |
| builder.add( |
| new CfInvoke( |
| Opcodes.INVOKESTATIC, |
| options.itemFactory.createMethod( |
| returnType, |
| options.itemFactory.createProto(returnType, options.itemFactory.objectArrayType), |
| options.itemFactory.createString("of")), |
| false), |
| new CfReturn(ValueType.OBJECT)); |
| |
| return new CfCode( |
| method.holder, |
| 4, |
| formalCount, |
| builder.build(), |
| ImmutableList.of(), |
| ImmutableList.of()); |
| } |
| |
| public static CfCode generateMapOf( |
| InternalOptions options, DexMethod method, int formalCount) { |
| DexType mapEntryArray = |
| options.itemFactory.createArrayType(1, options.itemFactory.mapEntryType); |
| DexType simpleEntry = options.itemFactory.abstractMapSimpleEntryType; |
| DexMethod simpleEntryConstructor = options.itemFactory.createMethod( |
| simpleEntry, |
| options.itemFactory.createProto( |
| options.itemFactory.voidType, |
| options.itemFactory.objectType, |
| options.itemFactory.objectType), |
| Constants.INSTANCE_INITIALIZER_NAME); |
| |
| Builder<CfInstruction> builder = ImmutableList.builder(); |
| builder.add( |
| new CfConstNumber(formalCount, ValueType.INT), |
| new CfNewArray(mapEntryArray)); |
| |
| for (int i = 0; i < formalCount; i++) { |
| builder.add( |
| new CfStackInstruction(CfStackInstruction.Opcode.Dup), |
| new CfConstNumber(i, ValueType.INT), |
| new CfNew(simpleEntry), |
| new CfStackInstruction(CfStackInstruction.Opcode.Dup), |
| new CfLoad(ValueType.OBJECT, i * 2), |
| new CfLoad(ValueType.OBJECT, i * 2 + 1), |
| new CfInvoke(Opcodes.INVOKESPECIAL, simpleEntryConstructor, false), |
| new CfArrayStore(MemberType.OBJECT)); |
| } |
| |
| builder.add( |
| new CfInvoke( |
| Opcodes.INVOKESTATIC, |
| options.itemFactory.createMethod( |
| options.itemFactory.mapType, |
| options.itemFactory.createProto( |
| options.itemFactory.mapType, |
| mapEntryArray), |
| options.itemFactory.createString("ofEntries")), |
| false), |
| new CfReturn(ValueType.OBJECT)); |
| |
| return new CfCode( |
| method.holder, |
| 7, |
| formalCount * 2, |
| builder.build(), |
| ImmutableList.of(), |
| ImmutableList.of()); |
| } |
| } |