Stream: cranelift

Topic: Silly questions


view this post on Zulip Firestar99 (Jan 14 2026 at 16:25):

I'm investigating cranelift since the beginning of this week and have a few questions. Instead of creating a bunch of threads, I thought I'd cummulate them here :D

view this post on Zulip Firestar99 (Jan 14 2026 at 16:28):

What's the difference between a StackSlot and a DynamicStackSlot? Is DynamicStackSlot only used to put DynamicTypes on the stack, for what are those used? I remember something about ARM having a dynamically sized SIMD width, could it be for that?

view this post on Zulip Chris Fallin (Jan 14 2026 at 16:29):

yes, exactly, and only for its new SVE instruction set, which isn't really fully supported in our compiler

view this post on Zulip Firestar99 (Jan 15 2026 at 12:19):

I've been reading into isle for a few days now, and I see this pattern in tutorial.isle:

(decl lower (HighLevelInst) LowLevelInst)
(rule lower ...)
(decl inst_result (HighLevelInst) Value)
(extern extractor inst_result inst_result)

I see these decl as rust function calls, in macro-rules form (decl $name:ident $($param:ty),+ $result:ty). So isle would generate to this in rust, ignoring self:

fn constructor_lower(_: HighLevelInst) -> LowLevelInst { ... }
fn inst_result(_: HighLevelInst) -> Option<Value> { ... }

(I think constructors only return Option<_> if the decl has partial?)

Now in the prelude.lower I'm coming across this:

(decl value_type (Type) Value)
(extern extractor infallible value_type value_type)

which I would think should be:

fn value_type(val: Type) -> Value { ... }

but it is actually:

fn value_type(val: Value) -> Type { ... }

Why are params and return type suddenly swapped?
(Logically, it ofc only sense to turn an SSA value into a result type, not the other way around)

These "swapped params / results" go all the way up to has_type, where I originally encountered it:

(decl result_type (Type) Inst)
(extractor (result_type ty)
           (first_result (value_type ty)))
(decl has_type (Type Inst) Inst)
(extractor (has_type ty inst)
           (and (result_type ty)
                inst))
A lightweight WebAssembly runtime that is fast, secure, and standards-compliant - bytecodealliance/wasmtime
A lightweight WebAssembly runtime that is fast, secure, and standards-compliant - bytecodealliance/wasmtime

view this post on Zulip Firestar99 (Jan 15 2026 at 13:08):

I assume the answer is that extern extractors "swap" return type and args within Rust compared to their constructor counterparts, since they "work in reverse" to constructors? Which would allow isle extractors, constructors and types (implicitly declaring both) to be declared with the exact same arg order, but extractors ofc "working in reverse".

view this post on Zulip Chris Fallin (Jan 15 2026 at 13:46):

Yep, exactly

view this post on Zulip AKSHANABHA CHAKRABORTY (Mar 03 2026 at 16:26):

Hello, actually I was working on Cranelift ISLE (basically after bitpacking the data as requested in PR 12701), I ended up with the following struct.

/// Atomic Read-Modify-Write Options
/// Describes the ordering as well as the option
pub struct AtomicRmwData(
  // bits 1/2/3/4/5 = AtomicRmwOp
  // 6/7/8 = AtomicOrdering
  pub(crate) u8,
);

impl AtomicRmwData {
  // 0 0 0 1 1 1 1 1
  // Keeps the RMW Bits
  const MASK_RMW: u8 = 0x1F;

  // 1 1 1 0 0 0 0 0
  // Keeps the ordering bits
  const MASK_ORDERING: u8 = 0xE0;

  pub fn new(ordering: AtomicOrdering, op: AtomicRmwOp) -> Self {
    let rmw = op.to_u8();

    Self(rmw | (ordering.to_u8() << 5))
  }

  pub fn ordering(&self) -> AtomicOrdering {
    AtomicOrdering::from_u8(self.0 >> 5)
  }

  pub fn set_ordering(&mut self, ordering: AtomicOrdering) {
    self.0 &= Self::MASK_RMW;
    self.0 |= ordering.to_u8() << 5;
  }

  pub fn op(&self) -> AtomicRmwOp {
    AtomicRmwOp::from_u8(self.0 & Self::MASK_RMW)
  }

  pub fn set_op(&mut self, op: AtomicRmwOp) {
    self.0 &= Self::MASK_ORDERING;
    self.0 |= op.to_u8();
  }
}

Now, actually I'm having a small issue while trying to implement this to these regions:

