Thread overview
[Issue 20594] [GCC ASM] Should the asm { } syntax be modernized for D2?
Feb 22, 2020
Iain Buclaw
Jul 16, 2020
Iain Buclaw
Dec 17, 2022
Iain Buclaw
Feb 15, 2023
Iain Buclaw
February 22, 2020
https://issues.dlang.org/show_bug.cgi?id=20594

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ibuclaw@gdcproject.org
           Assignee|nobody@puremagic.com        |ibuclaw@gdcproject.org

--
July 16, 2020
https://issues.dlang.org/show_bug.cgi?id=20594

--- Comment #1 from Iain Buclaw <ibuclaw@gdcproject.org> ---
(In reply to Iain Buclaw from comment #0)
> Then going one further and replacing the colons with commas.
> 
> asm pure nothrow @nogc {
>     "cmoveq %1, %2, %[result]",   // insn
>     [result = "=r": result],      // outputs
>     ["r": test, "r": newvalue,    // inputs
>      "[result]": oldvalue],
>     ["memory"];                   // clobbers
> }
> 

Could even drop the order dependency and re-use struct literal syntax of using labels to denote "fields" of the asm statement.

asm pure nothrow @nogc {
    insn:     "cmoveq %1, %2, %[result]",
    clobbers: ["memory"],
    inputs:   ["r": test, "r": newvalue,
               "[result]": oldvalue],
    outputs:  [result = "=r": result],
}

And so in the last example.

> int main()
> {
>     int iInt = 1;
> top:
>     asm nothrow @nogc {
>         "some assembler instructions here",
>         [/* No outputs. */],
>         ["q": iInt, "X": char.sizeof + 1, "i": 42],
>         [/* No clobbers. */],
>         [top];
>     }
> }

It can be abbreviated to:

int main()
{
    int iInt = 1;
top:
    asm nothrow @nogc {
        "some assembler instructions here",
        inputs: ["q": iInt, "X": char.sizeof + 1, "i": 42],
        labels: [top];
    }
}

--
December 17, 2022
https://issues.dlang.org/show_bug.cgi?id=20594

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P1                          |P4

--
February 15, 2023
https://issues.dlang.org/show_bug.cgi?id=20594

--- Comment #2 from Iain Buclaw <ibuclaw@gdcproject.org> ---
Another alternative that may prove nicer, is the use of `arg => value` instead.
 This also allows for each argument/property of the GCC-style assembler
statement to be optionally added.

However, there is also DIP88 to consider, which has adopted `arg: value` for named parameters.  So can't ignore the original alternative syntax suggested in 2020.

If going for named arguments, can also add a few more to expose the underbelly of the implementation to the user, for example `volatile` and `inline`.

Alternative syntax #1
```
asm @safe @nogc nothrow pure {
    "insn-template",          // can be CTFE-able expression with string result
    inputs   => ("a", value), // simple example, single input/output
    outputs  => [             // complex example, multiple input/outputs
        ("=a", result),
        ("=g", overflow)
    ],
    clobber  => "eax",        // or ["eax", "memory", ...]
    goto     => label,        // or [label1, label2, ...]
    volatile => true,         // default true, accept "false" as optimization
    inline   => true,         // default false, allow pragma(inline, true) to
                              // set if not specified
}
```

Alternative syntax #2
```
asm @safe @nogc nothrow pure {
    "insn-template",       // can be CTFE-able expression with string result
    inputs: ("a", value),  // simple example, single input/output
    outputs: [             // complex example, multiple input/outputs
        ("=a", result),
        ("=g", overflow)
    ],
    clobber: "eax",        // or ["eax", "memory", ...]
    goto: label,           // or [label1, label2, ...]
    volatile: true,        // default true, accept "false" as optimization
    inline: true,          // default false, allow pragma(inline, true) to
                           // set if not specified
}
```

Example 1:
```
int foo(int count)
{
    version (GNU_Alternate1_Asm)
    {
        asm { "dec %0, jb %l[stop]",
              goto => stop,
              outputs => ("+r", count);
              volatile => false;
        }
    }
    else version (GNU_Alternate2_Asm)
    {
        asm { "dec %0, jb %l[stop]",
              goto: stop,
              outputs: ("+r", count);
              volatile: false;
        }
    }
    else  // old-style syntax
    {
        asm { "dec %0, jb %l[stop]"
              : "+r" (count)
              : /* No inputs */
              : /* No clobbers */
              : stop;
        }
    }
  return count;
stop:
  return 0;
}
```

Example 2:
```
version (GNU_Alternate1_Asm)
{
    asm pure nothrow @nogc {
        "cpuid",
        outputs => [("=a", a), ("=b", b)],
        inputs  => ("a", 0x8000_001E),
        clobber => ["ecx", "edx"];
    }
}
else version (GNU_Alternate2_Asm)
{
    asm pure nothrow @nogc {
        "cpuid",
        outputs: [("=a", a), ("=b", b)],
        inputs:  ("a", 0x8000_001E),
        clobber: ["ecx", "edx"];
    }
}
else  // old-style syntax
{
    asm pure nothrow @nogc {
        "cpuid"
        : "=a" (a), "=b" (b)
        : "a" (0x8000_001E)
        : "ecx", "edx";
    }
}
```

--