Bug 20594 – [GCC ASM] Should the asm { } syntax be modernized for D2?

Status
NEW
Severity
enhancement
Priority
P4
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2020-02-22T12:57:18Z
Last change time
2024-12-13T19:07:10Z
Assigned to
Iain Buclaw
Creator
Iain Buclaw
Moved to GitHub: dmd#19666 →

Comments

Comment #0 by ibuclaw — 2020-02-22T12:57:18Z
The current syntax of the `asm { }` body follows the gcc extended style as documented in https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html This has been the case in gdc long before D1 v1.001 was released. This has been argued that it rather counters what is considered tasteful D style code. Consider the existing style: asm pure nothrow @nogc { "cmoveq %1, %2, %[result]" // insn : [result] "=r" (result) // outputs : "r" (test), "r" (newvalue), // inputs "[result]" (oldvalue) : "memory"; // clobbers } Then consider what that would look like if output/inputs were a hash, and clobbers an array: asm pure nothrow @nogc { "cmoveq %1, %2, %[result]" // insn : [result = "=r": result] // outputs : ["r": test, "r": newvalue, // inputs "[result]": oldvalue] : ["memory"]; // clobbers } 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 } --- Some examples of what this might look like in other cases: asm nothrow @nogc { "xchg %h0, %b0", ["+a": num]; } asm nothrow @nogc { "mtfsf 255,%1", ["=X": sum], ["f": fpenv]; } asm nothrow @nogc { "", [], [], ["memory"]; // volatile barrier. } asm pure nothrow @nogc { "bsfl %1,%0", ["=r": dwRes], ["r": dwSomeValue], ["cc"]; } asm nothrow @nogc { "rdtsc\n\t" "shl $32, %%rdx\n\t" "or %%rdx, %0", ["=a": msr], [], ["rdx"]; } asm nothrow @nogc { /* lots of asm here */ "#n=%1 ap=%8=%12 lda=%13 x=%7=%10 y=%0=%2 alpha=%9 o16=%11\n" "#a0=%3 a1=%4 a2=%5 a3=%6", [ // outputs "+m": *cast(double[10]*) y, "+&r": n, // 1 "+b": y, // 2 "=b": a0, // 3 "=&b": a1, // 4 "=&b": a2, // 5 "=&b": a3, // 6 ], [ // inputs "m": *cast(double[10]*) x, "m": *cast(double*) ap, "d": alpha, // 9 "r": x, // 10 "b": 16, // 11 "3": ap, // 12 "4": lda, // 13 ], [ // clobbers "cr0", "vs32","vs33","vs34","vs35","vs36","vs37", "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47" ]; } int frob(int x) { int y; asm { "frob %%r5, %1; jc %l[error]; mov (%2), %%r5", [/* No outputs. */], ["r": x, "r": &y], ["r5", "memory"], [Lerror]; } return y; Lerror: return -1; } 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]; } }
Comment #1 by ibuclaw — 2020-07-16T15:22:16Z
(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]; } }
Comment #2 by ibuclaw — 2023-02-15T20:23:31Z
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"; } } ```
Comment #3 by robert.schadek — 2024-12-13T19:07:10Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19666 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB