Format stack map table attribute

This commit is contained in:
ktkk 2026-07-06 21:55:57 +02:00
parent a451327a6a
commit 3a5fd90d14
2 changed files with 149 additions and 7 deletions

View file

@ -332,7 +332,20 @@ pub const AttributeInfo = union(enum) {
try a.indentedFormat(w, depth, attr_indent + 1, constant_pool);
}
},
//.stack_map_table,
.stack_map_table => |attr| {
try w.splatByteAll(' ', depth * indent);
_ = try w.write("entries:\n");
var stack_map_frame_indent = indent;
for (attr.entries, 0..) |*stack_map_frame, i| {
stack_map_frame_indent += 1;
defer stack_map_frame_indent -= 1;
try w.splatByteAll(' ', depth * stack_map_frame_indent);
try w.print("{d}:\n", .{ i });
try stack_map_frame.indentedFormat(w, depth, stack_map_frame_indent + 1, constant_pool);
}
},
.exceptions => |attr| {
try w.splatByteAll(' ', depth * indent);
_ = try w.write("exceptions:\n");
@ -791,6 +804,103 @@ pub const StackMapTable = struct {
else => {},
}
}
pub fn indentedFormat(
self: *const StackMapFrame,
w: *std.Io.Writer,
depth: usize,
indent: u8,
constant_pool: ConstantPool,
) std.Io.Writer.Error!void {
try w.splatByteAll(' ', depth * indent);
try w.print("frame_type: {s}\n", .{ @tagName(self.*) });
switch (self.*) {
.same_locals_1_stack_item_frame => |same_locals_1_stack_item_frame| {
try w.splatByteAll(' ', depth * indent);
_ = try w.write("stack:\n");
var stack_indent = indent;
for (&same_locals_1_stack_item_frame.stack, 0..) |*info, i| {
stack_indent += 1;
defer stack_indent -= 1;
try w.splatByteAll(' ', depth * stack_indent);
try w.print("{d}:\n", .{ i });
try info.indentedFormat(w, depth, stack_indent + 1, constant_pool);
}
},
.same_locals_1_stack_item_frame_extended => |same_locals_1_stack_item_frame_extended| {
try w.splatByteAll(' ', depth * indent);
try w.print("offset_delta: {d}\n", .{ same_locals_1_stack_item_frame_extended.offset_delta });
try w.splatByteAll(' ', depth * indent);
_ = try w.write("stack:\n");
var stack_indent = indent;
for (&same_locals_1_stack_item_frame_extended.stack, 0..) |*info, i| {
stack_indent += 1;
defer stack_indent -= 1;
try w.splatByteAll(' ', depth * stack_indent);
try w.print("{d}:\n", .{ i });
try info.indentedFormat(w, depth, stack_indent + 1, constant_pool);
}
},
.chop_frame => |chop_frame| {
try w.splatByteAll(' ', depth * indent);
try w.print("offset_delta: {d}\n", .{ chop_frame.offset_delta });
},
.append_frame => |append_frame| {
try w.splatByteAll(' ', depth * indent);
try w.print("offset_delta: {d}\n", .{ append_frame.offset_delta });
try w.splatByteAll(' ', depth * indent);
_ = try w.write("locals:\n");
var locals_indent = indent;
for (append_frame.locals, 0..) |*info, i| {
locals_indent += 1;
defer locals_indent -= 1;
try w.splatByteAll(' ', depth * locals_indent);
try w.print("{d}:\n", .{ i });
try info.indentedFormat(w, depth, locals_indent + 1, constant_pool);
}
},
.full_frame => |full_frame| {
try w.splatByteAll(' ', depth * indent);
try w.print("offset_delta: {d}\n", .{ full_frame.offset_delta });
try w.splatByteAll(' ', depth * indent);
_ = try w.write("locals:\n");
var locals_indent = indent;
for (full_frame.locals, 0..) |*info, i| {
locals_indent += 1;
defer locals_indent -= 1;
try w.splatByteAll(' ', depth * locals_indent);
try w.print("{d}:\n", .{ i });
try info.indentedFormat(w, depth, locals_indent + 1, constant_pool);
}
try w.splatByteAll(' ', depth * indent);
_ = try w.write("stack:\n");
var stack_indent = indent;
for (full_frame.stack, 0..) |*info, i| {
stack_indent += 1;
defer stack_indent -= 1;
try w.splatByteAll(' ', depth * stack_indent);
try w.print("{d}:\n", .{ i });
try info.indentedFormat(w, depth, stack_indent + 1, constant_pool);
}
},
else => {},
}
}
};
pub const VerificationTypeInfo = union(VerificationTypeInfo.Tag) {
@ -852,6 +962,31 @@ pub const StackMapTable = struct {
},
};
}
pub fn indentedFormat(
self: *const VerificationTypeInfo,
w: *std.Io.Writer,
depth: usize,
indent: u8,
constant_pool: ConstantPool,
) std.Io.Writer.Error!void {
try w.splatByteAll(' ', depth * indent);
try w.print("tag: {s}\n", .{ @tagName(self.*) });
switch (self.*) {
.object => |object| {
const class = object.class(constant_pool) catch return error.WriteFailed;
try w.splatByteAll(' ', depth * indent);
_ = try w.write("class:\n");
try class.indentedFormat(w, depth, indent + 1, constant_pool);
},
.uninitialized => |uninitialized| {
try w.splatByteAll(' ', depth * indent);
try w.print("offset: {d}\n", .{ uninitialized.offset });
},
else => {},
}
}
};
pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Self {

View file

@ -1,18 +1,26 @@
import java.util.function.Supplier;
@CustomAttribute
public class Main implements Runnable, Supplier<Integer>, Interface {
private static final String name = "John";
private static final int number = 42;
private static final double funnyNumber = 6.9;
public static void main() {
new Main().sayHello();
public static void main(String[] args) {
final var main = new Main();
main.sayHello();
try {
main.throwSomething();
} catch (Throwable e) {
System.err.println("Caught " + e.getMessage());
} finally {
System.err.println("Finally block");
}
}
@Override
public void run() {
Main.main();
Main.main(new String[] { "Hello" });
}
@Override
@ -38,4 +46,3 @@ public class Main implements Runnable, Supplier<Integer>, Interface {
private static final String name = "Inner John";
}
}