Thread overview
Question about inline assembly in LDC
Aug 21, 2023
Cecil Ward
Aug 21, 2023
kinke
Aug 21, 2023
Cecil Ward
Aug 21, 2023
Cecil Ward
Aug 22, 2023
kinke
Aug 22, 2023
Cecil Ward
August 21, 2023
When I try a certain snippet of D containing GCC-style inline x86 asm in LDC, it fails at compile-time with an error message. The code works fine in GDC though. Can anyone help me understand what’s going wrong.

the error message is:
     source>(231):2:15: error: unknown token in expression
        prefetcht0  [%rdi]

Note the % before the rdi, which shouldn’t be there and isn’t when I build under GDC.

The whole thing is:

void prefetcht0( in void * p ) @nogc nothrow @trusted
/* (temporal data)—prefetch data into all levels of the cache hierarchy.
*/	{
	asm nothrow @nogc {
		".intel_syntax"               ~ "\n\t" ~
		
	        "prefetcht0  [%0]"          ~ "\n\t" ~
		
	        ".att_syntax"                 ~ "\n"
	        : /* no outputs */
	        :  "r" ( p )
	        :
		;
	        }
	}


August 21, 2023
LDC doesn't support the Intel syntax in GDC-style inline asm, AT&T only. [We'd have to tell LLVM that an *entire* GDC-style inline asm statement is in Intel syntax.]

The Intel syntax is only supported in DMD-style inline asm.
August 21, 2023
On Monday, 21 August 2023 at 16:38:29 UTC, kinke wrote:
> LDC doesn't support the Intel syntax in GDC-style inline asm, AT&T only. [We'd have to tell LLVM that an *entire* GDC-style inline asm statement is in Intel syntax.]
>
> The Intel syntax is only supported in DMD-style inline asm.

Ah, shame. It would be good if LDC gave an error message when it sees the intel syntax directive, as its error messages in this situation seem to be a bit random now.


August 21, 2023
On Monday, 21 August 2023 at 16:38:29 UTC, kinke wrote:
> LDC doesn't support the Intel syntax in GDC-style inline asm, AT&T only. [We'd have to tell LLVM that an *entire* GDC-style inline asm statement is in Intel syntax.]
>
> The Intel syntax is only supported in DMD-style inline asm.

Does that mean that in principle LDC could understand intel-style syntax but only if it knew in advance which type of syntax was being used in the _whole_ thing, ie as opposed to being told too late by a .intel_syntax directive? To get interoperability between GDC and LDC then perhaps the two compilers could have an external ‘dialect’ parameter that is available before we get into the statements-body. Failing that, LDC would need to look ahead for the likes of a .intel_syntax directive with an auto detect-type initial regex. Seeing as presumably no one ever switches dialects other than at the start, then that would certainly work well. I’m very good at proposing work for others. :-)

August 22, 2023
On Monday, 21 August 2023 at 23:18:50 UTC, Cecil Ward wrote:
> Does that mean that in principle LDC could understand intel-style syntax but only if it knew in advance which type of syntax was being used in the _whole_ thing, ie as opposed to being told too late by a .intel_syntax directive? To get interoperability between GDC and LDC then perhaps the two compilers could have an external ‘dialect’ parameter that is available before we get into the statements-body. Failing that, LDC would need to look ahead for the likes of a .intel_syntax directive with an auto detect-type initial regex. Seeing as presumably no one ever switches dialects other than at the start, then that would certainly work well. I’m very good at proposing work for others. :-)

Heh :D - sure, could be done, but don't count on me. AFAIK, 2 different asm dialects only exist for x86[_64], one of many targets, so adding support for such an inherited legacy mess is not on my TODO list. And by the looks of it, you're an asm afficionado, but I don't recommend working at such a low level (in D) unless it can't be done otherwise (very few cases, druntime has some examples). Some reasons: readability, portability, poor compiler support for troubleshooting as you've seen (asm fragments are mostly a black box, for both LDC and the main LLVM passes), and premature optimization (asm fragments are a black box for the LLVM optimization passes, so using intrinsics and inline IR is much better, not just for portability to different archs, but also to let the optimizer know what you're doing).
August 22, 2023
On Tuesday, 22 August 2023 at 12:24:41 UTC, kinke wrote:
> On Monday, 21 August 2023 at 23:18:50 UTC, Cecil Ward wrote:
>> Does that mean that in principle LDC could understand intel-style syntax but only if it knew in advance which type of syntax was being used in the _whole_ thing, ie as opposed to being told too late by a .intel_syntax directive? To get interoperability between GDC and LDC then perhaps the two compilers could have an external ‘dialect’ parameter that is available before we get into the statements-body. Failing that, LDC would need to look ahead for the likes of a .intel_syntax directive with an auto detect-type initial regex. Seeing as presumably no one ever switches dialects other than at the start, then that would certainly work well. I’m very good at proposing work for others. :-)
>
> Heh :D - sure, could be done, but don't count on me. AFAIK, 2 different asm dialects only exist for x86[_64], one of many targets, so adding support for such an inherited legacy mess is not on my TODO list. And by the looks of it, you're an asm afficionado, but I don't recommend working at such a low level (in D) unless it can't be done otherwise (very few cases, druntime has some examples). Some reasons: readability, portability, poor compiler support for troubleshooting as you've seen (asm fragments are mostly a black box, for both LDC and the main LLVM passes), and premature optimization (asm fragments are a black box for the LLVM optimization passes, so using intrinsics and inline IR is much better, not just for portability to different archs, but also to let the optimizer know what you're doing).

I’m aware of the disadvantages. I would never recommend using inline asm unless it’s either essential or it gives otherwise unachievable performance benefits. I’m writing library functions to make available instructions that you cannot access without wrappers. I would never recommend using inline asm unless it’s either essential or it gives otherwise unachievable performance benefits. I’m writing libIt’s also a D learning project for me. I was a very experienced professional asm programmer, a long long time ago, before compilers became way too good. The GDC/LDC implementation is so fantastically efficient, unlike the DMD inline asm, that you can get literally zero-overhead asm fully integrated into your code. It can even adapt an instruction’s operands to handle memory accesses directly without needing to make use of a register as an intermediate location where applicable. LDC and GDC generate code with fs:addr operands when the argument is a static in thread-local-storage. To me that’s amazing sophistication from the compilers. In my little project, I give pure D equivalents when I have not been able to offer instructions for whatever the CPU is.

The prefetch case is one perfect example. Only experts should use such a thing and then D cannot achieve the benefits on offer without the CPU’s special instructions. Also using it and getting the placement and usage wrong will certainly make performance worse, so measurement before and after is needed to check that you’re doing it right. And even then, changes to the code can mess things up; the performance benefits are very fragile.

I do wish that D could handle Intel syntax as the ATT stuff hurts my brain after years of doing things the standard way for that processor. Is ARM code going to have the operands backwards way round? (Actually I think the ATT order is preferable as it reads better, but it’s down to what you have spent years doing and down to having to read the CPUs’ documentation in a different syntax.)

I recently wrote something to fix the problem of LDC not being able to handle named asm arguments. I was trying to avoid conditional compilation and duplicated code form GDC and LDC, but now I find that’s only one problem in the way of success, the ATT-only thing being much worse.

Does GCC for C handle Intel syntax inline asm?