1/*
2 * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>.
3 * Copyright (C) 2018 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#pragma once
28
29#include "GPRInfo.h"
30#include "LLIntPCRanges.h"
31#include "MacroAssemblerCodeRef.h"
32#include <wtf/Optional.h>
33#include <wtf/PlatformRegisters.h>
34#include <wtf/PointerPreparations.h>
35#include <wtf/StdLibExtras.h>
36
37namespace JSC {
38namespace MachineContext {
39
40template<typename T = void*> T stackPointer(const PlatformRegisters&);
41
42#if OS(WINDOWS) || HAVE(MACHINE_CONTEXT)
43template<typename T = void*> void setStackPointer(PlatformRegisters&, T);
44template<typename T = void*> T framePointer(const PlatformRegisters&);
45template<typename T = void*> void setFramePointer(PlatformRegisters&, T);
46inline MacroAssemblerCodePtr<PlatformRegistersLRPtrTag> linkRegister(const PlatformRegisters&);
47inline void setLinkRegister(PlatformRegisters&, MacroAssemblerCodePtr<CFunctionPtrTag>);
48inline Optional<MacroAssemblerCodePtr<PlatformRegistersPCPtrTag>> instructionPointer(const PlatformRegisters&);
49inline void setInstructionPointer(PlatformRegisters&, MacroAssemblerCodePtr<CFunctionPtrTag>);
50
51template<size_t N> void*& argumentPointer(PlatformRegisters&);
52template<size_t N> void* argumentPointer(const PlatformRegisters&);
53#if !ENABLE(C_LOOP)
54void*& llintInstructionPointer(PlatformRegisters&);
55void* llintInstructionPointer(const PlatformRegisters&);
56#endif // !ENABLE(C_LOOP)
57
58#if HAVE(MACHINE_CONTEXT)
59
60#if !USE(PLATFORM_REGISTERS_WITH_PROFILE)
61static inline void*& stackPointerImpl(mcontext_t&);
62static inline void*& framePointerImpl(mcontext_t&);
63static inline void*& instructionPointerImpl(mcontext_t&);
64#endif // !USE(PLATFORM_REGISTERS_WITH_PROFILE)
65
66template<typename T = void*> T stackPointer(const mcontext_t&);
67template<typename T = void*> void setStackPointer(mcontext_t&, T);
68template<typename T = void*> T framePointer(const mcontext_t&);
69template<typename T = void*> void setFramePointer(mcontext_t&, T);
70inline MacroAssemblerCodePtr<PlatformRegistersPCPtrTag> instructionPointer(const mcontext_t&);
71inline void setInstructionPointer(mcontext_t&, MacroAssemblerCodePtr<CFunctionPtrTag>);
72
73template<size_t N> void*& argumentPointer(mcontext_t&);
74template<size_t N> void* argumentPointer(const mcontext_t&);
75#if !ENABLE(C_LOOP)
76void*& llintInstructionPointer(mcontext_t&);
77void* llintInstructionPointer(const mcontext_t&);
78#endif // !ENABLE(C_LOOP)
79#endif // HAVE(MACHINE_CONTEXT)
80#endif // OS(WINDOWS) || HAVE(MACHINE_CONTEXT)
81
82#if OS(WINDOWS) || HAVE(MACHINE_CONTEXT)
83
84#if !USE(PLATFORM_REGISTERS_WITH_PROFILE)
85static inline void*& stackPointerImpl(PlatformRegisters& regs)
86{
87#if OS(DARWIN)
88#if __DARWIN_UNIX03
89
90#if CPU(X86)
91 return reinterpret_cast<void*&>(regs.__esp);
92#elif CPU(X86_64)
93 return reinterpret_cast<void*&>(regs.__rsp);
94#elif CPU(PPC) || CPU(PPC64)
95 return reinterpret_cast<void*&>(regs.__r1);
96#elif CPU(ARM_THUMB2) || CPU(ARM) || CPU(ARM64)
97 return reinterpret_cast<void*&>(regs.__sp);
98#else
99#error Unknown Architecture
100#endif
101
102#else // !__DARWIN_UNIX03
103
104#if CPU(X86)
105 return reinterpret_cast<void*&>(regs.esp);
106#elif CPU(X86_64)
107 return reinterpret_cast<void*&>(regs.rsp);
108#elif CPU(PPC) || CPU(PPC64)
109 return reinterpret_cast<void*&>(regs.r1);
110#else
111#error Unknown Architecture
112#endif
113
114#endif // __DARWIN_UNIX03
115
116#elif OS(WINDOWS)
117
118#if CPU(ARM)
119 return reinterpret_cast<void*&>((uintptr_t&) regs.Sp);
120#elif CPU(MIPS)
121 return reinterpret_cast<void*&>((uintptr_t&) regs.IntSp);
122#elif CPU(X86)
123 return reinterpret_cast<void*&>((uintptr_t&) regs.Esp);
124#elif CPU(X86_64)
125 return reinterpret_cast<void*&>((uintptr_t&) regs.Rsp);
126#else
127#error Unknown Architecture
128#endif
129
130#elif HAVE(MACHINE_CONTEXT)
131 return stackPointerImpl(regs.machineContext);
132#endif
133}
134#endif // !USE(PLATFORM_REGISTERS_WITH_PROFILE)
135
136template<typename T>
137inline T stackPointer(const PlatformRegisters& regs)
138{
139#if USE(PLATFORM_REGISTERS_WITH_PROFILE)
140 void* value = WTF_READ_PLATFORM_REGISTERS_SP_WITH_PROFILE(regs);
141 assertIsNotTagged(value);
142 return bitwise_cast<T>(value);
143#else
144 return bitwise_cast<T>(stackPointerImpl(const_cast<PlatformRegisters&>(regs)));
145#endif
146}
147
148template<typename T>
149inline void setStackPointer(PlatformRegisters& regs, T value)
150{
151#if USE(PLATFORM_REGISTERS_WITH_PROFILE)
152 assertIsNotTagged(bitwise_cast<void*>(value));
153 WTF_WRITE_PLATFORM_REGISTERS_SP_WITH_PROFILE(regs, bitwise_cast<void*>(value));
154#else
155 stackPointerImpl(regs) = bitwise_cast<void*>(value);
156#endif
157}
158
159#else // not OS(WINDOWS) || HAVE(MACHINE_CONTEXT)
160
161template<typename T>
162inline T stackPointer(const PlatformRegisters& regs)
163{
164 return bitwise_cast<T>(regs.stackPointer);
165}
166#endif // OS(WINDOWS) || HAVE(MACHINE_CONTEXT)
167
168#if HAVE(MACHINE_CONTEXT)
169
170#if !USE(PLATFORM_REGISTERS_WITH_PROFILE)
171static inline void*& stackPointerImpl(mcontext_t& machineContext)
172{
173#if OS(DARWIN)
174 return stackPointerImpl(machineContext->__ss);
175#elif OS(FREEBSD)
176
177#if CPU(X86)
178 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_esp);
179#elif CPU(X86_64)
180 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_rsp);
181#elif CPU(ARM)
182 return reinterpret_cast<void*&>((uintptr_t&) machineContext.__gregs[_REG_SP]);
183#elif CPU(ARM64)
184 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_gpregs.gp_sp);
185#elif CPU(MIPS)
186 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_regs[29]);
187#else
188#error Unknown Architecture
189#endif
190
191#elif OS(FUCHSIA) || defined(__GLIBC__) || defined(__BIONIC__)
192
193#if CPU(X86)
194 return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_ESP]);
195#elif CPU(X86_64)
196 return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_RSP]);
197#elif CPU(ARM)
198 return reinterpret_cast<void*&>((uintptr_t&) machineContext.arm_sp);
199#elif CPU(ARM64)
200 return reinterpret_cast<void*&>((uintptr_t&) machineContext.sp);
201#elif CPU(MIPS)
202 return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[29]);
203#else
204#error Unknown Architecture
205#endif
206#endif
207}
208#endif // !USE(PLATFORM_REGISTERS_WITH_PROFILE)
209
210template<typename T>
211inline T stackPointer(const mcontext_t& machineContext)
212{
213#if USE(PLATFORM_REGISTERS_WITH_PROFILE)
214 void* value = WTF_READ_MACHINE_CONTEXT_SP_WITH_PROFILE(machineContext);
215 assertIsNotTagged(value);
216 return bitwise_cast<T>(value);
217#else
218 return bitwise_cast<T>(stackPointerImpl(const_cast<mcontext_t&>(machineContext)));
219#endif
220}
221
222template<typename T>
223inline void setStackPointer(mcontext_t& machineContext, T value)
224{
225#if USE(PLATFORM_REGISTERS_WITH_PROFILE)
226 assertIsNotTagged(bitwise_cast<void*>(value));
227 WTF_WRITE_MACHINE_CONTEXT_SP_WITH_PROFILE(machineContext, bitwise_cast<void*>(value));
228#else
229 stackPointerImpl(machineContext) = bitwise_cast<void*>(value);
230#endif
231}
232#endif // HAVE(MACHINE_CONTEXT)
233
234
235#if OS(WINDOWS) || HAVE(MACHINE_CONTEXT)
236
237#if !USE(PLATFORM_REGISTERS_WITH_PROFILE)
238static inline void*& framePointerImpl(PlatformRegisters& regs)
239{
240#if OS(DARWIN)
241
242#if __DARWIN_UNIX03
243
244#if CPU(X86)
245 return reinterpret_cast<void*&>(regs.__ebp);
246#elif CPU(X86_64)
247 return reinterpret_cast<void*&>(regs.__rbp);
248#elif CPU(ARM_THUMB2)
249 return reinterpret_cast<void*&>(regs.__r[7]);
250#elif CPU(ARM)
251 return reinterpret_cast<void*&>(regs.__r[11]);
252#elif CPU(ARM64)
253 return reinterpret_cast<void*&>(regs.__x[29]);
254#else
255#error Unknown Architecture
256#endif
257
258#else // !__DARWIN_UNIX03
259
260#if CPU(X86)
261 return reinterpret_cast<void*&>(regs.esp);
262#elif CPU(X86_64)
263 return reinterpret_cast<void*&>(regs.rsp);
264#else
265#error Unknown Architecture
266#endif
267
268#endif // __DARWIN_UNIX03
269
270#elif OS(WINDOWS)
271
272#if CPU(ARM)
273 return reinterpret_cast<void*&>((uintptr_t&) regs.R11);
274#elif CPU(MIPS)
275#error Dont know what to do with mips. Do we even need this?
276#elif CPU(X86)
277 return reinterpret_cast<void*&>((uintptr_t&) regs.Ebp);
278#elif CPU(X86_64)
279 return reinterpret_cast<void*&>((uintptr_t&) regs.Rbp);
280#else
281#error Unknown Architecture
282#endif
283
284#elif HAVE(MACHINE_CONTEXT)
285 return framePointerImpl(regs.machineContext);
286#endif
287}
288#endif // !USE(PLATFORM_REGISTERS_WITH_PROFILE)
289
290template<typename T>
291inline T framePointer(const PlatformRegisters& regs)
292{
293#if USE(PLATFORM_REGISTERS_WITH_PROFILE)
294 void* value = WTF_READ_PLATFORM_REGISTERS_FP_WITH_PROFILE(regs);
295 assertIsNotTagged(value);
296 return bitwise_cast<T>(value);
297#else
298 return bitwise_cast<T>(framePointerImpl(const_cast<PlatformRegisters&>(regs)));
299#endif
300}
301
302template<typename T>
303inline void setFramePointer(PlatformRegisters& regs, T value)
304{
305#if USE(PLATFORM_REGISTERS_WITH_PROFILE)
306 assertIsNotTagged(bitwise_cast<void*>(value));
307 WTF_WRITE_PLATFORM_REGISTERS_FP_WITH_PROFILE(regs, bitwise_cast<void*>(value));
308#else
309 framePointerImpl(regs) = bitwise_cast<void*>(value);
310#endif
311}
312#endif // OS(WINDOWS) || HAVE(MACHINE_CONTEXT)
313
314
315#if HAVE(MACHINE_CONTEXT)
316
317#if !USE(PLATFORM_REGISTERS_WITH_PROFILE)
318static inline void*& framePointerImpl(mcontext_t& machineContext)
319{
320#if OS(DARWIN)
321 return framePointerImpl(machineContext->__ss);
322#elif OS(FREEBSD)
323
324#if CPU(X86)
325 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_ebp);
326#elif CPU(X86_64)
327 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_rbp);
328#elif CPU(ARM)
329 return reinterpret_cast<void*&>((uintptr_t&) machineContext.__gregs[_REG_FP]);
330#elif CPU(ARM64)
331 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_gpregs.gp_x[29]);
332#elif CPU(MIPS)
333 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_regs[30]);
334#else
335#error Unknown Architecture
336#endif
337
338#elif OS(FUCHSIA) || defined(__GLIBC__) || defined(__BIONIC__)
339
340// The following sequence depends on glibc's sys/ucontext.h.
341#if CPU(X86)
342 return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_EBP]);
343#elif CPU(X86_64)
344 return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_RBP]);
345#elif CPU(ARM)
346 return reinterpret_cast<void*&>((uintptr_t&) machineContext.arm_fp);
347#elif CPU(ARM64)
348 return reinterpret_cast<void*&>((uintptr_t&) machineContext.regs[29]);
349#elif CPU(MIPS)
350 return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[30]);
351#else
352#error Unknown Architecture
353#endif
354
355#else
356#error Need a way to get the frame pointer for another thread on this platform
357#endif
358}
359#endif // !USE(PLATFORM_REGISTERS_WITH_PROFILE)
360
361template<typename T>
362inline T framePointer(const mcontext_t& machineContext)
363{
364#if USE(PLATFORM_REGISTERS_WITH_PROFILE)
365 void* value = WTF_READ_MACHINE_CONTEXT_FP_WITH_PROFILE(machineContext);
366 assertIsNotTagged(value);
367 return bitwise_cast<T>(value);
368#else
369 return bitwise_cast<T>(framePointerImpl(const_cast<mcontext_t&>(machineContext)));
370#endif
371}
372
373template<typename T>
374inline void setFramePointer(mcontext_t& machineContext, T value)
375{
376#if USE(PLATFORM_REGISTERS_WITH_PROFILE)
377 assertIsNotTagged(bitwise_cast<void*>(value));
378 WTF_WRITE_MACHINE_CONTEXT_FP_WITH_PROFILE(machineContext, bitwise_cast<void*>(value));
379#else
380 framePointerImpl(machineContext) = bitwise_cast<void*>(value);
381#endif
382}
383#endif // HAVE(MACHINE_CONTEXT)
384
385
386#if OS(WINDOWS) || HAVE(MACHINE_CONTEXT)
387
388#if !USE(PLATFORM_REGISTERS_WITH_PROFILE)
389static inline void*& instructionPointerImpl(PlatformRegisters& regs)
390{
391#if OS(DARWIN)
392#if __DARWIN_UNIX03
393
394#if CPU(X86)
395 return reinterpret_cast<void*&>(regs.__eip);
396#elif CPU(X86_64)
397 return reinterpret_cast<void*&>(regs.__rip);
398#elif CPU(ARM_THUMB2) || CPU(ARM) || CPU(ARM64)
399 return reinterpret_cast<void*&>(regs.__pc);
400#else
401#error Unknown Architecture
402#endif
403
404#else // !__DARWIN_UNIX03
405#if CPU(X86)
406 return reinterpret_cast<void*&>(regs.eip);
407#elif CPU(X86_64)
408 return reinterpret_cast<void*&>(regs.rip);
409#else
410#error Unknown Architecture
411#endif
412
413#endif // __DARWIN_UNIX03
414
415#elif OS(WINDOWS)
416
417#if CPU(ARM)
418 return reinterpret_cast<void*&>((uintptr_t&) regs.Pc);
419#elif CPU(MIPS)
420#error Dont know what to do with mips. Do we even need this?
421#elif CPU(X86)
422 return reinterpret_cast<void*&>((uintptr_t&) regs.Eip);
423#elif CPU(X86_64)
424 return reinterpret_cast<void*&>((uintptr_t&) regs.Rip);
425#else
426#error Unknown Architecture
427#endif
428
429#elif HAVE(MACHINE_CONTEXT)
430 return instructionPointerImpl(regs.machineContext);
431#endif
432}
433#endif // !USE(PLATFORM_REGISTERS_WITH_PROFILE)
434
435inline Optional<MacroAssemblerCodePtr<PlatformRegistersPCPtrTag>> instructionPointer(const PlatformRegisters& regs)
436{
437#if USE(PLATFORM_REGISTERS_WITH_PROFILE)
438 void* value = WTF_READ_PLATFORM_REGISTERS_PC_WITH_PROFILE(regs);
439#else
440 void* value = instructionPointerImpl(const_cast<PlatformRegisters&>(regs));
441#endif
442 if (!value)
443 return MacroAssemblerCodePtr<PlatformRegistersPCPtrTag>(nullptr);
444 if (!usesPointerTagging())
445 return MacroAssemblerCodePtr<PlatformRegistersPCPtrTag>(value);
446 if (isTaggedWith(value, PlatformRegistersPCPtrTag))
447 return MacroAssemblerCodePtr<PlatformRegistersPCPtrTag>(value);
448 return WTF::nullopt;
449}
450
451inline void setInstructionPointer(PlatformRegisters& regs, MacroAssemblerCodePtr<CFunctionPtrTag> value)
452{
453#if USE(PLATFORM_REGISTERS_WITH_PROFILE)
454 WTF_WRITE_PLATFORM_REGISTERS_PC_WITH_PROFILE(regs, value.executableAddress());
455#else
456 instructionPointerImpl(regs) = value.executableAddress();
457#endif
458}
459#endif // OS(WINDOWS) || HAVE(MACHINE_CONTEXT)
460
461
462#if HAVE(MACHINE_CONTEXT)
463
464#if !USE(PLATFORM_REGISTERS_WITH_PROFILE)
465static inline void*& instructionPointerImpl(mcontext_t& machineContext)
466{
467#if OS(DARWIN)
468 return instructionPointerImpl(machineContext->__ss);
469#elif OS(FREEBSD)
470
471#if CPU(X86)
472 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_eip);
473#elif CPU(X86_64)
474 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_rip);
475#elif CPU(ARM)
476 return reinterpret_cast<void*&>((uintptr_t&) machineContext.__gregs[_REG_PC]);
477#elif CPU(ARM64)
478 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_gpregs.gp_elr);
479#elif CPU(MIPS)
480 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_pc);
481#else
482#error Unknown Architecture
483#endif
484
485#elif OS(FUCHSIA) || defined(__GLIBC__) || defined(__BIONIC__)
486
487// The following sequence depends on glibc's sys/ucontext.h.
488#if CPU(X86)
489 return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_EIP]);
490#elif CPU(X86_64)
491 return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_RIP]);
492#elif CPU(ARM)
493 return reinterpret_cast<void*&>((uintptr_t&) machineContext.arm_pc);
494#elif CPU(ARM64)
495 return reinterpret_cast<void*&>((uintptr_t&) machineContext.pc);
496#elif CPU(MIPS)
497 return reinterpret_cast<void*&>((uintptr_t&) machineContext.pc);
498#else
499#error Unknown Architecture
500#endif
501
502#else
503#error Need a way to get the instruction pointer for another thread on this platform
504#endif
505}
506#endif // !USE(PLATFORM_REGISTERS_WITH_PROFILE)
507
508inline MacroAssemblerCodePtr<PlatformRegistersPCPtrTag> instructionPointer(const mcontext_t& machineContext)
509{
510#if USE(PLATFORM_REGISTERS_WITH_PROFILE)
511 void* value = WTF_READ_MACHINE_CONTEXT_PC_WITH_PROFILE(machineContext);
512#else
513 void* value = instructionPointerImpl(const_cast<mcontext_t&>(machineContext));
514#endif
515 return MacroAssemblerCodePtr<PlatformRegistersPCPtrTag>(value);
516}
517
518inline void setInstructionPointer(mcontext_t& machineContext, MacroAssemblerCodePtr<CFunctionPtrTag> value)
519{
520#if USE(PLATFORM_REGISTERS_WITH_PROFILE)
521 WTF_WRITE_MACHINE_CONTEXT_PC_WITH_PROFILE(machineContext, value.executableAddress());
522#else
523 instructionPointerImpl(machineContext) = value.executableAddress();
524#endif
525}
526#endif // HAVE(MACHINE_CONTEXT)
527
528
529#if OS(WINDOWS) || HAVE(MACHINE_CONTEXT)
530
531#if OS(DARWIN) && __DARWIN_UNIX03 && CPU(ARM64)
532#if !USE(PLATFORM_REGISTERS_WITH_PROFILE)
533inline void*& linkRegisterImpl(PlatformRegisters& regs)
534{
535 return reinterpret_cast<void*&>(regs.__lr);
536}
537#endif // USE(PLATFORM_REGISTERS_WITH_PROFILE)
538
539
540inline MacroAssemblerCodePtr<PlatformRegistersLRPtrTag> linkRegister(const PlatformRegisters& regs)
541{
542#if USE(PLATFORM_REGISTERS_WITH_PROFILE)
543 void* value = WTF_READ_PLATFORM_REGISTERS_LR_WITH_PROFILE(regs);
544#else
545 void* value = linkRegisterImpl(const_cast<PlatformRegisters&>(regs));
546#endif
547 return MacroAssemblerCodePtr<PlatformRegistersLRPtrTag>(value);
548}
549
550inline void setLinkRegister(PlatformRegisters& regs, MacroAssemblerCodePtr<CFunctionPtrTag> value)
551{
552#if USE(PLATFORM_REGISTERS_WITH_PROFILE)
553 WTF_WRITE_PLATFORM_REGISTERS_PC_WITH_PROFILE(regs, value.executableAddress());
554#else
555 linkRegisterImpl(regs) = value.executableAddress();
556#endif
557}
558#endif // OS(DARWIN) && __DARWIN_UNIX03 && CPU(ARM64)
559
560#if HAVE(MACHINE_CONTEXT)
561template<> void*& argumentPointer<1>(mcontext_t&);
562#endif
563
564template<>
565inline void*& argumentPointer<1>(PlatformRegisters& regs)
566{
567#if OS(DARWIN)
568#if __DARWIN_UNIX03
569
570#if CPU(X86)
571 return reinterpret_cast<void*&>(regs.__edx);
572#elif CPU(X86_64)
573 return reinterpret_cast<void*&>(regs.__rsi);
574#elif CPU(ARM_THUMB2) || CPU(ARM)
575 return reinterpret_cast<void*&>(regs.__r[1]);
576#elif CPU(ARM64)
577 return reinterpret_cast<void*&>(regs.__x[1]);
578#else
579#error Unknown Architecture
580#endif
581
582#else // !__DARWIN_UNIX03
583
584#if CPU(X86)
585 return reinterpret_cast<void*&>(regs.edx);
586#elif CPU(X86_64)
587 return reinterpret_cast<void*&>(regs.rsi);
588#else
589#error Unknown Architecture
590#endif
591
592#endif // __DARWIN_UNIX03
593
594#elif OS(WINDOWS)
595
596#if CPU(ARM)
597 return reinterpret_cast<void*&>((uintptr_t&) regs.R1);
598#elif CPU(MIPS)
599#error Dont know what to do with mips. Do we even need this?
600#elif CPU(X86)
601 return reinterpret_cast<void*&>((uintptr_t&) regs.Edx);
602#elif CPU(X86_64)
603 return reinterpret_cast<void*&>((uintptr_t&) regs.Rdx);
604#else
605#error Unknown Architecture
606#endif
607
608#elif HAVE(MACHINE_CONTEXT)
609 return argumentPointer<1>(regs.machineContext);
610#endif
611}
612
613template<size_t N>
614inline void* argumentPointer(const PlatformRegisters& regs)
615{
616 return argumentPointer<N>(const_cast<PlatformRegisters&>(regs));
617}
618#endif // OS(WINDOWS) || HAVE(MACHINE_CONTEXT)
619
620#if HAVE(MACHINE_CONTEXT)
621template<>
622inline void*& argumentPointer<1>(mcontext_t& machineContext)
623{
624#if OS(DARWIN)
625 return argumentPointer<1>(machineContext->__ss);
626#elif OS(FREEBSD)
627
628#if CPU(X86)
629 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_edx);
630#elif CPU(X86_64)
631 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_rsi);
632#elif CPU(ARM)
633 return reinterpret_cast<void*&>((uintptr_t&) machineContext.__gregs[_REG_R1]);
634#elif CPU(ARM64)
635 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_gpregs.gp_x[1]);
636#elif CPU(MIPS)
637 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_regs[5]);
638#else
639#error Unknown Architecture
640#endif
641
642#elif OS(FUCHSIA) || defined(__GLIBC__) || defined(__BIONIC__)
643
644// The following sequence depends on glibc's sys/ucontext.h.
645#if CPU(X86)
646 return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_EDX]);
647#elif CPU(X86_64)
648 return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_RSI]);
649#elif CPU(ARM)
650 return reinterpret_cast<void*&>((uintptr_t&) machineContext.arm_r1);
651#elif CPU(ARM64)
652 return reinterpret_cast<void*&>((uintptr_t&) machineContext.regs[1]);
653#elif CPU(MIPS)
654 return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[5]);
655#else
656#error Unknown Architecture
657#endif
658
659#else
660#error Need a way to get the frame pointer for another thread on this platform
661#endif
662}
663
664template<unsigned N>
665inline void* argumentPointer(const mcontext_t& machineContext)
666{
667 return argumentPointer<N>(const_cast<mcontext_t&>(machineContext));
668}
669#endif // HAVE(MACHINE_CONTEXT)
670
671#if !ENABLE(C_LOOP)
672#if OS(WINDOWS) || HAVE(MACHINE_CONTEXT)
673inline void*& llintInstructionPointer(PlatformRegisters& regs)
674{
675 // LLInt uses regT4 as PC.
676#if OS(DARWIN)
677#if __DARWIN_UNIX03
678
679#if CPU(X86)
680 static_assert(LLInt::LLIntPC == X86Registers::esi, "Wrong LLInt PC.");
681 return reinterpret_cast<void*&>(regs.__esi);
682#elif CPU(X86_64)
683 static_assert(LLInt::LLIntPC == X86Registers::r8, "Wrong LLInt PC.");
684 return reinterpret_cast<void*&>(regs.__r8);
685#elif CPU(ARM)
686 static_assert(LLInt::LLIntPC == ARMRegisters::r8, "Wrong LLInt PC.");
687 return reinterpret_cast<void*&>(regs.__r[8]);
688#elif CPU(ARM64)
689 static_assert(LLInt::LLIntPC == ARM64Registers::x4, "Wrong LLInt PC.");
690 return reinterpret_cast<void*&>(regs.__x[4]);
691#else
692#error Unknown Architecture
693#endif
694
695#else // !__DARWIN_UNIX03
696#if CPU(X86)
697 static_assert(LLInt::LLIntPC == X86Registers::esi, "Wrong LLInt PC.");
698 return reinterpret_cast<void*&>(regs.esi);
699#elif CPU(X86_64)
700 static_assert(LLInt::LLIntPC == X86Registers::r8, "Wrong LLInt PC.");
701 return reinterpret_cast<void*&>(regs.r8);
702#else
703#error Unknown Architecture
704#endif
705
706#endif // __DARWIN_UNIX03
707
708#elif OS(WINDOWS)
709
710#if CPU(ARM)
711 static_assert(LLInt::LLIntPC == ARMRegisters::r8, "Wrong LLInt PC.");
712 return reinterpret_cast<void*&>((uintptr_t&) regs.R8);
713#elif CPU(MIPS)
714#error Dont know what to do with mips. Do we even need this?
715#elif CPU(X86)
716 static_assert(LLInt::LLIntPC == X86Registers::esi, "Wrong LLInt PC.");
717 return reinterpret_cast<void*&>((uintptr_t&) regs.Esi);
718#elif CPU(X86_64)
719 static_assert(LLInt::LLIntPC == X86Registers::r10, "Wrong LLInt PC.");
720 return reinterpret_cast<void*&>((uintptr_t&) regs.R10);
721#else
722#error Unknown Architecture
723#endif
724
725#elif HAVE(MACHINE_CONTEXT)
726 return llintInstructionPointer(regs.machineContext);
727#endif
728}
729
730inline void* llintInstructionPointer(const PlatformRegisters& regs)
731{
732 return llintInstructionPointer(const_cast<PlatformRegisters&>(regs));
733}
734#endif // OS(WINDOWS) || HAVE(MACHINE_CONTEXT)
735
736
737#if HAVE(MACHINE_CONTEXT)
738inline void*& llintInstructionPointer(mcontext_t& machineContext)
739{
740 // LLInt uses regT4 as PC.
741#if OS(DARWIN)
742 return llintInstructionPointer(machineContext->__ss);
743#elif OS(FREEBSD)
744
745#if CPU(X86)
746 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_esi);
747#elif CPU(X86_64)
748 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_r8);
749#elif CPU(ARM)
750 return reinterpret_cast<void*&>((uintptr_t&) machineContext.__gregs[_REG_R8]);
751#elif CPU(ARM64)
752 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_gpregs.gp_x[4]);
753#elif CPU(MIPS)
754 return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_regs[12]);
755#else
756#error Unknown Architecture
757#endif
758
759#elif OS(FUCHSIA) || defined(__GLIBC__) || defined(__BIONIC__)
760
761// The following sequence depends on glibc's sys/ucontext.h.
762#if CPU(X86)
763 return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_ESI]);
764#elif CPU(X86_64)
765 return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_R8]);
766#elif CPU(ARM)
767 return reinterpret_cast<void*&>((uintptr_t&) machineContext.arm_r8);
768#elif CPU(ARM64)
769 return reinterpret_cast<void*&>((uintptr_t&) machineContext.regs[4]);
770#elif CPU(MIPS)
771 return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[12]);
772#else
773#error Unknown Architecture
774#endif
775
776#else
777#error Need a way to get the LLIntPC for another thread on this platform
778#endif
779}
780
781inline void* llintInstructionPointer(const mcontext_t& machineContext)
782{
783 return llintInstructionPointer(const_cast<mcontext_t&>(machineContext));
784}
785#endif // HAVE(MACHINE_CONTEXT)
786#endif // !ENABLE(C_LOOP)
787
788}
789}
790