comparison dmd/link.c @ 276:21f85bac0b1a trunk

[svn r297] Fixed: rewrote linker code to use LLVM's Program facilities instead of DMD's oldschool broken "native" approach.
author lindquist
date Fri, 20 Jun 2008 17:45:13 +0200
parents b77664331d06
children
comparison
equal deleted inserted replaced
275:665b81613475 276:21f85bac0b1a
34 34
35 #include "gen/logger.h" 35 #include "gen/logger.h"
36 36
37 int executecmd(char *cmd, char *args, int useenv); 37 int executecmd(char *cmd, char *args, int useenv);
38 int executearg0(char *cmd, char *args); 38 int executearg0(char *cmd, char *args);
39
40 /*****************************
41 * Run the linker. Return status of execution.
42 */
43
44 int runLINK()
45 {
46 Logger::println("*** Linking executable ***");
47
48 #if _WIN32
49 assert(0 && "linking not done for win32");
50
51 char *p;
52 int i;
53 int status;
54 OutBuffer cmdbuf;
55
56 global.params.libfiles->push((void *) "user32");
57 global.params.libfiles->push((void *) "kernel32");
58
59 for (i = 0; i < global.params.objfiles->dim; i++)
60 {
61 if (i)
62 cmdbuf.writeByte('+');
63 p = (char *)global.params.objfiles->data[i];
64 char *ext = FileName::ext(p);
65 if (ext)
66 cmdbuf.write(p, ext - p - 1);
67 else
68 cmdbuf.writestring(p);
69 }
70 cmdbuf.writeByte(',');
71 if (global.params.exefile)
72 cmdbuf.writestring(global.params.exefile);
73 else
74 { // Generate exe file name from first obj name
75 char *n = (char *)global.params.objfiles->data[0];
76 char *ex;
77
78 n = FileName::name(n);
79 FileName *fn = FileName::forceExt(n, "exe");
80 global.params.exefile = fn->toChars();
81 }
82
83 // Make sure path to exe file exists
84 { char *p = FileName::path(global.params.exefile);
85 FileName::ensurePathExists(p);
86 mem.free(p);
87 }
88
89 cmdbuf.writeByte(',');
90 if (global.params.run)
91 cmdbuf.writestring("nul");
92 // if (mapfile)
93 // cmdbuf.writestring(output);
94 cmdbuf.writeByte(',');
95
96 for (i = 0; i < global.params.libfiles->dim; i++)
97 {
98 if (i)
99 cmdbuf.writeByte('+');
100 cmdbuf.writestring((char *) global.params.libfiles->data[i]);
101 }
102
103 if (global.params.deffile)
104 {
105 cmdbuf.writeByte(',');
106 cmdbuf.writestring(global.params.deffile);
107 }
108
109 /* Eliminate unnecessary trailing commas */
110 while (1)
111 { i = cmdbuf.offset;
112 if (!i || cmdbuf.data[i - 1] != ',')
113 break;
114 cmdbuf.offset--;
115 }
116
117 if (global.params.resfile)
118 {
119 cmdbuf.writestring("/RC:");
120 cmdbuf.writestring(global.params.resfile);
121 }
122
123 #if 0
124 if (mapfile)
125 cmdbuf.writestring("/m");
126 if (debuginfo)
127 cmdbuf.writestring("/li");
128 if (codeview)
129 {
130 cmdbuf.writestring("/co");
131 if (codeview3)
132 cmdbuf.writestring(":3");
133 }
134 #else
135 if (global.params.symdebug)
136 cmdbuf.writestring("/co");
137 #endif
138
139 cmdbuf.writestring("/noi");
140 for (i = 0; i < global.params.linkswitches->dim; i++)
141 {
142 cmdbuf.writestring((char *) global.params.linkswitches->data[i]);
143 }
144 cmdbuf.writeByte(';');
145
146 p = cmdbuf.toChars();
147
148 FileName *lnkfilename = NULL;
149 size_t plen = strlen(p);
150 if (plen > 7000)
151 {
152 lnkfilename = FileName::forceExt(global.params.exefile, "lnk");
153 File flnk(lnkfilename);
154 flnk.setbuffer(p, plen);
155 flnk.ref = 1;
156 if (flnk.write())
157 error("error writing file %s", lnkfilename);
158 if (lnkfilename->len() < plen)
159 sprintf(p, "@%s", lnkfilename->toChars());
160 }
161
162 char *linkcmd = getenv("LINKCMD");
163 if (!linkcmd)
164 linkcmd = "link";
165 status = executecmd(linkcmd, p, 1);
166 if (lnkfilename)
167 {
168 remove(lnkfilename->toChars());
169 delete lnkfilename;
170 }
171 return status;
172 #elif linux
173 pid_t childpid;
174 int i;
175 int status;
176
177 // Build argv[]
178 Array argv;
179
180 //char *cc = getenv("CC");
181 //if (!cc)
182 //cc = "gcc";
183 char *cc = "llvm-ld";
184 argv.push((void *)cc);
185
186 // None of that a.out stuff. Use explicit exe file name, or
187 // generate one from name of first source file.
188 OutBuffer* exestr = new OutBuffer;
189 if (global.params.exefile)
190 {
191 exestr->printf("-o=%s", global.params.exefile);
192 argv.push(exestr->toChars());
193 }
194 else
195 { // Generate exe file name from first obj name
196 char *n = (char *)global.params.objfiles->data[0];
197 char *e;
198 char *ex;
199
200 n = FileName::name(n);
201 e = FileName::ext(n);
202 if (e)
203 {
204 e--; // back up over '.'
205 ex = (char *)mem.malloc(e - n + 1);
206 memcpy(ex, n, e - n);
207 ex[e - n] = 0;
208 }
209 else
210 ex = (char *)"a.out"; // no extension, so give up
211 exestr->printf("-o=%s", ex);
212 ex = exestr->toChars();
213 argv.push(ex);
214 global.params.exefile = ex;
215 }
216
217 // Make sure path to exe file exists
218 { char *p = FileName::path(global.params.exefile);
219 FileName::ensurePathExists(p);
220 mem.free(p);
221 }
222
223 argv.insert(argv.dim, global.params.libfiles);
224
225 if (!global.params.symdebug)
226 argv.push((void *)"-strip-debug");
227
228 //argv.push((void *)"-m32");
229
230
231 if (!global.params.optimize)
232 argv.push((void *)"-disable-opt");
233 else {
234 const char* s = 0;
235 switch(global.params.optimizeLevel) {
236 case 0:
237 s = "-O0"; break;
238 case 1:
239 s = "-O1"; break;
240 case 2:
241 s = "-O2"; break;
242 case 3:
243 s = "-O3"; break;
244 case 4:
245 s = "-O4"; break;
246 case 5:
247 s = "-O5"; break;
248 default:
249 assert(0);
250 }
251 argv.push((void*)s);
252 }
253
254 if (!(global.params.useInline || global.params.llvmInline)) {
255 argv.push((void *)"-disable-inlining");
256 }
257
258 #if 0
259 if (0 && global.params.exefile)
260 {
261 /* This switch enables what is known as 'smart linking'
262 * in the Windows world, where unreferenced sections
263 * are removed from the executable. It eliminates unreferenced
264 * functions, essentially making a 'library' out of a module.
265 * Although it is documented to work with ld version 2.13,
266 * in practice it does not, but just seems to be ignored.
267 * Thomas Kuehne has verified that it works with ld 2.16.1.
268 * BUG: disabled because it causes exception handling to fail
269 */
270 argv.push((void *)"-Xlinker");
271 argv.push((void *)"--gc-sections");
272 }
273 #endif
274
275 for (i = 0; i < global.params.linkswitches->dim; i++)
276 { char *p = (char *)global.params.linkswitches->data[i];
277 //if (!p || !p[0] || !(p[0] == '-' && p[1] == 'l'))
278 //{ // Don't need -Xlinker if switch starts with -l
279 // argv.push((void *)"-Xlinker");
280 //}
281 argv.push((void *) p);
282 }
283
284 argv.push((void*)"-native");
285
286 /* Standard libraries must go after user specified libraries
287 * passed with -l.
288 */
289
290 argv.push((void*)"-ltango-base-c-llvmdc");
291 argv.push((void*)"-lpthread");
292 argv.push((void*)"-ldl");
293 argv.push((void*)"-lm");
294
295 argv.append(global.params.objfiles);
296
297 std::string runtime_path(global.params.runtimePath);
298 if (*runtime_path.rbegin() != '/')
299 runtime_path.append("/");
300 runtime_path.append("libtango-base-llvmdc.a");
301 argv.push((void*)runtime_path.c_str());
302
303 if (!global.params.quiet || global.params.verbose)
304 {
305 // Print it
306 for (i = 0; i < argv.dim; i++)
307 printf("%s ", (char *)argv.data[i]);
308 printf("\n");
309 fflush(stdout);
310 }
311
312 argv.push(NULL);
313 childpid = fork();
314 if (childpid == 0)
315 {
316 execvp((char *)argv.data[0], (char **)argv.data);
317 perror((char *)argv.data[0]); // failed to execute
318 return -1;
319 }
320
321 waitpid(childpid, &status, 0);
322
323 status=WEXITSTATUS(status);
324 if (status)
325 printf("--- errorlevel %d\n", status);
326 return status;
327 #else
328 printf ("Linking is not yet supported for this version of LLVMDC.\n");
329 return -1;
330 #endif
331 }
332 39
333 /********************************** 40 /**********************************
334 * Delete generated EXE file. 41 * Delete generated EXE file.
335 */ 42 */
336 43