aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/c_type.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/c_type.c')
-rw-r--r--src/c_type.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/src/c_type.c b/src/c_type.c
index ef4770d..c34d7df 100644
--- a/src/c_type.c
+++ b/src/c_type.c
@@ -224,7 +224,7 @@ completetype(internstr name, int id, TypeData *td)
assert(tagtypetags[id] == name && "bad redefn");
else
tagtypetags[id] = name;
- return mktype(td->t, .flag = td->flag, .dat = interntd(td));
+ return mktype(td->t, .dat = interntd(td));
}
Type
@@ -312,9 +312,24 @@ cvtarith(Type a, Type b)
if (!isarith(a) || !isarith(b)) return none;
if (a.t == TYENUM) a = typechild(a);
if (b.t == TYENUM) b = typechild(b);
+ if (iscomplex(a)) {
+ if (iscomplex(b)) {
+ /* when both are complex, choose type with greatest rank */
+ /* enumeration order of type tags reflects arithmetic type rank */
+ return a.t > b.t ? a : b;
+ }
+ /* complex float + double -> complex double */
+ if (a.t - TYCOMPLEXF + TYFLOAT < b.t)
+ a.t = b.t + TYCOMPLEXF - TYFLOAT;
+ return a;
+ } else if (iscomplex(b)) {
+ /* double + complex float -> complex double */
+ if (b.t - TYCOMPLEXF + TYFLOAT < a.t)
+ b.t = a.t + TYCOMPLEXF - TYFLOAT;
+ return b;
+ }
if (isflt(a) || isflt(b)) {
/* when one type is float, choose type with greatest rank */
- /* enumeration order of type tags reflects arithmetic type rank */
return a.t > b.t ? a : b;
}
a.t = intpromote(a.t);
@@ -340,4 +355,23 @@ cvtarith(Type a, Type b)
}
}
+/* transform 'complex T' -> struct 'complex T' { T real, imag; } */
+Type
+complex2struct(Type t)
+{
+ assert(iscomplex(t));
+ static Type cache[3];
+ if (cache[t.t-TYCOMPLEXF].t) return cache[t.t-TYCOMPLEXF];
+ static const char *names[] = {
+ "complex$float", "complex$double", "complex$longdouble"
+ };
+ Type base = mktype(t.t - TYCOMPLEXF + TYFLOAT);
+ return cache[t.t-TYCOMPLEXF] = mktagtype(intern(names[t.t-TYCOMPLEXF]), &(TypeData){
+ TYSTRUCT, .fld = (NamedField [2]){
+ {intern("real"), {.t = base, .off = 0}},
+ {intern("imag"), {.t = base, .off = typesize(base)}},
+ }, .nmemb = 2, .align = typealign(base), .siz = typesize(base) * 2
+ });
+}
+
/* vim:set ts=3 sw=3 expandtab: */