]> git.llucax.com Git - software/dgc/naive.git/blob - gc/arch.d
Remove alloc module, move all other modules to gc/ and document
[software/dgc/naive.git] / gc / arch.d
1 /**
2  * Architecture (and compiler) dependent functions.
3  *
4  * This is a support module for the Naive Garbage Collector. All the code that
5  * depends on the architecture (or compiler) is in this module.
6  *
7  * See_Also:  gc module
8  * Copyright: Public Domain
9  * License:   Public Domain
10  * Authors:   Leandro Lucarella <llucax@gmail.com>
11  */
12
13 module gc.arch;
14
15
16 package:
17
18 /**
19  * Small hack to define the string alias if not defined
20  *
21  * Tango don't define this alias in object.d, but Phobos 1 and 2 does.
22  */
23 /*
24  * XXX: this (more general approach) doesn't work:
25  *
26  * static if (!is(string))
27  *    private alias char[] string;
28  *
29  * See: http://d.puremagic.com/issues/show_bug.cgi?id=2848
30  */
31 version (Tango)
32     private alias char[] string;
33
34
35 version (D_Ddoc)
36 {
37
38     /**
39      * Push the registers into the stack.
40      *
41      * Note that this function should be used as a string mixin because if
42      * a regular function call would be done, the stack would be unwound at
43      * function exit and the register will not longer be in the stack.
44      *
45      * A pointer to the top of the stack is stored in a variable with the name
46      * 'sp_name' (which is expected to be a void*).
47      *
48      * Example:
49      * -----------------------------------------------------------------------
50      *  void some_function()
51      *  {
52      *      void* sp;
53      *      mixin(push_registers("sp"));
54      *      // Do something
55      *      mixin(pop_registers("sp"));
56      *  }
57      * -----------------------------------------------------------------------
58      *
59      * See_Also: pop_registers()
60      *
61      */
62     string push_registers(string sp_name);
63
64     /**
65      * Pop the registers out the stack.
66      *
67      * Note that this function should be used as a string mixin (see
68      * push_registers() for more details).
69      *
70      * A pointer to the top of the stack can be obtained from a variable with
71      * the name 'sp_name' (which is expected to be a void*).
72      *
73      * See_Also: push_registers()
74      */
75     string pop_registers(string sp_name);
76
77 }
78
79
80 // Implementation(s)
81
82 version (GNU)
83 {
84
85     /*
86      * GCC has an intrinsic function that does the job of pushing the
87      * registers into the stack, we use that function if available because it
88      * should work in all GCC supported architectures.
89      *
90      * Nothing needs to be done to pop the registers from the stack.
91      */
92
93     string push_registers(string sp_name)
94     {
95         return "
96             __builtin_unwind_init();
97             " ~ sp_name ~ " = &" ~ sp_name ~ ";
98         ";
99     }
100
101     string pop_registers(string sp_name)
102     {
103         return "";
104     }
105
106 }
107 else version (X86)
108 {
109
110     /*
111      * For X86 PUSHAD/POPAD are not used because they are too susceptible to
112      * compiler optimizations (like omitting the frame pointer).
113      *
114      * This method should work safely with all optimizations because it doesn't
115      * work behind the compilers back.
116      */
117
118     string push_registers(string sp_name)
119     {
120         return "
121             size_t eax, ecx, edx, ebx, ebp, esi, edi;
122             asm
123             {
124                 mov eax[EBP], EAX;
125                 mov ecx[EBP], ECX;
126                 mov edx[EBP], EDX;
127                 mov ebx[EBP], EBX;
128                 mov ebp[EBP], EBP;
129                 mov esi[EBP], ESI;
130                 mov edi[EBP], EDI;
131                 mov " ~ sp_name ~ "[EBP],  ESP;
132             }
133         ";
134     }
135
136     string pop_registers(string sp_name)
137     {
138         return "";
139     }
140
141 }
142 else version (X86_64)
143 {
144
145     /*
146      * See X86 comment above, X86_64 uses the same trick.
147      */
148
149     string push_registers(string sp_name)
150     {
151         return "
152             size_t rax, rbx, rcx, rdx, rbp, rsi, rdi,
153                    r10, r11, r12, r13, r14, r15;
154             asm
155             {
156                 movq rax[RBP], RAX;
157                 movq rbx[RBP], RBX;
158                 movq rcx[RBP], RCX;
159                 movq rdx[RBP], RDX;
160                 movq rbp[RBP], RBP;
161                 movq rsi[RBP], RSI;
162                 movq rdi[RBP], RDI;
163                 movq r10[RBP], R10;
164                 movq r11[RBP], R11;
165                 movq r12[RBP], R12;
166                 movq r13[RBP], R13;
167                 movq r14[RBP], R14;
168                 movq r15[RBP], R15;
169                 movq " ~ sp_name ~ "[RBP],  RSP;
170             }
171         ";
172     }
173
174     string pop_registers(string sp_name)
175     {
176         return "";
177     }
178
179 }
180 else // Unknown compiler/architecture
181 {
182
183     static assert(false, "Don't know how to push registers into the stack "
184                          "for this compiler/architecture");
185
186 }
187
188 // vim: set et sw=4 sts=4 :