1pub mod attributes;
4pub mod identification;
5pub mod module;
6pub mod strtab;
7pub mod symtab;
8pub mod type_table;
9
10use std::convert::TryFrom;
11
12use llvm_support::bitcodes::{IrBlockId, ReservedBlockId};
13use thiserror::Error;
14
15pub use self::attributes::*;
16pub use self::identification::*;
17pub use self::module::*;
18pub use self::strtab::*;
19pub use self::symtab::*;
20pub use self::type_table::*;
21use crate::map::{MapError, PartialCtxMappable, PartialMapCtx};
22use crate::unroll::UnrolledBlock;
23
24#[non_exhaustive]
26#[derive(Debug, Error)]
27pub enum BlockMapError {
28 #[error("error while mapping identification block")]
30 Identification(#[from] IdentificationError),
31
32 #[error("error while mapping module")]
34 Module(#[from] ModuleError),
35
36 #[error("error while mapping string table")]
38 Strtab(#[from] StrtabError),
39
40 #[error("error while mapping symbol table")]
42 Symtab(#[from] SymtabError),
43}
44
45#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
47pub enum BlockId {
48 Reserved(ReservedBlockId),
50 Ir(IrBlockId),
52 Unknown(u64),
54}
55
56impl From<u64> for BlockId {
57 fn from(value: u64) -> Self {
58 ReservedBlockId::try_from(value).map_or_else(
61 |_| IrBlockId::try_from(value).map_or_else(|_| BlockId::Unknown(value), BlockId::Ir),
62 BlockId::Reserved,
63 )
64 }
65}
66
67pub(crate) trait IrBlock: Sized {
70 type Error;
71
72 const BLOCK_ID: IrBlockId;
74
75 fn try_map_inner(block: &UnrolledBlock, ctx: &mut PartialMapCtx) -> Result<Self, Self::Error>;
79}
80
81impl<T: IrBlock> PartialCtxMappable<UnrolledBlock> for T
82where
83 T::Error: From<MapError>,
84{
85 type Error = T::Error;
86
87 fn try_map(block: &UnrolledBlock, ctx: &mut PartialMapCtx) -> Result<Self, Self::Error> {
88 if block.id != BlockId::Ir(T::BLOCK_ID) {
89 return Err(MapError::BadBlockMap(format!(
90 "can't map {:?} into {:?}",
91 block.id,
92 Identification::BLOCK_ID
93 ))
94 .into());
95 }
96
97 IrBlock::try_map_inner(block, ctx)
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104
105 #[test]
106 fn test_blockid_from_u64() {
107 assert_eq!(
108 BlockId::from(0),
109 BlockId::Reserved(ReservedBlockId::BlockInfo)
110 );
111 assert_eq!(
112 BlockId::from(7),
113 BlockId::Reserved(ReservedBlockId::Reserved7)
114 );
115 assert_eq!(BlockId::from(8), BlockId::Ir(IrBlockId::Module));
116 assert_eq!(BlockId::from(2384629342), BlockId::Unknown(2384629342));
117 }
118}