I’m working on building a custom language frontend for gcc and I’ve got basic operations like math and memory access working fine. However, I’m stuck on how to properly handle inline assembly instructions that need to be architecture specific.
What’s the right approach to pass assembly code from my custom language to gcc when it depends on the target architecture?
Here’s what I’m trying to achieve:
#ifdef TARGET_X86
simd_mul(reg_a, reg_b);
simd_add(reg_a, reg_b);
port_write(mem_addr, data_val);
#endif
I need this to generate proper inline assembly like:
// Using AT&T syntax for port_write:
out %data_val_register, %port_address
Basically I just need to emit inline assembly from my frontend. Any guidance on the gcc internals for this?
I ran into the same issue when building my custom frontend. Here’s what worked for me: use gcc’s inline assembly infrastructure through GIMPLE representation. Create GIMPLE_ASM statements during your frontend’s lowering phase. Define your arch-specific operations as built-in functions that map to inline assembly templates. For simd_mul, make a built-in that expands to SSE/AVX on x86 or NEON on ARM. GCC’s backend handles register allocation and instruction selection automatically. You’ll need to hook into target-specific macros and use the existing inline assembly constraint system. This keeps things portable while giving you the low-level control you need.
Interesting approach! Why not use the builtin_md patterns instead? Are you targeting multiple architectures or just sticking with x86? Also curious how other frontends like Rust handle this - do they go through GIMPLE or take a different route?
check out builtin_decl in your frontend - that’s how you register custom assembly builtins. I did smthing similar and created wrapper functions that call _builtin_ia32* intrinsics for x86. gcc already has tons of these for simd ops, so you dont need to write raw assembly templates. way easier than dealing with gimple_asm directly.