Recent submissions

Comment · 2 months ago
> No, you have tables _of the instructions that the compiler codegen may use_.

That's a distinction without a difference.

> ...because for most architectures it may not even be possible to build such tables in the first place!.

Name the architectures and the specific instructions; do not be hypothetical. In certain runtime-dependent cases like AVX-512, the clobbering is runtime-dependent which then can be explicitly stated by the user.

> You have no idea why you would need to pass a 128 bit int in two registers if there are no two 128-bit integer registers?

I completely understand, my point is that you would pass the two 64-bit parts into separate registers. There are no 128-bit integer registers on the platforms we care about, but if they did exist, supporting them would be trivial. So if you want to pass an 128-bit integer, it will have to be done in two registers, which is literally the point. `asm` templates are not necessarily meant to be used bare all the time, but sometimes it is better to wrap them in a procedure with the correct calling convention too (e.g. "c" or even "naked") if you want to utilizes Odin's native 128-bit integer types as part of the parameters.

Comment · 2 months ago
That "trick" is just a fancy string effectively, the thing I am complaining about in the first part of the article. And that little secret really does mean it is a fancy string again.

I did not want any of that for any reason.

Comment · 2 months ago
1. I don't think I am overselling rexcode, rather there isn't anything like it in the first place as a single library with that many ISAs and IRs. That's what I love about it, since I can now trivially make (non-optimizing) compilers without needing to use LLVM or use another external tool (including outputting C or assembly). Also all of those tables become binary blobs, so you could just use them in your favourite language any way.

2. That was a bug and it has now been fixed, along with many other analysis bugs.

3. The sorting algorithms are getting an overhauls soon to be a lot faster.

Comment · 2 months ago
I haven't fully thought out that syntax yet, but it's a problem with AVX-512 in terms of its predicate operands too.

My hunch would be the following:

        sve_ld1d_scalar :: asm(base: [^]u64, idx: i64, #mask pred: u16) -> (dst: #simd[vscale * 4]f32) [
                dst  = %z0,
                pred = #predicate(indirect=zeroing) %p0,
                dsth: u16 = dst,
        ] {
                ld1d dsth, pred, [base + idx<<3]
        }

        sve_ld1d_gather :: asm(base: [^]u64, #mask pred: u16) -> (dst: #simd[vscale * 4]f32) [
                dst  = %z0,
                pred = #predicate(indirect=zeroing) %p0,
                dsth: u16 = dst,
        ] {
                ld1d dsth, pred, [base + dsth<<3]
        }

So the parameter is marked as a predicate with zeroing or whatever, and then `pred` is just a normal operand as the binding section specifies everything.

This is not current behaviour yet but it I am considering it when I need to specify this for even AVX-512 and RISC-V behaviour (which has multiple different possibilities).

Comment · 2 months ago
How is this not an assembler?—even with your description which matches an assembler to a tee. It genuinely is an assembler, and I am not sure how you are thinking otherwise.

And where is the AT&T? Did you even look at the syntax or read the article? Is it just the use of `%rex` to prevent namespace collisions with parameters and constants which could hypothetically be named `rex` (and there could be good reasons they are named that too)? There are no other sigils in the grammar. The order of the operands is Intel-like. The memory operand syntax is Intel-like.

Comment · 2 months ago
Odin is never going to support SHARC nor Hexagon, so it is literally not a problem.

And I do not even seen why a universal syntax for such ISAs is impossible to support either at the syntax level. Hexagon's `.new`/`:sat`/`:<<1` stuff could be easily added into the universal syntax (with a better syntax), even if other ISAs do not support it. Same with SHARC's parallel-operation separators: you just pick a different syntax.

Even now, the full `[base + indexscale + disp]` syntax is not semantically supported for RISCV64 because they do not support `indexscale` in their memory operands.

Yes the prefix syntax is a quirk but if can tell me an alternative syntax that is context-free to solve this problem that is also not too stark nor dense too read, please do! I am open to new ideas, but it seems that even other assemblers like Plan9, Go, and D, all came to similar conclusion with `lock; xadd ...`.

And the article was not LLM written.

Comment · 2 months ago
Comment · 2 months ago
Why is a bad thing that another language design and compiler writer compares his language as a point of comparison?

I really like it when he does because it allows me to see what he has done for D, and learn from it.

Comment · 2 months ago
D's approach is great, but it has a few limitations for my use case in Odin. It only supports x86_64/amd64 and uses Intel-style syntax, whereas I needed a solution that universalizes its syntax across multiple ISAs.

D's inline asm is also statement-based rather than a callable template. Though the mixin trick fixes this, it does mean it still uses %0-style parameters making it hard to read and write, something I want to remove completely.

It is great to see that we arrived at similar design compromises, especially regarding `lock` being treated as a separate instruction and thus separated with a `;` (which is automatically inserted by the Odin compiler).

Comment · 2 months ago
That's pretty much the quibble. Most people's narrow view of type system.

And we already track all of the basic side-effects and clobbering that each form of each mnemonic does. That's kind of the entire point of this being possible: it's all "typed".

Comment · 2 months ago
> the different operand sizes have a lot of side effects

Which we have massive tables for each form which track those side effects and clobbering information too.

> author/LLM

I am the author, and not an LLM.

> Tomorrow you need to pass a 128 bit int into two registers

Okay? There are no 128-bit integer registers on AMD64, ARM64, nor RISCV-64. So I have no idea what you are on about. And note they are templates, so if you want 128-bit integer support, you can just wrap that template in a procedure and handle the behaviour yourself.

Comment · 2 months ago
I know that "untyped" means a single-type, but assembly operands have multiple different kinds of types (as I state in the article). What makes it really interesting is what you can know about each instruction and what it does (what operands it excepts, what it clobbers, what side-effects its has, etc).

And from that huge table of type information, this can be used to give good error messages and suggestions to the user because the compiler actually knows all of this. The type constraints here allow for a lot more than information that normal assemblers just don't give.

Comment · 2 months ago
The equivalent Odin syntax looks like this:

add_three :: asm(my_in: u64) -> (my_out: u64) { add my_out, my_in, 3 }

out_var = add_three(in_var)

Which is already infinitely more readable and requires no parochial sigils nor the arcane clobbering syntax.

Comment · 2 months ago
TALs are not what I am referring to here. I am arguing that assembly is already typed and does not need extra annotation to be typed.

TALs are also solving an entirely different problem.

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton