1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use crate::JavaString;
use std::fmt::Display;
/// Represents the verification types used in the JVM bytecode verification process. These types
/// correspond to the types defined in the Java Virtual Machine Specification (JVMS) for stack map
/// frames.
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) enum VerificationType {
/// Top type, used for the second slot of Long and Double
Top,
/// Integer type
Integer,
/// Float type
Float,
/// Long type
Long,
/// Double type
Double,
/// Null type
Null,
/// Uninitialized "this" type
UninitializedThis,
/// Object type with class name
Object(JavaString),
/// Uninitialized type with offset of the new instruction
// Long and Double take two slots, represented by Top in the second slot in some implementations,
// or handled by logic. JVMS suggests using "Long" and "Double" as single types that consume 2 entries in locals/stack calculations.
// But for type checking, we might need 2nd slot marker.
// Let's stick to JVMS 4.10.1.2:
// "Long and Double are considered to be of category 2... they occupy two local variables or two stack entries."
// We will follow the convention of having specific types and managing the 2-slot aspect in the Frame logic.
Uninitialized(u16),
}
/// Implements the Display trait for `VerificationType` to provide a human-readable representation.
impl Display for VerificationType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
VerificationType::Top => write!(f, "top"),
VerificationType::Integer => write!(f, "int"),
VerificationType::Float => write!(f, "float"),
VerificationType::Long => write!(f, "long"),
VerificationType::Double => write!(f, "double"),
VerificationType::Null => write!(f, "null"),
VerificationType::UninitializedThis => write!(f, "uninitialized_this"),
VerificationType::Object(name) => write!(f, "class {name}"),
VerificationType::Uninitialized(offset) => write!(f, "uninitialized({offset})"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_display() {
assert_eq!(VerificationType::Top.to_string(), "top");
assert_eq!(VerificationType::Integer.to_string(), "int");
assert_eq!(VerificationType::Float.to_string(), "float");
assert_eq!(VerificationType::Long.to_string(), "long");
assert_eq!(VerificationType::Double.to_string(), "double");
assert_eq!(VerificationType::Null.to_string(), "null");
assert_eq!(
VerificationType::UninitializedThis.to_string(),
"uninitialized_this"
);
assert_eq!(
VerificationType::Object(JavaString::from("java/lang/Object")).to_string(),
"class java/lang/Object"
);
assert_eq!(
VerificationType::Uninitialized(42).to_string(),
"uninitialized(42)"
);
}
}