Can't compile with inline asm with clobber

What am I doing wrong here? The compiler won’t let me compile since it wants me to make clob const even though it is written to.

pub inline fn rdtscp() u64 {
    var hi: u32 = undefined;
    var low: u32 = undefined;
    var clob: u32 = undefined;   // ERROR: local is never mutated

    asm (
        \\rdtscp
        : [low] "={eax}" (low),
          [hi] "={edx}" (hi),
        : [clob] "={ecx}" (clob),
    );
    return (@as(u64, hi) << 32) | @as(u64, low);
}

If we look detailed at the assembly section of the language reference, we will find out you were specifying the clobber as input and not as clobber, because after output comes input and then comes clobber. You would have to do the following if you want the clobber to be a clobber:

pub inline fn rdtscp() u64 {
    var hi: u32 = undefined;
    var low: u32 = undefined;
    var clob: u32 = undefined;

    asm (
        \\rdtscp
        : [low] "={eax}" (low),
          [hi] "={edx}" (hi),
        : // empty input list
        : [clob] "={ecx}" (clob),
    );
    return (@as(u64, hi) << 32) | @as(u64, low);
}

This should solve the problem…
If not, we could consider this a bug.

1 Like

The RDTSCP doe s a CPUID with it and puts it in ecx, but I don’t bother to return it, so it is kind of a clobber. It definitely gets written to, but not read from.

The error message is a little off. It should probably something more akin to store with no load, but those are allowed by the language. It’s in the return list after all.

fn f(x: u32) u32 {
   var y: u32 = undefined;
   y = 4;
   return x;
}

is totally acceptable, and that’s basically what the asm block does. The binding is clearly not const.