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