summaryrefslogtreecommitdiff
path: root/gcc/testsuite/gdc.test/runnable/testbtst.d
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/gdc.test/runnable/testbtst.d')
-rw-r--r--gcc/testsuite/gdc.test/runnable/testbtst.d156
1 files changed, 156 insertions, 0 deletions
diff --git a/gcc/testsuite/gdc.test/runnable/testbtst.d b/gcc/testsuite/gdc.test/runnable/testbtst.d
new file mode 100644
index 00000000000..a6967f6c17d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/testbtst.d
@@ -0,0 +1,156 @@
+/* PERMUTE_ARGS: -O
+ * https://issues.dlang.org/show_bug.cgi?id=19813
+ */
+
+struct BitArray
+{
+ import core.bitop : btc, bts, btr, bsf, bt;
+
+ size_t _len;
+ size_t* _ptr;
+ enum bitsPerSizeT = size_t.sizeof * 8;
+
+ static size_t lenToDim(size_t len) @nogc pure nothrow @safe
+ {
+ return (len + (bitsPerSizeT-1)) / bitsPerSizeT;
+ }
+
+ this(in bool[] ba) nothrow pure
+ {
+ length = ba.length;
+ foreach (i, b; ba)
+ {
+ if (b)
+ bts(_ptr, i);
+ else
+ btr(_ptr, i);
+ }
+ }
+
+ @property size_t length(size_t newlen) pure nothrow @system
+ {
+ if (newlen != _len)
+ {
+ size_t olddim = lenToDim(_len);
+ immutable newdim = lenToDim(newlen);
+
+ if (newdim != olddim)
+ {
+ // Create a fake array so we can use D's realloc machinery
+ auto b = _ptr[0 .. olddim];
+ b.length = newdim; // realloc
+ _ptr = b.ptr;
+ }
+
+ _len = newlen;
+ }
+ return _len;
+ }
+
+ int opCmp(ref BitArray a2) const @nogc pure nothrow
+ {
+ const lesser = this._len < a2._len ? &this : &a2;
+ immutable fullWords = lesser._len / lesser.bitsPerSizeT;
+ immutable endBits = lesser._len % lesser.bitsPerSizeT;
+ auto p1 = this._ptr;
+ auto p2 = a2._ptr;
+
+ foreach (i; 0 .. fullWords)
+ {
+ if (p1[i] != p2[i])
+ {
+ return p1[i] & (size_t(1) << bsf(p1[i] ^ p2[i])) ? 1 : -1;
+ }
+ }
+
+ if (endBits)
+ {
+ immutable i = fullWords;
+ immutable diff = p1[i] ^ p2[i];
+ if (diff)
+ {
+ immutable index = bsf(diff);
+ if (index < endBits)
+ {
+ // This gets optimized into OPbtst, and was doing it incorrectly
+ return p1[i] & (size_t(1) << index) ? 1 : -1;
+ }
+ }
+ }
+
+ return -1;
+ }
+}
+
+void test1()
+{
+ bool[] ba = [1,0,1,0,1];
+ bool[] bd = [1,0,1,1,1];
+
+ auto a = BitArray(ba);
+ auto d = BitArray(bd);
+
+ assert(a < d);
+}
+
+/***************************************/
+
+// https://issues.dlang.org/show_bug.cgi?id=18748
+
+int bt_32_imm(in uint* p)
+{
+ enum bitnum = 1;
+ return ((p[bitnum >> 5] & (1 << (bitnum & 31)))) != 0;
+}
+
+void test18748()
+{
+ version (linux)
+ {
+ import core.sys.posix.sys.mman;
+ import core.sys.posix.unistd;
+ // Allocate two pages.
+ immutable sz = 2 * sysconf(_SC_PAGESIZE);
+ auto m = mmap(null, sz, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0);
+ // Discard the higher page. It becomes unreadable.
+ munmap(m + sz / 2, sz / 2);
+ // Try looking at the last 4 bytes of the readable page.
+ uint* p = cast(uint*) (m + sz / 2 - uint.sizeof);
+ bt_32_imm(p);
+ munmap(m, sz / 2); // Free the readable page.
+ }
+}
+
+/***************************************/
+
+// https://issues.dlang.org/show_bug.cgi?id=18749
+
+ulong f(ulong* p, uint shift)
+{
+ return (*p >> shift) & 1;
+}
+
+ulong g(ulong* p, ulong shift)
+{
+ return f(p, cast(uint) shift);
+}
+
+void test18749()
+{
+ enum shift = uint.max + 1L;
+ assert(cast(uint) shift == 0);
+ ulong s = 1;
+ assert(g(&s, shift));
+}
+
+
+/***************************************/
+
+int main()
+{
+ test1();
+ test18748();
+ test18749();
+
+ return 0;
+}