Skip to content

Commit 7f4ccff

Browse files
asteriteMartin Verzilli
authored and
Martin Verzilli
committedSep 16, 2017
Fix: calling twice proc with extern didn't work. Fixes #4982
1 parent 611b5eb commit 7f4ccff

File tree

3 files changed

+27
-5
lines changed

3 files changed

+27
-5
lines changed
 

Diff for: ‎spec/compiler/codegen/extern_spec.cr

+21
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,27 @@ describe "Codegen: extern struct" do
143143
)).to_i.should eq(42)
144144
end
145145

146+
it "codegens extern proc call twice (#4982)" do
147+
run(%(
148+
@[Extern]
149+
struct Data
150+
def initialize(@foo : Int32)
151+
end
152+
153+
def foo
154+
@foo
155+
end
156+
end
157+
158+
f = ->(data : Data) { data.foo }
159+
160+
x = f.call(Data.new(1))
161+
y = f.call(Data.new(2))
162+
163+
x + y
164+
)).to_i.should eq(3)
165+
end
166+
146167
# These specs *should* also work for 32 bits, but for now we'll
147168
# make sure they work in 64 bits (they probably work in 32 bits too,
148169
# it's just that the specs need to be a bit different)

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ module Crystal
9898
end
9999

100100
@c_calling_convention : Bool? = nil
101-
setter c_calling_convention
101+
property c_calling_convention
102102

103103
# Returns `self` as an `External` if this Def is an External
104104
# that must respect the C calling convention.

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

+5-4
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ class Crystal::CodeGenVisitor
651651
c_calling_convention = target_def.proc_c_calling_convention?
652652

653653
proc_type = context.type.as(ProcInstanceType)
654-
0.upto(target_def.args.size - 1) do |i|
654+
target_def.args.size.times do |i|
655655
arg = args[i]
656656
proc_arg_type = proc_type.arg_types[i]
657657
target_def_arg_type = target_def.args[i].type
@@ -685,6 +685,9 @@ class Crystal::CodeGenVisitor
685685
# arguments according to the ABI.
686686
# For this we temporarily set the target_def's `abi_info` and `c_calling_convention`
687687
# properties for the non-closure branch, and then reset it.
688+
old_abi_info = target_def.abi_info?
689+
old_c_calling_convention = target_def.c_calling_convention
690+
688691
if c_calling_convention
689692
null_fun_ptr, null_args = codegen_extern_primitive_proc_call(target_def, args, fun_ptr)
690693
else
@@ -695,8 +698,6 @@ class Crystal::CodeGenVisitor
695698
phi.add value, node.type
696699

697700
# Reset abi_info + c_calling_convention so the closure part is generated as usual
698-
old_abi_info = target_def.abi_info?
699-
old_c_calling_convention = target_def.c_calling_convention?
700701
target_def.abi_info = false
701702
target_def.c_calling_convention = nil
702703

@@ -707,7 +708,7 @@ class Crystal::CodeGenVisitor
707708
phi.add value, node.type, true
708709

709710
target_def.abi_info = old_abi_info
710-
target_def.c_calling_convention = !!old_c_calling_convention
711+
target_def.c_calling_convention = old_c_calling_convention
711712
end
712713

713714
old_needs_value = @needs_value

0 commit comments

Comments
 (0)
Please sign in to comment.