# HG changeset patch # User lindquist # Date 1194845566 -3600 # Node ID 61615fa859401584a42dc9ae329fb7611b1fa6da # Parent 08508eebbb3e13ef5c9e26d19a433409c25e6ed4 [svn r98] Added support for std.c.stdlib.alloca via pragma(LLVM_internal, "alloca"). Added support for array .sort and .reverse properties. Fixed some bugs with pointer arithmetic. Disabled some DMD AST optimizations that was messing things up, destroying valuable information. Added a KDevelop project file, this is what I use for coding LLVMDC now :) Other minor stuff. diff -r 08508eebbb3e -r 61615fa85940 demos/ray.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demos/ray.d Mon Nov 12 06:32:46 2007 +0100 @@ -0,0 +1,96 @@ +//import std.stdio, std.math, std.string; +//import tools.base; + +double delta; +static this() { delta=sqrt(real.epsilon); } + +struct Vec { + double x, y, z; + Vec opAdd(ref Vec other) { return Vec(x+other.x, y+other.y, z+other.z); } + Vec opSub(ref Vec other) { return Vec(x-other.x, y-other.y, z-other.z); } + Vec opMul(double a) { return Vec(x*a, y*a, z*a); } + double dot(ref Vec other) { return x*other.x+y*other.y+z*other.z; } + Vec unitise() { return opMul(1.0/sqrt(dot(*this))); } +} + +struct Pair(T, U) { T first; U second; } +typedef Pair!(double, Vec) Hit; + +struct Ray { Vec orig, dir; } + +class Scene { + abstract void intersect(ref Hit, ref Ray); +} + +class Sphere : Scene { + Vec center; + double radius; + this(ref Vec c, double r) + { + center = c; + radius = r; + } + double ray_sphere(ref Ray ray) { + auto v = center - ray.orig, b = v.dot(ray.dir), disc=b*b - v.dot(v) + radius*radius; + if (disc < 0) return double.infinity; + auto d = sqrt(disc), t2 = b + d; + if (t2 < 0) return double.infinity; + auto t1 = b - d; + return (t1 > 0 ? t1 : t2); + } + void intersect(ref Hit hit, ref Ray ray) { + auto lambda = ray_sphere(ray); + if (lambda < hit.first) + hit = Hit(lambda, (ray.orig + lambda*ray.dir - center).unitise); + } +} + +class Group : Scene { + Sphere bound; + Scene[] children; + mixin This!("bound, children"); + void intersect(ref Hit hit, ref Ray ray) { + auto l = bound.ray_sphere(ray); + if (l < hit.first) foreach (child; children) child.intersect(hit, ray); + } +} + +double ray_trace(ref Vec light, ref Ray ray, Scene s) { + auto hit=Hit(double.infinity, Vec(0, 0, 0)); + s.intersect(hit, ray); + if (hit.first == double.infinity) return 0.0; + auto g = hit.second.dot(light); + if (g >= 0) return 0.0; + auto p = ray.orig + ray.dir*hit.first + hit.second*delta; + auto hit2=Hit(double.infinity, Vec(0, 0, 0)); + s.intersect(hit2, Ray(p, light*-1.0)); + return (hit2.first < double.infinity ? 0 : -g); +} + +Scene create(int level, ref Vec c, double r) { + auto s = new Sphere(c, r); + if (level == 1) return s; + Scene[] children=[s]; + double rn = 3*r/sqrt(12.0); + for (int dz=-1; dz<=1; dz+=2) + for (int dx=-1; dx<=1; dx+=2) + children~=create(level-1, c + Vec(dx, 1, dz)*rn, r/2); + return new Group(new Sphere(c, 3*r), children); +} + +void main(string[] args) { + int level = (args.length==3 ? args[1].atoi() : 9), + n = (args.length==3 ? args[2].atoi() : 512), ss = 4; + auto light = Vec(-1, -3, 2).unitise(); + auto s=create(level, Vec(0, -1, 0), 1); + writefln("P5\n", n, " ", n, "\n255"); + for (int y=n-1; y>=0; --y) + for (int x=0; xdim == 1); } + else if (strcmp(str,"alloca")==0) { + llvm_internal = LLVMalloca; + assert(args->dim == 1); + } else { error("unknown pragma command: %s", str); } @@ -904,6 +908,7 @@ case LLVMva_arg: case LLVMva_start: case LLVMnotypeinfo: + case LLVMalloca: break; default: @@ -960,6 +965,16 @@ s->llvmInternal = llvm_internal; break; + case LLVMalloca: + if (FuncDeclaration* fd = s->isFuncDeclaration()) { + fd->llvmInternal = llvm_internal; + } + else { + error("may only be used on function declarations"); + assert(0); + } + break; + default: assert(0 && "invalid LLVM_internal pragma got through :/"); } diff -r 08508eebbb3e -r 61615fa85940 dmd/cast.c --- a/dmd/cast.c Thu Nov 08 19:21:05 2007 +0100 +++ b/dmd/cast.c Mon Nov 12 06:32:46 2007 +0100 @@ -1116,7 +1116,7 @@ e2->type = t; type = e1->type; } - else if (t2b->ty && t1b->isintegral()) + else if (t2b->ty == Tpointer && t1b->isintegral()) { // Need to adjust operator by the stride // Replace (int + ptr) with (ptr + (int * stride)) Type *t = Type::tptrdiff_t; @@ -1127,11 +1127,13 @@ e = e1->castTo(sc, t); else e = e1; + #if !IN_LLVM if (t2b->next->isbit()) // BUG: should add runtime check for misaligned offsets e = new UshrExp(loc, e, new IntegerExp(0, 3, t)); else e = new MulExp(loc, e, new IntegerExp(0, stride, t)); + #endif e->type = t; type = e2->type; e1 = e2; diff -r 08508eebbb3e -r 61615fa85940 dmd/module.c --- a/dmd/module.c Thu Nov 08 19:21:05 2007 +0100 +++ b/dmd/module.c Mon Nov 12 06:32:46 2007 +0100 @@ -159,6 +159,9 @@ bcfile = new File(bcfilename); llfile = new File(llfilename); symfile = new File(symfilename); + + // LLVMDC + llvmCompileUnit = 0; } void Module::setDocfile() diff -r 08508eebbb3e -r 61615fa85940 dmd/module.h --- a/dmd/module.h Thu Nov 08 19:21:05 2007 +0100 +++ b/dmd/module.h Mon Nov 12 06:32:46 2007 +0100 @@ -29,6 +29,7 @@ #if IN_LLVM struct DValue; typedef DValue elem; +namespace llvm { class GlobalVariable; } #else #ifdef IN_GCC union tree_node; typedef union tree_node elem; @@ -166,6 +167,9 @@ Symbol *toSymbol(); void genmoduleinfo(); + // LLVMDC + llvm::GlobalVariable* llvmCompileUnit; + Module *isModule() { return this; } }; diff -r 08508eebbb3e -r 61615fa85940 dmd/mtype.c --- a/dmd/mtype.c Thu Nov 08 19:21:05 2007 +0100 +++ b/dmd/mtype.c Mon Nov 12 06:32:46 2007 +0100 @@ -1514,6 +1514,7 @@ nm = name[n->ty == Twchar]; fd = FuncDeclaration::genCfunc(Type::tindex, nm); + fd->llvmRunTimeHack = true; ec = new VarExp(0, fd); e = e->castTo(sc, n->arrayOf()); // convert to dynamic array arguments = new Expressions(); @@ -1531,6 +1532,7 @@ nm = name[n->ty == Twchar]; fd = FuncDeclaration::genCfunc(Type::tindex, nm); + fd->llvmRunTimeHack = true; ec = new VarExp(0, fd); e = e->castTo(sc, n->arrayOf()); // convert to dynamic array arguments = new Expressions(); @@ -1568,6 +1570,7 @@ fd = FuncDeclaration::genCfunc(tint32->arrayOf(), (char*)(n->ty == Tbit ? "_adSortBit" : "_adSort")); + fd->llvmRunTimeHack = true; ec = new VarExp(0, fd); e = e->castTo(sc, n->arrayOf()); // convert to dynamic array arguments = new Expressions(); diff -r 08508eebbb3e -r 61615fa85940 dmd/optimize.c --- a/dmd/optimize.c Thu Nov 08 19:21:05 2007 +0100 +++ b/dmd/optimize.c Mon Nov 12 06:32:46 2007 +0100 @@ -209,6 +209,7 @@ } return e; } +#if !IN_LLVM if (e1->op == TOKvar) { VarExp *ve = (VarExp *)e1; if (!ve->var->isOut() && !ve->var->isRef() && @@ -240,6 +241,7 @@ } } } +#endif return this; } diff -r 08508eebbb3e -r 61615fa85940 gen/arrays.cpp --- a/gen/arrays.cpp Thu Nov 08 19:21:05 2007 +0100 +++ b/gen/arrays.cpp Mon Nov 12 06:32:46 2007 +0100 @@ -21,14 +21,6 @@ const llvm::Type* at = DtoType(t->next); const llvm::Type* arrty; - /*if (t->ty == Tsarray) { - TypeSArray* tsa = (TypeSArray*)t; - assert(tsa->dim->type->isintegral()); - arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger()); - } - else { - arrty = llvm::ArrayType::get(at,0); - }*/ if (at == llvm::Type::VoidTy) { at = llvm::Type::Int8Ty; } @@ -648,12 +640,17 @@ ////////////////////////////////////////////////////////////////////////////////////////// llvm::Value* DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, const llvm::Type* newelemty) { - llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_cast_len"); - assert(fn); + size_t esz = gTargetData->getTypeSize(elemty); + size_t nsz = gTargetData->getTypeSize(newelemty); + if (esz == nsz) + return len; + std::vector args; args.push_back(len); - args.push_back(llvm::ConstantInt::get(DtoSize_t(), gTargetData->getTypeSize(elemty), false)); - args.push_back(llvm::ConstantInt::get(DtoSize_t(), gTargetData->getTypeSize(newelemty), false)); + args.push_back(llvm::ConstantInt::get(DtoSize_t(), esz, false)); + args.push_back(llvm::ConstantInt::get(DtoSize_t(), nsz, false)); + + llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_cast_len"); return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb()); } @@ -722,7 +719,9 @@ return DtoLoad(DtoGEPi(v->getRVal(), 0,0, "tmp")); } else if (t->ty == Tsarray) { - const llvm::ArrayType* t = llvm::cast(v->getLVal()->getType()); + llvm::Value* rv = v->getRVal(); + Logger::cout() << "casting: " << *rv << '\n'; + const llvm::ArrayType* t = llvm::cast(rv->getType()->getContainedType(0)); return DtoConstSize_t(t->getNumElements()); } assert(0); diff -r 08508eebbb3e -r 61615fa85940 gen/enums.h --- a/gen/enums.h Thu Nov 08 19:21:05 2007 +0100 +++ b/gen/enums.h Mon Nov 12 06:32:46 2007 +0100 @@ -5,5 +5,6 @@ LLVMva_arg, LLVMva_start, LLVMva_intrinsic, - LLVMnotypeinfo + LLVMnotypeinfo, + LLVMalloca }; diff -r 08508eebbb3e -r 61615fa85940 gen/irstate.cpp --- a/gen/irstate.cpp Thu Nov 08 19:21:05 2007 +0100 +++ b/gen/irstate.cpp Mon Nov 12 06:32:46 2007 +0100 @@ -38,7 +38,6 @@ emitMain = false; mainFunc = 0; ir.state = this; - dwarfCompileUnit = 0; } IRFunction& IRState::func() diff -r 08508eebbb3e -r 61615fa85940 gen/irstate.h --- a/gen/irstate.h Thu Nov 08 19:21:05 2007 +0100 +++ b/gen/irstate.h Mon Nov 12 06:32:46 2007 +0100 @@ -162,9 +162,6 @@ // builder helper IRBuilderHelper ir; - - // Dwarf debugging info - llvm::GlobalVariable* dwarfCompileUnit; }; #endif // LLVMDC_GEN_IRSTATE_H diff -r 08508eebbb3e -r 61615fa85940 gen/logger.cpp --- a/gen/logger.cpp Thu Nov 08 19:21:05 2007 +0100 +++ b/gen/logger.cpp Mon Nov 12 06:32:46 2007 +0100 @@ -62,5 +62,13 @@ { enabled = false; } + void attention(const char* fmt,...) + { + printf("***ATTENTION*** "); + va_list va; + va_start(va,fmt); + vprintf(fmt,va); + va_end(va); + printf("\n"); + } } - diff -r 08508eebbb3e -r 61615fa85940 gen/logger.h --- a/gen/logger.h Thu Nov 08 19:21:05 2007 +0100 +++ b/gen/logger.h Mon Nov 12 06:32:46 2007 +0100 @@ -12,14 +12,14 @@ void print(const char* fmt, ...); void enable(); void disable(); - + + void attention(const char* fmt, ...); struct LoggerScope { LoggerScope() { Logger::indent(); - } ~LoggerScope() { diff -r 08508eebbb3e -r 61615fa85940 gen/statements.cpp --- a/gen/statements.cpp Thu Nov 08 19:21:05 2007 +0100 +++ b/gen/statements.cpp Mon Nov 12 06:32:46 2007 +0100 @@ -7,7 +7,6 @@ #include #include "gen/llvm.h" -#include "llvm/Transforms/Utils/Cloning.h" #include "total.h" #include "init.h" @@ -39,8 +38,7 @@ if (s) s->toIR(p); else { - Logger::println("*** ATTENTION: null statement found in CompoundStatement"); - //assert(0); + Logger::println("??? null statement found in CompoundStatement"); } } } @@ -133,8 +131,8 @@ Logger::println("ExpStatement::toIR(%d): %s", esi++, toChars()); LOG_SCOPE; - if (global.params.symdebug) - DtoDwarfStopPoint(loc.linnum); +// if (global.params.symdebug) +// DtoDwarfStopPoint(loc.linnum); if (exp != 0) { elem* e = exp->toElem(p); @@ -255,8 +253,10 @@ // rewrite scope gIR->scope() = IRScope(whilebodybb,endbb); - // do while body code + // while body code + p->loopbbs.push_back(IRScope(whilebb,endbb)); body->toIR(p); + p->loopbbs.pop_back(); // loop new llvm::BranchInst(whilebb, gIR->scopebegin()); @@ -284,7 +284,7 @@ // replace current scope gIR->scope() = IRScope(dowhilebb,endbb); - // do do-while body code + // do-while body code body->toIR(p); // create the condition @@ -363,8 +363,7 @@ void BreakStatement::toIR(IRState* p) { - static int wsi = 0; - Logger::println("BreakStatement::toIR(%d): %s", wsi++, toChars()); + Logger::println("BreakStatement::toIR(): %s", toChars()); LOG_SCOPE; if (ident != 0) { @@ -380,8 +379,7 @@ void ContinueStatement::toIR(IRState* p) { - static int wsi = 0; - Logger::println("ContinueStatement::toIR(%d): %s", wsi++, toChars()); + Logger::println("ContinueStatement::toIR(): %s", toChars()); LOG_SCOPE; if (ident != 0) { @@ -397,8 +395,7 @@ void OnScopeStatement::toIR(IRState* p) { - static int wsi = 0; - Logger::println("OnScopeStatement::toIR(%d): %s", wsi++, toChars()); + Logger::println("OnScopeStatement::toIR(): %s", toChars()); LOG_SCOPE; assert(statement); @@ -407,10 +404,6 @@ ////////////////////////////////////////////////////////////////////////////// -static void replaceFinallyBBs(std::vector& a, std::vector& b) -{ -} - void TryFinallyStatement::toIR(IRState* p) { Logger::println("TryFinallyStatement::toIR(): %s", toChars()); @@ -495,7 +488,7 @@ Logger::println("TryCatchStatement::toIR(%d): %s", wsi++, toChars()); LOG_SCOPE; - Logger::println("*** ATTENTION: try-catch is not yet fully implemented, only the try block will be emitted."); + Logger::attention("try-catch is not yet fully implemented, only the try block will be emitted."); assert(body); body->toIR(p); @@ -516,10 +509,9 @@ Logger::println("ThrowStatement::toIR(%d): %s", wsi++, toChars()); LOG_SCOPE; - Logger::println("*** ATTENTION: throw is not yet implemented, replacing expression with assert(0);"); + Logger::attention("throw is not yet implemented, replacing expression with assert(0);"); - llvm::Value* line = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false); - DtoAssert(NULL, line, NULL); + DtoAssert(NULL, &loc, NULL); /* assert(exp); @@ -657,42 +649,62 @@ //Logger::println("Argument is %s", arg->toChars()); Logger::println("aggr = %s", aggr->toChars()); - Logger::println("func = %s", func->toChars()); - DValue* arr = aggr->toElem(p); - llvm::Value* val = 0; - if (!arr->isSlice()) { - val = arr->getRVal(); - Logger::cout() << "aggr2llvm = " << *val << '\n'; - } - - llvm::Value* numiters = 0; - + // key const llvm::Type* keytype = key ? DtoType(key->type) : DtoSize_t(); llvm::Value* keyvar = new llvm::AllocaInst(keytype, "foreachkey", p->topallocapoint()); if (key) key->llvmValue = keyvar; + llvm::Value* zerokey = llvm::ConstantInt::get(keytype,0,false); + // value const llvm::Type* valtype = DtoType(value->type); - llvm::Value* valvar = !(value->isRef() || value->isOut()) ? new llvm::AllocaInst(valtype, "foreachval", p->topallocapoint()) : NULL; + llvm::Value* valvar = NULL; + if (!value->isRef() && !value->isOut()) + valvar = new llvm::AllocaInst(valtype, "foreachval", p->topallocapoint()); + // what to iterate + DValue* aggrval = aggr->toElem(p); Type* aggrtype = DtoDType(aggr->type); + + // get length and pointer + llvm::Value* val = 0; + llvm::Value* niters = 0; + + // static array if (aggrtype->ty == Tsarray) { + Logger::println("foreach over static array"); + val = aggrval->getRVal(); assert(llvm::isa(val->getType())); assert(llvm::isa(val->getType()->getContainedType(0))); - size_t n = llvm::cast(val->getType()->getContainedType(0))->getNumElements(); - assert(n > 0); - numiters = llvm::ConstantInt::get(keytype,n,false); + size_t nelems = llvm::cast(val->getType()->getContainedType(0))->getNumElements(); + assert(nelems > 0); + niters = llvm::ConstantInt::get(keytype,nelems,false); } + // dynamic array else if (aggrtype->ty == Tarray) { - if (DSliceValue* slice = arr->isSlice()) { - numiters = slice->len; + if (DSliceValue* slice = aggrval->isSlice()) { + Logger::println("foreach over slice"); + niters = slice->len; + assert(niters); + if (llvm::isa(niters)) { + llvm::ConstantInt* ci = llvm::cast(niters); + Logger::println("const num iters: %u", ci); + } + else { + Logger::cout() << "numiters: " << *niters <<'\n'; + } val = slice->ptr; + assert(val); } else { - numiters = p->ir->CreateLoad(DtoGEPi(val,0,0,"tmp",p->scopebb())); - val = p->ir->CreateLoad(DtoGEPi(val,0,1,"tmp",p->scopebb())); + Logger::println("foreach over dynamic array"); + val = aggrval->getRVal(); + niters = DtoGEPi(val,0,0,"tmp",p->scopebb()); + niters = p->ir->CreateLoad(niters, "numiterations"); + val = DtoGEPi(val,0,1,"tmp",p->scopebb()); + val = p->ir->CreateLoad(val, "collection"); } } else @@ -700,41 +712,39 @@ assert(0 && "aggregate type is not Tarray or Tsarray"); } + llvm::Constant* delta = 0; if (op == TOKforeach) { - new llvm::StoreInst(llvm::ConstantInt::get(keytype,0,false), keyvar, p->scopebb()); + new llvm::StoreInst(zerokey, keyvar, p->scopebb()); } - else if (op == TOKforeach_reverse) { - llvm::Value* v = llvm::BinaryOperator::createSub(numiters, llvm::ConstantInt::get(keytype,1,false),"tmp",p->scopebb()); - new llvm::StoreInst(v, keyvar, p->scopebb()); + else { + new llvm::StoreInst(niters, keyvar, p->scopebb()); } - delete arr; - llvm::BasicBlock* oldend = gIR->scopeend(); - llvm::BasicBlock* nexbb = new llvm::BasicBlock("foreachnext", p->topfunc(), oldend); - llvm::BasicBlock* begbb = new llvm::BasicBlock("foreachbegin", p->topfunc(), oldend); + llvm::BasicBlock* condbb = new llvm::BasicBlock("foreachcond", p->topfunc(), oldend); + llvm::BasicBlock* bodybb = new llvm::BasicBlock("foreachbody", p->topfunc(), oldend); + llvm::BasicBlock* nextbb = new llvm::BasicBlock("foreachnext", p->topfunc(), oldend); llvm::BasicBlock* endbb = new llvm::BasicBlock("foreachend", p->topfunc(), oldend); - new llvm::BranchInst(begbb, p->scopebb()); + new llvm::BranchInst(condbb, p->scopebb()); - // next - p->scope() = IRScope(nexbb,begbb); + // condition + p->scope() = IRScope(condbb,bodybb); + llvm::Value* done = 0; llvm::Value* load = new llvm::LoadInst(keyvar, "tmp", p->scopebb()); if (op == TOKforeach) { - load = llvm::BinaryOperator::createAdd(load,llvm::ConstantInt::get(keytype, 1, false),"tmp",p->scopebb()); - new llvm::StoreInst(load, keyvar, p->scopebb()); - done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_ULT, load, numiters, "tmp", p->scopebb()); + done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_ULT, load, niters, "tmp", p->scopebb()); } else if (op == TOKforeach_reverse) { - done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_UGT, load, llvm::ConstantInt::get(keytype, 0, false), "tmp", p->scopebb()); + done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_UGT, load, zerokey, "tmp", p->scopebb()); load = llvm::BinaryOperator::createSub(load,llvm::ConstantInt::get(keytype, 1, false),"tmp",p->scopebb()); new llvm::StoreInst(load, keyvar, p->scopebb()); } - new llvm::BranchInst(begbb, endbb, done, p->scopebb()); + new llvm::BranchInst(bodybb, endbb, done, p->scopebb()); - // begin - p->scope() = IRScope(begbb,nexbb); + // body + p->scope() = IRScope(bodybb,nextbb); // get value for this iteration llvm::Constant* zero = llvm::ConstantInt::get(keytype,0,false); @@ -754,13 +764,21 @@ } // body - p->scope() = IRScope(p->scopebb(),endbb); - p->loopbbs.push_back(IRScope(nexbb,endbb)); + p->loopbbs.push_back(IRScope(nextbb,endbb)); body->toIR(p); p->loopbbs.pop_back(); if (!p->scopereturned()) - new llvm::BranchInst(nexbb, p->scopebb()); + new llvm::BranchInst(nextbb, p->scopebb()); + + // next + p->scope() = IRScope(nextbb,endbb); + if (op == TOKforeach) { + llvm::Value* load = DtoLoad(keyvar); + load = p->ir->CreateAdd(load, llvm::ConstantInt::get(keytype, 1, false), "tmp"); + DtoStore(load, keyvar); + } + new llvm::BranchInst(condbb, p->scopebb()); // end p->scope() = IRScope(endbb,oldend); @@ -828,13 +846,25 @@ ////////////////////////////////////////////////////////////////////////////// +void SynchronizedStatement::toIR(IRState* p) +{ + Logger::println("SynchronizedStatement::toIR(): %s", toChars()); + LOG_SCOPE; + + Logger::attention("synchronized is currently ignored. only the body will be emitted"); + + body->toIR(p); +} + +////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();} //STUBST(BreakStatement); //STUBST(ForStatement); //STUBST(WithStatement); -STUBST(SynchronizedStatement); +//STUBST(SynchronizedStatement); //STUBST(ReturnStatement); //STUBST(ContinueStatement); STUBST(DefaultStatement); diff -r 08508eebbb3e -r 61615fa85940 gen/todebug.cpp --- a/gen/todebug.cpp Thu Nov 08 19:21:05 2007 +0100 +++ b/gen/todebug.cpp Mon Nov 12 06:32:46 2007 +0100 @@ -56,7 +56,7 @@ */ if (!gIR->module->getNamedGlobal("llvm.dbg.compile_units")) { std::vector vals; - vals.push_back(DtoConstUint(0)); + vals.push_back(DtoConstUint(llvm::LLVMDebugVersion)); vals.push_back(DtoConstUint(DW_TAG_compile_unit)); llvm::Constant* i = llvm::ConstantStruct::get(t, vals); dbg_compile_units = new llvm::GlobalVariable(t,true,llvm::GlobalValue::LinkOnceLinkage,i,"llvm.dbg.compile_units",gIR->module); @@ -64,7 +64,7 @@ } if (!gIR->module->getNamedGlobal("llvm.dbg.global_variables")) { std::vector vals; - vals.push_back(DtoConstUint(0)); + vals.push_back(DtoConstUint(llvm::LLVMDebugVersion)); vals.push_back(DtoConstUint(DW_TAG_variable)); llvm::Constant* i = llvm::ConstantStruct::get(t, vals); dbg_global_variables = new llvm::GlobalVariable(t,true,llvm::GlobalValue::LinkOnceLinkage,i,"llvm.dbg.global_variables",gIR->module); @@ -72,7 +72,7 @@ } if (!gIR->module->getNamedGlobal("llvm.dbg.subprograms")) { std::vector vals; - vals.push_back(DtoConstUint(0)); + vals.push_back(DtoConstUint(llvm::LLVMDebugVersion)); vals.push_back(DtoConstUint(DW_TAG_subprogram)); llvm::Constant* i = llvm::ConstantStruct::get(t, vals); dbg_subprograms = new llvm::GlobalVariable(t,true,llvm::GlobalValue::LinkOnceLinkage,i,"llvm.dbg.subprograms",gIR->module); @@ -110,30 +110,33 @@ ////////////////////////////////////////////////////////////////////////////////////////////////// -llvm::GlobalVariable* DtoDwarfCompileUnit(Module* m) +llvm::GlobalVariable* DtoDwarfCompileUnit(Module* m, bool define) { - std::vector vals; - vals.push_back(llvm::ConstantExpr::getAdd( - DtoConstUint(DW_TAG_compile_unit), - DtoConstUint(llvm::LLVMDebugVersion))); - vals.push_back(dbgToArrTy(GetDwarfAnchor(DW_TAG_compile_unit))); + llvm::Constant* c = NULL; + if (1 || define) { + std::vector vals; + vals.push_back(llvm::ConstantExpr::getAdd( + DtoConstUint(DW_TAG_compile_unit), + DtoConstUint(llvm::LLVMDebugVersion))); + vals.push_back(dbgToArrTy(GetDwarfAnchor(DW_TAG_compile_unit))); - vals.push_back(DtoConstUint(DW_LANG_D)); - vals.push_back(DtoConstStringPtr(m->srcfile->name->toChars(), "llvm.metadata")); - std::string srcpath(FileName::path(m->srcfile->name->toChars())); - srcpath.append("/"); - vals.push_back(DtoConstStringPtr(srcpath.c_str(), "llvm.metadata")); - vals.push_back(DtoConstStringPtr("LLVMDC (http://www.dsource.org/projects/llvmdc)", "llvm.metadata")); + vals.push_back(DtoConstUint(DW_LANG_D)); + vals.push_back(DtoConstStringPtr(m->srcfile->name->toChars(), "llvm.metadata")); + std::string srcpath(FileName::path(m->srcfile->name->toChars())); + srcpath.append("/"); + vals.push_back(DtoConstStringPtr(srcpath.c_str(), "llvm.metadata")); + vals.push_back(DtoConstStringPtr("LLVMDC (http://www.dsource.org/projects/llvmdc)", "llvm.metadata")); - llvm::Constant* c = llvm::ConstantStruct::get(GetDwarfCompileUnitType(), vals); - llvm::GlobalVariable* gv = new llvm::GlobalVariable(c->getType(), true, llvm::GlobalValue::InternalLinkage, c, "llvm.dbg.compile_unit", gIR->module); + c = llvm::ConstantStruct::get(GetDwarfCompileUnitType(), vals); + } + llvm::GlobalVariable* gv = new llvm::GlobalVariable(GetDwarfCompileUnitType(), true, llvm::GlobalValue::InternalLinkage, c, "llvm.dbg.compile_unit", gIR->module); gv->setSection("llvm.metadata"); return gv; } ////////////////////////////////////////////////////////////////////////////////////////////////// -llvm::GlobalVariable* DtoDwarfSubProgram(FuncDeclaration* fd) +llvm::GlobalVariable* DtoDwarfSubProgram(FuncDeclaration* fd, llvm::GlobalVariable* compileUnit) { std::vector vals; vals.push_back(llvm::ConstantExpr::getAdd( @@ -141,11 +144,11 @@ DtoConstUint(llvm::LLVMDebugVersion))); vals.push_back(dbgToArrTy(GetDwarfAnchor(DW_TAG_subprogram))); - vals.push_back(dbgToArrTy(gIR->dwarfCompileUnit)); + vals.push_back(dbgToArrTy(compileUnit)); vals.push_back(DtoConstStringPtr(fd->toPrettyChars(), "llvm.metadata")); + vals.push_back(vals.back()); vals.push_back(DtoConstStringPtr(fd->mangle(), "llvm.metadata")); - vals.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty))); - vals.push_back(dbgToArrTy(gIR->dwarfCompileUnit)); + vals.push_back(dbgToArrTy(compileUnit)); vals.push_back(DtoConstUint(fd->loc.linnum)); vals.push_back(llvm::ConstantPointerNull::get(dbgArrTy())); vals.push_back(DtoConstBool(fd->protection == PROTprivate)); @@ -178,6 +181,7 @@ std::vector args; args.push_back(DtoConstUint(ln)); args.push_back(DtoConstUint(0)); - args.push_back(dbgToArrTy(gIR->dwarfCompileUnit)); + assert(gIR->dmodule->llvmCompileUnit); + args.push_back(dbgToArrTy(gIR->dmodule->llvmCompileUnit)); gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.stoppoint"), args.begin(), args.end()); } diff -r 08508eebbb3e -r 61615fa85940 gen/todebug.h --- a/gen/todebug.h Thu Nov 08 19:21:05 2007 +0100 +++ b/gen/todebug.h Mon Nov 12 06:32:46 2007 +0100 @@ -7,8 +7,8 @@ const llvm::StructType* GetDwarfCompileUnitType(); const llvm::StructType* GetDwarfSubProgramType(); -llvm::GlobalVariable* DtoDwarfCompileUnit(Module* m); -llvm::GlobalVariable* DtoDwarfSubProgram(FuncDeclaration* fd); +llvm::GlobalVariable* DtoDwarfCompileUnit(Module* m, bool define); +llvm::GlobalVariable* DtoDwarfSubProgram(FuncDeclaration* fd, llvm::GlobalVariable* compileUnit); void DtoDwarfFuncStart(FuncDeclaration* fd); void DtoDwarfFuncEnd(FuncDeclaration* fd); diff -r 08508eebbb3e -r 61615fa85940 gen/toir.cpp --- a/gen/toir.cpp Thu Nov 08 19:21:05 2007 +0100 +++ b/gen/toir.cpp Mon Nov 12 06:32:46 2007 +0100 @@ -66,9 +66,7 @@ //allocainst->setAlignment(vd->type->alignsize()); // TODO vd->llvmValue = allocainst; } - DVarValue* vv = new DVarValue(type, vd->llvmValue, true); - DValue* ie = DtoInitializer(vd->init, vv); - delete ie; + DValue* ie = DtoInitializer(vd->init); } return new DVarValue(vd, vd->llvmValue, true); @@ -465,6 +463,7 @@ DImValue* im = r->isIm(); if (!im || !im->inPlace()) { + Logger::println("assignment not inplace"); if (l->isArrayLen()) DtoResizeDynArray(l->getLVal(), r->getRVal()); else @@ -659,7 +658,14 @@ return new DFieldValue(type, v, true); } else if (e1type->ty == Tpointer) { - Logger::println("add to AddrExp of struct"); + Logger::println("add to pointer"); + if (r->isConst()) { + llvm::ConstantInt* cofs = llvm::cast(r->isConst()->c); + if (cofs->isZero()) { + Logger::println("is zero"); + return new DImValue(type, l->getRVal()); + } + } llvm::Value* v = new llvm::GetElementPtrInst(l->getRVal(), r->getRVal(), "tmp", p->scopebb()); return new DImValue(type, v); } @@ -728,9 +734,14 @@ DValue* r = e2->toElem(p); if (DtoDType(e1->type)->ty == Tpointer) { - llvm::Value* left = p->ir->CreatePtrToInt(l->getRVal(), DtoSize_t(), "tmp"); - llvm::Value* right = p->ir->CreatePtrToInt(r->getRVal(), DtoSize_t(), "tmp"); - llvm::Value* diff = p->ir->CreateSub(left,right,"tmp"); + llvm::Value* lv = l->getRVal(); + llvm::Value* rv = r->getRVal(); + Logger::cout() << "lv: " << *lv << " rv: " << *rv << '\n'; + if (isaPointer(lv)) + lv = p->ir->CreatePtrToInt(lv, DtoSize_t(), "tmp"); + if (isaPointer(rv)) + rv = p->ir->CreatePtrToInt(rv, DtoSize_t(), "tmp"); + llvm::Value* diff = p->ir->CreateSub(lv,rv,"tmp"); if (diff->getType() != DtoType(type)) diff = p->ir->CreateIntToPtr(diff, DtoType(type)); return new DImValue(type, diff); @@ -1095,6 +1106,13 @@ llt = llvm::PointerType::get(llt); return new DImValue(type, p->ir->CreateVAArg(expelem->getLVal(),llt,"tmp")); } + else if (fndecl->llvmInternal == LLVMalloca) { + //Argument* fnarg = Argument::getNth(tf->parameters, 0); + Expression* exp = (Expression*)arguments->data[0]; + DValue* expv = exp->toElem(p); + llvm::Value* alloc = new llvm::AllocaInst(llvm::Type::Int8Ty, expv->getRVal(), "alloca", p->scopebb()); + return new DImValue(type, alloc); + } } // args @@ -1545,14 +1563,13 @@ if (offset != 0) { Logger::println("offset = %d\n", offset); } - if (llvalue->getType() != llt) { - varmem = p->ir->CreateBitCast(llvalue, llt, "tmp"); - if (offset != 0) - varmem = DtoGEPi(varmem, offset, "tmp"); + if (offset == 0) { + varmem = llvalue; } else { - assert(offset == 0); - varmem = DtoGEPi(llvalue,0,0,"tmp"); + const llvm::Type* elemtype = llvalue->getType()->getContainedType(0)->getContainedType(0); + size_t elemsz = gTargetData->getTypeSize(elemtype); + varmem = DtoGEPi(llvalue, 0, offset / elemsz, "tmp"); } } else if (offset == 0) { @@ -1571,17 +1588,30 @@ } return new DFieldValue(type, varmem, true); } - else if (FuncDeclaration* fd = var->isFuncDeclaration()) + + assert(0); + return 0; +} + +////////////////////////////////////////////////////////////////////////////////////////// + +DValue* AddrExp::toElem(IRState* p) +{ + Logger::print("AddrExp::toElem: %s | %s\n", toChars(), type->toChars()); + LOG_SCOPE; + DValue* v = e1->toElem(p); + if (v->isField()) + return v; + if (DFuncValue* fv = v->isFunc()) { Logger::println("FuncDeclaration"); - + FuncDeclaration* fd = fv->func; + assert(fd); if (fd->llvmValue == 0) fd->toObjFile(); return new DFuncValue(fd, fd->llvmValue); } - - assert(0); - return 0; + return new DFieldValue(type, v->getLVal(), false); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1700,18 +1730,6 @@ ////////////////////////////////////////////////////////////////////////////////////////// -DValue* AddrExp::toElem(IRState* p) -{ - Logger::print("AddrExp::toElem: %s | %s\n", toChars(), type->toChars()); - LOG_SCOPE; - DValue* v = e1->toElem(p); - if (v->isField()) - return v; - return new DFieldValue(type, v->getLVal(), false); -} - -////////////////////////////////////////////////////////////////////////////////////////// - DValue* IndexExp::toElem(IRState* p) { Logger::print("IndexExp::toElem: %s | %s\n", toChars(), type->toChars()); @@ -1755,7 +1773,7 @@ Type* e1type = DtoDType(e1->type); DValue* v = e1->toElem(p); - llvm::Value* vmem = v->isIm() ? v->getRVal() : v->getLVal(); + llvm::Value* vmem = v->getRVal(); assert(vmem); llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); @@ -2100,47 +2118,46 @@ const llvm::Type* t = DtoType(ntype); llvm::Value* emem = 0; - bool inplace = true; + bool inplace = false; if (onstack) { assert(ntype->ty == Tclass); emem = new llvm::AllocaInst(t->getContainedType(0),"tmp",p->topallocapoint()); } - else { - if (ntype->ty == Tclass) { - emem = new llvm::MallocInst(t->getContainedType(0),"tmp",p->scopebb()); - } - else if (ntype->ty == Tarray) { - assert(arguments); - if (arguments->dim == 1) { - DValue* sz = ((Expression*)arguments->data[0])->toElem(p); - llvm::Value* dimval = sz->getRVal(); - Type* nnt = DtoDType(ntype->next); - if (nnt->ty == Tvoid) - nnt = Type::tint8; - if (!p->topexp() || p->topexp()->e2 != this) { - const llvm::Type* restype = DtoType(type); - Logger::cout() << "restype = " << *restype << '\n'; - emem = new llvm::AllocaInst(restype,"tmp",p->topallocapoint()); - DtoNewDynArray(emem, dimval, nnt); - inplace = false; - } - else if (p->topexp() || p->topexp()->e2 != this) { - assert(p->topexp()->v); - emem = p->topexp()->v->getLVal(); - DtoNewDynArray(emem, dimval, nnt); - } - else - assert(0); + else if (ntype->ty == Tclass) { + emem = new llvm::MallocInst(t->getContainedType(0),"tmp",p->scopebb()); + } + else if (ntype->ty == Tarray) { + assert(arguments); + if (arguments->dim == 1) { + DValue* sz = ((Expression*)arguments->data[0])->toElem(p); + llvm::Value* dimval = sz->getRVal(); + Type* nnt = DtoDType(ntype->next); + if (nnt->ty == Tvoid) + nnt = Type::tint8; + if (!p->topexp() || p->topexp()->e2 != this) { + const llvm::Type* restype = DtoType(type); + Logger::cout() << "restype = " << *restype << '\n'; + emem = new llvm::AllocaInst(restype,"newstorage",p->topallocapoint()); + DtoNewDynArray(emem, dimval, nnt); + return new DVarValue(newtype, emem, true); } - else { - assert(0); + else if (p->topexp() && p->topexp()->e2 == this) { + assert(p->topexp()->v); + emem = p->topexp()->v->getLVal(); + DtoNewDynArray(emem, dimval, nnt); + inplace = true; } + else + assert(0); } else { - emem = new llvm::MallocInst(t,"tmp",p->scopebb()); + assert(0); } } + else { + emem = new llvm::MallocInst(t,"tmp",p->scopebb()); + } if (ntype->ty == Tclass) { // first apply the static initializer @@ -2175,10 +2192,7 @@ } } - if (inplace) - return new DImValue(type, emem, true); - - return new DVarValue(type, emem, true); + return new DImValue(type, emem, inplace); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -2264,8 +2278,7 @@ DValue* u = e1->toElem(p); DValue* m = msg ? msg->toElem(p) : NULL; - llvm::Value* loca = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false); - DtoAssert(u->getRVal(), loca, m ? m->getRVal() : NULL); + DtoAssert(u->getRVal(), &loc, m); return 0; } @@ -2401,8 +2414,7 @@ Logger::print("HaltExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - llvm::Value* loca = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false); - DtoAssert(llvm::ConstantInt::getFalse(), loca, NULL); + DtoAssert(DtoConstBool(false), &loc, NULL); new llvm::UnreachableInst(p->scopebb()); return 0; @@ -2634,18 +2646,18 @@ fd->toObjFile(); + bool temp = false; llvm::Value* lval = NULL; - if (!p->topexp() || p->topexp()->e2 != this) { + if (p->topexp() && p->topexp()->e2 == this) { + assert(p->topexp()->v); + lval = p->topexp()->v->getLVal(); + } + else { const llvm::Type* dgty = DtoType(type); Logger::cout() << "delegate without explicit storage:" << '\n' << *dgty << '\n'; lval = new llvm::AllocaInst(dgty,"dgstorage",p->topallocapoint()); + temp = true; } - else if (p->topexp()->e2 == this) { - assert(p->topexp()->v); - lval = p->topexp()->v->getLVal();; - } - else - assert(0); llvm::Value* context = DtoGEPi(lval,0,0,"tmp",p->scopebb()); const llvm::PointerType* pty = llvm::cast(context->getType()->getContainedType(0)); @@ -2665,7 +2677,10 @@ llvm::Value* castfptr = new llvm::BitCastInst(fd->llvmValue,fptr->getType()->getContainedType(0),"tmp",p->scopebb()); new llvm::StoreInst(castfptr, fptr, p->scopebb()); - return new DImValue(type, lval, true); + if (temp) + return new DVarValue(type, lval, true); + else + return new DImValue(type, lval, true); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -3093,7 +3108,7 @@ AsmStatement::AsmStatement(Loc loc, Token *tokens) : Statement(loc) { - assert(0); + Logger::println("Ignoring AsmStatement"); } Statement *AsmStatement::syntaxCopy() { diff -r 08508eebbb3e -r 61615fa85940 gen/tollvm.cpp --- a/gen/tollvm.cpp Thu Nov 08 19:21:05 2007 +0100 +++ b/gen/tollvm.cpp Mon Nov 12 06:32:46 2007 +0100 @@ -797,15 +797,13 @@ ////////////////////////////////////////////////////////////////////////////////////////// -DValue* DtoInitializer(Initializer* init, DValue* v) +DValue* DtoInitializer(Initializer* init) { if (ExpInitializer* ex = init->isExpInitializer()) { Logger::println("expression initializer"); assert(ex->exp); - if (v) gIR->exps.push_back(IRExp(NULL,ex->exp,v)); return ex->exp->toElem(gIR); - if (v) gIR->exps.pop_back(); } else if (init->isVoidInitializer()) { @@ -1050,16 +1048,17 @@ ////////////////////////////////////////////////////////////////////////////////////////// -void DtoAssert(llvm::Value* cond, llvm::Value* loc, llvm::Value* msg) +void DtoAssert(llvm::Value* cond, Loc* loc, DValue* msg) { - assert(loc); + llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_assert"); + const llvm::FunctionType* fnt = fn->getFunctionType(); + std::vector llargs; llargs.resize(3); llargs[0] = cond ? DtoBoolean(cond) : llvm::ConstantInt::getFalse(); - llargs[1] = loc; - llargs[2] = msg ? msg : llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)); + llargs[1] = DtoConstUint(loc->linnum); + llargs[2] = msg ? msg->getRVal() : llvm::Constant::getNullValue(fnt->getParamType(2)); - llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_assert"); assert(fn); llvm::CallInst* call = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); call->setCallingConv(llvm::CallingConv::C); @@ -1301,6 +1300,11 @@ llvm::Value* r = rhs->getRVal(); llvm::Value* l = lhs->getLVal(); Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n'; + const llvm::Type* lit = l->getType()->getContainedType(0); + if (r->getType() != lit) { + r = DtoBitCast(r, lit); + Logger::cout() << "really assign\nlhs: " << *l << "rhs: " << *r << '\n'; + } gIR->ir->CreateStore(r, l); } } @@ -1404,6 +1408,31 @@ return gIR->ir->CreateBitCast(v, t, "tmp"); } +const llvm::PointerType* isaPointer(llvm::Value* v) +{ + return llvm::dyn_cast(v->getType()); +} + +const llvm::ArrayType* isaArray(llvm::Value* v) +{ + return llvm::dyn_cast(v->getType()); +} + +const llvm::StructType* isaStruct(llvm::Value* v) +{ + return llvm::dyn_cast(v->getType()); +} + +llvm::Constant* isaConstant(llvm::Value* v) +{ + return llvm::dyn_cast(v); +} + +llvm::ConstantInt* isaConstantInt(llvm::Value* v) +{ + return llvm::dyn_cast(v); +} + ////////////////////////////////////////////////////////////////////////////////////////// bool DtoIsTemplateInstance(Dsymbol* s) @@ -1431,7 +1460,7 @@ llvm::Value* cond = gIR->ir->CreateICmpEQ(gIR->ir->CreateLoad(gflag,"tmp"),DtoConstBool(false)); gIR->ir->CreateCondBr(cond, initbb, endinitbb); gIR->scope() = IRScope(initbb,endinitbb); - DValue* ie = DtoInitializer(init, NULL); + DValue* ie = DtoInitializer(init); if (!ie->inPlace()) { DValue* dst = new DVarValue(t, gvar, true); DtoAssign(dst, ie); diff -r 08508eebbb3e -r 61615fa85940 gen/tollvm.h --- a/gen/tollvm.h Thu Nov 08 19:21:05 2007 +0100 +++ b/gen/tollvm.h Mon Nov 12 06:32:46 2007 +0100 @@ -34,7 +34,7 @@ void DtoInitClass(TypeClass* tc, llvm::Value* dst); llvm::Constant* DtoConstInitializer(Type* type, Initializer* init); -DValue* DtoInitializer(Initializer* init, DValue* v); +DValue* DtoInitializer(Initializer* init); llvm::Function* LLVM_DeclareMemSet32(); llvm::Function* LLVM_DeclareMemSet64(); @@ -49,7 +49,7 @@ llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty); llvm::Value* DtoRealloc(llvm::Value* ptr, llvm::Value* len); -void DtoAssert(llvm::Value* cond, llvm::Value* loc, llvm::Value* msg); +void DtoAssert(llvm::Value* cond, Loc* loc, DValue* msg); llvm::Value* DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expression* argexp); @@ -75,6 +75,13 @@ void DtoStore(llvm::Value* src, llvm::Value* dst); llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t); +// llvm::dyn_cast wrappers +const llvm::PointerType* isaPointer(llvm::Value* v); +const llvm::ArrayType* isaArray(llvm::Value* v); +const llvm::StructType* isaStruct(llvm::Value* v); +llvm::Constant* isaConstant(llvm::Value* v); +llvm::ConstantInt* isaConstantInt(llvm::Value* v); + // basic operations void DtoAssign(DValue* lhs, DValue* rhs); diff -r 08508eebbb3e -r 61615fa85940 gen/toobj.cpp --- a/gen/toobj.cpp Thu Nov 08 19:21:05 2007 +0100 +++ b/gen/toobj.cpp Mon Nov 12 06:32:46 2007 +0100 @@ -81,7 +81,7 @@ // debug info if (global.params.symdebug) { RegisterDwarfSymbols(ir.module); - ir.dwarfCompileUnit = DtoDwarfCompileUnit(this); + ir.dmodule->llvmCompileUnit = DtoDwarfCompileUnit(this,true); } // process module members @@ -162,7 +162,7 @@ Logger::println("vmoduleinfo"); } if (needModuleInfo()) { - Logger::println("**** ATTENTION: module info is needed but skipped"); + Logger::attention("module info is needed but skipped"); } @@ -905,7 +905,7 @@ } if (isUnitTestDeclaration()) { - Logger::println("*** ATTENTION: ignoring unittest declaration: %s", toChars()); + Logger::attention("ignoring unittest declaration: %s", toChars()); return; } @@ -948,7 +948,11 @@ // debug info if (global.params.symdebug) { - llvmDwarfSubProgram = DtoDwarfSubProgram(this); + Module* mo = getModule(); + if (!mo->llvmCompileUnit) { + mo->llvmCompileUnit = DtoDwarfCompileUnit(mo,false); + } + llvmDwarfSubProgram = DtoDwarfSubProgram(this, mo->llvmCompileUnit); } assert(f->llvmType); @@ -1033,7 +1037,7 @@ vd->llvmValue = v; } else { - Logger::println("*** ATTENTION: some unknown argument: %s", arg ? arg->toChars() : 0); + Logger::attention("some unknown argument: %s", arg ? arg->toChars() : 0); } } diff -r 08508eebbb3e -r 61615fa85940 llvmdc.kdevelop --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/llvmdc.kdevelop Mon Nov 12 06:32:46 2007 +0100 @@ -0,0 +1,380 @@ + + + + Tomas Lindquist Olsen + tomas.l.olsen@gmail.com + 0.1 + KDevCustomProject + C++ + + C++ + Code + + + llvmdc + . + false + + + + + + + + + optimized + kdevgccoptions + kdevgppoptions + kdevg77options + -O2 -g0 + + + --enable-debug=full + debug + kdevgccoptions + kdevgppoptions + kdevg77options + -O0 -g3 + + + + + + ada + ada_bugs_gcc + bash + bash_bugs + clanlib + w3c-dom-level2-html + fortran_bugs_gcc + gnome1 + gnustep + gtk + gtk_bugs + haskell + haskell_bugs_ghc + java_bugs_gcc + java_bugs_sun + kde2book + opengl + pascal_bugs_fp + php + php_bugs + perl + perl_bugs + python + python_bugs + qt-kdev3 + ruby + ruby_bugs + sdl + w3c-svg + sw + w3c-uaag10 + wxwidgets_bugs + + + Guide to the Qt Translation Tools + Qt Assistant Manual + Qt Designer Manual + Qt Reference Documentation + qmake User Guide + + + KDE Libraries (Doxygen) + + + + + + + + + + + + + true + false + + + *.o,*.lo,CVS + false + + + + + Doxygen Documentation Collection + llvmdc.tag + + + + llvmdc + llvmdc + Llvmdc + LLVMDC + Tomas Lindquist Olsen + tomas.l.olsen@gmail.com + GPL + COPYING + 0.1 + 2007 + /home/tomas/projects/llvmdc + + + + false + 3 + 3 + /opt/qt + EmbeddedKDevDesigner + /opt/qt/bin/qmake + /opt/qt/bin/designer + + + + false + true + true + 250 + 400 + 250 + false + 0 + true + true + false + std=_GLIBCXX_STD;__gnu_cxx=std + true + false + false + false + false + true + true + false + .; + + + + set + m_,_ + theValue + true + true + + + false + true + Vertical + + + + + + executable + /home/tomas/kdevprojects/llvmdc + + + /home/tomas/kdevprojects/llvmdc + false + false + false + false + false + + + + *.h + *.c + *.cpp + *.d + + + dbgtypes.bc.cpp + debuginfo.c + debuginfo.cpp + dmdorig + dmdorig/dmd + dmdorig/dmd/access.c + dmdorig/dmd/aggregate.h + dmdorig/dmd/array.c + dmdorig/dmd/arraytypes.h + dmdorig/dmd/attrib.c + dmdorig/dmd/attrib.h + dmdorig/dmd/bit.c + dmdorig/dmd/cast.c + dmdorig/dmd/class.c + dmdorig/dmd/complex_t.h + dmdorig/dmd/cond.c + dmdorig/dmd/cond.h + dmdorig/dmd/constfold.c + dmdorig/dmd/dchar.c + dmdorig/dmd/dchar.h + dmdorig/dmd/declaration.c + dmdorig/dmd/declaration.h + dmdorig/dmd/delegatize.c + dmdorig/dmd/doc.c + dmdorig/dmd/doc.h + dmdorig/dmd/dsymbol.c + dmdorig/dmd/dsymbol.h + dmdorig/dmd/dump.c + dmdorig/dmd/entity.c + dmdorig/dmd/enum.c + dmdorig/dmd/enum.h + dmdorig/dmd/expression.c + dmdorig/dmd/expression.h + dmdorig/dmd/func.c + dmdorig/dmd/gnuc.c + dmdorig/dmd/gnuc.h + dmdorig/dmd/hdrgen.c + dmdorig/dmd/hdrgen.h + dmdorig/dmd/html.c + dmdorig/dmd/html.h + dmdorig/dmd/identifier.c + dmdorig/dmd/identifier.h + dmdorig/dmd/idgen.c + dmdorig/dmd/impcnvgen.c + dmdorig/dmd/import.c + dmdorig/dmd/import.h + dmdorig/dmd/inifile.c + dmdorig/dmd/init.c + dmdorig/dmd/init.h + dmdorig/dmd/inline.c + dmdorig/dmd/interpret.c + dmdorig/dmd/lexer.c + dmdorig/dmd/lexer.h + dmdorig/dmd/link.c + dmdorig/dmd/lstring.c + dmdorig/dmd/lstring.h + dmdorig/dmd/macro.c + dmdorig/dmd/macro.h + dmdorig/dmd/mangle.c + dmdorig/dmd/mars.c + dmdorig/dmd/mars.h + dmdorig/dmd/mem.c + dmdorig/dmd/mem.h + dmdorig/dmd/module.c + dmdorig/dmd/module.h + dmdorig/dmd/mtype.c + dmdorig/dmd/mtype.h + dmdorig/dmd/opover.c + dmdorig/dmd/optimize.c + dmdorig/dmd/parse.c + dmdorig/dmd/parse.h + dmdorig/dmd/port.h + dmdorig/dmd/root.c + dmdorig/dmd/root.h + dmdorig/dmd/scope.c + dmdorig/dmd/scope.h + dmdorig/dmd/statement.c + dmdorig/dmd/statement.h + dmdorig/dmd/staticassert.c + dmdorig/dmd/staticassert.h + dmdorig/dmd/stringtable.c + dmdorig/dmd/stringtable.h + dmdorig/dmd/struct.c + dmdorig/dmd/template.c + dmdorig/dmd/template.h + dmdorig/dmd/tocsym.c + dmdorig/dmd/todt.c + dmdorig/dmd/toir.c + dmdorig/dmd/toir.h + dmdorig/dmd/toobj.c + dmdorig/dmd/total.h + dmdorig/dmd/typinf.c + dmdorig/dmd/unialpha.c + dmdorig/dmd/utf.c + dmdorig/dmd/utf.h + dmdorig/dmd/version.c + dmdorig/dmd/version.h + dmdorig/phobos + dmdorig/phobos/errno.c + dmdorig/phobos/etc + dmdorig/phobos/etc/c + dmdorig/phobos/etc/c/zlib + dmdorig/phobos/etc/c/zlib/adler32.c + dmdorig/phobos/etc/c/zlib/compress.c + dmdorig/phobos/etc/c/zlib/crc32.c + dmdorig/phobos/etc/c/zlib/crc32.h + dmdorig/phobos/etc/c/zlib/deflate.c + dmdorig/phobos/etc/c/zlib/deflate.h + dmdorig/phobos/etc/c/zlib/example.c + dmdorig/phobos/etc/c/zlib/gzio.c + dmdorig/phobos/etc/c/zlib/infback.c + dmdorig/phobos/etc/c/zlib/inffast.c + dmdorig/phobos/etc/c/zlib/inffast.h + dmdorig/phobos/etc/c/zlib/inffixed.h + dmdorig/phobos/etc/c/zlib/inflate.c + dmdorig/phobos/etc/c/zlib/inflate.h + dmdorig/phobos/etc/c/zlib/inftrees.c + dmdorig/phobos/etc/c/zlib/inftrees.h + dmdorig/phobos/etc/c/zlib/minigzip.c + dmdorig/phobos/etc/c/zlib/trees.c + dmdorig/phobos/etc/c/zlib/trees.h + dmdorig/phobos/etc/c/zlib/uncompr.c + dmdorig/phobos/etc/c/zlib/zconf.h + dmdorig/phobos/etc/c/zlib/zconf.in.h + dmdorig/phobos/etc/c/zlib/zlib.h + dmdorig/phobos/etc/c/zlib/zutil.c + dmdorig/phobos/etc/c/zlib/zutil.h + dmdorig/phobos/internal + dmdorig/phobos/internal/complex.c + dmdorig/phobos/internal/critical.c + dmdorig/phobos/internal/deh.c + dmdorig/phobos/internal/mars.h + dmdorig/phobos/internal/monitor.c + + + make + + + + 0 + + + + default + + + + + + false + 0 + 0 + false + + + + default + + + + + + + + .h + .cpp + + + + + + + + + + true + false + false + false + + + false + true + 10 + + + diff -r 08508eebbb3e -r 61615fa85940 llvmdc.kdevelop.filelist --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/llvmdc.kdevelop.filelist Mon Nov 12 06:32:46 2007 +0100 @@ -0,0 +1,419 @@ +# KDevelop Custom Project File List +demos +demos/gl.d +demos/glfuncs.d +demos/gltypes.d +demos/lib.d +demos/libtest1.d +demos/qd.d +demos/qd1.d +demos/ray.d +demos/sdl.d +demos/sdldemo1.d +dmd +dmd/access.c +dmd/aggregate.h +dmd/array.c +dmd/arraytypes.h +dmd/attrib.c +dmd/attrib.h +dmd/cast.c +dmd/class.c +dmd/complex_t.h +dmd/cond.c +dmd/cond.h +dmd/constfold.c +dmd/dchar.c +dmd/dchar.h +dmd/declaration.c +dmd/declaration.h +dmd/delegatize.c +dmd/doc.c +dmd/doc.h +dmd/dsymbol.c +dmd/dsymbol.h +dmd/dump.c +dmd/entity.c +dmd/enum.c +dmd/enum.h +dmd/expression.c +dmd/expression.h +dmd/func.c +dmd/gnuc.c +dmd/gnuc.h +dmd/hdrgen.c +dmd/hdrgen.h +dmd/html.c +dmd/html.h +dmd/id.c +dmd/id.h +dmd/identifier.c +dmd/identifier.h +dmd/idgen.c +dmd/impcnvgen.c +dmd/impcnvtab.c +dmd/import.c +dmd/import.h +dmd/inifile.c +dmd/init.c +dmd/init.h +dmd/inline.c +dmd/interpret.c +dmd/lexer.c +dmd/lexer.h +dmd/link.c +dmd/lstring.c +dmd/lstring.h +dmd/macro.c +dmd/macro.h +dmd/mangle.c +dmd/mars.c +dmd/mars.h +dmd/mem.c +dmd/mem.h +dmd/module.c +dmd/module.h +dmd/mtype.c +dmd/mtype.h +dmd/opover.c +dmd/optimize.c +dmd/parse.c +dmd/parse.h +dmd/port.h +dmd/root.c +dmd/root.h +dmd/scope.c +dmd/scope.h +dmd/statement.c +dmd/statement.h +dmd/staticassert.c +dmd/staticassert.h +dmd/stringtable.c +dmd/stringtable.h +dmd/struct.c +dmd/template.c +dmd/template.h +dmd/total.h +dmd/unialpha.c +dmd/utf.c +dmd/utf.h +dmd/version.c +dmd/version.h +gen +gen/arrays.cpp +gen/arrays.h +gen/binops.cpp +gen/dvalue.cpp +gen/dvalue.h +gen/dwarftypes.cpp +gen/elem.cpp +gen/elem.h +gen/enums.h +gen/irstate.cpp +gen/irstate.h +gen/llvm.h +gen/logger.cpp +gen/logger.h +gen/runtime.cpp +gen/runtime.h +gen/statements.cpp +gen/structs.cpp +gen/structs.h +gen/symbol.h +gen/tocsym.cpp +gen/todebug.cpp +gen/todebug.h +gen/todt.cpp +gen/toir.cpp +gen/tollvm.cpp +gen/tollvm.h +gen/toobj.cpp +gen/typinf.cpp +lphobos +lphobos/crc32.d +lphobos/gc +lphobos/gc/gclinux.d +lphobos/gc/gcstub.d +lphobos/gcstats.d +lphobos/internal +lphobos/internal/aApply.d +lphobos/internal/aApplyR.d +lphobos/internal/adi.d +lphobos/internal/arrays.d +lphobos/internal/contract.d +lphobos/internal/mem.d +lphobos/internal/moduleinit.d +lphobos/internal/objectimpl.d +lphobos/internal/qsort2.d +lphobos/llvm +lphobos/llvm/intrinsic.d +lphobos/llvm/va_list.d +lphobos/llvmsupport.d +lphobos/obj +lphobos/object.d +lphobos/phobos.d +lphobos/std +lphobos/std/array.d +lphobos/std/base64.d +lphobos/std/c +lphobos/std/c/fenv.d +lphobos/std/c/linux +lphobos/std/c/linux/linux.d +lphobos/std/c/linux/linuxextern.d +lphobos/std/c/linux/pthread.d +lphobos/std/c/linux/socket.d +lphobos/std/c/locale.d +lphobos/std/c/math.d +lphobos/std/c/process.d +lphobos/std/c/stdarg.d +lphobos/std/c/stddef.d +lphobos/std/c/stdio.d +lphobos/std/c/stdlib.d +lphobos/std/c/string.d +lphobos/std/c/time.d +lphobos/std/compiler.d +lphobos/std/conv.d +lphobos/std/ctype.d +lphobos/std/format.d +lphobos/std/intrinsic.d +lphobos/std/moduleinit.d +lphobos/std/outofmemory.d +lphobos/std/stdarg.d +lphobos/std/stdint.d +lphobos/std/stdio.d +lphobos/std/string.d +lphobos/std/traits.d +lphobos/std/uni.d +lphobos/std/utf.d +lphobos/typeinfo1 +lphobos/typeinfo1/ti_byte.d +lphobos/typeinfo1/ti_char.d +lphobos/typeinfo1/ti_dchar.d +lphobos/typeinfo1/ti_delegate.d +lphobos/typeinfo1/ti_double.d +lphobos/typeinfo1/ti_float.d +lphobos/typeinfo1/ti_idouble.d +lphobos/typeinfo1/ti_ifloat.d +lphobos/typeinfo1/ti_int.d +lphobos/typeinfo1/ti_ireal.d +lphobos/typeinfo1/ti_long.d +lphobos/typeinfo1/ti_ptr.d +lphobos/typeinfo1/ti_real.d +lphobos/typeinfo1/ti_short.d +lphobos/typeinfo1/ti_ubyte.d +lphobos/typeinfo1/ti_uint.d +lphobos/typeinfo1/ti_ulong.d +lphobos/typeinfo1/ti_ushort.d +lphobos/typeinfo1/ti_void.d +lphobos/typeinfo1/ti_wchar.d +lphobos/typeinfo2 +lphobos/typeinfo2/ti_Adouble.d +lphobos/typeinfo2/ti_Afloat.d +lphobos/typeinfo2/ti_Ag.d +lphobos/typeinfo2/ti_Aint.d +lphobos/typeinfo2/ti_Along.d +lphobos/typeinfo2/ti_Areal.d +lphobos/typeinfo2/ti_Ashort.d +lphobos/typeinfos1.d +lphobos/typeinfos2.d +runalltests.d +test +test/a.d +test/alignment.d +test/alloca1.d +test/arrayinit.d +test/arrays.d +test/arrays10.d +test/arrays2.d +test/arrays3.d +test/arrays4.d +test/arrays5.d +test/arrays6.d +test/arrays7.d +test/arrays8.d +test/arrays9.d +test/assign.d +test/b.d +test/bitops.d +test/bug1.d +test/bug10.d +test/bug11.d +test/bug12.d +test/bug13.d +test/bug14.d +test/bug15.d +test/bug16.d +test/bug17.d +test/bug18.d +test/bug19.d +test/bug2.d +test/bug20.d +test/bug21.d +test/bug22.d +test/bug23.d +test/bug24.d +test/bug25.d +test/bug26.d +test/bug27.d +test/bug28.d +test/bug29.d +test/bug3.d +test/bug30.d +test/bug32.d +test/bug33.d +test/bug34.d +test/bug35.d +test/bug36.d +test/bug37.d +test/bug38.d +test/bug39.d +test/bug4.d +test/bug40.d +test/bug41.d +test/bug42.d +test/bug43.d +test/bug44.d +test/bug45.d +test/bug47.d +test/bug48.d +test/bug49.d +test/bug5.d +test/bug50.d +test/bug51.d +test/bug52.d +test/bug53.d +test/bug54.d +test/bug55.d +test/bug56.d +test/bug57.d +test/bug58.d +test/bug59.d +test/bug6.d +test/bug60.d +test/bug61.d +test/bug62.d +test/bug63.d +test/bug64.d +test/bug65.d +test/bug7.d +test/bug8.d +test/bug9.d +test/c.d +test/classes.d +test/classes2.d +test/classes3.d +test/classes4.d +test/classes5.d +test/classes6.d +test/classes7.d +test/classes8.d +test/classinfo1.d +test/comma.d +test/complex1.d +test/cond.d +test/cond1.d +test/condexp.d +test/condexp1.d +test/cyclic.d +test/d.d +test/dgs.d +test/dotproduct.d +test/e.d +test/enum1.d +test/enum2.d +test/enum3.d +test/f.d +test/fail1.d +test/fail2.d +test/floatcmp.d +test/foreach1.d +test/foreach2.d +test/foreach3.d +test/foreach4.d +test/foreach5.d +test/foreach6.d +test/foreach7.d +test/forwdecl.d +test/funcptr.d +test/funcs.d +test/funcs2.d +test/g.d +test/globals1.d +test/globals2.d +test/goto1.d +test/imag1.d +test/imports2.d +test/imports_1of2.d +test/imports_2of2.d +test/intrinsics.d +test/mainargs1.d +test/memory1.d +test/moduleinfo1.d +test/multiarr1.d +test/multiarr2.d +test/multiarr3.d +test/multiarr4.d +test/neg.d +test/nested1.d +test/nested2.d +test/nested3.d +test/nested4.d +test/pointers.d +test/pt.d +test/ptrarith.d +test/ray.d +test/scope1.d +test/scope2.d +test/scope3.d +test/scope4.d +test/scope5.d +test/sieve.d +test/slices.d +test/sqrts.d +test/static_ctor.d +test/staticarrays.d +test/staticvars.d +test/stdiotest.d +test/strings1.d +test/structinit.d +test/structinit2.d +test/structs.d +test/structs2.d +test/structs3.d +test/structs4.d +test/structs5.d +test/structs6.d +test/switch1.d +test/sync1.d +test/templ1.d +test/templ2.d +test/terms.d +test/throw1.d +test/tuple1.d +test/typeinfo.d +test/typeinfo10.d +test/typeinfo2.d +test/typeinfo3.d +test/typeinfo4.d +test/typeinfo5.d +test/typeinfo6.d +test/typeinfo7.d +test/typeinfo8.d +test/typeinfo9.d +test/union1.d +test/union2.d +test/union3.d +test/union4.d +test/union5.d +test/union6.d +test/union7.d +test/unittest1.d +test/unrolled.d +test/v2d.d +test/vararg1.d +test/vararg2.d +test/vararg3.d +test/vararg4.d +test/virtcall.d +test/with1.d +tester.d diff -r 08508eebbb3e -r 61615fa85940 lphobos/build.sh --- a/lphobos/build.sh Thu Nov 08 19:21:05 2007 +0100 +++ b/lphobos/build.sh Mon Nov 12 06:32:46 2007 +0100 @@ -35,10 +35,21 @@ llvmdc internal/aApplyR.d -c -odobj || exit 1 llvm-link -f -o=../lib/llvmdcore.bc obj/aApply.bc obj/aApplyR.bc ../lib/llvmdcore.bc || exit 1 +echo "compiling array runtime support" +llvmdc internal/qsort2.d -c -odobj || exit +llvm-link -f -o=../lib/llvmdcore.bc obj/qsort2.bc ../lib/llvmdcore.bc || exit 1 +llvmdc internal/adi.d -c -odobj || exit +llvm-link -f -o=../lib/llvmdcore.bc obj/adi.bc ../lib/llvmdcore.bc || exit 1 + echo "compiling llvm runtime support" -rebuild llvmsupport.d -c -oqobj -dc=llvmdc-posix || exit +rebuild llvmsupport.d -c -oqobj -dc=llvmdc-posix || exit 1 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/llvm.*.bc` ../lib/llvmdcore.bc || exit 1 +echo "compiling garbage collector" +llvmdc gc/gclinux.d -c -odobj || exit 1 +llvmdc gc/gcstub.d -c -odobj -Igc || exit 1 +llvm-link -f -o=../lib/llvmdcore.bc obj/gclinux.bc obj/gcstub.bc ../lib/llvmdcore.bc || exit 1 + echo "compiling phobos" rebuild phobos.d -c -oqobj -dc=llvmdc-posix || exit 1 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/std.*.bc` ../lib/llvmdcore.bc || exit 1 diff -r 08508eebbb3e -r 61615fa85940 lphobos/gc/gclinux.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lphobos/gc/gclinux.d Mon Nov 12 06:32:46 2007 +0100 @@ -0,0 +1,107 @@ + +// Copyright (C) 2001-2004 by Digital Mars, www.digitalmars.com +// All Rights Reserved +// Written by Walter Bright + +import std.c.linux.linuxextern; +import std.c.linux.linux; + +/+ +extern (C) +{ + // from + void* mmap(void* addr, uint len, int prot, int flags, int fd, uint offset); + int munmap(void* addr, uint len); + const void* MAP_FAILED = cast(void*)-1; + + // from + enum { PROT_NONE = 0, PROT_READ = 1, PROT_WRITE = 2, PROT_EXEC = 4 } + enum { MAP_SHARED = 1, MAP_PRIVATE = 2, MAP_TYPE = 0x0F, + MAP_FIXED = 0x10, MAP_FILE = 0, MAP_ANON = 0x20 } +} ++/ + +/*********************************** + * Map memory. + */ + +void *os_mem_map(uint nbytes) +{ void *p; + + //errno = 0; + p = mmap(null, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + return (p == MAP_FAILED) ? null : p; +} + +/*********************************** + * Commit memory. + * Returns: + * 0 success + * !=0 failure + */ + +int os_mem_commit(void *base, uint offset, uint nbytes) +{ + return 0; +} + + +/*********************************** + * Decommit memory. + * Returns: + * 0 success + * !=0 failure + */ + +int os_mem_decommit(void *base, uint offset, uint nbytes) +{ + return 0; +} + +/*********************************** + * Unmap memory allocated with os_mem_map(). + * Returns: + * 0 success + * !=0 failure + */ + +int os_mem_unmap(void *base, uint nbytes) +{ + return munmap(base, nbytes); +} + + +/********************************************** + * Determine "bottom" of stack (actually the top on x86 systems). + */ + +void *os_query_stackBottom() +{ + version (none) + { // See discussion: http://autopackage.org/forums/viewtopic.php?t=22 + static void** libc_stack_end; + + if (libc_stack_end == libc_stack_end.init) + { + void* handle = dlopen(null, RTLD_NOW); + libc_stack_end = cast(void **)dlsym(handle, "__libc_stack_end"); + dlclose(handle); + } + return *libc_stack_end; + } + else + { // This doesn't resolve on all versions of Linux + return __libc_stack_end; + } +} + + +/********************************************** + * Determine base address and size of static data segment. + */ + +void os_query_staticdataseg(void **base, uint *nbytes) +{ + *base = cast(void *)&__data_start; + *nbytes = cast(byte *)&_end - cast(byte *)&__data_start; +} diff -r 08508eebbb3e -r 61615fa85940 lphobos/gc/gcstub.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lphobos/gc/gcstub.d Mon Nov 12 06:32:46 2007 +0100 @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2004 by Digital Mars, www.digitalmars.com + * Written by Walter Bright + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * o The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ + +// D Garbage Collector stub to prevent linking in gc + +module gcx; + +//debug=PRINTF; + +/***************************************************/ + +import object; + +version (Win32) +{ + import win32; +} + +version (linux) +{ + import gclinux; +} + + +//alias GC* gc_t; +alias GC gc_t; + +struct GCStats { } + +/* ============================ GC =============================== */ + + +//alias int size_t; +alias void (*GC_FINALIZER)(void *p, void *dummy); + +const uint GCVERSION = 1; // increment every time we change interface + // to GC. + +class GC +{ + uint gcversion = GCVERSION; + + void *gcx; // implementation + + void initialize() + { + debug(PRINTF) printf("initialize()\n"); + } + + + void Dtor() + { + debug(PRINTF) printf("Dtor()\n"); + } + + /+invariant + { + debug(PRINTF) printf("invariant()\n"); + }+/ + + void *malloc(size_t size) + { + debug(PRINTF) printf("malloc()\n"); + return null; + } + + void *mallocNoSync(size_t size) + { + debug(PRINTF) printf("mallocNoSync()\n"); + return null; + } + + + void *calloc(size_t size, size_t n) + { + debug(PRINTF) printf("calloc()\n"); + return null; + } + + + void *realloc(void *p, size_t size) + { + debug(PRINTF) printf("realloc()\n"); + return null; + } + + + void free(void *p) + { + debug(PRINTF) printf("free()\n"); + } + + size_t capacity(void *p) + { + debug(PRINTF) printf("capacity()\n"); + return 0; + } + + void check(void *p) + { + debug(PRINTF) printf("check()\n"); + } + + + void setStackBottom(void *p) + { + debug(PRINTF) printf("setStackBottom()\n"); + } + + static void scanStaticData(gc_t g) + { + void *pbot; + void *ptop; + uint nbytes; + + debug(PRINTF) printf("scanStaticData()\n"); + //debug(PRINTF) printf("+GC.scanStaticData()\n"); + os_query_staticdataseg(&pbot, &nbytes); + ptop = pbot + nbytes; + g.addRange(pbot, ptop); + //debug(PRINTF) printf("-GC.scanStaticData()\n"); + } + + static void unscanStaticData(gc_t g) + { + void *pbot; + uint nbytes; + + debug(PRINTF) printf("unscanStaticData()\n"); + os_query_staticdataseg(&pbot, &nbytes); + g.removeRange(pbot); + } + + + void addRoot(void *p) // add p to list of roots + { + debug(PRINTF) printf("addRoot()\n"); + } + + void removeRoot(void *p) // remove p from list of roots + { + debug(PRINTF) printf("removeRoot()\n"); + } + + void addRange(void *pbot, void *ptop) // add range to scan for roots + { + debug(PRINTF) printf("addRange()\n"); + } + + void removeRange(void *pbot) // remove range + { + debug(PRINTF) printf("removeRange()\n"); + } + + void fullCollect() // do full garbage collection + { + debug(PRINTF) printf("fullCollect()\n"); + } + + void fullCollectNoStack() // do full garbage collection + { + debug(PRINTF) printf("fullCollectNoStack()\n"); + } + + void genCollect() // do generational garbage collection + { + debug(PRINTF) printf("genCollect()\n"); + } + + void minimize() // minimize physical memory usage + { + debug(PRINTF) printf("minimize()\n"); + } + + void setFinalizer(void *p, GC_FINALIZER pFn) + { + debug(PRINTF) printf("setFinalizer()\n"); + } + + void enable() + { + debug(PRINTF) printf("enable()\n"); + } + + void disable() + { + debug(PRINTF) printf("disable()\n"); + } + + void getStats(out GCStats stats) + { + debug(PRINTF) printf("getStats()\n"); + } +} diff -r 08508eebbb3e -r 61615fa85940 lphobos/internal/adi.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lphobos/internal/adi.d Mon Nov 12 06:32:46 2007 +0100 @@ -0,0 +1,803 @@ +//_ adi.d + +/** + * Part of the D programming language runtime library. + * Dynamic array property support routines + */ + +/* + * Copyright (C) 2000-2006 by Digital Mars, www.digitalmars.com + * Written by Walter Bright + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, in both source and binary form, subject to the following + * restrictions: + * + * o The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ + +//debug=adi; // uncomment to turn on debugging printf's + +//import std.stdio; +import std.c.stdio; +import std.c.stdlib; +import std.c.string; +//import std.string; +import std.outofmemory; +import std.utf; + +struct Array +{ + size_t length; + void* ptr; +} + +/********************************************** + * Reverse array of chars. + * Handled separately because embedded multibyte encodings should not be + * reversed. + */ + +extern (C) long _adReverseChar(char[] a) +{ + if (a.length > 1) + { + char[6] tmp; + char[6] tmplo; + char* lo = a.ptr; + char* hi = &a[length - 1]; + + while (lo < hi) + { auto clo = *lo; + auto chi = *hi; + + //printf("lo = %d, hi = %d\n", lo, hi); + if (clo <= 0x7F && chi <= 0x7F) + { + //printf("\tascii\n"); + *lo = chi; + *hi = clo; + lo++; + hi--; + continue; + } + + uint stridelo = std.utf.UTF8stride[clo]; + + uint stridehi = 1; + while ((chi & 0xC0) == 0x80) + { + chi = *--hi; + stridehi++; + assert(hi >= lo); + } + if (lo == hi) + break; + + //printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi); + if (stridelo == stridehi) + { + + memcpy(tmp.ptr, lo, stridelo); + memcpy(lo, hi, stridelo); + memcpy(hi, tmp.ptr, stridelo); + lo += stridelo; + hi--; + continue; + } + + /* Shift the whole array. This is woefully inefficient + */ + memcpy(tmp.ptr, hi, stridehi); + memcpy(tmplo.ptr, lo, stridelo); + memmove(lo + stridehi, lo + stridelo , (hi - lo) - stridelo); + memcpy(lo, tmp.ptr, stridehi); + memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo); + + lo += stridehi; + hi = hi - 1 + (stridehi - stridelo); + } + } + return *cast(long*)(&a); +} + +unittest +{ + string a = "abcd"; + string r; + + r = a.dup.reverse; + //writefln(r); + assert(r == "dcba"); + + a = "a\u1235\u1234c"; + //writefln(a); + r = a.dup.reverse; + //writefln(r); + assert(r == "c\u1234\u1235a"); + + a = "ab\u1234c"; + //writefln(a); + r = a.dup.reverse; + //writefln(r); + assert(r == "c\u1234ba"); + + a = "\u3026\u2021\u3061\n"; + r = a.dup.reverse; + assert(r == "\n\u3061\u2021\u3026"); +} + + +/********************************************** + * Reverse array of wchars. + * Handled separately because embedded multiword encodings should not be + * reversed. + */ + +extern (C) long _adReverseWchar(wchar[] a) +{ + if (a.length > 1) + { + wchar[2] tmp; + wchar* lo = a.ptr; + wchar* hi = &a[length - 1]; + + while (lo < hi) + { auto clo = *lo; + auto chi = *hi; + + if ((clo < 0xD800 || clo > 0xDFFF) && + (chi < 0xD800 || chi > 0xDFFF)) + { + *lo = chi; + *hi = clo; + lo++; + hi--; + continue; + } + + int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF); + + int stridehi = 1; + if (chi >= 0xDC00 && chi <= 0xDFFF) + { + chi = *--hi; + stridehi++; + assert(hi >= lo); + } + if (lo == hi) + break; + + if (stridelo == stridehi) + { int stmp; + + assert(stridelo == 2); + assert(stmp.sizeof == 2 * (*lo).sizeof); + stmp = *cast(int*)lo; + *cast(int*)lo = *cast(int*)hi; + *cast(int*)hi = stmp; + lo += stridelo; + hi--; + continue; + } + + /* Shift the whole array. This is woefully inefficient + */ + memcpy(tmp.ptr, hi, stridehi * wchar.sizeof); + memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof); + memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof); + memcpy(lo, tmp.ptr, stridehi * wchar.sizeof); + + lo += stridehi; + hi = hi - 1 + (stridehi - stridelo); + } + } + return *cast(long*)(&a); +} + +unittest +{ + wstring a = "abcd"; + wstring r; + + r = a.dup.reverse; + assert(r == "dcba"); + + a = "a\U00012356\U00012346c"; + r = a.dup.reverse; + assert(r == "c\U00012346\U00012356a"); + + a = "ab\U00012345c"; + r = a.dup.reverse; + assert(r == "c\U00012345ba"); +} + + +/********************************************** + * Support for array.reverse property. + */ + +extern (C) long _adReverse(Array a, size_t szelem) + out (result) + { + assert(result is *cast(long*)(&a)); + } + body + { + if (a.length >= 2) + { + byte* tmp; + byte[16] buffer; + + void* lo = a.ptr; + void* hi = a.ptr + (a.length - 1) * szelem; + + tmp = buffer.ptr; + if (szelem > 16) + { + //version (Win32) + tmp = cast(byte*) alloca(szelem); + //else + //tmp = new byte[szelem]; + } + + for (; lo < hi; lo += szelem, hi -= szelem) + { + memcpy(tmp, lo, szelem); + memcpy(lo, hi, szelem); + memcpy(hi, tmp, szelem); + } + + version (Win32) + { + } + else + { + //if (szelem > 16) + // BUG: bad code is generate for delete pointer, tries + // to call delclass. + //delete tmp; + } + } + return *cast(long*)(&a); + } + +unittest +{ + debug(adi) printf("array.reverse.unittest\n"); + + int[] a = new int[5]; + int[] b; + size_t i; + + for (i = 0; i < 5; i++) + a[i] = i; + b = a.reverse; + assert(b is a); + for (i = 0; i < 5; i++) + assert(a[i] == 4 - i); + + struct X20 + { // More than 16 bytes in size + int a; + int b, c, d, e; + } + + X20[] c = new X20[5]; + X20[] d; + + for (i = 0; i < 5; i++) + { c[i].a = i; + c[i].e = 10; + } + d = c.reverse; + assert(d is c); + for (i = 0; i < 5; i++) + { + assert(c[i].a == 4 - i); + assert(c[i].e == 10); + } +} + +/********************************************** + * Support for array.reverse property for bit[]. + */ + +version (none) +{ +extern (C) bit[] _adReverseBit(bit[] a) + out (result) + { + assert(result is a); + } + body + { + if (a.length >= 2) + { + bit t; + int lo, hi; + + lo = 0; + hi = a.length - 1; + for (; lo < hi; lo++, hi--) + { + t = a[lo]; + a[lo] = a[hi]; + a[hi] = t; + } + } + return a; + } + +unittest +{ + debug(adi) printf("array.reverse_Bit[].unittest\n"); + + bit[] b; + b = new bit[5]; + static bit[5] data = [1,0,1,1,0]; + int i; + + b[] = data[]; + b.reverse; + for (i = 0; i < 5; i++) + { + assert(b[i] == data[4 - i]); + } +} +} + +/********************************************** + * Sort array of chars. + */ + +extern (C) long _adSortChar(char[] a) +{ + if (a.length > 1) + { + dstring da = toUTF32(a); + da.sort; + size_t i = 0; + foreach (dchar d; da) + { char[4] buf; + string t = toUTF8(buf, d); + a[i .. i + t.length] = t[]; + i += t.length; + } + delete da; + } + return *cast(long*)(&a); +} + +/********************************************** + * Sort array of wchars. + */ + +extern (C) long _adSortWchar(wchar[] a) +{ + if (a.length > 1) + { + dstring da = toUTF32(a); + da.sort; + size_t i = 0; + foreach (dchar d; da) + { wchar[2] buf; + wstring t = toUTF16(buf, d); + a[i .. i + t.length] = t[]; + i += t.length; + } + delete da; + } + return *cast(long*)(&a); +} + +/********************************************** + * Support for array.sort property for bit[]. + */ + +version (none) +{ +extern (C) bit[] _adSortBit(bit[] a) + out (result) + { + assert(result is a); + } + body + { + if (a.length >= 2) + { + size_t lo, hi; + + lo = 0; + hi = a.length - 1; + while (1) + { + while (1) + { + if (lo >= hi) + goto Ldone; + if (a[lo] == true) + break; + lo++; + } + + while (1) + { + if (lo >= hi) + goto Ldone; + if (a[hi] == false) + break; + hi--; + } + + a[lo] = false; + a[hi] = true; + + lo++; + hi--; + } + Ldone: + ; + } + return a; + } + +unittest +{ + debug(adi) printf("array.sort_Bit[].unittest\n"); +} +} + +/*************************************** + * Support for array equality test. + */ + +extern (C) int _adEq(Array a1, Array a2, TypeInfo ti) +{ + //printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); + if (a1.length != a2.length) + return 0; // not equal + auto sz = ti.tsize(); + auto p1 = a1.ptr; + auto p2 = a2.ptr; + +/+ + for (int i = 0; i < a1.length; i++) + { + printf("%4x %4x\n", (cast(short*)p1)[i], (cast(short*)p2)[i]); + } ++/ + + if (sz == 1) + // We should really have a ti.isPOD() check for this + return (memcmp(p1, p2, a1.length) == 0); + + for (size_t i = 0; i < a1.length; i++) + { + if (!ti.equals(p1 + i * sz, p2 + i * sz)) + return 0; // not equal + } + return 1; // equal +} + +unittest +{ + debug(adi) printf("array.Eq unittest\n"); + + string a = "hello"; + + assert(a != "hel"); + assert(a != "helloo"); + assert(a != "betty"); + assert(a == "hello"); + assert(a != "hxxxx"); +} + +/*************************************** + * Support for array equality test for bit arrays. + */ + +version (none) +{ +extern (C) int _adEqBit(Array a1, Array a2) +{ size_t i; + + if (a1.length != a2.length) + return 0; // not equal + auto p1 = cast(byte*)a1.ptr; + auto p2 = cast(byte*)a2.ptr; + auto n = a1.length / 8; + for (i = 0; i < n; i++) + { + if (p1[i] != p2[i]) + return 0; // not equal + } + + ubyte mask; + + n = a1.length & 7; + mask = cast(ubyte)((1 << n) - 1); + //printf("i = %d, n = %d, mask = %x, %x, %x\n", i, n, mask, p1[i], p2[i]); + return (mask == 0) || (p1[i] & mask) == (p2[i] & mask); +} + +unittest +{ + debug(adi) printf("array.EqBit unittest\n"); + + static bit[] a = [1,0,1,0,1]; + static bit[] b = [1,0,1]; + static bit[] c = [1,0,1,0,1,0,1]; + static bit[] d = [1,0,1,1,1]; + static bit[] e = [1,0,1,0,1]; + + assert(a != b); + assert(a != c); + assert(a != d); + assert(a == e); +} +} + +/*************************************** + * Support for array compare test. + */ + +extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti) +{ + //printf("adCmp()\n"); + auto len = a1.length; + if (a2.length < len) + len = a2.length; + auto sz = ti.tsize(); + void *p1 = a1.ptr; + void *p2 = a2.ptr; + + if (sz == 1) + { // We should really have a ti.isPOD() check for this + auto c = memcmp(p1, p2, len); + if (c) + return c; + } + else + { + for (size_t i = 0; i < len; i++) + { + auto c = ti.compare(p1 + i * sz, p2 + i * sz); + if (c) + return c; + } + } + if (a1.length == a2.length) + return 0; + return (a1.length > a2.length) ? 1 : -1; +} + +unittest +{ + debug(adi) printf("array.Cmp unittest\n"); + + string a = "hello"; + + assert(a > "hel"); + assert(a >= "hel"); + assert(a < "helloo"); + assert(a <= "helloo"); + assert(a > "betty"); + assert(a >= "betty"); + assert(a == "hello"); + assert(a <= "hello"); + assert(a >= "hello"); +} + +/*************************************** + * Support for array compare test. + */ + +extern (C) int _adCmpChar(Array a1, Array a2) +{ +version (D_InlineAsm_X86) +{ + asm + { naked ; + + push EDI ; + push ESI ; + + mov ESI,a1+4[4+ESP] ; + mov EDI,a2+4[4+ESP] ; + + mov ECX,a1[4+ESP] ; + mov EDX,a2[4+ESP] ; + + cmp ECX,EDX ; + jb GotLength ; + + mov ECX,EDX ; + +GotLength: + cmp ECX,4 ; + jb DoBytes ; + + // Do alignment if neither is dword aligned + test ESI,3 ; + jz Aligned ; + + test EDI,3 ; + jz Aligned ; +DoAlign: + mov AL,[ESI] ; //align ESI to dword bounds + mov DL,[EDI] ; + + cmp AL,DL ; + jnz Unequal ; + + inc ESI ; + inc EDI ; + + test ESI,3 ; + + lea ECX,[ECX-1] ; + jnz DoAlign ; +Aligned: + mov EAX,ECX ; + + // do multiple of 4 bytes at a time + + shr ECX,2 ; + jz TryOdd ; + + repe ; + cmpsd ; + + jnz UnequalQuad ; + +TryOdd: + mov ECX,EAX ; +DoBytes: + // if still equal and not end of string, do up to 3 bytes slightly + // slower. + + and ECX,3 ; + jz Equal ; + + repe ; + cmpsb ; + + jnz Unequal ; +Equal: + mov EAX,a1[4+ESP] ; + mov EDX,a2[4+ESP] ; + + sub EAX,EDX ; + pop ESI ; + + pop EDI ; + ret ; + +UnequalQuad: + mov EDX,[EDI-4] ; + mov EAX,[ESI-4] ; + + cmp AL,DL ; + jnz Unequal ; + + cmp AH,DH ; + jnz Unequal ; + + shr EAX,16 ; + + shr EDX,16 ; + + cmp AL,DL ; + jnz Unequal ; + + cmp AH,DH ; +Unequal: + sbb EAX,EAX ; + pop ESI ; + + or EAX,1 ; + pop EDI ; + + ret ; + } +} +else +{ + int len; + int c; + + //printf("adCmpChar()\n"); + len = a1.length; + if (a2.length < len) + len = a2.length; + c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len); + if (!c) + c = cast(int)a1.length - cast(int)a2.length; + return c; +} +} + +unittest +{ + debug(adi) printf("array.CmpChar unittest\n"); + + string a = "hello"; + + assert(a > "hel"); + assert(a >= "hel"); + assert(a < "helloo"); + assert(a <= "helloo"); + assert(a > "betty"); + assert(a >= "betty"); + assert(a == "hello"); + assert(a <= "hello"); + assert(a >= "hello"); +} + +/*************************************** + * Support for array compare test. + */ + +version (none) +{ +extern (C) int _adCmpBit(Array a1, Array a2) +{ + int len; + uint i; + + len = a1.length; + if (a2.length < len) + len = a2.length; + ubyte *p1 = cast(ubyte*)a1.ptr; + ubyte *p2 = cast(ubyte*)a2.ptr; + uint n = len / 8; + for (i = 0; i < n; i++) + { + if (p1[i] != p2[i]) + break; // not equal + } + for (uint j = i * 8; j < len; j++) + { ubyte mask = cast(ubyte)(1 << j); + int c; + + c = cast(int)(p1[i] & mask) - cast(int)(p2[i] & mask); + if (c) + return c; + } + return cast(int)a1.length - cast(int)a2.length; +} + +unittest +{ + debug(adi) printf("array.CmpBit unittest\n"); + + static bit[] a = [1,0,1,0,1]; + static bit[] b = [1,0,1]; + static bit[] c = [1,0,1,0,1,0,1]; + static bit[] d = [1,0,1,1,1]; + static bit[] e = [1,0,1,0,1]; + + assert(a > b); + assert(a >= b); + assert(a < c); + assert(a <= c); + assert(a < d); + assert(a <= d); + assert(a == e); + assert(a <= e); + assert(a >= e); +} +} diff -r 08508eebbb3e -r 61615fa85940 lphobos/internal/arrays.d --- a/lphobos/internal/arrays.d Thu Nov 08 19:21:05 2007 +0100 +++ b/lphobos/internal/arrays.d Mon Nov 12 06:32:46 2007 +0100 @@ -143,11 +143,3 @@ res[i] = v[0 .. strlen(v)]; } } - - - - - - - - diff -r 08508eebbb3e -r 61615fa85940 lphobos/internal/contract.d --- a/lphobos/internal/contract.d Thu Nov 08 19:21:05 2007 +0100 +++ b/lphobos/internal/contract.d Mon Nov 12 06:32:46 2007 +0100 @@ -4,10 +4,10 @@ void exit(int); -void _d_assert(bool cond, uint line, char* msg) +void _d_assert(bool cond, uint line, char[] msg) { if (!cond) { - printf("Aborted(%u): %s\n", line, msg); + printf("Aborted(%u): %.*s\n", line, msg.length, msg.ptr); exit(1); } } diff -r 08508eebbb3e -r 61615fa85940 lphobos/internal/qsort2.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lphobos/internal/qsort2.d Mon Nov 12 06:32:46 2007 +0100 @@ -0,0 +1,68 @@ + +/* + * Placed into Public Domain + * written by Walter Bright + * www.digitalmars.com + * + * This is a public domain version of qsort.d. + * All it does is call C's qsort(), but runs a little slower since + * it needs to synchronize a global variable. + */ + + +//debug=qsort; + +import std.c.stdlib; + +struct Array +{ + size_t length; + void *ptr; +} + +private TypeInfo tiglobal; + +extern (C) int cmp(void* p1, void* p2) +{ + return tiglobal.compare(p1, p2); +} + +extern (C) long _adSort(Array a, TypeInfo ti) +{ + synchronized + { + tiglobal = ti; + std.c.stdlib.qsort(a.ptr, a.length, cast(size_t)ti.tsize(), &cmp); + } + return *cast(long*)(&a); +} + + + +unittest +{ + debug(qsort) printf("array.sort.unittest()\n"); + + int a[] = new int[10]; + + a[0] = 23; + a[1] = 1; + a[2] = 64; + a[3] = 5; + a[4] = 6; + a[5] = 5; + a[6] = 17; + a[7] = 3; + a[8] = 0; + a[9] = -1; + + a.sort; + + for (int i = 0; i < a.length - 1; i++) + { + //printf("i = %d", i); + //printf(" %d %d\n", a[i], a[i + 1]); + assert(a[i] <= a[i + 1]); + } +} + diff -r 08508eebbb3e -r 61615fa85940 lphobos/std/c/stdlib.d --- a/lphobos/std/c/stdlib.d Thu Nov 08 19:21:05 2007 +0100 +++ b/lphobos/std/c/stdlib.d Mon Nov 12 06:32:46 2007 +0100 @@ -42,6 +42,7 @@ int system(char *); + pragma(LLVM_internal, "alloca") void *alloca(uint); /// void *calloc(size_t, size_t); /// diff -r 08508eebbb3e -r 61615fa85940 lphobos/std/stdio.d --- a/lphobos/std/stdio.d Thu Nov 08 19:21:05 2007 +0100 +++ b/lphobos/std/stdio.d Mon Nov 12 06:32:46 2007 +0100 @@ -3,23 +3,42 @@ import std.traits; void _writef(T)(T t) { - static if(is(T: Object)) _writef(t.toString()); else - static if(is(T==char)) printf("%c", t); else - static if(is(T: char[])) printf("%.*s", t.length, t.ptr); else - static if(isArray!(T)) { - _writef('['); - if (t.length) _writef(t[0]); - for (int i=1; i