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}