llvm_mapper/block/
module.rs1use llvm_support::bitcodes::{IrBlockId, ModuleCode};
4use llvm_support::TARGET_TRIPLE;
5use thiserror::Error;
6
7use crate::block::attributes::{AttributeError, AttributeGroups, Attributes};
8use crate::block::type_table::{TypeTable, TypeTableError};
9use crate::block::{BlockId, IrBlock};
10use crate::map::{CtxMappable, MapError, PartialCtxMappable, PartialMapCtx};
11use crate::record::{
12 Alias, AliasError, Comdat, ComdatError, DataLayout, DataLayoutError,
13 Function as FunctionRecord, FunctionError as FunctionRecordError,
14};
15use crate::unroll::UnrolledBlock;
16
17#[derive(Debug, Error)]
19pub enum ModuleError {
20 #[error("bitcode module has no version")]
22 MissingVersion,
23
24 #[error("invalid datalayout record")]
26 DataLayoutRecord(#[from] DataLayoutError),
27
28 #[error("invalid type table block")]
30 TypeTableBlock(#[from] TypeTableError),
31
32 #[error("invalid attribute block")]
34 AttributeBlock(#[from] AttributeError),
35
36 #[error("invalid COMDAT record")]
38 ComdatRecord(#[from] ComdatError),
39
40 #[error("invalid function record")]
42 FunctionRecord(#[from] FunctionRecordError),
43
44 #[error("invalid alias record")]
46 Alias(#[from] AliasError),
47
48 #[error("generic mapping error")]
50 Map(#[from] MapError),
51}
52
53#[non_exhaustive]
55#[derive(Debug)]
56pub struct Module {
57 pub triple: String,
59 pub asm: Vec<String>,
61 pub deplibs: Vec<String>,
63}
64
65impl IrBlock for Module {
66 type Error = ModuleError;
67
68 const BLOCK_ID: IrBlockId = IrBlockId::Module;
69
70 fn try_map_inner(block: &UnrolledBlock, ctx: &mut PartialMapCtx) -> Result<Self, Self::Error> {
71 ctx.version = Some({
74 let version = block
75 .records()
76 .exactly_one(ModuleCode::Version)
77 .map_err(MapError::Inconsistent)?;
78
79 *version.fields().get(0).ok_or(ModuleError::MissingVersion)?
80 });
81
82 if let Some(record) = block
84 .records()
85 .one_or_none(ModuleCode::DataLayout)
86 .map_err(MapError::Inconsistent)?
87 {
88 ctx.datalayout = DataLayout::try_map(record, ctx)?;
89 }
90
91 ctx.section_table = block
93 .records()
94 .by_code(ModuleCode::SectionName)
95 .map(|rec| rec.try_string(0))
96 .collect::<Result<Vec<_>, _>>()
97 .map_err(MapError::RecordString)?;
98
99 ctx.gc_table = block
101 .records()
102 .by_code(ModuleCode::GcName)
103 .map(|rec| rec.try_string(0))
104 .collect::<Result<Vec<_>, _>>()
105 .map_err(MapError::RecordString)?;
106
107 ctx.type_table = Some(TypeTable::try_map(
109 block
110 .blocks()
111 .exactly_one(BlockId::Ir(IrBlockId::Type))
112 .map_err(MapError::Inconsistent)?,
113 ctx,
114 )?);
115
116 if let Some(attribute_groups) = block
121 .blocks()
122 .one_or_none(BlockId::Ir(IrBlockId::ParamAttrGroup))
123 .map_err(MapError::Inconsistent)?
124 .map(|b| AttributeGroups::try_map(b, ctx))
125 .transpose()?
126 {
127 ctx.attribute_groups = attribute_groups;
128 }
129
130 if let Some(attributes) = block
131 .blocks()
132 .one_or_none(BlockId::Ir(IrBlockId::ParamAttr))
133 .map_err(MapError::Inconsistent)?
134 .map(|b| Attributes::try_map(b, ctx))
135 .transpose()?
136 {
137 ctx.attributes = attributes;
138 }
139
140 ctx.comdats = block
142 .records()
143 .by_code(ModuleCode::Comdat)
144 .map(|rec| Comdat::try_map(rec, ctx))
145 .collect::<Result<Vec<_>, _>>()?;
146
147 let ctx = ctx.reify().map_err(MapError::Context)?;
149
150 let triple = match block
152 .records()
153 .one_or_none(ModuleCode::Triple)
154 .map_err(MapError::Inconsistent)?
155 {
156 Some(record) => record.try_string(0).map_err(MapError::RecordString)?,
157 None => TARGET_TRIPLE.into(),
158 };
159
160 let asm = match block
162 .records()
163 .one_or_none(ModuleCode::Asm)
164 .map_err(MapError::Inconsistent)?
165 {
166 None => Vec::new(),
167 Some(record) => record
168 .try_string(0)
169 .map_err(MapError::RecordString)?
170 .split('\n')
171 .map(String::from)
172 .collect::<Vec<_>>(),
173 };
174
175 let deplibs = block
177 .records()
178 .by_code(ModuleCode::DepLib)
179 .map(|rec| rec.try_string(0))
180 .collect::<Result<Vec<_>, _>>()
181 .map_err(MapError::RecordString)?;
182
183 let functions = block
185 .records()
186 .by_code(ModuleCode::Function)
187 .map(|rec| FunctionRecord::try_map(rec, &ctx))
188 .collect::<Result<Vec<_>, _>>()?;
189
190 log::debug!("functions: {:?}", functions);
192
193 let aliases = block
194 .records()
195 .by_code(ModuleCode::Alias)
196 .map(|rec| Alias::try_map(rec, &ctx))
197 .collect::<Result<Vec<_>, _>>()?;
198
199 log::debug!("aliases: {:?}", aliases);
200
201 Ok(Self {
202 triple,
203 asm,
204 deplibs,
205 })
206 }
207}