Skip to content

Commit

Permalink
strict-alias rewrite: make C typedefs more strict to improve error ch…
Browse files Browse the repository at this point in the history
…ecking in C functions. Strengthen alias semantics to compensate.
  • Loading branch information
FeepingCreature committed Sep 24, 2013
1 parent f7bdcca commit 638425d
Show file tree
Hide file tree
Showing 13 changed files with 106 additions and 35 deletions.
42 changes: 31 additions & 11 deletions ast/aliasing.d
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ final class MValueAlias : ExprAlias, MValue {

class _TypeAlias : Named, IType, SelfAdding, Dwarf2Encodable {
IType base;
bool strict;
// strictFrom: can't implicitly cast TA to base
// strictTo: can't implicitly cast base to TA
bool strictFrom, strictTo;
string name;
override {
bool isComplete() {
Expand All @@ -114,14 +116,18 @@ class _TypeAlias : Named, IType, SelfAdding, Dwarf2Encodable {
string toString() {
if (alreadyRecursing(this)) return qformat("recursive ", name);
pushRecurse(this); scope(exit) popRecurse();
return Format(name, ":", base);
string strict;
if (strictFrom && strictTo) strict = "strict ";
else if (strictFrom) strict = "strict(from) ";
else if (strictTo) strict = "strict(to) ";
return Format(strict, name, ":", base);
}
int opEquals(IType ty) {
if (ty is this) return true;
if (alreadyRecursing(this, ty)) return true; // break loop
pushRecurse(this, ty); scope(exit) popRecurse();
auto ta2 = fastcast!(TypeAlias) (ty);
if (strict) {
if (strictFrom || strictTo) {
if (!ta2) return false;
return name == ta2.name && base == ta2.base;
}
Expand All @@ -130,7 +136,7 @@ class _TypeAlias : Named, IType, SelfAdding, Dwarf2Encodable {
// then fall back to resolved check
return resolveType(base).opEquals(resolveType(ty));
}
IType proxyType() { if (strict) return null; return base; }
IType proxyType() { if (strictFrom || strictTo) return null; return base; }
bool canEncode() {
auto d2e = fastcast!(Dwarf2Encodable)(resolveType(base));
return d2e && d2e.canEncode();
Expand All @@ -143,7 +149,7 @@ class _TypeAlias : Named, IType, SelfAdding, Dwarf2Encodable {

final class TypeAlias : _TypeAlias {
static const isFinal = true;
mixin This!("base, name, strict = false"[]);
mixin This!("base, name, strictFrom = false, strictTo = false"[]);
}

static this() {
Expand All @@ -168,8 +174,22 @@ redo:
TypeAlias ta;
Object obj;

bool strict, raw;
if (t2.accept("strict"[])) strict = true;
bool strictFrom, strictTo, raw;
if (t2.accept("strict")) {
auto t3 = t2;
if (t3.accept("(") && t3.accept("from") && t3.accept(")")) {
t2 = t3;
strictFrom = true;
} else {
t3 = t2;
if (t3.accept("(") && t3.accept("to") && t3.accept(")")) {
t2 = t3;
strictTo = true;
} else {
strictFrom = strictTo = true;
}
}
}
if (t2.accept("raw"[])) raw = true;

if (!(t2.gotIdentifier(id) &&
Expand All @@ -187,7 +207,7 @@ redo:

if (rest(t3, "type"[], &ty) && gotTerm()) {
if (auto tup = resolveTup(ty, true)) ty = tup;
ta = fastalloc!(TypeAlias)(ty, id, strict);
ta = fastalloc!(TypeAlias)(ty, id, strictFrom, strictTo);
t2 = t3;
} else {
t3 = t2;
Expand Down Expand Up @@ -219,7 +239,7 @@ redo:
text = t2;
auto cv = fastcast!(CValue)~ ex, mv = fastcast!(MValue)~ ex, lv = fastcast!(LValue)~ ex;
if (ex) {
if (strict) t2.failparse("no such thing as strict expr-alias"[]);
if (strictFrom || strictTo) t2.failparse("no such thing as strict expr-alias"[]);
ExprAlias res;
if (lv) res = fastalloc!(LValueAlias)(lv, id);
else if (mv) res = fastalloc!(MValueAlias)(mv, id);
Expand All @@ -240,10 +260,10 @@ mixin DefaultParser!(gotAlias, "tree.toplevel.alias"[], null, "alias"[]);

import ast.casting;
static this() {
// type alias implicitly casts to parent type
// type alias implicitly casts to parent type (if not strictFrom)
implicits ~= delegate Expr(Expr ex) {
auto ta = fastcast!(TypeAlias) (ex.valueType());
if (!ta || !ta.strict) return null;
if (!ta || ta.strictFrom) return null;
return reinterpret_cast(ta.base, ex);
};
}
2 changes: 1 addition & 1 deletion ast/base.d
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ bool isWindoze() {
}

bool isARM() {
return !!platform_prefix.startsWith("arm-"[]);
return !!platform_prefix.startsWith("arm"[]);
}

version(Windows) static this() { platform_prefix = "i686-mingw32-"; }
Expand Down
18 changes: 16 additions & 2 deletions ast/c_bind.d
Original file line number Diff line number Diff line change
Expand Up @@ -906,7 +906,21 @@ src_cleanup_redo: // count, then copy
}

typedef_done:
auto ta = fastalloc!(TypeAlias)(target, name);
bool strict;
auto rt = resolveTypeHard(target, true);
// strict |= test(Single!(Void) == rt);
auto test = rt;
while (true) {
if (auto pt = fastcast!(Pointer)(test)) {
test = resolveTypeHard(pt.target, true);
continue;
}
break;
}
auto lt = fastcast!(LateType)(test);
strict |= lt && !lt.me;
// logln(name, " strict? ", strict, " on ", rt);
auto ta = fastalloc!(TypeAlias)(target, name, false, strict);
// logln("add ", name, " = ", ta);
(*cachep)[name] = ta;
continue;
Expand Down Expand Up @@ -1037,7 +1051,7 @@ void performCImport(string name) {
}
string filename = findfile(name);
string extra;
if (!isARM) extra = " -m32";
if (!isARM()) extra = " -m32";
synchronized(defines_sync) {
extra ~= (defines /map/ (string s) { return " -D"~s; }).join("");
if (name in prepend) extra ~= " "~(prepend[name] /map/ &findfile).join(" ");
Expand Down
2 changes: 1 addition & 1 deletion ast/funcall.d
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ bool matchedCallWith(Expr arg, Argument[] params, ref Expr[] res, out Statement[
else {
try matches = gotImplicitCast(ex, type, (IType it) {
tried ~= it;
// logln(" !! is ", it, " == ", type, "? ", test(it == type));
// logln(ex, " !! is ", it, " == ", type, "? ", test(it == type));
return test(it == type);
}, false, &score);
catch (Exception ex) {
Expand Down
4 changes: 2 additions & 2 deletions ast/index.d
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class SAIndexExpr : Expr {
import ast.tuples, ast.tuple_access;
void setupIndex() {
defineOp("index", delegate Expr(Expr e1, Expr e2) {
auto e1v = resolveType(e1.valueType()), e2v = resolveType(e2.valueType());
auto e1v = resolveTypeHard(e1.valueType()), e2v = resolveType(e2.valueType());
if (!fastcast!(StaticArray) (e1v) && !fastcast!(Array) (e1v) && !fastcast!(ExtArray) (e1v) && !fastcast!(Pointer) (e1v))
return null;
IType[] tried;
Expand All @@ -49,7 +49,7 @@ void setupIndex() {
}
if (fastcast!(Pointer)~ e1v)
return fastalloc!(DerefExpr)(lookupOp("+", e1, e2));
return getIndex(e1, e2);
return getIndex(reinterpret_cast(e1v, e1), e2);
});
defineOp("index", delegate Expr(Expr e1, Expr e2) {
auto e1v = resolveType(e1.valueType()), e2v = resolveType(e2.valueType());
Expand Down
5 changes: 3 additions & 2 deletions ast/intrinsic.d
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ void setupSysmods() {
string src = `
module sys;
pragma(lib, "m");
alias strict bool = int;
// can't treat int as bool, can treat bool as int
alias strict(to) bool = int;
alias true = bool:1;
alias false = bool:0;
alias null = void*:0;
Expand Down Expand Up @@ -618,7 +619,7 @@ void setupSysmods() {
memcpy(res, ptr, length);
return res;
}
int fastfloor(float f) { return (int:f) - (*int*:&f) >> 31; }
int fastfloor(float f) { return (int:f) - (*int*:&f) >>> 31; }
void fastfloor3f(vec3f v, vec3i* res) {
if (v.x > int.max || v.y > int.max || v.z > int.max) {
fail("fastfloor3f int conversion requested but there is actually no int equivalent for $v");
Expand Down
1 change: 1 addition & 0 deletions ast/stringex.d
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Object gotStringEx(ref string text, ParseCb cont, ParseCb rest) {
ubyte[] buf;
void flush() { if (!buf) return; res.addArray(fastalloc!(StringExpr)(cast(string) buf)); buf = null; }
ubyte xtake() {
if (!str.length) fail;
auto res = (cast(ubyte[]) str)[0];
str = cast(string) (cast(ubyte[]) str)[1..$];
return res;
Expand Down
15 changes: 12 additions & 3 deletions ast/type_info.d
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@ mixin DefaultParser!(gotParamTypes, "type.fun_param_type"[], "52"[], "ParamTypes
import ast.conditionals;
Object gotTypesEqual(ref string text, ParseCb cont, ParseCb rest) {
IType ty;
bool weak;
auto t2 = text;
if (t2.accept("weak")) weak = true;
if (!t2.accept("("[]))
t2.failparse("Opening parenthesis expected"[]);
setupStaticBoolLits;
Expand All @@ -138,9 +140,16 @@ Object gotTypesEqual(ref string text, ParseCb cont, ParseCb rest) {
t2.failparse("Comma expected"[]);
if (!rest(t2, "type"[], &ty2))
t2.failparse("Expect type parameter for types-equal! "[]);
if (!ty) ty = resolveType(ty2);
else if (ty != resolveType(ty2))
res = fastcast!(Object)(False);
if (weak) {
// if weak, then hard. IRONY
if (!ty) ty = resolveTypeHard(ty2);
else if (ty != resolveTypeHard(ty2))
res = fastcast!(Object)(False);
} else {
if (!ty) ty = resolveType(ty2);
else if (ty != resolveType(ty2))
res = fastcast!(Object)(False);
}
}
if (!res) res = fastcast!(Object)(True);
text = t2;
Expand Down
7 changes: 6 additions & 1 deletion ast/types.d
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,16 @@ interface ExternAware {
import tools.log;
// Strips out type-alias and the like
IType resolvecache;
extern(C) IType ast_types_resolveType(IType t, bool carefully = false);
extern(C) IType ast_types_resolveType(IType t, bool carefully = false, bool hard = false);
IType resolveType(IType t, bool carefully = false) {
return ast_types_resolveType(t, carefully);
}

// resolve for semantics, with no heed paid to strictness
IType resolveTypeHard(IType t, bool carefully = false) {
return ast_types_resolveType(t, carefully, true);
}

template TypeDefaults(bool OPEQUALS = true) {
static if (OPEQUALS) {
int opEquals(IType ty) {
Expand Down
36 changes: 28 additions & 8 deletions fcc.d
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,32 @@ alias ast.c_bind.readback readback;
import ast.parse, ast.namespace, ast.scopes;
// from ast.types
pragma(set_attribute, ast_types_resolveType, externally_visible);
extern(C) IType ast_types_resolveType(IType t, bool carefully = false) {
if (t is resolvecache) return t; // shortcut for repeated call
extern(C) IType ast_types_resolveType(IType t, bool carefully = false, bool hard = false) {
if (!hard && t is resolvecache) return t; // shortcut for repeated call
while (t) {
// avoid poking LateTypes if not needed.
if (carefully) if (auto lt = fastcast!(LateType)(t)) return lt;
if (auto tp = t.proxyType()) {
t = tp;
continue;
}
if (hard) {
if (auto ta = fastcast!(TypeAlias)(t)) {
assert(ta.strictFrom || ta.strictTo);
t = ta.base;
continue;
}
if (auto poi = fastcast!(Pointer)(t)) {
auto br = resolveTypeHard(poi.target, carefully);
if (br !is poi.target) {
t = fastalloc!(Pointer)(br);
continue;
}
}
}
break;
}
resolvecache = t;
resolvecache = hard?null:t;
return t;
}

Expand Down Expand Up @@ -375,15 +389,18 @@ void ast_math_constr() {
// logln("subst with ", res);
return res;
}
if (!isWindoze()) {
// NO
// fastfloor is fast
// floorf is slow >.<
/*if (!isWindoze()) {
foldopt ~= &substfun /fix/ stuple(1, (Function fun, Module mod) {
return fun.name == "fastfloor" && mod is sysmod;
}, delegate Expr(Expr[] args) {
return fastalloc!(FPAsInt)(lookupOp("+",
fastalloc!(IntrinsicExpr)("llvm.floor.f32"[], args, Single!(Float)),
fastalloc!(FloatExpr)(0.25)));
});
}
}*/
foldopt ~= &substfun /fix/ stuple(2, (Function fun, Module mod) {
return (fun.name == "copysignf" || fun.name == "[wrap]copysignf") && fun.extern_c;
}, delegate Expr(Expr[] args) {
Expand All @@ -405,6 +422,7 @@ void ast_math_constr() {
});
}
addCIntrin(1, "sqrtf" , Single!(Float), "llvm.sqrt.f32");
addCIntrin(1, "sqrt" , Single!(Double), "llvm.sqrt.f64");
// do in software, intrinsic is slow
// addCIntrin(1, "sinf" , Single!(Float), "llvm.sin.f32");
// addCIntrin(1, "cosf" , Single!(Float), "llvm.cos.f32");
Expand All @@ -422,7 +440,7 @@ void ast_math_constr() {
bool isDouble(IType it) { return test(Single!(Double) == it); }
bool isLong(IType it) { return test(Single!(Long) == it); }
bool isPointer(IType it) { return test(fastcast!(Pointer)~ it); }
bool isBool(IType it) { if (!sysmod) return false; return test(it == fastcast!(IType)(sysmod.lookup("bool"))); }
bool isBool(IType it) { if (!sysmod) return false; return exactlyEquals(it, fastcast!(IType)(sysmod.lookup("bool"))); }
Expr handleIntMath(string op, Expr ex1, Expr ex2) {
bool b1 = isBool(ex1.valueType()), b2 = isBool(ex2.valueType());
Expr i1 = ex1, i2 = ex2, u1 = ex1, u2 = ex2;
Expand Down Expand Up @@ -596,7 +614,7 @@ Object gotAsType(ref string text, ParseCb cont, ParseCb rest) {
} else {
if (!text.gotIdentifier(ident)) text.failparse("Identifier expected for as_type");
}
auto ta = fastalloc!(TypeAlias)(cast(IType) null, ident, false);
auto ta = fastalloc!(TypeAlias)(cast(IType) null, ident);
{
auto as_type_ns = fastalloc!(MiniNamespace)("as_type_ident_override");
as_type_ns.sup = namespace();
Expand Down Expand Up @@ -1478,7 +1496,9 @@ int incbuild(string start,
auto file = mod.name.undo();
string obj, asmf;
file.translate(obj, asmf);
if (file == "sys.nt") file = "fcc.exe"; // contained within
if (file == "sys.nt")
if (isWindoze()) file = "fcc.exe"; // contained within
else file = "fcc";
file = findfile(file);

auto start2 = findfile(start);
Expand Down
4 changes: 2 additions & 2 deletions llvmtype.d
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
module llvmtype;

import casts, llvmfile, quickformat;
import ast.base, ast.int_literal, ast.types, ast.pointer, ast.static_arrays, ast.arrays, ast.fun;
import ast.base, ast.int_literal, ast.types, ast.pointer, ast.static_arrays, ast.arrays, ast.fun, ast.aliasing;
import tools.log, tools.base: strip, between;
import parseBase: startsWith, endsWith;

pragma(set_attribute, typeToLLVM, externally_visible);
extern(C) string typeToLLVM(IType it, bool subst = false) {
// logln("typeToLLVM ", it);
if (!it) fail;
auto rt = resolveType(it);
auto rt = resolveTypeHard(it);
if (rt == Single!(Pointer, Single!(Void))) return "i8*";
if (subst) { // asked to substitute a simpler type
it = rt;
Expand Down
2 changes: 1 addition & 1 deletion std/lib/glfw3.nt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ platform(!*-mingw32) {

defmode GLFW "prefix GLFW_ prefix glfw";

static if (types-equal(GLFWwindow, void)) {
static if (types-equal weak (GLFWwindow, void)) {
alias GLFWWinType = GLFWwindow*;
} else {
alias GLFWWinType = GLFWwindow;
Expand Down
3 changes: 2 additions & 1 deletion std/math.nt
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ float sin(float x) {

// wrap to -PI .. PI
x += PI; // wrap to 0..2PI
x -= 2*PI*floorf(x/(2*PI));
// x -= 2*PI*floorf(x/(2*PI));
x -= 2*PI*fastfloor(x/(2*PI));
x -= PI; // and back

float y = B * x + C * x * abs x;
Expand Down

0 comments on commit 638425d

Please sign in to comment.