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