Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions spec/compiler/codegen/c_abi/c_abi_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ describe "Code gen: C ABI" do
test_c(
%(
struct s {
long x;
long long x;
short y;
};

long foo(struct s a) {
long long foo(struct s a) {
return a.x + a.y;
}
),
Expand All @@ -59,12 +59,12 @@ describe "Code gen: C ABI" do
test_c(
%(
struct s {
long x;
long y;
long long x;
long long y;
char z;
};

long foo(struct s a) {
long long foo(struct s a) {
return a.x + a.y + a.z;
}
),
Expand Down Expand Up @@ -116,7 +116,7 @@ describe "Code gen: C ABI" do
test_c(
%(
struct s {
long x;
long long x;
short y;
};

Expand Down Expand Up @@ -144,8 +144,8 @@ describe "Code gen: C ABI" do
test_c(
%(
struct s {
long x;
long y;
long long x;
long long y;
char z;
};

Expand Down
2 changes: 1 addition & 1 deletion spec/compiler/codegen/c_abi/c_abi_x86_64_spec.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require "../../../spec_helper"

{% if flag?(:x86_64) %}
{% if flag?(:x86_64) && !flag?(:win32) %}
describe "Code gen: C ABI x86_64" do
it "passes struct less than 64 bits as { i64 }" do
mod = codegen(%(
Expand Down
6 changes: 3 additions & 3 deletions spec/compiler/codegen/extern_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -431,9 +431,9 @@ describe "Codegen: extern struct" do
test_c(
%(
struct Struct {
long x;
long y;
long z;
long long x;
long long y;
long long z;
};

struct Struct foo(struct Struct (*callback)(struct Struct)) {
Expand Down
29 changes: 16 additions & 13 deletions spec/compiler/codegen/primitives_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -239,22 +239,25 @@ describe "Code gen: primitives" do
end

describe "va_arg" do
it "uses llvm's va_arg instruction" do
mod = codegen(%(
struct VaList
@[Primitive(:va_arg)]
def next(type)
# On Windows llvm's va_arg instruction works incorrectly.
{% unless flag?(:win32) %}
it "uses llvm's va_arg instruction" do
mod = codegen(%(
struct VaList
@[Primitive(:va_arg)]
def next(type)
end
end
end

list = VaList.new
list.next(Int32)
))
str = mod.to_s
str.should contain("va_arg %VaList* %list")
end
list = VaList.new
list.next(Int32)
))
str = mod.to_s
str.should contain("va_arg %VaList* %list")
end
{% end %}

it "works with C code" do
pending_win32 "works with C code" do
test_c(
%(
extern int foo_f(int,...);
Expand Down
3 changes: 3 additions & 0 deletions src/compiler/crystal/semantic/main_visitor.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2431,6 +2431,9 @@ module Crystal
end

def visit_va_arg(node)
if program.has_flag? "windows"
node.raise "va_arg is not yet supported on Windows"
end
arg = call.not_nil!.args[0]? || node.raise("requires type argument")
node.type = arg.type.instance_type
end
Expand Down
1 change: 1 addition & 0 deletions src/llvm/abi.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Based on https://github.com/rust-lang/rust/blob/29ac04402d53d358a1f6200bea45a301ff05b2d1/src/librustc_trans/trans/cabi.rs
abstract class LLVM::ABI
getter target_data : TargetData
getter? osx : Bool
Expand Down
1 change: 1 addition & 0 deletions src/llvm/abi/x86.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require "../abi"

# Based on https://github.com/rust-lang/rust/blob/29ac04402d53d358a1f6200bea45a301ff05b2d1/src/librustc_trans/trans/cabi_x86.rs
class LLVM::ABI::X86 < LLVM::ABI
def abi_info(atys : Array(Type), rty : Type, ret_def : Bool, context : Context)
ret_ty = compute_return_type(rty, ret_def, context)
Expand Down
1 change: 1 addition & 0 deletions src/llvm/abi/x86_64.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require "../abi"

# Based on https://github.com/rust-lang/rust/blob/29ac04402d53d358a1f6200bea45a301ff05b2d1/src/librustc_trans/trans/cabi_x86_64.rs
class LLVM::ABI::X86_64 < LLVM::ABI
def abi_info(atys : Array(Type), rty : Type, ret_def : Bool, context : Context)
arg_tys = Array(LLVM::Type).new(atys.size)
Expand Down
22 changes: 22 additions & 0 deletions src/llvm/abi/x86_win64.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
require "../abi"

# Based on https://github.com/rust-lang/rust/blob/29ac04402d53d358a1f6200bea45a301ff05b2d1/src/librustc_trans/trans/cabi_x86_win64.rs
class LLVM::ABI::X86_Win64 < LLVM::ABI::X86
private def compute_arg_types(atys, context)
atys.map do |t|
case t.kind
when Type::Kind::Struct
size = target_data.abi_size(t)
case size
when 1 then ArgType.direct(t, context.int8)
when 2 then ArgType.direct(t, context.int16)
when 4 then ArgType.direct(t, context.int32)
when 8 then ArgType.direct(t, context.int64)
else ArgType.indirect(t, LLVM::Attribute::ByVal)
end
else
non_struct(t, context)
end
end
end
end
2 changes: 2 additions & 0 deletions src/llvm/target_machine.cr
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class LLVM::TargetMachine
def abi
triple = self.triple
case triple
when /x86_64.+windows-msvc/
ABI::X86_Win64.new(self)
when /x86_64|amd64/
ABI::X86_64.new(self)
when /i386|i486|i586|i686/
Expand Down