Mercurial > projects > ddmd
annotate dmd/backend/glue.d @ 25:3f834bed4f13
FWindows linking issues fixed
author | korDen |
---|---|
date | Tue, 13 Apr 2010 00:38:04 +0400 |
parents | 5c9b78899f5d |
children | 544b922227c7 |
rev | line source |
---|---|
0 | 1 module dmd.backend.glue; |
2 | |
3 import dmd.Array; | |
4 import dmd.Dsymbol; | |
5 import dmd.File; | |
6 import dmd.FileName; | |
7 import dmd.Library; | |
8 import dmd.OutBuffer; | |
9 import dmd.Module; | |
10 import dmd.Identifier; | |
11 import dmd.AssertExp; | |
12 import dmd.TOK; | |
13 import dmd.Global; | |
14 import dmd.Param; | |
15 import dmd.backend.Config; | |
16 import dmd.backend.Configv; | |
17 import dmd.backend.StringTab; | |
18 | |
19 import core.stdc.string; | |
20 | |
21 __gshared Array obj_symbols_towrite; | |
22 | |
25 | 23 version (Windows) { |
24 extern (C++) extern | |
25 { | |
26 __gshared Outbuffer objbuf; | |
27 int go_flag(char* cp); | |
28 void util_set64(); | |
29 void util_set386(); | |
30 } | |
31 } else { | |
32 extern (C++) /+extern+/ | |
33 { | |
34 extern(C) extern __gshared Outbuffer objbuf; | |
35 int go_flag(char* cp); | |
36 void util_set64(); | |
37 void util_set386(); | |
38 } | |
0 | 39 } |
40 | |
41 import std.contracts; | |
42 import std.string; | |
43 | |
44 string lastmname; | |
45 | |
46 struct Outbuffer | |
47 { | |
48 ubyte* buf; // the buffer itself | |
49 ubyte* pend; // pointer past the end of the buffer | |
50 ubyte* p; // current position in buffer | |
51 uint len; // size of buffer | |
52 uint inc; // default increment size | |
53 | |
54 this(uint inc) | |
55 { | |
56 assert(false); | |
57 } | |
58 | |
59 ~this() | |
60 { | |
61 assert(false); | |
62 } | |
63 | |
64 void reset() | |
65 { | |
66 assert(false); | |
67 } | |
68 | |
69 // Reserve nbytes in buffer | |
70 void reserve(uint nbytes) | |
71 { | |
72 assert(false); | |
73 } | |
74 | |
75 // Write n zeros; return pointer to start of zeros | |
76 void* writezeros(uint n) | |
77 { | |
78 assert(false); | |
79 } | |
80 | |
81 // Position buffer to accept the specified number of bytes at offset | |
82 int position(uint offset, uint nbytes); | |
83 | |
84 // Write an array to the buffer, no reserve check | |
85 void writen(const(void)* b, int len) | |
86 { | |
87 memcpy(p,b,len); | |
88 p += len; | |
89 } | |
90 | |
91 // Clear bytes, no reserve check | |
92 void clearn(int len) | |
93 { | |
94 int i; | |
95 for (i=0; i< len; i++) | |
96 *p++ = 0; | |
97 } | |
98 | |
99 // Write an array to the buffer. | |
100 void write(const void *b, int len) | |
101 { | |
102 assert(false); | |
103 } | |
104 | |
105 void write(Outbuffer* b) | |
106 { | |
107 write(b.buf, b.p - b.buf); | |
108 } | |
109 | |
110 /** | |
111 * Flushes the stream. This will write any buffered | |
112 * output bytes. | |
113 */ | |
114 void flush() { } | |
115 | |
116 /** | |
117 * Writes an 8 bit byte, no reserve check. | |
118 */ | |
119 void writeByten(char v) | |
120 { | |
121 *p++ = v; | |
122 } | |
123 | |
124 /** | |
125 * Writes an 8 bit byte. | |
126 */ | |
127 void writeByte(int v) | |
128 { | |
129 assert(false); | |
130 } | |
131 | |
132 /** | |
133 * Writes a 16 bit little-end short, no reserve check. | |
134 */ | |
135 void writeWordn(int v) | |
136 { | |
137 version (_WIN32) { | |
138 *cast(ushort*)p = cast(short)v; | |
139 } else { | |
14
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
140 assert(0, "Check this"); |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
141 p[0] = cast(ubyte)v; |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
142 p[1] = cast(ubyte)(v >> 8); |
0 | 143 } |
144 p += 2; | |
145 } | |
146 | |
147 /** | |
148 * Writes a 16 bit little-end short. | |
149 */ | |
150 void writeWord(int v) | |
151 { | |
152 reserve(2); | |
153 writeWordn(v); | |
154 } | |
155 | |
156 /** | |
157 * Writes a 16 bit big-end short. | |
158 */ | |
159 void writeShort(int v) | |
160 { | |
161 if (pend - p < 2) | |
162 reserve(2); | |
163 | |
164 static if (false) { | |
165 p[0] = (cast(ubyte*)&v)[1]; | |
166 p[1] = v; | |
167 } else { | |
168 ubyte* q = p; | |
169 q[0] = cast(ubyte)(v >> 8); | |
170 q[1] = cast(ubyte)v; | |
171 } | |
172 p += 2; | |
173 } | |
174 | |
175 /** | |
176 * Writes a 16 bit char. | |
177 */ | |
178 void writeChar(int v) | |
179 { | |
180 writeShort(v); | |
181 } | |
182 | |
183 /** | |
184 * Writes a 32 bit int. | |
185 */ | |
186 void write32(long v) | |
187 { | |
188 assert(false); | |
189 } | |
190 | |
191 /** | |
192 * Writes a 64 bit long. | |
193 */ | |
194 ///#if __INTSIZE == 4 | |
195 void write64(long v) | |
196 { | |
197 assert(false); | |
198 } | |
199 ///#endif | |
200 | |
201 /** | |
202 * Writes a 32 bit float. | |
203 */ | |
204 void writeFloat(float v) | |
205 { | |
206 assert(false); | |
207 } | |
208 | |
209 /** | |
210 * Writes a 64 bit double. | |
211 */ | |
212 void writeDouble(double v) | |
213 { | |
214 assert(false); | |
215 } | |
216 | |
217 void write(const(char)* s) | |
218 { | |
219 assert(false); | |
220 } | |
221 | |
222 void write(const(ubyte)* s) | |
223 { | |
224 assert(false); | |
225 } | |
226 | |
227 void writeString(const(char)* s) | |
228 { | |
229 assert(false); | |
230 } | |
231 | |
232 void prependBytes(const(char)* s) | |
233 { | |
234 assert(false); | |
235 } | |
236 | |
237 void bracket(char c1, char c2) | |
238 { | |
239 assert(false); | |
240 } | |
241 | |
242 /** | |
243 * Returns the number of bytes written. | |
244 */ | |
245 int size() | |
246 { | |
247 return p - buf; | |
248 } | |
249 | |
250 char* toString() | |
251 { | |
252 assert(false); | |
253 } | |
254 | |
255 void setsize(uint size) | |
256 { | |
257 assert(false); | |
258 } | |
259 | |
260 void writesLEB128(long value) | |
261 { | |
262 assert(false); | |
263 } | |
264 | |
265 void writeuLEB128(uint value) | |
266 { | |
267 assert(false); | |
268 } | |
269 } | |
270 | |
271 static this() | |
272 { | |
273 obj_symbols_towrite = new Array(); | |
274 } | |
275 | |
276 /************************************** | |
277 * Append s to list of object files to generate later. | |
278 */ | |
279 | |
280 void obj_append(Dsymbol s) | |
281 { | |
282 obj_symbols_towrite.push(cast(void*)s); | |
283 } | |
284 | |
14
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
285 version (Bug4059) |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
286 { |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
287 private extern (C) void _Z8obj_initP9OutbufferPKcS2_(Outbuffer* objbuf, const(char)* filename, const(char)* csegname); |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
288 void obj_init(Outbuffer* objbuf, const(char)* filename, const(char)* csegname) { return _Z8obj_initP9OutbufferPKcS2_(objbuf, filename, csegname); } |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
289 } |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
290 else |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
291 { |
25 | 292 extern (C++) { |
293 void obj_init(Outbuffer* objbuf, const(char)* filename, const(char)* csegname); | |
294 } | |
14
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
295 } |
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
296 |
0 | 297 extern (C++) { |
298 void backend_init(); | |
299 void backend_term(); | |
300 void obj_term(); | |
301 void rtlsym_reset(); | |
302 void slist_reset(); | |
303 void el_reset(); | |
304 void cg87_reset(); | |
305 void out_reset(); | |
306 } | |
307 | |
308 void clearStringTab() | |
309 { | |
310 //printf("clearStringTab()\n"); | |
311 memset(stringTab.ptr, 0, stringTab.sizeof); | |
312 stidx = 0; | |
313 | |
314 assertexp_sfilename = null; | |
315 assertexp_name = null; | |
316 assertexp_mn = null; | |
317 } | |
318 | |
319 void obj_start(char *srcfile) | |
320 { | |
321 //printf("obj_start()\n"); | |
322 | |
323 out_config_init(); | |
324 | |
325 rtlsym_reset(); | |
326 slist_reset(); | |
327 clearStringTab(); | |
328 | |
329 obj_init(&objbuf, srcfile, null); | |
330 | |
331 el_reset(); | |
332 cg87_reset(); | |
333 out_reset(); | |
334 } | |
335 | |
336 void obj_end(Library library, File objfile) | |
337 { | |
338 obj_term(); | |
339 | |
340 if (library) | |
341 { | |
342 // Transfer image to library | |
343 library.addObject(objfile.name.toChars(), objbuf.buf, objbuf.p - objbuf.buf); | |
344 objbuf.buf = null; | |
345 } | |
346 else | |
347 { | |
348 // Transfer image to file | |
349 objfile.setbuffer(objbuf.buf, objbuf.p - objbuf.buf); | |
350 objbuf.buf = null; | |
351 | |
352 string p = FileName.path(objfile.name.toChars()); | |
353 FileName.ensurePathExists(p); | |
354 //mem.free(p); | |
355 | |
356 //printf("write obj %s\n", objfile.name.toChars()); | |
357 objfile.writev(); | |
358 } | |
359 | |
360 objbuf.pend = null; | |
361 objbuf.p = null; | |
362 objbuf.len = 0; | |
363 objbuf.inc = 0; | |
364 } | |
365 | |
366 void obj_write_deferred(Library library) | |
367 { | |
368 for (int i = 0; i < obj_symbols_towrite.dim; i++) | |
369 { | |
370 Dsymbol s = cast(Dsymbol)obj_symbols_towrite.data[i]; | |
371 Module m = s.getModule(); | |
372 | |
373 string mname; | |
374 if (m) | |
375 { | |
376 mname = m.srcfile.toChars(); | |
377 lastmname = mname; | |
378 } | |
379 else | |
380 { | |
381 //mname = s->ident->toChars(); | |
382 mname = lastmname; | |
383 assert(mname.length != 0); | |
384 } | |
385 | |
386 obj_start(cast(char*)toStringz(mname)); | |
387 | |
388 static int count; | |
389 count++; // sequence for generating names | |
390 | |
391 /* Create a module that's a doppelganger of m, with just | |
392 * enough to be able to create the moduleinfo. | |
393 */ | |
394 OutBuffer idbuf = new OutBuffer(); | |
395 idbuf.printf("%s.%d", m ? m.ident.toChars() : mname, count); | |
396 string idstr = idbuf.extractString(); | |
397 idbuf.data = null; | |
398 Identifier id = new Identifier(idstr, TOK.TOKidentifier); | |
399 | |
400 Module md = new Module(mname, id, 0, 0); | |
401 md.members = new Array(); | |
402 md.members.push(cast(void*)s); // its only 'member' is s | |
403 if (m) | |
404 { | |
405 md.doppelganger = 1; // identify this module as doppelganger | |
406 md.md = m.md; | |
407 md.aimports.push(cast(void*)m); // it only 'imports' m | |
408 md.massert = m.massert; | |
409 md.marray = m.marray; | |
410 } | |
411 | |
412 md.genobjfile(0); | |
413 | |
414 /* Set object file name to be source name with sequence number, | |
415 * as mangled symbol names get way too long. | |
416 */ | |
417 string fname = FileName.removeExt(mname); | |
418 | |
419 OutBuffer namebuf = new OutBuffer(); | |
420 uint hash = 0; | |
421 foreach (char c; s.toChars()) | |
422 hash += c; | |
423 | |
424 namebuf.printf("%s_%x_%x.%s", fname, count, hash, global.obj_ext); | |
425 fname = namebuf.extractString(); | |
426 | |
427 //printf("writing '%s'\n", fname); | |
428 File objfile = new File(fname); | |
429 obj_end(library, objfile); | |
430 } | |
431 | |
432 obj_symbols_towrite.dim = 0; | |
433 } | |
434 | |
435 /************************************** | |
436 * Initialize config variables. | |
437 */ | |
438 | |
439 void out_config_init() | |
440 { | |
441 Param* params = &global.params; | |
442 | |
443 if (!config.target_cpu) | |
444 { | |
445 config.target_cpu = TARGET_PentiumPro; | |
446 config.target_scheduler = config.target_cpu; | |
447 } | |
448 config.fulltypes = CVNONE; | |
449 config.inline8087 = 1; | |
450 config.memmodel = 0; | |
451 config.flags |= CFGuchar; // make sure TYchar is unsigned | |
452 version (TARGET_WINDOS) { | |
453 if (params.isX86_64) | |
454 config.exe = EX_WIN64; | |
455 else | |
456 config.exe = EX_NT; | |
457 | |
458 // Win32 eh | |
459 config.flags2 |= CFG2seh; | |
460 | |
461 if (params.run) | |
462 config.wflags |= WFexe; // EXE file only optimizations | |
463 else if (params.link && !global.params.deffile) | |
464 config.wflags |= WFexe; // EXE file only optimizations | |
465 else if (params.exefile) // if writing out EXE file | |
466 { | |
467 size_t len = params.exefile.length; | |
468 if (len >= 4 && icmp(params.exefile[len-3..len], "exe") == 0) | |
469 config.wflags |= WFexe; | |
470 } | |
471 config.flags4 |= CFG4underscore; | |
472 } | |
473 version (TARGET_LINUX) { | |
474 if (params.isX86_64) | |
475 config.exe = EX_LINUX64; | |
476 else | |
477 config.exe = EX_LINUX; | |
478 config.flags |= CFGnoebp; | |
479 config.flags |= CFGalwaysframe; | |
480 if (params.pic) | |
481 config.flags3 |= CFG3pic; | |
482 } | |
483 version (TARGET_OSX) { | |
484 if (params.isX86_64) | |
485 config.exe = EX_OSX64; | |
486 else | |
487 config.exe = EX_OSX; | |
488 config.flags |= CFGnoebp; | |
489 config.flags |= CFGalwaysframe; | |
490 if (params.pic) | |
491 config.flags3 |= CFG3pic; | |
492 } | |
493 version (TARGET_FREEBSD) { | |
494 if (params.isX86_64) | |
495 config.exe = EX_FREEBSD64; | |
496 else | |
497 config.exe = EX_FREEBSD; | |
498 config.flags |= CFGnoebp; | |
499 config.flags |= CFGalwaysframe; | |
500 if (params.pic) | |
501 config.flags3 |= CFG3pic; | |
502 } | |
503 version (TARGET_SOLARIS) { | |
504 if (params.isX86_64) | |
505 config.exe = EX_SOLARIS64; | |
506 else | |
507 config.exe = EX_SOLARIS; | |
508 config.flags |= CFGnoebp; | |
509 config.flags |= CFGalwaysframe; | |
510 if (params.pic) | |
511 config.flags3 |= CFG3pic; | |
512 } | |
513 config.flags2 |= CFG2nodeflib; // no default library | |
514 config.flags3 |= CFG3eseqds; | |
515 static if (false) { | |
516 if (env.getEEcontext().EEcompile != 2) | |
517 config.flags4 |= CFG4allcomdat; | |
518 if (env.nochecks()) | |
519 config.flags4 |= CFG4nochecks; // no runtime checking | |
520 } else version (TARGET_OSX) { | |
521 } else { | |
522 config.flags4 |= CFG4allcomdat; | |
523 } | |
524 if (params.trace) | |
525 config.flags |= CFGtrace; // turn on profiler | |
526 if (params.nofloat) | |
527 config.flags3 |= CFG3wkfloat; | |
528 | |
529 configv.verbose = params.verbose; | |
530 | |
531 if (params.optimize) | |
532 go_flag(cast(char*)"-o".ptr); | |
533 | |
534 if (params.symdebug) | |
535 { | |
536 version (ELFOBJ_OR_MACHOBJ) { | |
537 configv.addlinenumbers = 1; | |
538 config.fulltypes = (params.symdebug == 1) ? CVDWARF_D : CVDWARF_C; | |
539 } | |
540 version (OMFOBJ) { | |
541 configv.addlinenumbers = 1; | |
542 config.fulltypes = CV4; | |
543 } | |
544 if (!params.optimize) | |
545 config.flags |= CFGalwaysframe; | |
546 } | |
547 else | |
548 { | |
549 configv.addlinenumbers = 0; | |
550 config.fulltypes = CVNONE; | |
551 //config.flags &= ~CFGalwaysframe; | |
552 } | |
553 | |
554 if (params.isX86_64) | |
555 { | |
556 util_set64(); | |
557 cod3_set64(); | |
558 } | |
559 else | |
560 { | |
561 util_set386(); | |
562 cod3_set386(); | |
563 } | |
564 | |
565 debug { | |
566 debugb = params.debugb; | |
567 debugc = params.debugc; | |
568 debugf = params.debugf; | |
569 debugr = params.debugr; | |
570 debugw = params.debugw; | |
571 debugx = params.debugx; | |
572 debugy = params.debugy; | |
573 } | |
14
2cc604139636
Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
574 } |