.cpu_features_sub doesn't seem to be working as expected

I am not sure if this is a compiler bug or an error in my configuration, but I am unable to build my project when adding .sse, .sse2, and .mmx to .cpu_features_sub in build.zig.
Here is a minimal reproduction including build.zig and main.zig:

main.zig:

export fn main() void {
    while (true)
        asm volatile ("hlt");
}

build.zig

const std = @import("std");

pub fn build(b: *std.Build) void {
    const kernel = b.addExecutable(.{
        .name = "kernel",
        .root_module = b.createModule(.{
            .root_source_file = b.path("./main.zig"),
            .target = b.resolveTargetQuery(.{
                .cpu_arch = .x86_64,
                .os_tag = .freestanding,
                .ofmt = .elf,
                .cpu_features_add = std.Target.x86.featureSet(&.{.soft_float}),
                .cpu_features_sub = std.Target.x86.featureSet(&.{
                    .mmx,
                    .sse,
                    .sse2,
                }),
            }),
            .optimize = .Debug,
            .code_model = .kernel,
        }),
        .linkage = .static,
    });
    kernel.entry = .{ .symbol_name = "main" };
    b.installArtifact(kernel);
}

Error messages:

user@work:~/workspace/zigos$ zig build
install
└─ install kernel
   └─ compile exe kernel Debug x86_64-freestanding 2 errors
/home/user/bin/zig-x86_64-linux-0.16.0-dev.2193+fc517bd01/lib/ubsan_rt.zig:83:5: error: failed to select fpext f128 f64 |(none)| xmm0
    fn getFloat(value: Value) f128 {
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/user/bin/zig-x86_64-linux-0.16.0-dev.2193+fc517bd01/lib/std/Io/Writer.zig:596:5: error: emit MIR failed: InvalidInstruction (Zig compiler bug)
pub fn print(w: *Writer, comptime fmt: []const u8, args: anytype) Error!void {
~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: error(x86_64_encoder): no encoding found for: none movups xmm0 m128 none none
       
error: 2 compilation errors
failed command: /home/user/bin/zig-x86_64-linux-0.16.0-dev.2193+fc517bd01/zig build-exe -ofmt=elf -fentry=main -ODebug -mcmodel kernel -target x86_64-freestanding -mcpu baseline-mmx+soft_float-sse-sse2 -Mroot=/home/user/workspace/zigos/main.zig --cache-dir .zig-cache --global-cache-dir /home/user/.cache/zig --name kernel -static --zig-lib-dir /home/user/bin/zig-x86_64-linux-0.16.0-dev.2193+fc517bd01/lib/ --listen=-

Is this the intended behavior? I am developing an OS using Zig and want to build the kernel without any SIMD instructions. While Zig 0.16.0-dev produces the error above, version 0.15.2 results in a segmentation fault during zig build-exe.

It looks like the compiler is failing to emulate f128. Presumably, this emulation involves chaining xmm registers, but since you removed them, the compiler didn’t know what to do.
If Zig already has an emulation for f64 using integer registers, then I guess it’s just a matter of chaining these instead of xmm registers. But I’m not sure this emulation exists in the first place. I, for one, have no idea how to do floating point operations using integer registers, let alone make it remotely efficient.
Bottom line, I think it’s not intended, but I doubt they’re going to put time and energy into such a niche use case.

Appreciate the detailed explanation! The reason I’ve been investigating this is that my system frequently encounters General Protection Faults due to alignment issues when these registers are involved. To clarify, I am not actually using any floating-point operations in my kernel. However, it appears that the compiler automatically generates instructions using XMM regs when handling packed struct operations, which is what led to the issue.

I agree with you that this is likely not a high-priority issue. I will try to find other workaround for now.

2 Likes

I would say that the issue board is the correct place for that sort of decision to be made. We’re missing context: is the problem only when a chip which expects to have xmm is told not to use it? Is there simply no implementation of f128 available without them? Or is there a perfectly good one, which just doesn’t happen to be reached when SIMD “should be” available and the user subtracts it from the feature set?

This could be a #wontfix or it could be a one-line change. We just don’t know.

Posting a clear and replicable report on the issue board, if you want, is justified. Issues don’t have to be urgent to be worth tracking.

5 Likes