1#[derive(Debug)]
7pub enum IrError {
8 FunctionLocalClobbered(String, String),
9 InvalidMetadatum(String),
10 InvalidPhi,
11 MisplacedTerminator(String),
12 MissingBlock(String),
13 MissingTerminator(String),
14 ParseFailure(String, String),
15 RemoveMissingBlock(String),
16 ValueNotFound(String),
17 InconsistentParent(String, String, String),
18
19 VerifyArgumentValueIsNotArgument(String),
20 VerifyUnaryOpIncorrectArgType,
21 VerifyBinaryOpIncorrectArgType,
22 VerifyBitcastBetweenInvalidTypes(String, String),
23 VerifyBitcastUnknownSourceType,
24 VerifyEntryBlockHasPredecessors(String, Vec<String>),
25 VerifyBlockArgMalformed,
26 VerifyBranchParamsMismatch,
27 VerifyBranchToMissingBlock(String),
28 VerifyCallArgTypeMismatch(String, String, String),
29 VerifyCallToMissingFunction(String),
30 VerifyCmpBadTypes(String, String),
31 VerifyCmpTypeMismatch(String, String),
32 VerifyCmpUnknownTypes,
33 VerifyConditionExprNotABool,
34 VerifyContractCallBadTypes(String),
35 VerifyGepElementTypeNonPointer,
36 VerifyGepFromNonPointer(String, Option<Value>),
37 VerifyGepInconsistentTypes(String, Option<crate::Value>),
38 VerifyGepOnNonAggregate,
39 VerifyGetNonExistentPointer,
40 VerifyGlobalMissingInitializer(String),
41 VerifyInsertElementOfIncorrectType,
42 VerifyInsertValueOfIncorrectType,
43 VerifyIntToPtrFromNonIntegerType(String),
44 VerifyIntToPtrToNonPointer(String),
45 VerifyIntToPtrUnknownSourceType,
46 VerifyInvalidGtfIndexType,
47 VerifyLoadFromNonPointer(String),
48 VerifyLocalMissingInitializer(String, String),
49 VerifyLogId,
50 VerifyLogMismatchedTypes,
51 VerifyMemcopyNonPointer(String),
52 VerifyMemcopyMismatchedTypes(String, String),
53 VerifyPtrCastFromNonPointer(String),
54 VerifyPtrCastToNonPointer(String),
55 VerifyPtrToIntToNonInteger(String),
56 VerifyReturnMismatchedTypes(String),
57 VerifyRevertCodeBadType,
58 VerifySmoBadMessageType,
59 VerifySmoCoins,
60 VerifySmoMessageSize,
61 VerifySmoRecipientNonPointer(String),
62 VerifySmoMessageNonPointer(String),
63 VerifySmoRecipientBadType,
64 VerifyStateAccessNumOfSlots,
65 VerifyStateAccessQuadNonPointer(String),
66 VerifyStateDestBadType(String),
67 VerifyStateKeyBadType,
68 VerifyStateKeyNonPointer(String),
69 VerifyStoreMismatchedTypes(Option<Value>),
70 VerifyStoreToNonPointer(String),
71 VerifyUntypedValuePassedToFunction,
72}
73impl IrError {
74 pub(crate) fn get_problematic_value(&self) -> Option<&Value> {
75 match self {
76 Self::VerifyGepFromNonPointer(_, v) => v.as_ref(),
77 Self::VerifyGepInconsistentTypes(_, v) => v.as_ref(),
78 Self::VerifyStoreMismatchedTypes(v) => v.as_ref(),
79 _ => None,
80 }
81 }
82}
83
84impl std::error::Error for IrError {}
85
86use std::fmt;
87
88use crate::Value;
89use itertools::Itertools;
90
91impl fmt::Display for IrError {
92 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
93 match self {
94 IrError::FunctionLocalClobbered(fn_str, var_str) => write!(
95 f,
96 "Local storage for function {fn_str} already has an entry for variable {var_str}."
97 ),
98 IrError::InvalidMetadatum(why_str) => {
99 write!(f, "Unable to convert from invalid metadatum: {why_str}.")
100 }
101 IrError::InvalidPhi => write!(
102 f,
103 "Phi instruction has invalid block or value reference list."
104 ),
105 IrError::MisplacedTerminator(blk_str) => {
106 write!(f, "Block {blk_str} has a misplaced terminator.")
107 }
108 IrError::MissingBlock(blk_str) => write!(f, "Unable to find block {blk_str}."),
109 IrError::MissingTerminator(blk_str) => {
110 write!(f, "Block {blk_str} is missing its terminator.")
111 }
112 IrError::ParseFailure(expecting, found) => {
113 write!(
114 f,
115 "Parse failure: expecting '{expecting}', found '{found}'."
116 )
117 }
118 IrError::RemoveMissingBlock(blk_str) => {
119 write!(f, "Unable to remove block {blk_str}; not found.")
120 }
121 IrError::ValueNotFound(reason) => {
122 write!(f, "Invalid value: {reason}.")
123 }
124 IrError::InconsistentParent(entity, expected_parent, found_parent) => {
125 write!(
126 f,
127 "For IR Entity (module/function/block) {entity}, expected parent to be {expected_parent}, \
128 but found {found_parent}."
129 )
130 }
131 IrError::VerifyArgumentValueIsNotArgument(callee) => write!(
132 f,
133 "Verification failed: Argument specifier for function '{callee}' is not an \
134 argument value."
135 ),
136 IrError::VerifyBitcastUnknownSourceType => write!(
137 f,
138 "Verification failed: Bitcast unable to determine source type."
139 ),
140 IrError::VerifyBitcastBetweenInvalidTypes(from_ty, to_ty) => write!(
141 f,
142 "Verification failed: Bitcast not allowed from a {from_ty} to a {to_ty}."
143 ),
144 IrError::VerifyUnaryOpIncorrectArgType => {
145 write!(
146 f,
147 "Verification failed: Incorrect argument type for unary op"
148 )
149 }
150 IrError::VerifyBinaryOpIncorrectArgType => {
151 write!(
152 f,
153 "Verification failed: Incorrect argument type(s) for binary op"
154 )
155 }
156 IrError::VerifyBranchToMissingBlock(label) => {
157 write!(
158 f,
159 "Verification failed: \
160 Branch to block '{label}' is not a block in the current function."
161 )
162 }
163 IrError::VerifyCallArgTypeMismatch(callee, caller_ty, callee_ty) => {
164 write!(
165 f,
166 "Verification failed: Type mismatch found for call to '{callee}': {caller_ty} is not a {callee_ty}."
167 )
168 }
169 IrError::VerifyCallToMissingFunction(callee) => {
170 write!(
171 f,
172 "Verification failed: Call to invalid function '{callee}'."
173 )
174 }
175 IrError::VerifyCmpBadTypes(lhs_ty, rhs_ty) => {
176 write!(
177 f,
178 "Verification failed: Cannot compare non-integer types {lhs_ty} and {rhs_ty}."
179 )
180 }
181 IrError::VerifyCmpTypeMismatch(lhs_ty, rhs_ty) => {
182 write!(
183 f,
184 "Verification failed: \
185 Cannot compare values with different widths of {lhs_ty} and {rhs_ty}."
186 )
187 }
188 IrError::VerifyCmpUnknownTypes => {
189 write!(
190 f,
191 "Verification failed: Unable to determine type(s) of compared value(s)."
192 )
193 }
194 IrError::VerifyConditionExprNotABool => {
195 write!(
196 f,
197 "Verification failed: Expression used for conditional is not a boolean."
198 )
199 }
200 IrError::VerifyContractCallBadTypes(arg_name) => {
201 write!(
202 f,
203 "Verification failed: \
204 Argument {arg_name} passed to contract call has the incorrect type."
205 )
206 }
207 IrError::VerifyGepElementTypeNonPointer => {
208 write!(f, "Verification failed: GEP on a non-pointer.")
209 }
210 IrError::VerifyGepInconsistentTypes(error, _) => {
211 write!(
212 f,
213 "Verification failed: Struct field type mismatch: ({}).",
214 error
215 )
216 }
217 IrError::VerifyGepFromNonPointer(ty, _) => {
218 write!(
219 f,
220 "Verification failed: Struct access must be to a pointer value, not a {ty}."
221 )
222 }
223 IrError::VerifyGepOnNonAggregate => {
224 write!(
225 f,
226 "Verification failed: Attempt to access a field from a non struct."
227 )
228 }
229 IrError::VerifyGetNonExistentPointer => {
230 write!(
231 f,
232 "Verification failed: Attempt to get pointer not found in function locals."
233 )
234 }
235 IrError::VerifyInsertElementOfIncorrectType => {
236 write!(
237 f,
238 "Verification failed: Attempt to insert value of incorrect type into an array."
239 )
240 }
241 IrError::VerifyInsertValueOfIncorrectType => {
242 write!(
243 f,
244 "Verification failed: Attempt to insert value of incorrect type into a struct."
245 )
246 }
247 IrError::VerifyIntToPtrFromNonIntegerType(ty) => {
248 write!(f, "Verification failed: int_to_ptr cannot be from a {ty}.")
249 }
250 IrError::VerifyIntToPtrToNonPointer(ty) => {
251 write!(
252 f,
253 "Verification failed: int_to_ptr cannot be to a non-pointer {ty}."
254 )
255 }
256 IrError::VerifyIntToPtrUnknownSourceType => write!(
257 f,
258 "Verification failed: int_to_ptr unable to determine source type."
259 ),
260 IrError::VerifyLoadFromNonPointer(ty) => {
261 write!(
262 f,
263 "Verification failed: Load cannot be from a non-pointer {ty}."
264 )
265 }
266 IrError::VerifyMemcopyNonPointer(ty) => {
267 write!(
268 f,
269 "Verification failed: mem_copy cannot be to or from a non-pointer {ty}.",
270 )
271 }
272 IrError::VerifyMemcopyMismatchedTypes(dst_ty, src_ty) => {
273 write!(
274 f,
275 "Verification failed: mem_copy cannot be from {src_ty} pointer to {dst_ty} \
276 pointer.",
277 )
278 }
279 IrError::VerifyReturnMismatchedTypes(fn_str) => write!(
280 f,
281 "Verification failed: \
282 Function {fn_str} return type must match its RET instructions."
283 ),
284 IrError::VerifyEntryBlockHasPredecessors(function_name, predecessors) => {
285 let plural_s = if predecessors.len() == 1 { "" } else { "s" };
286 write!(
287 f,
288 "Verification failed: Entry block of the function \"{function_name}\" has {}predecessor{}. \
289 The predecessor{} {} {}.",
290 if predecessors.len() == 1 {
291 "a "
292 } else {
293 ""
294 },
295 plural_s,
296 plural_s,
297 if predecessors.len() == 1 {
298 "is"
299 } else {
300 "are"
301 },
302 predecessors.iter().map(|block_label| format!("\"{block_label}\"")).collect_vec().join(", ")
303 )
304 }
305 IrError::VerifyBlockArgMalformed => {
306 write!(f, "Verification failed: Block argument is malformed")
307 }
308 IrError::VerifyBranchParamsMismatch => {
309 write!(
310 f,
311 "Verification failed: Block parameter passed in branch is malformed"
312 )
313 }
314 IrError::VerifyPtrCastFromNonPointer(ty) => {
315 write!(
316 f,
317 "Verification failed: Pointer cast from non pointer {ty}."
318 )
319 }
320 IrError::VerifyPtrCastToNonPointer(ty) => {
321 write!(f, "Verification failed: Pointer cast to non pointer {ty}.")
322 }
323 IrError::VerifyPtrToIntToNonInteger(ty) => {
324 write!(f, "Verification failed: Pointer cast to non integer {ty}.")
325 }
326 IrError::VerifyStateAccessNumOfSlots => {
327 write!(
328 f,
329 "Verification failed: Number of slots for state access must be an integer."
330 )
331 }
332 IrError::VerifyStateAccessQuadNonPointer(ty) => {
333 write!(
334 f,
335 "Verification failed: \
336 State quad access must be to or from a pointer, not a {ty}."
337 )
338 }
339 IrError::VerifyStateKeyBadType => {
340 write!(
341 f,
342 "Verification failed: State load or store key must be a b256 pointer."
343 )
344 }
345 IrError::VerifyStateKeyNonPointer(ty) => {
346 write!(
347 f,
348 "Verification failed: State load or store key must be a pointer, not a {ty}."
349 )
350 }
351 IrError::VerifyStateDestBadType(ty) => {
352 write!(
353 f,
354 "Verification failed: State access operation must be to a {ty} pointer."
355 )
356 }
357 IrError::VerifyStoreMismatchedTypes(_) => {
358 write!(
359 f,
360 "Verification failed: Store value and pointer type mismatch."
361 )
362 }
363 IrError::VerifyStoreToNonPointer(ty) => {
364 write!(f, "Store must be to a pointer, not a {ty}.")
365 }
366 IrError::VerifyUntypedValuePassedToFunction => write!(
367 f,
368 "Verification failed: An untyped/void value has been passed to a function call."
369 ),
370 IrError::VerifyInvalidGtfIndexType => write!(
371 f,
372 "Verification failed: An non-integer value has been passed to a 'gtf' instruction."
373 ),
374 IrError::VerifyLogId => {
375 write!(f, "Verification failed: log ID must be an integer.")
376 }
377 IrError::VerifyLogMismatchedTypes => {
378 write!(
379 f,
380 "Verification failed: log type must match the type of the value being logged."
381 )
382 }
383 IrError::VerifyRevertCodeBadType => {
384 write!(
385 f,
386 "Verification failed: error code for revert must be a u64."
387 )
388 }
389 IrError::VerifySmoRecipientBadType => {
390 write!(
391 f,
392 "Verification failed: the `smo` must have a `b256` as its first argument."
393 )
394 }
395 IrError::VerifySmoBadMessageType => {
396 write!(
397 f,
398 "Verification failed: the second arg of of `smo` must be a struct."
399 )
400 }
401 IrError::VerifySmoMessageSize => {
402 write!(
403 f,
404 "Verification failed: smo message size must be an integer."
405 )
406 }
407 IrError::VerifySmoRecipientNonPointer(ty) => {
408 write!(
409 f,
410 "Verification failed: the first arg of `smo` cannot be a non-pointer of {ty}."
411 )
412 }
413 IrError::VerifySmoMessageNonPointer(ty) => {
414 write!(
415 f,
416 "Verification failed: the second arg of `smo` cannot be a non-pointer of {ty}."
417 )
418 }
419 IrError::VerifySmoCoins => {
420 write!(
421 f,
422 "Verification failed: smo coins value must be an integer."
423 )
424 }
425 IrError::VerifyGlobalMissingInitializer(global_name) => {
426 write!(
427 f,
428 "Verification failed: Immutable global variable {global_name}\
429 is missing an initializer."
430 )
431 }
432 IrError::VerifyLocalMissingInitializer(local_name, func_name) => {
433 write!(
434 f,
435 "Verification failed: Immutable local variable {local_name} in function \
436 {func_name} is missing an initializer."
437 )
438 }
439 }
440 }
441}