Skip to content

Commit e586dd2

Browse files
author
Ary Borenszweig
committedMar 1, 2017
Compiler: correctly copy anonymous struct types from other contexts. Fixes #4078 . Fixes #4082
1 parent 2e61cca commit e586dd2

File tree

3 files changed

+40
-6
lines changed

3 files changed

+40
-6
lines changed
 

Diff for: ‎spec/compiler/codegen/c_abi/c_abi_x86_64_spec.cr

+24
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,30 @@ require "../../../spec_helper"
8585
str.should contain("declare void @foo({ i64, i64 })")
8686
end
8787

88+
it "passes struct between 64 and 128 bits as { i64, i64 } (with multiple modules/contexts)" do
89+
codegen(%(
90+
require "prelude"
91+
92+
lib LibFoo
93+
struct Struct
94+
x : Int64
95+
y : Int16
96+
end
97+
98+
fun foo(s : Struct)
99+
end
100+
101+
module Moo
102+
def self.moo
103+
s = LibFoo::Struct.new
104+
LibFoo.foo(s)
105+
end
106+
end
107+
108+
Moo.moo
109+
))
110+
end
111+
88112
it "passes struct between 64 and 128 bits (for real)" do
89113
test_c(
90114
%(

Diff for: ‎src/compiler/crystal/codegen/llvm_typer.cr

+10-4
Original file line numberDiff line numberDiff line change
@@ -523,11 +523,17 @@ module Crystal
523523
LLVM::Type.function(params_types, ret_type, type.varargs?)
524524
when .struct?
525525
llvm_name = type.struct_name
526-
@structs[llvm_name] ||= begin
527-
@llvm_context.struct(llvm_name, type.packed_struct?) do |the_struct|
528-
@structs[llvm_name] = the_struct
529-
copy_types(type.struct_element_types)
526+
if llvm_name
527+
@structs[llvm_name] ||= begin
528+
@llvm_context.struct(llvm_name, type.packed_struct?) do |the_struct|
529+
@structs[llvm_name] = the_struct
530+
copy_types(type.struct_element_types)
531+
end
530532
end
533+
else
534+
# The case of an anonymous struct (only happens with C bindings and C ABI,
535+
# where structs like `{ double, double }` are generated)
536+
@llvm_context.struct(copy_types(type.struct_element_types), packed: type.packed_struct?)
531537
end
532538
else
533539
raise "don't know how to copy type: #{type} (#{type.kind})"

Diff for: ‎src/llvm/type.cr

+6-2
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,14 @@ struct LLVM::Type
6363
LibLLVM.is_packed_struct(self) != 0
6464
end
6565

66-
def struct_name
66+
# Assuming this type is a struct, returns its name.
67+
# The name can be `nil` if the struct is anynomous.
68+
# Raises if this type is not a struct.
69+
def struct_name : String?
6770
raise "not a Struct" unless kind == Kind::Struct
6871

69-
String.new(LibLLVM.get_struct_name(self))
72+
name = LibLLVM.get_struct_name(self)
73+
name ? String.new(name) : nil
7074
end
7175

7276
def struct_element_types

0 commit comments

Comments
 (0)
Please sign in to comment.