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 VerifyGetNonExistentLocalVarPointer,
40 VerifyGetNonExistentGlobalVarPointer,
41 VerifyGetNonExistentConfigPointer,
42 VerifyGetNonExistentStorageKeyPointer,
43 VerifyGlobalMissingInitializer(String),
44 VerifyInsertElementOfIncorrectType,
45 VerifyInsertValueOfIncorrectType,
46 VerifyIntToPtrFromNonIntegerType(String),
47 VerifyIntToPtrToNonPointer(String),
48 VerifyIntToPtrUnknownSourceType,
49 VerifyAllocCountNotUint64,
50 VerifyInvalidGtfIndexType,
51 VerifyInvalidGtfTxFieldIdSize(u64),
52 VerifyLoadFromNonPointer(String),
53 VerifyLocalMissingInitializer(String, String),
54 VerifyLogId,
55 VerifyLogMismatchedTypes,
56 VerifyLogEventDataVersion(u8),
57 VerifyLogEventDataInvalid(String),
58 VerifyMemcopyNonPointer(String),
59 VerifyMemcopyMismatchedTypes(String, String),
60 VerifyMemClearValNonPointer(String),
61 VerifyPtrCastFromNonPointer(String),
62 VerifyPtrCastToNonPointer(String),
63 VerifyPtrToIntToNonInteger(String),
64 VerifyReturnMismatchedTypes(String),
65 VerifyRevertCodeBadType,
66 VerifySmoBadMessageType,
67 VerifySmoCoins,
68 VerifySmoMessageSize,
69 VerifySmoRecipientNonPointer(String),
70 VerifySmoMessageNonPointer(String),
71 VerifySmoRecipientBadType,
72 VerifyStateAccessNumOfSlots,
73 VerifyStateAccessSourceDestNonPointer(String),
74 VerifyStateAccessSourceDestNonUntypedPointer(String),
75 VerifyStateDestBadType(String),
76 VerifyStateKeyBadType,
77 VerifyStateKeyNonPointer(String),
78 VerifyStateLoadWordOffsetSize(u64),
79 VerifyStateReadOffsetBadType,
80 VerifyStateReadLenBadType,
81 VerifyStateWriteSlotLenBadType,
82 VerifyStateUpdateSlotOffsetBadType,
83 VerifyStateUpdateSlotLenBadType,
84 VerifyStoreMismatchedTypes(Option<Value>),
85 VerifyStoreToNonPointer(String),
86 VerifyUntypedValuePassedToFunction,
87 VerifyInitAggrAggrPointerMismatch,
88 VerifyInitAggrMismatchedStructInitializerCount(usize, usize),
89 VerifyInitAggrMismatchedArrayInitializerCount(usize, usize),
90 VerifyInitAggrUnknownInitializerType(usize),
91 VerifyInitAggrMismatchedStructFieldType(usize, String, String),
92 VerifyInitAggrMismatchedArrayElementType(usize, String, String),
93}
94impl IrError {
95 pub(crate) fn get_problematic_value(&self) -> Option<&Value> {
96 match self {
97 Self::VerifyGepFromNonPointer(_, v) => v.as_ref(),
98 Self::VerifyGepInconsistentTypes(_, v) => v.as_ref(),
99 Self::VerifyStoreMismatchedTypes(v) => v.as_ref(),
100 _ => None,
101 }
102 }
103}
104
105impl std::error::Error for IrError {}
106
107use std::fmt;
108
109use crate::Value;
110use itertools::Itertools;
111
112impl fmt::Display for IrError {
113 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
114 match self {
115 IrError::FunctionLocalClobbered(fn_str, var_str) => write!(
116 f,
117 "Local storage for function {fn_str} already has an entry for variable {var_str}."
118 ),
119 IrError::InvalidMetadatum(why_str) => {
120 write!(f, "Unable to convert from invalid metadatum: {why_str}.")
121 }
122 IrError::InvalidPhi => write!(
123 f,
124 "Phi instruction has invalid block or value reference list."
125 ),
126 IrError::MisplacedTerminator(blk_str) => {
127 write!(f, "Block {blk_str} has a misplaced terminator.")
128 }
129 IrError::MissingBlock(blk_str) => write!(f, "Unable to find block {blk_str}."),
130 IrError::MissingTerminator(blk_str) => {
131 write!(f, "Block {blk_str} is missing its terminator.")
132 }
133 IrError::ParseFailure(expecting, found) => {
134 write!(
135 f,
136 "Parse failure: expecting '{expecting}', found '{found}'."
137 )
138 }
139 IrError::RemoveMissingBlock(blk_str) => {
140 write!(f, "Unable to remove block {blk_str}; not found.")
141 }
142 IrError::ValueNotFound(reason) => {
143 write!(f, "Invalid value: {reason}.")
144 }
145 IrError::InconsistentParent(entity, expected_parent, found_parent) => {
146 write!(
147 f,
148 "For IR Entity (module/function/block) {entity}, expected parent to be {expected_parent}, \
149 but found {found_parent}."
150 )
151 }
152 IrError::VerifyArgumentValueIsNotArgument(callee) => write!(
153 f,
154 "Verification failed: Argument specifier for function '{callee}' is not an \
155 argument value."
156 ),
157 IrError::VerifyBitcastUnknownSourceType => write!(
158 f,
159 "Verification failed: Bitcast unable to determine source type."
160 ),
161 IrError::VerifyBitcastBetweenInvalidTypes(from_ty, to_ty) => write!(
162 f,
163 "Verification failed: Bitcast not allowed from a {from_ty} to a {to_ty}."
164 ),
165 IrError::VerifyUnaryOpIncorrectArgType => {
166 write!(
167 f,
168 "Verification failed: Incorrect argument type for unary op"
169 )
170 }
171 IrError::VerifyBinaryOpIncorrectArgType => {
172 write!(
173 f,
174 "Verification failed: Incorrect argument type(s) for binary op"
175 )
176 }
177 IrError::VerifyBranchToMissingBlock(label) => {
178 write!(
179 f,
180 "Verification failed: \
181 Branch to block '{label}' is not a block in the current function."
182 )
183 }
184 IrError::VerifyCallArgTypeMismatch(callee, caller_ty, callee_ty) => {
185 write!(
186 f,
187 "Verification failed: Type mismatch found for call to '{callee}': {caller_ty} is not a {callee_ty}."
188 )
189 }
190 IrError::VerifyCallToMissingFunction(callee) => {
191 write!(
192 f,
193 "Verification failed: Call to invalid function '{callee}'."
194 )
195 }
196 IrError::VerifyCmpBadTypes(lhs_ty, rhs_ty) => {
197 write!(
198 f,
199 "Verification failed: Cannot compare non-integer types {lhs_ty} and {rhs_ty}."
200 )
201 }
202 IrError::VerifyCmpTypeMismatch(lhs_ty, rhs_ty) => {
203 write!(
204 f,
205 "Verification failed: \
206 Cannot compare values with different widths of {lhs_ty} and {rhs_ty}."
207 )
208 }
209 IrError::VerifyCmpUnknownTypes => {
210 write!(
211 f,
212 "Verification failed: Unable to determine type(s) of compared value(s)."
213 )
214 }
215 IrError::VerifyConditionExprNotABool => {
216 write!(
217 f,
218 "Verification failed: Expression used for conditional is not a boolean."
219 )
220 }
221 IrError::VerifyContractCallBadTypes(arg_name) => {
222 write!(
223 f,
224 "Verification failed: \
225 Argument {arg_name} passed to contract call has the incorrect type."
226 )
227 }
228 IrError::VerifyGepElementTypeNonPointer => {
229 write!(f, "Verification failed: GEP on a non-pointer.")
230 }
231 IrError::VerifyGepInconsistentTypes(error, _) => {
232 write!(
233 f,
234 "Verification failed: Struct field type mismatch: ({error})."
235 )
236 }
237 IrError::VerifyGepFromNonPointer(ty, _) => {
238 write!(
239 f,
240 "Verification failed: Struct access must be to a pointer value, not a {ty}."
241 )
242 }
243 IrError::VerifyGepOnNonAggregate => {
244 write!(
245 f,
246 "Verification failed: Attempt to access a field from a non struct."
247 )
248 }
249 IrError::VerifyGetNonExistentLocalVarPointer => {
250 write!(
251 f,
252 "Verification failed: Attempt to get pointer not found in function local variables."
253 )
254 }
255 IrError::VerifyGetNonExistentGlobalVarPointer => {
256 write!(
257 f,
258 "Verification failed: Attempt to get pointer not found in module global variables."
259 )
260 }
261 IrError::VerifyGetNonExistentConfigPointer => {
262 write!(
263 f,
264 "Verification failed: Attempt to get pointer not found in module configurables."
265 )
266 }
267 IrError::VerifyGetNonExistentStorageKeyPointer => {
268 write!(
269 f,
270 "Verification failed: Attempt to get pointer not found in module storage keys."
271 )
272 }
273 IrError::VerifyInsertElementOfIncorrectType => {
274 write!(
275 f,
276 "Verification failed: Attempt to insert value of incorrect type into an array."
277 )
278 }
279 IrError::VerifyInsertValueOfIncorrectType => {
280 write!(
281 f,
282 "Verification failed: Attempt to insert value of incorrect type into a struct."
283 )
284 }
285 IrError::VerifyIntToPtrFromNonIntegerType(ty) => {
286 write!(f, "Verification failed: int_to_ptr cannot be from a {ty}.")
287 }
288 IrError::VerifyIntToPtrToNonPointer(ty) => {
289 write!(
290 f,
291 "Verification failed: int_to_ptr cannot be to a non-pointer {ty}."
292 )
293 }
294 IrError::VerifyIntToPtrUnknownSourceType => write!(
295 f,
296 "Verification failed: int_to_ptr unable to determine source type."
297 ),
298 IrError::VerifyAllocCountNotUint64 => {
299 write!(
300 f,
301 "Verification failed: alloc instruction count must be a u64 integer."
302 )
303 }
304 IrError::VerifyLoadFromNonPointer(ty) => {
305 write!(
306 f,
307 "Verification failed: Load cannot be from a non-pointer {ty}."
308 )
309 }
310 IrError::VerifyMemcopyNonPointer(ty) => {
311 write!(
312 f,
313 "Verification failed: mem_copy cannot be to or from a non-pointer {ty}.",
314 )
315 }
316 IrError::VerifyMemcopyMismatchedTypes(dst_ty, src_ty) => {
317 write!(
318 f,
319 "Verification failed: mem_copy cannot be from {src_ty} pointer to {dst_ty} \
320 pointer.",
321 )
322 }
323 IrError::VerifyMemClearValNonPointer(ty) => {
324 write!(
325 f,
326 "Verification failed: mem_clear_val argument is not a pointer {ty}.",
327 )
328 }
329 IrError::VerifyReturnMismatchedTypes(fn_str) => write!(
330 f,
331 "Verification failed: \
332 Function {fn_str} return type must match its RET instructions."
333 ),
334 IrError::VerifyEntryBlockHasPredecessors(function_name, predecessors) => {
335 let plural_s = if predecessors.len() == 1 { "" } else { "s" };
336 write!(
337 f,
338 "Verification failed: Entry block of the function \"{function_name}\" has {}predecessor{}. \
339 The predecessor{} {} {}.",
340 if predecessors.len() == 1 {
341 "a "
342 } else {
343 ""
344 },
345 plural_s,
346 plural_s,
347 if predecessors.len() == 1 {
348 "is"
349 } else {
350 "are"
351 },
352 predecessors.iter().map(|block_label| format!("\"{block_label}\"")).collect_vec().join(", ")
353 )
354 }
355 IrError::VerifyBlockArgMalformed => {
356 write!(f, "Verification failed: Block argument is malformed")
357 }
358 IrError::VerifyBranchParamsMismatch => {
359 write!(
360 f,
361 "Verification failed: Block parameter passed in branch is malformed"
362 )
363 }
364 IrError::VerifyPtrCastFromNonPointer(ty) => {
365 write!(
366 f,
367 "Verification failed: Pointer cast from non pointer {ty}."
368 )
369 }
370 IrError::VerifyPtrCastToNonPointer(ty) => {
371 write!(f, "Verification failed: Pointer cast to non pointer {ty}.")
372 }
373 IrError::VerifyPtrToIntToNonInteger(ty) => {
374 write!(f, "Verification failed: Pointer cast to non integer {ty}.")
375 }
376 IrError::VerifyStateAccessNumOfSlots => {
377 write!(
378 f,
379 "Verification failed: Number of slots for state access must be an integer."
380 )
381 }
382 IrError::VerifyStateAccessSourceDestNonPointer(ty) => {
383 write!(
384 f,
385 "Verification failed: \
386 State access must be to or from a pointer, not a `{ty}`."
387 )
388 }
389 IrError::VerifyStateAccessSourceDestNonUntypedPointer(ty) => {
390 write!(
391 f,
392 "Verification failed: \
393 State access must be to or from an untyped pointer, not a `{ty}`."
394 )
395 }
396 IrError::VerifyStateKeyBadType => {
397 write!(
398 f,
399 "Verification failed: State loading or storing key must be a `b256` pointer."
400 )
401 }
402 IrError::VerifyStateKeyNonPointer(ty) => {
403 write!(
404 f,
405 "Verification failed: State loading or storing key must be a pointer, not a `{ty}`."
406 )
407 }
408 IrError::VerifyStateDestBadType(ty) => {
409 write!(
410 f,
411 "Verification failed: State access operation must be to a `{ty}` pointer."
412 )
413 }
414 IrError::VerifyStateLoadWordOffsetSize(offset) => write!(
415 f,
416 "Verification failed: 'state_load_word' instruction has offset that does not fit in 6 bits: {offset}."
417 ),
418 IrError::VerifyStateReadOffsetBadType => write!(
419 f,
420 "Verification failed: 'state_read_slot' instruction has an offset argument that is not an integer."
421 ),
422 IrError::VerifyStateReadLenBadType => write!(
423 f,
424 "Verification failed: 'state_read_slot' instruction has a length argument that is not an integer."
425 ),
426 IrError::VerifyStateWriteSlotLenBadType => write!(
427 f,
428 "Verification failed: 'state_write_slot' instruction has a length argument that is not an integer."
429 ),
430 IrError::VerifyStateUpdateSlotOffsetBadType => write!(
431 f,
432 "Verification failed: 'state_update_slot' instruction has an offset argument that is not an integer."
433 ),
434 IrError::VerifyStateUpdateSlotLenBadType => write!(
435 f,
436 "Verification failed: 'state_update_slot' instruction has a length argument that is not an integer."
437 ),
438 IrError::VerifyStoreMismatchedTypes(_) => {
439 write!(
440 f,
441 "Verification failed: Store value and pointer type mismatch."
442 )
443 }
444 IrError::VerifyStoreToNonPointer(ty) => {
445 write!(f, "Store must be to a pointer, not a {ty}.")
446 }
447 IrError::VerifyUntypedValuePassedToFunction => write!(
448 f,
449 "Verification failed: An untyped/void value has been passed to a function call."
450 ),
451 IrError::VerifyInvalidGtfIndexType => write!(
452 f,
453 "Verification failed: A non-integer value has been passed as index to a 'gtf' instruction."
454 ),
455 IrError::VerifyInvalidGtfTxFieldIdSize(tx_field_id) => write!(
456 f,
457 "Verification failed: 'gtf' instruction has transaction field ID that does not fit in 12 bits: {tx_field_id}."
458 ),
459 IrError::VerifyLogId => {
460 write!(f, "Verification failed: log ID must be an integer.")
461 }
462 IrError::VerifyLogMismatchedTypes => {
463 write!(
464 f,
465 "Verification failed: log type must match the type of the value being logged."
466 )
467 }
468 IrError::VerifyLogEventDataVersion(version) => {
469 write!(
470 f,
471 "Verification failed: unsupported log event metadata version {version}."
472 )
473 }
474 IrError::VerifyLogEventDataInvalid(reason) => {
475 write!(
476 f,
477 "Verification failed: invalid log event metadata ({reason})."
478 )
479 }
480 IrError::VerifyRevertCodeBadType => {
481 write!(
482 f,
483 "Verification failed: error code for revert must be a u64."
484 )
485 }
486 IrError::VerifySmoRecipientBadType => {
487 write!(
488 f,
489 "Verification failed: the `smo` must have a `b256` as its first argument."
490 )
491 }
492 IrError::VerifySmoBadMessageType => {
493 write!(
494 f,
495 "Verification failed: the second arg of of `smo` must be a struct."
496 )
497 }
498 IrError::VerifySmoMessageSize => {
499 write!(
500 f,
501 "Verification failed: smo message size must be an integer."
502 )
503 }
504 IrError::VerifySmoRecipientNonPointer(ty) => {
505 write!(
506 f,
507 "Verification failed: the first arg of `smo` cannot be a non-pointer of {ty}."
508 )
509 }
510 IrError::VerifySmoMessageNonPointer(ty) => {
511 write!(
512 f,
513 "Verification failed: the second arg of `smo` cannot be a non-pointer of {ty}."
514 )
515 }
516 IrError::VerifySmoCoins => {
517 write!(
518 f,
519 "Verification failed: smo coins value must be an integer."
520 )
521 }
522 IrError::VerifyGlobalMissingInitializer(global_name) => {
523 write!(
524 f,
525 "Verification failed: Immutable global variable {global_name}\
526 is missing an initializer."
527 )
528 }
529 IrError::VerifyLocalMissingInitializer(local_name, func_name) => {
530 write!(
531 f,
532 "Verification failed: Immutable local variable {local_name} in function \
533 {func_name} is missing an initializer."
534 )
535 }
536 IrError::VerifyInitAggrAggrPointerMismatch => {
537 write!(
538 f,
539 "Verification failed: init_aggr instruction's aggregate pointer must be a pointer to IR struct or array."
540 )
541 }
542 IrError::VerifyInitAggrMismatchedStructInitializerCount(
543 num_of_fields,
544 num_of_initializers,
545 ) => {
546 write!(
547 f,
548 "Verification failed: init_aggr instruction has {num_of_initializers} initializer(s) and the initialized struct has {num_of_fields} field(s)."
549 )
550 }
551 IrError::VerifyInitAggrMismatchedArrayInitializerCount(
552 num_of_elements,
553 num_of_initializers,
554 ) => {
555 write!(
556 f,
557 "Verification failed: init_aggr instruction has {num_of_initializers} initializer(s) and the initialized array has {num_of_elements} element(s)."
558 )
559 }
560 IrError::VerifyInitAggrUnknownInitializerType(idx) => {
561 write!(
562 f,
563 "Verification failed: init_aggr instruction has an initializer with an unknown type. Initializer index: {idx}."
564 )
565 }
566 IrError::VerifyInitAggrMismatchedStructFieldType(idx, field_ty, initializer_ty) => {
567 write!(
568 f,
569 "Verification failed: init_aggr instruction has an initializer with a type mismatch for struct field at index {idx}. Expected field type: {field_ty}, found initializer type: {initializer_ty}."
570 )
571 }
572 IrError::VerifyInitAggrMismatchedArrayElementType(idx, element_ty, initializer_ty) => {
573 write!(
574 f,
575 "Verification failed: init_aggr instruction has an initializer with a type mismatch for array element at index {idx}. Expected element type: {element_ty}, found initializer type: {initializer_ty}."
576 )
577 }
578 }
579 }
580}