/*
* Copyright ( C ) 2007 The Android Open Source Project
*
* 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 com.android.dx.rop.code;
import com.android.dx.rop.type.StdTypeList;
import com.android.dx.rop.type.Type;
import com.android.dx.rop.type.TypeList;
import com.android.dx.util.ToHuman;
/**
* A register - based instruction . An instruction is the combination of
* an opcode ( which specifies operation and source / result types ) , a
* list of actual sources and result registers / values , and additional
* information .
*/
public abstract class Insn implements ToHuman {
/** {@code non-null;} opcode */
private final Rop opcode;
/** {@code non-null;} source position */
private final SourcePosition position;
/** {@code null-ok;} spec for the result of this instruction, if any */
private final RegisterSpec result;
/** {@code non-null;} specs for all the sources of this instruction */
private final RegisterSpecList sources;
/**
* Constructs an instance .
*
* @ param opcode { @ code non - null ; } the opcode
* @ param position { @ code non - null ; } source position
* @ param result { @ code null - ok ; } spec for the result , if any
* @ param sources { @ code non - null ; } specs for all the sources
*/
public Insn(Rop opcode, SourcePosition position, RegisterSpec result,
RegisterSpecList sources) {
if (opcode == null ) {
throw new NullPointerException("opcode == null" );
}
if (position == null ) {
throw new NullPointerException("position == null" );
}
if (sources == null ) {
throw new NullPointerException("sources == null" );
}
this .opcode = opcode;
this .position = position;
this .result = result;
this .sources = sources;
}
/**
* { @ inheritDoc }
*
* Instances of this class compare by identity . That is ,
* { @ code x . equals ( y ) } is only true if { @ code x = = y } .
*/
@Override
public final boolean equals(Object other) {
return (this == other);
}
/**
* { @ inheritDoc }
*
* This implementation returns the identity hashcode of this
* instance . This is proper , since instances of this class compare
* by identity ( see { @ link # equals } ) .
*/
@Override
public final int hashCode() {
return System.identityHashCode(this );
}
/** {@inheritDoc} */
@Override
public String toString() {
return toStringWithInline(getInlineString());
}
/**
* Gets a human - oriented ( and slightly lossy ) string for this instance .
*
* @ return { @ code non - null ; } the human string form
*/
@Override
public String toHuman() {
return toHumanWithInline(getInlineString());
}
/**
* Gets an " inline " string portion for toHuman ( ) , if available . This
* is the portion that appears after the Rop opcode
*
* @ return { @ code null - ok ; } if non - null , the inline text for toHuman ( )
*/
public String getInlineString() {
return null ;
}
/**
* Gets the opcode .
*
* @ return { @ code non - null ; } the opcode
*/
public final Rop getOpcode() {
return opcode;
}
/**
* Gets the source position .
*
* @ return { @ code non - null ; } the source position
*/
public final SourcePosition getPosition() {
return position;
}
/**
* Gets the result spec , if any . A return value of { @ code null }
* means this instruction returns nothing .
*
* @ return { @ code null - ok ; } the result spec , if any
*/
public final RegisterSpec getResult() {
return result;
}
/**
* Gets the spec of a local variable assignment that occurs at this
* instruction , or null if no local variable assignment occurs . This
* may be the result register , or for { @ code mark - local } insns
* it may be the source .
*
* @ return { @ code null - ok ; } a named register spec or null
*/
public final RegisterSpec getLocalAssignment() {
RegisterSpec assignment;
if (opcode.getOpcode() == RegOps.MARK_LOCAL) {
assignment = sources.get(0 );
} else {
assignment = result;
}
if (assignment == null ) {
return null ;
}
LocalItem localItem = assignment.getLocalItem();
if (localItem == null ) {
return null ;
}
return assignment;
}
/**
* Gets the source specs .
*
* @ return { @ code non - null ; } the source specs
*/
public final RegisterSpecList getSources() {
return sources;
}
/**
* Gets whether this instruction can possibly throw an exception . This
* is just a convenient wrapper for { @ code getOpcode ( ) . canThrow ( ) } .
*
* @ return { @ code true } iff this instruction can possibly throw
*/
public final boolean canThrow() {
return opcode.canThrow();
}
/**
* Gets the list of possibly - caught exceptions . This returns { @ link
* StdTypeList # EMPTY } if this instruction has no handlers ,
* which can be < i > either < / i > if this instruction can ' t possibly
* throw or if it merely doesn ' t handle any of its possible
* exceptions . To determine whether this instruction can throw ,
* use { @ link # canThrow } .
*
* @ return { @ code non - null ; } the catches list
*/
public abstract TypeList getCatches();
/**
* Calls the appropriate method on the given visitor , depending on the
* class of this instance . Subclasses must override this .
*
* @ param visitor { @ code non - null ; } the visitor to call on
*/
public abstract void accept(Visitor visitor);
/**
* Returns an instance that is just like this one , except that it
* has a catch list with the given item appended to the end . This
* method throws an exception if this instance can ' t possibly
* throw . To determine whether this instruction can throw , use
* { @ link # canThrow } .
*
* @ param type { @ code non - null ; } type to append to the catch list
* @ return { @ code non - null ; } an appropriately - constructed instance
*/
public abstract Insn withAddedCatch(Type type);
/**
* Returns an instance that is just like this one , except that all
* register references have been offset by the given delta .
*
* @ param delta the amount to offset register references by
* @ return { @ code non - null ; } an appropriately - constructed instance
*/
public abstract Insn withRegisterOffset(int delta);
/**
* Returns an instance that is just like this one , except that , if
* possible , the insn is converted into a version in which a source
* ( if it is a constant ) is represented directly rather than as a
* register reference . { @ code this } is returned in cases where the
* translation is not possible .
*
* @ return { @ code non - null ; } an appropriately - constructed instance
*/
public Insn withSourceLiteral() {
return this ;
}
/**
* Returns an exact copy of this Insn
*
* @ return { @ code non - null ; } an appropriately - constructed instance
*/
public Insn copy() {
return withRegisterOffset(0 );
}
/**
* Compares , handling nulls safely
*
* @ param a first object
* @ param b second object
* @ return true if they ' re equal or both null .
*/
private static boolean equalsHandleNulls (Object a, Object b) {
return (a == b) || ((a != null ) && a.equals(b));
}
/**
* Compares Insn contents , since { @ code Insn . equals ( ) } is defined
* to be an identity compare . Insn ' s are { @ code contentEquals ( ) }
* if they have the same opcode , registers , source position , and other
* metadata .
*
* @ return true in the case described above
*/
public boolean contentEquals(Insn b) {
return opcode == b.getOpcode()
&& position.equals(b.getPosition())
&& (getClass() == b.getClass())
&& equalsHandleNulls(result, b.getResult())
&& equalsHandleNulls(sources, b.getSources())
&& StdTypeList.equalContents(getCatches(), b.getCatches());
}
/**
* Returns an instance that is just like this one , except
* with new result and source registers .
*
* @ param result { @ code null - ok ; } new result register
* @ param sources { @ code non - null ; } new sources registers
* @ return { @ code non - null ; } an appropriately - constructed instance
*/
public abstract Insn withNewRegisters(RegisterSpec result,
RegisterSpecList sources);
/**
* Returns the string form of this instance , with the given bit added in
* the standard location for an inline argument .
*
* @ param extra { @ code null - ok ; } the inline argument string
* @ return { @ code non - null ; } the string form
*/
protected final String toStringWithInline(String extra) {
StringBuilder sb = new StringBuilder(80 );
sb.append("Insn{" );
sb.append(position);
sb.append(' ' );
sb.append(opcode);
if (extra != null ) {
sb.append(' ' );
sb.append(extra);
}
sb.append(" :: " );
if (result != null ) {
sb.append(result);
sb.append(" <- " );
}
sb.append(sources);
sb.append('}' );
return sb.toString();
}
/**
* Returns the human string form of this instance , with the given
* bit added in the standard location for an inline argument .
*
* @ param extra { @ code null - ok ; } the inline argument string
* @ return { @ code non - null ; } the human string form
*/
protected final String toHumanWithInline(String extra) {
StringBuilder sb = new StringBuilder(80 );
sb.append(position);
sb.append(": " );
sb.append(opcode.getNickname());
if (extra != null ) {
sb.append("(" );
sb.append(extra);
sb.append(")" );
}
if (result == null ) {
sb.append(" ." );
} else {
sb.append(" " );
sb.append(result.toHuman());
}
sb.append(" <-" );
int sz = sources.size();
if (sz == 0 ) {
sb.append(" ." );
} else {
for (int i = 0 ; i < sz; i++) {
sb.append(" " );
sb.append(sources.get(i).toHuman());
}
}
return sb.toString();
}
/**
* Visitor interface for this ( outer ) class .
*/
public static interface Visitor {
/**
* Visits a { @ link PlainInsn } .
*
* @ param insn { @ code non - null ; } the instruction to visit
*/
public void visitPlainInsn(PlainInsn insn);
/**
* Visits a { @ link PlainCstInsn } .
*
* @ param insn { @ code non - null ; } the instruction to visit
*/
public void visitPlainCstInsn(PlainCstInsn insn);
/**
* Visits a { @ link SwitchInsn } .
*
* @ param insn { @ code non - null ; } the instruction to visit
*/
public void visitSwitchInsn(SwitchInsn insn);
/**
* Visits a { @ link ThrowingCstInsn } .
*
* @ param insn { @ code non - null ; } the instruction to visit
*/
public void visitThrowingCstInsn(ThrowingCstInsn insn);
/**
* Visits a { @ link ThrowingInsn } .
*
* @ param insn { @ code non - null ; } the instruction to visit
*/
public void visitThrowingInsn(ThrowingInsn insn);
/**
* Visits a { @ link FillArrayDataInsn } .
*
* @ param insn { @ code non - null ; } the instruction to visit
*/
public void visitFillArrayDataInsn(FillArrayDataInsn insn);
/**
* Visits a { @ link InvokePolymorphicInsn } .
*
* @ param insn { @ code non - null ; } the instruction to visit
*/
public void visitInvokePolymorphicInsn(InvokePolymorphicInsn insn);
}
/**
* Base implementation of { @ link Visitor } , which has empty method
* bodies for all methods .
*/
public static class BaseVisitor implements Visitor {
/** {@inheritDoc} */
@Override
public void visitPlainInsn(PlainInsn insn) {
// This space intentionally left blank.
}
/** {@inheritDoc} */
@Override
public void visitPlainCstInsn(PlainCstInsn insn) {
// This space intentionally left blank.
}
/** {@inheritDoc} */
@Override
public void visitSwitchInsn(SwitchInsn insn) {
// This space intentionally left blank.
}
/** {@inheritDoc} */
@Override
public void visitThrowingCstInsn(ThrowingCstInsn insn) {
// This space intentionally left blank.
}
/** {@inheritDoc} */
@Override
public void visitThrowingInsn(ThrowingInsn insn) {
// This space intentionally left blank.
}
/** {@inheritDoc} */
@Override
public void visitFillArrayDataInsn(FillArrayDataInsn insn) {
// This space intentionally left blank.
}
/** {@inheritDoc} */
@Override
public void visitInvokePolymorphicInsn(InvokePolymorphicInsn insn) {
// This space intentionally left blank.
}
}
}
Messung V0.5 in Prozent C=94 H=95 G=94
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet am 2026-06-27)
¤
*© Formatika GbR, Deutschland