forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLink.rs
174 lines (152 loc) · 5.8 KB
/
Link.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import driver.session;
import lib.llvm.llvm;
import middle.trans;
import std.Str;
import std.FS;
import lib.llvm.llvm.ModuleRef;
import lib.llvm.llvm.ValueRef;
import lib.llvm.mk_pass_manager;
import lib.llvm.mk_target_data;
import lib.llvm.mk_type_names;
import lib.llvm.False;
import lib.llvm.True;
tag output_type {
output_type_none;
output_type_bitcode;
output_type_assembly;
output_type_object;
}
fn llvm_err(session.session sess, str msg) {
auto buf = llvm.LLVMRustGetLastError();
if ((buf as uint) == 0u) {
sess.err(msg);
} else {
sess.err(msg + ": " + Str.str_from_cstr(buf));
}
fail;
}
fn link_intrinsics(session.session sess, ModuleRef llmod) {
auto path = FS.connect(sess.get_opts().sysroot, "intrinsics.bc");
auto membuf =
llvm.LLVMRustCreateMemoryBufferWithContentsOfFile(Str.buf(path));
if ((membuf as uint) == 0u) {
llvm_err(sess, "installation problem: couldn't open intrinstics.bc");
fail;
}
auto llintrinsicsmod = llvm.LLVMRustParseBitcode(membuf);
if ((llintrinsicsmod as uint) == 0u) {
llvm_err(sess, "installation problem: couldn't parse intrinstics.bc");
fail;
}
if (llvm.LLVMLinkModules(llmod, llintrinsicsmod) == False) {
llvm_err(sess, "couldn't link the module with the intrinsics");
fail;
}
}
mod Write {
fn is_object_or_assembly(output_type ot) -> bool {
if (ot == output_type_assembly) {
ret true;
}
if (ot == output_type_object) {
ret true;
}
ret false;
}
// Decides what to call an intermediate file, given the name of the output
// and the extension to use.
fn mk_intermediate_name(str output_path, str extension) -> str {
auto dot_pos = Str.index(output_path, '.' as u8);
auto stem;
if (dot_pos < 0) {
stem = output_path;
} else {
stem = Str.substr(output_path, 0u, dot_pos as uint);
}
ret stem + "." + extension;
}
fn run_passes(session.session sess, ModuleRef llmod, str output) {
link_intrinsics(sess, llmod);
auto pm = mk_pass_manager();
auto opts = sess.get_opts();
auto td = mk_target_data(x86.get_data_layout());
llvm.LLVMAddTargetData(td.lltd, pm.llpm);
// TODO: run the linter here also, once there are llvm-c bindings for
// it.
// Generate a pre-optimization intermediate file if -save-temps was
// specified.
if (opts.save_temps) {
alt (opts.output_type) {
case (output_type_bitcode) {
if (opts.optimize != 0u) {
auto filename = mk_intermediate_name(output,
"no-opt.bc");
llvm.LLVMWriteBitcodeToFile(llmod,
Str.buf(filename));
}
}
case (_) {
auto filename = mk_intermediate_name(output, "bc");
llvm.LLVMWriteBitcodeToFile(llmod, Str.buf(filename));
}
}
}
// FIXME: LTO?
if (opts.optimize != 0u) {
let uint threshold = 225u;
auto fpm = mk_pass_manager();
llvm.LLVMAddTargetData(td.lltd, fpm.llpm);
llvm.LLVMAddStandardFunctionPasses(fpm.llpm, opts.optimize);
llvm.LLVMRunPassManager(fpm.llpm, llmod);
if (opts.optimize == 3u) {
threshold = 275u;
}
llvm.LLVMAddStandardModulePasses(pm.llpm,
opts.optimize,// opt level
False, // opt for size
True, // unit-at-a-time
True, // unroll loops
True, // simplifyLibCalls
True, // have exceptions
threshold); // inline threshold
}
if (opts.verify) {
llvm.LLVMAddVerifierPass(pm.llpm);
}
// TODO: Write .s if -c was specified and -save-temps was on.
if (is_object_or_assembly(opts.output_type)) {
let int LLVMAssemblyFile = 0;
let int LLVMObjectFile = 1;
let int LLVMNullFile = 2;
auto FileType;
if (opts.output_type == output_type_object) {
FileType = LLVMObjectFile;
} else {
FileType = LLVMAssemblyFile;
}
// Write optimized bitcode if --save-temps was on.
if (opts.save_temps) {
alt (opts.output_type) {
case (output_type_bitcode) { /* nothing to do */ }
case (_) {
auto filename = mk_intermediate_name(output,
"opt.bc");
llvm.LLVMRunPassManager(pm.llpm, llmod);
llvm.LLVMWriteBitcodeToFile(llmod,
Str.buf(filename));
pm = mk_pass_manager();
}
}
}
llvm.LLVMRustWriteOutputFile(pm.llpm, llmod,
Str.buf(x86.get_target_triple()),
Str.buf(output),
FileType);
llvm.LLVMDisposeModule(llmod);
ret;
}
llvm.LLVMRunPassManager(pm.llpm, llmod);
llvm.LLVMWriteBitcodeToFile(llmod, Str.buf(output));
llvm.LLVMDisposeModule(llmod);
}
}