summaryrefslogtreecommitdiffstats
path: root/third_party/rust/cranelift-codegen/src/isa/x86/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/cranelift-codegen/src/isa/x86/mod.rs')
-rw-r--r--third_party/rust/cranelift-codegen/src/isa/x86/mod.rs190
1 files changed, 190 insertions, 0 deletions
diff --git a/third_party/rust/cranelift-codegen/src/isa/x86/mod.rs b/third_party/rust/cranelift-codegen/src/isa/x86/mod.rs
new file mode 100644
index 0000000000..cbdeb3069d
--- /dev/null
+++ b/third_party/rust/cranelift-codegen/src/isa/x86/mod.rs
@@ -0,0 +1,190 @@
+//! x86 Instruction Set Architectures.
+
+mod abi;
+mod binemit;
+mod enc_tables;
+mod registers;
+pub mod settings;
+#[cfg(feature = "unwind")]
+pub mod unwind;
+
+use super::super::settings as shared_settings;
+#[cfg(feature = "testing_hooks")]
+use crate::binemit::CodeSink;
+use crate::binemit::{emit_function, MemoryCodeSink};
+use crate::ir;
+use crate::isa::enc_tables::{self as shared_enc_tables, lookup_enclist, Encodings};
+use crate::isa::Builder as IsaBuilder;
+#[cfg(feature = "unwind")]
+use crate::isa::{unwind::systemv::RegisterMappingError, RegUnit};
+use crate::isa::{EncInfo, RegClass, RegInfo, TargetIsa};
+use crate::regalloc;
+use crate::result::CodegenResult;
+use crate::timing;
+use alloc::borrow::Cow;
+use alloc::boxed::Box;
+use core::any::Any;
+use core::fmt;
+use target_lexicon::{PointerWidth, Triple};
+
+#[allow(dead_code)]
+struct Isa {
+ triple: Triple,
+ shared_flags: shared_settings::Flags,
+ isa_flags: settings::Flags,
+ cpumode: &'static [shared_enc_tables::Level1Entry<u16>],
+}
+
+/// Get an ISA builder for creating x86 targets.
+pub fn isa_builder(triple: Triple) -> IsaBuilder {
+ IsaBuilder {
+ triple,
+ setup: settings::builder(),
+ constructor: isa_constructor,
+ }
+}
+
+fn isa_constructor(
+ triple: Triple,
+ shared_flags: shared_settings::Flags,
+ builder: shared_settings::Builder,
+) -> Box<dyn TargetIsa> {
+ let level1 = match triple.pointer_width().unwrap() {
+ PointerWidth::U16 => unimplemented!("x86-16"),
+ PointerWidth::U32 => &enc_tables::LEVEL1_I32[..],
+ PointerWidth::U64 => &enc_tables::LEVEL1_I64[..],
+ };
+
+ let isa_flags = settings::Flags::new(&shared_flags, builder);
+
+ Box::new(Isa {
+ triple,
+ isa_flags,
+ shared_flags,
+ cpumode: level1,
+ })
+}
+
+impl TargetIsa for Isa {
+ fn name(&self) -> &'static str {
+ "x86"
+ }
+
+ fn triple(&self) -> &Triple {
+ &self.triple
+ }
+
+ fn flags(&self) -> &shared_settings::Flags {
+ &self.shared_flags
+ }
+
+ fn uses_cpu_flags(&self) -> bool {
+ true
+ }
+
+ fn uses_complex_addresses(&self) -> bool {
+ true
+ }
+
+ fn register_info(&self) -> RegInfo {
+ registers::INFO.clone()
+ }
+
+ #[cfg(feature = "unwind")]
+ fn map_dwarf_register(&self, reg: RegUnit) -> Result<u16, RegisterMappingError> {
+ unwind::systemv::map_reg(self, reg).map(|r| r.0)
+ }
+
+ fn encoding_info(&self) -> EncInfo {
+ enc_tables::INFO.clone()
+ }
+
+ fn legal_encodings<'a>(
+ &'a self,
+ func: &'a ir::Function,
+ inst: &'a ir::InstructionData,
+ ctrl_typevar: ir::Type,
+ ) -> Encodings<'a> {
+ lookup_enclist(
+ ctrl_typevar,
+ inst,
+ func,
+ self.cpumode,
+ &enc_tables::LEVEL2[..],
+ &enc_tables::ENCLISTS[..],
+ &enc_tables::LEGALIZE_ACTIONS[..],
+ &enc_tables::RECIPE_PREDICATES[..],
+ &enc_tables::INST_PREDICATES[..],
+ self.isa_flags.predicate_view(),
+ )
+ }
+
+ fn legalize_signature(&self, sig: &mut Cow<ir::Signature>, current: bool) {
+ abi::legalize_signature(
+ sig,
+ &self.triple,
+ current,
+ &self.shared_flags,
+ &self.isa_flags,
+ )
+ }
+
+ fn regclass_for_abi_type(&self, ty: ir::Type) -> RegClass {
+ abi::regclass_for_abi_type(ty)
+ }
+
+ fn allocatable_registers(&self, _func: &ir::Function) -> regalloc::RegisterSet {
+ abi::allocatable_registers(&self.triple, &self.shared_flags)
+ }
+
+ #[cfg(feature = "testing_hooks")]
+ fn emit_inst(
+ &self,
+ func: &ir::Function,
+ inst: ir::Inst,
+ divert: &mut regalloc::RegDiversions,
+ sink: &mut dyn CodeSink,
+ ) {
+ binemit::emit_inst(func, inst, divert, sink, self)
+ }
+
+ fn emit_function_to_memory(&self, func: &ir::Function, sink: &mut MemoryCodeSink) {
+ emit_function(func, binemit::emit_inst, sink, self)
+ }
+
+ fn prologue_epilogue(&self, func: &mut ir::Function) -> CodegenResult<()> {
+ let _tt = timing::prologue_epilogue();
+ abi::prologue_epilogue(func, self)
+ }
+
+ fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC {
+ ir::condcodes::IntCC::UnsignedLessThan
+ }
+
+ fn unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC {
+ ir::condcodes::IntCC::UnsignedLessThan
+ }
+
+ #[cfg(feature = "unwind")]
+ fn create_unwind_info(
+ &self,
+ func: &ir::Function,
+ ) -> CodegenResult<Option<super::unwind::UnwindInfo>> {
+ abi::create_unwind_info(func, self)
+ }
+
+ #[cfg(feature = "unwind")]
+ fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry> {
+ Some(unwind::systemv::create_cie())
+ }
+
+ fn as_any(&self) -> &dyn Any {
+ self as &dyn Any
+ }
+}
+
+impl fmt::Display for Isa {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}\n{}", self.shared_flags, self.isa_flags)
+ }
+}