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