Post AtHgukyjfEL1Bi2R6G by me_@sueden.social
 (DIR) More posts by me_@sueden.social
 (DIR) Post #AtHgueE4lnRwFGA5XU by mpweiher@mastodon.social
       2025-04-20T06:06:12Z
       
       0 likes, 0 repeats
       
       So golang has a machine-independent assembler.  Which is very cool, and yes, machine instruction sets for modern machines are very similar:  ALU instructions, memory load/store, branches.However, it appears that this machine-independent instruction set is not actually used by the compiler's code generator. Instead it has completely machine-specific backends, with all the extra effort that entails.Anybody know why?
       
 (DIR) Post #AtHgufSICQPq3doxKy by me_@sueden.social
       2025-04-20T08:18:56Z
       
       0 likes, 0 repeats
       
       @mpweiher That’s probably a relic of the compiler’s heritage - they were derived from the Plan 9 C compilers, which also used that intermediate assembler format and left instruction selection for the target architecture (mostly) to the linker.
       
 (DIR) Post #AtHgugY08gZnRdV1sG by mpweiher@mastodon.social
       2025-04-20T12:16:42Z
       
       0 likes, 0 repeats
       
       @me_ With that heritage, I would expect the opposite:  that the go compiler *does* use the machine-independent assembler.  If not the ASCII syntax, but the binary representation.But it does not.At least as far as I can tell.As far as I can tell, each of the backends goes directly to the target machine, without the machine-independent assembler.
       
 (DIR) Post #AtHguhbwBXJqk8LgeG by me_@sueden.social
       2025-04-20T13:33:19Z
       
       0 likes, 0 repeats
       
       @mpweiher Maybe that's a misunderstanding. Plan9's C compilers never generated completely machine-independent output.I built some example intermediate assembler outputs generated from this simple and stupid C program using the Plan9 C compiler:int main(void) {  int i,j;  for (i=1; i<42; i++)        if (i%3) j+=i;    return j;}
       
 (DIR) Post #AtHguifAH1Uk0QrmJk by me_@sueden.social
       2025-04-20T13:35:00Z
       
       0 likes, 0 repeats
       
       @mpweiher Using 8c (32-bit x86, uses x86 register names): TEXT    main+0(SB),0,$12 MOVL    j+-8(SP),BX MOVL    $1,CX JMP     ,4(PC) JMP     ,2(PC) JMP     ,12(PC) INCL    ,CX CMPL    CX,$42 JGE     ,-3(PC) MOVL    CX,AX CDQ     , MOVL    $3,.safe+-12(SP) IDIVL   .safe+-12(SP), CMPL    DX,$0 JEQ     ,2(PC) ADDL    CX,BX JMP     ,-12(PC) MOVL    BX,AX RET     , RET     , END     ,
       
 (DIR) Post #AtHgujKHo8O83y6cPg by me_@sueden.social
       2025-04-20T13:35:43Z
       
       0 likes, 0 repeats
       
       @mpweiher With 5c (32-bit ARM): TEXT   main+0(SB),0,$8 MOVW   j-8(SP),R6 MOVW   $1,R1 MOVW   R1,R4 B      ,4(PC) B      ,2(PC) B      ,12(PC) ADD    $1,R4,R4 CMP    $42,R4, BGE    ,-3(PC) MOVW   R4,R2 MOVW   $3,R5 MOD    R5,R2 CMP    $0,R2, MOVW.NE        R4,R1 ADD.NE R4,R6,R3 MOVW.NE        R3,R6 B      ,-12(PC) MOVW   R6,R0 RET    , RET    , END    ,
       
 (DIR) Post #AtHguk1BEehQD0AsGu by me_@sueden.social
       2025-04-20T13:36:34Z
       
       0 likes, 0 repeats
       
       @mpweiher With kc (32-bit SPARC): TEXT   main+0(SB),0,$12 MOVW   j-8(SP),R13 MOVW   $1,R11   JMP    ,4(PC)   JMP    ,2(PC)   JMP    ,10(PC)  ADD    $1,R11,R11 CMP    R11,$42  BGE    ,-3(PC)  MOVW   $3,R12   MOD    R12,R11,R9 CMP    R9,$0    BE     ,2(PC)   ADD    R11,R13,R13 JMP    ,-10(PC) MOVW   R13,R7   RETURN , RETURN , END    ,
       
 (DIR) Post #AtHgukVfPJ5NjYRDn6 by me_@sueden.social
       2025-04-20T13:37:25Z
       
       0 likes, 0 repeats
       
       @mpweiher ...qc (32-bit PPC): TEXT   main+0(SB),0,$8 MOVW   j-8(SP),R9 MOVW   $1,R7 BR     ,4(PC) BR     ,2(PC) BR     ,9(PC) ADD    $1,R7,R7 CMP    R7,$42 BGE    ,-3(PC) MOVW   $3,R8 REMCC  R8,R7,R5 BEQ    ,2(PC) ADD    R7,R9,R9 BR     ,-9(PC) MOVW   R9,R3 RETURN , RETURN , END    ,
       
 (DIR) Post #AtHgukyjfEL1Bi2R6G by me_@sueden.social
       2025-04-20T13:38:43Z
       
       0 likes, 0 repeats
       
       @mpweiher and vc (32-bit MIPS) as the last one, here you see "HI" used as a MIPS-specific register: TEXT   main+0(SB),0,$8 MOVW   j-8(SP),R7 MOVW   $1,R5 JMP    ,4(PC) JMP    ,2(PC) JMP    ,10(PC) ADDU   $1,R5,R5 SGT    $42,R5,R2 BEQ    R2,-3(PC) MOVW   $3,R6 DIV    R6,R5, MOVW   HI,R3 BEQ    R3,2(PC) ADDU   R5,R7,R7 JMP    ,-10(PC) MOVW   R7,R1 RET    , RET    , END    ,
       
 (DIR) Post #AtHgulYXW6ygykn1uK by me_@sueden.social
       2025-04-20T13:47:47Z
       
       1 likes, 0 repeats
       
       @mpweiher All of these are superficially very similar, but there are already some optimizations done in the compiler stage, e.g. using "INC" on x86 instead of adding 1 on the RISC architectures. But this is not a higher-level representation e.g. on the level of LLVM IR. Some stuff is unified, "such as left-to-right assignment order for instruction operands and the synthesis of macro instructions such as MOVE" (from [1]).[1] https://9p.io/sys/doc/asm.html
       
 (DIR) Post #AtHguwlhpV2tkm2CSO by me_@sueden.social
       2025-04-20T13:49:06Z
       
       0 likes, 0 repeats
       
       @mpweiher There's an example of the abstraction level given in [2]:"For example, on the 68020 the object file may specify a MOVE instruction but the loader will decide just which variant of the MOVE instruction — MOVE immediate, MOVE quick, MOVE address, etc. — is most efficient."Indeed, it's pretty weird at first sight...[2] https://9p.io/sys/doc/comp.html