1 //! x86 Instruction Set Architectures.
2 
3 mod abi;
4 mod binemit;
5 mod enc_tables;
6 mod registers;
7 pub mod settings;
8 #[cfg(feature = "unwind")]
9 pub mod unwind;
10 
11 use super::super::settings as shared_settings;
12 #[cfg(feature = "testing_hooks")]
13 use crate::binemit::CodeSink;
14 use crate::binemit::{emit_function, MemoryCodeSink};
15 use crate::ir;
16 use crate::isa::enc_tables::{self as shared_enc_tables, lookup_enclist, Encodings};
17 use crate::isa::Builder as IsaBuilder;
18 #[cfg(feature = "unwind")]
19 use crate::isa::{unwind::systemv::RegisterMappingError, RegUnit};
20 use crate::isa::{EncInfo, RegClass, RegInfo, TargetIsa};
21 use crate::regalloc;
22 use crate::result::CodegenResult;
23 use crate::timing;
24 use alloc::borrow::Cow;
25 use alloc::boxed::Box;
26 use core::fmt;
27 use target_lexicon::{PointerWidth, Triple};
28 
29 #[allow(dead_code)]
30 struct Isa {
31     triple: Triple,
32     shared_flags: shared_settings::Flags,
33     isa_flags: settings::Flags,
34     cpumode: &'static [shared_enc_tables::Level1Entry<u16>],
35 }
36 
37 /// Get an ISA builder for creating x86 targets.
isa_builder(triple: Triple) -> IsaBuilder38 pub fn isa_builder(triple: Triple) -> IsaBuilder {
39     IsaBuilder {
40         triple,
41         setup: settings::builder(),
42         constructor: isa_constructor,
43     }
44 }
45 
isa_constructor( triple: Triple, shared_flags: shared_settings::Flags, builder: shared_settings::Builder, ) -> Box<dyn TargetIsa>46 fn isa_constructor(
47     triple: Triple,
48     shared_flags: shared_settings::Flags,
49     builder: shared_settings::Builder,
50 ) -> Box<dyn TargetIsa> {
51     let level1 = match triple.pointer_width().unwrap() {
52         PointerWidth::U16 => unimplemented!("x86-16"),
53         PointerWidth::U32 => &enc_tables::LEVEL1_I32[..],
54         PointerWidth::U64 => &enc_tables::LEVEL1_I64[..],
55     };
56     Box::new(Isa {
57         triple,
58         isa_flags: settings::Flags::new(&shared_flags, builder),
59         shared_flags,
60         cpumode: level1,
61     })
62 }
63 
64 impl TargetIsa for Isa {
name(&self) -> &'static str65     fn name(&self) -> &'static str {
66         "x86"
67     }
68 
triple(&self) -> &Triple69     fn triple(&self) -> &Triple {
70         &self.triple
71     }
72 
flags(&self) -> &shared_settings::Flags73     fn flags(&self) -> &shared_settings::Flags {
74         &self.shared_flags
75     }
76 
uses_cpu_flags(&self) -> bool77     fn uses_cpu_flags(&self) -> bool {
78         true
79     }
80 
uses_complex_addresses(&self) -> bool81     fn uses_complex_addresses(&self) -> bool {
82         true
83     }
84 
register_info(&self) -> RegInfo85     fn register_info(&self) -> RegInfo {
86         registers::INFO.clone()
87     }
88 
89     #[cfg(feature = "unwind")]
map_dwarf_register(&self, reg: RegUnit) -> Result<u16, RegisterMappingError>90     fn map_dwarf_register(&self, reg: RegUnit) -> Result<u16, RegisterMappingError> {
91         unwind::systemv::map_reg(self, reg).map(|r| r.0)
92     }
93 
encoding_info(&self) -> EncInfo94     fn encoding_info(&self) -> EncInfo {
95         enc_tables::INFO.clone()
96     }
97 
legal_encodings<'a>( &'a self, func: &'a ir::Function, inst: &'a ir::InstructionData, ctrl_typevar: ir::Type, ) -> Encodings<'a>98     fn legal_encodings<'a>(
99         &'a self,
100         func: &'a ir::Function,
101         inst: &'a ir::InstructionData,
102         ctrl_typevar: ir::Type,
103     ) -> Encodings<'a> {
104         lookup_enclist(
105             ctrl_typevar,
106             inst,
107             func,
108             self.cpumode,
109             &enc_tables::LEVEL2[..],
110             &enc_tables::ENCLISTS[..],
111             &enc_tables::LEGALIZE_ACTIONS[..],
112             &enc_tables::RECIPE_PREDICATES[..],
113             &enc_tables::INST_PREDICATES[..],
114             self.isa_flags.predicate_view(),
115         )
116     }
117 
legalize_signature(&self, sig: &mut Cow<ir::Signature>, current: bool)118     fn legalize_signature(&self, sig: &mut Cow<ir::Signature>, current: bool) {
119         abi::legalize_signature(
120             sig,
121             &self.triple,
122             current,
123             &self.shared_flags,
124             &self.isa_flags,
125         )
126     }
127 
regclass_for_abi_type(&self, ty: ir::Type) -> RegClass128     fn regclass_for_abi_type(&self, ty: ir::Type) -> RegClass {
129         abi::regclass_for_abi_type(ty)
130     }
131 
allocatable_registers(&self, _func: &ir::Function) -> regalloc::RegisterSet132     fn allocatable_registers(&self, _func: &ir::Function) -> regalloc::RegisterSet {
133         abi::allocatable_registers(&self.triple, &self.shared_flags)
134     }
135 
136     #[cfg(feature = "testing_hooks")]
emit_inst( &self, func: &ir::Function, inst: ir::Inst, divert: &mut regalloc::RegDiversions, sink: &mut dyn CodeSink, )137     fn emit_inst(
138         &self,
139         func: &ir::Function,
140         inst: ir::Inst,
141         divert: &mut regalloc::RegDiversions,
142         sink: &mut dyn CodeSink,
143     ) {
144         binemit::emit_inst(func, inst, divert, sink, self)
145     }
146 
emit_function_to_memory(&self, func: &ir::Function, sink: &mut MemoryCodeSink)147     fn emit_function_to_memory(&self, func: &ir::Function, sink: &mut MemoryCodeSink) {
148         emit_function(func, binemit::emit_inst, sink, self)
149     }
150 
prologue_epilogue(&self, func: &mut ir::Function) -> CodegenResult<()>151     fn prologue_epilogue(&self, func: &mut ir::Function) -> CodegenResult<()> {
152         let _tt = timing::prologue_epilogue();
153         abi::prologue_epilogue(func, self)
154     }
155 
unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC156     fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC {
157         ir::condcodes::IntCC::UnsignedLessThan
158     }
159 
unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC160     fn unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC {
161         ir::condcodes::IntCC::UnsignedLessThan
162     }
163 
164     #[cfg(feature = "unwind")]
create_unwind_info( &self, func: &ir::Function, ) -> CodegenResult<Option<super::unwind::UnwindInfo>>165     fn create_unwind_info(
166         &self,
167         func: &ir::Function,
168     ) -> CodegenResult<Option<super::unwind::UnwindInfo>> {
169         abi::create_unwind_info(func, self)
170     }
171 
172     #[cfg(feature = "unwind")]
create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry>173     fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry> {
174         Some(unwind::systemv::create_cie())
175     }
176 }
177 
178 impl fmt::Display for Isa {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result179     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
180         write!(f, "{}\n{}", self.shared_flags, self.isa_flags)
181     }
182 }
183