0

I have some very basic C code for which I want to view the equivalent assembly instructions. I'm interested to use zig cc because it can cross compile to M1 ARM, X86, etc. Here is my code:

void variable_sort_2(int length, int *a) {
  if(length == 2){
    if(a[0] > a[1]){
      int temp = a[0];
      a[0] = a[1];
      a[1] = temp;
    }
  }
}
static int a0[] = {};
int main(void){
  variable_sort_2(0, a0);
  return 0;
}

This will successfully do what I want using gcc:

gcc -S sort2.c -o sort2.s

According to gcc --help that will "Only run preprocess and compilation steps."

How to do the equivalent with zig cc?

I tried doing the same -S operation with zig cc but it gives me a much larger output file:

$ zig cc -S sort2.c -o sort2.zig_cc.s
$ gcc -S sort2.c -o sort2.gcc.s
$ ls -l sort2*
-rw-r--r--  1 mee  wheel    236 Jun 13 12:32 sort2.c
-rw-r--r--  1 mee  wheel  27646 Jun 13 16:32 sort2.zig_cc.s
-rw-r--r--  1 mee  wheel   1455 Jun 13 16:33 sort2.gcc.s
$ wc -l *s
  63 sort2.gcc.s
 688 sort2.zig_cc.s

I don't understand assembly well enough to explain why the zig cc file is ten times longer; my assumption is it's linking in system stuff, but I don't know. I see lots of lines like this:

    .byte   17                              ## DW_TAG_compile_unit
    .byte   1                               ## DW_CHILDREN_yes
    .byte   37                              ## DW_AT_producer
    .byte   14                              ## DW_FORM_strp
    .byte   19                              ## DW_AT_language
    .byte   5                               ## DW_FORM_data2

That's lines 300 through 305 of the zig cc -S compiled output on my computer:

$ uname -a
Darwin meee 22.2.0 Darwin Kernel Version 22.2.0: Fri Nov 11 02:08:47 PST 2022; root:xnu-8792.61.2~4/RELEASE_X86_64 x86_64

I created 3 github gists to contain the C code and the two assembly files: sort2.c, sort2.zig_cc.s, sort2.gcc.s:

@ShadowRanger suggested trying -g0 which makes the file smaller, but still not as small as I get with gcc.

$ zig cc -S -g0 sort2.c -o sort2.g0.s
$ ls -l sort2.g0.s
-rw-r--r--  1 mee  wheel  5042 Jun 14 17:40 sort2.g0.s
$ wc -l sort2.g0.s 
     239 sort2.g0.s

And here is a gist for that output file:

Purplejacket
  • 1,808
  • 2
  • 25
  • 43
  • 3
    "I tried doing the same `-S` operation with `zig cc` but it gives me a much larger output file" What is *in* the output file? Wildly varying sizes don't mean it's wrong, it just might have differing levels of commenting, optimization, etc. – ShadowRanger Jun 13 '23 at 23:43
  • @mkrieger1 I am guessing that the larger assembled file has all of the linked system code ... which I am not interested in. – Purplejacket Jun 13 '23 at 23:44
  • @Purplejacket: Actually look at it, rather than guessing? The C runtime is almost always dynamically linked, and actual "system" functions are system calls, which definitely wouldn't be inlined (if it needs a system call, it often can't be done from the user mode code at all); perhaps there are some unnecessary symbols pulled in from headers to bloat it, but inlining the assembly for system libraries would be supremely weird. – ShadowRanger Jun 13 '23 at 23:46
  • you didn't compile with any optimization. And also comparing unstripped binaries are pointless – phuclv Jun 14 '23 at 07:22
  • 2
    All that `## DW_…` stuff is debug information in DWARF format. – datenwolf Jun 14 '23 at 07:27
  • Your `zig` version contains debug information, your `gcc` version doesn't. – Cubic Jun 14 '23 at 07:32
  • Did you compare the sizes of the actual machine code? The size of a source file can vary a lot. – the busybee Jun 14 '23 at 10:17

1 Answers1

0

Looks like your zig cc assembly output has DWARF debugging information in it, which is what is bloating the file size significantly; gcc isn't producing said debug info by default.

I can't find good docs on what you can use to turn off DWARF debug generation for zig cc (other forms of using zig accept -fstrip to avoid generating it; you might try that?), but in short, nothing is wrong, zig cc is just more verbose by default.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • Tried it, am getting: `error: Unknown Clang option: '-fstrip' ` – Purplejacket Jun 14 '23 at 23:59
  • 1
    @Purplejacket: If it's expecting `clang` arguments, `-g0` might at least minimize the debugging symbols. Not clear to me if there's an explicit argument to *disable* all debugging symbols; `clang` normally defaults to debug off, so if `zig cc` is defaulting to on, I'm not sure what the complete "turn it all off" solution is. – ShadowRanger Jun 15 '23 at 00:39
  • — I tried `-g0` and it did approximately halve the output. I updated my answer to link to a gist with the output. – Purplejacket Jun 20 '23 at 02:35