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, boxed::Box, vec::Vec};
25 use core::any::Any;
26 use core::fmt;
27 use core::hash::{Hash, Hasher};
28 use target_lexicon::{PointerWidth, Triple};
29 
30 #[allow(dead_code)]
31 struct Isa {
32     triple: Triple,
33     shared_flags: shared_settings::Flags,
34     isa_flags: settings::Flags,
35     cpumode: &'static [shared_enc_tables::Level1Entry<u16>],
36 }
37 
38 /// Get an ISA builder for creating x86 targets.
isa_builder(triple: Triple) -> IsaBuilder39 pub fn isa_builder(triple: Triple) -> IsaBuilder {
40     IsaBuilder {
41         triple,
42         setup: settings::builder(),
43         constructor: isa_constructor,
44     }
45 }
46 
isa_constructor( triple: Triple, shared_flags: shared_settings::Flags, builder: shared_settings::Builder, ) -> Box<dyn TargetIsa>47 fn isa_constructor(
48     triple: Triple,
49     shared_flags: shared_settings::Flags,
50     builder: shared_settings::Builder,
51 ) -> Box<dyn TargetIsa> {
52     let level1 = match triple.pointer_width().unwrap() {
53         PointerWidth::U16 => unimplemented!("x86-16"),
54         PointerWidth::U32 => &enc_tables::LEVEL1_I32[..],
55         PointerWidth::U64 => &enc_tables::LEVEL1_I64[..],
56     };
57 
58     let isa_flags = settings::Flags::new(&shared_flags, builder);
59 
60     Box::new(Isa {
61         triple,
62         isa_flags,
63         shared_flags,
64         cpumode: level1,
65     })
66 }
67 
68 impl TargetIsa for Isa {
name(&self) -> &'static str69     fn name(&self) -> &'static str {
70         "x86"
71     }
72 
triple(&self) -> &Triple73     fn triple(&self) -> &Triple {
74         &self.triple
75     }
76 
flags(&self) -> &shared_settings::Flags77     fn flags(&self) -> &shared_settings::Flags {
78         &self.shared_flags
79     }
80 
isa_flags(&self) -> Vec<shared_settings::Value>81     fn isa_flags(&self) -> Vec<shared_settings::Value> {
82         self.isa_flags.iter().collect()
83     }
84 
hash_all_flags(&self, mut hasher: &mut dyn Hasher)85     fn hash_all_flags(&self, mut hasher: &mut dyn Hasher) {
86         self.shared_flags.hash(&mut hasher);
87         self.isa_flags.hash(&mut hasher);
88     }
89 
uses_cpu_flags(&self) -> bool90     fn uses_cpu_flags(&self) -> bool {
91         true
92     }
93 
uses_complex_addresses(&self) -> bool94     fn uses_complex_addresses(&self) -> bool {
95         true
96     }
97 
register_info(&self) -> RegInfo98     fn register_info(&self) -> RegInfo {
99         registers::INFO.clone()
100     }
101 
102     #[cfg(feature = "unwind")]
map_dwarf_register(&self, reg: RegUnit) -> Result<u16, RegisterMappingError>103     fn map_dwarf_register(&self, reg: RegUnit) -> Result<u16, RegisterMappingError> {
104         unwind::systemv::map_reg(self, reg).map(|r| r.0)
105     }
106 
encoding_info(&self) -> EncInfo107     fn encoding_info(&self) -> EncInfo {
108         enc_tables::INFO.clone()
109     }
110 
legal_encodings<'a>( &'a self, func: &'a ir::Function, inst: &'a ir::InstructionData, ctrl_typevar: ir::Type, ) -> Encodings<'a>111     fn legal_encodings<'a>(
112         &'a self,
113         func: &'a ir::Function,
114         inst: &'a ir::InstructionData,
115         ctrl_typevar: ir::Type,
116     ) -> Encodings<'a> {
117         lookup_enclist(
118             ctrl_typevar,
119             inst,
120             func,
121             self.cpumode,
122             &enc_tables::LEVEL2[..],
123             &enc_tables::ENCLISTS[..],
124             &enc_tables::LEGALIZE_ACTIONS[..],
125             &enc_tables::RECIPE_PREDICATES[..],
126             &enc_tables::INST_PREDICATES[..],
127             self.isa_flags.predicate_view(),
128         )
129     }
130 
legalize_signature(&self, sig: &mut Cow<ir::Signature>, current: bool)131     fn legalize_signature(&self, sig: &mut Cow<ir::Signature>, current: bool) {
132         abi::legalize_signature(
133             sig,
134             &self.triple,
135             current,
136             &self.shared_flags,
137             &self.isa_flags,
138         )
139     }
140 
regclass_for_abi_type(&self, ty: ir::Type) -> RegClass141     fn regclass_for_abi_type(&self, ty: ir::Type) -> RegClass {
142         abi::regclass_for_abi_type(ty)
143     }
144 
allocatable_registers(&self, _func: &ir::Function) -> regalloc::RegisterSet145     fn allocatable_registers(&self, _func: &ir::Function) -> regalloc::RegisterSet {
146         abi::allocatable_registers(&self.triple, &self.shared_flags)
147     }
148 
149     #[cfg(feature = "testing_hooks")]
emit_inst( &self, func: &ir::Function, inst: ir::Inst, divert: &mut regalloc::RegDiversions, sink: &mut dyn CodeSink, )150     fn emit_inst(
151         &self,
152         func: &ir::Function,
153         inst: ir::Inst,
154         divert: &mut regalloc::RegDiversions,
155         sink: &mut dyn CodeSink,
156     ) {
157         binemit::emit_inst(func, inst, divert, sink, self)
158     }
159 
emit_function_to_memory(&self, func: &ir::Function, sink: &mut MemoryCodeSink)160     fn emit_function_to_memory(&self, func: &ir::Function, sink: &mut MemoryCodeSink) {
161         emit_function(func, binemit::emit_inst, sink, self)
162     }
163 
prologue_epilogue(&self, func: &mut ir::Function) -> CodegenResult<()>164     fn prologue_epilogue(&self, func: &mut ir::Function) -> CodegenResult<()> {
165         let _tt = timing::prologue_epilogue();
166         abi::prologue_epilogue(func, self)
167     }
168 
unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC169     fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC {
170         ir::condcodes::IntCC::UnsignedLessThan
171     }
172 
unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC173     fn unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC {
174         ir::condcodes::IntCC::UnsignedLessThan
175     }
176 
177     #[cfg(feature = "unwind")]
create_unwind_info( &self, func: &ir::Function, ) -> CodegenResult<Option<super::unwind::UnwindInfo>>178     fn create_unwind_info(
179         &self,
180         func: &ir::Function,
181     ) -> CodegenResult<Option<super::unwind::UnwindInfo>> {
182         abi::create_unwind_info(func, self)
183     }
184 
185     #[cfg(feature = "unwind")]
create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry>186     fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry> {
187         Some(unwind::systemv::create_cie())
188     }
189 
as_any(&self) -> &dyn Any190     fn as_any(&self) -> &dyn Any {
191         self as &dyn Any
192     }
193 }
194 
195 impl fmt::Display for Isa {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result196     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197         write!(f, "{}\n{}", self.shared_flags, self.isa_flags)
198     }
199 }
200