sway_ir/
error.rs

1/// These errors are for internal IR failures, not designed to be useful to a Sway developer, but
2/// more for users of the `sway-ir` crate, i.e., compiler developers.
3///
4/// XXX They're not very rich and could do with a little more verbosity.
5
6#[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}