Skip to content

Commit 5c5d448

Browse files
committed
Implement cent/ucent data types.
This is a first try at implementing the data types cent and ucent. All changes are wrapped in #if WANT_CENT .. #endif. It takes advantage of the GCC builtin type __int128 and is currently only enabled if compiled with gcc. As soon as this is stable it should go upstream, too.
1 parent 62bbd5f commit 5c5d448

19 files changed

Lines changed: 694 additions & 7 deletions

dmd2/builtin.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,12 @@ static inline int getBitsizeOfType(Loc loc, Type *type)
120120
case Tuns16: return 16;
121121
case Tint128:
122122
case Tuns128:
123+
#if WANT_CENT
124+
return 128;
125+
#else
123126
error(loc, "cent/ucent not supported");
124127
break;
128+
#endif
125129
default:
126130
error(loc, "unsupported type");
127131
break;
@@ -273,8 +277,20 @@ Expression *eval_bswap(Loc loc, FuncDeclaration *fd, Expressions *arguments)
273277
#define BYTEMASK 0x00FF00FF00FF00FFLL
274278
#define SHORTMASK 0x0000FFFF0000FFFFLL
275279
#define INTMASK 0x00000000FFFFFFFFLL
280+
#if WANT_CENT
281+
#define LONGMASK 0xFFFFFFFFFFFFFFFFLL
282+
#endif
276283
switch (type->toBasetype()->ty)
277284
{
285+
case Tint128:
286+
case Tuns128:
287+
#if WANT_CENT
288+
// swap high and low uints
289+
n = ((n >> 64) & LONGMASK) | ((n & LONGMASK) << 64);
290+
#else
291+
error(loc, "cent/ucent not supported");
292+
break;
293+
#endif
278294
case Tint64:
279295
case Tuns64:
280296
// swap high and low uints
@@ -288,10 +304,6 @@ Expression *eval_bswap(Loc loc, FuncDeclaration *fd, Expressions *arguments)
288304
// swap adjacent ubytes
289305
n = ((n >> 8 ) & BYTEMASK) | ((n & BYTEMASK) << 8 );
290306
break;
291-
case Tint128:
292-
case Tuns128:
293-
error(loc, "cent/ucent not supported");
294-
break;
295307
default:
296308
error(loc, "unsupported type");
297309
break;

dmd2/constfold.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,16 @@ UnionExp Shr(Type *type, Expression *e1, Expression *e2)
648648
value = (d_uns64)(value) >> count;
649649
break;
650650

651+
#if WANT_CENT
652+
case Tint128:
653+
value = (d_int128)(value) >> count;
654+
break;
655+
656+
case Tuns128:
657+
value = (d_uns128)(value) >> count;
658+
break;
659+
#endif
660+
651661
case Terror:
652662
new(&ue) ErrorExp();
653663
return ue;
@@ -690,10 +700,22 @@ UnionExp Ushr(Type *type, Expression *e1, Expression *e2)
690700
value = (value & 0xFFFFFFFF) >> count;
691701
break;
692702

703+
#if WANT_CENT
704+
case Tint64:
705+
case Tuns64:
706+
value = (value & 0xFFFFFFFFFFFFFFFF) >> count;
707+
break;
708+
709+
case Tint128:
710+
case Tuns128:
711+
value = (d_uns128)(value) >> count;
712+
break;
713+
#else
693714
case Tint64:
694715
case Tuns64:
695716
value = (d_uns64)(value) >> count;
696717
break;
718+
#endif
697719

698720
case Terror:
699721
new(&ue) ErrorExp();
@@ -1258,6 +1280,10 @@ UnionExp Cast(Type *type, Type *to, Expression *e1)
12581280
case Tuns32: result = (d_uns32)r; break;
12591281
case Tint64: result = (d_int64)r; break;
12601282
case Tuns64: result = (d_uns64)r; break;
1283+
#if WANT_CENT
1284+
case Tint128: result = (d_int128)r; break;
1285+
case Tuns128: result = (d_uns128)r; break;
1286+
#endif
12611287
default:
12621288
assert(0);
12631289
}

