Issue 250924.2: DW_OP_mod doesn’t specify which definition of modulo
| Author: | Ben Woodard |
|---|---|
| Champion: | Mark Wielaard |
| Date submitted: | 2025-09-24 |
| Date revised: | 2025-11-24 |
| Date closed: | 2025-11-24 |
| Type: | Clarification |
| Status: | Accepted |
| DWARF version: | 6 |
Comparing original with latest. [ Return to the latest version ]
## Background Evidently, originally DWARF didn’t allow arithmetic operations on
floating point numbers and most uses of the DWARF stack were done with the assumption that the values being acted upon were addresses and so the computation was assumed to be acting upon unsigned numbers.
(typed) natural or floating point numbers and most uses of the DWARF stack were done with the assumption that the values being acted upon were addresses and so the computation was assumed to be acting upon unsigned numbers.
At some point, DWARF began to allow the arithmetic operations to work on
At some point, DWARF began to allow the arithmetic operations to work
floating point numbers and several operations were explicitly defined to work over non-integral values. This led to the paragraph in the current DWARF working draft that says in section 2.5.2.4 on page 37 lines 24-27:
on (typed) natural or floating point numbers and several operations were explicitly defined to work over non-integral values. This led to the paragraph in the current DWARF working draft that says in section 2.5.2.4 on page 37 lines 24-27:
> Operations other than `DW_OP_abs`, `DW_OP_div`, > `DW_OP_minus`, `DW_OP_mul`, `DW_OP_neg` and `DW_OP_plus` > require integral types of the operand (either integral base > type or the generic type). Operations do not cause an > exception on overflow. Unlike all the other arithmetic operations this explicitly limits `DW_OP_mod` to integral base types and the generic type. It lumps `DW_OP_mod` in with the logical operations. Furthermore, there are multiple definitions of the modulo operator which vary in how they handle signed values. According to the dwarf-discuss archives, this was [raised][tromey] in 2010 and Michael Eager [responded][eager] that `DW_OP_mod` used the modulo algorithm for unsigned arithmetic. However, this decision was not recorded in the standard. Since that time, consumers have implemented different implementations of `DW_OP_mod`. This proposal seeks to clarify and harmonize the consumer
implementations of the `DW_OP_mod` operator by defining which algorithm to
implementations of the `DW_OP_mod` operator by defining which
use for signed arithmetic as well as define it for floating point numbers.
algorithm to use for signed arithmetic as well as decide whether to define it for floating point numbers.
## Proposal
Add `DW_OP_mod` to the list of operators which do not require integral base types by changing:
Rename `DW_OP_mod` to `DW_OP_mod_trunc` and explicitly define the algorithm used as using truncated division.
> Operations other than `DW_OP_abs`, `DW_OP_div`, `DW_OP_minus`, `DW_OP_mul`, > `DW_OP_neg` and `DW_OP_plus` require integral types of the operand (either > integral base type or the generic type).
Under 2.5.1.4 Arithmetic and Logical Operations change 5. `DW_OP_mod` to `DW_OP_mod_trunc`. Add at the end of the paragraph: "Use the following formula for modulo: *x* `mod_trunc` *y* = *x* − *y* × trunc(*x* / *y*)".
To:
Insert 6. `DW_OP_mod_floor` with the same explanation as `DW_OP_mod_trunc`, but using the formula: "*x* `mod_floor` *y* = *x* − *y* × floor(*x* / *y*)".
> Operations other than `DW_OP_abs`, `DW_OP_div`, `DW_OP_mod`, `DW_OP_minus`, > `DW_OP_mul`, `DW_OP_neg` and `DW_OP_plus` require integral types of the > operand (either integral base type or the generic type).
In Table 7.9: DWARF operation encodings change `DW_OP_mod` to `DW_OP_mod_trunc`. Add `DW_OP_mod_floor` with constant TBA and no. of operants zero.
Then append the following sentence to the description of the `DW_OP_mod` operator:
6.4.2 Call Frame Instructions. Add `DW_OP_mod_floor` to the list of DWARF operators that cannot be used.
Keep the list of operators which do not require integral the same. `DW_OP_mod_trunc` and `DW_OP_mod_floor` are only defined for integral types, not floating point.
> The algorithm used to implement modulo shall be the one defined in > [Knuth][knuth] Volume 1: Fundamental Algorithms, Section 1.2.4. ## Alternative proposals 1. Explicitly state in the standard that `DW_OP_mod` is only defined for unsigned integral arithmetic. This effectively standardizes the 2010 [ruling][eager]. 2. Pick any algorithm for modulo that works for signed as well unsigned arithmetic and specify that `DW_OP_mod` shall follow it. The current GDB implementation follows [Knuth][knuth] 1.2.4 for signed and unsigned integral arithmetic but excludes the algorithm for reals and floating point numbers.
## References
From [Knuth][knuth] Section 1.2.4:
> If *x* and *y* are any real numbers, we define the following binary operation:
>
> > *x* mod *y* = *x* − *y* × floor(*x* / *y*), if *y* ≠ 0; *x* mod 0 = *x*.
[tromey]: https://lists.dwarfstd.org/pipermail/dwarf-discuss/2010-January/000805.html
[eager]: https://lists.dwarfstd.org/pipermail/dwarf-discuss/2010-January/000806.html
[knuth]: https://www-cs-faculty.stanford.edu/~knuth/taocp.html
---
2025-10-27: Identified the following options:
- Define `DW_OP_mod` for unsigned arithmetic only.
- Pick one definition to support signed arithmetic
(see Wikipedia article on [Modulo][wiki]):
- Floored (Knuth, typically called modulo)
- Truncated (often called remainder)
- Euclidean (always non-negative, uncommon)
- Rounded (mostly used only for floating-point remainder)
- Define `DW_OP_mod` to use floored division;
add `DW_OP_rem` using truncated division.
- Make it language/target dependent [ruled out by consensus].
Orthogonal:
- Should it/they be defined for floating-point?
- Should operations on the generic type be unsigned?
[wiki]: https://en.wikipedia.org/wiki/Modulo
2025-11-24: [Update][diff1] after vote on naming and proposal for other issues. - Update background to mention this isn't just about floating point. - Rename `DW_OP_mod` to `DW_OP_mod_trunc` (but keep constant value) - Define `DW_OP_mod_trunc` to use truncated division - Add `DW_OP_mod_floor`, defined using floored division - Explicitly disallow `DW_OP_mod_floor` in CFI - Don't define for zero nominator (like division, expr just errors) - Don't change the operators that require integral values (won't support floating point for modulo) 2025-11-24: Accepted.