Skip to content

Instantly share code, notes, and snippets.

@dnadlinger
Forked from yebblies/fuzzvarargs.d
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dnadlinger/afcb826282f45ba76f92 to your computer and use it in GitHub Desktop.
Save dnadlinger/afcb826282f45ba76f92 to your computer and use it in GitHub Desktop.
import std.stdio;
import std.process;
import std.random;
import std.exception;
import std.uuid;
import std.range;
import std.string;
// x86_32 - bug with empty struct - fixed
// x86_64 posix - bug with empty struct (https://issues.dlang.org/show_bug.cgi?id=13956)
// x86_64 posix - bug with float+double struct (https://issues.dlang.org/show_bug.cgi?id=13955)
// x86_64 posix - bug with double+char struct (not reduced, probably similar)
// x86_64 posix - more?
abstract
class Value
{
// void writeCheckCpp(ref File f, string prefix, size_t i);
// void writeCheckD(ref File f, string prefix, size_t i);
void writeStructCpp(ref File f);
void writeStructD(ref File f);
void writeMemberCpp(ref File f, size_t i);
void writeMemberD(ref File f, size_t i);
void writeParamD(ref File f, size_t i);
void writeParamPromotedD(ref File f, size_t i);
void writeVarD(ref File f, size_t i, bool value);
void writeVarPromotedD(ref File f, size_t i, bool value);
void writeTypeD(ref File f, size_t i);
void writeTypePromotedD(ref File f, size_t i);
void writeInitD(ref File f);
void writeParamCpp(ref File f, size_t i);
void writeParamPromotedCpp(ref File f, size_t i);
void writeVarPromotedCpp(ref File f, size_t i);
void writeTypePromotedCpp(ref File f, size_t i);
}
class Struct : Value
{
string name;
Value[] members;
this(string name)
{
this.name = name;
}
// override void writeCheckCpp(ref File f, string prefix, size_t i)
// {
// auto m = "val_%d".format(i);
// f.writefln("\tprintf(\"%s: %%p\\n\", (char*)&%s.%s - (char*)&%s);", m, prefix, m, prefix);
// }
// override void writeCheckD(ref File f, string prefix, size_t i)
// {
// auto m = "val_%d".format(i);
// f.writefln("\tprintf(\"%s: %%p\\n\", cast(char*)&%s.%s - cast(char*)&%s);", m, prefix, m, prefix);
// }
override void writeStructCpp(ref File f)
{
foreach(i, m; members)
m.writeStructCpp(f);
f.writefln("struct %s {", name);
foreach(i, m; members)
m.writeMemberCpp(f, i);
f.writefln("};");
f.writefln("");
}
override void writeStructD(ref File f)
{
foreach(i, m; members)
m.writeStructD(f);
f.writefln("struct %s {", name);
foreach(i, m; members)
m.writeMemberD(f, i);
f.writefln("}");
f.writefln("");
}
override void writeMemberCpp(ref File f, size_t i)
{
auto mname = "val_%d".format(i);
f.writefln("\t%s %s;", name, mname);
}
override void writeMemberD(ref File f, size_t i)
{
auto mname = "val_%d".format(i);
f.writefln("\t%s %s;", name, mname);
}
override void writeParamD(ref File f, size_t i)
{
if (i)
f.write(", ");
f.writef("%s arg%d", name, i);
}
override void writeParamPromotedD(ref File f, size_t i)
{
if (i)
f.write(", ");
f.writef("%s arg%d", name, i);
}
override void writeParamCpp(ref File f, size_t i)
{
if (i)
f.write(", ");
f.writef("%s arg%d", name, i);
}
override void writeParamPromotedCpp(ref File f, size_t i)
{
if (i)
f.write(", ");
f.writef("%s arg%d", name, i);
}
override void writeTypeD(ref File f, size_t i)
{
f.writef("%s", name);
}
override void writeTypePromotedD(ref File f, size_t i)
{
f.writef("%s", name);
}
override void writeTypePromotedCpp(ref File f, size_t i)
{
f.writef("%s", name);
}
override void writeVarD(ref File f, size_t i, bool value)
{
if (value)
{
f.writef(" %s arg%d = ", name, i);
writeInitD(f);
f.writeln(";");
}
else
f.writefln(" %s arg%d;", name, i);
}
override void writeVarPromotedD(ref File f, size_t i, bool value)
{
writeVarD(f, i, value);
}
override void writeVarPromotedCpp(ref File f, size_t i)
{
f.writefln(" %s arg%d;", name, i);
}
override void writeInitD(ref File f)
{
f.writef("%s(", name);
foreach(i, m; members)
{
if (i)
f.write(", ");
m.writeInitD(f);
}
f.writef(")");
}
}
class Basic : Value
{
string dname;
string cname;
string ival;
string dprom;
string cprom;
this(string dname, string cname, string ival, string dprom, string cprom)
{
this.dname = dname;
this.cname = cname;
this.ival = ival;
this.dprom = dprom;
this.cprom = cprom;
}
// override void writeCheckCpp(ref File f, string prefix, size_t i)
// {
// auto m = "val_%d".format(i);
// f.writefln("\tprintf(\"%s: %%p\\n\", (char*)&%s.%s - (char*)&%s);", m, prefix, m, prefix);
// }
// override void writeCheckD(ref File f, string prefix, size_t i)
// {
// auto m = "val_%d".format(i);
// f.writefln("\tprintf(\"%s: %%p\\n\", cast(char*)&%s.%s - cast(char*)&%s);", m, prefix, m, prefix);
// }
override void writeStructCpp(ref File f)
{
}
override void writeStructD(ref File f)
{
}
override void writeMemberCpp(ref File f, size_t i)
{
auto mname = "val_%d".format(i);
f.writefln("\t%s %s;", cname, mname);
}
override void writeMemberD(ref File f, size_t i)
{
auto mname = "val_%d".format(i);
f.writefln("\t%s %s;", dname, mname);
}
override void writeParamD(ref File f, size_t i)
{
if (i)
f.write(", ");
f.writef("%s arg%d", dname, i);
}
override void writeParamPromotedD(ref File f, size_t i)
{
if (i)
f.write(", ");
f.writef("%s arg%d", dprom, i);
}
override void writeParamCpp(ref File f, size_t i)
{
if (i)
f.write(", ");
f.writef("%s arg%d", cname, i);
}
override void writeParamPromotedCpp(ref File f, size_t i)
{
if (i)
f.write(", ");
f.writef("%s arg%d", cprom, i);
}
override void writeTypeD(ref File f, size_t i)
{
f.writef("%s", dname);
}
override void writeTypePromotedD(ref File f, size_t i)
{
f.writef("%s", dprom);
}
override void writeTypePromotedCpp(ref File f, size_t i)
{
f.writef("%s", cprom);
}
override void writeVarD(ref File f, size_t i, bool value)
{
if (value)
f.writefln(" %s arg%d = %s;", dname, i, ival);
else
f.writefln(" %s arg%d;", dname, i);
}
override void writeVarPromotedD(ref File f, size_t i, bool value)
{
if (value)
f.writefln(" %s arg%d = %s;", dprom, i, ival);
else
f.writefln(" %s arg%d;", dprom, i);
}
override void writeVarPromotedCpp(ref File f, size_t i)
{
f.writefln(" %s arg%d;", cprom, i);
}
override void writeInitD(ref File f)
{
f.writef("%s", ival);
}
}
version(D_LP64)
{
static immutable string[5][] basics =
[
["byte", "signed char", "99", "int", "int"],
["ubyte", "unsigned char", "100", "int", "int"],
["char", "char", "101", "int", "int"],
["int", "int", "102", "int", "int"],
["uint", "unsigned", "103", "uint", "unsigned"],
["long", "long", "104", "long", "long"],
["ulong", "unsigned long", "105", "ulong", "unsigned long"],
["float", "float", "0", "double", "double"],
["double", "double", "0", "double", "double"],
["real", "long double", "0", "real", "long double"],
["bool", "bool", "false", "int", "int"],
["void*", "void*", "null", "void*", "void*"],
];
}
else version(X86)
{
static immutable string[5][] basics =
[
["byte", "signed char", "99", "int", "int"],
["ubyte", "unsigned char", "100", "int", "int"],
["char", "char", "101", "int", "int"],
["int", "int", "102", "int", "int"],
["uint", "unsigned", "103", "uint", "unsigned"],
["long", "long long", "104", "long", "long long"],
["ulong", "unsigned long long", "105", "ulong", "unsigned long long"],
["float", "float", "0", "double", "double"],
["double", "double", "0", "double", "double"],
["real", "long double", "0", "real", "long double"],
["bool", "bool", "false", "int", "int"],
["void*", "void*", "null", "void*", "void*"],
];
}
Value genValue(bool allowstruct)
{
auto p = uniform(0, basics.length+allowstruct);
if (p == basics.length)
{
static int id;
return genStruct("S%d".format(id++));
}
else
{
return new Basic(basics[p][0], basics[p][1], basics[p][2], basics[p][3], basics[p][4]);
}
}
Struct genStruct(string name)
{
auto s = new Struct(name);
// modify here to change the number of struct members
foreach(i; 0..uniform(0, 3))
{
s.members ~= genValue(false);
}
return s;
}
void main()
{
while(true)
{
auto testname = "test_vararg_" ~ randomUUID().toString().replace("-", "_");
Value[] values;
// modify here to change the number of parameters
values.length = uniform(2, 20);
foreach(ref v; values)
v = genValue(true);
// modify here to change the number of named parameters
auto namedArgs = values.length; //uniform(1, values.length);
auto df = File(testname ~ "_d.d", "wb");
auto cf = File(testname ~ "_cpp.cpp", "wb");
df.writeln("import core.stdc.stdarg;");
df.writeln();
cf.writeln("#include <stdarg.h>");
cf.writeln();
foreach(v; values)
{
v.writeStructCpp(cf);
v.writeStructD(df);
}
cf.write("void checkValues(");
foreach(i, v; values)
{
if (i < namedArgs)
v.writeParamCpp(cf, i);
else
v.writeParamPromotedCpp(cf, i);
}
cf.writeln(");");
// cf.writeln("int main(void) {");
// cf.writeln("\tTest s;");
// foreach(i, m; s.members)
// m.writeCheckCpp(cf, "s", i);
// cf.writefln("printf(\"size: %%d\\n\", sizeof(s));");
// cf.writeln("\treturn 0;");
// cf.writeln("}");
cf.write("void cppvararg(");
foreach(i, v; values[0..namedArgs])
v.writeParamCpp(cf, i);
if (values.length != namedArgs)
cf.writeln(", ...)");
else
cf.writeln(")");
cf.writeln("{");
foreach(i, v; values)
{
if (i < namedArgs)
continue;
v.writeVarPromotedCpp(cf, i);
}
if (values.length != namedArgs)
{
cf.writeln(" va_list va;");
cf.writefln(" va_start(va, arg%d);", namedArgs-1);
}
foreach(i, v; values)
{
if (i < namedArgs)
continue;
cf.writef(" arg%d = va_arg(va, ", i);
v.writeTypePromotedCpp(cf, i);
cf.writefln(");");
}
if (values.length != namedArgs)
{
cf.writeln(" va_end(va);");
}
cf.write(" checkValues(");
foreach(i, v; values)
{
if (i)
cf.write(", ");
cf.writef("arg%d", i);
}
cf.writeln(");");
cf.writeln("}");
cf.writeln();
/////////////////////////////////////////////
df.write("extern(C++) void cppvararg(");
foreach(i, v; values[0..namedArgs])
v.writeParamD(df, i);
if (values.length > namedArgs)
df.writeln(", ...);");
else
df.writeln(");");
/////////////////////////////////////////////
df.write("extern(C++) void dvararg(");
foreach(i, v; values[0..namedArgs])
v.writeParamD(df, i);
if (values.length != namedArgs)
df.writeln(", ...)");
else
df.writeln(")");
df.writeln("{");
foreach(i, v; values)
{
if (i < namedArgs)
continue;
v.writeVarPromotedD(df, i, false);
}
if (values.length != namedArgs)
{
df.writeln(" va_list va;");
version(X86)
{
df.writefln(" va_start(va, arg%d);", namedArgs-1);
}
else version (Windows)
{
static assert(0);
}
else version(X86_64)
{
df.writefln(" va_start(va, __va_argsave);", namedArgs-1);
}
else
static assert(0);
}
foreach(i, v; values)
{
if (i < namedArgs)
continue;
df.write(" va_arg!(");
v.writeTypePromotedD(df, i);
df.writefln(")(va, arg%d);", i);
}
if (values.length != namedArgs)
{
df.writeln(" va_end(va);");
}
df.write(" checkValues(");
foreach(i, v; values)
{
if (i)
df.write(", ");
df.writef("arg%d", i);
}
df.writeln(");");
df.writeln("}");
df.writeln();
/////////////////////////////////////////////
df.write("extern(C++) void checkValues(");
foreach(i, v; values)
{
if (i < namedArgs)
v.writeParamD(df, i);
else
v.writeParamPromotedD(df, i);
}
df.writeln(")");
df.writeln("{");
foreach(i, v; values)
{
df.writef(" assert(arg%d == ", i);
v.writeInitD(df);
df.writeln(");");
}
df.writeln("}");
df.writeln();
/////////////////////////////////////////////
df.writeln("void main()");
df.writeln("{");
foreach(i, v; values)
{
v.writeVarD(df, i, true);
}
df.write(" dvararg(");
foreach(i, v; values)
{
if (i)
df.write(", ");
df.writef("arg%d", i);
}
df.writeln(");");
df.write(" cppvararg(");
foreach(i, v; values)
{
if (i)
df.write(", ");
df.writef("arg%d", i);
}
df.writeln(");");
df.writeln("}");
df.writeln();
/////////////////////////////////////////////
// df.writeln("\tTest s;");
// foreach(i, m; s.members)
// m.writeCheckD(df, "s", i);
// df.writefln("printf(\"size: %%d\\n\", s.sizeof);");
// df.writeln("}");
// df.writeln("void main() {");
// df.writeln("\tTest s;");
// foreach(i, m; s.members)
// m.writeCheckD(df, "s", i);
// df.writefln("printf(\"size: %%d\\n\", s.sizeof);");
// df.writeln("}");
cf.close();
df.close();
version(Windows)
{
writeln("%s_d.d".format(testname));
auto dmcres = executeShell("dmc -g -c %s_cpp.cpp".format(testname));
writeln(dmcres.output);
enforce(dmcres.status == 0);
auto dmdres = executeShell("dmd -g %s_d.d %s_cpp.obj".format(testname, testname));
writeln(dmdres.output);
enforce(dmdres.status == 0);
auto dout = executeShell("%s_d".format(testname));
}
else
{
writeln("%s_d.d".format(testname));
auto gppres = executeShell("g++ -g %s_cpp.cpp -c -o %s_cpp.o".format(testname, testname));
writeln(gppres.output);
enforce(gppres.status == 0);
auto dmdres = executeShell("CC=g++ ./dmd -gc %s_d.d %s_cpp.o".format(testname, testname));
writeln(dmdres.output);
enforce(dmdres.status == 0);
auto dout = executeShell("./%s_d".format(testname));
}
writeln(dout.output);
enforce(dout.status == 0);
import std.file;
remove("%s_cpp.cpp".format(testname));
remove("%s_cpp.o".format(testname));
remove("%s_d.d".format(testname));
remove("%s_d.o".format(testname));
remove("%s_d".format(testname));
}
}
// extern(C++) void dvarArg(int arg0, ...)
// {
// long arg1;
// bool arg2;
// va_list va;
// va_start(va, arg0);
// va_arg!long(va, arg1);
// va_arg!bool(va, arg2);
// va_end(va);
// checkValues(arg0, arg1, arg2);
// }
// extern(C++) void checkValues(int arg0, long arg1, bool arg2)
// {
// assert(arg0 == 3);
// assert(arg1 == 7);
// assert(arg2 == false);
// }
// void main()
// {
// int arg0 = 3;
// long arg1 = 7;
// bool arg2 = false;
// dvarArg(arg0, arg1, arg2);
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment