cranelift-object: Support per function sections
This makes it possible for the linker to omit unused functions when --gc-sections is passed.
This commit is contained in:
@@ -30,6 +30,7 @@ pub struct ObjectBuilder {
|
|||||||
name: Vec<u8>,
|
name: Vec<u8>,
|
||||||
libcall_names: Box<dyn Fn(ir::LibCall) -> String>,
|
libcall_names: Box<dyn Fn(ir::LibCall) -> String>,
|
||||||
function_alignment: u64,
|
function_alignment: u64,
|
||||||
|
per_function_section: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectBuilder {
|
impl ObjectBuilder {
|
||||||
@@ -88,6 +89,7 @@ impl ObjectBuilder {
|
|||||||
name: name.into(),
|
name: name.into(),
|
||||||
libcall_names,
|
libcall_names,
|
||||||
function_alignment: 1,
|
function_alignment: 1,
|
||||||
|
per_function_section: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +98,12 @@ impl ObjectBuilder {
|
|||||||
self.function_alignment = alignment;
|
self.function_alignment = alignment;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set if every function should end up in their own section.
|
||||||
|
pub fn per_function_section(&mut self, per_function_section: bool) -> &mut Self {
|
||||||
|
self.per_function_section = per_function_section;
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A `ObjectBackend` implements `Backend` and emits ".o" files using the `object` library.
|
/// A `ObjectBackend` implements `Backend` and emits ".o" files using the `object` library.
|
||||||
@@ -110,6 +118,7 @@ pub struct ObjectBackend {
|
|||||||
libcalls: HashMap<ir::LibCall, SymbolId>,
|
libcalls: HashMap<ir::LibCall, SymbolId>,
|
||||||
libcall_names: Box<dyn Fn(ir::LibCall) -> String>,
|
libcall_names: Box<dyn Fn(ir::LibCall) -> String>,
|
||||||
function_alignment: u64,
|
function_alignment: u64,
|
||||||
|
per_function_section: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Backend for ObjectBackend {
|
impl Backend for ObjectBackend {
|
||||||
@@ -138,6 +147,7 @@ impl Backend for ObjectBackend {
|
|||||||
libcalls: HashMap::new(),
|
libcalls: HashMap::new(),
|
||||||
libcall_names: builder.libcall_names,
|
libcall_names: builder.libcall_names,
|
||||||
function_alignment: builder.function_alignment,
|
function_alignment: builder.function_alignment,
|
||||||
|
per_function_section: builder.per_function_section,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,10 +240,26 @@ impl Backend for ObjectBackend {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let symbol = self.functions[func_id].unwrap();
|
let symbol = self.functions[func_id].unwrap();
|
||||||
|
|
||||||
|
let (section, offset) = if self.per_function_section {
|
||||||
|
let symbol_name = self.object.symbol(symbol).name.clone();
|
||||||
|
let (section, offset) = self.object.add_subsection(
|
||||||
|
StandardSection::Text,
|
||||||
|
&symbol_name,
|
||||||
|
&code,
|
||||||
|
self.function_alignment,
|
||||||
|
);
|
||||||
|
self.object.symbol_mut(symbol).section = SymbolSection::Section(section);
|
||||||
|
self.object.symbol_mut(symbol).value = offset;
|
||||||
|
(section, offset)
|
||||||
|
} else {
|
||||||
let section = self.object.section_id(StandardSection::Text);
|
let section = self.object.section_id(StandardSection::Text);
|
||||||
let offset = self
|
let offset =
|
||||||
.object
|
self.object
|
||||||
.add_symbol_data(symbol, section, &code, self.function_alignment);
|
.add_symbol_data(symbol, section, &code, self.function_alignment);
|
||||||
|
(section, offset)
|
||||||
|
};
|
||||||
|
|
||||||
if !reloc_sink.relocs.is_empty() {
|
if !reloc_sink.relocs.is_empty() {
|
||||||
self.relocs.push(SymbolRelocs {
|
self.relocs.push(SymbolRelocs {
|
||||||
section,
|
section,
|
||||||
@@ -252,10 +278,24 @@ impl Backend for ObjectBackend {
|
|||||||
_namespace: &ModuleNamespace<Self>,
|
_namespace: &ModuleNamespace<Self>,
|
||||||
) -> ModuleResult<ObjectCompiledFunction> {
|
) -> ModuleResult<ObjectCompiledFunction> {
|
||||||
let symbol = self.functions[func_id].unwrap();
|
let symbol = self.functions[func_id].unwrap();
|
||||||
|
|
||||||
|
if self.per_function_section {
|
||||||
|
let symbol_name = self.object.symbol(symbol).name.clone();
|
||||||
|
let (section, offset) = self.object.add_subsection(
|
||||||
|
StandardSection::Text,
|
||||||
|
&symbol_name,
|
||||||
|
bytes,
|
||||||
|
self.function_alignment,
|
||||||
|
);
|
||||||
|
self.object.symbol_mut(symbol).section = SymbolSection::Section(section);
|
||||||
|
self.object.symbol_mut(symbol).value = offset;
|
||||||
|
} else {
|
||||||
let section = self.object.section_id(StandardSection::Text);
|
let section = self.object.section_id(StandardSection::Text);
|
||||||
let _offset = self
|
let _offset =
|
||||||
.object
|
self.object
|
||||||
.add_symbol_data(symbol, section, bytes, self.function_alignment);
|
.add_symbol_data(symbol, section, bytes, self.function_alignment);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(ObjectCompiledFunction)
|
Ok(ObjectCompiledFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user