dmd2/ctfeexpr.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,6 +1120,17 @@ void intBinary(TOK op, IntegerExp *dest, Type *type, IntegerExp *e1, IntegerExp
11201120
case Tuns64:
11211121
result = (d_uns64)(value) >> count;
11221122
break;
1123+
1124+
#if WANT_CENT
1125+
case Tint128:
1126+
result = (d_int128)(value) >> count;
1127+
break;
1128+
1129+
case Tuns128:
1130+
result = (d_uns128)(value) >> count;
1131+
break;
1132+
#endif
1133+
11231134
default:
11241135
assert(0);
11251136
}
@@ -1153,10 +1164,22 @@ void intBinary(TOK op, IntegerExp *dest, Type *type, IntegerExp *e1, IntegerExp
11531164
result = (value & 0xFFFFFFFF) >> count;
11541165
break;
11551166

1167+
#if WANT_CENT
1168+
case Tint64:
1169+
case Tuns64:
1170+
result = (value & 0xFFFFFFFFFFFFFFFF) >> count;
1171+
break;
1172+
1173+
case Tint128:
1174+
case Tuns128:
1175+
result = (d_uns128)(value) >> count;
1176+
break;
1177+
#else
11561178
case Tint64:
11571179
case Tuns64:
11581180
result = (d_uns64)(value) >> count;
11591181
break;
1182+
#endif
11601183

11611184
default:
11621185
assert(0);

dmd2/expression.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2870,6 +2870,10 @@ void IntegerExp::normalize()
28702870
case Tuns32: value = (d_uns32) value; break;
28712871
case Tint64: value = (d_int64) value; break;
28722872
case Tuns64: value = (d_uns64) value; break;
2873+
#if WANT_CENT
2874+
case Tint128: value = (d_int128) value; break;
2875+
case Tuns128: value = (d_uns128) value; break;
2876+
#endif
28732877
case Tpointer:
28742878
if (Target::ptrsize == 4)
28752879
value = (d_uns32) value;

dmd2/globals.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#endif
1818

1919
#include "longdouble.h"
20+
#include "int128.h"
2021
#include "outbuffer.h"
2122

2223
// Can't include arraytypes.h here, need to declare these directly.
@@ -280,6 +281,11 @@ struct Global
280281

281282
extern Global global;
282283

284+
#if WANT_CENT
285+
typedef uint128_t dinteger_t;
286+
typedef int128_t sinteger_t;
287+
typedef uint128_t uinteger_t;
288+
#else
283289
// Because int64_t and friends may be any integral type of the
284290
// correct size, we have to explicitly ask for the correct
285291
// integer type to get the correct mangling with ddmd
@@ -296,6 +302,7 @@ typedef unsigned long long dinteger_t;
296302
typedef long long sinteger_t;
297303
typedef unsigned long long uinteger_t;
298304
#endif
305+
#endif
299306

300307
typedef int8_t d_int8;
301308
typedef uint8_t d_uns8;
@@ -305,6 +312,10 @@ typedef int32_t d_int32;
305312
typedef uint32_t d_uns32;
306313
typedef int64_t d_int64;
307314
typedef uint64_t d_uns64;
315+
#if WANT_CENT
316+
typedef int128_t d_int128;
317+
typedef uint128_t d_uns128;
318+
#endif
308319

309320
typedef float d_float32;
310321
typedef double d_float64;

dmd2/hdrgen.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2121,6 +2121,24 @@ class PrettyPrintVisitor : public Visitor
21212121
buf->printf("%lluLU", v);
21222122
break;
21232123

2124+
#if WANT_CENT
2125+
case Tint128: {
2126+
char buffer[42];
2127+
sprintf_i128(buffer, v);
2128+
assert(strlen(buffer) < sizeof(buffer));
2129+
buf->writestring(buffer);
2130+
}
2131+
break;
2132+
2133+
case Tuns128: {
2134+
char buffer[42];
2135+
sprintf_u128(buffer, v);
2136+
assert(strlen(buffer) < sizeof(buffer));
2137+
buf->writestring(buffer);
2138+
}
2139+
break;
2140+
#endif
2141+
21242142
case Tbool:
21252143
buf->writestring(v ? "true" : "false");
21262144
break;

0 commit comments

Comments
 (0)