cosmopolitan/libc/macros.internal.h
Justine Tunney ff77f2a6af
Make improvements
- This change fixes a bug that allowed unbuffered printf() output (to
  streams like stderr) to be truncated. This regression was introduced
  some time between now and the last release.

- POSIX specifies all functions as thread safe by default. This change
  works towards cleaning up our use of the @threadsafe / @threadunsafe
  documentation annotations to reflect that. The goal is (1) to use
  @threadunsafe to document functions which POSIX say needn't be thread
  safe, and (2) use @threadsafe to document functions that we chose to
  implement as thread safe even though POSIX didn't mandate it.

- Tidy up the clock_gettime() implementation. We're now trying out a
  cleaner approach to system call support that aims to maintain the
  Linux errno convention as long as possible. This also fixes bugs that
  existed previously, where the vDSO errno wasn't being translated
  properly. The gettimeofday() system call is now a wrapper for
  clock_gettime(), which reduces bloat in apps that use both.

- The recently-introduced improvements to the execute bit on Windows has
  had bugs fixed. access(X_OK) on a directory on Windows now succeeds.
  fstat() will now perform the MZ/#! ReadFile() operation correctly.

- Windows.h is no longer included in libc/isystem/, because it confused
  PCRE's build system into thinking Cosmopolitan is a WIN32 platform.
  Cosmo's Windows.h polyfill was never even really that good, since it
  only defines a subset of the subset of WIN32 APIs that Cosmo defines.

- The setlongerjmp() / longerjmp() APIs are removed. While they're nice
  APIs that are superior to the standardized setjmp / longjmp functions,
  they weren't superior enough to not be dead code in the monorepo. If
  you use these APIs, please file an issue and they'll be restored.

- The .com appending magic has now been removed from APE Loader.
2023-10-03 06:17:16 -07:00

528 lines
12 KiB
C

