1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//! Adapter for a `MachBackend` to implement the `TargetIsa` trait.

use crate::binemit;
use crate::ir;
use crate::isa::{EncInfo, Encoding, Encodings, Legalize, RegClass, RegInfo, TargetIsa};
use crate::machinst::*;
use crate::regalloc::RegisterSet;
use crate::settings::Flags;

#[cfg(feature = "testing_hooks")]
use crate::regalloc::RegDiversions;

use core::any::Any;
use std::borrow::Cow;
use std::fmt;
use target_lexicon::Triple;

/// A wrapper around a `MachBackend` that provides a `TargetIsa` impl.
pub struct TargetIsaAdapter {
    backend: Box<dyn MachBackend + Send + Sync + 'static>,
    triple: Triple,
}

impl TargetIsaAdapter {
    /// Create a new `TargetIsa` wrapper around a `MachBackend`.
    pub fn new<B: MachBackend + Send + Sync + 'static>(backend: B) -> TargetIsaAdapter {
        let triple = backend.triple();
        TargetIsaAdapter {
            backend: Box::new(backend),
            triple,
        }
    }
}

impl fmt::Display for TargetIsaAdapter {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("MachBackend")
            .field("name", &self.backend.name())
            .field("triple", &self.backend.triple())
            .field("flags", &format!("{}", self.backend.flags()))
            .finish()
    }
}

impl TargetIsa for TargetIsaAdapter {
    fn name(&self) -> &'static str {
        self.backend.name()
    }

    fn triple(&self) -> &Triple {
        &self.triple
    }

    fn flags(&self) -> &Flags {
        self.backend.flags()
    }

    fn register_info(&self) -> RegInfo {
        // Called from function's Display impl, so we need a stub here.
        RegInfo {
            banks: &[],
            classes: &[],
        }
    }

    fn legal_encodings<'a>(
        &'a self,
        _func: &'a ir::Function,
        _inst: &'a ir::InstructionData,
        _ctrl_typevar: ir::Type,
    ) -> Encodings<'a> {
        panic!("Should not be called when new-style backend is available!")
    }

    fn encode(
        &self,
        _func: &ir::Function,
        _inst: &ir::InstructionData,
        _ctrl_typevar: ir::Type,
    ) -> Result<Encoding, Legalize> {
        panic!("Should not be called when new-style backend is available!")
    }

    fn encoding_info(&self) -> EncInfo {
        panic!("Should not be called when new-style backend is available!")
    }

    fn legalize_signature(&self, _sig: &mut Cow<ir::Signature>, _current: bool) {
        panic!("Should not be called when new-style backend is available!")
    }

    fn regclass_for_abi_type(&self, _ty: ir::Type) -> RegClass {
        panic!("Should not be called when new-style backend is available!")
    }

    fn allocatable_registers(&self, _func: &ir::Function) -> RegisterSet {
        panic!("Should not be called when new-style backend is available!")
    }

    fn prologue_epilogue(&self, _func: &mut ir::Function) -> CodegenResult<()> {
        panic!("Should not be called when new-style backend is available!")
    }

    #[cfg(feature = "testing_hooks")]
    fn emit_inst(
        &self,
        _func: &ir::Function,
        _inst: ir::Inst,
        _divert: &mut RegDiversions,
        _sink: &mut dyn binemit::CodeSink,
    ) {
        panic!("Should not be called when new-style backend is available!")
    }

    /// Emit a whole function into memory.
    fn emit_function_to_memory(&self, _func: &ir::Function, _sink: &mut binemit::MemoryCodeSink) {
        panic!("Should not be called when new-style backend is available!")
    }

    fn get_mach_backend(&self) -> Option<&dyn MachBackend> {
        Some(&*self.backend)
    }

    fn unsigned_add_overflow_condition(&self) -> ir::condcodes::IntCC {
        self.backend.unsigned_add_overflow_condition()
    }

    fn unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC {
        self.backend.unsigned_sub_overflow_condition()
    }

    #[cfg(feature = "unwind")]
    fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry> {
        self.backend.create_systemv_cie()
    }

    fn as_any(&self) -> &dyn Any {
        self as &dyn Any
    }
}