master
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4const expectEqual = std.testing.expectEqual;
5
6const is_x86_64_linux = builtin.cpu.arch == .x86_64 and builtin.os.tag == .linux;
7
8comptime {
9 if (builtin.zig_backend != .stage2_arm and
10 !(builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) and // MSVC doesn't support inline assembly
11 is_x86_64_linux)
12 {
13 asm (
14 \\.globl this_is_my_alias;
15 );
16 // test multiple asm per comptime block
17 asm (
18 \\.type this_is_my_alias, @function;
19 \\.set this_is_my_alias, derp;
20 );
21 } else if (builtin.zig_backend == .stage2_spirv) {
22 asm (
23 \\%a = OpString "hello there"
24 );
25 }
26}
27
28test "module level assembly" {
29 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
30 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
33
34 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
35
36 if (is_x86_64_linux) {
37 try expect(this_is_my_alias() == 1234);
38 }
39}
40
41test "output constraint modifiers" {
42 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
43 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
44 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
45 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
46 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
47 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
48
49 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
50
51 // This is only testing compilation.
52 var a: u32 = 3;
53 asm volatile (""
54 : [_] "=m,r" (a),
55 :
56 : .{});
57 asm volatile (""
58 : [_] "=r,m" (a),
59 :
60 : .{});
61}
62
63test "alternative constraints" {
64 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
65 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
66 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
67 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
68 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
69 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
70 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/159200
71
72 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
73
74 // Make sure we allow commas as a separator for alternative constraints.
75 var a: u32 = 3;
76 asm volatile (""
77 : [_] "=r,m" (a),
78 : [_] "r,m" (a),
79 );
80}
81
82test "sized integer/float in asm input" {
83 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
84 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
85 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
86 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
87 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
88
89 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
90
91 asm volatile (""
92 :
93 : [_] "m" (@as(usize, 3)),
94 );
95 asm volatile (""
96 :
97 : [_] "m" (@as(i15, -3)),
98 );
99 asm volatile (""
100 :
101 : [_] "m" (@as(u3, 3)),
102 );
103 asm volatile (""
104 :
105 : [_] "m" (@as(i3, 3)),
106 );
107 asm volatile (""
108 :
109 : [_] "m" (@as(u121, 3)),
110 );
111 asm volatile (""
112 :
113 : [_] "m" (@as(i121, 3)),
114 );
115 asm volatile (""
116 :
117 : [_] "m" (@as(f32, 3.17)),
118 );
119 asm volatile (""
120 :
121 : [_] "m" (@as(f64, 3.17)),
122 );
123}
124
125test "struct/array/union types as input values" {
126 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
127 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
128 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
129 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
130
131 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
132
133 asm volatile (""
134 :
135 : [_] "m" (@as([1]u32, undefined)),
136 ); // fails
137 asm volatile (""
138 :
139 : [_] "m" (@as(struct { x: u32, y: u8 }, undefined)),
140 ); // fails
141 asm volatile (""
142 :
143 : [_] "m" (@as(union { x: u32, y: u8 }, undefined)),
144 ); // fails
145}
146
147extern fn this_is_my_alias() i32;
148
149export fn derp() i32 {
150 return 1234;
151}
152
153test "rw constraint (x86_64)" {
154 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
155 if (builtin.target.cpu.arch != .x86_64) return error.SkipZigTest;
156
157 var res: i32 = 5;
158 asm ("addl %[b], %[a]"
159 : [a] "+r" (res),
160 : [b] "r" (@as(i32, 13)),
161 : .{ .flags = true });
162 try expectEqual(@as(i32, 18), res);
163}
164
165test "asm modifiers (AArch64)" {
166 if (!builtin.target.cpu.arch.isAARCH64()) return error.SkipZigTest;
167
168 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
169
170 var x: u32 = 15;
171 _ = &x;
172 const double = asm ("add %[ret:w], %[in:w], %[in:w]"
173 : [ret] "=r" (-> u32),
174 : [in] "r" (x),
175 );
176 try expectEqual(2 * x, double);
177}