Is unchecked assembly possible?

I'm trying to compile my code with -emit=llvm-ir, and i want to be able to put in assembly statements that are not actually valid assembly for any existing llvm/rust architecture, so i can use a custom backend for it. unfortunately, rust's asm! and global_asm! macros both check that the assembly is valid for the target architecture, and my target architecture doesnt exist in rust. Is there a way to have it just put the contents of the inline assembly macro into the output .ll file

I believe LLVM always parses inline asm. Clang doesn't accept invalid instructions in inline asm either. GCC on the other hand is completely fine with it as it doesn't have a builtin assembler.

LLVM doesn't always parse inline asm, clang will allow anything in a c asm statement if you use the -S and -emit-llvm options

When using -emit-llvm that makes sense as compilation stops long before anything is done with assembly. For -S however I'm still getting an error from clang:

$ echo 'void foo() { asm ("bar"); }' | clang -x c -S -
<stdin>:1:19: error: invalid instruction mnemonic 'bar'
void foo() { asm ("bar"); }
                  ^
<inline asm>:1:2: note: instantiated into assembly here
        bar
        ^~~
1 error generated.

i was using both arguments at the same time, and it outputted

  call void asm sideeffect "bar"

with a little bit of junk afterwards

this issue seems to be related, but it doesnt really give a clear answer. Custom CPU instructions with `asm!`
edit: the .insn directive is marked as a solution, but as far as i can tell that only exists in risc-v and maybe mips

Strange. Works fine for me.

Ah, you are using -no-integrated-as. Rustc removed support for it's equivalent years ago as no target needed it anymore and it did make some already non-trivial code even more complex.

Well… without -no-integrated-as LLVM just emits the machine code directly, not text to be interpreted by assembler, thus it's hard to imagine how unchecked asm may work in that setup.

this works for me without -no-integrated-as to emit IR, and i know rust does support emitting IR with -emit=llvm-ir
edit: link to the -no-integrated-as issue

1 Like

I just found a solution to my problem, using cargo rustc -- --emit=llvm-ir with invalid assembly does cause the compiler to error and not finish, but the .ll files i'm looking for are still generated before checking the assembly is valid in target/<debug or release>/deps/<long name>.ll

I assumed that assembly was being checked with the rest of the code, and therefore the files wouldn't be generated, but i was wrong, and i can still extract the .ll file i need

Not if you pass -S. -S is what causes assembly to be output rather than machinecode. -no-integrated-as causes LLVM to use an external assembler rather than it's builtin assembly parsing and (without -S) machine code emission.