| xf.li | bdd93d5 | 2023-05-12 07:10:14 -0700 | [diff] [blame] | 1 | /* Assembler macros for ARM. | 
 | 2 |    Copyright (C) 1997-2016 Free Software Foundation, Inc. | 
 | 3 |    This file is part of the GNU C Library. | 
 | 4 |  | 
 | 5 |    The GNU C Library is free software; you can redistribute it and/or | 
 | 6 |    modify it under the terms of the GNU Lesser General Public | 
 | 7 |    License as published by the Free Software Foundation; either | 
 | 8 |    version 2.1 of the License, or (at your option) any later version. | 
 | 9 |  | 
 | 10 |    The GNU C Library is distributed in the hope that it will be useful, | 
 | 11 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 12 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 | 13 |    Lesser General Public License for more details. | 
 | 14 |  | 
 | 15 |    You should have received a copy of the GNU Lesser General Public | 
 | 16 |    License along with the GNU C Library.  If not, see | 
 | 17 |    <http://www.gnu.org/licenses/>.  */ | 
 | 18 |  | 
 | 19 | #include <sysdeps/generic/sysdep.h> | 
 | 20 | #include <features.h> | 
 | 21 |  | 
 | 22 | #ifndef __ASSEMBLER__ | 
 | 23 | # include <stdint.h> | 
 | 24 | #else | 
 | 25 | # include <arm-features.h> | 
 | 26 | #endif | 
 | 27 |  | 
 | 28 | /* The __ARM_ARCH define is provided by gcc 4.8.  Construct it otherwise.  */ | 
 | 29 | #ifndef __ARM_ARCH | 
 | 30 | # ifdef __ARM_ARCH_2__ | 
 | 31 | #  define __ARM_ARCH 2 | 
 | 32 | # elif defined (__ARM_ARCH_3__) || defined (__ARM_ARCH_3M__) | 
 | 33 | #  define __ARM_ARCH 3 | 
 | 34 | # elif defined (__ARM_ARCH_4__) || defined (__ARM_ARCH_4T__) | 
 | 35 | #  define __ARM_ARCH 4 | 
 | 36 | # elif defined (__ARM_ARCH_5__) || defined (__ARM_ARCH_5E__) \ | 
 | 37 |        || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \ | 
 | 38 |        || defined(__ARM_ARCH_5TEJ__) | 
 | 39 | #  define __ARM_ARCH 5 | 
 | 40 | # elif defined (__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ | 
 | 41 |        || defined (__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \ | 
 | 42 |        || defined (__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) | 
 | 43 | #  define __ARM_ARCH 6 | 
 | 44 | # elif defined (__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ | 
 | 45 |        || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ | 
 | 46 |        || defined(__ARM_ARCH_7EM__) | 
 | 47 | #  define __ARM_ARCH 7 | 
 | 48 | # else | 
 | 49 | #  error unknown arm architecture | 
 | 50 | # endif | 
 | 51 | #endif | 
 | 52 |  | 
 | 53 | #if __ARM_ARCH > 4 || defined (__ARM_ARCH_4T__) | 
 | 54 | # define ARCH_HAS_BX | 
 | 55 | #endif | 
 | 56 | #if __ARM_ARCH > 4 | 
 | 57 | # define ARCH_HAS_BLX | 
 | 58 | #endif | 
 | 59 | #if __ARM_ARCH > 6 || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6ZK__) | 
 | 60 | # define ARCH_HAS_HARD_TP | 
 | 61 | #endif | 
 | 62 | #if __ARM_ARCH > 6 || defined (__ARM_ARCH_6T2__) | 
 | 63 | # define ARCH_HAS_T2 | 
 | 64 | #endif | 
 | 65 |  | 
 | 66 | #ifdef	__ASSEMBLER__ | 
 | 67 |  | 
 | 68 | /* Syntactic details of assembler.  */ | 
 | 69 |  | 
 | 70 | #define ALIGNARG(log2) log2 | 
 | 71 | #define ASM_SIZE_DIRECTIVE(name) .size name,.-name | 
 | 72 |  | 
 | 73 | #define PLTJMP(_x)	_x##(PLT) | 
 | 74 |  | 
 | 75 | #ifdef ARCH_HAS_BX | 
 | 76 | # define BX(R)		bx	R | 
 | 77 | # define BXC(C, R)	bx##C	R | 
 | 78 | # ifdef ARCH_HAS_BLX | 
 | 79 | #  define BLX(R)	blx	R | 
 | 80 | # else | 
 | 81 | #  define BLX(R)	mov	lr, pc; bx R | 
 | 82 | # endif | 
 | 83 | #else | 
 | 84 | # define BX(R)		mov	pc, R | 
 | 85 | # define BXC(C, R)	mov##C	pc, R | 
 | 86 | # define BLX(R)		mov	lr, pc; mov pc, R | 
 | 87 | #endif | 
 | 88 |  | 
 | 89 | #define DO_RET(R)	BX(R) | 
 | 90 | #define RETINSTR(C, R)	BXC(C, R) | 
 | 91 |  | 
 | 92 | /* Define an entry point visible from C.  */ | 
 | 93 | #define	ENTRY(name)					\ | 
 | 94 | 	.globl	C_SYMBOL_NAME(name);			\ | 
 | 95 | 	.type	C_SYMBOL_NAME(name),%function;		\ | 
 | 96 | 	.align	ALIGNARG(4);				\ | 
 | 97 |   C_LABEL(name)						\ | 
 | 98 | 	CFI_SECTIONS;					\ | 
 | 99 | 	cfi_startproc;					\ | 
 | 100 | 	CALL_MCOUNT | 
 | 101 |  | 
 | 102 | #define CFI_SECTIONS					\ | 
 | 103 | 	.cfi_sections .debug_frame | 
 | 104 |  | 
 | 105 | #undef	END | 
 | 106 | #define END(name)					\ | 
 | 107 | 	cfi_endproc;					\ | 
 | 108 | 	ASM_SIZE_DIRECTIVE(name) | 
 | 109 |  | 
 | 110 | /* If compiled for profiling, call `mcount' at the start of each function.  */ | 
 | 111 | #ifdef	PROF | 
 | 112 | /* Call __gnu_mcount_nc (GCC >= 4.4).  */ | 
 | 113 | #define CALL_MCOUNT					\ | 
 | 114 | 	push	{lr};					\ | 
 | 115 | 	cfi_adjust_cfa_offset (4);			\ | 
 | 116 | 	cfi_rel_offset (lr, 0);				\ | 
 | 117 | 	bl	PLTJMP(mcount);				\ | 
 | 118 | 	cfi_adjust_cfa_offset (-4);			\ | 
 | 119 | 	cfi_restore (lr) | 
 | 120 | #else | 
 | 121 | #define CALL_MCOUNT		/* Do nothing.  */ | 
 | 122 | #endif | 
 | 123 |  | 
 | 124 | /* Since C identifiers are not normally prefixed with an underscore | 
 | 125 |    on this system, the asm identifier `syscall_error' intrudes on the | 
 | 126 |    C name space.  Make sure we use an innocuous name.  */ | 
 | 127 | #define	syscall_error	__syscall_error | 
 | 128 | #define mcount		__gnu_mcount_nc | 
 | 129 |  | 
 | 130 | /* Tag_ABI_align8_preserved: This code preserves 8-byte | 
 | 131 |    alignment in any callee.  */ | 
 | 132 | 	.eabi_attribute 25, 1 | 
 | 133 | /* Tag_ABI_align8_needed: This code may require 8-byte alignment from | 
 | 134 |    the caller.  */ | 
 | 135 | 	.eabi_attribute 24, 1 | 
 | 136 |  | 
 | 137 | /* The thumb2 encoding is reasonably complete.  Unless suppressed, use it.  */ | 
 | 138 | 	.syntax unified | 
 | 139 | # if defined(__thumb2__) && !defined(NO_THUMB) | 
 | 140 | 	.thumb | 
 | 141 | #else | 
 | 142 | #  undef __thumb__ | 
 | 143 | #  undef __thumb2__ | 
 | 144 | 	.arm | 
 | 145 | # endif | 
 | 146 |  | 
 | 147 | /* Load or store to/from address X + Y into/from R, (maybe) using T. | 
 | 148 |    X or Y can use T freely; T can be R if OP is a load.  The first | 
 | 149 |    version eschews the two-register addressing mode, while the | 
 | 150 |    second version uses it.  */ | 
 | 151 | # define LDST_INDEXED_NOINDEX(OP, R, T, X, Y)		\ | 
 | 152 | 	add	T, X, Y;				\ | 
 | 153 | 	sfi_breg T,					\ | 
 | 154 | 	OP	R, [T] | 
 | 155 | # define LDST_INDEXED_INDEX(OP, R, X, Y)		\ | 
 | 156 | 	OP	R, [X, Y] | 
 | 157 |  | 
 | 158 | # ifdef ARM_NO_INDEX_REGISTER | 
 | 159 | /* We're never using the two-register addressing mode, so this | 
 | 160 |    always uses an intermediate add.  */ | 
 | 161 | #  define LDST_INDEXED(OP, R, T, X, Y)	LDST_INDEXED_NOINDEX (OP, R, T, X, Y) | 
 | 162 | #  define LDST_PC_INDEXED(OP, R, T, X)	LDST_INDEXED_NOINDEX (OP, R, T, pc, X) | 
 | 163 | # else | 
 | 164 | /* The two-register addressing mode is OK, except on Thumb with pc.  */ | 
 | 165 | #  define LDST_INDEXED(OP, R, T, X, Y)	LDST_INDEXED_INDEX (OP, R, X, Y) | 
 | 166 | #  ifdef __thumb2__ | 
 | 167 | #   define LDST_PC_INDEXED(OP, R, T, X)	LDST_INDEXED_NOINDEX (OP, R, T, pc, X) | 
 | 168 | #  else | 
 | 169 | #   define LDST_PC_INDEXED(OP, R, T, X)	LDST_INDEXED_INDEX (OP, R, pc, X) | 
 | 170 | #  endif | 
 | 171 | # endif | 
 | 172 |  | 
 | 173 | /* Load or store to/from a pc-relative EXPR into/from R, using T.  */ | 
 | 174 | # ifdef __thumb2__ | 
 | 175 | #  define LDST_PCREL(OP, R, T, EXPR) \ | 
 | 176 | 	ldr	T, 98f;					\ | 
 | 177 | 	.subsection 2;					\ | 
 | 178 | 98:	.word	EXPR - 99f - PC_OFS;			\ | 
 | 179 | 	.previous;					\ | 
 | 180 | 99:	add	T, T, pc;				\ | 
 | 181 | 	OP	R, [T] | 
 | 182 | # elif defined (ARCH_HAS_T2) && ARM_PCREL_MOVW_OK | 
 | 183 | #  define LDST_PCREL(OP, R, T, EXPR)			\ | 
 | 184 | 	movw	T, #:lower16:EXPR - 99f - PC_OFS;	\ | 
 | 185 | 	movt	T, #:upper16:EXPR - 99f - PC_OFS;	\ | 
 | 186 | 99:	LDST_PC_INDEXED (OP, R, T, T) | 
 | 187 | # else | 
 | 188 | #  define LDST_PCREL(OP, R, T, EXPR) \ | 
 | 189 | 	ldr	T, 98f;					\ | 
 | 190 | 	.subsection 2;					\ | 
 | 191 | 98:	.word	EXPR - 99f - PC_OFS;			\ | 
 | 192 | 	.previous;					\ | 
 | 193 | 99:	OP	R, [pc, T] | 
 | 194 | # endif | 
 | 195 |  | 
 | 196 | /* Load from a global SYMBOL + CONSTANT into R, using T.  */ | 
 | 197 | # if defined (ARCH_HAS_T2) && !defined (PIC) | 
 | 198 | #  define LDR_GLOBAL(R, T, SYMBOL, CONSTANT)				\ | 
 | 199 | 	movw	T, #:lower16:SYMBOL;					\ | 
 | 200 | 	movt	T, #:upper16:SYMBOL;					\ | 
 | 201 | 	sfi_breg T, ldr R, [\B, $CONSTANT] | 
 | 202 | # elif defined (ARCH_HAS_T2) && defined (PIC) && ARM_PCREL_MOVW_OK | 
 | 203 | #  define LDR_GLOBAL(R, T, SYMBOL, CONSTANT)				\ | 
 | 204 | 	movw	R, #:lower16:_GLOBAL_OFFSET_TABLE_ - 97f - PC_OFS;	\ | 
 | 205 | 	movw	T, #:lower16:99f - 98f - PC_OFS;			\ | 
 | 206 | 	movt	R, #:upper16:_GLOBAL_OFFSET_TABLE_ - 97f - PC_OFS;	\ | 
 | 207 | 	movt	T, #:upper16:99f - 98f - PC_OFS;			\ | 
 | 208 | 	.pushsection .rodata.cst4, "aM", %progbits, 4;			\ | 
 | 209 | 	.balign 4;							\ | 
 | 210 | 99:	.word	SYMBOL##(GOT);						\ | 
 | 211 | 	.popsection;							\ | 
 | 212 | 97:	add	R, R, pc;						\ | 
 | 213 | 98:	LDST_PC_INDEXED (ldr, T, T, T);					\ | 
 | 214 | 	LDST_INDEXED (ldr, R, T, R, T);					\ | 
 | 215 | 	sfi_breg R, ldr	R, [\B, $CONSTANT] | 
 | 216 | # else | 
 | 217 | #  define LDR_GLOBAL(R, T, SYMBOL, CONSTANT)		\ | 
 | 218 | 	ldr	T, 99f;					\ | 
 | 219 | 	ldr	R, 100f;				\ | 
 | 220 | 98:	add	T, T, pc;				\ | 
 | 221 | 	ldr	T, [T, R];				\ | 
 | 222 | 	.subsection 2;					\ | 
 | 223 | 99:	.word	_GLOBAL_OFFSET_TABLE_ - 98b - PC_OFS;	\ | 
 | 224 | 100:	.word	SYMBOL##(GOT);				\ | 
 | 225 | 	.previous;					\ | 
 | 226 | 	ldr	R, [T, $CONSTANT] | 
 | 227 | # endif | 
 | 228 |  | 
 | 229 | /* This is the same as LDR_GLOBAL, but for a SYMBOL that is known to | 
 | 230 |    be in the same linked object (as for one with hidden visibility). | 
 | 231 |    We can avoid the GOT indirection in the PIC case.  For the pure | 
 | 232 |    static case, LDR_GLOBAL is already optimal.  */ | 
 | 233 | # ifdef PIC | 
 | 234 | #  define LDR_HIDDEN(R, T, SYMBOL, CONSTANT) \ | 
 | 235 |   LDST_PCREL (ldr, R, T, SYMBOL + CONSTANT) | 
 | 236 | # else | 
 | 237 | #  define LDR_HIDDEN(R, T, SYMBOL, CONSTANT) \ | 
 | 238 |   LDR_GLOBAL (R, T, SYMBOL, CONSTANT) | 
 | 239 | # endif | 
 | 240 |  | 
 | 241 | /* Cope with negative memory offsets, which thumb can't encode. | 
 | 242 |    Use NEGOFF_ADJ_BASE to (conditionally) alter the base register, | 
 | 243 |    and then NEGOFF_OFF1 to use 0 for thumb and the offset for arm, | 
 | 244 |    or NEGOFF_OFF2 to use A-B for thumb and A for arm.  */ | 
 | 245 | # ifdef __thumb2__ | 
 | 246 | #  define NEGOFF_ADJ_BASE(R, OFF)	add R, R, $OFF | 
 | 247 | #  define NEGOFF_ADJ_BASE2(D, S, OFF)	add D, S, $OFF | 
 | 248 | #  define NEGOFF_OFF1(R, OFF)		[R] | 
 | 249 | #  define NEGOFF_OFF2(R, OFFA, OFFB)	[R, $((OFFA) - (OFFB))] | 
 | 250 | # else | 
 | 251 | #  define NEGOFF_ADJ_BASE(R, OFF) | 
 | 252 | #  define NEGOFF_ADJ_BASE2(D, S, OFF)	mov D, S | 
 | 253 | #  define NEGOFF_OFF1(R, OFF)		[R, $OFF] | 
 | 254 | #  define NEGOFF_OFF2(R, OFFA, OFFB)	[R, $OFFA] | 
 | 255 | # endif | 
 | 256 |  | 
 | 257 | /* Helper to get the TLS base pointer.  The interface is that TMP is a | 
 | 258 |    register that may be used to hold the LR, if necessary.  TMP may be | 
 | 259 |    LR itself to indicate that LR need not be saved.  The base pointer | 
 | 260 |    is returned in R0.  Only R0 and TMP are modified.  */ | 
 | 261 |  | 
 | 262 | # ifdef ARCH_HAS_HARD_TP | 
 | 263 | /* If the cpu has cp15 available, use it.  */ | 
 | 264 | #  define GET_TLS(TMP)		mrc p15, 0, r0, c13, c0, 3 | 
 | 265 | # else | 
 | 266 | /* At this generic level we have no tricks to pull.  Call the ABI routine.  */ | 
 | 267 | #  define GET_TLS(TMP)					\ | 
 | 268 | 	push	{ r1, r2, r3, lr };			\ | 
 | 269 | 	cfi_remember_state;				\ | 
 | 270 | 	cfi_adjust_cfa_offset (16);			\ | 
 | 271 | 	cfi_rel_offset (r1, 0);				\ | 
 | 272 | 	cfi_rel_offset (r2, 4);				\ | 
 | 273 | 	cfi_rel_offset (r3, 8);				\ | 
 | 274 | 	cfi_rel_offset (lr, 12);			\ | 
 | 275 | 	bl	__aeabi_read_tp;			\ | 
 | 276 | 	pop	{ r1, r2, r3, lr };			\ | 
 | 277 | 	cfi_restore_state | 
 | 278 | # endif /* ARCH_HAS_HARD_TP */ | 
 | 279 |  | 
 | 280 | # ifndef ARM_SFI_MACROS | 
 | 281 | # define ARM_SFI_MACROS 1 | 
 | 282 | /* This assembly macro is prepended to any load/store instruction, | 
 | 283 |    pulling the base register out of the addressing mode syntax and | 
 | 284 |    making it the first operand of the macro.  For example: | 
 | 285 | 	ldr r0, [r1] | 
 | 286 |    becomes: | 
 | 287 | 	sfi_breg r1, ldr r0, [\B] | 
 | 288 |    The \B stands in for the base register that is the first operand | 
 | 289 |    to the macro, so we can avoid error-prone repetition of the base | 
 | 290 |    register in two places on the line. | 
 | 291 |  | 
 | 292 |    This is used for all memory access through a base register other | 
 | 293 |    than PC or SP.  It's intended to support SFI schemes such as | 
 | 294 |    Native Client, where the OS will enforce that all load/store | 
 | 295 |    instructions use a special form.  In any such configuration, | 
 | 296 |    another sysdep.h file will have defined ARM_SFI_MACROS and | 
 | 297 |    provided its own assembly macros with the same interface.  */ | 
 | 298 |  | 
 | 299 |         .macro sfi_breg basereg, insn, operands:vararg | 
 | 300 |                 .macro _sfi_breg_doit B | 
 | 301 |                 \insn \operands | 
 | 302 |                 .endm | 
 | 303 |                 _sfi_breg_doit \basereg | 
 | 304 |                 .purgem _sfi_breg_doit | 
 | 305 |         .endm | 
 | 306 |  | 
 | 307 | /* This assembly macro replaces the "pld" instruction. | 
 | 308 |    The syntax: | 
 | 309 | 	sfi_pld REGISTER, #OFFSET | 
 | 310 |    is exactly equivalent to: | 
 | 311 | 	sfi_breg REGISTER, pld [\B, #OFFSET] | 
 | 312 |    (and ", #OFFSET" is optional).  We have a separate macro | 
 | 313 |    only to work around a bug in GAS versions prior to 2.23.2, | 
 | 314 |    that misparses the sfi_breg macro expansion in this case.  */ | 
 | 315 |  | 
 | 316 | 	.macro sfi_pld basereg, offset=#0 | 
 | 317 | 		pld [\basereg, \offset] | 
 | 318 | 	.endm | 
 | 319 |  | 
 | 320 | /* This macro precedes any instruction that directly changes the SP. | 
 | 321 |    It's not needed for push/pop or for any kind of load or store that | 
 | 322 |    implicitly changes the SP via the ! syntax.  */ | 
 | 323 | # define sfi_sp	/* Nothing to do.  */ | 
 | 324 |  | 
 | 325 | # endif | 
 | 326 |  | 
 | 327 | /* These are the directives used for EABI unwind info. | 
 | 328 |    Wrap them in macros so another configuration's sysdep.h | 
 | 329 |    file can define them away if it doesn't use EABI unwind info.  */ | 
 | 330 | # define eabi_fnstart		.fnstart | 
 | 331 | # define eabi_fnend		.fnend | 
 | 332 | # define eabi_save(...)		.save __VA_ARGS__ | 
 | 333 | # define eabi_cantunwind	.cantunwind | 
 | 334 | # define eabi_pad(n)		.pad n | 
 | 335 |  | 
 | 336 | #endif	/* __ASSEMBLER__ */ | 
 | 337 |  | 
 | 338 | /* This number is the offset from the pc at the current location.  */ | 
 | 339 | #ifdef __thumb__ | 
 | 340 | # define PC_OFS  4 | 
 | 341 | #else | 
 | 342 | # define PC_OFS  8 | 
 | 343 | #endif | 
 | 344 |  | 
 | 345 | /* Pointer mangling support.  */ | 
 | 346 | #if (IS_IN (rtld) || \ | 
 | 347 |      (!defined SHARED && (IS_IN (libc) || IS_IN (libpthread)))) | 
 | 348 | # ifdef __ASSEMBLER__ | 
 | 349 | #  define PTR_MANGLE_LOAD(guard, tmp)					\ | 
 | 350 |   LDR_HIDDEN (guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard_local), 0) | 
 | 351 | #  define PTR_MANGLE(dst, src, guard, tmp)				\ | 
 | 352 |   PTR_MANGLE_LOAD(guard, tmp);						\ | 
 | 353 |   PTR_MANGLE2(dst, src, guard) | 
 | 354 | /* Use PTR_MANGLE2 for efficiency if guard is already loaded.  */ | 
 | 355 | #  define PTR_MANGLE2(dst, src, guard)		\ | 
 | 356 |   eor dst, src, guard | 
 | 357 | #  define PTR_DEMANGLE(dst, src, guard, tmp)	\ | 
 | 358 |   PTR_MANGLE (dst, src, guard, tmp) | 
 | 359 | #  define PTR_DEMANGLE2(dst, src, guard)	\ | 
 | 360 |   PTR_MANGLE2 (dst, src, guard) | 
 | 361 | # else | 
 | 362 | extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden; | 
 | 363 | #  define PTR_MANGLE(var) \ | 
 | 364 |   (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local) | 
 | 365 | #  define PTR_DEMANGLE(var)     PTR_MANGLE (var) | 
 | 366 | # endif | 
 | 367 | #else | 
 | 368 | # ifdef __ASSEMBLER__ | 
 | 369 | #  define PTR_MANGLE_LOAD(guard, tmp)					\ | 
 | 370 |   LDR_GLOBAL (guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard), 0); | 
 | 371 | #  define PTR_MANGLE(dst, src, guard, tmp)				\ | 
 | 372 |   PTR_MANGLE_LOAD(guard, tmp);						\ | 
 | 373 |   PTR_MANGLE2(dst, src, guard) | 
 | 374 | /* Use PTR_MANGLE2 for efficiency if guard is already loaded.  */ | 
 | 375 | #  define PTR_MANGLE2(dst, src, guard)		\ | 
 | 376 |   eor dst, src, guard | 
 | 377 | #  define PTR_DEMANGLE(dst, src, guard, tmp)	\ | 
 | 378 |   PTR_MANGLE (dst, src, guard, tmp) | 
 | 379 | #  define PTR_DEMANGLE2(dst, src, guard)	\ | 
 | 380 |   PTR_MANGLE2 (dst, src, guard) | 
 | 381 | # else | 
 | 382 | extern uintptr_t __pointer_chk_guard attribute_relro; | 
 | 383 | #  define PTR_MANGLE(var) \ | 
 | 384 |   (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard) | 
 | 385 | #  define PTR_DEMANGLE(var)     PTR_MANGLE (var) | 
 | 386 | # endif | 
 | 387 | #endif |