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