Add cranelift-object
This commit is contained in:
@@ -29,6 +29,7 @@ cranelift-native = { path = "cranelift-native", version = "0.42.0" }
|
|||||||
cranelift-filetests = { path = "cranelift-filetests", version = "0.42.0" }
|
cranelift-filetests = { path = "cranelift-filetests", version = "0.42.0" }
|
||||||
cranelift-module = { path = "cranelift-module", version = "0.42.0" }
|
cranelift-module = { path = "cranelift-module", version = "0.42.0" }
|
||||||
cranelift-faerie = { path = "cranelift-faerie", version = "0.42.0" }
|
cranelift-faerie = { path = "cranelift-faerie", version = "0.42.0" }
|
||||||
|
cranelift-object = { path = "cranelift-object", version = "0.42.0" }
|
||||||
cranelift-simplejit = { path = "cranelift-simplejit", version = "0.42.0" }
|
cranelift-simplejit = { path = "cranelift-simplejit", version = "0.42.0" }
|
||||||
cranelift-preopt = { path = "cranelift-preopt", version = "0.42.0" }
|
cranelift-preopt = { path = "cranelift-preopt", version = "0.42.0" }
|
||||||
cranelift = { path = "cranelift-umbrella", version = "0.42.0" }
|
cranelift = { path = "cranelift-umbrella", version = "0.42.0" }
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
/// convention in the embedding VM's runtime library.
|
/// convention in the embedding VM's runtime library.
|
||||||
///
|
///
|
||||||
/// This list is likely to grow over time.
|
/// This list is likely to grow over time.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub enum LibCall {
|
pub enum LibCall {
|
||||||
/// probe for stack overflow. These are emitted for functions which need
|
/// probe for stack overflow. These are emitted for functions which need
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ use cranelift_codegen::binemit::{
|
|||||||
use cranelift_codegen::isa::TargetIsa;
|
use cranelift_codegen::isa::TargetIsa;
|
||||||
use cranelift_codegen::{self, binemit, ir};
|
use cranelift_codegen::{self, binemit, ir};
|
||||||
use cranelift_module::{
|
use cranelift_module::{
|
||||||
Backend, DataContext, DataDescription, Init, Linkage, ModuleError, ModuleNamespace,
|
Backend, DataContext, DataDescription, DataId, FuncId, Init, Linkage, ModuleError,
|
||||||
ModuleResult,
|
ModuleNamespace, ModuleResult,
|
||||||
};
|
};
|
||||||
use faerie;
|
use faerie;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
@@ -123,13 +123,20 @@ impl Backend for FaerieBackend {
|
|||||||
&*self.isa
|
&*self.isa
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_function(&mut self, name: &str, linkage: Linkage) {
|
fn declare_function(&mut self, _id: FuncId, name: &str, linkage: Linkage) {
|
||||||
self.artifact
|
self.artifact
|
||||||
.declare(name, translate_function_linkage(linkage))
|
.declare(name, translate_function_linkage(linkage))
|
||||||
.expect("inconsistent declarations");
|
.expect("inconsistent declarations");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_data(&mut self, name: &str, linkage: Linkage, writable: bool, align: Option<u8>) {
|
fn declare_data(
|
||||||
|
&mut self,
|
||||||
|
_id: DataId,
|
||||||
|
name: &str,
|
||||||
|
linkage: Linkage,
|
||||||
|
writable: bool,
|
||||||
|
align: Option<u8>,
|
||||||
|
) {
|
||||||
self.artifact
|
self.artifact
|
||||||
.declare(name, translate_data_linkage(linkage, writable, align))
|
.declare(name, translate_data_linkage(linkage, writable, align))
|
||||||
.expect("inconsistent declarations");
|
.expect("inconsistent declarations");
|
||||||
@@ -137,6 +144,7 @@ impl Backend for FaerieBackend {
|
|||||||
|
|
||||||
fn define_function(
|
fn define_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
_id: FuncId,
|
||||||
name: &str,
|
name: &str,
|
||||||
ctx: &cranelift_codegen::Context,
|
ctx: &cranelift_codegen::Context,
|
||||||
namespace: &ModuleNamespace<Self>,
|
namespace: &ModuleNamespace<Self>,
|
||||||
@@ -194,6 +202,7 @@ impl Backend for FaerieBackend {
|
|||||||
|
|
||||||
fn define_data(
|
fn define_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
_id: DataId,
|
||||||
name: &str,
|
name: &str,
|
||||||
_writable: bool,
|
_writable: bool,
|
||||||
_align: Option<u8>,
|
_align: Option<u8>,
|
||||||
@@ -274,6 +283,7 @@ impl Backend for FaerieBackend {
|
|||||||
|
|
||||||
fn finalize_function(
|
fn finalize_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
_id: FuncId,
|
||||||
_func: &FaerieCompiledFunction,
|
_func: &FaerieCompiledFunction,
|
||||||
_namespace: &ModuleNamespace<Self>,
|
_namespace: &ModuleNamespace<Self>,
|
||||||
) {
|
) {
|
||||||
@@ -284,7 +294,12 @@ impl Backend for FaerieBackend {
|
|||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize_data(&mut self, _data: &FaerieCompiledData, _namespace: &ModuleNamespace<Self>) {
|
fn finalize_data(
|
||||||
|
&mut self,
|
||||||
|
_id: DataId,
|
||||||
|
_data: &FaerieCompiledData,
|
||||||
|
_namespace: &ModuleNamespace<Self>,
|
||||||
|
) {
|
||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
//! Defines the `Backend` trait.
|
//! Defines the `Backend` trait.
|
||||||
|
|
||||||
use crate::DataContext;
|
use crate::DataContext;
|
||||||
|
use crate::DataId;
|
||||||
|
use crate::FuncId;
|
||||||
use crate::Linkage;
|
use crate::Linkage;
|
||||||
use crate::ModuleNamespace;
|
use crate::ModuleNamespace;
|
||||||
use crate::ModuleResult;
|
use crate::ModuleResult;
|
||||||
@@ -56,16 +58,24 @@ where
|
|||||||
fn isa(&self) -> &dyn TargetIsa;
|
fn isa(&self) -> &dyn TargetIsa;
|
||||||
|
|
||||||
/// Declare a function.
|
/// Declare a function.
|
||||||
fn declare_function(&mut self, name: &str, linkage: Linkage);
|
fn declare_function(&mut self, id: FuncId, name: &str, linkage: Linkage);
|
||||||
|
|
||||||
/// Declare a data object.
|
/// Declare a data object.
|
||||||
fn declare_data(&mut self, name: &str, linkage: Linkage, writable: bool, align: Option<u8>);
|
fn declare_data(
|
||||||
|
&mut self,
|
||||||
|
id: DataId,
|
||||||
|
name: &str,
|
||||||
|
linkage: Linkage,
|
||||||
|
writable: bool,
|
||||||
|
align: Option<u8>,
|
||||||
|
);
|
||||||
|
|
||||||
/// Define a function, producing the function body from the given `Context`.
|
/// Define a function, producing the function body from the given `Context`.
|
||||||
///
|
///
|
||||||
/// Functions must be declared before being defined.
|
/// Functions must be declared before being defined.
|
||||||
fn define_function(
|
fn define_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
id: FuncId,
|
||||||
name: &str,
|
name: &str,
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
namespace: &ModuleNamespace<Self>,
|
namespace: &ModuleNamespace<Self>,
|
||||||
@@ -77,6 +87,7 @@ where
|
|||||||
/// Data objects must be declared before being defined.
|
/// Data objects must be declared before being defined.
|
||||||
fn define_data(
|
fn define_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
id: DataId,
|
||||||
name: &str,
|
name: &str,
|
||||||
writable: bool,
|
writable: bool,
|
||||||
align: Option<u8>,
|
align: Option<u8>,
|
||||||
@@ -107,6 +118,7 @@ where
|
|||||||
/// and `Export` entities referenced to be defined.
|
/// and `Export` entities referenced to be defined.
|
||||||
fn finalize_function(
|
fn finalize_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
id: FuncId,
|
||||||
func: &Self::CompiledFunction,
|
func: &Self::CompiledFunction,
|
||||||
namespace: &ModuleNamespace<Self>,
|
namespace: &ModuleNamespace<Self>,
|
||||||
) -> Self::FinalizedFunction;
|
) -> Self::FinalizedFunction;
|
||||||
@@ -118,6 +130,7 @@ where
|
|||||||
/// `Local` and `Export` entities referenced to be defined.
|
/// `Local` and `Export` entities referenced to be defined.
|
||||||
fn finalize_data(
|
fn finalize_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
id: DataId,
|
||||||
data: &Self::CompiledData,
|
data: &Self::CompiledData,
|
||||||
namespace: &ModuleNamespace<Self>,
|
namespace: &ModuleNamespace<Self>,
|
||||||
) -> Self::FinalizedData;
|
) -> Self::FinalizedData;
|
||||||
|
|||||||
@@ -224,26 +224,32 @@ impl<B> ModuleContents<B>
|
|||||||
where
|
where
|
||||||
B: Backend,
|
B: Backend,
|
||||||
{
|
{
|
||||||
fn get_function_info(&self, name: &ir::ExternalName) -> &ModuleFunction<B> {
|
fn get_function_id(&self, name: &ir::ExternalName) -> FuncId {
|
||||||
if let ir::ExternalName::User { namespace, index } = *name {
|
if let ir::ExternalName::User { namespace, index } = *name {
|
||||||
debug_assert_eq!(namespace, 0);
|
debug_assert_eq!(namespace, 0);
|
||||||
let func = FuncId::from_u32(index);
|
FuncId::from_u32(index)
|
||||||
&self.functions[func]
|
|
||||||
} else {
|
} else {
|
||||||
panic!("unexpected ExternalName kind {}", name)
|
panic!("unexpected ExternalName kind {}", name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the `DataDeclaration` for the function named by `name`.
|
fn get_data_id(&self, name: &ir::ExternalName) -> DataId {
|
||||||
fn get_data_info(&self, name: &ir::ExternalName) -> &ModuleData<B> {
|
|
||||||
if let ir::ExternalName::User { namespace, index } = *name {
|
if let ir::ExternalName::User { namespace, index } = *name {
|
||||||
debug_assert_eq!(namespace, 1);
|
debug_assert_eq!(namespace, 1);
|
||||||
let data = DataId::from_u32(index);
|
DataId::from_u32(index)
|
||||||
&self.data_objects[data]
|
|
||||||
} else {
|
} else {
|
||||||
panic!("unexpected ExternalName kind {}", name)
|
panic!("unexpected ExternalName kind {}", name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_function_info(&self, name: &ir::ExternalName) -> &ModuleFunction<B> {
|
||||||
|
&self.functions[self.get_function_id(name)]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the `DataDeclaration` for the function named by `name`.
|
||||||
|
fn get_data_info(&self, name: &ir::ExternalName) -> &ModuleData<B> {
|
||||||
|
&self.data_objects[self.get_data_id(name)]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This provides a view to the state of a module which allows `ir::ExternalName`s to be translated
|
/// This provides a view to the state of a module which allows `ir::ExternalName`s to be translated
|
||||||
@@ -259,12 +265,22 @@ impl<'a, B> ModuleNamespace<'a, B>
|
|||||||
where
|
where
|
||||||
B: Backend,
|
B: Backend,
|
||||||
{
|
{
|
||||||
|
/// Get the `FuncId` for the function named by `name`.
|
||||||
|
pub fn get_function_id(&self, name: &ir::ExternalName) -> FuncId {
|
||||||
|
self.contents.get_function_id(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the `DataId` for the data object named by `name`.
|
||||||
|
pub fn get_data_id(&self, name: &ir::ExternalName) -> DataId {
|
||||||
|
self.contents.get_data_id(name)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the `FunctionDeclaration` for the function named by `name`.
|
/// Get the `FunctionDeclaration` for the function named by `name`.
|
||||||
pub fn get_function_decl(&self, name: &ir::ExternalName) -> &FunctionDeclaration {
|
pub fn get_function_decl(&self, name: &ir::ExternalName) -> &FunctionDeclaration {
|
||||||
&self.contents.get_function_info(name).decl
|
&self.contents.get_function_info(name).decl
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the `DataDeclaration` for the function named by `name`.
|
/// Get the `DataDeclaration` for the data object named by `name`.
|
||||||
pub fn get_data_decl(&self, name: &ir::ExternalName) -> &DataDeclaration {
|
pub fn get_data_decl(&self, name: &ir::ExternalName) -> &DataDeclaration {
|
||||||
&self.contents.get_data_info(name).decl
|
&self.contents.get_data_info(name).decl
|
||||||
}
|
}
|
||||||
@@ -407,7 +423,8 @@ where
|
|||||||
FuncOrDataId::Func(id) => {
|
FuncOrDataId::Func(id) => {
|
||||||
let existing = &mut self.contents.functions[id];
|
let existing = &mut self.contents.functions[id];
|
||||||
existing.merge(linkage, signature)?;
|
existing.merge(linkage, signature)?;
|
||||||
self.backend.declare_function(name, existing.decl.linkage);
|
self.backend
|
||||||
|
.declare_function(id, name, existing.decl.linkage);
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
FuncOrDataId::Data(..) => {
|
FuncOrDataId::Data(..) => {
|
||||||
@@ -424,7 +441,7 @@ where
|
|||||||
compiled: None,
|
compiled: None,
|
||||||
});
|
});
|
||||||
entry.insert(FuncOrDataId::Func(id));
|
entry.insert(FuncOrDataId::Func(id));
|
||||||
self.backend.declare_function(name, linkage);
|
self.backend.declare_function(id, name, linkage);
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -451,6 +468,7 @@ where
|
|||||||
let existing = &mut self.contents.data_objects[id];
|
let existing = &mut self.contents.data_objects[id];
|
||||||
existing.merge(linkage, writable, align);
|
existing.merge(linkage, writable, align);
|
||||||
self.backend.declare_data(
|
self.backend.declare_data(
|
||||||
|
id,
|
||||||
name,
|
name,
|
||||||
existing.decl.linkage,
|
existing.decl.linkage,
|
||||||
existing.decl.writable,
|
existing.decl.writable,
|
||||||
@@ -474,7 +492,8 @@ where
|
|||||||
compiled: None,
|
compiled: None,
|
||||||
});
|
});
|
||||||
entry.insert(FuncOrDataId::Data(id));
|
entry.insert(FuncOrDataId::Data(id));
|
||||||
self.backend.declare_data(name, linkage, writable, align);
|
self.backend
|
||||||
|
.declare_data(id, name, linkage, writable, align);
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -536,7 +555,6 @@ where
|
|||||||
);
|
);
|
||||||
ModuleError::Compilation(e)
|
ModuleError::Compilation(e)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let info = &self.contents.functions[func];
|
let info = &self.contents.functions[func];
|
||||||
if info.compiled.is_some() {
|
if info.compiled.is_some() {
|
||||||
return Err(ModuleError::DuplicateDefinition(info.decl.name.clone()));
|
return Err(ModuleError::DuplicateDefinition(info.decl.name.clone()));
|
||||||
@@ -546,6 +564,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
let compiled = Some(self.backend.define_function(
|
let compiled = Some(self.backend.define_function(
|
||||||
|
func,
|
||||||
&info.decl.name,
|
&info.decl.name,
|
||||||
ctx,
|
ctx,
|
||||||
&ModuleNamespace::<B> {
|
&ModuleNamespace::<B> {
|
||||||
@@ -570,6 +589,7 @@ where
|
|||||||
return Err(ModuleError::InvalidImportDefinition(info.decl.name.clone()));
|
return Err(ModuleError::InvalidImportDefinition(info.decl.name.clone()));
|
||||||
}
|
}
|
||||||
Some(self.backend.define_data(
|
Some(self.backend.define_data(
|
||||||
|
data,
|
||||||
&info.decl.name,
|
&info.decl.name,
|
||||||
info.decl.writable,
|
info.decl.writable,
|
||||||
info.decl.align,
|
info.decl.align,
|
||||||
@@ -638,6 +658,7 @@ where
|
|||||||
let info = &self.contents.functions[func];
|
let info = &self.contents.functions[func];
|
||||||
debug_assert!(info.decl.linkage.is_definable());
|
debug_assert!(info.decl.linkage.is_definable());
|
||||||
self.backend.finalize_function(
|
self.backend.finalize_function(
|
||||||
|
func,
|
||||||
info.compiled
|
info.compiled
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("function must be compiled before it can be finalized"),
|
.expect("function must be compiled before it can be finalized"),
|
||||||
@@ -650,6 +671,7 @@ where
|
|||||||
let info = &self.contents.data_objects[data];
|
let info = &self.contents.data_objects[data];
|
||||||
debug_assert!(info.decl.linkage.is_definable());
|
debug_assert!(info.decl.linkage.is_definable());
|
||||||
self.backend.finalize_data(
|
self.backend.finalize_data(
|
||||||
|
data,
|
||||||
info.compiled
|
info.compiled
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("data object must be compiled before it can be finalized"),
|
.expect("data object must be compiled before it can be finalized"),
|
||||||
|
|||||||
20
cranelift/object/Cargo.toml
Normal file
20
cranelift/object/Cargo.toml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
[package]
|
||||||
|
name = "cranelift-object"
|
||||||
|
version = "0.42.0"
|
||||||
|
authors = ["The Cranelift Project Developers"]
|
||||||
|
description = "Emit Cranelift output to native object files with `object`"
|
||||||
|
repository = "https://github.com/CraneStation/cranelift"
|
||||||
|
documentation = "https://cranelift.readthedocs.io/"
|
||||||
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
|
readme = "README.md"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
cranelift-codegen = { path = "../cranelift-codegen", version = "0.42.0" }
|
||||||
|
cranelift-module = { path = "../cranelift-module", version = "0.42.0" }
|
||||||
|
object = { version = "0.14.0", default-features = false, features = ["write"] }
|
||||||
|
target-lexicon = "0.8.1"
|
||||||
|
|
||||||
|
[badges]
|
||||||
|
maintenance = { status = "experimental" }
|
||||||
|
travis-ci = { repository = "CraneStation/cranelift" }
|
||||||
220
cranelift/object/LICENSE
Normal file
220
cranelift/object/LICENSE
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
--- LLVM Exceptions to the Apache 2.0 License ----
|
||||||
|
|
||||||
|
As an exception, if, as a result of your compiling your source code, portions
|
||||||
|
of this Software are embedded into an Object form of such source code, you
|
||||||
|
may redistribute such embedded portions in such Object form without complying
|
||||||
|
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
|
||||||
|
|
||||||
|
In addition, if you combine or link compiled forms of this Software with
|
||||||
|
software that is licensed under the GPLv2 ("Combined Software") and if a
|
||||||
|
court of competent jurisdiction determines that the patent provision (Section
|
||||||
|
3), the indemnity provision (Section 9) or other Section of the License
|
||||||
|
conflicts with the conditions of the GPLv2, you may retroactively and
|
||||||
|
prospectively choose to deem waived or otherwise exclude such Section(s) of
|
||||||
|
the License, but only in their entirety and only with respect to the Combined
|
||||||
|
Software.
|
||||||
|
|
||||||
4
cranelift/object/README.md
Normal file
4
cranelift/object/README.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
This crate contains a library that enables
|
||||||
|
[Cranelift](https://crates.io/crates/cranelift)
|
||||||
|
to emit native object (".o") files, using the
|
||||||
|
[object](https://crates.io/crates/object) library.
|
||||||
584
cranelift/object/src/backend.rs
Normal file
584
cranelift/object/src/backend.rs
Normal file
@@ -0,0 +1,584 @@
|
|||||||
|
//! Defines `ObjectBackend`.
|
||||||
|
|
||||||
|
use crate::traps::{ObjectTrapSink, ObjectTrapSite};
|
||||||
|
use cranelift_codegen::binemit::{
|
||||||
|
Addend, CodeOffset, NullStackmapSink, NullTrapSink, Reloc, RelocSink,
|
||||||
|
};
|
||||||
|
use cranelift_codegen::entity::SecondaryMap;
|
||||||
|
use cranelift_codegen::isa::TargetIsa;
|
||||||
|
use cranelift_codegen::{self, binemit, ir};
|
||||||
|
use cranelift_module::{
|
||||||
|
Backend, DataContext, DataDescription, DataId, FuncId, Init, Linkage, ModuleNamespace,
|
||||||
|
ModuleResult,
|
||||||
|
};
|
||||||
|
use object::write::{Object, Relocation, SectionId, StandardSection, Symbol, SymbolId};
|
||||||
|
use object::{RelocationEncoding, RelocationKind, SymbolKind, SymbolScope};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use target_lexicon::PointerWidth;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
/// Setting to enable collection of traps. Setting this to `Enabled` in
|
||||||
|
/// `ObjectBuilder` means that `ObjectProduct` will contains trap sites.
|
||||||
|
pub enum ObjectTrapCollection {
|
||||||
|
/// `ObjectProduct::traps` will be empty
|
||||||
|
Disabled,
|
||||||
|
/// `ObjectProduct::traps` will contain trap sites
|
||||||
|
Enabled,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A builder for `ObjectBackend`.
|
||||||
|
pub struct ObjectBuilder {
|
||||||
|
isa: Box<dyn TargetIsa>,
|
||||||
|
name: String,
|
||||||
|
collect_traps: ObjectTrapCollection,
|
||||||
|
libcall_names: Box<dyn Fn(ir::LibCall) -> String>,
|
||||||
|
function_alignment: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObjectBuilder {
|
||||||
|
/// Create a new `ObjectBuilder` using the given Cranelift target, that
|
||||||
|
/// can be passed to
|
||||||
|
/// [`Module::new`](cranelift_module/struct.Module.html#method.new].
|
||||||
|
///
|
||||||
|
/// `collect_traps` setting determines whether trap information is collected in the
|
||||||
|
/// `ObjectProduct`.
|
||||||
|
///
|
||||||
|
/// The `libcall_names` function provides a way to translate `cranelift_codegen`'s `ir::LibCall`
|
||||||
|
/// enum to symbols. LibCalls are inserted in the IR as part of the legalization for certain
|
||||||
|
/// floating point instructions, and for stack probes. If you don't know what to use for this
|
||||||
|
/// argument, use `cranelift_module::default_libcall_names()`.
|
||||||
|
pub fn new(
|
||||||
|
isa: Box<dyn TargetIsa>,
|
||||||
|
name: String,
|
||||||
|
collect_traps: ObjectTrapCollection,
|
||||||
|
libcall_names: Box<dyn Fn(ir::LibCall) -> String>,
|
||||||
|
) -> ModuleResult<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
isa,
|
||||||
|
name,
|
||||||
|
collect_traps,
|
||||||
|
libcall_names,
|
||||||
|
function_alignment: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the alignment used for functions.
|
||||||
|
pub fn function_alignment(&mut self, alignment: u64) -> &mut Self {
|
||||||
|
self.function_alignment = alignment;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A `ObjectBackend` implements `Backend` and emits ".o" files using the `object` library.
|
||||||
|
///
|
||||||
|
/// See the `ObjectBuilder` for a convenient way to construct `ObjectBackend` instances.
|
||||||
|
pub struct ObjectBackend {
|
||||||
|
isa: Box<dyn TargetIsa>,
|
||||||
|
object: Object,
|
||||||
|
functions: SecondaryMap<FuncId, Option<SymbolId>>,
|
||||||
|
data_objects: SecondaryMap<DataId, Option<SymbolId>>,
|
||||||
|
traps: SecondaryMap<FuncId, Vec<ObjectTrapSite>>,
|
||||||
|
libcalls: HashMap<ir::LibCall, SymbolId>,
|
||||||
|
libcall_names: Box<dyn Fn(ir::LibCall) -> String>,
|
||||||
|
collect_traps: ObjectTrapCollection,
|
||||||
|
function_alignment: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Backend for ObjectBackend {
|
||||||
|
type Builder = ObjectBuilder;
|
||||||
|
|
||||||
|
type CompiledFunction = ObjectCompiledFunction;
|
||||||
|
type CompiledData = ObjectCompiledData;
|
||||||
|
|
||||||
|
// There's no need to return individual artifacts; we're writing them into
|
||||||
|
// the output file instead.
|
||||||
|
type FinalizedFunction = ();
|
||||||
|
type FinalizedData = ();
|
||||||
|
|
||||||
|
type Product = ObjectProduct;
|
||||||
|
|
||||||
|
/// Create a new `ObjectBackend` using the given Cranelift target.
|
||||||
|
fn new(builder: ObjectBuilder) -> Self {
|
||||||
|
let triple = builder.isa.triple();
|
||||||
|
let mut object = Object::new(triple.binary_format, triple.architecture);
|
||||||
|
object.add_file_symbol(builder.name.as_bytes().to_vec());
|
||||||
|
Self {
|
||||||
|
isa: builder.isa,
|
||||||
|
object,
|
||||||
|
functions: SecondaryMap::new(),
|
||||||
|
data_objects: SecondaryMap::new(),
|
||||||
|
traps: SecondaryMap::new(),
|
||||||
|
libcalls: HashMap::new(),
|
||||||
|
libcall_names: builder.libcall_names,
|
||||||
|
collect_traps: builder.collect_traps,
|
||||||
|
function_alignment: builder.function_alignment,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn isa(&self) -> &dyn TargetIsa {
|
||||||
|
&*self.isa
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declare_function(&mut self, id: FuncId, name: &str, linkage: Linkage) {
|
||||||
|
let (scope, weak) = translate_linkage(linkage);
|
||||||
|
|
||||||
|
if let Some(function) = self.functions[id] {
|
||||||
|
let symbol = self.object.symbol_mut(function);
|
||||||
|
symbol.scope = scope;
|
||||||
|
symbol.weak = weak;
|
||||||
|
} else {
|
||||||
|
let symbol_id = self.object.add_symbol(Symbol {
|
||||||
|
name: name.as_bytes().to_vec(),
|
||||||
|
value: 0,
|
||||||
|
size: 0,
|
||||||
|
kind: SymbolKind::Text,
|
||||||
|
scope,
|
||||||
|
weak,
|
||||||
|
section: None,
|
||||||
|
});
|
||||||
|
self.functions[id] = Some(symbol_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declare_data(
|
||||||
|
&mut self,
|
||||||
|
id: DataId,
|
||||||
|
name: &str,
|
||||||
|
linkage: Linkage,
|
||||||
|
_writable: bool,
|
||||||
|
_align: Option<u8>,
|
||||||
|
) {
|
||||||
|
let (scope, weak) = translate_linkage(linkage);
|
||||||
|
|
||||||
|
if let Some(data) = self.data_objects[id] {
|
||||||
|
let symbol = self.object.symbol_mut(data);
|
||||||
|
symbol.scope = scope;
|
||||||
|
symbol.weak = weak;
|
||||||
|
} else {
|
||||||
|
let symbol_id = self.object.add_symbol(Symbol {
|
||||||
|
name: name.as_bytes().to_vec(),
|
||||||
|
value: 0,
|
||||||
|
size: 0,
|
||||||
|
kind: SymbolKind::Data,
|
||||||
|
scope,
|
||||||
|
weak,
|
||||||
|
section: None,
|
||||||
|
});
|
||||||
|
self.data_objects[id] = Some(symbol_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn define_function(
|
||||||
|
&mut self,
|
||||||
|
func_id: FuncId,
|
||||||
|
_name: &str,
|
||||||
|
ctx: &cranelift_codegen::Context,
|
||||||
|
_namespace: &ModuleNamespace<Self>,
|
||||||
|
code_size: u32,
|
||||||
|
) -> ModuleResult<ObjectCompiledFunction> {
|
||||||
|
let mut code: Vec<u8> = vec![0; code_size as usize];
|
||||||
|
let mut reloc_sink = ObjectRelocSink::default();
|
||||||
|
let mut trap_sink = ObjectTrapSink::default();
|
||||||
|
let mut stackmap_sink = NullStackmapSink {};
|
||||||
|
|
||||||
|
if let ObjectTrapCollection::Enabled = self.collect_traps {
|
||||||
|
unsafe {
|
||||||
|
ctx.emit_to_memory(
|
||||||
|
&*self.isa,
|
||||||
|
code.as_mut_ptr(),
|
||||||
|
&mut reloc_sink,
|
||||||
|
&mut trap_sink,
|
||||||
|
&mut stackmap_sink,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
let mut trap_sink = NullTrapSink {};
|
||||||
|
unsafe {
|
||||||
|
ctx.emit_to_memory(
|
||||||
|
&*self.isa,
|
||||||
|
code.as_mut_ptr(),
|
||||||
|
&mut reloc_sink,
|
||||||
|
&mut trap_sink,
|
||||||
|
&mut stackmap_sink,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let symbol = self.functions[func_id].unwrap();
|
||||||
|
let section = self.object.section_id(StandardSection::Text);
|
||||||
|
let offset = self
|
||||||
|
.object
|
||||||
|
.add_symbol_data(symbol, section, &code, self.function_alignment);
|
||||||
|
self.traps[func_id] = trap_sink.sites;
|
||||||
|
Ok(ObjectCompiledFunction {
|
||||||
|
offset,
|
||||||
|
size: code_size,
|
||||||
|
section,
|
||||||
|
relocs: reloc_sink.relocs,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn define_data(
|
||||||
|
&mut self,
|
||||||
|
data_id: DataId,
|
||||||
|
_name: &str,
|
||||||
|
writable: bool,
|
||||||
|
align: Option<u8>,
|
||||||
|
data_ctx: &DataContext,
|
||||||
|
_namespace: &ModuleNamespace<Self>,
|
||||||
|
) -> ModuleResult<ObjectCompiledData> {
|
||||||
|
let &DataDescription {
|
||||||
|
ref init,
|
||||||
|
ref function_decls,
|
||||||
|
ref data_decls,
|
||||||
|
ref function_relocs,
|
||||||
|
ref data_relocs,
|
||||||
|
} = data_ctx.description();
|
||||||
|
|
||||||
|
let size = init.size();
|
||||||
|
let mut data = Vec::with_capacity(size);
|
||||||
|
match *init {
|
||||||
|
Init::Uninitialized => {
|
||||||
|
panic!("data is not initialized yet");
|
||||||
|
}
|
||||||
|
Init::Zeros { .. } => {
|
||||||
|
data.resize(size, 0);
|
||||||
|
}
|
||||||
|
Init::Bytes { ref contents } => {
|
||||||
|
data.extend_from_slice(contents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let reloc_size = match self.isa.triple().pointer_width().unwrap() {
|
||||||
|
PointerWidth::U16 => 16,
|
||||||
|
PointerWidth::U32 => 32,
|
||||||
|
PointerWidth::U64 => 64,
|
||||||
|
};
|
||||||
|
let mut relocs = Vec::new();
|
||||||
|
for &(offset, id) in function_relocs {
|
||||||
|
relocs.push(RelocRecord {
|
||||||
|
offset,
|
||||||
|
name: function_decls[id].clone(),
|
||||||
|
kind: RelocationKind::Absolute,
|
||||||
|
encoding: RelocationEncoding::Generic,
|
||||||
|
size: reloc_size,
|
||||||
|
addend: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for &(offset, id, addend) in data_relocs {
|
||||||
|
relocs.push(RelocRecord {
|
||||||
|
offset,
|
||||||
|
name: data_decls[id].clone(),
|
||||||
|
kind: RelocationKind::Absolute,
|
||||||
|
encoding: RelocationEncoding::Generic,
|
||||||
|
size: reloc_size,
|
||||||
|
addend,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let symbol = self.data_objects[data_id].unwrap();
|
||||||
|
let section = self.object.section_id(if writable {
|
||||||
|
StandardSection::Data
|
||||||
|
} else if relocs.is_empty() {
|
||||||
|
StandardSection::ReadOnlyData
|
||||||
|
} else {
|
||||||
|
StandardSection::ReadOnlyDataWithRel
|
||||||
|
});
|
||||||
|
let offset =
|
||||||
|
self.object
|
||||||
|
.add_symbol_data(symbol, section, &data, u64::from(align.unwrap_or(1)));
|
||||||
|
Ok(ObjectCompiledData {
|
||||||
|
offset,
|
||||||
|
section,
|
||||||
|
relocs,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_data_funcaddr(
|
||||||
|
&mut self,
|
||||||
|
_data: &mut ObjectCompiledData,
|
||||||
|
_offset: usize,
|
||||||
|
_what: ir::FuncRef,
|
||||||
|
) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_data_dataaddr(
|
||||||
|
&mut self,
|
||||||
|
_data: &mut ObjectCompiledData,
|
||||||
|
_offset: usize,
|
||||||
|
_what: ir::GlobalValue,
|
||||||
|
_usize: binemit::Addend,
|
||||||
|
) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize_function(
|
||||||
|
&mut self,
|
||||||
|
_id: FuncId,
|
||||||
|
func: &ObjectCompiledFunction,
|
||||||
|
namespace: &ModuleNamespace<Self>,
|
||||||
|
) {
|
||||||
|
for &RelocRecord {
|
||||||
|
offset,
|
||||||
|
ref name,
|
||||||
|
kind,
|
||||||
|
encoding,
|
||||||
|
size,
|
||||||
|
addend,
|
||||||
|
} in &func.relocs
|
||||||
|
{
|
||||||
|
let offset = func.offset + offset as u64;
|
||||||
|
let symbol = self.get_symbol(namespace, name);
|
||||||
|
self.object
|
||||||
|
.add_relocation(
|
||||||
|
func.section,
|
||||||
|
Relocation {
|
||||||
|
offset,
|
||||||
|
size,
|
||||||
|
kind,
|
||||||
|
encoding,
|
||||||
|
symbol,
|
||||||
|
addend,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_finalized_function(&self, _func: &ObjectCompiledFunction) {
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize_data(
|
||||||
|
&mut self,
|
||||||
|
_id: DataId,
|
||||||
|
data: &ObjectCompiledData,
|
||||||
|
namespace: &ModuleNamespace<Self>,
|
||||||
|
) {
|
||||||
|
for &RelocRecord {
|
||||||
|
offset,
|
||||||
|
ref name,
|
||||||
|
kind,
|
||||||
|
encoding,
|
||||||
|
size,
|
||||||
|
addend,
|
||||||
|
} in &data.relocs
|
||||||
|
{
|
||||||
|
let offset = data.offset + offset as u64;
|
||||||
|
let symbol = self.get_symbol(namespace, name);
|
||||||
|
self.object
|
||||||
|
.add_relocation(
|
||||||
|
data.section,
|
||||||
|
Relocation {
|
||||||
|
offset,
|
||||||
|
size,
|
||||||
|
kind,
|
||||||
|
encoding,
|
||||||
|
symbol,
|
||||||
|
addend,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_finalized_data(&self, _data: &ObjectCompiledData) {
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn publish(&mut self) {
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(self) -> ObjectProduct {
|
||||||
|
ObjectProduct {
|
||||||
|
object: self.object,
|
||||||
|
functions: self.functions,
|
||||||
|
data_objects: self.data_objects,
|
||||||
|
traps: self.traps,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObjectBackend {
|
||||||
|
// This should only be called during finalization because it creates
|
||||||
|
// symbols for missing libcalls.
|
||||||
|
fn get_symbol(
|
||||||
|
&mut self,
|
||||||
|
namespace: &ModuleNamespace<Self>,
|
||||||
|
name: &ir::ExternalName,
|
||||||
|
) -> SymbolId {
|
||||||
|
match *name {
|
||||||
|
ir::ExternalName::User { .. } => {
|
||||||
|
if namespace.is_function(name) {
|
||||||
|
let id = namespace.get_function_id(name);
|
||||||
|
self.functions[id].unwrap()
|
||||||
|
} else {
|
||||||
|
let id = namespace.get_data_id(name);
|
||||||
|
self.data_objects[id].unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ir::ExternalName::LibCall(ref libcall) => {
|
||||||
|
let name = (self.libcall_names)(*libcall);
|
||||||
|
if let Some(symbol) = self.object.symbol_id(name.as_bytes()) {
|
||||||
|
symbol
|
||||||
|
} else if let Some(symbol) = self.libcalls.get(libcall) {
|
||||||
|
*symbol
|
||||||
|
} else {
|
||||||
|
let symbol = self.object.add_symbol(Symbol {
|
||||||
|
name: name.as_bytes().to_vec(),
|
||||||
|
value: 0,
|
||||||
|
size: 0,
|
||||||
|
kind: SymbolKind::Text,
|
||||||
|
scope: SymbolScope::Unknown,
|
||||||
|
weak: false,
|
||||||
|
section: None,
|
||||||
|
});
|
||||||
|
self.libcalls.insert(*libcall, symbol);
|
||||||
|
symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("invalid ExternalName {}", name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn translate_linkage(linkage: Linkage) -> (SymbolScope, bool) {
|
||||||
|
let scope = match linkage {
|
||||||
|
Linkage::Import => SymbolScope::Unknown,
|
||||||
|
Linkage::Local => SymbolScope::Compilation,
|
||||||
|
Linkage::Export | Linkage::Preemptible => SymbolScope::Dynamic,
|
||||||
|
};
|
||||||
|
// TODO: this matches rustc_codegen_cranelift, but may be wrong.
|
||||||
|
let weak = linkage == Linkage::Preemptible;
|
||||||
|
(scope, weak)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ObjectCompiledFunction {
|
||||||
|
offset: u64,
|
||||||
|
size: u32,
|
||||||
|
section: SectionId,
|
||||||
|
relocs: Vec<RelocRecord>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ObjectCompiledData {
|
||||||
|
offset: u64,
|
||||||
|
section: SectionId,
|
||||||
|
relocs: Vec<RelocRecord>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is the output of `Module`'s
|
||||||
|
/// [`finish`](../cranelift_module/struct.Module.html#method.finish) function.
|
||||||
|
/// It contains the generated `Object` and other information produced during
|
||||||
|
/// compilation.
|
||||||
|
pub struct ObjectProduct {
|
||||||
|
/// Object artifact with all functions and data from the module defined.
|
||||||
|
pub object: Object,
|
||||||
|
/// Symbol IDs for functions (both declared and defined).
|
||||||
|
pub functions: SecondaryMap<FuncId, Option<SymbolId>>,
|
||||||
|
/// Symbol IDs for data objects (both declared and defined).
|
||||||
|
pub data_objects: SecondaryMap<DataId, Option<SymbolId>>,
|
||||||
|
/// Trap sites for defined functions.
|
||||||
|
pub traps: SecondaryMap<FuncId, Vec<ObjectTrapSite>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObjectProduct {
|
||||||
|
/// Return the `SymbolId` for the given function.
|
||||||
|
#[inline]
|
||||||
|
pub fn function_symbol(&self, id: FuncId) -> SymbolId {
|
||||||
|
self.functions[id].unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the `SymbolId` for the given data object.
|
||||||
|
#[inline]
|
||||||
|
pub fn data_symbol(&self, id: DataId) -> SymbolId {
|
||||||
|
self.data_objects[id].unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write the object bytes in memory.
|
||||||
|
#[inline]
|
||||||
|
pub fn emit(self) -> Result<Vec<u8>, String> {
|
||||||
|
self.object.write()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct RelocRecord {
|
||||||
|
offset: CodeOffset,
|
||||||
|
name: ir::ExternalName,
|
||||||
|
kind: RelocationKind,
|
||||||
|
encoding: RelocationEncoding,
|
||||||
|
size: u8,
|
||||||
|
addend: Addend,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct ObjectRelocSink {
|
||||||
|
relocs: Vec<RelocRecord>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelocSink for ObjectRelocSink {
|
||||||
|
fn reloc_ebb(&mut self, _offset: CodeOffset, _reloc: Reloc, _ebb_offset: CodeOffset) {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reloc_external(
|
||||||
|
&mut self,
|
||||||
|
offset: CodeOffset,
|
||||||
|
reloc: Reloc,
|
||||||
|
name: &ir::ExternalName,
|
||||||
|
addend: Addend,
|
||||||
|
) {
|
||||||
|
let (kind, encoding, size) = match reloc {
|
||||||
|
Reloc::Abs4 => (RelocationKind::Absolute, RelocationEncoding::Generic, 32),
|
||||||
|
Reloc::Abs8 => (RelocationKind::Absolute, RelocationEncoding::Generic, 64),
|
||||||
|
Reloc::X86PCRel4 => (RelocationKind::Relative, RelocationEncoding::Generic, 32),
|
||||||
|
Reloc::X86CallPCRel4 => (RelocationKind::Relative, RelocationEncoding::X86Branch, 32),
|
||||||
|
// TODO: Get Cranelift to tell us when we can use
|
||||||
|
// R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX.
|
||||||
|
Reloc::X86CallPLTRel4 => (
|
||||||
|
RelocationKind::PltRelative,
|
||||||
|
RelocationEncoding::X86Branch,
|
||||||
|
32,
|
||||||
|
),
|
||||||
|
Reloc::X86GOTPCRel4 => (RelocationKind::GotRelative, RelocationEncoding::Generic, 32),
|
||||||
|
// FIXME
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
self.relocs.push(RelocRecord {
|
||||||
|
offset,
|
||||||
|
name: name.clone(),
|
||||||
|
kind,
|
||||||
|
encoding,
|
||||||
|
size,
|
||||||
|
addend,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reloc_jt(&mut self, _offset: CodeOffset, reloc: Reloc, _jt: ir::JumpTable) {
|
||||||
|
match reloc {
|
||||||
|
Reloc::X86PCRelRodata4 => {
|
||||||
|
// Not necessary to record this unless we are going to split apart code and its
|
||||||
|
// jumptbl/rodata.
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
panic!("Unhandled reloc");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reloc_constant(&mut self, _offset: CodeOffset, reloc: Reloc, _jt: ir::ConstantOffset) {
|
||||||
|
match reloc {
|
||||||
|
Reloc::X86PCRelRodata4 => {
|
||||||
|
// Not necessary to record this unless we are going to split apart code and its
|
||||||
|
// jumptbl/rodata.
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
panic!("Unhandled reloc");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
cranelift/object/src/lib.rs
Normal file
38
cranelift/object/src/lib.rs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
//! Top-level lib.rs for `cranelift_object`.
|
||||||
|
//!
|
||||||
|
//! Users of this module should not have to depend on `object` directly.
|
||||||
|
|
||||||
|
#![deny(
|
||||||
|
missing_docs,
|
||||||
|
trivial_numeric_casts,
|
||||||
|
unused_extern_crates,
|
||||||
|
unstable_features
|
||||||
|
)]
|
||||||
|
#![warn(unused_import_braces)]
|
||||||
|
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
|
||||||
|
#![cfg_attr(
|
||||||
|
feature = "cargo-clippy",
|
||||||
|
allow(clippy::new_without_default, clippy::new_without_default_derive)
|
||||||
|
)]
|
||||||
|
#![cfg_attr(
|
||||||
|
feature = "cargo-clippy",
|
||||||
|
warn(
|
||||||
|
clippy::float_arithmetic,
|
||||||
|
clippy::mut_mut,
|
||||||
|
clippy::nonminimal_bool,
|
||||||
|
clippy::option_map_unwrap_or,
|
||||||
|
clippy::option_map_unwrap_or_else,
|
||||||
|
clippy::print_stdout,
|
||||||
|
clippy::unicode_not_nfc,
|
||||||
|
clippy::use_self
|
||||||
|
)
|
||||||
|
)]
|
||||||
|
|
||||||
|
mod backend;
|
||||||
|
mod traps;
|
||||||
|
|
||||||
|
pub use crate::backend::{ObjectBackend, ObjectBuilder, ObjectProduct, ObjectTrapCollection};
|
||||||
|
pub use crate::traps::{ObjectTrapSink, ObjectTrapSite};
|
||||||
|
|
||||||
|
/// Version number of this crate.
|
||||||
|
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
32
cranelift/object/src/traps.rs
Normal file
32
cranelift/object/src/traps.rs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
//! Records every `TrapCode` that cranelift outputs during code generation,
|
||||||
|
//! for every function in the module. This data may be useful at runtime.
|
||||||
|
|
||||||
|
use cranelift_codegen::{binemit, ir};
|
||||||
|
|
||||||
|
/// Record of the arguments cranelift passes to `TrapSink::trap`
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ObjectTrapSite {
|
||||||
|
/// Offset into function
|
||||||
|
pub offset: binemit::CodeOffset,
|
||||||
|
/// Source location given to cranelift
|
||||||
|
pub srcloc: ir::SourceLoc,
|
||||||
|
/// Trap code, as determined by cranelift
|
||||||
|
pub code: ir::TrapCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Record of the trap sites for a given function
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
pub struct ObjectTrapSink {
|
||||||
|
/// All trap sites collected in function
|
||||||
|
pub sites: Vec<ObjectTrapSite>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl binemit::TrapSink for ObjectTrapSink {
|
||||||
|
fn trap(&mut self, offset: binemit::CodeOffset, srcloc: ir::SourceLoc, code: ir::TrapCode) {
|
||||||
|
self.sites.push(ObjectTrapSite {
|
||||||
|
offset,
|
||||||
|
srcloc,
|
||||||
|
code,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,8 @@ use cranelift_codegen::binemit::{
|
|||||||
use cranelift_codegen::isa::TargetIsa;
|
use cranelift_codegen::isa::TargetIsa;
|
||||||
use cranelift_codegen::{self, ir, settings};
|
use cranelift_codegen::{self, ir, settings};
|
||||||
use cranelift_module::{
|
use cranelift_module::{
|
||||||
Backend, DataContext, DataDescription, Init, Linkage, ModuleNamespace, ModuleResult,
|
Backend, DataContext, DataDescription, DataId, FuncId, Init, Linkage, ModuleNamespace,
|
||||||
|
ModuleResult,
|
||||||
};
|
};
|
||||||
use cranelift_native;
|
use cranelift_native;
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
@@ -222,12 +223,13 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend {
|
|||||||
&*self.isa
|
&*self.isa
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_function(&mut self, _name: &str, _linkage: Linkage) {
|
fn declare_function(&mut self, _id: FuncId, _name: &str, _linkage: Linkage) {
|
||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_data(
|
fn declare_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
_id: DataId,
|
||||||
_name: &str,
|
_name: &str,
|
||||||
_linkage: Linkage,
|
_linkage: Linkage,
|
||||||
_writable: bool,
|
_writable: bool,
|
||||||
@@ -238,6 +240,7 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend {
|
|||||||
|
|
||||||
fn define_function(
|
fn define_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
_id: FuncId,
|
||||||
name: &str,
|
name: &str,
|
||||||
ctx: &cranelift_codegen::Context,
|
ctx: &cranelift_codegen::Context,
|
||||||
_namespace: &ModuleNamespace<Self>,
|
_namespace: &ModuleNamespace<Self>,
|
||||||
@@ -283,6 +286,7 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend {
|
|||||||
|
|
||||||
fn define_data(
|
fn define_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
_id: DataId,
|
||||||
_name: &str,
|
_name: &str,
|
||||||
writable: bool,
|
writable: bool,
|
||||||
align: Option<u8>,
|
align: Option<u8>,
|
||||||
@@ -372,6 +376,7 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend {
|
|||||||
|
|
||||||
fn finalize_function(
|
fn finalize_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
_id: FuncId,
|
||||||
func: &Self::CompiledFunction,
|
func: &Self::CompiledFunction,
|
||||||
namespace: &ModuleNamespace<Self>,
|
namespace: &ModuleNamespace<Self>,
|
||||||
) -> Self::FinalizedFunction {
|
) -> Self::FinalizedFunction {
|
||||||
@@ -425,6 +430,7 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend {
|
|||||||
|
|
||||||
fn finalize_data(
|
fn finalize_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
_id: DataId,
|
||||||
data: &Self::CompiledData,
|
data: &Self::CompiledData,
|
||||||
namespace: &ModuleNamespace<Self>,
|
namespace: &ModuleNamespace<Self>,
|
||||||
) -> Self::FinalizedData {
|
) -> Self::FinalizedData {
|
||||||
|
|||||||
Reference in New Issue
Block a user