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