Skip to content

Commit

Permalink
Hierarchy tool: Fix byte sizes for Procs inside extern structs(#13711)
Browse files Browse the repository at this point in the history
Extern structs store `Proc`s without the closure pointer, so they should use `llvm_embedded_c_type` rather than `llvm_embedded_type` for the correct byte sizes.

The total sizes of the extern structs themselves are already correct and unaffected by this PR.
  • Loading branch information
HertzDevil committed Aug 1, 2023
1 parent 69468c8 commit a5a617d
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 5 deletions.
30 changes: 30 additions & 0 deletions spec/compiler/crystal/tools/hierarchy_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,36 @@ describe Crystal::TextHierarchyPrinter do
@x : Bool (1 bytes)\n
EOS
end

it "shows correct size for Proc inside extern struct" do
program = semantic(<<-CRYSTAL).program
@[Extern]
struct Foo
@x = uninitialized ->
end
lib Bar
struct Foo
x : Int32 -> Int32
end
end
CRYSTAL

output = String.build { |io| Crystal.print_hierarchy(program, io, "Foo", "text") }
output.should eq(<<-EOS)
- class Object (4 bytes)
|
+- struct Value (0 bytes)
|
+- struct Struct (0 bytes)
|
+- struct Bar::Foo (8 bytes)
| @x : Proc(Int32, Int32) (8 bytes)
|
+- struct Foo (8 bytes)
@x : Proc(Nil) (8 bytes)\n
EOS
end
end

describe Crystal::JSONHierarchyPrinter do
Expand Down
11 changes: 6 additions & 5 deletions src/compiler/crystal/tools/print_hierarchy.cr
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,9 @@ module Crystal
@llvm_typer.size_of(@llvm_typer.llvm_struct_type(type))
end

def ivar_size(ivar)
@llvm_typer.size_of(@llvm_typer.llvm_embedded_type(ivar.type))
def ivar_size(ivar, extern)
llvm_type = extern ? @llvm_typer.llvm_embedded_c_type(ivar.type) : @llvm_typer.llvm_embedded_type(ivar.type)
@llvm_typer.size_of(llvm_type)
end
end

Expand Down Expand Up @@ -201,7 +202,7 @@ module Crystal
max_name_size = instance_vars.max_of &.name.size

max_type_size = typed_instance_vars.max_of?(&.type.to_s.size) || 0
max_bytes_size = typed_instance_vars.max_of? { |var| ivar_size(var).to_s.size } || 0
max_bytes_size = typed_instance_vars.max_of? { |var| ivar_size(var, type.extern?).to_s.size } || 0

instance_vars.each do |ivar|
print_indent
Expand All @@ -214,7 +215,7 @@ module Crystal
ivar_type.to_s.ljust(@io, max_type_size)
with_color.light_gray.surround(@io) do
@io << " ("
ivar_size(ivar).to_s.rjust(@io, max_bytes_size)
ivar_size(ivar, type.extern?).to_s.rjust(@io, max_bytes_size)
@io << " bytes)"
end
else
Expand Down Expand Up @@ -330,7 +331,7 @@ module Crystal
@json.object do
@json.field "name", instance_var.name.to_s
@json.field "type", ivar_type.to_s
@json.field "size_in_bytes", ivar_size(instance_var)
@json.field "size_in_bytes", ivar_size(instance_var, type.extern?)
end
end
end
Expand Down

0 comments on commit a5a617d

Please sign in to comment.