cosmopolitan/libc/macros.internal.h

529 lines
12 KiB
C
Raw Normal View History

2020-06-15 14:18:57 +00:00
#ifndef COSMOPOLITAN_LIBC_MACROS_H_
#define COSMOPOLITAN_LIBC_MACROS_H_
#if 0
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § macros
*/
#endif
/**
* @fileoverview Common C preprocessor, assembler, and linker macros.
*/
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 02:25:19 +00:00
#ifdef MAX
#undef MAX
#endif
#ifdef MIN
#undef MIN
#endif
2020-06-15 14:18:57 +00:00
#define TRUE 1
#define FALSE 0
#define IS2POW(X) (!((X) & ((X) - 1)))
#define ROUNDUP(X, K) (((X) + (K) - 1) & -(K))
2023-05-02 02:43:59 +00:00
#define ROUNDDOWN(X, K) ((X) & -(K))
#ifndef __ASSEMBLER__
2023-05-02 02:43:59 +00:00
#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.
2023-05-02 02:43:59 +00:00
#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
2020-06-15 14:18:57 +00:00
#define PASTE(A, B) __PASTE(A, B)
#define STRINGIFY(A) __STRINGIFY(A)
2020-12-24 07:42:56 +00:00
#define EQUIVALENT(X, Y) (__builtin_constant_p((X) == (Y)) && ((X) == (Y)))
2020-06-15 14:18:57 +00:00
#define TYPE_BIT(type) (sizeof(type) * CHAR_BIT)
#define TYPE_SIGNED(type) (((type) - 1) < 0)
2020-06-15 14:18:57 +00:00
#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
2023-05-02 02:43:59 +00:00
// 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
2023-05-02 02:43:59 +00:00
.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
2023-05-02 02:43:59 +00:00
// 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
2023-05-02 02:43:59 +00:00
.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
2023-05-02 20:38:16 +00:00
// 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
2023-05-02 02:43:59 +00:00
// 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
2023-05-02 02:43:59 +00:00
#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__
2022-08-19 00:41:32 +00:00
.poison __BASE_FILE__, -20 # kAsanGlobalUnderrun
#endif
.endm
.macro .overrun
#ifdef __SANITIZE_ADDRESS__
2022-08-19 00:41:32 +00:00
.poison __BASE_FILE__, -21 # kAsanGlobalOverrun
#endif
.endm
2023-05-02 02:43:59 +00:00
#else
.macro .underrun
.endm
.macro .overrun
.endm
// clang-format on
2023-05-02 02:43:59 +00:00
#endif /* __x86_64__ */
2020-06-15 14:18:57 +00:00
#endif /* __ASSEMBLER__ */
#endif /* COSMOPOLITAN_LIBC_MACROS_H_ */