(rule 1 (lower (and (use_lse)
                  (has_type (valid_atomic_transaction ty)
                      (atomic_rmw (little_or_native_endian flags) (AtomicRmwOp.Add) addr src))))
      (lse_atomic_rmw (AtomicRMWOp.Add) addr src ty flags))

I actually am more/less not able to find out the correct strategy to achieve this. Can anyone guide me? (Due to the nature, we need a rust function potentially an extractor I think)

Any guidance would be extremely helpful

view this post on Zulip Chris Fallin (Mar 03 2026 at 16:41):

Yes, you'll need to define an extractor of signature (for example) (decl atomic_rmw_op (AtomicRmwOp) AtomicRmwData), which will be implemented in Rust with signature fn atomic_rmw_op(&mut self, data: &AtomicRmwData) -> Option<AtomicRmwOp> in the lowering environment trait

view this post on Zulip AKSHANABHA CHAKRABORTY (Mar 03 2026 at 16:43):

Is this used in this way later?

(rule 1 (lower (and (use_lse)
                  (has_type (valid_atomic_transaction ty)
                      (atomic_rmw (little_or_native_endian flags) (atomic_rmw_op AtomicRmwOp.Add) addr src))))
      (lse_atomic_rmw (AtomicRMWOp.Add) addr src ty flags))

??

view this post on Zulip Chris Fallin (Mar 03 2026 at 16:44):

yep, pretty much! (parens around (AtomicRmwOp.Add) but that's a minor syntactic detail)

view this post on Zulip AKSHANABHA CHAKRABORTY (Mar 03 2026 at 17:09):

Thanks a lot, that helped me lower it

view this post on Zulip Jacob Lifshay (Mar 03 2026 at 17:18):

AKSHANABHA CHAKRABORTY said:

Hello, actually I was working on Cranelift ISLE (basically after bitpacking the data as requested in PR 12701), I ended up with the following struct.

  // 0 0 0 1 1 1 1 1
  // Keeps the RMW Bits
  const MASK_RMW: u8 = 0x1F;

rust supports binary literals so you could write 0b000_11111 and 0b111_00000 if you wanted rather than having a comment with the binary and having to write it in hexadecimal.

view this post on Zulip AKSHANABHA CHAKRABORTY (Mar 04 2026 at 04:43):

I have a question regarding MemFlags, which bits are actually (meaningfully) used in an AtomicCas

#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct MemFlags {
    // Initialized to all zeros to have all flags have their default value.
    // This is interpreted through various methods below. Currently the bits of
    // this are defined as:
    //
    // * 0 - aligned flag
    // * 1 - readonly flag
    // * 2 - little endian flag
    // * 3 - big endian flag
    // * 4 - checked flag
    // * 5/6 - alias region
    // * 7/8/9/10/11/12/13/14 - trap code
    // * 15 - can_move flag
    //
    // Current properties upheld are:
    //
    // * only one of little/big endian is set
    // * only one alias region can be set - once set it cannot be changed
    bits: u16,
}

I was wondering, if i could shave off 3 bits for AtomicOrdering when it represents AtomicCas

view this post on Zulip Akshanabha Chakraborty (Mar 04 2026 at 09:00):

Apologies to @Firestar99—I totally misread the thread title 'Silly Questions' as a general community dump-bin/off-topic thread rather than a personal log! I hope you would apologise me :brain:

view this post on Zulip Akshanabha Chakraborty (Mar 04 2026 at 12:39):

My plan is to basically create a new structure

pub struct AtomicCasMemFlags {
    bits: u16
}

where the flags are exclusively made for the AtomicCas instruction to fit ordering and remove redundant data.
As, i have found out, readonly and can_move are redundant and hence their bits can be re-used. Then, we need exactly 1 extra bit for this to be complete

view this post on Zulip bjorn3 (Mar 04 2026 at 15:11):

Akshanabha Chakraborty said:

Apologies to @Firestar99—I totally misread the thread title 'Silly Questions' as a general community dump-bin/off-topic thread rather than a personal log! I hope you would apologise me :brain:

You can move the messages to a different topic if you want. Just click on the three dots menu of the first message you want to move and choose "Move messages".

view this post on Zulip Notification Bot (Mar 04 2026 at 15:18):

10 messages were moved from this topic to #cranelift > ISLE Lowering, Extractors, MemFlags by Akshanabha Chakraborty.


Last updated: Mar 23 2026 at 19:19 UTC