aklomp / base64

Fast Base64 stream encoder/decoder in C99, with SIMD acceleration
BSD 2-Clause "Simplified" License
865 stars 162 forks source link

NEON64: enc: ASM build fails on gcc with dd7a2b5f31 #99

Closed mscdex closed 2 years ago

mscdex commented 2 years ago

It looks like at least gcc fails now with BASE64_NEON64_USE_ASM set and -O0. Example output:

18:45:00 In file included from ../deps/base64/base64/lib/arch/neon64/codec.c:63:
18:45:00 ../deps/base64/base64/lib/arch/neon64/enc_loop_asm.c:11:36: error: invalid character ' ' in raw string delimiter
18:45:00   "ld3 {"P".16b, "Q".16b, "R".16b}, [%[src]], #48 \n\t"
18:45:00                            ^         
18:45:00 ../deps/base64/base64/lib/arch/neon64/enc_loop_asm.c:18:28: error: invalid character ' ' in raw string delimiter
18:45:00   "ushr %[t2].16b, "R".16b,   #6         \n\t" \
18:45:00                     ^        
18:45:00 ../deps/base64/base64/lib/arch/neon64/enc_loop_asm.c:23:28: error: invalid character ' ' in raw string delimiter
18:45:00   "and  %[t3].16b, "R".16b,   %[n63].16b \n\t"
18:45:00                     ^        
18:45:00 ../deps/base64/base64/lib/arch/neon64/enc_loop_asm.c:31:16: error: invalid character ' ' in raw string delimiter
18:45:00   "tbl "R".16b, {v8.16b-v11.16b}, %[t2].16b \n\t" \
18:45:00         ^        
18:45:00 ../deps/base64/base64/lib/arch/neon64/enc_loop_asm.c:37:35: error: invalid character ' ' in raw string delimiter
18:45:00   "st4 {"P".16b, "Q".16b, "R".16b, "S".16b}, [%[dst]], #64 \n\t"
18:45:00                            ^        
18:45:00 ../deps/base64/base64/lib/arch/neon64/enc_loop_asm.c: In function 'enc_loop_neon64':
18:45:00 ../deps/base64/base64/lib/arch/neon64/enc_loop_asm.c:11:27: error: stray 'R' in program
18:45:00   "ld3 {"P".16b, "Q".16b, "R".16b}, [%[src]], #48 \n\t"
18:45:00                            ^
18:45:00 ../deps/base64/base64/lib/arch/neon64/enc_loop_asm.c:65:2: note: in expansion of macro 'LOAD'
18:45:00   LOAD("v2", "v3", "v4") \
18:45:00   ^~~~
18:45:00 ../deps/base64/base64/lib/arch/neon64/enc_loop_asm.c:114:10: note: in expansion of macro 'ROUND_A_FIRST'
18:45:00    "    " ROUND_A_FIRST()
18:45:00           ^~~~~~~~~~~~~
18:45:00 ../deps/base64/base64/lib/arch/neon64/enc_loop_asm.c:11:28: error: expected ':' or ')' before string constant
18:45:00   "ld3 {"P".16b, "Q".16b, "R".16b}, [%[src]], #48 \n\t"
18:45:00                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~
18:45:00 ../deps/base64/base64/lib/arch/neon64/enc_loop_asm.c:65:2: note: in expansion of macro 'LOAD'
18:45:00   LOAD("v2", "v3", "v4") \
18:45:00   ^~~~
18:45:00 ../deps/base64/base64/lib/arch/neon64/enc_loop_asm.c:114:10: note: in expansion of macro 'ROUND_A_FIRST'
18:45:00    "    " ROUND_A_FIRST()
18:45:00           ^~~~~~~~~~~~~

and a bunch of similar "stray 'R'" errors after that.

clang compiles without errors however.

mscdex commented 2 years ago

It looks like the character "R" is some kind of reserved token that I'm blanking on at the moment. Changing the macro variables to start with "A" instead of "P" in all of the macro functions fixes things.

mscdex commented 2 years ago

Ah ok it seems that "R" is a valid string literal prefix much like "L" can be for wide strings. Apparently there are others that I was unaware of like "U"/"u" and "u8" according to here.

aklomp commented 2 years ago

I think this might be a side effect of compiling this C library as C++ code. We're being hit by a language incompatibility.

In the C world, this would be gross behavior by GCC, because the R variable is only supposed to be seen by the preprocessor. And the preprocessor is only supposed to do textual substitution. The R is never supposed to be visible to the compiler, at all, ever. So through that lens, this bug makes no sense and seems bizarre.

In C++ it's apparently acceptable?

Anyway, thanks for finding this bug/incompatibility. I think your PR is the right fix.