]> git.llucax.com Git - software/dgc/naive.git/blob - arch.d
fbfa40f4ee2b25ec1b2d867fadb431759f79c02b
[software/dgc/naive.git] / arch.d
1 /**
2  * This module contains a minimal garbage collector implementation according to
3  * Tango requirements.  This library is mostly intended to serve as an example,
4  * but it is usable in applications which do not rely on a garbage collector
5  * to clean up memory (ie. when dynamic array resizing is not used, and all
6  * memory allocated with 'new' is freed deterministically with 'delete').
7  *
8  * Please note that block attribute data must be tracked, or at a minimum, the
9  * FINALIZE bit must be tracked for any allocated memory block because calling
10  * rt_finalize on a non-object block can result in an access violation.  In the
11  * allocator below, this tracking is done via a leading uint bitmask.  A real
12  * allocator may do better to store this data separately, similar to the basic
13  * GC normally used by Tango.
14  *
15  * Copyright: Public Domain
16  * License:   BOLA
17  * Authors:   Leandro Lucarella
18  */
19
20 module arch;
21
22 // TODO: explain why the functions return strings to use as string mixins
23
24 /*
25  * Small hack to define the string alias if not defined
26  *
27  * Tango don't define this alias in object.d, but Phobos 1 and 2 does.
28  */
29 // XXX: this doesnt work:
30 // static if (!is(string))
31 //    alias char[] string;
32 // See: http://d.puremagic.com/issues/show_bug.cgi?id=2848
33 version (Tango)
34     alias char[] string;
35
36 /*
37  * Functions dependant on the direction in which the stack grows
38  *
39  * By default, stack is considered to grow down, as in x86 architectures.
40  */
41
42 version = STACK_GROWS_DOWN;
43
44 bool stack_smaller(void* ptr1, void* ptr2)
45 {
46     version (STACK_GROWS_DOWN)
47         return ptr1 > ptr2;
48     else
49         return ptr1 < ptr2;
50 }
51
52 // Functions to push/pop registers into/from the stack
53
54 version (GNU)
55 {
56
57     /*
58      * GCC has an intrinsic function that does the job of pushing the registers
59      * into the stack, we use that function if available because it should work
60      * in all GCC supported architectures.
61      */
62
63     string push_registers(string sp_name)
64     {
65         return "
66             __builtin_unwind_init();
67             " ~ sp_name ~ " = &" ~ sp_name ~ ";
68         ";
69     }
70
71     string pop_registers(string sp_name)
72     {
73         return "";
74     }
75
76 }
77 else version (X86)
78 {
79
80     /*
81      * For X86 PUSHAD/POPAD are not used because they are too fragile to
82      * compiler optimizations (like ommitting the frame pointer).
83      *
84      * This method should work safely with all optimizations because it doesn't
85      * works behind the compilers back.
86      */
87
88     string push_registers(string sp_name)
89     {
90         return "
91             size_t eax, ecx, edx, ebx, ebp, esi, edi;
92             asm
93             {
94                 mov eax[EBP], EAX;
95                 mov ecx[EBP], ECX;
96                 mov edx[EBP], EDX;
97                 mov ebx[EBP], EBX;
98                 mov ebp[EBP], EBP;
99                 mov esi[EBP], ESI;
100                 mov edi[EBP], EDI;
101                 mov " ~ sp_name ~ "[EBP],  ESP;
102             }
103         ";
104     }
105
106     string pop_registers(string sp_name)
107     {
108         return "";
109     }
110
111 }
112 else version (X86_64)
113 {
114
115     /*
116      * See X86 comment above.
117      */
118
119     string push_registers(string sp_name)
120     {
121         return "
122             size_t rax, rbx, rcx, rdx, rbp, rsi, rdi,
123                    r10, r11, r12, r13, r14, r15;
124             asm
125             {
126                 movq rax[RBP], RAX;
127                 movq rbx[RBP], RBX;
128                 movq rcx[RBP], RCX;
129                 movq rdx[RBP], RDX;
130                 movq rbp[RBP], RBP;
131                 movq rsi[RBP], RSI;
132                 movq rdi[RBP], RDI;
133                 movq r10[RBP], R10;
134                 movq r11[RBP], R11;
135                 movq r12[RBP], R12;
136                 movq r13[RBP], R13;
137                 movq r14[RBP], R14;
138                 movq r15[RBP], R15;
139                 movq " ~ sp_name ~ "[RBP],  RSP;
140             }
141         ";
142     }
143
144     string pop_registers(string sp_name)
145     {
146         return "";
147     }
148
149 }
150 else // Unkown compiler/architecture
151 {
152
153     pragma(msg, "Don't know how to push registers into the stack for this "
154                 "compiler/architecture");
155     static assert(false);
156
157 }
158
159 // vim: set et sw=4 sts=4 :