Add clif-util compile option to output object file (#5493)
* add clif-util compile option to output object file * switch from a box to a borrow * update objectmodule tests to use borrowed isa * put targetisa into an arc
This commit is contained in:
@@ -216,7 +216,7 @@ pub fn isa_builder(triple: Triple) -> IsaBuilder {
|
|||||||
constructor: |triple, shared_flags, builder| {
|
constructor: |triple, shared_flags, builder| {
|
||||||
let isa_flags = aarch64_settings::Flags::new(&shared_flags, builder);
|
let isa_flags = aarch64_settings::Flags::new(&shared_flags, builder);
|
||||||
let backend = AArch64Backend::new_with_flags(triple, shared_flags, isa_flags);
|
let backend = AArch64Backend::new_with_flags(triple, shared_flags, isa_flags);
|
||||||
Ok(Box::new(backend))
|
Ok(backend.wrapped())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ use crate::machinst::{CompiledCode, CompiledCodeStencil, TextSectionBuilder, Unw
|
|||||||
use crate::settings;
|
use crate::settings;
|
||||||
use crate::settings::SetResult;
|
use crate::settings::SetResult;
|
||||||
use crate::CodegenResult;
|
use crate::CodegenResult;
|
||||||
use alloc::{boxed::Box, vec::Vec};
|
use alloc::{boxed::Box, sync::Arc, vec::Vec};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::fmt::{Debug, Formatter};
|
use core::fmt::{Debug, Formatter};
|
||||||
use target_lexicon::{triple, Architecture, PointerWidth, Triple};
|
use target_lexicon::{triple, Architecture, PointerWidth, Triple};
|
||||||
@@ -142,14 +142,16 @@ impl fmt::Display for LookupError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The type of a polymorphic TargetISA object which is 'static.
|
||||||
|
pub type OwnedTargetIsa = Arc<dyn TargetIsa>;
|
||||||
|
|
||||||
/// Builder for a `TargetIsa`.
|
/// Builder for a `TargetIsa`.
|
||||||
/// Modify the ISA-specific settings before creating the `TargetIsa` trait object with `finish`.
|
/// Modify the ISA-specific settings before creating the `TargetIsa` trait object with `finish`.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Builder {
|
pub struct Builder {
|
||||||
triple: Triple,
|
triple: Triple,
|
||||||
setup: settings::Builder,
|
setup: settings::Builder,
|
||||||
constructor:
|
constructor: fn(Triple, settings::Flags, settings::Builder) -> CodegenResult<OwnedTargetIsa>,
|
||||||
fn(Triple, settings::Flags, settings::Builder) -> CodegenResult<Box<dyn TargetIsa>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Builder {
|
impl Builder {
|
||||||
@@ -169,7 +171,7 @@ impl Builder {
|
|||||||
/// flags are inconsistent or incompatible: for example, some
|
/// flags are inconsistent or incompatible: for example, some
|
||||||
/// platform-independent features, like general SIMD support, may
|
/// platform-independent features, like general SIMD support, may
|
||||||
/// need certain ISA extensions to be enabled.
|
/// need certain ISA extensions to be enabled.
|
||||||
pub fn finish(self, shared_flags: settings::Flags) -> CodegenResult<Box<dyn TargetIsa>> {
|
pub fn finish(self, shared_flags: settings::Flags) -> CodegenResult<OwnedTargetIsa> {
|
||||||
(self.constructor)(self.triple, shared_flags, self.setup)
|
(self.constructor)(self.triple, shared_flags, self.setup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -297,6 +299,14 @@ pub trait TargetIsa: fmt::Display + Send + Sync {
|
|||||||
|
|
||||||
/// The function alignment required by this ISA.
|
/// The function alignment required by this ISA.
|
||||||
fn function_alignment(&self) -> u32;
|
fn function_alignment(&self) -> u32;
|
||||||
|
|
||||||
|
/// Create a polymorphic TargetIsa from this specific implementation.
|
||||||
|
fn wrapped(self) -> OwnedTargetIsa
|
||||||
|
where
|
||||||
|
Self: Sized + 'static,
|
||||||
|
{
|
||||||
|
Arc::new(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Methods implemented for free for target ISA!
|
/// Methods implemented for free for target ISA!
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ pub fn isa_builder(triple: Triple) -> IsaBuilder {
|
|||||||
constructor: |triple, shared_flags, builder| {
|
constructor: |triple, shared_flags, builder| {
|
||||||
let isa_flags = riscv_settings::Flags::new(&shared_flags, builder);
|
let isa_flags = riscv_settings::Flags::new(&shared_flags, builder);
|
||||||
let backend = Riscv64Backend::new_with_flags(triple, shared_flags, isa_flags);
|
let backend = Riscv64Backend::new_with_flags(triple, shared_flags, isa_flags);
|
||||||
Ok(Box::new(backend))
|
Ok(backend.wrapped())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ pub fn isa_builder(triple: Triple) -> IsaBuilder {
|
|||||||
constructor: |triple, shared_flags, builder| {
|
constructor: |triple, shared_flags, builder| {
|
||||||
let isa_flags = s390x_settings::Flags::new(&shared_flags, builder);
|
let isa_flags = s390x_settings::Flags::new(&shared_flags, builder);
|
||||||
let backend = S390xBackend::new_with_flags(triple, shared_flags, isa_flags);
|
let backend = S390xBackend::new_with_flags(triple, shared_flags, isa_flags);
|
||||||
Ok(Box::new(backend))
|
Ok(backend.wrapped())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
pub use self::inst::{args, EmitInfo, EmitState, Inst};
|
pub use self::inst::{args, EmitInfo, EmitState, Inst};
|
||||||
|
|
||||||
use super::TargetIsa;
|
use super::{OwnedTargetIsa, TargetIsa};
|
||||||
use crate::ir::{condcodes::IntCC, Function, Type};
|
use crate::ir::{condcodes::IntCC, Function, Type};
|
||||||
#[cfg(feature = "unwind")]
|
#[cfg(feature = "unwind")]
|
||||||
use crate::isa::unwind::systemv;
|
use crate::isa::unwind::systemv;
|
||||||
@@ -196,7 +196,7 @@ fn isa_constructor(
|
|||||||
triple: Triple,
|
triple: Triple,
|
||||||
shared_flags: Flags,
|
shared_flags: Flags,
|
||||||
builder: shared_settings::Builder,
|
builder: shared_settings::Builder,
|
||||||
) -> CodegenResult<Box<dyn TargetIsa>> {
|
) -> CodegenResult<OwnedTargetIsa> {
|
||||||
let isa_flags = x64_settings::Flags::new(&shared_flags, builder);
|
let isa_flags = x64_settings::Flags::new(&shared_flags, builder);
|
||||||
|
|
||||||
// Check for compatibility between flags and ISA level
|
// Check for compatibility between flags and ISA level
|
||||||
@@ -214,7 +214,7 @@ fn isa_constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let backend = X64Backend::new_with_flags(triple, shared_flags, isa_flags);
|
let backend = X64Backend::new_with_flags(triple, shared_flags, isa_flags);
|
||||||
Ok(Box::new(backend))
|
Ok(backend.wrapped())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use cranelift_codegen::data_value::DataValue;
|
|||||||
use cranelift_codegen::ir::{
|
use cranelift_codegen::ir::{
|
||||||
ExternalName, Function, InstBuilder, Signature, UserExternalName, UserFuncName,
|
ExternalName, Function, InstBuilder, Signature, UserExternalName, UserFuncName,
|
||||||
};
|
};
|
||||||
use cranelift_codegen::isa::TargetIsa;
|
use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa};
|
||||||
use cranelift_codegen::{ir, settings, CodegenError, Context};
|
use cranelift_codegen::{ir, settings, CodegenError, Context};
|
||||||
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
||||||
use cranelift_jit::{JITBuilder, JITModule};
|
use cranelift_jit::{JITBuilder, JITModule};
|
||||||
@@ -86,7 +86,7 @@ impl TestFileCompiler {
|
|||||||
/// Build a [TestFileCompiler] from a [TargetIsa]. For functions to be runnable on the
|
/// Build a [TestFileCompiler] from a [TargetIsa]. For functions to be runnable on the
|
||||||
/// host machine, this [TargetIsa] must match the host machine's ISA (see
|
/// host machine, this [TargetIsa] must match the host machine's ISA (see
|
||||||
/// [TestFileCompiler::with_host_isa]).
|
/// [TestFileCompiler::with_host_isa]).
|
||||||
pub fn new(isa: Box<dyn TargetIsa>) -> Self {
|
pub fn new(isa: OwnedTargetIsa) -> Self {
|
||||||
let builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
|
let builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
|
||||||
let module = JITModule::new(builder);
|
let module = JITModule::new(builder);
|
||||||
let ctx = module.make_context();
|
let ctx = module.make_context();
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use crate::subtest::{Context, SubTest};
|
|||||||
use anyhow::Context as _;
|
use anyhow::Context as _;
|
||||||
use cranelift_codegen::data_value::DataValue;
|
use cranelift_codegen::data_value::DataValue;
|
||||||
use cranelift_codegen::ir::Type;
|
use cranelift_codegen::ir::Type;
|
||||||
use cranelift_codegen::isa::TargetIsa;
|
use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa};
|
||||||
use cranelift_codegen::settings::{Configurable, Flags};
|
use cranelift_codegen::settings::{Configurable, Flags};
|
||||||
use cranelift_codegen::{ir, settings};
|
use cranelift_codegen::{ir, settings};
|
||||||
use cranelift_reader::TestCommand;
|
use cranelift_reader::TestCommand;
|
||||||
@@ -34,7 +34,7 @@ fn build_host_isa(
|
|||||||
infer_native_flags: bool,
|
infer_native_flags: bool,
|
||||||
flags: settings::Flags,
|
flags: settings::Flags,
|
||||||
isa_flags: Vec<settings::Value>,
|
isa_flags: Vec<settings::Value>,
|
||||||
) -> Box<dyn TargetIsa> {
|
) -> OwnedTargetIsa {
|
||||||
let mut builder = cranelift_native::builder_with_options(infer_native_flags)
|
let mut builder = cranelift_native::builder_with_options(infer_native_flags)
|
||||||
.expect("Unable to build a TargetIsa for the current host");
|
.expect("Unable to build a TargetIsa for the current host");
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ fn write_non_default_flags(f: &mut fmt::Formatter<'_>, flags: &settings::Flags)
|
|||||||
/// A generated function with an ISA that targets one of cranelift's backends.
|
/// A generated function with an ISA that targets one of cranelift's backends.
|
||||||
pub struct FunctionWithIsa {
|
pub struct FunctionWithIsa {
|
||||||
/// TargetIsa to use when compiling this test case
|
/// TargetIsa to use when compiling this test case
|
||||||
pub isa: Box<dyn isa::TargetIsa>,
|
pub isa: isa::OwnedTargetIsa,
|
||||||
|
|
||||||
/// Function under test
|
/// Function under test
|
||||||
pub func: Function,
|
pub func: Function,
|
||||||
@@ -96,7 +96,7 @@ impl<'a> Arbitrary<'a> for FunctionWithIsa {
|
|||||||
|
|
||||||
pub struct TestCase {
|
pub struct TestCase {
|
||||||
/// TargetIsa to use when compiling this test case
|
/// TargetIsa to use when compiling this test case
|
||||||
pub isa: Box<dyn isa::TargetIsa>,
|
pub isa: isa::OwnedTargetIsa,
|
||||||
/// Function under test
|
/// Function under test
|
||||||
pub func: Function,
|
pub func: Function,
|
||||||
/// Generate multiple test inputs for each test case.
|
/// Generate multiple test inputs for each test case.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! Defines `JITModule`.
|
//! Defines `JITModule`.
|
||||||
|
|
||||||
use crate::{compiled_blob::CompiledBlob, memory::BranchProtection, memory::Memory};
|
use crate::{compiled_blob::CompiledBlob, memory::BranchProtection, memory::Memory};
|
||||||
use cranelift_codegen::isa::TargetIsa;
|
use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa};
|
||||||
use cranelift_codegen::settings::Configurable;
|
use cranelift_codegen::settings::Configurable;
|
||||||
use cranelift_codegen::{self, ir, settings, MachReloc};
|
use cranelift_codegen::{self, ir, settings, MachReloc};
|
||||||
use cranelift_codegen::{binemit::Reloc, CodegenError};
|
use cranelift_codegen::{binemit::Reloc, CodegenError};
|
||||||
@@ -26,7 +26,7 @@ const READONLY_DATA_ALIGNMENT: u64 = 0x1;
|
|||||||
|
|
||||||
/// A builder for `JITModule`.
|
/// A builder for `JITModule`.
|
||||||
pub struct JITBuilder {
|
pub struct JITBuilder {
|
||||||
isa: Box<dyn TargetIsa>,
|
isa: OwnedTargetIsa,
|
||||||
symbols: HashMap<String, *const u8>,
|
symbols: HashMap<String, *const u8>,
|
||||||
lookup_symbols: Vec<Box<dyn Fn(&str) -> Option<*const u8>>>,
|
lookup_symbols: Vec<Box<dyn Fn(&str) -> Option<*const u8>>>,
|
||||||
libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
|
libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
|
||||||
@@ -67,7 +67,7 @@ impl JITBuilder {
|
|||||||
/// floating point instructions, and for stack probes. If you don't know what to use for this
|
/// floating point instructions, and for stack probes. If you don't know what to use for this
|
||||||
/// argument, use `cranelift_module::default_libcall_names()`.
|
/// argument, use `cranelift_module::default_libcall_names()`.
|
||||||
pub fn with_isa(
|
pub fn with_isa(
|
||||||
isa: Box<dyn TargetIsa>,
|
isa: OwnedTargetIsa,
|
||||||
libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
|
libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let symbols = HashMap::new();
|
let symbols = HashMap::new();
|
||||||
@@ -153,7 +153,7 @@ struct GotUpdate {
|
|||||||
///
|
///
|
||||||
/// See the `JITBuilder` for a convenient way to construct `JITModule` instances.
|
/// See the `JITBuilder` for a convenient way to construct `JITModule` instances.
|
||||||
pub struct JITModule {
|
pub struct JITModule {
|
||||||
isa: Box<dyn TargetIsa>,
|
isa: OwnedTargetIsa,
|
||||||
hotswap_enabled: bool,
|
hotswap_enabled: bool,
|
||||||
symbols: RefCell<HashMap<String, *const u8>>,
|
symbols: RefCell<HashMap<String, *const u8>>,
|
||||||
lookup_symbols: Vec<Box<dyn Fn(&str) -> Option<*const u8>>>,
|
lookup_symbols: Vec<Box<dyn Fn(&str) -> Option<*const u8>>>,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use cranelift_codegen::entity::SecondaryMap;
|
use cranelift_codegen::entity::SecondaryMap;
|
||||||
use cranelift_codegen::isa::TargetIsa;
|
use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa};
|
||||||
use cranelift_codegen::{self, ir, MachReloc};
|
use cranelift_codegen::{self, ir, MachReloc};
|
||||||
use cranelift_codegen::{
|
use cranelift_codegen::{
|
||||||
binemit::{Addend, CodeOffset, Reloc},
|
binemit::{Addend, CodeOffset, Reloc},
|
||||||
@@ -26,7 +26,7 @@ use target_lexicon::PointerWidth;
|
|||||||
|
|
||||||
/// A builder for `ObjectModule`.
|
/// A builder for `ObjectModule`.
|
||||||
pub struct ObjectBuilder {
|
pub struct ObjectBuilder {
|
||||||
isa: Box<dyn TargetIsa>,
|
isa: OwnedTargetIsa,
|
||||||
binary_format: object::BinaryFormat,
|
binary_format: object::BinaryFormat,
|
||||||
architecture: object::Architecture,
|
architecture: object::Architecture,
|
||||||
flags: object::FileFlags,
|
flags: object::FileFlags,
|
||||||
@@ -45,7 +45,7 @@ impl ObjectBuilder {
|
|||||||
/// floating point instructions, and for stack probes. If you don't know what to use for this
|
/// floating point instructions, and for stack probes. If you don't know what to use for this
|
||||||
/// argument, use [cranelift_module::default_libcall_names]().
|
/// argument, use [cranelift_module::default_libcall_names]().
|
||||||
pub fn new<V: Into<Vec<u8>>>(
|
pub fn new<V: Into<Vec<u8>>>(
|
||||||
isa: Box<dyn TargetIsa>,
|
isa: OwnedTargetIsa,
|
||||||
name: V,
|
name: V,
|
||||||
libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
|
libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
|
||||||
) -> ModuleResult<Self> {
|
) -> ModuleResult<Self> {
|
||||||
@@ -124,7 +124,7 @@ impl ObjectBuilder {
|
|||||||
///
|
///
|
||||||
/// See the `ObjectBuilder` for a convenient way to construct `ObjectModule` instances.
|
/// See the `ObjectBuilder` for a convenient way to construct `ObjectModule` instances.
|
||||||
pub struct ObjectModule {
|
pub struct ObjectModule {
|
||||||
isa: Box<dyn TargetIsa>,
|
isa: OwnedTargetIsa,
|
||||||
object: Object<'static>,
|
object: Object<'static>,
|
||||||
declarations: ModuleDeclarations,
|
declarations: ModuleDeclarations,
|
||||||
functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>,
|
functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
use crate::error::{Location, ParseError};
|
use crate::error::{Location, ParseError};
|
||||||
use crate::testcommand::TestOption;
|
use crate::testcommand::TestOption;
|
||||||
use cranelift_codegen::isa::TargetIsa;
|
use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa};
|
||||||
use cranelift_codegen::settings::{Configurable, Flags, SetError};
|
use cranelift_codegen::settings::{Configurable, Flags, SetError};
|
||||||
|
|
||||||
/// The ISA specifications in a `.clif` file.
|
/// The ISA specifications in a `.clif` file.
|
||||||
@@ -19,7 +19,7 @@ pub enum IsaSpec {
|
|||||||
|
|
||||||
/// The parsed file does contain `isa` commands.
|
/// The parsed file does contain `isa` commands.
|
||||||
/// Each `isa` command is used to configure a `TargetIsa` trait object.
|
/// Each `isa` command is used to configure a `TargetIsa` trait object.
|
||||||
Some(Vec<Box<dyn TargetIsa>>),
|
Some(Vec<OwnedTargetIsa>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IsaSpec {
|
impl IsaSpec {
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ mod testcommand;
|
|||||||
mod testfile;
|
mod testfile;
|
||||||
|
|
||||||
use anyhow::{Error, Result};
|
use anyhow::{Error, Result};
|
||||||
use cranelift_codegen::isa::{self, TargetIsa};
|
use cranelift_codegen::isa::{self, OwnedTargetIsa};
|
||||||
use cranelift_codegen::settings::{self, FlagsOrIsa};
|
use cranelift_codegen::settings::{self, FlagsOrIsa};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use target_lexicon::Triple;
|
use target_lexicon::Triple;
|
||||||
@@ -52,7 +52,7 @@ use target_lexicon::Triple;
|
|||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub enum OwnedFlagsOrIsa {
|
pub enum OwnedFlagsOrIsa {
|
||||||
Flags(settings::Flags),
|
Flags(settings::Flags),
|
||||||
Isa(Box<dyn TargetIsa>),
|
Isa(OwnedTargetIsa),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OwnedFlagsOrIsa {
|
impl OwnedFlagsOrIsa {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use cranelift_codegen::print_errors::pretty_error;
|
|||||||
use cranelift_codegen::settings::FlagsOrIsa;
|
use cranelift_codegen::settings::FlagsOrIsa;
|
||||||
use cranelift_codegen::timing;
|
use cranelift_codegen::timing;
|
||||||
use cranelift_codegen::Context;
|
use cranelift_codegen::Context;
|
||||||
|
use cranelift_reader::OwnedFlagsOrIsa;
|
||||||
use cranelift_reader::{parse_sets_and_triple, parse_test, ParseOptions};
|
use cranelift_reader::{parse_sets_and_triple, parse_test, ParseOptions};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -37,18 +38,50 @@ pub struct Options {
|
|||||||
|
|
||||||
/// Specify an input file to be used. Use '-' for stdin.
|
/// Specify an input file to be used. Use '-' for stdin.
|
||||||
files: Vec<PathBuf>,
|
files: Vec<PathBuf>,
|
||||||
|
|
||||||
|
/// Output object file
|
||||||
|
#[clap(short = 'o', long = "output")]
|
||||||
|
output: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(options: &Options) -> Result<()> {
|
pub fn run(options: &Options) -> Result<()> {
|
||||||
let parsed = parse_sets_and_triple(&options.settings, &options.target)?;
|
let parsed = parse_sets_and_triple(&options.settings, &options.target)?;
|
||||||
|
|
||||||
|
let mut module = match (&options.output, &parsed) {
|
||||||
|
(Some(output), OwnedFlagsOrIsa::Isa(isa)) => {
|
||||||
|
let builder = cranelift_object::ObjectBuilder::new(
|
||||||
|
isa.clone(),
|
||||||
|
output
|
||||||
|
.file_name()
|
||||||
|
.and_then(|s| s.to_str())
|
||||||
|
.unwrap_or("a.out"),
|
||||||
|
cranelift_module::default_libcall_names(),
|
||||||
|
)?;
|
||||||
|
Some(cranelift_object::ObjectModule::new(builder))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
for path in &options.files {
|
for path in &options.files {
|
||||||
let name = String::from(path.as_os_str().to_string_lossy());
|
let name = String::from(path.as_os_str().to_string_lossy());
|
||||||
handle_module(options, path, &name, parsed.as_fisa())?;
|
handle_module(options, path, &name, parsed.as_fisa(), module.as_mut())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let (Some(module), Some(output)) = (module, &options.output) {
|
||||||
|
let bytes = module.finish().emit()?;
|
||||||
|
std::fs::write(output, bytes)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_module(options: &Options, path: &Path, name: &str, fisa: FlagsOrIsa) -> Result<()> {
|
fn handle_module(
|
||||||
|
options: &Options,
|
||||||
|
path: &Path,
|
||||||
|
name: &str,
|
||||||
|
fisa: FlagsOrIsa,
|
||||||
|
module: Option<&mut impl cranelift_module::Module>,
|
||||||
|
) -> Result<()> {
|
||||||
let buffer = read_to_string(&path)?;
|
let buffer = read_to_string(&path)?;
|
||||||
let test_file = parse_test(&buffer, ParseOptions::default())
|
let test_file = parse_test(&buffer, ParseOptions::default())
|
||||||
.with_context(|| format!("failed to parse {}", name))?;
|
.with_context(|| format!("failed to parse {}", name))?;
|
||||||
@@ -57,39 +90,48 @@ fn handle_module(options: &Options, path: &Path, name: &str, fisa: FlagsOrIsa) -
|
|||||||
// file contains a unique isa, use that.
|
// file contains a unique isa, use that.
|
||||||
let isa = fisa.isa.or(test_file.isa_spec.unique_isa());
|
let isa = fisa.isa.or(test_file.isa_spec.unique_isa());
|
||||||
|
|
||||||
if isa.is_none() {
|
let isa = match isa {
|
||||||
anyhow::bail!("compilation requires a target isa");
|
None => anyhow::bail!("compilation requires a target isa"),
|
||||||
|
Some(isa) => isa,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (func, _) in test_file.functions {
|
for (func, _) in test_file.functions {
|
||||||
if let Some(isa) = isa {
|
let mut context = Context::new();
|
||||||
let mut context = Context::new();
|
context.func = func;
|
||||||
context.func = func;
|
let mut mem = vec![];
|
||||||
let mut mem = vec![];
|
|
||||||
|
|
||||||
// Compile and encode the result to machine code.
|
// Compile and encode the result to machine code.
|
||||||
let compiled_code = context
|
let compiled_code = context
|
||||||
.compile_and_emit(isa, &mut mem)
|
.compile_and_emit(isa, &mut mem)
|
||||||
.map_err(|err| anyhow::anyhow!("{}", pretty_error(&err.func, err.inner)))?;
|
.map_err(|err| anyhow::anyhow!("{}", pretty_error(&err.func, err.inner)))?;
|
||||||
let code_info = compiled_code.code_info();
|
let code_info = compiled_code.code_info();
|
||||||
|
|
||||||
if options.print {
|
if let Some(&mut ref mut module) = module {
|
||||||
println!("{}", context.func.display());
|
let name = context.func.name.to_string();
|
||||||
}
|
let fid = module.declare_function(
|
||||||
|
&name,
|
||||||
|
cranelift_module::Linkage::Export,
|
||||||
|
&context.func.signature,
|
||||||
|
)?;
|
||||||
|
module.define_function(fid, &mut context)?;
|
||||||
|
}
|
||||||
|
|
||||||
if options.disasm {
|
if options.print {
|
||||||
let result = context.compiled_code().unwrap();
|
println!("{}", context.func.display());
|
||||||
print_all(
|
}
|
||||||
isa,
|
|
||||||
&context.func.params,
|
if options.disasm {
|
||||||
&mem,
|
let result = context.compiled_code().unwrap();
|
||||||
code_info.total_size,
|
print_all(
|
||||||
options.print,
|
isa,
|
||||||
result.buffer.relocs(),
|
&context.func.params,
|
||||||
result.buffer.traps(),
|
&mem,
|
||||||
result.buffer.stack_maps(),
|
code_info.total_size,
|
||||||
)?;
|
options.print,
|
||||||
}
|
result.buffer.relocs(),
|
||||||
|
result.buffer.traps(),
|
||||||
|
result.buffer.stack_maps(),
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
use crate::utils::{iterate_files, read_to_string};
|
use crate::utils::{iterate_files, read_to_string};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use cranelift_codegen::isa::{CallConv, TargetIsa};
|
use cranelift_codegen::isa::{CallConv, OwnedTargetIsa};
|
||||||
use cranelift_filetests::TestFileCompiler;
|
use cranelift_filetests::TestFileCompiler;
|
||||||
use cranelift_native::builder as host_isa_builder;
|
use cranelift_native::builder as host_isa_builder;
|
||||||
use cranelift_reader::{parse_run_command, parse_test, Details, IsaSpec, ParseOptions};
|
use cranelift_reader::{parse_run_command, parse_test, Details, IsaSpec, ParseOptions};
|
||||||
@@ -105,7 +105,7 @@ fn run_file_contents(file_contents: String) -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Build an ISA based on the current machine running this code (the host)
|
/// Build an ISA based on the current machine running this code (the host)
|
||||||
fn create_target_isa(isa_spec: &IsaSpec) -> Result<Box<dyn TargetIsa>> {
|
fn create_target_isa(isa_spec: &IsaSpec) -> Result<OwnedTargetIsa> {
|
||||||
if let IsaSpec::None(flags) = isa_spec {
|
if let IsaSpec::None(flags) = isa_spec {
|
||||||
// build an ISA for the current machine
|
// build an ISA for the current machine
|
||||||
let builder = host_isa_builder().map_err(|s| anyhow::anyhow!("{}", s))?;
|
let builder = host_isa_builder().map_err(|s| anyhow::anyhow!("{}", s))?;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use anyhow::{Context as _, Result};
|
|||||||
use cranelift_codegen::ir::{
|
use cranelift_codegen::ir::{
|
||||||
self, ExternalName, Function, InstBuilder, MemFlags, UserExternalName, UserFuncName, Value,
|
self, ExternalName, Function, InstBuilder, MemFlags, UserExternalName, UserFuncName, Value,
|
||||||
};
|
};
|
||||||
use cranelift_codegen::isa::TargetIsa;
|
use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa};
|
||||||
use cranelift_codegen::print_errors::pretty_error;
|
use cranelift_codegen::print_errors::pretty_error;
|
||||||
use cranelift_codegen::Context;
|
use cranelift_codegen::Context;
|
||||||
use cranelift_codegen::{settings, MachReloc, MachTrap};
|
use cranelift_codegen::{settings, MachReloc, MachTrap};
|
||||||
@@ -68,7 +68,7 @@ impl Default for CompilerContext {
|
|||||||
/// the Wasm to Compiler IR, optimizing it and then translating to assembly.
|
/// the Wasm to Compiler IR, optimizing it and then translating to assembly.
|
||||||
pub(crate) struct Compiler {
|
pub(crate) struct Compiler {
|
||||||
contexts: Mutex<Vec<CompilerContext>>,
|
contexts: Mutex<Vec<CompilerContext>>,
|
||||||
isa: Box<dyn TargetIsa>,
|
isa: OwnedTargetIsa,
|
||||||
linkopts: LinkOptions,
|
linkopts: LinkOptions,
|
||||||
cache_store: Option<Arc<dyn CacheStore>>,
|
cache_store: Option<Arc<dyn CacheStore>>,
|
||||||
}
|
}
|
||||||
@@ -103,7 +103,7 @@ impl Drop for Compiler {
|
|||||||
|
|
||||||
impl Compiler {
|
impl Compiler {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
isa: Box<dyn TargetIsa>,
|
isa: OwnedTargetIsa,
|
||||||
cache_store: Option<Arc<dyn CacheStore>>,
|
cache_store: Option<Arc<dyn CacheStore>>,
|
||||||
linkopts: LinkOptions,
|
linkopts: LinkOptions,
|
||||||
) -> Compiler {
|
) -> Compiler {
|
||||||
|
|||||||
Reference in New Issue
Block a user