blob: 02ba8d43139e47d545749879d0e239ab419cd8c1 [file] [log] [blame]
// Copyright (c) 2021, 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.graph.bytecodemetadata;
import static com.android.tools.r8.utils.MapUtils.ignoreKey;
import com.android.tools.r8.ir.code.Instruction;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.function.Consumer;
/**
* Mapping from IR instructions to the metadata that should be attached to the resulting CF or DEX
* bytecode instruction that results from the given IR instruction.
*/
public class BytecodeMetadataProvider {
private static final BytecodeMetadataProvider EMPTY =
new BytecodeMetadataProvider(Collections.emptyMap());
private final Map<Instruction, BytecodeInstructionMetadata> backing;
BytecodeMetadataProvider(Map<Instruction, BytecodeInstructionMetadata> backing) {
this.backing = backing;
}
public static Builder builder() {
return new Builder();
}
public static BytecodeMetadataProvider empty() {
return EMPTY;
}
/**
* Returns the metadata for a given IR instruction that should be attached to the CF or DEX
* instruction when finalizing the IR to CF or DEX.
*/
public BytecodeInstructionMetadata getMetadata(Instruction instruction) {
return backing.get(instruction);
}
public static class Builder {
private final Map<Instruction, BytecodeInstructionMetadata.Builder> builders =
new IdentityHashMap<>();
/**
* Used to mutate the metadata that should be attached to the CF or DEX instruction that results
* from the given IR instruction.
*/
public Builder addMetadata(
Instruction instruction, Consumer<BytecodeInstructionMetadata.Builder> fn) {
assert !builders.containsKey(instruction);
BytecodeInstructionMetadata.Builder builder =
builders.computeIfAbsent(instruction, ignoreKey(BytecodeInstructionMetadata::builder));
fn.accept(builder);
return this;
}
public BytecodeMetadataProvider build() {
if (builders.isEmpty()) {
return empty();
}
Map<Instruction, BytecodeInstructionMetadata> backing =
new IdentityHashMap<>(builders.size());
builders.forEach((instruction, builder) -> backing.put(instruction, builder.build()));
return new BytecodeMetadataProvider(backing);
}
}
}