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
::{CodegenFnAttrFlags, 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
;
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 flate2
::write
::DeflateEncoder
;
49 use flate2
::Compression
;
52 let (metadata_llcx
, metadata_llmod
) = (&*llvm_module
.llcx
, llvm_module
.llmod());
53 let mut compressed
= tcx
.metadata_encoding_version();
54 DeflateEncoder
::new(&mut compressed
, Compression
::fast())
55 .write_all(&metadata
.raw_data
)
58 let llmeta
= common
::bytes_in_context(metadata_llcx
, &compressed
);
59 let llconst
= common
::struct_in_context(metadata_llcx
, &[llmeta
], false);
60 let name
= exported_symbols
::metadata_symbol_name(tcx
);
61 let buf
= CString
::new(name
).unwrap();
63 unsafe { llvm::LLVMAddGlobal(metadata_llmod, common::val_ty(llconst), buf.as_ptr()) }
;
65 llvm
::LLVMSetInitializer(llglobal
, llconst
);
66 let section_name
= metadata
::metadata_section_name(&tcx
.sess
.target
.target
);
67 let name
= SmallCStr
::new(section_name
);
68 llvm
::LLVMSetSection(llglobal
, name
.as_ptr());
70 // Also generate a .section directive to force no
71 // flags, at least for ELF outputs, so that the
72 // metadata doesn't get loaded into memory.
73 let directive
= format
!(".section {}", section_name
);
74 llvm
::LLVMSetModuleInlineAsm2(metadata_llmod
, directive
.as_ptr().cast(), directive
.len())
78 pub struct ValueIter
<'ll
> {
79 cur
: Option
<&'ll Value
>,
80 step
: unsafe extern "C" fn(&'ll Value
) -> Option
<&'ll Value
>,
83 impl Iterator
for ValueIter
<'ll
> {
84 type Item
= &'ll Value
;
86 fn next(&mut self) -> Option
<&'ll Value
> {
88 if let Some(old
) = old
{
89 self.cur
= unsafe { (self.step)(old) }
;
95 pub fn iter_globals(llmod
: &'ll llvm
::Module
) -> ValueIter
<'ll
> {
96 unsafe { ValueIter { cur: llvm::LLVMGetFirstGlobal(llmod), step: llvm::LLVMGetNextGlobal }
}
99 pub fn compile_codegen_unit(
102 ) -> (ModuleCodegen
<ModuleLlvm
>, u64) {
103 let prof_timer
= tcx
.prof
.generic_activity("codegen_module");
104 let start_time
= Instant
::now();
106 let dep_node
= tcx
.codegen_unit(cgu_name
).codegen_dep_node(tcx
);
108 tcx
.dep_graph
.with_task(dep_node
, tcx
, cgu_name
, module_codegen
, dep_graph
::hash_result
);
109 let time_to_codegen
= start_time
.elapsed();
112 // We assume that the cost to run LLVM on a CGU is proportional to
113 // the time we needed for codegenning it.
114 let cost
= time_to_codegen
.as_secs() * 1_000_000_000 + time_to_codegen
.subsec_nanos() as u64;
116 fn module_codegen(tcx
: TyCtxt
<'_
>, cgu_name
: Symbol
) -> ModuleCodegen
<ModuleLlvm
> {
117 let cgu
= tcx
.codegen_unit(cgu_name
);
118 // Instantiate monomorphizations without filling out definitions yet...
119 let llvm_module
= ModuleLlvm
::new(tcx
, &cgu_name
.as_str());
121 let cx
= CodegenCx
::new(tcx
, cgu
, &llvm_module
);
122 let mono_items
= cx
.codegen_unit
.items_in_deterministic_order(cx
.tcx
);
123 for &(mono_item
, (linkage
, visibility
)) in &mono_items
{
124 mono_item
.predefine
::<Builder
<'_
, '_
, '_
>>(&cx
, linkage
, visibility
);
127 // ... and now that we have everything pre-defined, fill out those definitions.
128 for &(mono_item
, _
) in &mono_items
{
129 mono_item
.define
::<Builder
<'_
, '_
, '_
>>(&cx
);
132 // If this codegen unit contains the main function, also create the
134 if let Some(entry
) = maybe_create_entry_wrapper
::<Builder
<'_
, '_
, '_
>>(&cx
) {
135 attributes
::sanitize(&cx
, CodegenFnAttrFlags
::empty(), entry
);
138 // Run replace-all-uses-with for statics that need it
139 for &(old_g
, new_g
) in cx
.statics_to_rauw().borrow().iter() {
141 let bitcast
= llvm
::LLVMConstPointerCast(new_g
, cx
.val_ty(old_g
));
142 llvm
::LLVMReplaceAllUsesWith(old_g
, bitcast
);
143 llvm
::LLVMDeleteGlobal(old_g
);
147 // Create the llvm.used variable
148 // This variable has type [N x i8*] and is stored in the llvm.metadata section
149 if !cx
.used_statics().borrow().is_empty() {
150 cx
.create_used_variable()
153 // Finalize debuginfo
154 if cx
.sess().opts
.debuginfo
!= DebugInfo
::None
{
155 cx
.debuginfo_finalize();
160 name
: cgu_name
.to_string(),
161 module_llvm
: llvm_module
,
162 kind
: ModuleKind
::Regular
,
169 pub fn set_link_section(llval
: &Value
, attrs
: &CodegenFnAttrs
) {
170 let sect
= match attrs
.link_section
{
175 let buf
= SmallCStr
::new(§
.as_str());
176 llvm
::LLVMSetSection(llval
, buf
.as_ptr());
180 pub fn linkage_to_llvm(linkage
: Linkage
) -> llvm
::Linkage
{
182 Linkage
::External
=> llvm
::Linkage
::ExternalLinkage
,
183 Linkage
::AvailableExternally
=> llvm
::Linkage
::AvailableExternallyLinkage
,
184 Linkage
::LinkOnceAny
=> llvm
::Linkage
::LinkOnceAnyLinkage
,
185 Linkage
::LinkOnceODR
=> llvm
::Linkage
::LinkOnceODRLinkage
,
186 Linkage
::WeakAny
=> llvm
::Linkage
::WeakAnyLinkage
,
187 Linkage
::WeakODR
=> llvm
::Linkage
::WeakODRLinkage
,
188 Linkage
::Appending
=> llvm
::Linkage
::AppendingLinkage
,
189 Linkage
::Internal
=> llvm
::Linkage
::InternalLinkage
,
190 Linkage
::Private
=> llvm
::Linkage
::PrivateLinkage
,
191 Linkage
::ExternalWeak
=> llvm
::Linkage
::ExternalWeakLinkage
,
192 Linkage
::Common
=> llvm
::Linkage
::CommonLinkage
,
196 pub fn visibility_to_llvm(linkage
: Visibility
) -> llvm
::Visibility
{
198 Visibility
::Default
=> llvm
::Visibility
::Default
,
199 Visibility
::Hidden
=> llvm
::Visibility
::Hidden
,
200 Visibility
::Protected
=> llvm
::Visibility
::Protected
,