Wiki Roadmap Timeline Tickets New Ticket Source Search Help / Guide About Trac Login

root/gen/linker.cpp

Revision 1650:40bd4a0d4870, 9.7 kB (checked in by Tomas Lindquist Olsen, 2 years ago)

Update to work with LLVM 2.7.

Removed use of dyn_cast, llvm no compiles
without exceptions and rtti by
default. We do need exceptions for the libconfig stuff, but rtti isn't
necessary (anymore).

Debug info needs to be rewritten, as in LLVM 2.7 the format has
completely changed. To have something to look at while rewriting, the
old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means
that you have to define this to compile at the moment.

Updated tango 0.99.9 patch to include updated EH runtime code, which is
needed for LLVM 2.7 as well.

Line 
1 #include "gen/linker.h"
2 #include "gen/llvm.h"
3 #include "llvm/Linker.h"
4 #include "llvm/System/Program.h"
5 #if _WIN32
6 #include "llvm/Support/SystemUtils.h"
7 #endif
8
9 #include "root.h"
10 #include "mars.h"
11 #include "module.h"
12
13 #define NO_COUT_LOGGER
14 #include "gen/logger.h"
15 #include "gen/cl_options.h"
16 #include "gen/optimizer.h"
17 #include "gen/programs.h"
18
19 //////////////////////////////////////////////////////////////////////////////
20
21 // Is this useful?
22 llvm::cl::opt<bool> quiet("quiet",
23     llvm::cl::desc("Suppress output of link command (unless -v is also passed)"),
24     llvm::cl::Hidden,
25     llvm::cl::ZeroOrMore,
26     llvm::cl::init(true));
27
28 //////////////////////////////////////////////////////////////////////////////
29
30 typedef std::vector<llvm::Module*> Module_vector;
31
32 void linkModules(llvm::Module* dst, const Module_vector& MV)
33 {
34     if (MV.empty())
35         return;
36
37     llvm::Linker linker("ldc", dst);
38
39     std::string err;
40     for (Module_vector::const_iterator i=MV.begin(); i!=MV.end(); ++i)
41     {
42         if (!linker.LinkInModule(*i, &err))
43         {
44             error("%s", err.c_str());
45             fatal();
46         }
47     }
48 }
49
50 //////////////////////////////////////////////////////////////////////////////
51
52 static llvm::sys::Path gExePath;
53
54 int linkExecutable(const char* argv0)
55 {
56     Logger::println("*** Linking executable ***");
57
58     // error string
59     std::string errstr;
60
61     // find the llvm-ld program
62     llvm::sys::Path ldpath = llvm::sys::Program::FindProgramByName("llvm-ld");
63     if (ldpath.isEmpty())
64     {
65         ldpath.set("llvm-ld");
66     }
67
68     // build arguments
69     std::vector<const char*> args;
70
71     // first the program name ??
72     args.push_back("llvm-ld");
73
74     // output filename
75     std::string exestr;
76     if (global.params.exefile)
77     {   // explicit
78         exestr = global.params.exefile;
79     }
80     else
81     {   // inferred
82         // try root module name
83         if (Module::rootModule)
84             exestr = Module::rootModule->toChars();
85         else
86             exestr = "a.out";
87     }
88     if (global.params.os == OSWindows && !(exestr.substr(exestr.length()-4) == ".exe"))
89         exestr.append(".exe");
90
91     std::string outopt = "-o=" + exestr;
92     args.push_back(outopt.c_str());
93
94     // set the global gExePath
95     gExePath.set(exestr);
96     assert(gExePath.isValid());
97
98     // create path to exe
99     llvm::sys::Path exedir(gExePath);
100     exedir.set(gExePath.getDirname());
101     if (!exedir.exists())
102     {
103         exedir.createDirectoryOnDisk(true, &errstr);
104         if (!errstr.empty())
105         {
106             error("failed to create path to linking output: %s\n%s", exedir.c_str(), errstr.c_str());
107             fatal();
108         }
109     }
110
111     // strip debug info
112     if (!global.params.symdebug)
113         args.push_back("-strip-debug");
114
115     // optimization level
116     if (!optimize())
117         args.push_back("-disable-opt");
118     else
119     {
120         const char* s = 0;
121         switch(optLevel())
122         {
123         case 0:
124             args.push_back("-disable-opt");
125             break;
126         case 1:
127             args.push_back("-globaldce");
128             args.push_back("-disable-opt");
129             args.push_back("-globaldce");
130             args.push_back("-mem2reg");
131         case 2:
132         case 3:
133         case 4:
134         case 5:
135             // use default optimization
136             break;
137         default:
138             assert(0);
139         }
140     }
141
142     // inlining
143     if (!(global.params.useInline || doInline()))
144     {
145         args.push_back("-disable-inlining");
146     }
147
148     // additional linker switches
149     for (int i = 0; i < global.params.linkswitches->dim; i++)
150     {
151         char *p = (char *)global.params.linkswitches->data[i];
152         args.push_back(p);
153     }
154
155     // native please
156     args.push_back("-native");
157
158
159     // user libs
160     for (int i = 0; i < global.params.libfiles->dim; i++)
161     {
162         char *p = (char *)global.params.libfiles->data[i];
163         args.push_back(p);
164     }
165
166     // default libs
167     switch(global.params.os) {
168     case OSLinux:
169     case OSMacOSX:
170         args.push_back("-ldl");
171     case OSFreeBSD:
172         args.push_back("-lpthread");
173         args.push_back("-lm");
174         break;
175
176     case OSWindows:
177         // FIXME: I'd assume kernel32 etc
178         break;
179     }
180
181     // object files
182     for (int i = 0; i < global.params.objfiles->dim; i++)
183     {
184         char *p = (char *)global.params.objfiles->data[i];
185         args.push_back(p);
186     }
187
188     // print link command?
189     if (!quiet || global.params.verbose)
190     {
191         // Print it
192         for (int i = 0; i < args.size(); i++)
193             printf("%s ", args[i]);
194         printf("\n");
195         fflush(stdout);
196     }
197
198     // terminate args list
199     args.push_back(NULL);
200
201     // try to call linker!!!
202     if (int status = llvm::sys::Program::ExecuteAndWait(ldpath, &args[0], NULL, NULL, 0,0, &errstr))
203     {
204         error("linking failed:\nstatus: %d", status);
205         if (!errstr.empty())
206             error("message: %s", errstr.c_str());
207         return status;
208     }
209
210     return 0;
211 }
212
213 //////////////////////////////////////////////////////////////////////////////
214
215 int linkObjToExecutable(const char* argv0)
216 {
217     Logger::println("*** Linking executable ***");
218
219     // error string
220     std::string errstr;
221
222     // find gcc for linking
223     llvm::sys::Path gcc = getGcc();
224     // get a string version for argv[0]
225     const char* gccStr = gcc.c_str();
226
227     // build arguments
228     std::vector<const char*> args;
229
230     // first the program name ??
231     args.push_back(gccStr);
232
233     // object files
234     for (int i = 0; i < global.params.objfiles->dim; i++)
235     {
236         char *p = (char *)global.params.objfiles->data[i];
237         args.push_back(p);
238     }
239
240     // output filename
241     std::string exestr;
242     if (global.params.exefile)
243     {   // explicit
244         exestr = global.params.exefile;
245     }
246     else
247     {   // inferred
248         // try root module name
249         if (Module::rootModule)
250             exestr = Module::rootModule->toChars();
251         else if (global.params.objfiles->dim)
252             exestr = FileName::removeExt((char*)global.params.objfiles->data[0]);
253         else
254             exestr = "a.out";
255     }
256     if (global.params.os == OSWindows && !(exestr.rfind(".exe") == exestr.length()-4))
257         exestr.append(".exe");
258
259     args.push_back("-o");
260     args.push_back(exestr.c_str());
261
262     // set the global gExePath
263     gExePath.set(exestr);
264     assert(gExePath.isValid());
265
266     // create path to exe
267     llvm::sys::Path exedir(gExePath);
268     exedir.set(gExePath.getDirname());
269     if (!exedir.exists())
270     {
271         exedir.createDirectoryOnDisk(true, &errstr);
272         if (!errstr.empty())
273         {
274             error("failed to create path to linking output: %s\n%s", exedir.c_str(), errstr.c_str());
275             fatal();
276         }
277     }
278
279     // additional linker switches
280     for (int i = 0; i < global.params.linkswitches->dim; i++)
281     {
282         char *p = (char *)global.params.linkswitches->data[i];
283         args.push_back(p);
284     }
285
286     // user libs
287     for (int i = 0; i < global.params.libfiles->dim; i++)
288     {
289         char *p = (char *)global.params.libfiles->data[i];
290         args.push_back(p);
291     }
292
293     // default libs
294     switch(global.params.os) {
295     case OSLinux:
296     case OSMacOSX:
297         args.push_back("-ldl");
298         // fallthrough
299     case OSFreeBSD:
300         args.push_back("-lpthread");
301         args.push_back("-lm");
302         break;
303
304     case OSSolaris:
305         args.push_back("-lm");
306         args.push_back("-lumem");
307         // solaris TODO
308         break;
309
310     case OSWindows:
311         // FIXME: I'd assume kernel32 etc
312         break;
313     }
314
315     //FIXME: enforce 64 bit
316     if (global.params.is64bit)
317         args.push_back("-m64");
318     else
319         // Assume 32-bit?
320         args.push_back("-m32");
321
322     // print link command?
323     if (!quiet || global.params.verbose)
324     {
325         // Print it
326         for (int i = 0; i < args.size(); i++)
327             printf("%s ", args[i]);
328         printf("\n");
329         fflush(stdout);
330     }
331
332     Logger::println("Linking with: ");
333     std::vector<const char*>::const_iterator I = args.begin(), E = args.end();
334     Stream logstr = Logger::cout();
335     for (; I != E; ++I)
336         if (*I)
337             logstr << "'" << *I << "'" << " ";
338     logstr << "\n"; // FIXME where's flush ?
339
340
341     // terminate args list
342     args.push_back(NULL);
343
344     // try to call linker
345     if (int status = llvm::sys::Program::ExecuteAndWait(gcc, &args[0], NULL, NULL, 0,0, &errstr))
346     {
347         error("linking failed:\nstatus: %d", status);
348         if (!errstr.empty())
349             error("message: %s", errstr.c_str());
350         return status;
351     }
352
353     return 0;
354 }
355
356 //////////////////////////////////////////////////////////////////////////////
357
358 void deleteExecutable()
359 {
360     if (!gExePath.isEmpty())
361     {
362         assert(gExePath.isValid());
363         assert(!gExePath.isDirectory());
364         gExePath.eraseFromDisk(false);
365     }
366 }
367
368 //////////////////////////////////////////////////////////////////////////////
369
370 int runExecutable()
371 {
372     assert(!gExePath.isEmpty());
373     assert(gExePath.isValid());
374
375     // build arguments
376     std::vector<const char*> args;
377     // args[0] should be the name of the executable
378     args.push_back(gExePath.c_str());
379     // Skip first argument to -run; it's a D source file.
380     for (size_t i = 1, length = opts::runargs.size(); i < length; i++)
381     {
382         args.push_back(opts::runargs[i].c_str());
383     }
384     // terminate args list
385     args.push_back(NULL);
386
387     // try to call linker!!!
388     std::string errstr;
389     int status = llvm::sys::Program::ExecuteAndWait(gExePath, &args[0], NULL, NULL, 0,0, &errstr);
390     if (status < 0)
391     {
392         error("program received signal %d (%s)", -status, strsignal(-status));
393         return -status;
394     }
395
396     if (!errstr.empty())
397     {
398         error("failed to execute program");
399         if (!errstr.empty())
400             error("error message: %s", errstr.c_str());
401         fatal();
402     }
403     return status;
404 }
Note: See TracBrowser for help on using the browser.
Copyright © 2008, LDC Development Team.