comparison gen/linker.cpp @ 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 a95056b3c996
children 90a8c798b0db
comparison
equal deleted inserted replaced
275:665b81613475 276:21f85bac0b1a
1 #include "gen/llvm.h" 1 #include "gen/llvm.h"
2 #include "llvm/Linker.h" 2 #include "llvm/Linker.h"
3 #include "llvm/System/Program.h"
3 4
4 #include "root.h" 5 #include "root.h"
5 #include "mars.h" 6 #include "mars.h"
7 #include "module.h"
8
9 #define NO_COUT_LOGGER
10 #include "gen/logger.h"
11
12 //////////////////////////////////////////////////////////////////////////////
6 13
7 typedef std::vector<llvm::Module*> Module_vector; 14 typedef std::vector<llvm::Module*> Module_vector;
8 15
9 void linkModules(llvm::Module* dst, const Module_vector& MV) 16 void linkModules(llvm::Module* dst, const Module_vector& MV)
10 { 17 {
21 error("%s", err.c_str()); 28 error("%s", err.c_str());
22 fatal(); 29 fatal();
23 } 30 }
24 } 31 }
25 } 32 }
33
34 //////////////////////////////////////////////////////////////////////////////
35
36 int linkExecutable()
37 {
38 Logger::println("*** Linking executable ***");
39
40 // error string
41 std::string errstr;
42
43 // find the llvm-ld program
44 llvm::sys::Path ldpath = llvm::sys::Program::FindProgramByName("llvm-ld");
45 if (ldpath.isEmpty())
46 {
47 error("linker program not found");
48 fatal();
49 }
50
51 // build arguments
52 std::vector<const char*> args;
53
54 // first the program name ??
55 args.push_back("llvm-ld");
56
57 // output filename
58 std::string exestr;
59 if (global.params.exefile)
60 { // explicit
61 exestr = global.params.exefile;
62 }
63 else
64 { // inferred
65 // try root module name
66 if (Module::rootModule)
67 exestr = Module::rootModule->toChars();
68 else
69 exestr = "a.out";
70 }
71 if (global.params.isWindows)
72 exestr.append(".exe");
73
74 std::string outopt = "-o=" + exestr;
75 args.push_back(outopt.c_str());
76
77 // create path to exe
78 llvm::sys::Path exepath(exestr);
79 exepath.set(exepath.getDirname());
80 exepath.createDirectoryOnDisk(true, &errstr);
81 if (!errstr.empty())
82 {
83 error("failed to create path to linking output\n%s", errstr.c_str());
84 fatal();
85 }
86
87 // strip debug info
88 if (!global.params.symdebug)
89 args.push_back("-strip-debug");
90
91 // optimization level
92 if (!global.params.optimize)
93 args.push_back("-disable-opt");
94 else
95 {
96 const char* s = 0;
97 switch(global.params.optimizeLevel)
98 {
99 case 0:
100 s = "-O0"; break;
101 case 1:
102 s = "-O1"; break;
103 case 2:
104 s = "-O2"; break;
105 case 3:
106 s = "-O3"; break;
107 case 4:
108 s = "-O4"; break;
109 case 5:
110 s = "-O5"; break;
111 default:
112 assert(0);
113 }
114 args.push_back(s);
115 }
116
117 // inlining
118 if (!(global.params.useInline || global.params.llvmInline))
119 {
120 args.push_back("-disable-inlining");
121 }
122
123 // additional linker switches
124 for (int i = 0; i < global.params.linkswitches->dim; i++)
125 {
126 char *p = (char *)global.params.linkswitches->data[i];
127 args.push_back(p);
128 }
129
130 // native please
131 args.push_back("-native");
132
133
134 // user libs
135 for (int i = 0; i < global.params.libfiles->dim; i++)
136 {
137 char *p = (char *)global.params.libfiles->data[i];
138 args.push_back(p);
139 }
140
141 // default libs
142 args.push_back("-ltango-base-c-llvmdc");
143 args.push_back("-lpthread");
144 args.push_back("-ldl");
145 args.push_back("-lm");
146
147 // object files
148 for (int i = 0; i < global.params.objfiles->dim; i++)
149 {
150 char *p = (char *)global.params.objfiles->data[i];
151 args.push_back(p);
152 }
153
154 // runtime library
155 // must be linked in last to null terminate the moduleinfo appending list
156 std::string runtime_path(global.params.runtimePath);
157 if (*runtime_path.rbegin() != '/')
158 runtime_path.append("/");
159 runtime_path.append("libtango-base-llvmdc.a");
160 args.push_back(runtime_path.c_str());
161
162 // print link command?
163 if (!global.params.quiet || global.params.verbose)
164 {
165 // Print it
166 for (int i = 0; i < args.size(); i++)
167 printf("%s ", args[i]);
168 printf("\n");
169 fflush(stdout);
170 }
171
172 // terminate args list
173 args.push_back(NULL);
174
175 // try to call linker!!!
176 if (int status = llvm::sys::Program::ExecuteAndWait(ldpath, &args[0], NULL, NULL, 0,0, &errstr))
177 {
178 error("linking failed:\nstatus: %d", status);
179 if (!errstr.empty())
180 error("message: %s", errstr.c_str());
181 fatal();
182 }
183 }