blob: c2e2244d2cba17d28aee3860aa41d06fd3505e8f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2008 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.codegen;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
public class VerificationTypeInfo {
/**
* The tag value representing top variable info
*
* @since 3.2
*/
public static final int ITEM_TOP = 0;
/**
* The tag value representing integer variable info
*
* @since 3.2
*/
public static final int ITEM_INTEGER = 1;
/**
* The tag value representing float variable info
*
* @since 3.2
*/
public static final int ITEM_FLOAT = 2;
/**
* The tag value representing double variable info
*
* @since 3.2
*/
public static final int ITEM_DOUBLE = 3;
/**
* The tag value representing long variable info
*
* @since 3.2
*/
public static final int ITEM_LONG = 4;
/**
* The tag value representing null variable info
*
* @since 3.2
*/
public static final int ITEM_NULL = 5;
/**
* The tag value representing uninitialized this variable info
*
* @since 3.2
*/
public static final int ITEM_UNINITIALIZED_THIS = 6;
/**
* The tag value representing object variable info
*
* @since 3.2
*/
public static final int ITEM_OBJECT = 7;
/**
* The tag value representing uninitialized variable info
*
* @since 3.2
*/
public static final int ITEM_UNINITIALIZED = 8;
public int tag;
private int id;
private TypeBinding binding;
public int offset; // where the new opcode is used
private List<TypeBinding> bindings;
public VerificationTypeInfo(int tag, TypeBinding binding) {
this(binding);
this.tag = tag;
}
public VerificationTypeInfo(TypeBinding binding) {
if (binding == null) return;
this.id = binding.id;
this.binding = binding;
switch (binding.id) {
case TypeIds.T_boolean:
case TypeIds.T_byte:
case TypeIds.T_char:
case TypeIds.T_int:
case TypeIds.T_short:
this.tag = VerificationTypeInfo.ITEM_INTEGER;
break;
case TypeIds.T_float:
this.tag = VerificationTypeInfo.ITEM_FLOAT;
break;
case TypeIds.T_long:
this.tag = VerificationTypeInfo.ITEM_LONG;
break;
case TypeIds.T_double:
this.tag = VerificationTypeInfo.ITEM_DOUBLE;
break;
case TypeIds.T_null:
this.tag = VerificationTypeInfo.ITEM_NULL;
break;
default:
this.tag = VerificationTypeInfo.ITEM_OBJECT;
}
}
public void setBinding(TypeBinding binding) {
final int typeBindingId = binding.id;
this.id = typeBindingId;
switch (typeBindingId) {
case TypeIds.T_boolean:
case TypeIds.T_byte:
case TypeIds.T_char:
case TypeIds.T_int:
case TypeIds.T_short:
this.tag = VerificationTypeInfo.ITEM_INTEGER;
break;
case TypeIds.T_float:
this.tag = VerificationTypeInfo.ITEM_FLOAT;
break;
case TypeIds.T_long:
this.tag = VerificationTypeInfo.ITEM_LONG;
break;
case TypeIds.T_double:
this.tag = VerificationTypeInfo.ITEM_DOUBLE;
break;
case TypeIds.T_null:
this.tag = VerificationTypeInfo.ITEM_NULL;
break;
default:
this.tag = VerificationTypeInfo.ITEM_OBJECT;
}
}
public int id() {
return this.id;
}
@Override
public String toString() {
StringBuffer buffer = new StringBuffer();
switch (this.tag) {
case VerificationTypeInfo.ITEM_UNINITIALIZED_THIS:
buffer.append("uninitialized_this(").append(readableName()).append(")"); //$NON-NLS-1$//$NON-NLS-2$
break;
case VerificationTypeInfo.ITEM_UNINITIALIZED:
buffer.append("uninitialized(").append(readableName()).append(")"); //$NON-NLS-1$//$NON-NLS-2$
break;
case VerificationTypeInfo.ITEM_OBJECT:
buffer.append(readableName());
break;
case VerificationTypeInfo.ITEM_DOUBLE:
buffer.append('D');
break;
case VerificationTypeInfo.ITEM_FLOAT:
buffer.append('F');
break;
case VerificationTypeInfo.ITEM_INTEGER:
buffer.append('I');
break;
case VerificationTypeInfo.ITEM_LONG:
buffer.append('J');
break;
case VerificationTypeInfo.ITEM_NULL:
buffer.append("null"); //$NON-NLS-1$
break;
case VerificationTypeInfo.ITEM_TOP:
buffer.append("top"); //$NON-NLS-1$
break;
}
return String.valueOf(buffer);
}
public VerificationTypeInfo duplicate() {
VerificationTypeInfo verificationTypeInfo = new VerificationTypeInfo(this.tag, this.binding);
verificationTypeInfo.offset = this.offset;
return verificationTypeInfo;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof VerificationTypeInfo) {
VerificationTypeInfo info1 = (VerificationTypeInfo) obj;
return info1.tag == this.tag
&& info1.offset == this.offset
&& CharOperation.equals(info1.constantPoolName(), constantPoolName());
}
return false;
}
@Override
public int hashCode() {
return this.tag + this.offset + CharOperation.hashCode(constantPoolName());
}
public char[] constantPoolName() {
return this.binding.constantPoolName();
}
public char[] readableName() {
return this.constantPoolName();
}
public void replaceWithElementType() {
ArrayBinding arrayBinding = (ArrayBinding) this.binding;
this.binding = arrayBinding.elementsType();
this.id = this.binding.id;
}
public VerificationTypeInfo merge(VerificationTypeInfo verificationTypeInfo, Scope scope) {
if (this.binding.isBaseType() && verificationTypeInfo.binding.isBaseType()) {
return this;
}
if (!this.binding.equals(verificationTypeInfo.binding)) {
if (this.bindings == null) {
this.bindings = new ArrayList<TypeBinding>();
this.bindings.add(this.binding);
}
this.bindings.add(verificationTypeInfo.binding);
this.binding = scope.lowerUpperBound(this.bindings.toArray(new TypeBinding[this.bindings.size()]));
if (this.binding != null) {
this.id = this.binding.id;
switch (this.id) {
case TypeIds.T_null:
this.tag = VerificationTypeInfo.ITEM_NULL;
break;
default:
this.tag = VerificationTypeInfo.ITEM_OBJECT;
}
} else {
this.binding = scope.getJavaLangObject();
this.tag = VerificationTypeInfo.ITEM_OBJECT;
}
}
return this;
}
}