-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Summary Replace the usage of `TNodeTable` with `Table` in `cgen`. This is a preparation for moving away from `TNode` in the code generators. In addition, the change allowed for fixing an issue with the structural comparison logic that led to `-0.0` and `0.0` being treated as equal and thus not-equal array construction expressions (e.g. `[-0.0, 0.0]` and `[0.0, 0.0]`) collapsed into the the same constant when using the C backend. ## Details The implementation of `TNodeTable` is almost exactly the same as that of `Table`, with the largest difference being that `TNodeTable` uses the `key` and not its stored hash for testing whether a slot is empty. To be able to use a `PNode` as the key, a distinct type (`ConstrTree`; for "construction tree") is created that has a structural hash and structural equality operator. Both operators are based on the previously used `hashTree` and `treesEquivalent` procedures from the `treetab` module, with adjustments made for the specific use case: - `nkIdent` nodes don't reach the code generator (and thus don't need to be considered) - nodes of integer kind always have their value hashed, as opposed to the value being used as the hash (which means a hash is also computed for >= 2^32 values when using a 32-bit compiler) - the bit pattern of floats are compared, not the values themselves The last change fixes the aforementioned issue with two non-bit-pattern- equal values resulting from constant array construction expressions using into the same constant. --------- Co-authored-by: Saem Ghani <saemghani+github@gmail.com>
- Loading branch information
Showing
5 changed files
with
133 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
discard """ | ||
targets: "c js vm" | ||
description: ''' | ||
Regression test for two constant array construction expressions being | ||
lifted into the *same* constant, despite their float contents having | ||
different bit representations | ||
''' | ||
""" | ||
|
||
import std/math | ||
|
||
type Obj = object | ||
x: float | ||
|
||
proc test() = | ||
# use a wrapper procedure in order to test with locals, and not globals | ||
var | ||
a = [-0.0, 0.0] | ||
b = [0.0, 0.0] | ||
|
||
# the array values are compile-time known, meaning that they can be lifted | ||
# into constants, but they must not be erroneously collapsed into a single | ||
# one | ||
doAssert classify(a[0]) == fcNegZero | ||
doAssert classify(a[1]) == fcZero | ||
doAssert classify(b[0]) == fcZero | ||
doAssert classify(b[1]) == fcZero | ||
|
||
# for completeness, also test with tuples and objects: | ||
var | ||
c = (-0.0, 0.0) | ||
d = (0.0, 0.0) | ||
|
||
doAssert classify(c[0]) == fcNegZero | ||
doAssert classify(c[1]) == fcZero | ||
doAssert classify(d[0]) == fcZero | ||
doAssert classify(d[1]) == fcZero | ||
|
||
# test with objects: | ||
var | ||
e = Obj(x: -0.0) | ||
f = Obj(x: 0.0) | ||
|
||
doAssert classify(e.x) == fcNegZero | ||
doAssert classify(f.x) == fcZero | ||
|
||
test() |