1 //! Codegen the completed AST to the LLVM IR.
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
6 //! particular definition to the LLVM IR output we're producing.
8 //! Hopefully useful general knowledge about codegen:
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`.
16 use super::ModuleLlvm
;
18 use crate::attributes
;
19 use crate::builder
::Builder
;
21 use crate::context
::CodegenCx
;
24 use crate::value
::Value
;
26 use rustc_codegen_ssa
::base
::maybe_create_entry_wrapper
;
27 use rustc_codegen_ssa
::mono_item
::MonoItemExt
;
28 use rustc_codegen_ssa
::traits
::*;
29 use rustc_codegen_ssa
::{ModuleCodegen, ModuleKind}
;
30 use rustc_data_structures
::small_c_str
::SmallCStr
;
31 use rustc_middle
::dep_graph
;
32 use rustc_middle
::middle
::codegen_fn_attrs
::CodegenFnAttrs
;
33 use rustc_middle
::middle
::cstore
::EncodedMetadata
;
34 use rustc_middle
::middle
::exported_symbols
;
35 use rustc_middle
::mir
::mono
::{Linkage, Visibility}
;
36 use rustc_middle
::ty
::TyCtxt
;
37 use rustc_session
::config
::{DebugInfo, SanitizerSet}
;
38 use rustc_span
::symbol
::Symbol
;
40 use std
::ffi
::CString
;
41 use std
::time
::Instant
;
43 pub fn write_compressed_metadata
<'tcx
>(
45 metadata
: &EncodedMetadata
,
46 llvm_module
: &mut ModuleLlvm
,
48 use snap
::write
::FrameEncoder
;
51 let (metadata_llcx
, metadata_llmod
) = (&*llvm_module
.llcx
, llvm_module
.llmod());
52 let mut compressed
= tcx
.metadata_encoding_version();
53 FrameEncoder
::new(&mut compressed
).write_all(&metadata
.raw_data
).unwrap();
55 let llmeta
= common
::bytes_in_context(metadata_llcx
, &compressed
);
56 let llconst
= common
::struct_in_context(metadata_llcx
, &[llmeta
], false);
57 let name
= exported_symbols
::metadata_symbol_name(tcx
);
58 let buf
= CString
::new(name
).unwrap();
60 unsafe { llvm::LLVMAddGlobal(metadata_llmod, common::val_ty(llconst), buf.as_ptr()) }
;
62 llvm
::LLVMSetInitializer(llglobal
, llconst
);
63 let section_name
= metadata
::metadata_section_name(&tcx
.sess
.target
);
64 let name
= SmallCStr
::new(section_name
);
65 llvm
::LLVMSetSection(llglobal
, name
.as_ptr());
67 // Also generate a .section directive to force no
68 // flags, at least for ELF outputs, so that the
69 // metadata doesn't get loaded into memory.
70 let directive
= format
!(".section {}", section_name
);
71 llvm
::LLVMSetModuleInlineAsm2(metadata_llmod
, directive
.as_ptr().cast(), directive
.len())
75 pub struct ValueIter
<'ll
> {
76 cur
: Option
<&'ll Value
>,
77 step
: unsafe extern "C" fn(&'ll Value
) -> Option
<&'ll Value
>,
80 impl Iterator
for ValueIter
<'ll
> {
81 type Item
= &'ll Value
;
83 fn next(&mut self) -> Option
<&'ll Value
> {
85 if let Some(old
) = old
{
86 self.cur
= unsafe { (self.step)(old) }
;
92 pub fn iter_globals(llmod
: &'ll llvm
::Module
) -> ValueIter
<'ll
> {
93 unsafe { ValueIter { cur: llvm::LLVMGetFirstGlobal(llmod), step: llvm::LLVMGetNextGlobal }
}
96 pub fn compile_codegen_unit(
99 ) -> (ModuleCodegen
<ModuleLlvm
>, u64) {
100 let prof_timer
= tcx
.prof
.generic_activity_with_arg("codegen_module", cgu_name
.to_string());
101 let start_time
= Instant
::now();
103 let dep_node
= tcx
.codegen_unit(cgu_name
).codegen_dep_node(tcx
);
105 tcx
.dep_graph
.with_task(dep_node
, tcx
, cgu_name
, module_codegen
, dep_graph
::hash_result
);
106 let time_to_codegen
= start_time
.elapsed();
109 // We assume that the cost to run LLVM on a CGU is proportional to
110 // the time we needed for codegenning it.
111 let cost
= time_to_codegen
.as_nanos() as u64;
113 fn module_codegen(tcx
: TyCtxt
<'_
>, cgu_name
: Symbol
) -> ModuleCodegen
<ModuleLlvm
> {
114 let cgu
= tcx
.codegen_unit(cgu_name
);
115 // Instantiate monomorphizations without filling out definitions yet...
116 let llvm_module
= ModuleLlvm
::new(tcx
, &cgu_name
.as_str());
118 let cx
= CodegenCx
::new(tcx
, cgu
, &llvm_module
);
119 let mono_items
= cx
.codegen_unit
.items_in_deterministic_order(cx
.tcx
);
120 for &(mono_item
, (linkage
, visibility
)) in &mono_items
{
121 mono_item
.predefine
::<Builder
<'_
, '_
, '_
>>(&cx
, linkage
, visibility
);
124 // ... and now that we have everything pre-defined, fill out those definitions.
125 for &(mono_item
, _
) in &mono_items
{
126 mono_item
.define
::<Builder
<'_
, '_
, '_
>>(&cx
);
129 // If this codegen unit contains the main function, also create the
131 if let Some(entry
) = maybe_create_entry_wrapper
::<Builder
<'_
, '_
, '_
>>(&cx
) {
132 attributes
::sanitize(&cx
, SanitizerSet
::empty(), entry
);
135 // Run replace-all-uses-with for statics that need it
136 for &(old_g
, new_g
) in cx
.statics_to_rauw().borrow().iter() {
138 let bitcast
= llvm
::LLVMConstPointerCast(new_g
, cx
.val_ty(old_g
));
139 llvm
::LLVMReplaceAllUsesWith(old_g
, bitcast
);
140 llvm
::LLVMDeleteGlobal(old_g
);
144 // Finalize code coverage by injecting the coverage map. Note, the coverage map will
145 // also be added to the `llvm.used` variable, created next.
146 if cx
.sess().opts
.debugging_opts
.instrument_coverage
{
147 cx
.coverageinfo_finalize();
150 // Create the llvm.used variable
151 // This variable has type [N x i8*] and is stored in the llvm.metadata section
152 if !cx
.used_statics().borrow().is_empty() {
153 cx
.create_used_variable()
156 // Finalize debuginfo
157 if cx
.sess().opts
.debuginfo
!= DebugInfo
::None
{
158 cx
.debuginfo_finalize();
163 name
: cgu_name
.to_string(),
164 module_llvm
: llvm_module
,
165 kind
: ModuleKind
::Regular
,
172 pub fn set_link_section(llval
: &Value
, attrs
: &CodegenFnAttrs
) {
173 let sect
= match attrs
.link_section
{
178 let buf
= SmallCStr
::new(§
.as_str());
179 llvm
::LLVMSetSection(llval
, buf
.as_ptr());
183 pub fn linkage_to_llvm(linkage
: Linkage
) -> llvm
::Linkage
{
185 Linkage
::External
=> llvm
::Linkage
::ExternalLinkage
,
186 Linkage
::AvailableExternally
=> llvm
::Linkage
::AvailableExternallyLinkage
,
187 Linkage
::LinkOnceAny
=> llvm
::Linkage
::LinkOnceAnyLinkage
,
188 Linkage
::LinkOnceODR
=> llvm
::Linkage
::LinkOnceODRLinkage
,
189 Linkage
::WeakAny
=> llvm
::Linkage
::WeakAnyLinkage
,
190 Linkage
::WeakODR
=> llvm
::Linkage
::WeakODRLinkage
,
191 Linkage
::Appending
=> llvm
::Linkage
::AppendingLinkage
,
192 Linkage
::Internal
=> llvm
::Linkage
::InternalLinkage
,
193 Linkage
::Private
=> llvm
::Linkage
::PrivateLinkage
,
194 Linkage
::ExternalWeak
=> llvm
::Linkage
::ExternalWeakLinkage
,
195 Linkage
::Common
=> llvm
::Linkage
::CommonLinkage
,
199 pub fn visibility_to_llvm(linkage
: Visibility
) -> llvm
::Visibility
{
201 Visibility
::Default
=> llvm
::Visibility
::Default
,
202 Visibility
::Hidden
=> llvm
::Visibility
::Hidden
,
203 Visibility
::Protected
=> llvm
::Visibility
::Protected
,