* Manually rename BasicBlock to BlockPredecessor BasicBlock is a pair of (Ebb, Inst) that is used to represent the basic block subcomponent of an Ebb that is a predecessor to an Ebb. Eventually we will be able to remove this struct, but for now it makes sense to give it a non-conflicting name so that we can start to transition Ebb to represent a basic block. I have not updated any comments that refer to BasicBlock, as eventually we will remove BlockPredecessor and replace with Block, which is a basic block, so the comments will become correct. * Manually rename SSABuilder block types to avoid conflict SSABuilder has its own Block and BlockData types. These along with associated identifier will cause conflicts in a later commit, so they are renamed to be more verbose here. * Automatically rename 'Ebb' to 'Block' in *.rs * Automatically rename 'EBB' to 'block' in *.rs * Automatically rename 'ebb' to 'block' in *.rs * Automatically rename 'extended basic block' to 'basic block' in *.rs * Automatically rename 'an basic block' to 'a basic block' in *.rs * Manually update comment for `Block` `Block`'s wikipedia article required an update. * Automatically rename 'an `Block`' to 'a `Block`' in *.rs * Automatically rename 'extended_basic_block' to 'basic_block' in *.rs * Automatically rename 'ebb' to 'block' in *.clif * Manually rename clif constant that contains 'ebb' as substring to avoid conflict * Automatically rename filecheck uses of 'EBB' to 'BB' 'regex: EBB' -> 'regex: BB' '$EBB' -> '$BB' * Automatically rename 'EBB' 'Ebb' to 'block' in *.clif * Automatically rename 'an block' to 'a block' in *.clif * Fix broken testcase when function name length increases Test function names are limited to 16 characters. This causes the new longer name to be truncated and fail a filecheck test. An outdated comment was also fixed.
164 lines
4.9 KiB
Rust
164 lines
4.9 KiB
Rust
//! External names.
|
|
//!
|
|
//! These are identifiers for declaring entities defined outside the current
|
|
//! function. The name of an external declaration doesn't have any meaning to
|
|
//! Cranelift, which compiles functions independently.
|
|
|
|
use crate::ir::LibCall;
|
|
use core::cmp;
|
|
use core::fmt::{self, Write};
|
|
use core::str::FromStr;
|
|
|
|
const TESTCASE_NAME_LENGTH: usize = 16;
|
|
|
|
/// The name of an external is either a reference to a user-defined symbol
|
|
/// table, or a short sequence of ascii bytes so that test cases do not have
|
|
/// to keep track of a symbol table.
|
|
///
|
|
/// External names are primarily used as keys by code using Cranelift to map
|
|
/// from a `cranelift_codegen::ir::FuncRef` or similar to additional associated
|
|
/// data.
|
|
///
|
|
/// External names can also serve as a primitive testing and debugging tool.
|
|
/// In particular, many `.clif` test files use function names to identify
|
|
/// functions.
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub enum ExternalName {
|
|
/// A name in a user-defined symbol table. Cranelift does not interpret
|
|
/// these numbers in any way.
|
|
User {
|
|
/// Arbitrary.
|
|
namespace: u32,
|
|
/// Arbitrary.
|
|
index: u32,
|
|
},
|
|
/// A test case function name of up to a hardcoded amount of ascii
|
|
/// characters. This is not intended to be used outside test cases.
|
|
TestCase {
|
|
/// How many of the bytes in `ascii` are valid?
|
|
length: u8,
|
|
/// Ascii bytes of the name.
|
|
ascii: [u8; TESTCASE_NAME_LENGTH],
|
|
},
|
|
/// A well-known runtime library function.
|
|
LibCall(LibCall),
|
|
}
|
|
|
|
impl ExternalName {
|
|
/// Creates a new external name from a sequence of bytes. Caller is expected
|
|
/// to guarantee bytes are only ascii alphanumeric or `_`.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```rust
|
|
/// # use cranelift_codegen::ir::ExternalName;
|
|
/// // Create `ExternalName` from a string.
|
|
/// let name = ExternalName::testcase("hello");
|
|
/// assert_eq!(name.to_string(), "%hello");
|
|
/// ```
|
|
pub fn testcase<T: AsRef<[u8]>>(v: T) -> Self {
|
|
let vec = v.as_ref();
|
|
let len = cmp::min(vec.len(), TESTCASE_NAME_LENGTH);
|
|
let mut bytes = [0u8; TESTCASE_NAME_LENGTH];
|
|
bytes[0..len].copy_from_slice(&vec[0..len]);
|
|
|
|
Self::TestCase {
|
|
length: len as u8,
|
|
ascii: bytes,
|
|
}
|
|
}
|
|
|
|
/// Create a new external name from user-provided integer indices.
|
|
///
|
|
/// # Examples
|
|
/// ```rust
|
|
/// # use cranelift_codegen::ir::ExternalName;
|
|
/// // Create `ExternalName` from integer indices
|
|
/// let name = ExternalName::user(123, 456);
|
|
/// assert_eq!(name.to_string(), "u123:456");
|
|
/// ```
|
|
pub fn user(namespace: u32, index: u32) -> Self {
|
|
Self::User { namespace, index }
|
|
}
|
|
}
|
|
|
|
impl Default for ExternalName {
|
|
fn default() -> Self {
|
|
Self::user(0, 0)
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for ExternalName {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
match *self {
|
|
Self::User { namespace, index } => write!(f, "u{}:{}", namespace, index),
|
|
Self::TestCase { length, ascii } => {
|
|
f.write_char('%')?;
|
|
for byte in ascii.iter().take(length as usize) {
|
|
f.write_char(*byte as char)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
Self::LibCall(lc) => write!(f, "%{}", lc),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl FromStr for ExternalName {
|
|
type Err = ();
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
// Try to parse as a libcall name, otherwise it's a test case.
|
|
match s.parse() {
|
|
Ok(lc) => Ok(Self::LibCall(lc)),
|
|
Err(_) => Ok(Self::testcase(s.as_bytes())),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::ExternalName;
|
|
use crate::ir::LibCall;
|
|
use alloc::string::ToString;
|
|
use core::u32;
|
|
|
|
#[test]
|
|
fn display_testcase() {
|
|
assert_eq!(ExternalName::testcase("").to_string(), "%");
|
|
assert_eq!(ExternalName::testcase("x").to_string(), "%x");
|
|
assert_eq!(ExternalName::testcase("x_1").to_string(), "%x_1");
|
|
assert_eq!(
|
|
ExternalName::testcase("longname12345678").to_string(),
|
|
"%longname12345678"
|
|
);
|
|
// Constructor will silently drop bytes beyond the 16th
|
|
assert_eq!(
|
|
ExternalName::testcase("longname123456789").to_string(),
|
|
"%longname12345678"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn display_user() {
|
|
assert_eq!(ExternalName::user(0, 0).to_string(), "u0:0");
|
|
assert_eq!(ExternalName::user(1, 1).to_string(), "u1:1");
|
|
assert_eq!(
|
|
ExternalName::user(u32::MAX, u32::MAX).to_string(),
|
|
"u4294967295:4294967295"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parsing() {
|
|
assert_eq!(
|
|
"FloorF32".parse(),
|
|
Ok(ExternalName::LibCall(LibCall::FloorF32))
|
|
);
|
|
assert_eq!(
|
|
ExternalName::LibCall(LibCall::FloorF32).to_string(),
|
|
"%FloorF32"
|
|
);
|
|
}
|
|
}
|