pub mod attributes;
pub mod identification;
pub mod module;
pub mod strtab;
pub mod symtab;
pub mod type_table;
use std::convert::TryFrom;
use llvm_support::bitcodes::{IrBlockId, ReservedBlockId};
use thiserror::Error;
pub use self::attributes::*;
pub use self::identification::*;
pub use self::module::*;
pub use self::strtab::*;
pub use self::symtab::*;
pub use self::type_table::*;
use crate::map::{MapError, PartialCtxMappable, PartialMapCtx};
use crate::unroll::UnrolledBlock;
#[non_exhaustive]
#[derive(Debug, Error)]
pub enum BlockMapError {
#[error("error while mapping identification block")]
Identification(#[from] IdentificationError),
#[error("error while mapping module")]
Module(#[from] ModuleError),
#[error("error while mapping string table")]
Strtab(#[from] StrtabError),
#[error("error while mapping symbol table")]
Symtab(#[from] SymtabError),
}
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum BlockId {
Reserved(ReservedBlockId),
Ir(IrBlockId),
Unknown(u64),
}
impl From<u64> for BlockId {
fn from(value: u64) -> Self {
ReservedBlockId::try_from(value).map_or_else(
|_| IrBlockId::try_from(value).map_or_else(|_| BlockId::Unknown(value), BlockId::Ir),
BlockId::Reserved,
)
}
}
pub(crate) trait IrBlock: Sized {
type Error;
const BLOCK_ID: IrBlockId;
fn try_map_inner(block: &UnrolledBlock, ctx: &mut PartialMapCtx) -> Result<Self, Self::Error>;
}
impl<T: IrBlock> PartialCtxMappable<UnrolledBlock> for T
where
T::Error: From<MapError>,
{
type Error = T::Error;
fn try_map(block: &UnrolledBlock, ctx: &mut PartialMapCtx) -> Result<Self, Self::Error> {
if block.id != BlockId::Ir(T::BLOCK_ID) {
return Err(MapError::BadBlockMap(format!(
"can't map {:?} into {:?}",
block.id,
Identification::BLOCK_ID
))
.into());
}
IrBlock::try_map_inner(block, ctx)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_blockid_from_u64() {
assert_eq!(
BlockId::from(0),
BlockId::Reserved(ReservedBlockId::BlockInfo)
);
assert_eq!(
BlockId::from(7),
BlockId::Reserved(ReservedBlockId::Reserved7)
);
assert_eq!(BlockId::from(8), BlockId::Ir(IrBlockId::Module));
assert_eq!(BlockId::from(2384629342), BlockId::Unknown(2384629342));
}
}