#ifndef COSMOPOLITAN_LIBC_MACROS_H_
#define COSMOPOLITAN_LIBC_MACROS_H_
#if 0
/*───────────────────────────────────────────────────────────────────────────│─╗
│ cosmopolitan § macros ─╬─│┼
╚────────────────────────────────────────────────────────────────────────────│*/
#endif
/**
* @fileoverview Common C preprocessor, assembler, and linker macros.
*/
#ifdef MAX
#undef MAX
#endif
#ifdef MIN
#undef MIN
#endif
#define TRUE 1
#define FALSE 0
#define IS2POW(X) (!((X) & ((X)-1)))
#define ROUNDUP(X, K) (((X) + (K)-1) & -(K))
#define ROUNDDOWN(X, K) ((X) & -(K))
#ifndef __ASSEMBLER__
#define ABS(X) ((X) >= 0 ? (X) : -(X))
#define MIN(X, Y) ((Y) > (X) ? (X) : (Y))
#define MAX(X, Y) ((Y) < (X) ? (X) : (Y))
#else
// The GNU assembler does not grok the ?: ternary operator; furthermore,
// boolean expressions yield -1 and 0 for "true" and "false", not 1 and 0.
#define __MAPBOOL(P) (!!(P) / (!!(P) + !(P)))
#define __IFELSE(P, X, Y) (__MAPBOOL(P) * (X) + __MAPBOOL(!(P)) * (Y))
#define MIN(X, Y) (__IFELSE((Y) > (X), (X), (Y)))
#define MAX(X, Y) (__IFELSE((Y) < (X), (X), (Y)))
#endif
#define PASTE(A, B) __PASTE(A, B)
#define STRINGIFY(A) __STRINGIFY(A)
#define EQUIVALENT(X, Y) (__builtin_constant_p((X) == (Y)) && ((X) == (Y)))
#define TYPE_BIT(type) (sizeof(type) * CHAR_BIT)
#define TYPE_SIGNED(type) (((type)-1) < 0)
#define TYPE_INTEGRAL(type) (((type)0.5) != 0.5)
#define ARRAYLEN(A) \
((sizeof(A) / sizeof(*(A))) / ((unsigned)!(sizeof(A) % sizeof(*(A)))))
#define __STRINGIFY(A) #A
#define __PASTE(A, B) A##B
#ifdef __ASSEMBLER__
// clang-format off
// Ends function definition.
// @cost saves 1-3 lines of code
.macro .endfn name:req bnd vis
.size "\name",.-"\name"
.type "\name",@function
.ifnb \bnd
.\bnd "\name"
.endif
.ifnb \vis
.\vis "\name"
.endif
.endm
// Ends variable definition.
// @cost saves 1-3 lines of code
.macro .endobj name:req bnd vis
.size "\name",.-"\name"
.type "\name",@object
.ifnb \bnd
.\bnd "\name"
.endif
.ifnb \vis
.\vis "\name"
.endif
.endm
// Shorthand notation for widely-acknowledged sections.
.macro .rodata
.section .rodata,"a",@progbits
.endm
.macro .init
.section .init,"ax",@progbits
.endm
.macro .real
.section .text.real,"ax",@progbits
.endm
.macro .head
.section .text.head,"ax",@progbits
.endm
.macro .text.startup
.section .text.startup,"ax",@progbits
.endm
.macro .text.exit
.section .text.exit,"ax",@progbits
.endm
.macro .firstclass
.section .text.hot,"ax",@progbits
.endm
.macro .text.unlikely
.section .text.unlikely,"ax",@progbits
.endm
.macro .text.likely
.section .text.hot,"ax",@progbits
.endm
.macro .text.modernity
.section .text.modernity,"ax",@progbits
.balign 16
.endm
.macro .text.antiquity
.section .text.antiquity,"ax",@progbits
.endm
.macro .text.hot
.section .text.hot,"ax",@progbits
.endm
.macro .preinit_array
.section .preinit_array,"a",@init_array
.endm
.macro .init_array
.section .init_array,"a",@init_array
.endm
.macro .text.windows
.section .text.windows,"ax",@progbits
.endm
// Mergeable NUL-terminated UTF-8 string constant section.
//
// @note linker de-dupes C strings here across whole compile
// @note therefore item/values are reordered w.r.t. link order
// @note therefore no section relative addressing
.macro .rodata.str1.1
.section .rodata.str1.1,"aMS",@progbits,1
.balign 1
.endm
// Locates unreferenced code invulnerable to --gc-sections.
.macro .keep.text
.section .keep.text,"ax",@progbits
.endm
// Flags code as only allowed for testing purposes.
.macro .testonly
.section .test,"ax",@progbits
.endm
// Makes code runnable while code morphing.
.macro .privileged
.section .privileged,"ax",@progbits
.endm
// Declares alternative implementation of function.
// @param implement e.g. tinymath_pow
// @param canonical e.g. pow
.macro .alias implement:req canonical:req
.equ \canonical,\implement
.weak \canonical
.endm
#ifdef __aarch64__
.macro jmp dest:req
b \dest
.endm
#endif
// Pulls unrelated module into linkage.
//
// In order for this technique to work with --gc-sections, another
// module somewhere might want to weakly reference whats yoinked.
.macro .yoink symbol:req
.section .yoink
#ifdef __x86_64__
nopl "\symbol"(%rip)
#elif defined(__aarch64__)
b "\symbol"
#endif
.previous
.endm
// Begins definition of frameless function that calls no functions.
.macro .leafprologue
#if !(defined(TINY) && !defined(__PG__))
#ifdef __x86_64__
push %rbp
mov %rsp,%rbp
#elif defined(__aarch64__)
stp x29,x30,[sp,#-16]!
mov x29,sp
#endif
#endif
.endm
// Ends definition of frameless function that calls no functions.
.macro .leafepilogue
#if !(defined(TINY) && !defined(__PG__))
#ifdef __x86_64__
pop %rbp
#elif defined(__aarch64__)
ldp x29,x30,[sp],#16
#endif
#endif
ret
.endm
// Documents unreachable assembly code.
.macro .unreachable
#if !defined(NDEBUG) && defined(__x86_64__)
ud2 // crash if contract is broken
#elif !defined(NDEBUG) && defined(__aarch64__)
brk #1000
#elif defined(__FNO_OMIT_FRAME_POINTER__) && defined(__x86_64__)
nop // avoid noreturn tail call backtrace ambiguity
#endif
.endm
// Embeds Fixed-Width Zero-Padded String.
// @note .fxstr is better
.macro .ascin str:req fieldsize:req
1347: .ascii "\str"
.org 1347b+\fieldsize,0x00
.endm
// Inserts --ftrace pre-prologue.
// This goes immediately before the function symbol.
// @see .ftrace2
.macro .ftrace1
#ifdef FTRACE
#ifdef __x86_64__
.rept 9
nop
.endr
#elif defined(__aarch64__)
.rept 6
nop
.endr
#endif /* __x86_64__ */
#endif /* FTRACE */
.endm
// Inserts --ftrace prologue.
// This goes immediately after the function symbol.
// @see .ftrace1
.macro .ftrace2
#ifdef FTRACE
#ifdef __x86_64__
xchg %ax,%ax
#elif defined(__aarch64__)
nop
#endif /* __x86_64__ */
#endif /* FTRACE */
.endm
#ifdef __x86_64__
#if __MNO_VZEROUPPER__ + 0
#define vzeroupper
#endif
// Mergeable numeric constant sections.
//
// @note linker de-dupes item/values across whole compile
// @note therefore item/values are reordered w.r.t. link order
// @note therefore no section relative addressing
.macro .rodata.cst4
.section .rodata.cst4,"aM",@progbits,4
.balign 4
.endm
.macro .rodata.cst8
.section .rodata.cst8,"aM",@progbits,8
.balign 8
.endm
.macro .rodata.cst16
.section .rodata.cst16,"aM",@progbits,16
.balign 16
.endm
.macro .rodata.cst32
.section .rodata.cst32,"aM",@progbits,32
.balign 32
.endm
.macro .rodata.cst64
.section .rodata.cst64,"aM",@progbits,64
.balign 64
.endm
.macro .tdata
.section .tdata,"awT",@progbits
.balign 4
.endm
.macro .tbss
.section .tdata,"awT",@nobits
.balign 4
.endm
// Loads address of errno into %rcx
.macro .errno
call __errno_location
.endm
// Post-Initialization Read-Only (PIRO) BSS section.
// @param ss is an optional string, for control image locality
.macro .piro ss
.ifnb \ss
.section .piro.sort.bss.\ss,"aw",@nobits
.else
.section .piro.bss,"aw",@nobits
.endif
.endm
// Helpers for Cosmopolitan _init() amalgamation magic.
// @param name should be consistent across macros for a module
// @see libc/runtime/_init.S
.macro .initro number:req name:req
.section ".initro.\number\().\name","a",@progbits
.balign 8
.endm
.macro .initbss number:req name:req
.section ".piro.bss.init.2.\number\().\name","aw",@nobits
.balign 8
.endm
.macro .init.start number:req name:req
.section ".init.\number\().\name","ax",@progbits
"\name":
.endm
.macro .init.end number:req name:req bnd=globl vis
.endfn "\name",\bnd,\vis
.previous
.endm
// LOOP Instruction Replacement.
.macro .loop label:req
.byte 0x83
.byte 0xe9
.byte 0x01
jnz \label
.endm
// Pushes CONSTEXPR ∈ [-128,127].
// @note assembler is wrong for non-literal constexprs
.macro pushb x:req
.byte 0x6a
.byte \x
.endm
// Sign-extends CONSTEXPR ∈ [-128,127] to REGISTER.
// @cost ≥1 cycles, -2 bytes
.macro pushpop constexpr:req register:req
pushb \constexpr
pop \register
.endm
// Moves REGISTER to REGISTER.
// @cost ≥1 cycles, -1 REX byte
.macro movpp src:req dest:req
push \src
pop \dest
.endm
// Embeds fixed-width zero-filled string table.
// @note zero-padded ≠ nul-terminated
.macro .fxstr width head rest:vararg
.ifnb \head
0: .ascii "\head"
.org 0b+\width
.fxstr \width,\rest
.endif
.endm
// Marks symbols as object en-masse.
// @note zero-padded ≠ nul-terminated
.macro .object symbol rest:vararg
.ifnb \symbol
.type \symbol,@object
.object \rest
.endif
.endm
// Pads function prologue unconditionally for runtime hooking.
// @cost ≥0.3 cycles, 5 bytes
// @see .ftrace1
.macro .hookable
.byte 0x0f
.byte 0x1f
.byte 0x44
.byte 0x00
.byte 0x00
.endm
// Puts initialized data in uninitialized data section.
.macro .bsdata name:req expr:req bnd vis
.section ".initbss.300._init_\name","aw",@nobits
"\name":
.quad 0
.endobj "\name",\bnd,\vis
.previous
.section ".initro.300._init_\name","a",@progbits
.quad \expr
.previous
.section ".init.300._init_\name","ax",@progbits
"_init_\name":
movsq
.endfn "_init_\name"
.previous
.endm
// ICE Breakpoint.
// Modern gas forgot this but objdump knows
// @mode long,legacy,real
.macro icebp
.byte 0xF1
.endm
.macro int1
icebp
.endm
// Sets breakpoint for software debugger.
// @mode long,legacy,real
.macro .softicebp
.byte 0x53 # push bx
.byte 0x87 # xchg bx,bx (bochs breakpoint)
.byte 0xdb
.byte 0x5b # pop bx
.byte 0x66 # xchg ax,ax (microsoft breakpoint)
.byte 0x90
int3 # gdb breakpoint
.endm
// Assembles Intel Official 4-Byte NOP.
.macro fatnop4
.byte 0x0f,0x1f,0x40,0x00
.endm
// Calls Windows function.
//
// @param cx,dx,r8,r9,stack
// @return ax
// @clob ax,cx,dx,r8-r11
.macro ntcall symbol:req
sub $32,%rsp
call *\symbol(%rip)
add $32,%rsp
.endm
// Custom emulator instruction for bottom stack frame.
.macro bofram endfunc:req
.byte 0x0f,0x1f,0105,\endfunc-. # nopl disp8(%rbp)
.endm
// Good alignment for functions where alignment actually helps.
// @note 16-byte
.macro .alignfunc
#ifndef __OPTIMIZE_SIZE__
.p2align 4
#endif
.endm
// TODO(jart): delete
// Loads Effective Address
// Supporting security blankets
.macro ezlea symbol:req reg:req
#if __pic__ + __pie__ + __code_model_medium__ + __code_model_large__ + 0 > 1
// lea \symbol(%rip),%r\reg
mov $\symbol,%e\reg
#else
mov $\symbol,%e\reg
#endif
.endm
// Loads address of linktime mergeable string literal into register.
.macro loadstr text:req reg:req regsz bias=0
.section .rodata.str1.1,"aSM",@progbits,1
.type .Lstr\@,@object
.Lstr\@: .asciz "\text"
.Lstr\@.size = .-.Lstr\@ - 1
.size .Lstr\@,.-.Lstr\@
.previous
ezlea .Lstr\@,\reg
.ifnb \regsz
#ifdef __OPTIMIZE_SIZE__
.if .Lstr\@.size + \bias < 128
pushpop .Lstr\@.size,%r\regsz
.else
mov $.Lstr\@.size,%e\regsz
.endif
#else
mov $.Lstr\@.size,%e\regsz
#endif
.endif
.endm
.macro .poison name:req kind:req
#ifdef __SANITIZE_ADDRESS__
2323: .quad 0
.init.start 304,"_init_\name\()_poison_\@"
push %rdi
push %rsi
ezlea 2323b,di
mov $8,%esi
mov $\kind,%edx
call __asan_poison
pop %rsi
pop %rdi
.init.end 304,"_init_\name\()_poison_\@"
#endif
.endm
.macro .underrun
#ifdef __SANITIZE_ADDRESS__
.poison __BASE_FILE__, -20 # kAsanGlobalUnderrun
#endif
.endm
.macro .overrun
#ifdef __SANITIZE_ADDRESS__
.poison __BASE_FILE__, -21 # kAsanGlobalOverrun
#endif
.endm
#else
.macro .underrun
.endm
.macro .overrun
.endm
// clang-format on
#endif /* __x86_64__ */
#endif /* __ASSEMBLER__ */
#endif /* COSMOPOLITAN_LIBC_MACROS_H_ */