Skip to main content

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    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}