]>
Commit | Line | Data |
---|---|---|
94b46f34 | 1 | //! Codegen the completed AST to the LLVM IR. |
9346a6ac | 2 | //! |
94b46f34 XL |
3 | //! Some functions here, such as codegen_block and codegen_expr, return a value -- |
4 | //! the result of the codegen to LLVM -- while others, such as codegen_fn | |
5 | //! and mono_item, are called only for the side effect of adding a | |
9346a6ac AL |
6 | //! particular definition to the LLVM IR output we're producing. |
7 | //! | |
94b46f34 | 8 | //! Hopefully useful general knowledge about codegen: |
9346a6ac | 9 | //! |
9fa01778 XL |
10 | //! * There's no way to find out the `Ty` type of a Value. Doing so |
11 | //! would be "trying to get the eggs out of an omelette" (credit: | |
12 | //! pcwalton). You can, instead, find out its `llvm::Type` by calling `val_ty`, | |
13 | //! but one `llvm::Type` corresponds to many `Ty`s; for instance, `tup(int, int, | |
14 | //! int)` and `rec(x=int, y=int, z=int)` will have the same `llvm::Type`. | |
1a4d82fc | 15 | |
532ac7d7 | 16 | use super::{LlvmCodegenBackend, ModuleLlvm}; |
a1dfa0c6 XL |
17 | use rustc_codegen_ssa::{ModuleCodegen, ModuleKind}; |
18 | use rustc_codegen_ssa::base::maybe_create_entry_wrapper; | |
1a4d82fc | 19 | |
9fa01778 XL |
20 | use crate::llvm; |
21 | use crate::metadata; | |
22 | use crate::builder::Builder; | |
23 | use crate::common; | |
24 | use crate::context::CodegenCx; | |
9fa01778 | 25 | use rustc::dep_graph; |
dc9dc135 | 26 | use rustc::mir::mono::{Linkage, Visibility}; |
ff7c6d11 | 27 | use rustc::middle::cstore::{EncodedMetadata}; |
a1dfa0c6 | 28 | use rustc::ty::TyCtxt; |
0531ce1d | 29 | use rustc::middle::exported_symbols; |
48663c56 | 30 | use rustc::session::config::DebugInfo; |
a1dfa0c6 | 31 | use rustc_codegen_ssa::mono_item::MonoItemExt; |
b7449926 | 32 | use rustc_data_structures::small_c_str::SmallCStr; |
1a4d82fc | 33 | |
a1dfa0c6 XL |
34 | use rustc_codegen_ssa::traits::*; |
35 | use rustc_codegen_ssa::back::write::submit_codegened_module_to_llvm; | |
36 | ||
abe05a73 | 37 | use std::ffi::CString; |
a1dfa0c6 | 38 | use std::time::Instant; |
ea8adc8c | 39 | use syntax_pos::symbol::InternedString; |
a1dfa0c6 | 40 | use rustc::hir::CodegenFnAttrs; |
1a4d82fc | 41 | |
9fa01778 | 42 | use crate::value::Value; |
b7449926 | 43 | |
dc9dc135 XL |
44 | pub fn write_compressed_metadata<'tcx>( |
45 | tcx: TyCtxt<'tcx>, | |
48663c56 | 46 | metadata: &EncodedMetadata, |
dc9dc135 | 47 | llvm_module: &mut ModuleLlvm, |
48663c56 | 48 | ) { |
041b39d2 XL |
49 | use std::io::Write; |
50 | use flate2::Compression; | |
51 | use flate2::write::DeflateEncoder; | |
1a4d82fc | 52 | |
b7449926 | 53 | let (metadata_llcx, metadata_llmod) = (&*llvm_module.llcx, llvm_module.llmod()); |
ea8adc8c | 54 | let mut compressed = tcx.metadata_encoding_version(); |
ff7c6d11 | 55 | DeflateEncoder::new(&mut compressed, Compression::fast()) |
041b39d2 | 56 | .write_all(&metadata.raw_data).unwrap(); |
1a4d82fc | 57 | |
a1dfa0c6 XL |
58 | let llmeta = common::bytes_in_context(metadata_llcx, &compressed); |
59 | let llconst = common::struct_in_context(metadata_llcx, &[llmeta], false); | |
0531ce1d | 60 | let name = exported_symbols::metadata_symbol_name(tcx); |
85aaf69f | 61 | let buf = CString::new(name).unwrap(); |
1a4d82fc | 62 | let llglobal = unsafe { |
a1dfa0c6 | 63 | llvm::LLVMAddGlobal(metadata_llmod, common::val_ty(llconst), buf.as_ptr()) |
1a4d82fc JJ |
64 | }; |
65 | unsafe { | |
66 | llvm::LLVMSetInitializer(llglobal, llconst); | |
7cac9316 | 67 | let section_name = metadata::metadata_section_name(&tcx.sess.target.target); |
b7449926 | 68 | let name = SmallCStr::new(section_name); |
5bcae85e SL |
69 | llvm::LLVMSetSection(llglobal, name.as_ptr()); |
70 | ||
71 | // Also generate a .section directive to force no | |
72 | // flags, at least for ELF outputs, so that the | |
73 | // metadata doesn't get loaded into memory. | |
74 | let directive = format!(".section {}", section_name); | |
75 | let directive = CString::new(directive).unwrap(); | |
cc61c64b | 76 | llvm::LLVMSetModuleInlineAsm(metadata_llmod, directive.as_ptr()) |
1a4d82fc | 77 | } |
e9174d1e SL |
78 | } |
79 | ||
b7449926 XL |
80 | pub struct ValueIter<'ll> { |
81 | cur: Option<&'ll Value>, | |
82 | step: unsafe extern "C" fn(&'ll Value) -> Option<&'ll Value>, | |
e9174d1e SL |
83 | } |
84 | ||
b7449926 XL |
85 | impl Iterator for ValueIter<'ll> { |
86 | type Item = &'ll Value; | |
1a4d82fc | 87 | |
b7449926 | 88 | fn next(&mut self) -> Option<&'ll Value> { |
e9174d1e | 89 | let old = self.cur; |
b7449926 | 90 | if let Some(old) = old { |
b039eaaf | 91 | self.cur = unsafe { (self.step)(old) }; |
e9174d1e | 92 | } |
b7449926 | 93 | old |
1a4d82fc | 94 | } |
e9174d1e | 95 | } |
1a4d82fc | 96 | |
b7449926 | 97 | pub fn iter_globals(llmod: &'ll llvm::Module) -> ValueIter<'ll> { |
e9174d1e SL |
98 | unsafe { |
99 | ValueIter { | |
100 | cur: llvm::LLVMGetFirstGlobal(llmod), | |
101 | step: llvm::LLVMGetNextGlobal, | |
102 | } | |
103 | } | |
104 | } | |
1a4d82fc | 105 | |
dc9dc135 | 106 | pub fn compile_codegen_unit(tcx: TyCtxt<'tcx>, cgu_name: InternedString) { |
ea8adc8c | 107 | let start_time = Instant::now(); |
b7449926 XL |
108 | |
109 | let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx); | |
dc9dc135 XL |
110 | let (module, _) = tcx.dep_graph.with_task( |
111 | dep_node, | |
112 | tcx, | |
113 | cgu_name, | |
114 | module_codegen, | |
115 | dep_graph::hash_result, | |
116 | ); | |
94b46f34 | 117 | let time_to_codegen = start_time.elapsed(); |
ea8adc8c XL |
118 | |
119 | // We assume that the cost to run LLVM on a CGU is proportional to | |
94b46f34 XL |
120 | // the time we needed for codegenning it. |
121 | let cost = time_to_codegen.as_secs() * 1_000_000_000 + | |
122 | time_to_codegen.subsec_nanos() as u64; | |
ea8adc8c | 123 | |
a1dfa0c6 | 124 | submit_codegened_module_to_llvm(&LlvmCodegenBackend(()), tcx, module, cost); |
ea8adc8c | 125 | |
dc9dc135 XL |
126 | fn module_codegen<'tcx>( |
127 | tcx: TyCtxt<'tcx>, | |
128 | cgu_name: InternedString, | |
129 | ) -> ModuleCodegen<ModuleLlvm> { | |
b7449926 | 130 | let cgu = tcx.codegen_unit(cgu_name); |
94b46f34 | 131 | // Instantiate monomorphizations without filling out definitions yet... |
532ac7d7 | 132 | let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str()); |
dc9dc135 | 133 | { |
b7449926 | 134 | let cx = CodegenCx::new(tcx, cgu, &llvm_module); |
94b46f34 | 135 | let mono_items = cx.codegen_unit |
b7449926 | 136 | .items_in_deterministic_order(cx.tcx); |
94b46f34 | 137 | for &(mono_item, (linkage, visibility)) in &mono_items { |
9fa01778 | 138 | mono_item.predefine::<Builder<'_, '_, '_>>(&cx, linkage, visibility); |
ea8adc8c XL |
139 | } |
140 | ||
141 | // ... and now that we have everything pre-defined, fill out those definitions. | |
94b46f34 | 142 | for &(mono_item, _) in &mono_items { |
9fa01778 | 143 | mono_item.define::<Builder<'_, '_, '_>>(&cx); |
ea8adc8c XL |
144 | } |
145 | ||
146 | // If this codegen unit contains the main function, also create the | |
147 | // wrapper here | |
9fa01778 | 148 | maybe_create_entry_wrapper::<Builder<'_, '_, '_>>(&cx); |
ea8adc8c XL |
149 | |
150 | // Run replace-all-uses-with for statics that need it | |
a1dfa0c6 | 151 | for &(old_g, new_g) in cx.statics_to_rauw().borrow().iter() { |
ea8adc8c | 152 | unsafe { |
a1dfa0c6 | 153 | let bitcast = llvm::LLVMConstPointerCast(new_g, cx.val_ty(old_g)); |
ea8adc8c XL |
154 | llvm::LLVMReplaceAllUsesWith(old_g, bitcast); |
155 | llvm::LLVMDeleteGlobal(old_g); | |
156 | } | |
157 | } | |
158 | ||
159 | // Create the llvm.used variable | |
160 | // This variable has type [N x i8*] and is stored in the llvm.metadata section | |
a1dfa0c6 XL |
161 | if !cx.used_statics().borrow().is_empty() { |
162 | cx.create_used_variable() | |
ea8adc8c XL |
163 | } |
164 | ||
165 | // Finalize debuginfo | |
b7449926 | 166 | if cx.sess().opts.debuginfo != DebugInfo::None { |
a1dfa0c6 | 167 | cx.debuginfo_finalize(); |
ea8adc8c | 168 | } |
dc9dc135 | 169 | } |
ea8adc8c | 170 | |
dc9dc135 | 171 | ModuleCodegen { |
b7449926 XL |
172 | name: cgu_name.to_string(), |
173 | module_llvm: llvm_module, | |
174 | kind: ModuleKind::Regular, | |
dc9dc135 | 175 | } |
ea8adc8c XL |
176 | } |
177 | } | |
178 | ||
a1dfa0c6 XL |
179 | pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) { |
180 | let sect = match attrs.link_section { | |
181 | Some(name) => name, | |
182 | None => return, | |
0531ce1d | 183 | }; |
a1dfa0c6 XL |
184 | unsafe { |
185 | let buf = SmallCStr::new(§.as_str()); | |
186 | llvm::LLVMSetSection(llval, buf.as_ptr()); | |
187 | } | |
ea8adc8c XL |
188 | } |
189 | ||
ea8adc8c XL |
190 | pub fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage { |
191 | match linkage { | |
192 | Linkage::External => llvm::Linkage::ExternalLinkage, | |
193 | Linkage::AvailableExternally => llvm::Linkage::AvailableExternallyLinkage, | |
194 | Linkage::LinkOnceAny => llvm::Linkage::LinkOnceAnyLinkage, | |
195 | Linkage::LinkOnceODR => llvm::Linkage::LinkOnceODRLinkage, | |
196 | Linkage::WeakAny => llvm::Linkage::WeakAnyLinkage, | |
197 | Linkage::WeakODR => llvm::Linkage::WeakODRLinkage, | |
198 | Linkage::Appending => llvm::Linkage::AppendingLinkage, | |
199 | Linkage::Internal => llvm::Linkage::InternalLinkage, | |
200 | Linkage::Private => llvm::Linkage::PrivateLinkage, | |
201 | Linkage::ExternalWeak => llvm::Linkage::ExternalWeakLinkage, | |
202 | Linkage::Common => llvm::Linkage::CommonLinkage, | |
203 | } | |
204 | } | |
205 | ||
206 | pub fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility { | |
207 | match linkage { | |
208 | Visibility::Default => llvm::Visibility::Default, | |
209 | Visibility::Hidden => llvm::Visibility::Hidden, | |
210 | Visibility::Protected => llvm::Visibility::Protected, | |
211 | } | |
212 | } |