From 48492229ec06daac7e6b503a0f99d61ab86f65d7 Mon Sep 17 00:00:00 2001 From: Tomas Lindquist Olsen Date: Sat, 3 Nov 2007 14:44:58 +0100 Subject: [PATCH] [svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!! Lots of bugfixes. Added support for special foreach on strings. Added std.array, std.utf, std.ctype and std.uni to phobos. Changed all the .c files in the gen dir to .cpp (it *is* C++ after all) --- dmd/declaration.h | 1 + dmd/expression.h | 5 + dmd/func.c | 1 + dmd/module.h | 7 +- dmd/statement.c | 4 +- dmd/statement.h | 15 +- gen/{arrays.c => arrays.cpp} | 172 ++- gen/arrays.h | 11 +- gen/binops.cpp | 56 + gen/{dwarftypes.c => dwarftypes.cpp} | 0 gen/{elem.c => elem.cpp} | 19 +- gen/elem.h | 16 +- gen/{irstate.c => irstate.cpp} | 2 +- gen/irstate.h | 6 +- gen/{logger.c => logger.cpp} | 0 gen/{runtime.c => runtime.cpp} | 0 gen/{statements.c => statements.cpp} | 110 +- gen/{tocsym.c => tocsym.cpp} | 0 gen/{todebug.c => todebug.cpp} | 0 gen/{todt.c => todt.cpp} | 0 gen/{toir.c => toir.cpp} | 1594 ++++++++++++-------------- gen/{tollvm.c => tollvm.cpp} | 170 ++- gen/tollvm.h | 27 +- gen/{toobj.c => toobj.cpp} | 21 +- gen/{typinf.c => typinf.cpp} | 0 lphobos/build.sh | 15 +- lphobos/internal/aApply.d | 410 +++++++ lphobos/internal/aApplyR.d | 977 ++++++++++++++++ lphobos/internal/objectimpl.d | 6 + lphobos/phobos.d | 6 +- lphobos/std/array.d | 38 + lphobos/std/ctype.d | 154 +++ lphobos/std/uni.d | 630 ++++++++++ lphobos/std/utf.d | 969 ++++++++++++++++ premake.lua | 4 +- test/arrays10.d | 7 + test/arrays7.d | 11 + test/arrays9.d | 8 + test/b.d | 4 +- test/bitops.d | 4 +- test/bug48.d | 10 + test/bug49.d | 16 + test/bug50.d | 28 + 43 files changed, 4517 insertions(+), 1017 deletions(-) rename gen/{arrays.c => arrays.cpp} (83%) create mode 100644 gen/binops.cpp rename gen/{dwarftypes.c => dwarftypes.cpp} (100%) rename gen/{elem.c => elem.cpp} (80%) rename gen/{irstate.c => irstate.cpp} (93%) rename gen/{logger.c => logger.cpp} (100%) rename gen/{runtime.c => runtime.cpp} (100%) rename gen/{statements.c => statements.cpp} (90%) rename gen/{tocsym.c => tocsym.cpp} (100%) rename gen/{todebug.c => todebug.cpp} (100%) rename gen/{todt.c => todt.cpp} (100%) rename gen/{toir.c => toir.cpp} (73%) rename gen/{tollvm.c => tollvm.cpp} (90%) rename gen/{toobj.c => toobj.cpp} (95%) rename gen/{typinf.c => typinf.cpp} (100%) create mode 100644 lphobos/internal/aApply.d create mode 100644 lphobos/internal/aApplyR.d create mode 100644 lphobos/std/array.d create mode 100644 lphobos/std/ctype.d create mode 100644 lphobos/std/uni.d create mode 100644 lphobos/std/utf.d create mode 100644 test/arrays10.d create mode 100644 test/arrays9.d create mode 100644 test/bug48.d create mode 100644 test/bug49.d create mode 100644 test/bug50.d diff --git a/dmd/declaration.h b/dmd/declaration.h index 8bc76e57..2a9647e4 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -527,6 +527,7 @@ struct FuncDeclaration : Declaration llvm::Value* llvmArguments; llvm::Value* llvmArgPtr; llvm::Constant* llvmDwarfSubProgram; + bool llvmRunTimeHack; }; struct FuncAliasDeclaration : FuncDeclaration diff --git a/dmd/expression.h b/dmd/expression.h index 98d9a5c3..664ce2b3 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -56,11 +56,16 @@ enum TOK; struct IRState; struct dt_t; +#if IN_LLVM +struct DValue; +typedef DValue elem; +#else #ifdef IN_GCC union tree_node; typedef union tree_node elem; #else struct elem; #endif +#endif void initPrecedence(); diff --git a/dmd/func.c b/dmd/func.c index 3bea465b..72a2b2b1 100644 --- a/dmd/func.c +++ b/dmd/func.c @@ -79,6 +79,7 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC s llvmArguments = NULL; llvmArgPtr = NULL; llvmDwarfSubProgram = NULL; + llvmRunTimeHack = false; } Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s) diff --git a/dmd/module.h b/dmd/module.h index df86002d..ceacfeec 100644 --- a/dmd/module.h +++ b/dmd/module.h @@ -26,11 +26,16 @@ struct Escape; struct VarDeclaration; // Back end -#if IN_GCC +#if IN_LLVM +struct DValue; +typedef DValue elem; +#else +#ifdef IN_GCC union tree_node; typedef union tree_node elem; #else struct elem; #endif +#endif struct Package : ScopeDsymbol { diff --git a/dmd/statement.c b/dmd/statement.c index b3dc416a..c0a0a672 100644 --- a/dmd/statement.c +++ b/dmd/statement.c @@ -1438,6 +1438,7 @@ Statement *ForeachStatement::semantic(Scope *sc) fdapply = FuncDeclaration::genCfunc(Type::tindex, "_aaApply2"); else fdapply = FuncDeclaration::genCfunc(Type::tindex, "_aaApply"); + fdapply->llvmRunTimeHack = true; ec = new VarExp(0, fdapply); Expressions *exps = new Expressions(); exps->push(aggr); @@ -1479,6 +1480,7 @@ Statement *ForeachStatement::semantic(Scope *sc) int j = sprintf(fdname, "_aApply%s%.*s%d", r, 2, fntab[flag], dim); assert(j < sizeof(fdname)); fdapply = FuncDeclaration::genCfunc(Type::tindex, fdname); + fdapply->llvmRunTimeHack = true; ec = new VarExp(0, fdapply); Expressions *exps = new Expressions(); @@ -3464,7 +3466,7 @@ LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement) this->statement = statement; this->tf = NULL; this->lblock = NULL; - this->isReturnLabel = 0; + this->isReturnLabel = 0; this->llvmBB = NULL; } diff --git a/dmd/statement.h b/dmd/statement.h index 2b6ed9ca..6fa73d12 100644 --- a/dmd/statement.h +++ b/dmd/statement.h @@ -51,19 +51,24 @@ enum TOK; namespace llvm { - class Value; + class Value; class BasicBlock; } // Back end struct IRState; struct Blockx; +#if IN_LLVM +struct DValue; +typedef DValue elem; +#endif + #if IN_GCC union tree_node; typedef union tree_node block; -union tree_node; typedef union tree_node elem; +//union tree_node; typedef union tree_node elem; #else struct block; -struct elem; +//struct elem; #endif struct code; @@ -715,8 +720,8 @@ struct LabelStatement : Statement Statement *inlineScan(InlineScanState *iss); - void toIR(IRState *irs); - + void toIR(IRState *irs); + llvm::BasicBlock* llvmBB; }; diff --git a/gen/arrays.c b/gen/arrays.cpp similarity index 83% rename from gen/arrays.c rename to gen/arrays.cpp index 16a319bc..5cbdbe81 100644 --- a/gen/arrays.c +++ b/gen/arrays.cpp @@ -11,7 +11,7 @@ #include "gen/arrays.h" #include "gen/runtime.h" #include "gen/logger.h" -#include "gen/elem.h" +#include "gen/dvalue.h" ////////////////////////////////////////////////////////////////////////////////////////// @@ -125,17 +125,18 @@ void DtoArrayInit(llvm::Value* l, llvm::Value* r) { const llvm::PointerType* ptrty = llvm::cast(l->getType()); const llvm::Type* t = ptrty->getContainedType(0); - const llvm::ArrayType* arrty = llvm::cast_or_null(t); + const llvm::ArrayType* arrty = llvm::dyn_cast(t); if (arrty) { llvm::Value* ptr = DtoGEPi(l,0,0,"tmp",gIR->scopebb()); llvm::Value* dim = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false); - llvm::Value* val = r; - DtoArrayInit(ptr, dim, val); + DtoArrayInit(ptr, dim, r); } else if (llvm::isa(t)) { - assert(0 && "Only static arrays support initialisers atm"); + llvm::Value* dim = DtoLoad(DtoGEPi(l, 0,0, "tmp")); + llvm::Value* ptr = DtoLoad(DtoGEPi(l, 0,1, "tmp")); + DtoArrayInit(ptr, dim, r); } else assert(0); @@ -159,6 +160,8 @@ static size_t checkRectArrayInit(const llvm::Type* pt, constLLVMTypeP& finalty) void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val) { + Logger::println("HELLO"); + Logger::cout() << "array: " << *ptr << " dim: " << *dim << " val: " << *val << '\n'; const llvm::Type* pt = ptr->getType()->getContainedType(0); const llvm::Type* t = val->getType(); const llvm::Type* finalTy; @@ -250,9 +253,20 @@ llvm::Constant* DtoConstArrayInitializer(ArrayInitializer* arrinit) { Logger::println("arr init begin"); Type* arrinittype = DtoDType(arrinit->type); - assert(arrinittype->ty == Tsarray); - TypeSArray* t = (TypeSArray*)arrinittype; - integer_t tdim = t->dim->toInteger(); + + Type* t; + integer_t tdim; + if (arrinittype->ty == Tsarray) { + TypeSArray* tsa = (TypeSArray*)arrinittype; + tdim = tsa->dim->toInteger(); + t = tsa; + } + else if (arrinittype->ty == Tarray) { + t = arrinittype; + tdim = arrinit->dim; + } + else + assert(0); std::vector inits(tdim, 0); @@ -308,32 +322,41 @@ llvm::Constant* DtoConstArrayInitializer(ArrayInitializer* arrinit) inits[i] = v; } - const llvm::ArrayType* arrty = DtoStaticArrayType(t); - return llvm::ConstantArray::get(arrty, inits); + const llvm::ArrayType* arrty = llvm::ArrayType::get(elemty,tdim); + llvm::Constant* constarr = llvm::ConstantArray::get(arrty, inits); + + if (arrinittype->ty == Tsarray) + return constarr; + else + assert(arrinittype->ty == Tarray); + + llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrty,true,llvm::GlobalValue::InternalLinkage,constarr,"constarray",gIR->module); + llvm::Constant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) }; + llvm::Constant* gep = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2); + return DtoConstSlice(DtoConstSize_t(tdim),gep); } ////////////////////////////////////////////////////////////////////////////////////////// -static llvm::Value* get_slice_ptr(elem* e, llvm::Value*& sz) +static llvm::Value* get_slice_ptr(DSliceValue* e, llvm::Value*& sz) { - assert(e->mem); - const llvm::Type* t = e->mem->getType()->getContainedType(0); + const llvm::Type* t = e->ptr->getType()->getContainedType(0); llvm::Value* ret = 0; - if (e->arg != 0) { + if (e->len != 0) { // this means it's a real slice - ret = e->mem; + ret = e->ptr; size_t elembsz = gTargetData->getTypeSize(ret->getType()); llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false); - if (llvm::isa(e->arg)) { - sz = llvm::ConstantExpr::getMul(elemsz, llvm::cast(e->arg)); + if (llvm::isa(e->len)) { + sz = llvm::ConstantExpr::getMul(elemsz, llvm::cast(e->len)); } else { - sz = llvm::BinaryOperator::createMul(elemsz,e->arg,"tmp",gIR->scopebb()); + sz = llvm::BinaryOperator::createMul(elemsz,e->len,"tmp",gIR->scopebb()); } } else if (llvm::isa(t)) { - ret = DtoGEPi(e->mem, 0, 0, "tmp", gIR->scopebb()); + ret = DtoGEPi(e->ptr, 0, 0, "tmp", gIR->scopebb()); size_t elembsz = gTargetData->getTypeSize(ret->getType()->getContainedType(0)); llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false); @@ -344,13 +367,13 @@ static llvm::Value* get_slice_ptr(elem* e, llvm::Value*& sz) sz = llvm::ConstantExpr::getMul(elemsz, nelems); } else if (llvm::isa(t)) { - ret = DtoGEPi(e->mem, 0, 1, "tmp", gIR->scopebb()); + ret = DtoGEPi(e->ptr, 0, 1, "tmp", gIR->scopebb()); ret = new llvm::LoadInst(ret, "tmp", gIR->scopebb()); size_t elembsz = gTargetData->getTypeSize(ret->getType()->getContainedType(0)); llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false); - llvm::Value* len = DtoGEPi(e->mem, 0, 0, "tmp", gIR->scopebb()); + llvm::Value* len = DtoGEPi(e->ptr, 0, 0, "tmp", gIR->scopebb()); len = new llvm::LoadInst(len, "tmp", gIR->scopebb()); sz = llvm::BinaryOperator::createMul(len,elemsz,"tmp",gIR->scopebb()); } @@ -360,13 +383,8 @@ static llvm::Value* get_slice_ptr(elem* e, llvm::Value*& sz) return ret; } -void DtoArrayCopy(elem* dst, elem* src) +void DtoArrayCopy(DSliceValue* dst, DSliceValue* src) { - Logger::cout() << "Array copy ((((" << *src->mem << ")))) into ((((" << *dst->mem << "))))\n"; - - assert(dst->type == elem::SLICE); - assert(src->type == elem::SLICE); - llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); llvm::Value* sz1; @@ -435,9 +453,8 @@ llvm::Value* DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, Type* dty, bool llvm::Value* newptr = DtoRealloc(nullptr, bytesize); if (doinit) { - elem* e = dty->defaultInit()->toElem(gIR); - DtoArrayInit(newptr,dim,e->getValue()); - delete e; + DValue* e = dty->defaultInit()->toElem(gIR); + DtoArrayInit(newptr,dim,e->getRVal()); } llvm::Value* lenptr = DtoGEPi(dst,0,0,"tmp",gIR->scopebb()); @@ -449,7 +466,7 @@ llvm::Value* DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, Type* dty, bool } ////////////////////////////////////////////////////////////////////////////////////////// -void DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz) +llvm::Value* DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz) { llvm::Value* ptr = DtoGEPi(arr, 0, 1, "tmp", gIR->scopebb()); llvm::Value* ptrld = new llvm::LoadInst(ptr,"tmp",gIR->scopebb()); @@ -463,25 +480,52 @@ void DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz) llvm::Value* len = DtoGEPi(arr, 0, 0, "tmp", gIR->scopebb()); new llvm::StoreInst(sz,len,gIR->scopebb()); + + return newptr; } ////////////////////////////////////////////////////////////////////////////////////////// void DtoCatAssignElement(llvm::Value* arr, Expression* exp) { - llvm::Value* ptr = DtoGEPi(arr, 0, 0, "tmp", gIR->scopebb()); - llvm::Value* idx = new llvm::LoadInst(ptr, "tmp", gIR->scopebb()); + llvm::Value* ptr = DtoGEPi(arr, 0, 0, "tmp"); + llvm::Value* idx = DtoLoad(ptr); llvm::Value* one = llvm::ConstantInt::get(idx->getType(),1,false); llvm::Value* len = llvm::BinaryOperator::createAdd(idx, one, "tmp", gIR->scopebb()); DtoResizeDynArray(arr,len); - ptr = DtoGEPi(arr, 0, 1, "tmp", gIR->scopebb()); - ptr = new llvm::LoadInst(ptr, "tmp", gIR->scopebb()); + ptr = DtoLoad(DtoGEPi(arr, 0, 1, "tmp")); ptr = new llvm::GetElementPtrInst(ptr, idx, "tmp", gIR->scopebb()); - elem* e = exp->toElem(gIR); - Type* et = DtoDType(exp->type); - DtoAssign(et, ptr, e->getValue()); - delete e; + DValue* dptr = new DVarValue(exp->type, ptr, true); + + gIR->exps.push_back(IRExp(0,exp,dptr)); + DValue* e = exp->toElem(gIR); + gIR->exps.pop_back(); + + if (!e->inPlace()) + DtoAssign(dptr, e); +} + +////////////////////////////////////////////////////////////////////////////////////////// +void DtoCatAssignArray(llvm::Value* arr, Expression* exp) +{ + DValue* e = exp->toElem(gIR); + + llvm::Value *len1, *len2, *src1, *src2, *res; + + DValue* darr = new DVarValue(exp->type, arr, true); + + len1 = DtoArrayLen(darr); + len2 = DtoArrayLen(e); + res = gIR->ir->CreateAdd(len1,len2,"tmp"); + + llvm::Value* mem = DtoResizeDynArray(arr,res); + + src1 = DtoArrayPtr(darr); + src2 = DtoArrayPtr(e); + + mem = gIR->ir->CreateGEP(mem,len1,"tmp"); + DtoMemCpy(mem,src2,len2); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -493,13 +537,11 @@ void DtoCatArrays(llvm::Value* arr, Expression* exp1, Expression* exp2) assert(t1->ty == Tarray); assert(t1->ty == t2->ty); - elem* e1 = exp1->toElem(gIR); - llvm::Value* a = e1->getValue(); - delete e1; + DValue* e1 = exp1->toElem(gIR); + llvm::Value* a = e1->getRVal(); - elem* e2 = exp2->toElem(gIR); - llvm::Value* b = e2->getValue(); - delete e2; + DValue* e2 = exp2->toElem(gIR); + llvm::Value* b = e2->getRVal(); llvm::Value *len1, *len2, *src1, *src2, *res; len1 = gIR->ir->CreateLoad(DtoGEPi(a,0,0,"tmp"),"tmp"); @@ -670,3 +712,43 @@ llvm::Constant* DtoConstStaticArray(const llvm::Type* t, llvm::Constant* c) initvals.resize(at->getNumElements(), c); return llvm::ConstantArray::get(at, initvals); } + +////////////////////////////////////////////////////////////////////////////////////////// +llvm::Value* DtoArrayLen(DValue* v) +{ + Type* t = DtoDType(v->getType()); + if (t->ty == Tarray) { + if (DSliceValue* s = v->isSlice()) { + if (s->len) return s->len; + DValue* next = new DVarValue(t,s->ptr,true); + return DtoArrayLen(next); + } + return DtoLoad(DtoGEPi(v->getRVal(), 0,0, "tmp")); + } + else if (t->ty == Tsarray) { + const llvm::ArrayType* t = llvm::cast(v->getLVal()->getType()); + return DtoConstSize_t(t->getNumElements()); + } + assert(0); + return 0; +} + +////////////////////////////////////////////////////////////////////////////////////////// +llvm::Value* DtoArrayPtr(DValue* v) +{ + Type* t = DtoDType(v->getType()); + if (t->ty == Tarray) { + if (DSliceValue* s = v->isSlice()) { + if (s->len) return s->ptr; + DValue* next = new DVarValue(t,s->ptr,true); + return DtoArrayPtr(next); + } + return DtoLoad(DtoGEPi(v->getRVal(), 0,1, "tmp")); + } + else if (t->ty == Tsarray) { + return DtoGEPi(v->getRVal(), 0,0, "tmp"); + } + assert(0); + return 0; +} + diff --git a/gen/arrays.h b/gen/arrays.h index d4461ccd..2a72a4ec 100644 --- a/gen/arrays.h +++ b/gen/arrays.h @@ -1,6 +1,8 @@ #ifndef LLVMC_GEN_ARRAYS_H #define LLVMC_GEN_ARRAYS_H +struct DSliceValue; + const llvm::StructType* DtoArrayType(Type* t); const llvm::ArrayType* DtoStaticArrayType(Type* t); @@ -8,7 +10,8 @@ llvm::Constant* DtoConstArrayInitializer(ArrayInitializer* si); llvm::Constant* DtoConstSlice(llvm::Constant* dim, llvm::Constant* ptr); llvm::Constant* DtoConstStaticArray(const llvm::Type* t, llvm::Constant* c); -void DtoArrayCopy(elem* dst, elem* src); +void DtoArrayCopy(DSliceValue* dst, DSliceValue* src); + void DtoArrayInit(llvm::Value* l, llvm::Value* r); void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val); void DtoArrayAssign(llvm::Value* l, llvm::Value* r); @@ -16,9 +19,10 @@ void DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr); void DtoNullArray(llvm::Value* v); llvm::Value* DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, Type* dty, bool doinit=true); -void DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz); +llvm::Value* DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz); void DtoCatAssignElement(llvm::Value* arr, Expression* exp); +void DtoCatAssignArray(llvm::Value* arr, Expression* exp); void DtoCatArrays(llvm::Value* arr, Expression* e1, Expression* e2); void DtoStaticArrayCopy(llvm::Value* dst, llvm::Value* src); @@ -30,4 +34,7 @@ llvm::Value* DtoDynArrayIs(TOK op, llvm::Value* l, llvm::Value* r); llvm::Value* DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, const llvm::Type* newelemty); +llvm::Value* DtoArrayLen(DValue* v); +llvm::Value* DtoArrayPtr(DValue* v); + #endif // LLVMC_GEN_ARRAYS_H diff --git a/gen/binops.cpp b/gen/binops.cpp new file mode 100644 index 00000000..81bc218c --- /dev/null +++ b/gen/binops.cpp @@ -0,0 +1,56 @@ +#include "gen/llvm.h" + +#include "declaration.h" + +#include "gen/irstate.h" +#include "gen/dvalue.h" + +DValue* DtoBinAdd(DValue* lhs, DValue* rhs) +{ + llvm::Value* v = gIR->ir->CreateAdd(lhs->getRVal(), rhs->getRVal(), "tmp"); + return new DImValue( lhs->getType(), v ); +} + +DValue* DtoBinSub(DValue* lhs, DValue* rhs) +{ + llvm::Value* v = gIR->ir->CreateSub(lhs->getRVal(), rhs->getRVal(), "tmp"); + return new DImValue( lhs->getType(), v ); +} + +DValue* DtoBinMul(DValue* lhs, DValue* rhs) +{ + llvm::Value* v = gIR->ir->CreateMul(lhs->getRVal(), rhs->getRVal(), "tmp"); + return new DImValue( lhs->getType(), v ); +} + +DValue* DtoBinDiv(DValue* lhs, DValue* rhs) +{ + Type* t = lhs->getType(); + llvm::Value *l, *r; + l = lhs->getRVal(); + r = rhs->getRVal(); + llvm::Value* res; + if (t->isfloating()) + res = gIR->ir->CreateFDiv(l, r, "tmp"); + else if (!t->isunsigned()) + res = gIR->ir->CreateSDiv(l, r, "tmp"); + else + res = gIR->ir->CreateUDiv(l, r, "tmp"); + return new DImValue( lhs->getType(), res ); +} + +DValue* DtoBinRem(DValue* lhs, DValue* rhs) +{ + Type* t = lhs->getType(); + llvm::Value *l, *r; + l = lhs->getRVal(); + r = rhs->getRVal(); + llvm::Value* res; + if (t->isfloating()) + res = gIR->ir->CreateFRem(l, r, "tmp"); + else if (!t->isunsigned()) + res = gIR->ir->CreateSRem(l, r, "tmp"); + else + res = gIR->ir->CreateURem(l, r, "tmp"); + return new DImValue( lhs->getType(), res ); +} diff --git a/gen/dwarftypes.c b/gen/dwarftypes.cpp similarity index 100% rename from gen/dwarftypes.c rename to gen/dwarftypes.cpp diff --git a/gen/elem.c b/gen/elem.cpp similarity index 80% rename from gen/elem.c rename to gen/elem.cpp index 6285d693..3ea14b9a 100644 --- a/gen/elem.c +++ b/gen/elem.cpp @@ -1,3 +1,4 @@ +/* #include #include "gen/llvm.h" @@ -5,11 +6,14 @@ #include "gen/elem.h" #include "gen/irstate.h" #include "gen/logger.h" +#include "gen/dvalue.h" ////////////////////////////////////////////////////////////////////////////////////////// -elem::elem() +elem::elem(Expression* e) { + exp = e; + mem = 0; val = 0; arg = 0; @@ -24,10 +28,22 @@ elem::elem() vardecl = 0; funcdecl = 0; + + dvalue = 0; +} + +elem::~elem() +{ + delete dvalue; } llvm::Value* elem::getValue() { + if (dvalue && !dvalue->isSlice()) { + Logger::println("HAS DVALUE"); + return dvalue->getRVal(); + } + assert(val || mem); switch(type) { @@ -66,3 +82,4 @@ llvm::Value* elem::getValue() assert(0 && "type == invalid value"); return 0; } +*/ diff --git a/gen/elem.h b/gen/elem.h index 9882766a..57fdae64 100644 --- a/gen/elem.h +++ b/gen/elem.h @@ -1,10 +1,17 @@ #ifndef LLVMDC_GEN_ELEM_H #define LLVMDC_GEN_ELEM_H +#include "dvalue.h" +typedef DValue elem; + +/* + #include "root.h" #include "declaration.h" #include "aggregate.h" +struct DValue; + // represents a value. be it a constant literal, a variable etc. // maintains all the information for doing load/store appropriately struct elem : Object @@ -22,7 +29,10 @@ struct elem : Object }; public: - elem(); + elem(Expression* e); + virtual ~elem(); + + Expression* exp; llvm::Value* mem; llvm::Value* val; @@ -41,7 +51,11 @@ public: llvm::Value* getValue(); //llvm::Value* getMemory(); + DValue* dvalue; + bool isNull() {return !(mem || val);} }; +*/ + #endif // LLVMDC_GEN_ELEM_H diff --git a/gen/irstate.c b/gen/irstate.cpp similarity index 93% rename from gen/irstate.c rename to gen/irstate.cpp index 6f303d33..cdf123d0 100644 --- a/gen/irstate.c +++ b/gen/irstate.cpp @@ -164,7 +164,7 @@ IRExp::IRExp() v = NULL; } -IRExp::IRExp(Expression* l, Expression* r, llvm::Value* val) +IRExp::IRExp(Expression* l, Expression* r, DValue* val) { e1 = l; e2 = r; diff --git a/gen/irstate.h b/gen/irstate.h index 3a2c695d..2f93f94e 100644 --- a/gen/irstate.h +++ b/gen/irstate.h @@ -101,9 +101,9 @@ struct IRExp { Expression* e1; Expression* e2; - llvm::Value* v; + DValue* v; IRExp(); - IRExp(Expression* l, Expression* r, llvm::Value* val); + IRExp(Expression* l, Expression* r, DValue* val); }; // represents the module @@ -158,7 +158,7 @@ struct IRState // might be a better way but it works. problem is I only get a // VarDeclaration for __dollar, but I can't see how to get the // array pointer from this :( - std::vector arrays; + std::vector arrays; // builder helper IRBuilderHelper ir; diff --git a/gen/logger.c b/gen/logger.cpp similarity index 100% rename from gen/logger.c rename to gen/logger.cpp diff --git a/gen/runtime.c b/gen/runtime.cpp similarity index 100% rename from gen/runtime.c rename to gen/runtime.cpp diff --git a/gen/statements.c b/gen/statements.cpp similarity index 90% rename from gen/statements.c rename to gen/statements.cpp index 82dda1a1..398290d5 100644 --- a/gen/statements.c +++ b/gen/statements.cpp @@ -23,6 +23,7 @@ #include "gen/runtime.h" #include "gen/arrays.h" #include "gen/todebug.h" +#include "gen/dvalue.h" ////////////////////////////////////////////////////////////////////////////// @@ -66,34 +67,14 @@ void ReturnStatement::toIR(IRState* p) if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum); - p->exps.push_back(IRExp(NULL,exp,f->llvmRetArg)); - elem* e = exp->toElem(p); + DValue* rvar = new DVarValue(f->next, f->llvmRetArg, true); + + p->exps.push_back(IRExp(NULL,exp,rvar)); + DValue* e = exp->toElem(p); p->exps.pop_back(); - if (expty == Tstruct) { - if (!e->inplace) - DtoStructCopy(f->llvmRetArg,e->getValue()); - } - else if (expty == Tdelegate) { - if (!e->inplace) - DtoDelegateCopy(f->llvmRetArg,e->getValue()); - } - else if (expty == Tarray) { - if (e->type == elem::SLICE) { - assert(e->mem); - DtoSetArray(f->llvmRetArg,e->arg,e->mem); - } - else if (!e->inplace) { - if (e->type == elem::NUL) { - DtoNullArray(f->llvmRetArg); - } - else { - DtoArrayAssign(f->llvmRetArg, e->getValue()); - } - } - } - else - assert(0); + if (!e->inPlace()) + DtoAssign(rvar, e); IRFunction::FinallyVec& fin = p->func().finallys; if (fin.empty()) { @@ -103,12 +84,11 @@ void ReturnStatement::toIR(IRState* p) else { new llvm::BranchInst(fin.back().retbb, p->scopebb()); } - delete e; } else { if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum); - elem* e = exp->toElem(p); - llvm::Value* v = e->getValue(); + DValue* e = exp->toElem(p); + llvm::Value* v = e->getRVal(); delete e; Logger::cout() << "return value is '" <<*v << "'\n"; @@ -174,8 +154,8 @@ void IfStatement::toIR(IRState* p) Logger::println("IfStatement::toIR(%d): %s", wsi++, toChars()); LOG_SCOPE; - elem* cond_e = condition->toElem(p); - llvm::Value* cond_val = cond_e->getValue(); + DValue* cond_e = condition->toElem(p); + llvm::Value* cond_val = cond_e->getRVal(); delete cond_e; llvm::BasicBlock* oldend = gIR->scopeend(); @@ -265,8 +245,8 @@ void WhileStatement::toIR(IRState* p) gIR->scope() = IRScope(whilebb,endbb); // create the condition - elem* cond_e = condition->toElem(p); - llvm::Value* cond_val = DtoBoolean(cond_e->getValue()); + DValue* cond_e = condition->toElem(p); + llvm::Value* cond_val = DtoBoolean(cond_e->getRVal()); delete cond_e; // conditional branch @@ -308,8 +288,8 @@ void DoStatement::toIR(IRState* p) body->toIR(p); // create the condition - elem* cond_e = condition->toElem(p); - llvm::Value* cond_val = DtoBoolean(cond_e->getValue()); + DValue* cond_e = condition->toElem(p); + llvm::Value* cond_val = DtoBoolean(cond_e->getRVal()); delete cond_e; // conditional branch @@ -347,8 +327,8 @@ void ForStatement::toIR(IRState* p) gIR->scope() = IRScope(forbb,forbodybb); // create the condition - elem* cond_e = condition->toElem(p); - llvm::Value* cond_val = DtoBoolean(cond_e->getValue()); + DValue* cond_e = condition->toElem(p); + llvm::Value* cond_val = DtoBoolean(cond_e->getRVal()); delete cond_e; // conditional branch @@ -366,7 +346,7 @@ void ForStatement::toIR(IRState* p) // increment if (increment) { - elem* inc = increment->toElem(p); + DValue* inc = increment->toElem(p); delete inc; } @@ -543,7 +523,7 @@ void ThrowStatement::toIR(IRState* p) /* assert(exp); - elem* e = exp->toElem(p); + DValue* e = exp->toElem(p); delete e; */ } @@ -565,9 +545,10 @@ void SwitchStatement::toIR(IRState* p) CaseStatement* cs = (CaseStatement*)cases->data[i]; // get the case value - elem* e = cs->exp->toElem(p); - assert(e->val && llvm::isa(e->val)); - llvm::ConstantInt* ec = llvm::cast(e->val); + DValue* e = cs->exp->toElem(p); + DConstValue* ce = e->isConst(); + assert(ce && llvm::isa(ce->c)); + llvm::ConstantInt* ec = llvm::cast(ce->c); delete e; // create the case bb with a nice label @@ -587,8 +568,8 @@ void SwitchStatement::toIR(IRState* p) llvm::BasicBlock* endbb = new llvm::BasicBlock("switchend", p->topfunc(), oldend); // condition var - elem* cond = condition->toElem(p); - llvm::SwitchInst* si = new llvm::SwitchInst(cond->getValue(), defbb ? defbb : endbb, cases->dim, p->scopebb()); + DValue* cond = condition->toElem(p); + llvm::SwitchInst* si = new llvm::SwitchInst(cond->getRVal(), defbb ? defbb : endbb, cases->dim, p->scopebb()); delete cond; // add the cases @@ -678,9 +659,12 @@ void ForeachStatement::toIR(IRState* p) Logger::println("aggr = %s", aggr->toChars()); Logger::println("func = %s", func->toChars()); - elem* arr = aggr->toElem(p); - llvm::Value* val = arr->getValue(); - Logger::cout() << "aggr2llvm = " << *val << '\n'; + DValue* arr = aggr->toElem(p); + llvm::Value* val = 0; + if (!arr->isSlice()) { + val = arr->getRVal(); + Logger::cout() << "aggr2llvm = " << *val << '\n'; + } llvm::Value* numiters = 0; @@ -689,7 +673,7 @@ void ForeachStatement::toIR(IRState* p) if (key) key->llvmValue = keyvar; const llvm::Type* valtype = DtoType(value->type); - llvm::Value* valvar = !value->isRef() ? new llvm::AllocaInst(valtype, "foreachval", p->topallocapoint()) : NULL; + llvm::Value* valvar = !(value->isRef() || value->isOut()) ? new llvm::AllocaInst(valtype, "foreachval", p->topallocapoint()) : NULL; Type* aggrtype = DtoDType(aggr->type); if (aggrtype->ty == Tsarray) @@ -702,9 +686,9 @@ void ForeachStatement::toIR(IRState* p) } else if (aggrtype->ty == Tarray) { - if (arr->type == elem::SLICE) { - numiters = arr->arg; - val = arr->mem; + if (DSliceValue* slice = arr->isSlice()) { + numiters = slice->len; + val = slice->ptr; } else { numiters = p->ir->CreateLoad(DtoGEPi(val,0,0,"tmp",p->scopebb())); @@ -760,12 +744,12 @@ void ForeachStatement::toIR(IRState* p) else if (aggrtype->ty == Tarray) value->llvmValue = new llvm::GetElementPtrInst(val,loadedKey,"tmp",p->scopebb()); - if (!value->isRef()) { - elem* e = new elem; - e->mem = value->llvmValue; - e->type = elem::VAR; - DtoAssign(DtoDType(value->type), valvar, e->getValue()); - delete e; + if (!value->isRef() && !value->isOut()) { + DValue* dst = new DVarValue(value->type, valvar, true); + DValue* src = new DVarValue(value->type, value->llvmValue, true); + DtoAssign(dst, src); + delete dst; + delete src; value->llvmValue = valvar; } @@ -798,9 +782,12 @@ void LabelStatement::toIR(IRState* p) else llvmBB = new llvm::BasicBlock("label", p->topfunc(), oldend); - new llvm::BranchInst(llvmBB, p->scopebb()); + if (!p->scopereturned()) + new llvm::BranchInst(llvmBB, p->scopebb()); + p->scope() = IRScope(llvmBB,oldend); - statement->toIR(p); + if (statement) + statement->toIR(p); } ////////////////////////////////////////////////////////////////////////////// @@ -817,6 +804,7 @@ void GotoStatement::toIR(IRState* p) if (label->statement->llvmBB == NULL) label->statement->llvmBB = new llvm::BasicBlock("label", p->topfunc()); + assert(!p->scopereturned()); new llvm::BranchInst(label->statement->llvmBB, p->scopebb()); p->scope() = IRScope(bb,oldend); } @@ -831,8 +819,8 @@ void WithStatement::toIR(IRState* p) assert(exp); assert(body); - elem* e = exp->toElem(p); - wthis->llvmValue = e->getValue(); + DValue* e = exp->toElem(p); + wthis->llvmValue = e->getRVal(); delete e; body->toIR(p); diff --git a/gen/tocsym.c b/gen/tocsym.cpp similarity index 100% rename from gen/tocsym.c rename to gen/tocsym.cpp diff --git a/gen/todebug.c b/gen/todebug.cpp similarity index 100% rename from gen/todebug.c rename to gen/todebug.cpp diff --git a/gen/todt.c b/gen/todt.cpp similarity index 100% rename from gen/todt.c rename to gen/todt.cpp diff --git a/gen/toir.c b/gen/toir.cpp similarity index 73% rename from gen/toir.c rename to gen/toir.cpp index 94169a21..5ebd8137 100644 --- a/gen/toir.c +++ b/gen/toir.cpp @@ -28,13 +28,14 @@ #include "gen/runtime.h" #include "gen/arrays.h" +#include "gen/dvalue.h" + ////////////////////////////////////////////////////////////////////////////////////////// -elem* DeclarationExp::toElem(IRState* p) +DValue* DeclarationExp::toElem(IRState* p) { Logger::print("DeclarationExp::toElem: %s | T=%s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; // variable declaration if (VarDeclaration* vd = declaration->isVarDeclaration()) @@ -64,9 +65,11 @@ elem* DeclarationExp::toElem(IRState* p) //allocainst->setAlignment(vd->type->alignsize()); // TODO vd->llvmValue = allocainst; } - elem* ie = DtoInitializer(vd->init); + DValue* ie = DtoInitializer(vd->init); delete ie; } + + return new DVarValue(vd, vd->llvmValue, true); } // struct declaration else if (StructDeclaration* s = declaration->isStructDeclaration()) @@ -97,18 +100,16 @@ elem* DeclarationExp::toElem(IRState* p) error("Only Var/Struct-Declaration is supported for DeclarationExp"); assert(0); } - return e; + return 0; } ////////////////////////////////////////////////////////////////////////////////////////// -elem* VarExp::toElem(IRState* p) +DValue* VarExp::toElem(IRState* p) { Logger::print("VarExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; - assert(var); if (VarDeclaration* vd = var->isVarDeclaration()) { @@ -118,28 +119,27 @@ elem* VarExp::toElem(IRState* p) if (vd->ident == Id::_arguments) { Logger::println("Id::_arguments"); - vd->llvmValue = p->func().decl->llvmArguments; + if (!vd->llvmValue) + vd->llvmValue = p->func().decl->llvmArguments; assert(vd->llvmValue); - e->mem = vd->llvmValue; - e->type = elem::VAR; + return new DVarValue(vd, vd->llvmValue, true); } // _argptr else if (vd->ident == Id::_argptr) { Logger::println("Id::_argptr"); - vd->llvmValue = p->func().decl->llvmArgPtr; + if (!vd->llvmValue) + vd->llvmValue = p->func().decl->llvmArgPtr; assert(vd->llvmValue); - e->mem = vd->llvmValue; - e->type = elem::VAR; + return new DVarValue(vd, vd->llvmValue, true); } // _dollar else if (vd->ident == Id::dollar) { Logger::println("Id::dollar"); assert(!p->arrays.empty()); - llvm::Value* tmp = DtoGEPi(p->arrays.back(),0,0,"tmp",p->scopebb()); - e->val = new llvm::LoadInst(tmp,"tmp",p->scopebb()); - e->type = elem::VAL; + llvm::Value* tmp = DtoArrayLen(p->arrays.back()); + return new DVarValue(vd, tmp, false); } // typeinfo else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration()) @@ -148,18 +148,17 @@ elem* VarExp::toElem(IRState* p) tid->toObjFile(); assert(tid->llvmValue); const llvm::Type* vartype = DtoType(type); + llvm::Value* m; if (tid->llvmValue->getType() != llvm::PointerType::get(vartype)) - e->mem = p->ir->CreateBitCast(tid->llvmValue, vartype, "tmp"); + m = p->ir->CreateBitCast(tid->llvmValue, vartype, "tmp"); else - e->mem = tid->llvmValue; - e->type = elem::VAR; + m = tid->llvmValue; + return new DVarValue(vd, m, true); } // nested variable else if (vd->nestedref) { Logger::println("nested variable"); - e->mem = DtoNestedVariable(vd); - e->type = elem::VAR; - e->vardecl = vd; + return new DVarValue(vd, DtoNestedVariable(vd), true); } // function parameter else if (vd->isParameter()) { @@ -170,14 +169,10 @@ elem* VarExp::toElem(IRState* p) vd->llvmValue = &p->func().func->getArgumentList().back(); } if (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type) || llvm::isa(vd->llvmValue)) { - e->mem = vd->llvmValue; - e->type = elem::VAR; - e->vardecl = vd; + return new DVarValue(vd, vd->llvmValue, true); } else if (llvm::isa(vd->llvmValue)) { - e->val = vd->llvmValue; - e->type = elem::VAL; - e->vardecl = vd; + return new DImValue(type, vd->llvmValue); } else assert(0); } @@ -186,21 +181,15 @@ elem* VarExp::toElem(IRState* p) if (!vd->llvmTouched && vd->isDataseg()) vd->toObjFile(); assert(vd->llvmValue); - e->mem = vd->llvmValue; - e->vardecl = vd; - e->type = elem::VAR; + return new DVarValue(vd, vd->llvmValue, true); } - - assert(e->mem || e->val); } else if (FuncDeclaration* fdecl = var->isFuncDeclaration()) { Logger::println("FuncDeclaration"); - if (fdecl->llvmInternal != LLVMva_arg && fdecl->llvmValue == 0) + if (fdecl->llvmInternal != LLVMva_arg)// && fdecl->llvmValue == 0) fdecl->toObjFile(); - e->val = fdecl->llvmValue; - e->type = elem::FUNC; - e->funcdecl = fdecl; + return new DFuncValue(fdecl, fdecl->llvmValue); } else if (SymbolDeclaration* sdecl = var->isSymbolDeclaration()) { @@ -209,16 +198,15 @@ elem* VarExp::toElem(IRState* p) Logger::print("Sym: type=%s\n", sdecltype->toChars()); assert(sdecltype->ty == Tstruct); TypeStruct* ts = (TypeStruct*)sdecltype; - e->mem = ts->llvmInit; - assert(e->mem); - e->type = elem::VAR; + assert(ts->llvmInit); + return new DVarValue(type, ts->llvmInit, true); } else { assert(0 && "Unimplemented VarExp type"); } - return e; + return 0; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -243,14 +231,12 @@ llvm::Constant* VarExp::toConstElem(IRState* p) ////////////////////////////////////////////////////////////////////////////////////////// -elem* IntegerExp::toElem(IRState* p) +DValue* IntegerExp::toElem(IRState* p) { Logger::print("IntegerExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; - e->val = toConstElem(p); - e->type = elem::CONST; - return e; + llvm::Constant* c = toConstElem(p); + return new DConstValue(type, c); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -273,14 +259,12 @@ llvm::Constant* IntegerExp::toConstElem(IRState* p) ////////////////////////////////////////////////////////////////////////////////////////// -elem* RealExp::toElem(IRState* p) +DValue* RealExp::toElem(IRState* p) { Logger::print("RealExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; - e->val = toConstElem(p); - e->type = elem::CONST; - return e; + llvm::Constant* c = toConstElem(p); + return new DConstValue(type, c); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -301,15 +285,12 @@ llvm::Constant* RealExp::toConstElem(IRState* p) ////////////////////////////////////////////////////////////////////////////////////////// -elem* NullExp::toElem(IRState* p) +DValue* NullExp::toElem(IRState* p) { Logger::print("NullExp::toElem(type=%s): %s\n", type->toChars(),toChars()); LOG_SCOPE; - elem* e = new elem; - e->val = toConstElem(p); - e->type = elem::NUL; - //Logger::cout() << "null value is now " << *e->val << '\n'; - return e; + llvm::Constant* c = toConstElem(p); + return new DNullValue(type, c); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -332,24 +313,44 @@ llvm::Constant* NullExp::toConstElem(IRState* p) ////////////////////////////////////////////////////////////////////////////////////////// -elem* StringExp::toElem(IRState* p) +DValue* StringExp::toElem(IRState* p) { Logger::print("StringExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; Type* dtype = DtoDType(type); - - assert(dtype->next->ty == Tchar && "Only char is supported"); - assert(sz == 1); + Type* cty = DtoDType(dtype->next); const llvm::Type* ct = DtoType(dtype->next); //printf("ct = %s\n", type->next->toChars()); const llvm::ArrayType* at = llvm::ArrayType::get(ct,len+1); - uint8_t* str = (uint8_t*)string; - std::string cont((char*)str, len); - - llvm::Constant* _init = llvm::ConstantArray::get(cont,true); + llvm::Constant* _init; + if (cty->ty == Tchar) { + uint8_t* str = (uint8_t*)string; + std::string cont((char*)str, len); + _init = llvm::ConstantArray::get(cont,true); + } + else if (cty->ty == Twchar) { + uint16_t* str = (uint16_t*)string; + std::vector vals; + for(size_t i=0; ity == Tdchar) { + uint32_t* str = (uint32_t*)string; + std::vector vals; + for(size_t i=0; imodule); @@ -358,39 +359,32 @@ elem* StringExp::toElem(IRState* p) llvm::Constant* idxs[2] = { zero, zero }; llvm::Constant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2); - elem* e = new elem; - if (dtype->ty == Tarray) { llvm::Constant* clen = llvm::ConstantInt::get(DtoSize_t(),len,false); if (!p->topexp() || p->topexp()->e2 != this) { llvm::Value* tmpmem = new llvm::AllocaInst(DtoType(dtype),"tempstring",p->topallocapoint()); DtoSetArray(tmpmem, clen, arrptr); - e->mem = tmpmem; - e->temp = true; + return new DVarValue(type, tmpmem, true); } else if (p->topexp()->e2 == this) { - llvm::Value* arr = p->topexp()->v; + DValue* arr = p->topexp()->v; assert(arr); - DtoSetArray(arr, clen, arrptr); - e->inplace = true; + DtoSetArray(arr->getLVal(), clen, arrptr); + return new DImValue(type, arr->getLVal(), true); } - else assert(0); } else if (dtype->ty == Tsarray) { const llvm::Type* dstType = llvm::PointerType::get(llvm::ArrayType::get(ct, len)); - e->mem = new llvm::BitCastInst(gvar, dstType, "tmp", gIR->scopebb()); + llvm::Value* emem = (gvar->getType() == dstType) ? gvar : DtoBitCast(gvar, dstType); + return new DVarValue(type, emem, true); } else if (dtype->ty == Tpointer) { - e->mem = arrptr; - } - else { - assert(0); + return new DImValue(type, arrptr); } - e->type = elem::VAL; - - return e; + assert(0); + return 0; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -432,20 +426,27 @@ llvm::Constant* StringExp::toConstElem(IRState* p) ////////////////////////////////////////////////////////////////////////////////////////// -elem* AssignExp::toElem(IRState* p) +DValue* AssignExp::toElem(IRState* p) { Logger::print("AssignExp::toElem: %s | %s = %s\n", toChars(), e1->type->toChars(), e2->type ? e2->type->toChars() : 0); LOG_SCOPE; p->exps.push_back(IRExp(e1,e2,NULL)); - elem* l = e1->toElem(p); - p->topexp()->v = l->mem; - elem* r = e2->toElem(p); + DValue* l = e1->toElem(p); + p->topexp()->v = l; + DValue* r = e2->toElem(p); p->exps.pop_back(); - if (l->type == elem::ARRAYLEN) + if (l->isArrayLen()) + DtoResizeDynArray(l->getLVal(), r->getRVal()); + else + DtoAssign(l, r); + return l; + + /* + if (l->type == DValue::ARRAYLEN) { DtoResizeDynArray(l->mem, r->getValue()); delete r; @@ -458,8 +459,8 @@ elem* AssignExp::toElem(IRState* p) TY e1ty = e1type->ty; TY e2ty = e2type->ty; - elem* e = new elem; - e->type = elem::VAR; + DValue* e = new DValue(this); + e->type = DValue::VAR; // struct if (e1ty == Tstruct) { @@ -489,20 +490,25 @@ elem* AssignExp::toElem(IRState* p) } else if (e1ty == Tarray) { if (e2type->isscalar() || e2type->ty == Tclass){ - DtoArrayInit(l->mem, r->getValue()); + if (l->type == DValue::SLICE) { + DtoArrayInit(l->mem, l->arg, r->getValue()); + } + else { + DtoArrayInit(l->mem, r->getValue()); + } } else if (e2ty == Tarray) { //new llvm::StoreInst(r->val,l->val,p->scopebb()); - if (r->type == elem::NUL) { + if (r->type == DValue::NUL) { llvm::Constant* c = llvm::cast(r->val); assert(c->isNullValue()); DtoNullArray(l->mem); e->mem = l->mem; } - else if (r->type == elem::SLICE) { - if (l->type == elem::SLICE) { + else if (r->type == DValue::SLICE) { + if (l->type == DValue::SLICE) { DtoArrayCopy(l,r); - e->type = elem::SLICE; + e->type = DValue::SLICE; e->mem = l->mem; e->arg = l->arg; } @@ -562,7 +568,7 @@ elem* AssignExp::toElem(IRState* p) else if (e1ty == Tdelegate) { Logger::println("Assigning to delegate"); if (e2ty == Tdelegate) { - if (r->type == elem::NUL) { + if (r->type == DValue::NUL) { llvm::Constant* c = llvm::cast(r->val); if (c->isNullValue()) { DtoNullDelegate(l->mem); @@ -595,17 +601,18 @@ elem* AssignExp::toElem(IRState* p) delete l; return e; + */ } ////////////////////////////////////////////////////////////////////////////////////////// -elem* AddExp::toElem(IRState* p) +DValue* AddExp::toElem(IRState* p) { Logger::print("AddExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; - elem* l = e1->toElem(p); - elem* r = e2->toElem(p); + + DValue* l = e1->toElem(p); + DValue* r = e2->toElem(p); Type* t = DtoDType(type); Type* e1type = DtoDType(e1->type); @@ -613,46 +620,54 @@ elem* AddExp::toElem(IRState* p) if (e1type != e2type) { if (e1type->ty == Tpointer && e1type->next->ty == Tstruct) { - //assert(l->field); - assert(r->type == elem::CONST); - llvm::ConstantInt* cofs = llvm::cast(r->val); + assert(r->isConst()); + llvm::ConstantInt* cofs = llvm::cast(r->isConst()->c); TypeStruct* ts = (TypeStruct*)e1type->next; std::vector offsets; - e->mem = DtoIndexStruct(l->getValue(), ts->sym, t->next, cofs->getZExtValue(), offsets); - e->type = elem::VAR; - e->field = true; + llvm::Value* v = DtoIndexStruct(l->getRVal(), ts->sym, t->next, cofs->getZExtValue(), offsets); + return new DFieldValue(type, v, true); } else if (e1->type->ty == Tpointer) { - e->val = new llvm::GetElementPtrInst(l->getValue(), r->getValue(), "tmp", p->scopebb()); - e->type = elem::VAR; - } - else { - assert(0); + llvm::Value* v = new llvm::GetElementPtrInst(l->getRVal(), r->getRVal(), "tmp", p->scopebb()); + return new DImValue(type, v); } + assert(0); } else { - e->val = llvm::BinaryOperator::createAdd(l->getValue(), r->getValue(), "tmp", p->scopebb()); - e->type = elem::VAL; + return DtoBinAdd(l,r); } - delete l; - delete r; - return e; } ////////////////////////////////////////////////////////////////////////////////////////// -elem* AddAssignExp::toElem(IRState* p) +DValue* AddAssignExp::toElem(IRState* p) { Logger::print("AddAssignExp::toElem: %s\n", toChars()); LOG_SCOPE; - elem* l = e1->toElem(p); - elem* r = e2->toElem(p); + p->exps.push_back(IRExp(e1,e2,NULL)); + DValue* l = e1->toElem(p); + DValue* r = e2->toElem(p); + p->exps.pop_back(); + + DValue* res; + if (DtoDType(e1->type)->ty == Tpointer) { + llvm::Value* gep = new llvm::GetElementPtrInst(l->getRVal(),r->getRVal(),"tmp",p->scopebb()); + res = new DImValue(type, gep); + } + else { + res = DtoBinAdd(l,r); + } + DtoAssign(l, res); + + return l; + + /* Type* e1type = DtoDType(e1->type); - elem* e = new elem; + DValue* e = new DValue(this); llvm::Value* val = 0; if (e1type->ty == Tpointer) { val = e->mem = new llvm::GetElementPtrInst(l->getValue(),r->getValue(),"tmp",p->scopebb()); @@ -661,31 +676,39 @@ elem* AddAssignExp::toElem(IRState* p) val = e->val = llvm::BinaryOperator::createAdd(l->getValue(),r->getValue(),"tmp",p->scopebb()); } - /*llvm::Value* storeVal = l->storeVal ? l->storeVal : l->val; - if (llvm::isa(storeVal->getType()) && storeVal->getType()->getContainedType(0) != tmp->getType()) - { - tmp = DtoPointedType(storeVal, tmp); - }*/ - assert(l->mem); new llvm::StoreInst(val,l->mem,p->scopebb()); - e->type = elem::VAR; + e->type = DValue::VAR; delete l; delete r; return e; + */ } ////////////////////////////////////////////////////////////////////////////////////////// -elem* MinExp::toElem(IRState* p) +DValue* MinExp::toElem(IRState* p) { Logger::print("MinExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; - elem* l = e1->toElem(p); - elem* r = e2->toElem(p); + DValue* l = e1->toElem(p); + 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"); + if (diff->getType() != DtoType(type)) + diff = p->ir->CreateIntToPtr(diff, DtoType(type)); + return new DImValue(type, diff); + } + else { + return DtoBinSub(l,r); + } + + /* llvm::Value* left = l->getValue(); if (llvm::isa(left->getType())) left = new llvm::PtrToIntInst(left,DtoSize_t(),"tmp",p->scopebb()); @@ -695,7 +718,7 @@ elem* MinExp::toElem(IRState* p) right = new llvm::PtrToIntInst(right,DtoSize_t(),"tmp",p->scopebb()); e->val = llvm::BinaryOperator::createSub(left,right,"tmp",p->scopebb()); - e->type = elem::VAL; + e->type = DValue::VAL; const llvm::Type* totype = DtoType(type); if (e->val->getType() != totype) { @@ -708,17 +731,35 @@ elem* MinExp::toElem(IRState* p) delete l; delete r; return e; + */ } ////////////////////////////////////////////////////////////////////////////////////////// -elem* MinAssignExp::toElem(IRState* p) +DValue* MinAssignExp::toElem(IRState* p) { - Logger::print("MinAssignExp::toElem: %s\n", toChars()); + Logger::print("MinAssignExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* l = e1->toElem(p); - elem* r = e2->toElem(p); + DValue* l = e1->toElem(p); + DValue* r = e2->toElem(p); + + DValue* res; + if (DtoDType(e1->type)->ty == Tpointer) { + llvm::Value* tmp = r->getRVal(); + llvm::Value* zero = llvm::ConstantInt::get(tmp->getType(),0,false); + tmp = llvm::BinaryOperator::createSub(zero,tmp,"tmp",p->scopebb()); + tmp = new llvm::GetElementPtrInst(l->getRVal(),tmp,"tmp",p->scopebb()); + res = new DImValue(type, tmp); + } + else { + res = DtoBinSub(l,r); + } + DtoAssign(l, res); + + return l; + + /* Type* e1type = DtoDType(e1->type); @@ -733,84 +774,96 @@ elem* MinAssignExp::toElem(IRState* p) tmp = llvm::BinaryOperator::createSub(l->getValue(),r->getValue(),"tmp",p->scopebb()); } - /*llvm::Value* storeVal = l->storeVal ? l->storeVal : l->val; - if (storeVal->getType()->getContainedType(0) != tmp->getType()) - { - tmp = DtoPointedType(storeVal, tmp); - }*/ - assert(l->mem); new llvm::StoreInst(tmp, l->mem, p->scopebb()); delete l; delete r; - elem* e = new elem; + DValue* e = new DValue(this); e->val = tmp; - e->type = elem::VAR; + e->type = DValue::VAR; return e; + */ } ////////////////////////////////////////////////////////////////////////////////////////// -elem* MulExp::toElem(IRState* p) +DValue* MulExp::toElem(IRState* p) { Logger::print("MulExp::toElem: %s\n", toChars()); LOG_SCOPE; - elem* e = new elem; - elem* l = e1->toElem(p); - elem* r = e2->toElem(p); - llvm::Value* vl = l->getValue(); - llvm::Value* vr = r->getValue(); - Logger::cout() << "mul: " << *vl << ", " << *vr << '\n'; - e->val = llvm::BinaryOperator::createMul(vl,vr,"tmp",p->scopebb()); - e->type = elem::VAL; + + DValue* l = e1->toElem(p); + DValue* r = e2->toElem(p); + + return DtoBinMul(l,r); + /* + if (l->dvalue && r->dvalue) { + Logger::println("DVALUE PATH"); + e->dvalue = DtoBinMul(l->dvalue, r->dvalue); + e->val = e->dvalue->getRVal(); + } + else { + llvm::Value* vl = l->getValue(); + llvm::Value* vr = r->getValue(); + Logger::cout() << "mul: " << *vl << ", " << *vr << '\n'; + e->val = llvm::BinaryOperator::createMul(vl,vr,"tmp",p->scopebb()); + e->dvalue = new DImValue(type, e->val); + } + e->type = DValue::VAL; delete l; delete r; return e; + */ } ////////////////////////////////////////////////////////////////////////////////////////// -elem* MulAssignExp::toElem(IRState* p) +DValue* MulAssignExp::toElem(IRState* p) { Logger::print("MulAssignExp::toElem: %s\n", toChars()); LOG_SCOPE; - elem* l = e1->toElem(p); - elem* r = e2->toElem(p); + DValue* l = e1->toElem(p); + DValue* r = e2->toElem(p); + + DValue* res = DtoBinMul(l,r); + DtoAssign(l, res); + + return l; + + /* llvm::Value* vl = l->getValue(); llvm::Value* vr = r->getValue(); Logger::cout() << "mulassign: " << *vl << ", " << *vr << '\n'; llvm::Value* tmp = llvm::BinaryOperator::createMul(vl,vr,"tmp",p->scopebb()); - /*llvm::Value* storeVal = l->storeVal ? l->storeVal : l->val; - if (storeVal->getType()->getContainedType(0) != tmp->getType()) - { - tmp = DtoPointedType(storeVal, tmp); - }*/ - assert(l->mem); new llvm::StoreInst(tmp,l->mem,p->scopebb()); delete l; delete r; - elem* e = new elem; + DValue* e = new DValue(this); e->val = tmp; - e->type = elem::VAR; + e->type = DValue::VAR; return e; + */ } ////////////////////////////////////////////////////////////////////////////////////////// -elem* DivExp::toElem(IRState* p) +DValue* DivExp::toElem(IRState* p) { Logger::print("DivExp::toElem: %s\n", toChars()); LOG_SCOPE; - elem* e = new elem; - elem* l = e1->toElem(p); - elem* r = e2->toElem(p); + + DValue* l = e1->toElem(p); + DValue* r = e2->toElem(p); + + return DtoBinDiv(l, r); + /* Type* t = DtoDType(type); @@ -822,21 +875,29 @@ elem* DivExp::toElem(IRState* p) e->val = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb()); else assert(0); - e->type = elem::VAL; + e->type = DValue::VAL; delete l; delete r; return e; + */ } ////////////////////////////////////////////////////////////////////////////////////////// -elem* DivAssignExp::toElem(IRState* p) +DValue* DivAssignExp::toElem(IRState* p) { Logger::print("DivAssignExp::toElem: %s\n", toChars()); LOG_SCOPE; - elem* l = e1->toElem(p); - elem* r = e2->toElem(p); + DValue* l = e1->toElem(p); + DValue* r = e2->toElem(p); + + DValue* res = DtoBinDiv(l,r); + DtoAssign(l, res); + + return l; + + /* Type* t = DtoDType(type); @@ -850,34 +911,31 @@ elem* DivAssignExp::toElem(IRState* p) else assert(0); - /*llvm::Value* storeVal = l->storeVal ? l->storeVal : l->val; - if (storeVal->getType()->getContainedType(0) != tmp->getType()) - { - tmp = DtoPointedType(storeVal, tmp); - }*/ - assert(l->mem); new llvm::StoreInst(tmp,l->mem,p->scopebb()); delete l; delete r; - elem* e = new elem; + DValue* e = new DValue(this); e->val = tmp; - e->type = elem::VAR; + e->type = DValue::VAR; return e; + */ } ////////////////////////////////////////////////////////////////////////////////////////// -elem* ModExp::toElem(IRState* p) +DValue* ModExp::toElem(IRState* p) { Logger::print("ModExp::toElem: %s\n", toChars()); LOG_SCOPE; - elem* e = new elem; - elem* l = e1->toElem(p); - elem* r = e2->toElem(p); + DValue* l = e1->toElem(p); + DValue* r = e2->toElem(p); + + return DtoBinRem(l, r); + /* Type* t = DtoDType(type); if (t->isunsigned()) @@ -888,21 +946,29 @@ elem* ModExp::toElem(IRState* p) e->val = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb()); else assert(0); - e->type = elem::VAL; + e->type = DValue::VAL; delete l; delete r; return e; + */ } ////////////////////////////////////////////////////////////////////////////////////////// -elem* ModAssignExp::toElem(IRState* p) +DValue* ModAssignExp::toElem(IRState* p) { Logger::print("ModAssignExp::toElem: %s\n", toChars()); LOG_SCOPE; - elem* l = e1->toElem(p); - elem* r = e2->toElem(p); + DValue* l = e1->toElem(p); + DValue* r = e2->toElem(p); + + DValue* res = DtoBinRem(l, r); + DtoAssign(l, res); + + return l; + + /* Type* t = DtoDType(type); @@ -916,33 +982,27 @@ elem* ModAssignExp::toElem(IRState* p) else assert(0); - /*llvm::Value* storeVal = l->storeVal ? l->storeVal : l->val; - if (storeVal->getType()->getContainedType(0) != tmp->getType()) - { - tmp = DtoPointedType(storeVal, tmp); - }*/ - assert(l->mem); new llvm::StoreInst(tmp,l->mem,p->scopebb()); delete l; delete r; - elem* e = new elem; + DValue* e = new DValue(this); e->val = tmp; - e->type = elem::VAR; + e->type = DValue::VAR; return e; + */ } ////////////////////////////////////////////////////////////////////////////////////////// -elem* CallExp::toElem(IRState* p) +DValue* CallExp::toElem(IRState* p) { Logger::print("CallExp::toElem: %s\n", toChars()); LOG_SCOPE; - elem* e = new elem; - elem* fn = e1->toElem(p); + DValue* fn = e1->toElem(p); TypeFunction* tf = 0; Type* e1type = DtoDType(e1->type); @@ -984,41 +1044,39 @@ elem* CallExp::toElem(IRState* p) // va args bool va_magic = false; bool va_intrinsic = false; - if (fn->funcdecl) { - if (fn->funcdecl->llvmInternal == LLVMva_intrinsic) { + DFuncValue* dfv = fn->isFunc(); + if (dfv && dfv->func) { + FuncDeclaration* fndecl = dfv->func; + if (fndecl->llvmInternal == LLVMva_intrinsic) { va_magic = true; va_intrinsic = true; } - else if (fn->funcdecl->llvmInternal == LLVMva_start) { + else if (fndecl->llvmInternal == LLVMva_start) { va_magic = true; } - else if (fn->funcdecl->llvmInternal == LLVMva_arg) { + else if (fndecl->llvmInternal == LLVMva_arg) { //Argument* fnarg = Argument::getNth(tf->parameters, 0); Expression* exp = (Expression*)arguments->data[0]; - elem* expelem = exp->toElem(p); - assert(expelem->mem); - elem* e = new elem; + DValue* expelem = exp->toElem(p); Type* t = DtoDType(type); const llvm::Type* llt = DtoType(type); if (DtoIsPassedByRef(t)) llt = llvm::PointerType::get(llt); - e->type = elem::VAL; - e->val = p->ir->CreateVAArg(expelem->mem,llt,"tmp"); - delete expelem; - return e; + return new DImValue(type, p->ir->CreateVAArg(expelem->getLVal(),llt,"tmp")); } } // args size_t n = arguments->dim; - if (fn->funcdecl && fn->funcdecl->llvmInternal == LLVMva_start) + DFuncValue* dfn = fn->isFunc(); + if (dfn && dfn->func && dfn->func->llvmInternal == LLVMva_start) n = 1; - if (fn->arg || delegateCall) n++; + if (delegateCall || (dfn && dfn->vthis)) n++; if (retinptr) n++; if (tf->linkage == LINKd && tf->varargs == 1) n+=2; - if (fn->funcdecl && fn->funcdecl->isNested()) n++; + if (dfn && dfn->func && dfn->func->isNested()) n++; - llvm::Value* funcval = fn->getValue(); + llvm::Value* funcval = fn->getRVal(); assert(funcval != 0); std::vector llargs(n, 0); @@ -1064,14 +1122,17 @@ elem* CallExp::toElem(IRState* p) IRExp* topexp = p->topexp(); + bool isInPlace = false; + // hidden struct return arguments if (retinptr) { if (topexp && topexp->e2 == this) { assert(topexp->v); - assert(llvm::isa(topexp->v->getType()->getContainedType(0))); - llargs[j] = topexp->v; + llvm::Value* tlv = topexp->v->getLVal(); + assert(llvm::isa(tlv->getType()->getContainedType(0))); + llargs[j] = tlv; if (DtoIsPassedByRef(tf->next)) { - e->inplace = true; + isInPlace = true; } else assert(0); @@ -1081,21 +1142,17 @@ elem* CallExp::toElem(IRState* p) } ++j; ++argiter; - e->type = elem::VAR; - } - else { - e->type = elem::VAL; } // this arguments - if (fn->arg) { + if (dfn && dfn->vthis) { Logger::println("This Call"); - if (fn->arg->getType() != argiter->get()) { + if (dfn->vthis->getType() != argiter->get()) { //Logger::cout() << *fn->thisparam << '|' << *argiter->get() << '\n'; - llargs[j] = new llvm::BitCastInst(fn->arg, argiter->get(), "tmp", p->scopebb()); + llargs[j] = new llvm::BitCastInst(dfn->vthis, argiter->get(), "tmp", p->scopebb()); } else { - llargs[j] = fn->arg; + llargs[j] = dfn->vthis; } ++j; ++argiter; @@ -1103,13 +1160,13 @@ elem* CallExp::toElem(IRState* p) // delegate context arguments else if (delegateCall) { Logger::println("Delegate Call"); - llvm::Value* contextptr = DtoGEP(fn->mem,zero,zero,"tmp",p->scopebb()); + llvm::Value* contextptr = DtoGEP(fn->getRVal(),zero,zero,"tmp",p->scopebb()); llargs[j] = new llvm::LoadInst(contextptr,"tmp",p->scopebb()); ++j; ++argiter; } // nested call - else if (fn->funcdecl && fn->funcdecl->isNested()) { + else if (dfn && dfn->func && dfn->func->isNested()) { Logger::println("Nested Call"); llvm::Value* contextptr = p->func().decl->llvmNested; assert(contextptr); @@ -1125,10 +1182,8 @@ elem* CallExp::toElem(IRState* p) { Argument* fnarg = Argument::getNth(tf->parameters, i); Expression* exp = (Expression*)arguments->data[i]; - elem* expelem = exp->toElem(p); - assert(expelem->mem); - llargs[j] = p->ir->CreateBitCast(expelem->mem, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp"); - delete expelem; + DValue* expelem = exp->toElem(p); + llargs[j] = p->ir->CreateBitCast(expelem->getLVal(), llvm::PointerType::get(llvm::Type::Int8Ty), "tmp"); } } // regular arguments @@ -1185,9 +1240,15 @@ elem* CallExp::toElem(IRState* p) for (int i=0; idim; i++,j++) { Argument* fnarg = Argument::getNth(tf->parameters, i); llargs[j] = DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]); + // this hack is necessary :/ + if (dfn && dfn->func && dfn->func->llvmRunTimeHack) { + if (llargs[j]->getType() != llfnty->getParamType(j)) + llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j)); + } } Logger::println("%d params passed", n); for (int i=0; iscopebb()); - if (retinptr) - e->mem = llargs[0]; - else - e->val = call; + llvm::Value* retllval = (retinptr) ? llargs[0] : call; // set calling convention - if (fn->funcdecl) { - int li = fn->funcdecl->llvmInternal; + if (dfn && dfn->func) { + int li = dfn->func->llvmInternal; if (li != LLVMintrinsic && li != LLVMva_start && li != LLVMva_intrinsic) { call->setCallingConv(DtoCallingConv(dlink)); } @@ -1217,22 +1275,22 @@ elem* CallExp::toElem(IRState* p) else if (delegateCall) { call->setCallingConv(DtoCallingConv(dlink)); } - else if (fn->callconv != (unsigned)-1) { - call->setCallingConv(fn->callconv); + else if (dfn && dfn->cc != (unsigned)-1) { + call->setCallingConv(dfn->cc); } - delete fn; - return e; + return new DImValue(type, retllval, isInPlace); } ////////////////////////////////////////////////////////////////////////////////////////// -elem* CastExp::toElem(IRState* p) +DValue* CastExp::toElem(IRState* p) { Logger::print("CastExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; - elem* u = e1->toElem(p); + + DValue* u = e1->toElem(p); + const llvm::Type* tolltype = DtoType(to); Type* fromtype = DtoDType(e1->type); Type* totype = DtoDType(to); @@ -1240,52 +1298,52 @@ elem* CastExp::toElem(IRState* p) int rsz = totype->size(); // this makes sure the strange lvalue casts don't screw things up - e->mem = u->mem; + llvm::Value* rval = 0; + llvm::Value* rval2 = 0; + bool isslice = false; if (fromtype->isintegral()) { if (totype->isintegral()) { if (lsz < rsz) { - Logger::cout() << *tolltype << '\n'; + Logger::cout() << "cast to: " << *tolltype << '\n'; if (fromtype->isunsigned() || fromtype->ty == Tbool) { - e->val = new llvm::ZExtInst(u->getValue(), tolltype, "tmp", p->scopebb()); + rval = new llvm::ZExtInst(u->getRVal(), tolltype, "tmp", p->scopebb()); } else { - e->val = new llvm::SExtInst(u->getValue(), tolltype, "tmp", p->scopebb()); + rval = new llvm::SExtInst(u->getRVal(), tolltype, "tmp", p->scopebb()); } } else if (lsz > rsz) { - e->val = new llvm::TruncInst(u->getValue(), tolltype, "tmp", p->scopebb()); + rval = new llvm::TruncInst(u->getRVal(), tolltype, "tmp", p->scopebb()); } else { - e->val = new llvm::BitCastInst(u->getValue(), tolltype, "tmp", p->scopebb()); + rval = new llvm::BitCastInst(u->getRVal(), tolltype, "tmp", p->scopebb()); } } else if (totype->isfloating()) { if (fromtype->isunsigned()) { - e->val = new llvm::UIToFPInst(u->getValue(), tolltype, "tmp", p->scopebb()); + rval = new llvm::UIToFPInst(u->getRVal(), tolltype, "tmp", p->scopebb()); } else { - e->val = new llvm::SIToFPInst(u->getValue(), tolltype, "tmp", p->scopebb()); + rval = new llvm::SIToFPInst(u->getRVal(), tolltype, "tmp", p->scopebb()); } } else if (totype->ty == Tpointer) { - e->val = p->ir->CreateIntToPtr(u->getValue(), tolltype, "tmp"); + rval = p->ir->CreateIntToPtr(u->getRVal(), tolltype, "tmp"); } else { assert(0); } - //e->storeVal = u->storeVal ? u->storeVal : u->val; - e->type = elem::VAL; } else if (fromtype->isfloating()) { if (totype->isfloating()) { if ((fromtype->ty == Tfloat80 || fromtype->ty == Tfloat64) && (totype->ty == Tfloat80 || totype->ty == Tfloat64)) { - e->val = u->getValue(); + rval = u->getRVal(); } else if (lsz < rsz) { - e->val = new llvm::FPExtInst(u->getValue(), tolltype, "tmp", p->scopebb()); + rval = new llvm::FPExtInst(u->getRVal(), tolltype, "tmp", p->scopebb()); } else if (lsz > rsz) { - e->val = new llvm::FPTruncInst(u->getValue(), tolltype, "tmp", p->scopebb()); + rval = new llvm::FPTruncInst(u->getRVal(), tolltype, "tmp", p->scopebb()); } else { assert(0); @@ -1293,21 +1351,19 @@ elem* CastExp::toElem(IRState* p) } else if (totype->isintegral()) { if (totype->isunsigned()) { - e->val = new llvm::FPToUIInst(u->getValue(), tolltype, "tmp", p->scopebb()); + rval = new llvm::FPToUIInst(u->getRVal(), tolltype, "tmp", p->scopebb()); } else { - e->val = new llvm::FPToSIInst(u->getValue(), tolltype, "tmp", p->scopebb()); + rval = new llvm::FPToSIInst(u->getRVal(), tolltype, "tmp", p->scopebb()); } } else { assert(0); } - e->type = elem::VAL; } else if (fromtype->ty == Tclass) { //assert(to->ty == Tclass); - e->val = new llvm::BitCastInst(u->getValue(), tolltype, "tmp", p->scopebb()); - e->type = elem::VAL; + rval = new llvm::BitCastInst(u->getRVal(), tolltype, "tmp", p->scopebb()); } else if (fromtype->ty == Tarray || fromtype->ty == Tsarray) { Logger::cout() << "from array or sarray" << '\n'; @@ -1316,11 +1372,10 @@ elem* CastExp::toElem(IRState* p) assert(fromtype->next == totype->next || totype->next->ty == Tvoid); llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false); - llvm::Value* ptr = DtoGEP(u->getValue(),zero,one,"tmp",p->scopebb()); - e->val = new llvm::LoadInst(ptr, "tmp", p->scopebb()); + llvm::Value* ptr = DtoGEP(u->getRVal(),zero,one,"tmp",p->scopebb()); + rval = new llvm::LoadInst(ptr, "tmp", p->scopebb()); if (fromtype->next != totype->next) - e->val = p->ir->CreateBitCast(e->val, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp"); - e->type = elem::VAL; + rval = p->ir->CreateBitCast(rval, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp"); } else if (totype->ty == Tarray) { Logger::cout() << "to array" << '\n'; @@ -1333,37 +1388,37 @@ elem* CastExp::toElem(IRState* p) if (ety == llvm::Type::VoidTy) ety = llvm::Type::Int8Ty; - if (u->type == elem::SLICE) { - e->mem = new llvm::BitCastInst(u->mem, ptrty, "tmp", p->scopebb()); + if (DSliceValue* usl = u->isSlice()) { + rval = new llvm::BitCastInst(usl->ptr, ptrty, "tmp", p->scopebb()); if (fromtype->next->size() == totype->next->size()) - e->arg = u->arg; + rval2 = usl->len; else - e->arg = DtoArrayCastLength(u->arg, ety, ptrty->getContainedType(0)); + rval2 = DtoArrayCastLength(usl->len, ety, ptrty->getContainedType(0)); } else { - llvm::Value* uval = u->getValue(); + llvm::Value* uval = u->getRVal(); if (fromtype->ty == Tsarray) { Logger::cout() << "uvalTy = " << *uval->getType() << '\n'; assert(llvm::isa(uval->getType())); const llvm::ArrayType* arrty = llvm::cast(uval->getType()->getContainedType(0)); - e->arg = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false); - e->arg = DtoArrayCastLength(e->arg, ety, ptrty->getContainedType(0)); - e->mem = new llvm::BitCastInst(uval, ptrty, "tmp", p->scopebb()); + rval2 = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false); + rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0)); + rval = new llvm::BitCastInst(uval, ptrty, "tmp", p->scopebb()); } else { llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false); - e->arg = DtoGEP(uval,zero,zero,"tmp",p->scopebb()); - e->arg = new llvm::LoadInst(e->arg, "tmp", p->scopebb()); - e->arg = DtoArrayCastLength(e->arg, ety, ptrty->getContainedType(0)); + rval2 = DtoGEP(uval,zero,zero,"tmp",p->scopebb()); + rval2 = new llvm::LoadInst(rval2, "tmp", p->scopebb()); + rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0)); - e->mem = DtoGEP(uval,zero,one,"tmp",p->scopebb()); - e->mem = new llvm::LoadInst(e->mem, "tmp", p->scopebb()); + rval = DtoGEP(uval,zero,one,"tmp",p->scopebb()); + rval = new llvm::LoadInst(rval, "tmp", p->scopebb()); //Logger::cout() << *e->mem->getType() << '|' << *ptrty << '\n'; - e->mem = new llvm::BitCastInst(e->mem, ptrty, "tmp", p->scopebb()); + rval = new llvm::BitCastInst(rval, ptrty, "tmp", p->scopebb()); } } - e->type = elem::SLICE; + isslice = true; } else if (totype->ty == Tsarray) { Logger::cout() << "to sarray" << '\n'; @@ -1375,40 +1430,56 @@ elem* CastExp::toElem(IRState* p) } else if (fromtype->ty == Tpointer) { if (totype->ty == Tpointer || totype->ty == Tclass) { - llvm::Value* src = u->getValue(); - Logger::cout() << *src << '|' << *tolltype << '\n'; - e->val = new llvm::BitCastInst(src, tolltype, "tmp", p->scopebb()); + llvm::Value* src = u->getRVal(); + Logger::cout() << "src: " << *src << "to type: " << *tolltype << '\n'; + rval = new llvm::BitCastInst(src, tolltype, "tmp", p->scopebb()); } else if (totype->isintegral()) { - e->val = new llvm::PtrToIntInst(u->getValue(), tolltype, "tmp", p->scopebb()); + rval = new llvm::PtrToIntInst(u->getRVal(), tolltype, "tmp", p->scopebb()); } else assert(0); - e->type = elem::VAL; } else { assert(0); } - delete u; - return e; + + if (isslice) { + return new DSliceValue(type, rval2, rval); + } + else if (u->isLValueCast() || u->isVar()) { + return new DLValueCast(type, u->getLVal(), rval); + } + else if (p->topexp() && p->topexp()->e1 == this) { + llvm::Value* lval = u->getLVal(); + Logger::cout() << "lval: " << *lval << "rval: " << *rval << '\n'; + return new DLValueCast(type, lval, rval); + } + else { + Logger::cout() << "im rval: " << *rval << '\n'; + return new DImValue(type, rval); + } } ////////////////////////////////////////////////////////////////////////////////////////// -elem* SymOffExp::toElem(IRState* p) +DValue* SymOffExp::toElem(IRState* p) { Logger::print("SymOffExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = 0; + if (VarDeclaration* vd = var->isVarDeclaration()) { Logger::println("VarDeclaration"); if (!vd->llvmTouched && vd->isDataseg()) vd->toObjFile(); + // TODO + /* if (vd->isTypedefDeclaration()) { e->istypeinfo = true; } + */ assert(vd->llvmValue); Type* t = DtoDType(type); @@ -1416,29 +1487,27 @@ elem* SymOffExp::toElem(IRState* p) Type* vdtype = DtoDType(vd->type); llvm::Value* llvalue = vd->nestedref ? DtoNestedVariable(vd) : vd->llvmValue; + llvm::Value* varmem = 0; if (vdtype->ty == Tstruct && !(t->ty == Tpointer && t->next == vdtype)) { Logger::println("struct"); TypeStruct* vdt = (TypeStruct*)vdtype; assert(vdt->sym); - e = new elem; + const llvm::Type* llt = DtoType(t); if (offset == 0) { - e->mem = p->ir->CreateBitCast(llvalue, llt, "tmp"); + varmem = p->ir->CreateBitCast(llvalue, llt, "tmp"); } else { std::vector dst; - e->mem = DtoIndexStruct(llvalue,vdt->sym, tnext, offset, dst); + varmem = DtoIndexStruct(llvalue,vdt->sym, tnext, offset, dst); } - e->type = elem::VAL; - e->field = true; } else if (vdtype->ty == Tsarray) { Logger::println("sarray"); - e = new elem; + assert(llvalue); - e->arg = llvalue; - e->type = elem::VAL; + //e->arg = llvalue; // TODO const llvm::Type* llt = DtoType(t); llvm::Value* off = 0; @@ -1446,78 +1515,74 @@ elem* SymOffExp::toElem(IRState* p) Logger::println("offset = %d\n", offset); } if (llvalue->getType() != llt) { - e->mem = p->ir->CreateBitCast(llvalue, llt, "tmp"); + varmem = p->ir->CreateBitCast(llvalue, llt, "tmp"); if (offset != 0) - e->mem = DtoGEPi(e->mem, offset, "tmp"); + varmem = DtoGEPi(varmem, offset, "tmp"); } else { assert(offset == 0); - e->mem = DtoGEPi(llvalue,0,0,"tmp"); + varmem = DtoGEPi(llvalue,0,0,"tmp"); } } else if (offset == 0) { Logger::println("normal symoff"); - e = new elem; - e->type = elem::VAL; + assert(llvalue); - e->mem = llvalue; + varmem = llvalue; const llvm::Type* llt = DtoType(t); if (llvalue->getType() != llt) { - e->mem = p->ir->CreateBitCast(e->mem, llt, "tmp"); + varmem = p->ir->CreateBitCast(varmem, llt, "tmp"); } } else { assert(0); } + return new DFieldValue(type, varmem, true); } else if (FuncDeclaration* fd = var->isFuncDeclaration()) { Logger::println("FuncDeclaration"); - e = new elem; + if (fd->llvmValue == 0) fd->toObjFile(); - e->val = fd->llvmValue; - e->type = elem::FUNC; + return new DFuncValue(fd, fd->llvmValue); } - assert(e != 0); - assert(e->type != elem::NONE); - return e; + + assert(0); + return 0; } ////////////////////////////////////////////////////////////////////////////////////////// -elem* PtrExp::toElem(IRState* p) +DValue* PtrExp::toElem(IRState* p) { Logger::print("PtrExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; - elem* a = e1->toElem(p); - if (a->mem) - Logger::cout() << "mem: " << *a->mem << '\n'; - if (a->val) - Logger::cout() << "val: " << *a->val << '\n'; + DValue* a = e1->toElem(p); - if (a->field) - e->mem = a->mem; - else - e->mem = a->getValue(); - e->type = elem::VAR; + if (p->topexp() && p->topexp()->e1 == this) { + Logger::println("lval PtrExp"); + //if (a->isField()) return a; + return new DVarValue(type, a->getRVal(), true); + } - delete a; - return e; + llvm::Value* lv = a->getRVal(); + llvm::Value* v = lv; + if (DtoCanLoad(v)) + v = DtoLoad(v); + return new DLValueCast(type, lv, v); } ////////////////////////////////////////////////////////////////////////////////////////// -elem* DotVarExp::toElem(IRState* p) +DValue* DotVarExp::toElem(IRState* p) { Logger::print("DotVarExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; - elem* l = e1->toElem(p); + DValue* l = e1->toElem(p); Type* t = DtoDType(type); Type* e1type = DtoDType(e1->type); @@ -1530,7 +1595,7 @@ elem* DotVarExp::toElem(IRState* p) assert(e1type->next->ty == Tstruct); TypeStruct* ts = (TypeStruct*)e1type->next; Logger::println("Struct member offset:%d", vd->offset); - llvm::Value* src = l->val ? l->val : l->mem; + llvm::Value* src = l->getRVal(); std::vector vdoffsets; arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets); } @@ -1539,15 +1604,15 @@ elem* DotVarExp::toElem(IRState* p) Logger::println("Class member offset: %d", vd->offset); std::vector vdoffsets(1,0); tc->sym->offsetToIndex(vd->type, vd->offset, vdoffsets); - llvm::Value* src = l->getValue(); + llvm::Value* src = l->getRVal(); Logger::cout() << "src: " << *src << '\n'; arrptr = DtoGEP(src,vdoffsets,"tmp",p->scopebb()); } else assert(0); - e->mem = arrptr; - Logger::cout() << "mem: " << *e->mem << '\n'; - e->type = elem::VAR; + + Logger::cout() << "mem: " << *arrptr << '\n'; + return new DVarValue(vd, arrptr, true); } else if (FuncDeclaration* fdecl = var->isFuncDeclaration()) { @@ -1557,7 +1622,8 @@ elem* DotVarExp::toElem(IRState* p) } llvm::Value* funcval = fdecl->llvmValue; - e->arg = l->getValue(); + llvm::Value* vthis = l->getRVal(); + unsigned cc = (unsigned)-1; // virtual call if (fdecl->isVirtual()) { @@ -1566,177 +1632,66 @@ elem* DotVarExp::toElem(IRState* p) llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); llvm::Value* vtblidx = llvm::ConstantInt::get(llvm::Type::Int32Ty, (size_t)fdecl->vtblIndex, false); - funcval = DtoGEP(e->arg, zero, zero, "tmp", p->scopebb()); + funcval = DtoGEP(vthis, zero, zero, "tmp", p->scopebb()); funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb()); funcval = DtoGEP(funcval, zero, vtblidx, toChars(), p->scopebb()); funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb()); assert(funcval->getType() == fdecl->llvmValue->getType()); - e->callconv = DtoCallingConv(fdecl->linkage); + cc = DtoCallingConv(fdecl->linkage); } - e->val = funcval; - e->type = elem::FUNC; - e->funcdecl = fdecl; + return new DFuncValue(fdecl, funcval, vthis); } else { printf("unknown: %s\n", var->toChars()); - assert(0); } - delete l; - - return e; + assert(0); + return 0; } ////////////////////////////////////////////////////////////////////////////////////////// -elem* ThisExp::toElem(IRState* p) +DValue* ThisExp::toElem(IRState* p) { Logger::print("ThisExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; if (VarDeclaration* vd = var->isVarDeclaration()) { llvm::Value* v = p->func().decl->llvmThisVar; if (llvm::isa(v)) v = new llvm::LoadInst(v, "tmp", p->scopebb()); - e->mem = v; - e->type = elem::VAL; - e->isthis = true; - } - else { - assert(0); + return new DThisValue(vd, v); } - return e; + assert(0); + return 0; } ////////////////////////////////////////////////////////////////////////////////////////// -elem* AddrExp::toElem(IRState* p) +DValue* AddrExp::toElem(IRState* p) { Logger::print("AddrExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = e1->toElem(p); - e->field = true; - return e; + DValue* v = e1->toElem(p); + if (v->isField()) + return v; + return new DFieldValue(type, v->getLVal(), false); } ////////////////////////////////////////////////////////////////////////////////////////// -elem* StructLiteralExp::toElem(IRState* p) -{ - Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars()); - LOG_SCOPE; - elem* e = new elem; - - llvm::Value* sptr; - const llvm::Type* llt = DtoType(type); - - // temporary struct literal - if (!p->topexp() || p->topexp()->e2 != this) - { - sptr = new llvm::AllocaInst(llt,"tmpstructliteral",p->topallocapoint()); - e->mem = sptr; - e->type = elem::VAR; - } - // already has memory - else - { - assert(p->topexp()->e2 == this); - sptr = p->topexp()->v; - } - - // num elements in literal - unsigned n = elements->dim; - - // unions might have different types for each literal - if (sd->llvmHasUnions) { - // build the type of the literal - std::vector tys; - for (unsigned i=0; idata[i]; - if (!vx) continue; - tys.push_back(DtoType(vx->type)); - } - const llvm::StructType* t = llvm::StructType::get(tys); - if (t != llt) { - if (gTargetData->getTypeSize(t) != gTargetData->getTypeSize(llt)) { - Logger::cout() << "got size " << gTargetData->getTypeSize(t) << ", expected " << gTargetData->getTypeSize(llt) << '\n'; - assert(0 && "type size mismatch"); - } - sptr = p->ir->CreateBitCast(sptr, llvm::PointerType::get(t), "tmp"); - Logger::cout() << "sptr type is now: " << *t << '\n'; - } - } - - // build - unsigned j = 0; - for (unsigned i=0; idata[i]; - if (!vx) continue; - - Logger::cout() << "getting index " << j << " of " << *sptr << '\n'; - llvm::Value* arrptr = DtoGEPi(sptr,0,j,"tmp",p->scopebb()); - - p->exps.push_back(IRExp(NULL,vx,arrptr)); - elem* ve = vx->toElem(p); - p->exps.pop_back(); - - if (!ve->inplace) { - llvm::Value* val = ve->getValue(); - Logger::cout() << *val << " | " << *arrptr << '\n'; - - Type* vxtype = DtoDType(vx->type); - DtoAssign(vxtype, arrptr, val); - } - delete ve; - - j++; - } - - e->inplace = true; - - return e; -} - -////////////////////////////////////////////////////////////////////////////////////////// - -llvm::Constant* StructLiteralExp::toConstElem(IRState* p) -{ - Logger::print("StructLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars()); - LOG_SCOPE; - - unsigned n = elements->dim; - std::vector vals(n, NULL); - - for (unsigned i=0; idata[i]; - vals[i] = vx->toConstElem(p); - } - - assert(DtoDType(type)->ty == Tstruct); - const llvm::Type* t = DtoType(type); - const llvm::StructType* st = llvm::cast(t); - return llvm::ConstantStruct::get(st,vals); -} - -////////////////////////////////////////////////////////////////////////////////////////// - -elem* IndexExp::toElem(IRState* p) +DValue* IndexExp::toElem(IRState* p) { Logger::print("IndexExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; - - elem* l = e1->toElem(p); + DValue* l = e1->toElem(p); Type* e1type = DtoDType(e1->type); - p->arrays.push_back(l->mem); // if $ is used it must be an array so this is fine. - elem* r = e2->toElem(p); + p->arrays.push_back(l); // if $ is used it must be an array so this is fine. + DValue* r = e2->toElem(p); p->arrays.pop_back(); llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); @@ -1744,90 +1699,82 @@ elem* IndexExp::toElem(IRState* p) llvm::Value* arrptr = 0; if (e1type->ty == Tpointer) { - arrptr = new llvm::GetElementPtrInst(l->getValue(),r->getValue(),"tmp",p->scopebb()); + arrptr = new llvm::GetElementPtrInst(l->getRVal(),r->getRVal(),"tmp",p->scopebb()); } else if (e1type->ty == Tsarray) { - arrptr = DtoGEP(l->getValue(), zero, r->getValue(),"tmp",p->scopebb()); + arrptr = DtoGEP(l->getRVal(), zero, r->getRVal(),"tmp",p->scopebb()); } else if (e1type->ty == Tarray) { - arrptr = DtoGEP(l->mem,zero,one,"tmp",p->scopebb()); + arrptr = DtoGEP(l->getLVal(),zero,one,"tmp",p->scopebb()); arrptr = new llvm::LoadInst(arrptr,"tmp",p->scopebb()); - arrptr = new llvm::GetElementPtrInst(arrptr,r->getValue(),"tmp",p->scopebb()); + arrptr = new llvm::GetElementPtrInst(arrptr,r->getRVal(),"tmp",p->scopebb()); } assert(arrptr); - - e->mem = arrptr; - e->type = elem::VAR; - - delete l; - delete r; - - return e; + return new DVarValue(type, arrptr, true); } ////////////////////////////////////////////////////////////////////////////////////////// -elem* SliceExp::toElem(IRState* p) +DValue* SliceExp::toElem(IRState* p) { Logger::print("SliceExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; Type* t = DtoDType(type); - assert(t->ty == Tarray); - - elem* v = e1->toElem(p); Type* e1type = DtoDType(e1->type); - elem* e = new elem; - assert(v->mem); - e->type = elem::SLICE; + DValue* v = e1->toElem(p); + llvm::Value* vmem = v->getLVal(); + assert(vmem); llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false); + llvm::Value* emem = 0; + llvm::Value* earg = 0; + // partial slice if (lwr) { assert(upr); - p->arrays.push_back(v->mem); - elem* lo = lwr->toElem(p); + p->arrays.push_back(v); + DValue* lo = lwr->toElem(p); bool lwr_is_zero = false; - if (lo->type == elem::CONST) + if (DConstValue* cv = lo->isConst()) { - assert(lo->val); - assert(llvm::isa(lo->val)); + assert(llvm::isa(cv->c)); if (e1type->ty == Tpointer) { - e->mem = v->getValue(); + emem = v->getRVal(); } else if (e1type->ty == Tarray) { - llvm::Value* tmp = DtoGEP(v->mem,zero,one,"tmp",p->scopebb()); - e->mem = new llvm::LoadInst(tmp,"tmp",p->scopebb()); + llvm::Value* tmp = DtoGEP(vmem,zero,one,"tmp",p->scopebb()); + emem = new llvm::LoadInst(tmp,"tmp",p->scopebb()); } else if (e1type->ty == Tsarray) { - e->mem = DtoGEP(v->mem,zero,zero,"tmp",p->scopebb()); + emem = DtoGEP(vmem,zero,zero,"tmp",p->scopebb()); } else - assert(e->mem); + assert(emem); - llvm::ConstantInt* c = llvm::cast(lo->val); + llvm::ConstantInt* c = llvm::cast(cv->c); if (!(lwr_is_zero = c->isZero())) { - e->mem = new llvm::GetElementPtrInst(e->mem,lo->val,"tmp",p->scopebb()); + emem = new llvm::GetElementPtrInst(emem,cv->c,"tmp",p->scopebb()); } } else { if (e1type->ty == Tarray) { - llvm::Value* tmp = DtoGEP(v->mem,zero,one,"tmp",p->scopebb()); + llvm::Value* tmp = DtoGEP(vmem,zero,one,"tmp",p->scopebb()); tmp = new llvm::LoadInst(tmp,"tmp",p->scopebb()); - e->mem = new llvm::GetElementPtrInst(tmp,lo->getValue(),"tmp",p->scopebb()); + emem = new llvm::GetElementPtrInst(tmp,lo->getRVal(),"tmp",p->scopebb()); } else if (e1type->ty == Tsarray) { - e->mem = DtoGEP(v->mem,zero,lo->getValue(),"tmp",p->scopebb()); + emem = DtoGEP(vmem,zero,lo->getRVal(),"tmp",p->scopebb()); } else if (e1type->ty == Tpointer) { - e->mem = new llvm::GetElementPtrInst(v->getValue(),lo->getValue(),"tmp",p->scopebb()); + emem = new llvm::GetElementPtrInst(v->getRVal(),lo->getRVal(),"tmp",p->scopebb()); } else { Logger::println("type = %s", e1type->toChars()); @@ -1835,77 +1782,61 @@ elem* SliceExp::toElem(IRState* p) } } - elem* up = upr->toElem(p); + DValue* up = upr->toElem(p); p->arrays.pop_back(); - if (up->type == elem::CONST) + if (DConstValue* cv = up->isConst()) { - assert(up->val); - assert(llvm::isa(up->val)); + assert(llvm::isa(cv->c)); if (lwr_is_zero) { - e->arg = up->val; + earg = cv->c; } else { - if (lo->type == elem::CONST) { - llvm::Constant* clo = llvm::cast(lo->val); - llvm::Constant* cup = llvm::cast(up->val); - e->arg = llvm::ConstantExpr::getSub(cup, clo); + if (lo->isConst()) { + llvm::Constant* clo = llvm::cast(lo->getRVal()); + llvm::Constant* cup = llvm::cast(cv->c); + earg = llvm::ConstantExpr::getSub(cup, clo); } else { - e->arg = llvm::BinaryOperator::createSub(up->val, lo->getValue(), "tmp", p->scopebb()); + earg = llvm::BinaryOperator::createSub(cv->c, lo->getRVal(), "tmp", p->scopebb()); } } } else { if (lwr_is_zero) { - e->arg = up->getValue(); + earg = up->getRVal(); } else { - e->arg = llvm::BinaryOperator::createSub(up->getValue(), lo->getValue(), "tmp", p->scopebb()); + earg = llvm::BinaryOperator::createSub(up->getRVal(), lo->getRVal(), "tmp", p->scopebb()); } } - - delete lo; - delete up; - - /* - llvm::Value* tmpmem = new llvm::AllocaInst(DtoType(t),"tmp",p->topallocapoint()); - llvm::Value* ptr = DtoGEPi(tmpmem,0,0,"tmp"); - p->ir->CreateStore(e->arg, ptr); - ptr = DtoGEPi(tmpmem,0,1,"tmp"); - p->ir->CreateStore(e->mem, ptr); - e->arg = NULL; - e->mem = tmpmem; - */ } // full slice else { - e->mem = v->mem; + emem = vmem; } - delete v; - - return e; + return new DSliceValue(type,earg,emem); } ////////////////////////////////////////////////////////////////////////////////////////// -elem* CmpExp::toElem(IRState* p) +DValue* CmpExp::toElem(IRState* p) { Logger::print("CmpExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; - - elem* l = e1->toElem(p); - elem* r = e2->toElem(p); + DValue* l = e1->toElem(p); + DValue* r = e2->toElem(p); Type* t = DtoDType(e1->type); Type* e2t = DtoDType(e2->type); assert(t == e2t); + llvm::Value* eval = 0; + if (t->isintegral() || t->ty == Tpointer) { llvm::ICmpInst::Predicate cmpop; @@ -1936,11 +1867,11 @@ elem* CmpExp::toElem(IRState* p) break; case TOKleg: skip = true; - e->val = llvm::ConstantInt::getTrue(); + eval = llvm::ConstantInt::getTrue(); break; case TOKunord: skip = true; - e->val = llvm::ConstantInt::getFalse(); + eval = llvm::ConstantInt::getFalse(); break; default: @@ -1948,7 +1879,7 @@ elem* CmpExp::toElem(IRState* p) } if (!skip) { - e->val = new llvm::ICmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb()); + eval = new llvm::ICmpInst(cmpop, l->getRVal(), r->getRVal(), "tmp", p->scopebb()); } } else if (t->isfloating()) @@ -1984,37 +1915,32 @@ elem* CmpExp::toElem(IRState* p) default: assert(0); } - e->val = new llvm::FCmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb()); + eval = new llvm::FCmpInst(cmpop, l->getRVal(), r->getRVal(), "tmp", p->scopebb()); } else { assert(0 && "Unsupported CmpExp type"); } - delete l; - delete r; - - e->type = elem::VAL; - - return e; + return new DImValue(type, eval); } ////////////////////////////////////////////////////////////////////////////////////////// -elem* EqualExp::toElem(IRState* p) +DValue* EqualExp::toElem(IRState* p) { Logger::print("EqualExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; - - elem* l = e1->toElem(p); - elem* r = e2->toElem(p); + DValue* l = e1->toElem(p); + DValue* r = e2->toElem(p); Type* t = DtoDType(e1->type); Type* e2t = DtoDType(e2->type); assert(t == e2t); + llvm::Value* eval = 0; + if (t->isintegral() || t->ty == Tpointer) { Logger::println("integral or pointer"); @@ -2030,7 +1956,7 @@ elem* EqualExp::toElem(IRState* p) default: assert(0); } - e->val = new llvm::ICmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb()); + eval = new llvm::ICmpInst(cmpop, l->getRVal(), r->getRVal(), "tmp", p->scopebb()); } else if (t->isfloating()) { @@ -2047,52 +1973,42 @@ elem* EqualExp::toElem(IRState* p) default: assert(0); } - e->val = new llvm::FCmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb()); + eval = new llvm::FCmpInst(cmpop, l->getRVal(), r->getRVal(), "tmp", p->scopebb()); } else if (t->ty == Tsarray) { Logger::println("static array"); - e->val = DtoStaticArrayCompare(op,l->mem,r->mem); + eval = DtoStaticArrayCompare(op,l->getRVal(),r->getRVal()); } else if (t->ty == Tarray) { Logger::println("dynamic array"); - e->val = DtoDynArrayCompare(op,l->mem,r->mem); + eval = DtoDynArrayCompare(op,l->getRVal(),r->getRVal()); } else if (t->ty == Tdelegate) { Logger::println("delegate"); - e->val = DtoCompareDelegate(op,l->mem,r->mem); + eval = DtoCompareDelegate(op,l->getRVal(),r->getRVal()); } else { assert(0 && "Unsupported EqualExp type"); } - delete l; - delete r; - - e->type = elem::VAL; - - return e; + return new DImValue(type, eval); } ////////////////////////////////////////////////////////////////////////////////////////// -elem* PostExp::toElem(IRState* p) +DValue* PostExp::toElem(IRState* p) { Logger::print("PostExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* l = e1->toElem(p); - elem* r = e2->toElem(p); + DValue* l = e1->toElem(p); + DValue* r = e2->toElem(p); - elem* e = new elem; - e->mem = l->mem; - e->val = l->getValue(); - e->type = elem::VAL; - - llvm::Value* val = e->val; + llvm::Value* val = l->getRVal(); llvm::Value* post = 0; Type* e1type = DtoDType(e1->type); @@ -2131,18 +2047,14 @@ elem* PostExp::toElem(IRState* p) else assert(post); - assert(l->mem); - new llvm::StoreInst(post,l->mem,p->scopebb()); + DtoStore(post,l->getLVal()); - delete l; - delete r; - - return e; + return new DImValue(type,val,true); } ////////////////////////////////////////////////////////////////////////////////////////// -elem* NewExp::toElem(IRState* p) +DValue* NewExp::toElem(IRState* p) { Logger::print("NewExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; @@ -2152,58 +2064,56 @@ elem* NewExp::toElem(IRState* p) assert(newtype); assert(!allocator); - elem* e = new elem; - e->inplace = true; - Type* ntype = DtoDType(newtype); const llvm::Type* t = DtoType(ntype); + llvm::Value* emem = 0; + bool inplace = true; + if (onstack) { assert(ntype->ty == Tclass); - e->mem = new llvm::AllocaInst(t->getContainedType(0),"tmp",p->topallocapoint()); + emem = new llvm::AllocaInst(t->getContainedType(0),"tmp",p->topallocapoint()); } else { if (ntype->ty == Tclass) { - e->mem = new llvm::MallocInst(t->getContainedType(0),"tmp",p->scopebb()); + emem = new llvm::MallocInst(t->getContainedType(0),"tmp",p->scopebb()); } else if (ntype->ty == Tarray) { assert(arguments); if (arguments->dim == 1) { - elem* sz = ((Expression*)arguments->data[0])->toElem(p); - llvm::Value* dimval = sz->getValue(); + 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'; - e->mem = new llvm::AllocaInst(restype,"tmp",p->topallocapoint()); - DtoNewDynArray(e->mem, dimval, nnt); - e->inplace = false; + 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); - e->mem = p->topexp()->v; - DtoNewDynArray(e->mem, dimval, nnt); + emem = p->topexp()->v->getLVal(); + DtoNewDynArray(emem, dimval, nnt); } else assert(0); - delete sz; } else { assert(0); } } else { - e->mem = new llvm::MallocInst(t,"tmp",p->scopebb()); + emem = new llvm::MallocInst(t,"tmp",p->scopebb()); } } if (ntype->ty == Tclass) { // first apply the static initializer - assert(e->mem); - DtoInitClass((TypeClass*)ntype, e->mem); + DtoInitClass((TypeClass*)ntype, emem); // then call constructor if (arguments) { @@ -2213,7 +2123,7 @@ elem* NewExp::toElem(IRState* p) TypeFunction* tf = (TypeFunction*)DtoDType(member->type); std::vector ctorargs; - ctorargs.push_back(e->mem); + ctorargs.push_back(emem); for (size_t i=0; idim; ++i) { Expression* ex = (Expression*)arguments->data[i]; @@ -2221,35 +2131,36 @@ elem* NewExp::toElem(IRState* p) llvm::Value* a = DtoArgument(fn->getFunctionType()->getParamType(i+1), fnarg, ex); ctorargs.push_back(a); } - e->mem = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb()); + emem = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb()); } } else if (ntype->ty == Tstruct) { TypeStruct* ts = (TypeStruct*)ntype; if (ts->isZeroInit()) { - DtoStructZeroInit(e->mem); + DtoStructZeroInit(emem); } else { - DtoStructCopy(e->mem,ts->llvmInit); + DtoStructCopy(emem,ts->llvmInit); } } - e->type = elem::VAR; + if (inplace) + return new DImValue(type, emem, true); - return e; + return new DVarValue(type, emem, true); } ////////////////////////////////////////////////////////////////////////////////////////// -elem* DeleteExp::toElem(IRState* p) +DValue* DeleteExp::toElem(IRState* p) { Logger::print("DeleteExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; //assert(e1->type->ty != Tclass); - elem* v = e1->toElem(p); - llvm::Value* val = v->getValue(); + DValue* v = e1->toElem(p); + llvm::Value* val = v->getRVal(); llvm::Value* ldval = 0; const llvm::Type* t = val->getType(); @@ -2258,30 +2169,26 @@ elem* DeleteExp::toElem(IRState* p) Type* e1type = DtoDType(e1->type); if (e1type->ty == Tpointer) { - ldval = v->getValue(); - new llvm::FreeInst(ldval, p->scopebb()); - Logger::cout() << *z << '\n'; Logger::cout() << *val << '\n'; - new llvm::StoreInst(z, v->mem, p->scopebb()); + new llvm::FreeInst(val, p->scopebb()); + new llvm::StoreInst(z, v->getLVal(), p->scopebb()); } else if (e1type->ty == Tclass) { TypeClass* tc = (TypeClass*)e1type; DtoCallClassDtors(tc, val); - if (v->vardecl && !v->vardecl->onstack) { - new llvm::FreeInst(val, p->scopebb()); + if (DVarValue* vv = v->isVar()) { + if (vv->var && !vv->var->onstack) + new llvm::FreeInst(val, p->scopebb()); } - new llvm::StoreInst(z, v->mem, p->scopebb()); + new llvm::StoreInst(z, v->getLVal(), p->scopebb()); } else if (e1type->ty == Tarray) { // must be on the heap (correct?) - ldval = v->getValue(); - llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false); - - llvm::Value* ptr = DtoGEP(ldval,zero,one,"tmp",p->scopebb()); + llvm::Value* ptr = DtoGEP(val,zero,one,"tmp",p->scopebb()); ptr = new llvm::LoadInst(ptr,"tmp",p->scopebb()); new llvm::FreeInst(ptr, p->scopebb()); DtoNullArray(val); @@ -2290,83 +2197,68 @@ elem* DeleteExp::toElem(IRState* p) assert(0); } - delete v; - // this expression produces no useful data return 0; } ////////////////////////////////////////////////////////////////////////////////////////// -elem* ArrayLengthExp::toElem(IRState* p) +DValue* ArrayLengthExp::toElem(IRState* p) { Logger::print("ArrayLengthExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; - elem* u = e1->toElem(p); + DValue* u = e1->toElem(p); if (p->topexp() && p->topexp()->e1 == this) { - e->mem = u->mem; - e->type = elem::ARRAYLEN; + return new DArrayLenValue(type, u->getLVal()); } else { llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); - llvm::Value* ptr = DtoGEP(u->mem,zero,zero,"tmp",p->scopebb()); - e->val = new llvm::LoadInst(ptr, "tmp", p->scopebb()); - e->type = elem::VAL; + llvm::Value* ptr = DtoGEP(u->getRVal(),zero,zero,"tmp",p->scopebb()); + ptr = new llvm::LoadInst(ptr, "tmp", p->scopebb()); + return new DImValue(type, ptr); } - delete u; - - return e; } ////////////////////////////////////////////////////////////////////////////////////////// -elem* AssertExp::toElem(IRState* p) +DValue* AssertExp::toElem(IRState* p) { Logger::print("AssertExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* u = e1->toElem(p); - elem* m = msg ? msg->toElem(p) : NULL; + 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->getValue(), loca, m ? m->val : NULL); + DtoAssert(u->getRVal(), loca, m ? m->getRVal() : NULL); - delete m; - delete u; - - return new elem; + return 0; } ////////////////////////////////////////////////////////////////////////////////////////// -elem* NotExp::toElem(IRState* p) +DValue* NotExp::toElem(IRState* p) { Logger::print("NotExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; - elem* u = e1->toElem(p); + DValue* u = e1->toElem(p); - llvm::Value* b = DtoBoolean(u->getValue()); + llvm::Value* b = DtoBoolean(u->getRVal()); - llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int1Ty, 0, true); - e->val = p->ir->CreateICmpEQ(b,zero); - //e->val = new llvm::ICmpInst(llvm::ICmpInst::ICMP_EQ,b,zero,"tmp",p->scopebb()); - e->type = elem::VAL; + llvm::Constant* zero = llvm::ConstantInt::get(llvm::Type::Int1Ty, 0, true); + b = p->ir->CreateICmpEQ(b,zero); - delete u; - - return e; + return new DImValue(type, b); } ////////////////////////////////////////////////////////////////////////////////////////// -elem* AndAndExp::toElem(IRState* p) +DValue* AndAndExp::toElem(IRState* p) { Logger::print("AndAndExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; @@ -2375,40 +2267,34 @@ elem* AndAndExp::toElem(IRState* p) llvm::Value* resval = 0; llvm::BasicBlock* entryblock = &p->topfunc()->front(); resval = new llvm::AllocaInst(llvm::Type::Int1Ty,"andandtmp",p->topallocapoint()); - - elem* e = new elem; - elem* u = e1->toElem(p); + + DValue* u = e1->toElem(p); llvm::BasicBlock* oldend = p->scopeend(); llvm::BasicBlock* andand = new llvm::BasicBlock("andand", gIR->topfunc(), oldend); llvm::BasicBlock* andandend = new llvm::BasicBlock("andandend", gIR->topfunc(), oldend); - - llvm::Value* ubool = DtoBoolean(u->getValue()); + + llvm::Value* ubool = DtoBoolean(u->getRVal()); new llvm::StoreInst(ubool,resval,p->scopebb()); new llvm::BranchInst(andand,andandend,ubool,p->scopebb()); - - p->scope() = IRScope(andand, andandend); - elem* v = e2->toElem(p); - llvm::Value* vbool = DtoBoolean(v->getValue()); + p->scope() = IRScope(andand, andandend); + DValue* v = e2->toElem(p); + + llvm::Value* vbool = DtoBoolean(v->getRVal()); llvm::Value* uandvbool = llvm::BinaryOperator::create(llvm::BinaryOperator::And, ubool, vbool,"tmp",p->scopebb()); new llvm::StoreInst(uandvbool,resval,p->scopebb()); new llvm::BranchInst(andandend,p->scopebb()); - delete u; - delete v; - p->scope() = IRScope(andandend, oldend); - - e->val = new llvm::LoadInst(resval,"tmp",p->scopebb()); - e->type = elem::VAL; - return e; + resval = new llvm::LoadInst(resval,"tmp",p->scopebb()); + return new DImValue(type, resval); } ////////////////////////////////////////////////////////////////////////////////////////// -elem* OrOrExp::toElem(IRState* p) +DValue* OrOrExp::toElem(IRState* p) { Logger::print("OrOrExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; @@ -2417,73 +2303,57 @@ elem* OrOrExp::toElem(IRState* p) llvm::Value* resval = 0; llvm::BasicBlock* entryblock = &p->topfunc()->front(); resval = new llvm::AllocaInst(llvm::Type::Int1Ty,"orortmp",p->topallocapoint()); - - elem* e = new elem; - elem* u = e1->toElem(p); + + DValue* u = e1->toElem(p); llvm::BasicBlock* oldend = p->scopeend(); llvm::BasicBlock* oror = new llvm::BasicBlock("oror", gIR->topfunc(), oldend); llvm::BasicBlock* ororend = new llvm::BasicBlock("ororend", gIR->topfunc(), oldend); - - llvm::Value* ubool = DtoBoolean(u->getValue()); + + llvm::Value* ubool = DtoBoolean(u->getRVal()); new llvm::StoreInst(ubool,resval,p->scopebb()); new llvm::BranchInst(ororend,oror,ubool,p->scopebb()); - - p->scope() = IRScope(oror, ororend); - elem* v = e2->toElem(p); - llvm::Value* vbool = DtoBoolean(v->getValue()); + p->scope() = IRScope(oror, ororend); + DValue* v = e2->toElem(p); + + llvm::Value* vbool = DtoBoolean(v->getRVal()); new llvm::StoreInst(vbool,resval,p->scopebb()); new llvm::BranchInst(ororend,p->scopebb()); - delete u; - delete v; - p->scope() = IRScope(ororend, oldend); - - e->val = new llvm::LoadInst(resval,"tmp",p->scopebb()); - e->type = elem::VAL; - return e; + resval = new llvm::LoadInst(resval,"tmp",p->scopebb()); + return new DImValue(type, resval); } ////////////////////////////////////////////////////////////////////////////////////////// #define BinBitExp(X,Y) \ -elem* X##Exp::toElem(IRState* p) \ +DValue* X##Exp::toElem(IRState* p) \ { \ Logger::print("%sExp::toElem: %s | %s\n", #X, toChars(), type->toChars()); \ LOG_SCOPE; \ - elem* e = new elem; \ - elem* u = e1->toElem(p); \ - elem* v = e2->toElem(p); \ - e->val = llvm::BinaryOperator::create(llvm::Instruction::Y, u->getValue(), v->getValue(), "tmp", p->scopebb()); \ - e->type = elem::VAL; \ - delete u; \ - delete v; \ - return e; \ + DValue* u = e1->toElem(p); \ + DValue* v = e2->toElem(p); \ + llvm::Value* x = llvm::BinaryOperator::create(llvm::Instruction::Y, u->getRVal(), v->getRVal(), "tmp", p->scopebb()); \ + return new DImValue(type, x); \ } \ \ -elem* X##AssignExp::toElem(IRState* p) \ +DValue* X##AssignExp::toElem(IRState* p) \ { \ Logger::print("%sAssignExp::toElem: %s | %s\n", #X, toChars(), type->toChars()); \ LOG_SCOPE; \ - elem* u = e1->toElem(p); \ - elem* v = e2->toElem(p); \ - llvm::Value* uval = u->getValue(); \ - assert(uval); \ - llvm::Value* vval = v->getValue(); \ - assert(vval); \ + p->exps.push_back(IRExp(e1,e2,NULL)); \ + DValue* u = e1->toElem(p); \ + p->topexp()->v = u; \ + DValue* v = e2->toElem(p); \ + p->exps.pop_back(); \ + llvm::Value* uval = u->getRVal(); \ + llvm::Value* vval = v->getRVal(); \ llvm::Value* tmp = llvm::BinaryOperator::create(llvm::Instruction::Y, uval, vval, "tmp", p->scopebb()); \ - assert(u->mem); \ - Logger::cout() << *tmp << '|' << *u->mem << '\n'; \ - new llvm::StoreInst(DtoPointedType(u->mem, tmp), u->mem, p->scopebb()); \ - delete u; \ - delete v; \ - elem* e = new elem; \ - e->mem = u->mem; \ - e->type = elem::VAR; \ - return e; \ + new llvm::StoreInst(DtoPointedType(u->getLVal(), tmp), u->getLVal(), p->scopebb()); \ + return u; \ } BinBitExp(And,And); @@ -2495,7 +2365,7 @@ BinBitExp(Ushr,LShr); ////////////////////////////////////////////////////////////////////////////////////////// -elem* HaltExp::toElem(IRState* p) +DValue* HaltExp::toElem(IRState* p) { Logger::print("HaltExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; @@ -2509,13 +2379,12 @@ elem* HaltExp::toElem(IRState* p) ////////////////////////////////////////////////////////////////////////////////////////// -elem* DelegateExp::toElem(IRState* p) +DValue* DelegateExp::toElem(IRState* p) { Logger::print("DelegateExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; - elem* u = e1->toElem(p); + DValue* u = e1->toElem(p); llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false); @@ -2523,10 +2392,10 @@ elem* DelegateExp::toElem(IRState* p) const llvm::Type* int8ptrty = llvm::PointerType::get(llvm::Type::Int8Ty); assert(p->topexp() && p->topexp()->e2 == this && p->topexp()->v); - llvm::Value* lval = p->topexp()->v; + llvm::Value* lval = p->topexp()->v->getLVal(); llvm::Value* context = DtoGEP(lval,zero,zero,"tmp",p->scopebb()); - llvm::Value* castcontext = new llvm::BitCastInst(u->getValue(),int8ptrty,"tmp",p->scopebb()); + llvm::Value* castcontext = new llvm::BitCastInst(u->getRVal(),int8ptrty,"tmp",p->scopebb()); new llvm::StoreInst(castcontext, context, p->scopebb()); llvm::Value* fptr = DtoGEP(lval,zero,one,"tmp",p->scopebb()); @@ -2535,70 +2404,61 @@ elem* DelegateExp::toElem(IRState* p) llvm::Value* castfptr = new llvm::BitCastInst(func->llvmValue,fptr->getType()->getContainedType(0),"tmp",p->scopebb()); new llvm::StoreInst(castfptr, fptr, p->scopebb()); - e->inplace = true; - - delete u; - return e; + return new DImValue(type, u->getRVal(), true); } ////////////////////////////////////////////////////////////////////////////////////////// -elem* IdentityExp::toElem(IRState* p) +DValue* IdentityExp::toElem(IRState* p) { Logger::print("IdentityExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* u = e1->toElem(p); - elem* v = e2->toElem(p); + DValue* u = e1->toElem(p); + DValue* v = e2->toElem(p); - elem* e = new elem; - - llvm::Value* l = u->field ? u->mem : u->getValue(); - llvm::Value* r = v->field ? v->mem : v->getValue(); + llvm::Value* l = u->getRVal(); + llvm::Value* r = v->getRVal(); Type* t1 = DtoDType(e1->type); + llvm::Value* eval = 0; + if (t1->ty == Tarray) { - if (v->type == elem::NUL) { + if (v->isNull()) { r = NULL; } else { assert(l->getType() == r->getType()); } - e->val = DtoDynArrayIs(op,l,r); + eval = DtoDynArrayIs(op,l,r); } else { llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE; - if (t1->ty == Tpointer && v->type == elem::NUL && l->getType() != r->getType()) { + if (t1->ty == Tpointer && v->isNull() && l->getType() != r->getType()) { r = llvm::ConstantPointerNull::get(llvm::cast(l->getType())); } Logger::cout() << "l = " << *l << " r = " << *r << '\n'; - e->val = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb()); + eval = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb()); } - e->type = elem::VAL; - - delete u; - delete v; - - return e; + return new DImValue(type, eval); } ////////////////////////////////////////////////////////////////////////////////////////// -elem* CommaExp::toElem(IRState* p) +DValue* CommaExp::toElem(IRState* p) { Logger::print("CommaExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* u = e1->toElem(p); - elem* v = e2->toElem(p); - delete u; + DValue* u = e1->toElem(p); + DValue* v = e2->toElem(p); return v; } ////////////////////////////////////////////////////////////////////////////////////////// -elem* CondExp::toElem(IRState* p) +DValue* CondExp::toElem(IRState* p) { Logger::print("CondExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; @@ -2609,68 +2469,56 @@ elem* CondExp::toElem(IRState* p) // allocate a temporary for the final result. failed to come up with a better way :/ llvm::BasicBlock* entryblock = &p->topfunc()->front(); llvm::Value* resval = new llvm::AllocaInst(resty,"condtmp",p->topallocapoint()); + DVarValue* dvv = new DVarValue(type, resval, true); llvm::BasicBlock* oldend = p->scopeend(); llvm::BasicBlock* condtrue = new llvm::BasicBlock("condtrue", gIR->topfunc(), oldend); llvm::BasicBlock* condfalse = new llvm::BasicBlock("condfalse", gIR->topfunc(), oldend); llvm::BasicBlock* condend = new llvm::BasicBlock("condend", gIR->topfunc(), oldend); - elem* c = econd->toElem(p); - llvm::Value* cond_val = DtoBoolean(c->getValue()); - delete c; + DValue* c = econd->toElem(p); + llvm::Value* cond_val = DtoBoolean(c->getRVal()); new llvm::BranchInst(condtrue,condfalse,cond_val,p->scopebb()); p->scope() = IRScope(condtrue, condfalse); - elem* u = e1->toElem(p); - DtoAssign(dtype, resval, u->getValue()); + DValue* u = e1->toElem(p); + DtoAssign(dvv, u); new llvm::BranchInst(condend,p->scopebb()); - delete u; p->scope() = IRScope(condfalse, condend); - elem* v = e2->toElem(p); - DtoAssign(dtype, resval, v->getValue()); + DValue* v = e2->toElem(p); + DtoAssign(dvv, v); new llvm::BranchInst(condend,p->scopebb()); - delete v; p->scope() = IRScope(condend, oldend); - - elem* e = new elem; - e->mem = resval; - e->type = elem::VAR; - return e; + return dvv; } ////////////////////////////////////////////////////////////////////////////////////////// -elem* ComExp::toElem(IRState* p) +DValue* ComExp::toElem(IRState* p) { Logger::print("ComExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; - elem* u = e1->toElem(p); + DValue* u = e1->toElem(p); - llvm::Value* value = u->getValue(); + llvm::Value* value = u->getRVal(); llvm::Value* minusone = llvm::ConstantInt::get(value->getType(), -1, true); - e->val = llvm::BinaryOperator::create(llvm::Instruction::Xor, value, minusone, "tmp", p->scopebb()); + value = llvm::BinaryOperator::create(llvm::Instruction::Xor, value, minusone, "tmp", p->scopebb()); - delete u; - - e->type = elem::VAL; - - return e; + return new DImValue(type, value); } ////////////////////////////////////////////////////////////////////////////////////////// -elem* NegExp::toElem(IRState* p) +DValue* NegExp::toElem(IRState* p) { Logger::print("NegExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* e = new elem; - elem* l = e1->toElem(p); - llvm::Value* val = l->getValue(); - delete l; + + DValue* l = e1->toElem(p); + llvm::Value* val = l->getRVal(); Type* t = DtoDType(type); @@ -2688,61 +2536,52 @@ elem* NegExp::toElem(IRState* p) else assert(0); - e->val = llvm::BinaryOperator::createSub(zero,val,"tmp",p->scopebb()); - e->type = elem::VAL; - - return e; + val = llvm::BinaryOperator::createSub(zero,val,"tmp",p->scopebb()); + return new DImValue(type, val); } ////////////////////////////////////////////////////////////////////////////////////////// -elem* CatExp::toElem(IRState* p) +DValue* CatExp::toElem(IRState* p) { Logger::print("CatExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; Type* t = DtoDType(type); - bool inplace = false; - llvm::Value* dst = 0; IRExp* ex = p->topexp(); if (ex && ex->e2 == this) { assert(ex->v); - dst = ex->v; - inplace = true; + DtoCatArrays(ex->v->getLVal(),e1,e2); + return new DImValue(type, ex->v->getLVal(), true); } else { assert(t->ty == Tarray); const llvm::Type* arrty = DtoType(t); - dst = new llvm::AllocaInst(arrty, "tmpmem", p->topallocapoint()); + llvm::Value* dst = new llvm::AllocaInst(arrty, "tmpmem", p->topallocapoint()); + DtoCatArrays(dst,e1,e2); + return new DVarValue(type, dst, true); } - - DtoCatArrays(dst,e1,e2); - - elem* e = new elem; - e->mem = dst; - e->type = elem::VAR; - e->inplace = inplace; - - return e; } ////////////////////////////////////////////////////////////////////////////////////////// -elem* CatAssignExp::toElem(IRState* p) +DValue* CatAssignExp::toElem(IRState* p) { Logger::print("CatAssignExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - elem* l = e1->toElem(p); - assert(l->mem); + DValue* l = e1->toElem(p); Type* e1type = DtoDType(e1->type); Type* elemtype = DtoDType(e1type->next); Type* e2type = DtoDType(e2->type); if (e2type == elemtype) { - DtoCatAssignElement(l->mem,e2); + DtoCatAssignElement(l->getLVal(),e2); + } + else if (e1type == e2type) { + DtoCatAssignArray(l->getLVal(),e2); } else assert(0 && "only one element at a time right now"); @@ -2752,7 +2591,55 @@ elem* CatAssignExp::toElem(IRState* p) ////////////////////////////////////////////////////////////////////////////////////////// -elem* ArrayLiteralExp::toElem(IRState* p) +DValue* FuncExp::toElem(IRState* p) +{ + Logger::print("FuncExp::toElem: %s | %s\n", toChars(), type->toChars()); + LOG_SCOPE; + + assert(fd); + + if (fd->isNested()) Logger::println("nested"); + Logger::println("kind = %s\n", fd->kind()); + + fd->toObjFile(); + + llvm::Value* lval = NULL; + if (!p->topexp() || p->topexp()->e2 != this) { + const llvm::Type* dgty = DtoType(type); + Logger::cout() << "delegate without explicit storage:" << '\n' << *dgty << '\n'; + lval = new llvm::AllocaInst(dgty,"dgstorage",p->topallocapoint()); + } + 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)); + llvm::Value* llvmNested = p->func().decl->llvmNested; + if (llvmNested == NULL) { + llvm::Value* nullcontext = llvm::ConstantPointerNull::get(pty); + p->ir->CreateStore(nullcontext, context); + } + else { + llvm::Value* nestedcontext = p->ir->CreateBitCast(llvmNested, pty, "tmp"); + p->ir->CreateStore(nestedcontext, context); + } + + llvm::Value* fptr = DtoGEPi(lval,0,1,"tmp",p->scopebb()); + + assert(fd->llvmValue); + 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); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +DValue* ArrayLiteralExp::toElem(IRState* p) { Logger::print("ArrayLiteralExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; @@ -2766,7 +2653,14 @@ elem* ArrayLiteralExp::toElem(IRState* p) mem = new llvm::AllocaInst(t,"tmparrayliteral",p->topallocapoint()); } else if (p->topexp()->e2 == this) { - mem = p->topexp()->v; + DValue* tlv = p->topexp()->v; + if (DSliceValue* sv = tlv->isSlice()) { + assert(sv->len == 0); + mem = sv->ptr; + } + else { + mem = p->topexp()->v->getLVal(); + } assert(mem); if (!llvm::isa(mem->getType()) || !llvm::isa(mem->getType()->getContainedType(0))) @@ -2782,16 +2676,11 @@ elem* ArrayLiteralExp::toElem(IRState* p) { Expression* expr = (Expression*)elements->data[i]; llvm::Value* elemAddr = DtoGEPi(mem,0,i,"tmp",p->scopebb()); - elem* e = expr->toElem(p); - new llvm::StoreInst(e->getValue(), elemAddr, p->scopebb()); + DValue* e = expr->toElem(p); + new llvm::StoreInst(e->getRVal(), elemAddr, p->scopebb()); } - elem* e = new elem; - e->mem = mem; - e->type = elem::VAL; - e->inplace = true; - - return e; + return new DImValue(type, mem, true); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -2819,61 +2708,100 @@ llvm::Constant* ArrayLiteralExp::toConstElem(IRState* p) ////////////////////////////////////////////////////////////////////////////////////////// -elem* FuncExp::toElem(IRState* p) +DValue* StructLiteralExp::toElem(IRState* p) { - Logger::print("FuncExp::toElem: %s | %s\n", toChars(), type->toChars()); + Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - assert(fd); + llvm::Value* sptr; + const llvm::Type* llt = DtoType(type); - if (fd->isNested()) Logger::println("nested"); - Logger::println("kind = %s\n", fd->kind()); + llvm::Value* mem = 0; - fd->toObjFile(); - - llvm::Value* lval = NULL; - if (!p->topexp() || p->topexp()->e2 != this) { - const llvm::Type* dgty = DtoType(type); - Logger::cout() << "delegate without explicit storage:" << '\n' << *dgty << '\n'; - lval = new llvm::AllocaInst(dgty,"dgstorage",p->topallocapoint()); - } - else if (p->topexp()->e2 == this) { - lval = p->topexp()->v; - assert(lval); + // temporary struct literal + if (!p->topexp() || p->topexp()->e2 != this) + { + sptr = new llvm::AllocaInst(llt,"tmpstructliteral",p->topallocapoint()); } + // already has memory else - assert(0); - - elem* e = new elem; - - llvm::Value* context = DtoGEPi(lval,0,0,"tmp",p->scopebb()); - const llvm::PointerType* pty = llvm::cast(context->getType()->getContainedType(0)); - llvm::Value* llvmNested = p->func().decl->llvmNested; - if (llvmNested == NULL) { - llvm::Value* nullcontext = llvm::ConstantPointerNull::get(pty); - p->ir->CreateStore(nullcontext, context); - } - else { - llvm::Value* nestedcontext = p->ir->CreateBitCast(llvmNested, pty, "tmp"); - p->ir->CreateStore(nestedcontext, context); + { + assert(p->topexp()->e2 == this); + sptr = p->topexp()->v->getLVal(); } - llvm::Value* fptr = DtoGEPi(lval,0,1,"tmp",p->scopebb()); + // num elements in literal + unsigned n = elements->dim; - assert(fd->llvmValue); - llvm::Value* castfptr = new llvm::BitCastInst(fd->llvmValue,fptr->getType()->getContainedType(0),"tmp",p->scopebb()); - new llvm::StoreInst(castfptr, fptr, p->scopebb()); + // unions might have different types for each literal + if (sd->llvmHasUnions) { + // build the type of the literal + std::vector tys; + for (unsigned i=0; idata[i]; + if (!vx) continue; + tys.push_back(DtoType(vx->type)); + } + const llvm::StructType* t = llvm::StructType::get(tys); + if (t != llt) { + if (gTargetData->getTypeSize(t) != gTargetData->getTypeSize(llt)) { + Logger::cout() << "got size " << gTargetData->getTypeSize(t) << ", expected " << gTargetData->getTypeSize(llt) << '\n'; + assert(0 && "type size mismatch"); + } + sptr = p->ir->CreateBitCast(sptr, llvm::PointerType::get(t), "tmp"); + Logger::cout() << "sptr type is now: " << *t << '\n'; + } + } - e->inplace = true; - e->mem = lval; - e->type = elem::VAR; + // build + unsigned j = 0; + for (unsigned i=0; idata[i]; + if (!vx) continue; - return e; + Logger::cout() << "getting index " << j << " of " << *sptr << '\n'; + llvm::Value* arrptr = DtoGEPi(sptr,0,j,"tmp",p->scopebb()); + DValue* darrptr = new DVarValue(vx->type, arrptr, true); + + p->exps.push_back(IRExp(NULL,vx,darrptr)); + DValue* ve = vx->toElem(p); + p->exps.pop_back(); + + if (!ve->inPlace()) + DtoAssign(darrptr, ve); + + j++; + } + + return new DImValue(type, sptr, true); } ////////////////////////////////////////////////////////////////////////////////////////// -#define STUB(x) elem *x::toElem(IRState * p) {error("Exp type "#x" not implemented: %s", toChars()); fatal(); return 0; } +llvm::Constant* StructLiteralExp::toConstElem(IRState* p) +{ + Logger::print("StructLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars()); + LOG_SCOPE; + + unsigned n = elements->dim; + std::vector vals(n, NULL); + + for (unsigned i=0; idata[i]; + vals[i] = vx->toConstElem(p); + } + + assert(DtoDType(type)->ty == Tstruct); + const llvm::Type* t = DtoType(type); + const llvm::StructType* st = llvm::cast(t); + return llvm::ConstantStruct::get(st,vals); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +#define STUB(x) DValue *x::toElem(IRState * p) {error("Exp type "#x" not implemented: %s", toChars()); fatal(); return 0; } //STUB(IdentityExp); //STUB(CondExp); //STUB(EqualExp); diff --git a/gen/tollvm.c b/gen/tollvm.cpp similarity index 90% rename from gen/tollvm.c rename to gen/tollvm.cpp index f58b926d..f99b1611 100644 --- a/gen/tollvm.c +++ b/gen/tollvm.cpp @@ -12,13 +12,13 @@ #include "gen/irstate.h" #include "gen/logger.h" #include "gen/runtime.h" -#include "gen/elem.h" #include "gen/arrays.h" +#include "gen/dvalue.h" bool DtoIsPassedByRef(Type* type) { TY t = DtoDType(type)->ty; - return (t == Tstruct || t == Tarray || t == Tdelegate); + return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray); } Type* DtoDType(Type* t) @@ -890,7 +890,7 @@ llvm::Constant* DtoConstInitializer(Type* type, Initializer* init) ////////////////////////////////////////////////////////////////////////////////////////// -elem* DtoInitializer(Initializer* init) +DValue* DtoInitializer(Initializer* init) { if (ExpInitializer* ex = init->isExpInitializer()) { @@ -1069,7 +1069,7 @@ llvm::Function* DtoDeclareFunction(FuncDeclaration* fdecl) { Argument* arg = Argument::getNth(f->parameters, k++); //arg->llvmValue = iarg; - //printf("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident); + //Logger::println("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident); if (arg && arg->ident != 0) { if (arg->vardecl) { arg->vardecl->llvmValue = iarg; @@ -1094,6 +1094,8 @@ llvm::Function* DtoDeclareFunction(FuncDeclaration* fdecl) } } + Logger::cout() << "func decl: " << *func << '\n'; + return func; } @@ -1163,15 +1165,13 @@ llvm::Value* DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expressio if (haslvals) gIR->exps.push_back(IRExp(NULL,NULL,NULL)); - elem* arg = argexp->toElem(gIR); + DValue* arg = argexp->toElem(gIR); if (haslvals) gIR->exps.pop_back(); - if (arg->inplace) { - assert(arg->mem != 0); - retval = arg->mem; - delete arg; + if (arg->inPlace()) { + retval = arg->getRVal(); return retval; } @@ -1179,8 +1179,13 @@ llvm::Value* DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expressio TY argty = realtype->ty; if (DtoIsPassedByRef(realtype)) { if (!fnarg || !fnarg->llvmCopy) { - retval = arg->getValue(); - assert(retval != 0); + if (DSliceValue* sv = arg->isSlice()) { + retval = new llvm::AllocaInst(DtoType(realtype), "tmpparam", gIR->topallocapoint()); + DtoSetArray(retval, DtoArrayLen(sv), DtoArrayPtr(sv)); + } + else { + retval = arg->getRVal(); + } } else { llvm::Value* allocaInst = 0; @@ -1190,54 +1195,61 @@ llvm::Value* DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expressio const llvm::PointerType* pty = llvm::PointerType::get(realtypell); if (argty == Tstruct) { allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint()); - DtoStructCopy(allocaInst,arg->mem); + DValue* dst = new DVarValue(realtype, allocaInst, true); + DtoAssign(dst,arg); + delete dst; } else if (argty == Tdelegate) { allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint()); - DtoDelegateCopy(allocaInst,arg->mem); + DValue* dst = new DVarValue(realtype, allocaInst, true); + DtoAssign(dst,arg); + delete dst; } else if (argty == Tarray) { - if (arg->type == elem::SLICE) { + if (arg->isSlice()) { allocaInst = new llvm::AllocaInst(realtypell, "tmpparam", gIR->topallocapoint()); - DtoSetArray(allocaInst, arg->arg, arg->mem); - } - else if (arg->temp) { - allocaInst = arg->mem; } else { allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint()); - DtoArrayAssign(allocaInst,arg->mem); } } else assert(0); + DValue* dst = new DVarValue(realtype, allocaInst, true); + DtoAssign(dst,arg); + delete dst; + retval = allocaInst; } } else if (!fnarg || fnarg->llvmCopy) { Logger::println("regular arg"); - assert(arg->type != elem::SLICE); - if (arg->mem) Logger::cout() << "mem = " << *arg->mem << '\n'; - if (arg->val) Logger::cout() << "val = " << *arg->val << '\n'; - if (arg->arg) Logger::cout() << "arg = " << *arg->arg << '\n'; - retval = arg->arg ? arg->arg : arg->field ? arg->mem : arg->getValue(); + if (DSliceValue* sl = arg->isSlice()) { + if (sl->ptr) Logger::cout() << "ptr = " << *sl->ptr << '\n'; + if (sl->len) Logger::cout() << "len = " << *sl->len << '\n'; + assert(0); + } + else { + retval = arg->getRVal(); + } } else { Logger::println("as ptr arg"); - retval = arg->mem ? arg->mem : arg->val; + retval = arg->getLVal(); if (paramtype && retval->getType() != paramtype) { - assert(retval->getType() == paramtype->getContainedType(0)); - new llvm::StoreInst(retval, arg->mem, gIR->scopebb()); - retval = arg->mem; + assert(0); + /*assert(retval->getType() == paramtype->getContainedType(0)); + new llvm::StoreInst(retval, arg->getLVal(), gIR->scopebb()); + retval = arg->getLVal();*/ } } if (fnarg && paramtype && retval->getType() != paramtype) { // this is unfortunately needed with the way SymOffExp is overused // and static arrays can end up being a pointer to their element type - if (arg->field) { + if (arg->isField()) { retval = gIR->ir->CreateBitCast(retval, paramtype, "tmp"); } else { @@ -1307,29 +1319,78 @@ llvm::Value* DtoNestedVariable(VarDeclaration* vd) ////////////////////////////////////////////////////////////////////////////////////////// -void DtoAssign(Type* t, llvm::Value* lhs, llvm::Value* rhs) +void DtoAssign(DValue* lhs, DValue* rhs) { - Logger::cout() << "assignment:" << '\n' << *lhs << *rhs << '\n'; + Type* t = DtoDType(lhs->getType()); + Type* t2 = DtoDType(rhs->getType()); if (t->ty == Tstruct) { - assert(lhs->getType() == rhs->getType()); - DtoStructCopy(lhs,rhs); + if (t2 != t) { + // TODO: fix this, use 'rhs' for something + DtoStructZeroInit(lhs->getLVal()); + } + else if (!rhs->inPlace()) { + DtoStructCopy(lhs->getLVal(),rhs->getRVal()); + } } else if (t->ty == Tarray) { - assert(lhs->getType() == rhs->getType()); - DtoArrayAssign(lhs,rhs); + // lhs is slice + if (DSliceValue* s = lhs->isSlice()) { + if (DSliceValue* s2 = rhs->isSlice()) { + DtoArrayCopy(s, s2); + } + else if (t->next == t2) { + if (s->len) + DtoArrayInit(s->ptr, s->len, rhs->getRVal()); + else + DtoArrayInit(s->ptr, rhs->getRVal()); + } + else + assert(rhs->inPlace()); + } + // rhs is slice + else if (DSliceValue* s = rhs->isSlice()) { + DtoSetArray(lhs->getLVal(),s->len,s->ptr); + } + // null + else if (rhs->isNull()) { + DtoNullArray(lhs->getLVal()); + } + // reference assignment + else { + DtoArrayAssign(lhs->getLVal(), rhs->getRVal()); + } } else if (t->ty == Tsarray) { - assert(lhs->getType() == rhs->getType()); - DtoStaticArrayCopy(lhs,rhs); + DtoStaticArrayCopy(lhs->getLVal(), rhs->getRVal()); } else if (t->ty == Tdelegate) { - assert(lhs->getType() == rhs->getType()); - DtoDelegateCopy(lhs,rhs); + if (rhs->isNull()) + DtoNullDelegate(lhs->getLVal()); + else if (!rhs->inPlace()) + DtoDelegateCopy(lhs->getLVal(), rhs->getRVal()); + } + else if (t->ty == Tclass) { + assert(t2->ty == Tclass); + // assignment to this in constructor special case + if (lhs->isThis()) { + llvm::Value* tmp = rhs->getRVal(); + FuncDeclaration* fdecl = gIR->func().decl; + // respecify the this param + if (!llvm::isa(fdecl->llvmThisVar)) + fdecl->llvmThisVar = new llvm::AllocaInst(tmp->getType(), "newthis", gIR->topallocapoint()); + DtoStore(tmp, fdecl->llvmThisVar); + } + // regular class ref -> class ref assignment + else { + DtoStore(rhs->getRVal(), lhs->getLVal()); + } } else { - assert(lhs->getType()->getContainedType(0) == rhs->getType()); - gIR->ir->CreateStore(rhs, lhs); + llvm::Value* r = rhs->getRVal(); + llvm::Value* l = lhs->getLVal(); + Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n'; + gIR->ir->CreateStore(r, l); } } @@ -1409,6 +1470,31 @@ void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes) ////////////////////////////////////////////////////////////////////////////////////////// +llvm::Value* DtoLoad(llvm::Value* src) +{ + return gIR->ir->CreateLoad(src,"tmp"); +} + +void DtoStore(llvm::Value* src, llvm::Value* dst) +{ + gIR->ir->CreateStore(src,dst); +} + +bool DtoCanLoad(llvm::Value* ptr) +{ + if (llvm::isa(ptr->getType())) { + return ptr->getType()->getContainedType(0)->isFirstClassType(); + } + return false; +} + +llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t) +{ + return gIR->ir->CreateBitCast(v, t, "tmp"); +} + +////////////////////////////////////////////////////////////////////////////////////////// + llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector& idxs) { Logger::println("checking for offset %u type %s:", os, t->toChars()); @@ -1470,7 +1556,7 @@ llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, un bool DtoIsTemplateInstance(Dsymbol* s) { - assert(s); + if (!s) return false; if (s->isTemplateInstance() && !s->isTemplateMixin()) return true; else if (s->parent) diff --git a/gen/tollvm.h b/gen/tollvm.h index 353818a1..c7233ade 100644 --- a/gen/tollvm.h +++ b/gen/tollvm.h @@ -1,6 +1,10 @@ +#ifndef LLVMDC_GEN_TOLLVM_H +#define LLVMDC_GEN_TOLLVM_H + // D -> LLVM helpers struct StructInitializer; +struct DValue; const llvm::Type* DtoType(Type* t); bool DtoIsPassedByRef(Type* type); @@ -55,8 +59,6 @@ llvm::Value* DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expressio llvm::Value* DtoNestedVariable(VarDeclaration* vd); -void DtoAssign(Type* lhsType, llvm::Value* lhs, llvm::Value* rhs); - llvm::ConstantInt* DtoConstSize_t(size_t); llvm::ConstantInt* DtoConstUint(unsigned i); llvm::ConstantInt* DtoConstInt(int i); @@ -64,10 +66,27 @@ llvm::Constant* DtoConstString(const char*); llvm::Constant* DtoConstStringPtr(const char* str, const char* section = 0); llvm::Constant* DtoConstBool(bool); -void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes); - llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector& idxs); bool DtoIsTemplateInstance(Dsymbol* s); +// llvm wrappers +void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes); +bool DtoCanLoad(llvm::Value* ptr); +llvm::Value* DtoLoad(llvm::Value* src); +void DtoStore(llvm::Value* src, llvm::Value* dst); +llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t); + +// basic operations +void DtoAssign(DValue* lhs, DValue* rhs); + +// binary operations +DValue* DtoBinAdd(DValue* lhs, DValue* rhs); +DValue* DtoBinSub(DValue* lhs, DValue* rhs); +DValue* DtoBinMul(DValue* lhs, DValue* rhs); +DValue* DtoBinDiv(DValue* lhs, DValue* rhs); +DValue* DtoBinRem(DValue* lhs, DValue* rhs); + #include "enums.h" + +#endif // LLVMDC_GEN_TOLLVM_H diff --git a/gen/toobj.c b/gen/toobj.cpp similarity index 95% rename from gen/toobj.c rename to gen/toobj.cpp index cf043a8b..1d6b96d1 100644 --- a/gen/toobj.c +++ b/gen/toobj.cpp @@ -37,6 +37,7 @@ #include "gen/tollvm.h" #include "gen/arrays.h" #include "gen/todebug.h" +#include "gen/runtime.h" ////////////////////////////////////////////////////////////////////////////////////////// @@ -628,8 +629,11 @@ void VarDeclaration::toObjFile() gIR->ir->CreateCondBr(cond, initbb, endinitbb); gIR->scope() = IRScope(initbb,endinitbb); elem* ie = DtoInitializer(init); - if (!ie->inplace) - DtoAssign(t, gvar, ie->getValue()); + if (!ie->inPlace()) { + DValue* dst = new DVarValue(t, gvar, true); + DtoAssign(dst, ie); + delete dst; + } gIR->ir->CreateStore(DtoConstBool(true), gflag); gIR->ir->CreateBr(endinitbb); gIR->scope() = IRScope(endinitbb,oldend); @@ -754,6 +758,13 @@ void FuncDeclaration::toObjFile() return; } + if (llvmRunTimeHack) { + Logger::println("runtime hack func chars: %s", toChars()); + if (!llvmValue) + llvmValue = LLVM_D_GetRuntimeFunction(gIR->module, toChars()); + return; + } + if (isUnitTestDeclaration()) { Logger::println("*** ATTENTION: ignoring unittest declaration: %s", toChars()); return; @@ -763,6 +774,8 @@ void FuncDeclaration::toObjFile() TypeFunction* f = (TypeFunction*)t; bool declareOnly = false; + if (parent) + { if (TemplateInstance* tinst = parent->isTemplateInstance()) { TemplateDeclaration* tempdecl = tinst->tempdecl; if (tempdecl->llvmInternal == LLVMva_start) @@ -778,6 +791,7 @@ void FuncDeclaration::toObjFile() return; } } + } llvm::Function* func = DtoDeclareFunction(this); @@ -802,8 +816,7 @@ void FuncDeclaration::toObjFile() const llvm::FunctionType* functype = llvm::cast(llvmValue->getType()->getContainedType(0)); // template instances should have weak linkage - assert(parent); - if (DtoIsTemplateInstance(parent)) { + if (parent && DtoIsTemplateInstance(parent)) { func->setLinkage(llvm::GlobalValue::WeakLinkage); } diff --git a/gen/typinf.c b/gen/typinf.cpp similarity index 100% rename from gen/typinf.c rename to gen/typinf.cpp diff --git a/lphobos/build.sh b/lphobos/build.sh index 0b38812c..dd41a418 100755 --- a/lphobos/build.sh +++ b/lphobos/build.sh @@ -12,7 +12,7 @@ echo "compiling common runtime" rebuild internal/arrays.d \ internal/mem.d \ internal/moduleinit.d \ - -c -oqobj -dc=llvmdc-posix || exit 1 + -c -oqobj -dc=llvmdc-posix -explicit || exit 1 echo "compiling module init backend" llvm-as -f -o=obj/moduleinit_backend.bc internal/moduleinit_backend.ll || exit 1 @@ -30,18 +30,21 @@ echo "compiling typeinfo 2" rebuild typeinfos2.d -c -oqobj -dc=llvmdc-posix || exit 1 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/typeinfo2.*.bc` ../lib/llvmdcore.bc || exit 1 +echo "compiling string foreach runtime support" +llvmdc internal/aApply.d -c -odobj || exit 1 +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 llvm runtime support" rebuild llvmsupport.d -c -oqobj -dc=llvmdc-posix || exit llvm-link -f -o=../lib/llvmdcore.bc `ls obj/llvm.*.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 + echo "optimizing" opt -f -std-compile-opts -o=../lib/llvmdcore.bc ../lib/llvmdcore.bc || exit 1 -# build phobos -echo "compiling phobos" -rebuild phobos.d -c -oqobj -dc=llvmdc-posix || exit 1 -llvm-link -f -o=../lib/lphobos.bc `ls obj/std.*.bc` || exit 1 -opt -f -std-compile-opts -o=../lib/lphobos.bc ../lib/lphobos.bc || exit 1 echo "SUCCESS" diff --git a/lphobos/internal/aApply.d b/lphobos/internal/aApply.d new file mode 100644 index 00000000..019b4781 --- /dev/null +++ b/lphobos/internal/aApply.d @@ -0,0 +1,410 @@ + +/** + * Part of the D programming language runtime library. + */ + +/* + * Copyright (C) 2004-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. + */ + +/* This code handles decoding UTF strings for foreach loops. + * There are 6 combinations of conversions between char, wchar, + * and dchar, and 2 of each of those. + */ + +import std.utf; + +//debug=apply; + +/********************************************** + */ + +// dg is D, but _aApplycd() is C +extern (D) typedef int delegate(void *) dg_t; + +extern (C) int _aApplycd1(char[] aa, dg_t dg) +{ int result; + size_t i; + size_t len = aa.length; + + debug(apply) printf("_aApplycd1(), len = %d\n", len); + for (i = 0; i < len; ) + { dchar d; + + d = aa[i]; + if (d & 0x80) + d = std.utf.decode(aa, i); + else + i++; + result = dg(cast(void *)&d); + if (result) + break; + } + return result; +} + +extern (C) int _aApplywd1(wchar[] aa, dg_t dg) +{ int result; + size_t i; + size_t len = aa.length; + + debug(apply) printf("_aApplywd1(), len = %d\n", len); + for (i = 0; i < len; ) + { dchar d; + + d = aa[i]; + if (d & ~0x7F) + d = std.utf.decode(aa, i); + else + i++; + result = dg(cast(void *)&d); + if (result) + break; + } + return result; +} + +extern (C) int _aApplycw1(char[] aa, dg_t dg) +{ int result; + size_t i; + size_t len = aa.length; + + debug(apply) printf("_aApplycw1(), len = %d\n", len); + for (i = 0; i < len; ) + { dchar d; + wchar w; + + w = aa[i]; + if (w & 0x80) + { d = std.utf.decode(aa, i); + if (d <= 0xFFFF) + w = cast(wchar) d; + else + { + w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); + result = dg(cast(void *)&w); + if (result) + break; + w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00); + } + } + else + i++; + result = dg(cast(void *)&w); + if (result) + break; + } + return result; +} + +extern (C) int _aApplywc1(wchar[] aa, dg_t dg) +{ int result; + size_t i; + size_t len = aa.length; + + debug(apply) printf("_aApplywc1(), len = %d\n", len); + for (i = 0; i < len; ) + { dchar d; + wchar w; + char c; + + w = aa[i]; + if (w & ~0x7F) + { + char[4] buf; + char[] b; + + d = std.utf.decode(aa, i); + b = std.utf.toUTF8(buf, d); + foreach (char c2; b) + { + result = dg(cast(void *)&c2); + if (result) + return result; + } + continue; + } + else + { c = cast(char)w; + i++; + } + result = dg(cast(void *)&c); + if (result) + break; + } + return result; +} + +extern (C) int _aApplydc1(dchar[] aa, dg_t dg) +{ int result; + + debug(apply) printf("_aApplydc1(), len = %d\n", aa.length); + foreach (dchar d; aa) + { + char c; + + if (d & ~0x7F) + { + char[4] buf; + char[] b; + + b = std.utf.toUTF8(buf, d); + foreach (char c2; b) + { + result = dg(cast(void *)&c2); + if (result) + return result; + } + continue; + } + else + { + c = cast(char)d; + } + result = dg(cast(void *)&c); + if (result) + break; + } + return result; +} + +extern (C) int _aApplydw1(dchar[] aa, dg_t dg) +{ int result; + + debug(apply) printf("_aApplydw1(), len = %d\n", aa.length); + foreach (dchar d; aa) + { + wchar w; + + if (d <= 0xFFFF) + w = cast(wchar) d; + else + { + w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); + result = dg(cast(void *)&w); + if (result) + break; + w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00); + } + result = dg(cast(void *)&w); + if (result) + break; + } + return result; +} + + +/****************************************************************************/ + +// dg is D, but _aApplycd2() is C +extern (D) typedef int delegate(void *, void *) dg2_t; + +extern (C) int _aApplycd2(char[] aa, dg2_t dg) +{ int result; + size_t i; + size_t n; + size_t len = aa.length; + + debug(apply) printf("_aApplycd2(), len = %d\n", len); + for (i = 0; i < len; i += n) + { dchar d; + + d = aa[i]; + if (d & 0x80) + { + n = i; + d = std.utf.decode(aa, n); + n -= i; + } + else + n = 1; + result = dg(&i, cast(void *)&d); + if (result) + break; + } + return result; +} + +extern (C) int _aApplywd2(wchar[] aa, dg2_t dg) +{ int result; + size_t i; + size_t n; + size_t len = aa.length; + + debug(apply) printf("_aApplywd2(), len = %d\n", len); + for (i = 0; i < len; i += n) + { dchar d; + + d = aa[i]; + if (d & ~0x7F) + { + n = i; + d = std.utf.decode(aa, n); + n -= i; + } + else + n = 1; + result = dg(&i, cast(void *)&d); + if (result) + break; + } + return result; +} + +extern (C) int _aApplycw2(char[] aa, dg2_t dg) +{ int result; + size_t i; + size_t n; + size_t len = aa.length; + + debug(apply) printf("_aApplycw2(), len = %d\n", len); + for (i = 0; i < len; i += n) + { dchar d; + wchar w; + + w = aa[i]; + if (w & 0x80) + { n = i; + d = std.utf.decode(aa, n); + n -= i; + if (d <= 0xFFFF) + w = cast(wchar) d; + else + { + w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); + result = dg(&i, cast(void *)&w); + if (result) + break; + w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); + } + } + else + n = 1; + result = dg(&i, cast(void *)&w); + if (result) + break; + } + return result; +} + +extern (C) int _aApplywc2(wchar[] aa, dg2_t dg) +{ int result; + size_t i; + size_t n; + size_t len = aa.length; + + debug(apply) printf("_aApplywc2(), len = %d\n", len); + for (i = 0; i < len; i += n) + { dchar d; + wchar w; + char c; + + w = aa[i]; + if (w & ~0x7F) + { + char[4] buf; + char[] b; + + n = i; + d = std.utf.decode(aa, n); + n -= i; + b = std.utf.toUTF8(buf, d); + foreach (char c2; b) + { + result = dg(&i, cast(void *)&c2); + if (result) + return result; + } + continue; + } + else + { c = cast(char)w; + n = 1; + } + result = dg(&i, cast(void *)&c); + if (result) + break; + } + return result; +} + +extern (C) int _aApplydc2(dchar[] aa, dg2_t dg) +{ int result; + size_t i; + size_t len = aa.length; + + debug(apply) printf("_aApplydc2(), len = %d\n", len); + for (i = 0; i < len; i++) + { dchar d; + char c; + + d = aa[i]; + if (d & ~0x7F) + { + char[4] buf; + char[] b; + + b = std.utf.toUTF8(buf, d); + foreach (char c2; b) + { + result = dg(&i, cast(void *)&c2); + if (result) + return result; + } + continue; + } + else + { c = cast(char)d; + } + result = dg(&i, cast(void *)&c); + if (result) + break; + } + return result; +} + +extern (C) int _aApplydw2(dchar[] aa, dg2_t dg) +{ int result; + + debug(apply) printf("_aApplydw2(), len = %d\n", aa.length); + foreach (size_t i, dchar d; aa) + { + wchar w; + + if (d <= 0xFFFF) + w = cast(wchar) d; + else + { + w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); + result = dg(&i, cast(void *)&w); + if (result) + break; + w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); + } + result = dg(&i, cast(void *)&w); + if (result) + break; + } + return result; +} + + diff --git a/lphobos/internal/aApplyR.d b/lphobos/internal/aApplyR.d new file mode 100644 index 00000000..c419ab84 --- /dev/null +++ b/lphobos/internal/aApplyR.d @@ -0,0 +1,977 @@ + +/** + * Part of the D programming language runtime library. + */ + +/* + * Copyright (C) 2004-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. + */ + +/* This code handles decoding UTF strings for foreach_reverse loops. + * There are 6 combinations of conversions between char, wchar, + * and dchar, and 2 of each of those. + */ + +import std.utf; + +//debug=apply; + +/**********************************************/ +/* 1 argument versions */ + +// dg is D, but _aApplyRcd() is C +extern (D) typedef int delegate(void *) dg_t; + +extern (C) int _aApplyRcd1(char[] aa, dg_t dg) +{ int result; + + debug(apply) printf("_aApplyRcd1(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d; + + i--; + d = aa[i]; + if (d & 0x80) + { char c = cast(char)d; + uint j; + uint m = 0x3F; + d = 0; + while ((c & 0xC0) != 0xC0) + { if (i == 0) + throw new std.utf.UtfException("Invalid UTF-8 sequence", 0); + i--; + d |= (c & 0x3F) << j; + j += 6; + m >>= 1; + c = aa[i]; + } + d |= (c & m) << j; + } + result = dg(cast(void *)&d); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRcd1.unittest\n"); + + char[] s = "hello"; + int i; + + foreach_reverse(dchar d; s) + { + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + default: assert(0); + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(dchar d; s) + { + //printf("i = %d, d = %x\n", i, d); + switch (i) + { + case 0: assert(d == 'b'); break; + case 1: assert(d == '\U00100456'); break; + case 2: assert(d == '\u1234'); break; + case 3: assert(d == 'a'); break; + default: assert(0); + } + i++; + } + assert(i == 4); +} + +/*****************************/ + +extern (C) int _aApplyRwd1(wchar[] aa, dg_t dg) +{ int result; + + debug(apply) printf("_aApplyRwd1(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d; + + i--; + d = aa[i]; + if (d >= 0xDC00 && d <= 0xDFFF) + { if (i == 0) + throw new std.utf.UtfException("Invalid UTF-16 sequence", 0); + i--; + d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00); + } + result = dg(cast(void *)&d); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRwd1.unittest\n"); + + wchar[] s = "hello"; + int i; + + foreach_reverse(dchar d; s) + { + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + default: assert(0); + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(dchar d; s) + { + //printf("i = %d, d = %x\n", i, d); + switch (i) + { + case 0: assert(d == 'b'); break; + case 1: assert(d == '\U00100456'); break; + case 2: assert(d == '\u1234'); break; + case 3: assert(d == 'a'); break; + default: assert(0); + } + i++; + } + assert(i == 4); +} + +/*****************************/ + +extern (C) int _aApplyRcw1(char[] aa, dg_t dg) +{ int result; + + debug(apply) printf("_aApplyRcw1(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d; + wchar w; + + i--; + w = aa[i]; + if (w & 0x80) + { char c = cast(char)w; + uint j; + uint m = 0x3F; + d = 0; + while ((c & 0xC0) != 0xC0) + { if (i == 0) + throw new std.utf.UtfException("Invalid UTF-8 sequence", 0); + i--; + d |= (c & 0x3F) << j; + j += 6; + m >>= 1; + c = aa[i]; + } + d |= (c & m) << j; + + if (d <= 0xFFFF) + w = cast(wchar) d; + else + { + w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); + result = dg(cast(void *)&w); + if (result) + break; + w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); + } + } + result = dg(cast(void *)&w); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRcw1.unittest\n"); + + char[] s = "hello"; + int i; + + foreach_reverse(wchar d; s) + { + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + default: assert(0); + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(wchar d; s) + { + //printf("i = %d, d = %x\n", i, d); + switch (i) + { + case 0: assert(d == 'b'); break; + case 1: assert(d == 0xDBC1); break; + case 2: assert(d == 0xDC56); break; + case 3: assert(d == 0x1234); break; + case 4: assert(d == 'a'); break; + default: assert(0); + } + i++; + } + assert(i == 5); +} + +/*****************************/ + +extern (C) int _aApplyRwc1(wchar[] aa, dg_t dg) +{ int result; + + debug(apply) printf("_aApplyRwc1(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d; + char c; + + i--; + d = aa[i]; + if (d >= 0xDC00 && d <= 0xDFFF) + { if (i == 0) + throw new std.utf.UtfException("Invalid UTF-16 sequence", 0); + i--; + d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00); + } + + if (d & ~0x7F) + { + char[4] buf; + char[] b; + + b = std.utf.toUTF8(buf, d); + foreach (char c2; b) + { + result = dg(cast(void *)&c2); + if (result) + return result; + } + continue; + } + c = cast(char)d; + result = dg(cast(void *)&c); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRwc1.unittest\n"); + + wchar[] s = "hello"; + int i; + + foreach_reverse(char d; s) + { + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + default: assert(0); + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(char d; s) + { + //printf("i = %d, d = %x\n", i, d); + switch (i) + { + case 0: assert(d == 'b'); break; + case 1: assert(d == 0xF4); break; + case 2: assert(d == 0x80); break; + case 3: assert(d == 0x91); break; + case 4: assert(d == 0x96); break; + case 5: assert(d == 0xE1); break; + case 6: assert(d == 0x88); break; + case 7: assert(d == 0xB4); break; + case 8: assert(d == 'a'); break; + default: assert(0); + } + i++; + } + assert(i == 9); +} + +/*****************************/ + +extern (C) int _aApplyRdc1(dchar[] aa, dg_t dg) +{ int result; + + debug(apply) printf("_aApplyRdc1(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0;) + { dchar d = aa[--i]; + char c; + + if (d & ~0x7F) + { + char[4] buf; + char[] b; + + b = std.utf.toUTF8(buf, d); + foreach (char c2; b) + { + result = dg(cast(void *)&c2); + if (result) + return result; + } + continue; + } + else + { + c = cast(char)d; + } + result = dg(cast(void *)&c); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRdc1.unittest\n"); + + dchar[] s = "hello"; + int i; + + foreach_reverse(char d; s) + { + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + default: assert(0); + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(char d; s) + { + //printf("i = %d, d = %x\n", i, d); + switch (i) + { + case 0: assert(d == 'b'); break; + case 1: assert(d == 0xF4); break; + case 2: assert(d == 0x80); break; + case 3: assert(d == 0x91); break; + case 4: assert(d == 0x96); break; + case 5: assert(d == 0xE1); break; + case 6: assert(d == 0x88); break; + case 7: assert(d == 0xB4); break; + case 8: assert(d == 'a'); break; + default: assert(0); + } + i++; + } + assert(i == 9); +} + +/*****************************/ + +extern (C) int _aApplyRdw1(dchar[] aa, dg_t dg) +{ int result; + + debug(apply) printf("_aApplyRdw1(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d = aa[--i]; + wchar w; + + if (d <= 0xFFFF) + w = cast(wchar) d; + else + { + w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); + result = dg(cast(void *)&w); + if (result) + break; + w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); + } + result = dg(cast(void *)&w); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRdw1.unittest\n"); + + dchar[] s = "hello"; + int i; + + foreach_reverse(wchar d; s) + { + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + default: assert(0); + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(wchar d; s) + { + //printf("i = %d, d = %x\n", i, d); + switch (i) + { + case 0: assert(d == 'b'); break; + case 1: assert(d == 0xDBC1); break; + case 2: assert(d == 0xDC56); break; + case 3: assert(d == 0x1234); break; + case 4: assert(d == 'a'); break; + default: assert(0); + } + i++; + } + assert(i == 5); +} + + +/****************************************************************************/ +/* 2 argument versions */ + +// dg is D, but _aApplyRcd2() is C +extern (D) typedef int delegate(void *, void *) dg2_t; + +extern (C) int _aApplyRcd2(char[] aa, dg2_t dg) +{ int result; + size_t i; + size_t len = aa.length; + + debug(apply) printf("_aApplyRcd2(), len = %d\n", len); + for (i = len; i != 0; ) + { dchar d; + + i--; + d = aa[i]; + if (d & 0x80) + { char c = cast(char)d; + uint j; + uint m = 0x3F; + d = 0; + while ((c & 0xC0) != 0xC0) + { if (i == 0) + throw new std.utf.UtfException("Invalid UTF-8 sequence", 0); + i--; + d |= (c & 0x3F) << j; + j += 6; + m >>= 1; + c = aa[i]; + } + d |= (c & m) << j; + } + result = dg(&i, cast(void *)&d); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRcd2.unittest\n"); + + char[] s = "hello"; + int i; + + foreach_reverse(k, dchar d; s) + { + assert(k == 4 - i); + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + default: assert(0); + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(k, dchar d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + switch (i) + { + case 0: assert(d == 'b'); assert(k == 8); break; + case 1: assert(d == '\U00100456'); assert(k == 4); break; + case 2: assert(d == '\u1234'); assert(k == 1); break; + case 3: assert(d == 'a'); assert(k == 0); break; + default: assert(0); + } + i++; + } + assert(i == 4); +} + +/*****************************/ + +extern (C) int _aApplyRwd2(wchar[] aa, dg2_t dg) +{ int result; + + debug(apply) printf("_aApplyRwd2(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d; + + i--; + d = aa[i]; + if (d >= 0xDC00 && d <= 0xDFFF) + { if (i == 0) + throw new std.utf.UtfException("Invalid UTF-16 sequence", 0); + i--; + d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00); + } + result = dg(&i, cast(void *)&d); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRwd2.unittest\n"); + + wchar[] s = "hello"; + int i; + + foreach_reverse(k, dchar d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + assert(k == 4 - i); + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + default: assert(0); + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(k, dchar d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + switch (i) + { + case 0: assert(k == 4); assert(d == 'b'); break; + case 1: assert(k == 2); assert(d == '\U00100456'); break; + case 2: assert(k == 1); assert(d == '\u1234'); break; + case 3: assert(k == 0); assert(d == 'a'); break; + default: assert(0); + } + i++; + } + assert(i == 4); +} + +/*****************************/ + +extern (C) int _aApplyRcw2(char[] aa, dg2_t dg) +{ int result; + + debug(apply) printf("_aApplyRcw2(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d; + wchar w; + + i--; + w = aa[i]; + if (w & 0x80) + { char c = cast(char)w; + uint j; + uint m = 0x3F; + d = 0; + while ((c & 0xC0) != 0xC0) + { if (i == 0) + throw new std.utf.UtfException("Invalid UTF-8 sequence", 0); + i--; + d |= (c & 0x3F) << j; + j += 6; + m >>= 1; + c = aa[i]; + } + d |= (c & m) << j; + + if (d <= 0xFFFF) + w = cast(wchar) d; + else + { + w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); + result = dg(&i, cast(void *)&w); + if (result) + break; + w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); + } + } + result = dg(&i, cast(void *)&w); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRcw2.unittest\n"); + + char[] s = "hello"; + int i; + + foreach_reverse(k, wchar d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + assert(k == 4 - i); + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + default: assert(0); + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(k, wchar d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + switch (i) + { + case 0: assert(k == 8); assert(d == 'b'); break; + case 1: assert(k == 4); assert(d == 0xDBC1); break; + case 2: assert(k == 4); assert(d == 0xDC56); break; + case 3: assert(k == 1); assert(d == 0x1234); break; + case 4: assert(k == 0); assert(d == 'a'); break; + default: assert(0); + } + i++; + } + assert(i == 5); +} + +/*****************************/ + +extern (C) int _aApplyRwc2(wchar[] aa, dg2_t dg) +{ int result; + + debug(apply) printf("_aApplyRwc2(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d; + char c; + + i--; + d = aa[i]; + if (d >= 0xDC00 && d <= 0xDFFF) + { if (i == 0) + throw new std.utf.UtfException("Invalid UTF-16 sequence", 0); + i--; + d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00); + } + + if (d & ~0x7F) + { + char[4] buf; + char[] b; + + b = std.utf.toUTF8(buf, d); + foreach (char c2; b) + { + result = dg(&i, cast(void *)&c2); + if (result) + return result; + } + continue; + } + c = cast(char)d; + result = dg(&i, cast(void *)&c); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRwc2.unittest\n"); + + wchar[] s = "hello"; + int i; + + foreach_reverse(k, char d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + assert(k == 4 - i); + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + default: assert(0); + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(k, char d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + switch (i) + { + case 0: assert(k == 4); assert(d == 'b'); break; + case 1: assert(k == 2); assert(d == 0xF4); break; + case 2: assert(k == 2); assert(d == 0x80); break; + case 3: assert(k == 2); assert(d == 0x91); break; + case 4: assert(k == 2); assert(d == 0x96); break; + case 5: assert(k == 1); assert(d == 0xE1); break; + case 6: assert(k == 1); assert(d == 0x88); break; + case 7: assert(k == 1); assert(d == 0xB4); break; + case 8: assert(k == 0); assert(d == 'a'); break; + default: assert(0); + } + i++; + } + assert(i == 9); +} + +/*****************************/ + +extern (C) int _aApplyRdc2(dchar[] aa, dg2_t dg) +{ int result; + + debug(apply) printf("_aApplyRdc2(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d = aa[--i]; + char c; + + if (d & ~0x7F) + { + char[4] buf; + char[] b; + + b = std.utf.toUTF8(buf, d); + foreach (char c2; b) + { + result = dg(&i, cast(void *)&c2); + if (result) + return result; + } + continue; + } + else + { c = cast(char)d; + } + result = dg(&i, cast(void *)&c); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRdc2.unittest\n"); + + dchar[] s = "hello"; + int i; + + foreach_reverse(k, char d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + assert(k == 4 - i); + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + default: assert(0); + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(k, char d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + switch (i) + { + case 0: assert(k == 3); assert(d == 'b'); break; + case 1: assert(k == 2); assert(d == 0xF4); break; + case 2: assert(k == 2); assert(d == 0x80); break; + case 3: assert(k == 2); assert(d == 0x91); break; + case 4: assert(k == 2); assert(d == 0x96); break; + case 5: assert(k == 1); assert(d == 0xE1); break; + case 6: assert(k == 1); assert(d == 0x88); break; + case 7: assert(k == 1); assert(d == 0xB4); break; + case 8: assert(k == 0); assert(d == 'a'); break; + default: assert(0); + } + i++; + } + assert(i == 9); +} + +/*****************************/ + +extern (C) int _aApplyRdw2(dchar[] aa, dg2_t dg) +{ int result; + + debug(apply) printf("_aApplyRdw2(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d = aa[--i]; + wchar w; + + if (d <= 0xFFFF) + w = cast(wchar) d; + else + { + w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800); + result = dg(&i, cast(void *)&w); + if (result) + break; + w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00); + } + result = dg(&i, cast(void *)&w); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRdw2.unittest\n"); + + dchar[] s = "hello"; + int i; + + foreach_reverse(k, wchar d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + assert(k == 4 - i); + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + default: assert(0); + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(k, wchar d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + switch (i) + { + case 0: assert(k == 3); assert(d == 'b'); break; + case 1: assert(k == 2); assert(d == 0xDBC1); break; + case 2: assert(k == 2); assert(d == 0xDC56); break; + case 3: assert(k == 1); assert(d == 0x1234); break; + case 4: assert(k == 0); assert(d == 'a'); break; + default: assert(0); + } + i++; + } + assert(i == 5); +} + + diff --git a/lphobos/internal/objectimpl.d b/lphobos/internal/objectimpl.d index f63b23ab..b0f762d9 100644 --- a/lphobos/internal/objectimpl.d +++ b/lphobos/internal/objectimpl.d @@ -1135,6 +1135,12 @@ class Exception : Object this.msg = msg; } + void print() + { + char[] s = toString(); + printf("%.*s\n", s.length, s.ptr); + } + char[] toString() { return msg; } } diff --git a/lphobos/phobos.d b/lphobos/phobos.d index 2767647e..7dfd2dda 100644 --- a/lphobos/phobos.d +++ b/lphobos/phobos.d @@ -1,5 +1,9 @@ module phobos; import +std.array, +std.ctype, std.stdio, -std.stdarg; +std.stdarg, +std.uni, +std.utf; \ No newline at end of file diff --git a/lphobos/std/array.d b/lphobos/std/array.d new file mode 100644 index 00000000..c3af5e44 --- /dev/null +++ b/lphobos/std/array.d @@ -0,0 +1,38 @@ + +module std.array; + +private import std.c.stdio; + +class ArrayBoundsError : Error +{ + private: + + uint linnum; + char[] filename; + + public: + this(char[] filename, uint linnum) + { + this.linnum = linnum; + this.filename = filename; + + char[] buffer = new char[19 + filename.length + linnum.sizeof * 3 + 1]; + int len; + len = sprintf(buffer.ptr, "ArrayBoundsError %.*s(%u)", filename, linnum); + super(buffer[0..len]); + } +} + + +/******************************************** + * Called by the compiler generated module assert function. + * Builds an ArrayBoundsError exception and throws it. + */ + +extern (C) static void _d_array_bounds(char[] filename, uint line) +{ + //printf("_d_assert(%s, %d)\n", (char *)filename, line); + ArrayBoundsError a = new ArrayBoundsError(filename, line); + //printf("assertion %p created\n", a); + throw a; +} diff --git a/lphobos/std/ctype.d b/lphobos/std/ctype.d new file mode 100644 index 00000000..6335e950 --- /dev/null +++ b/lphobos/std/ctype.d @@ -0,0 +1,154 @@ +/* + * Placed into the Public Domain. + * Digital Mars, www.digitalmars.com + * Written by Walter Bright + */ + +/** + * Simple ASCII character classification functions. + * For Unicode classification, see $(LINK2 std_uni.html, std.uni). + * References: + * $(LINK2 http://www.digitalmars.com/d/ascii-table.html, ASCII Table), + * $(LINK2 http://en.wikipedia.org/wiki/Ascii, Wikipedia) + * Macros: + * WIKI=Phobos/StdCtype + */ + +module std.ctype; + +/** + * Returns !=0 if c is a letter in the range (0..9, a..z, A..Z). + */ +int isalnum(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG) : 0; } + +/** + * Returns !=0 if c is an ascii upper or lower case letter. + */ +int isalpha(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP) : 0; } + +/** + * Returns !=0 if c is a control character. + */ +int iscntrl(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_CTL) : 0; } + +/** + * Returns !=0 if c is a digit. + */ +int isdigit(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_DIG) : 0; } + +/** + * Returns !=0 if c is lower case ascii letter. + */ +int islower(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_LC) : 0; } + +/** + * Returns !=0 if c is a punctuation character. + */ +int ispunct(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_PNC) : 0; } + +/** + * Returns !=0 if c is a space, tab, vertical tab, form feed, + * carriage return, or linefeed. + */ +int isspace(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_SPC) : 0; } + +/** + * Returns !=0 if c is an upper case ascii character. + */ +int isupper(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_UC) : 0; } + +/** + * Returns !=0 if c is a hex digit (0..9, a..f, A..F). + */ +int isxdigit(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_HEX) : 0; } + +/** + * Returns !=0 if c is a printing character except for the space character. + */ +int isgraph(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG|_PNC) : 0; } + +/** + * Returns !=0 if c is a printing character including the space character. + */ +int isprint(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG|_PNC|_BLK) : 0; } + +/** + * Returns !=0 if c is in the ascii character set, i.e. in the range 0..0x7F. + */ +int isascii(dchar c) { return c <= 0x7F; } + + +/** + * If c is an upper case ascii character, + * return the lower case equivalent, otherwise return c. + */ +dchar tolower(dchar c) + out (result) + { + assert(!isupper(result)); + } + body + { + return isupper(c) ? c + (cast(dchar)'a' - 'A') : c; + } + + +/** + * If c is a lower case ascii character, + * return the upper case equivalent, otherwise return c. + */ +dchar toupper(dchar c) + out (result) + { + assert(!islower(result)); + } + body + { + return islower(c) ? c - (cast(dchar)'a' - 'A') : c; + } + +private: + +enum +{ + _SPC = 8, + _CTL = 0x20, + _BLK = 0x40, + _HEX = 0x80, + _UC = 1, + _LC = 2, + _PNC = 0x10, + _DIG = 4, + _ALP = _UC|_LC, +} + +ubyte _ctype[128] = +[ + _CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL, + _CTL,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL,_CTL, + _CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL, + _CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL, + _SPC|_BLK,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC, + _PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC, + _DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX, + _DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX, + _PNC,_PNC,_PNC,_PNC,_PNC,_PNC, + _PNC,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC, + _UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC, + _UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC, + _UC,_UC,_UC,_PNC,_PNC,_PNC,_PNC,_PNC, + _PNC,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC, + _LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC, + _LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC, + _LC,_LC,_LC,_PNC,_PNC,_PNC,_PNC,_CTL +]; + + +unittest +{ + assert(isspace(' ')); + assert(!isspace('z')); + assert(toupper('a') == 'A'); + assert(tolower('Q') == 'q'); + assert(!isxdigit('G')); +} diff --git a/lphobos/std/uni.d b/lphobos/std/uni.d new file mode 100644 index 00000000..e4ce1e5d --- /dev/null +++ b/lphobos/std/uni.d @@ -0,0 +1,630 @@ + +// Written in the D programming language. + +/* + * Placed into the Public Domain. + * Digital Mars, www.digitalmars.com + * Written by Walter Bright + */ + +/** + * Simple Unicode character classification functions. + * For ASCII classification, see $(LINK2 std_ctype.html, std.ctype). + * Macros: + * WIKI=Phobos/StdUni + * References: + * $(LINK2 http://www.digitalmars.com/d/ascii-table.html, ASCII Table), + * $(LINK2 http://en.wikipedia.org/wiki/Unicode, Wikipedia), + * $(LINK2 http://www.unicode.org, The Unicode Consortium) + * Trademarks: + * Unicode(tm) is a trademark of Unicode, Inc. + */ + + +module std.uni; + +/** + * Returns !=0 if c is a Unicode lower case character. + */ +int isUniLower(dchar c) +{ + if (c <= 0x7F) + return (c >= 'a' && c <= 'z'); + + return isUniAlpha(c) && c == toUniLower(c); +} + +/** + * Returns !=0 if c is a Unicode upper case character. + */ +int isUniUpper(dchar c) +{ + if (c <= 0x7F) + return (c >= 'A' && c <= 'Z'); + + return isUniAlpha(c) && c == toUniUpper(c); +} + +/** + * If c is a Unicode upper case character, return the lower case + * equivalent, otherwise return c. + */ +dchar toUniLower(dchar c) +{ + if (c >= 'A' && c <= 'Z') + { + c += 32; + } + else if (c >= 0x00C0) + { + if ((c >= 0x00C0 && c <= 0x00D6) || (c >= 0x00D8 && c<=0x00DE)) + { + c += 32; + } + else if ((c >= 0x0100 && c < 0x0138) || (c > 0x0149 && c < 0x0178)) + { + if (c == 0x0130) + c = 0x0069; + else if ((c & 1) == 0) + c += 1; + } + else if (c == 0x0178) + { + c = 0x00FF; + } + else if ((c >= 0x0139 && c < 0x0149) || (c > 0x0178 && c < 0x017F)) + { + if (c & 1) + c += 1; + } + else if (c >= 0x0200 && c <= 0x0217) + { + if ((c & 1) == 0) + c += 1; + } + else if ((c >= 0x0401 && c <= 0x040C) || (c>= 0x040E && c <= 0x040F)) + { + c += 80; + } + else if (c >= 0x0410 && c <= 0x042F) + { + c += 32; + } + else if (c >= 0x0460 && c <= 0x047F) + { + if ((c & 1) == 0) + c += 1; + } + else if (c >= 0x0531 && c <= 0x0556) + { + c += 48; + } + else if (c >= 0x10A0 && c <= 0x10C5) + { + c += 48; + } + else if (c >= 0xFF21 && c <= 0xFF3A) + { + c += 32; + } + } + return c; +} + +/** + * If c is a Unicode lower case character, return the upper case + * equivalent, otherwise return c. + */ +dchar toUniUpper(dchar c) +{ + if (c >= 'a' && c <= 'z') + { + c -= 32; + } + else if (c >= 0x00E0) + { + if ((c >= 0x00E0 && c <= 0x00F6) || (c >= 0x00F8 && c <= 0x00FE)) + { + c -= 32; + } + else if (c == 0x00FF) + { + c = 0x0178; + } + else if ((c >= 0x0100 && c < 0x0138) || (c > 0x0149 && c < 0x0178)) + { + if (c == 0x0131) + c = 0x0049; + else if (c & 1) + c -= 1; + } + else if ((c >= 0x0139 && c < 0x0149) || (c > 0x0178 && c < 0x017F)) + { + if ((c & 1) == 0) + c = c-1; + } + else if (c == 0x017F) + { + c = 0x0053; + } + else if (c >= 0x0200 && c <= 0x0217) + { + if (c & 1) + c = c-1; + } + else if (c >= 0x0430 && c<= 0x044F) + { + c -= 32; + } + else if ((c >= 0x0451 && c <= 0x045C) || (c >=0x045E && c<= 0x045F)) + { + c -= 80; + } + else if (c >= 0x0460 && c <= 0x047F) + { + if (c & 1) + c -= 1; + } + else if (c >= 0x0561 && c < 0x0587) + { + c -= 48; + } + else if (c >= 0xFF41 && c <= 0xFF5A) + { + c -= 32; + } + } + return c; +} + + +/******************************* + * Return !=0 if u is a Unicode alpha character. + * (general Unicode category: Lu, Ll, Lt, Lm and Lo) + * + * Standards: Unicode 5.0.0 + */ + +int isUniAlpha(dchar u) +{ + static dchar table[][2] = + [ + [ 'A', 'Z' ], + [ 'a', 'z' ], + [ 0x00AA, 0x00AA ], + [ 0x00B5, 0x00B5 ], + [ 0x00BA, 0x00BA ], + [ 0x00C0, 0x00D6 ], + [ 0x00D8, 0x00F6 ], + [ 0x00F8, 0x02C1 ], + [ 0x02C6, 0x02D1 ], + [ 0x02E0, 0x02E4 ], + [ 0x02EE, 0x02EE ], + [ 0x037A, 0x037D ], + [ 0x0386, 0x0386 ], + [ 0x0388, 0x038A ], + [ 0x038C, 0x038C ], + [ 0x038E, 0x03A1 ], + [ 0x03A3, 0x03CE ], + [ 0x03D0, 0x03F5 ], + [ 0x03F7, 0x0481 ], + [ 0x048A, 0x0513 ], + [ 0x0531, 0x0556 ], + [ 0x0559, 0x0559 ], + [ 0x0561, 0x0587 ], + [ 0x05D0, 0x05EA ], + [ 0x05F0, 0x05F2 ], + [ 0x0621, 0x063A ], + [ 0x0640, 0x064A ], + [ 0x066E, 0x066F ], + [ 0x0671, 0x06D3 ], + [ 0x06D5, 0x06D5 ], + [ 0x06E5, 0x06E6 ], + [ 0x06EE, 0x06EF ], + [ 0x06FA, 0x06FC ], + [ 0x06FF, 0x06FF ], + [ 0x0710, 0x0710 ], + [ 0x0712, 0x072F ], + [ 0x074D, 0x076D ], + [ 0x0780, 0x07A5 ], + [ 0x07B1, 0x07B1 ], + [ 0x07CA, 0x07EA ], + [ 0x07F4, 0x07F5 ], + [ 0x07FA, 0x07FA ], + [ 0x0904, 0x0939 ], + [ 0x093D, 0x093D ], + [ 0x0950, 0x0950 ], + [ 0x0958, 0x0961 ], + [ 0x097B, 0x097F ], + [ 0x0985, 0x098C ], + [ 0x098F, 0x0990 ], + [ 0x0993, 0x09A8 ], + [ 0x09AA, 0x09B0 ], + [ 0x09B2, 0x09B2 ], + [ 0x09B6, 0x09B9 ], + [ 0x09BD, 0x09BD ], + [ 0x09CE, 0x09CE ], + [ 0x09DC, 0x09DD ], + [ 0x09DF, 0x09E1 ], + [ 0x09F0, 0x09F1 ], + [ 0x0A05, 0x0A0A ], + [ 0x0A0F, 0x0A10 ], + [ 0x0A13, 0x0A28 ], + [ 0x0A2A, 0x0A30 ], + [ 0x0A32, 0x0A33 ], + [ 0x0A35, 0x0A36 ], + [ 0x0A38, 0x0A39 ], + [ 0x0A59, 0x0A5C ], + [ 0x0A5E, 0x0A5E ], + [ 0x0A72, 0x0A74 ], + [ 0x0A85, 0x0A8D ], + [ 0x0A8F, 0x0A91 ], + [ 0x0A93, 0x0AA8 ], + [ 0x0AAA, 0x0AB0 ], + [ 0x0AB2, 0x0AB3 ], + [ 0x0AB5, 0x0AB9 ], + [ 0x0ABD, 0x0ABD ], + [ 0x0AD0, 0x0AD0 ], + [ 0x0AE0, 0x0AE1 ], + [ 0x0B05, 0x0B0C ], + [ 0x0B0F, 0x0B10 ], + [ 0x0B13, 0x0B28 ], + [ 0x0B2A, 0x0B30 ], + [ 0x0B32, 0x0B33 ], + [ 0x0B35, 0x0B39 ], + [ 0x0B3D, 0x0B3D ], + [ 0x0B5C, 0x0B5D ], + [ 0x0B5F, 0x0B61 ], + [ 0x0B71, 0x0B71 ], + [ 0x0B83, 0x0B83 ], + [ 0x0B85, 0x0B8A ], + [ 0x0B8E, 0x0B90 ], + [ 0x0B92, 0x0B95 ], + [ 0x0B99, 0x0B9A ], + [ 0x0B9C, 0x0B9C ], + [ 0x0B9E, 0x0B9F ], + [ 0x0BA3, 0x0BA4 ], + [ 0x0BA8, 0x0BAA ], + [ 0x0BAE, 0x0BB9 ], + [ 0x0C05, 0x0C0C ], + [ 0x0C0E, 0x0C10 ], + [ 0x0C12, 0x0C28 ], + [ 0x0C2A, 0x0C33 ], + [ 0x0C35, 0x0C39 ], + [ 0x0C60, 0x0C61 ], + [ 0x0C85, 0x0C8C ], + [ 0x0C8E, 0x0C90 ], + [ 0x0C92, 0x0CA8 ], + [ 0x0CAA, 0x0CB3 ], + [ 0x0CB5, 0x0CB9 ], + [ 0x0CBD, 0x0CBD ], + [ 0x0CDE, 0x0CDE ], + [ 0x0CE0, 0x0CE1 ], + [ 0x0D05, 0x0D0C ], + [ 0x0D0E, 0x0D10 ], + [ 0x0D12, 0x0D28 ], + [ 0x0D2A, 0x0D39 ], + [ 0x0D60, 0x0D61 ], + [ 0x0D85, 0x0D96 ], + [ 0x0D9A, 0x0DB1 ], + [ 0x0DB3, 0x0DBB ], + [ 0x0DBD, 0x0DBD ], + [ 0x0DC0, 0x0DC6 ], + [ 0x0E01, 0x0E30 ], + [ 0x0E32, 0x0E33 ], + [ 0x0E40, 0x0E46 ], + [ 0x0E81, 0x0E82 ], + [ 0x0E84, 0x0E84 ], + [ 0x0E87, 0x0E88 ], + [ 0x0E8A, 0x0E8A ], + [ 0x0E8D, 0x0E8D ], + [ 0x0E94, 0x0E97 ], + [ 0x0E99, 0x0E9F ], + [ 0x0EA1, 0x0EA3 ], + [ 0x0EA5, 0x0EA5 ], + [ 0x0EA7, 0x0EA7 ], + [ 0x0EAA, 0x0EAB ], + [ 0x0EAD, 0x0EB0 ], + [ 0x0EB2, 0x0EB3 ], + [ 0x0EBD, 0x0EBD ], + [ 0x0EC0, 0x0EC4 ], + [ 0x0EC6, 0x0EC6 ], + [ 0x0EDC, 0x0EDD ], + [ 0x0F00, 0x0F00 ], + [ 0x0F40, 0x0F47 ], + [ 0x0F49, 0x0F6A ], + [ 0x0F88, 0x0F8B ], + [ 0x1000, 0x1021 ], + [ 0x1023, 0x1027 ], + [ 0x1029, 0x102A ], + [ 0x1050, 0x1055 ], + [ 0x10A0, 0x10C5 ], + [ 0x10D0, 0x10FA ], + [ 0x10FC, 0x10FC ], + [ 0x1100, 0x1159 ], + [ 0x115F, 0x11A2 ], + [ 0x11A8, 0x11F9 ], + [ 0x1200, 0x1248 ], + [ 0x124A, 0x124D ], + [ 0x1250, 0x1256 ], + [ 0x1258, 0x1258 ], + [ 0x125A, 0x125D ], + [ 0x1260, 0x1288 ], + [ 0x128A, 0x128D ], + [ 0x1290, 0x12B0 ], + [ 0x12B2, 0x12B5 ], + [ 0x12B8, 0x12BE ], + [ 0x12C0, 0x12C0 ], + [ 0x12C2, 0x12C5 ], + [ 0x12C8, 0x12D6 ], + [ 0x12D8, 0x1310 ], + [ 0x1312, 0x1315 ], + [ 0x1318, 0x135A ], + [ 0x1380, 0x138F ], + [ 0x13A0, 0x13F4 ], + [ 0x1401, 0x166C ], + [ 0x166F, 0x1676 ], + [ 0x1681, 0x169A ], + [ 0x16A0, 0x16EA ], + [ 0x1700, 0x170C ], + [ 0x170E, 0x1711 ], + [ 0x1720, 0x1731 ], + [ 0x1740, 0x1751 ], + [ 0x1760, 0x176C ], + [ 0x176E, 0x1770 ], + [ 0x1780, 0x17B3 ], + [ 0x17D7, 0x17D7 ], + [ 0x17DC, 0x17DC ], + [ 0x1820, 0x1877 ], + [ 0x1880, 0x18A8 ], + [ 0x1900, 0x191C ], + [ 0x1950, 0x196D ], + [ 0x1970, 0x1974 ], + [ 0x1980, 0x19A9 ], + [ 0x19C1, 0x19C7 ], + [ 0x1A00, 0x1A16 ], + [ 0x1B05, 0x1B33 ], + [ 0x1B45, 0x1B4B ], + [ 0x1D00, 0x1DBF ], + [ 0x1E00, 0x1E9B ], + [ 0x1EA0, 0x1EF9 ], + [ 0x1F00, 0x1F15 ], + [ 0x1F18, 0x1F1D ], + [ 0x1F20, 0x1F45 ], + [ 0x1F48, 0x1F4D ], + [ 0x1F50, 0x1F57 ], + [ 0x1F59, 0x1F59 ], + [ 0x1F5B, 0x1F5B ], + [ 0x1F5D, 0x1F5D ], + [ 0x1F5F, 0x1F7D ], + [ 0x1F80, 0x1FB4 ], + [ 0x1FB6, 0x1FBC ], + [ 0x1FBE, 0x1FBE ], + [ 0x1FC2, 0x1FC4 ], + [ 0x1FC6, 0x1FCC ], + [ 0x1FD0, 0x1FD3 ], + [ 0x1FD6, 0x1FDB ], + [ 0x1FE0, 0x1FEC ], + [ 0x1FF2, 0x1FF4 ], + [ 0x1FF6, 0x1FFC ], + [ 0x2071, 0x2071 ], + [ 0x207F, 0x207F ], + [ 0x2090, 0x2094 ], + [ 0x2102, 0x2102 ], + [ 0x2107, 0x2107 ], + [ 0x210A, 0x2113 ], + [ 0x2115, 0x2115 ], + [ 0x2119, 0x211D ], + [ 0x2124, 0x2124 ], + [ 0x2126, 0x2126 ], + [ 0x2128, 0x2128 ], + [ 0x212A, 0x212D ], + [ 0x212F, 0x2139 ], + [ 0x213C, 0x213F ], + [ 0x2145, 0x2149 ], + [ 0x214E, 0x214E ], + [ 0x2183, 0x2184 ], + [ 0x2C00, 0x2C2E ], + [ 0x2C30, 0x2C5E ], + [ 0x2C60, 0x2C6C ], + [ 0x2C74, 0x2C77 ], + [ 0x2C80, 0x2CE4 ], + [ 0x2D00, 0x2D25 ], + [ 0x2D30, 0x2D65 ], + [ 0x2D6F, 0x2D6F ], + [ 0x2D80, 0x2D96 ], + [ 0x2DA0, 0x2DA6 ], + [ 0x2DA8, 0x2DAE ], + [ 0x2DB0, 0x2DB6 ], + [ 0x2DB8, 0x2DBE ], + [ 0x2DC0, 0x2DC6 ], + [ 0x2DC8, 0x2DCE ], + [ 0x2DD0, 0x2DD6 ], + [ 0x2DD8, 0x2DDE ], + [ 0x3005, 0x3006 ], + [ 0x3031, 0x3035 ], + [ 0x303B, 0x303C ], + [ 0x3041, 0x3096 ], + [ 0x309D, 0x309F ], + [ 0x30A1, 0x30FA ], + [ 0x30FC, 0x30FF ], + [ 0x3105, 0x312C ], + [ 0x3131, 0x318E ], + [ 0x31A0, 0x31B7 ], + [ 0x31F0, 0x31FF ], + [ 0x3400, 0x4DB5 ], + [ 0x4E00, 0x9FBB ], + [ 0xA000, 0xA48C ], + [ 0xA717, 0xA71A ], + [ 0xA800, 0xA801 ], + [ 0xA803, 0xA805 ], + [ 0xA807, 0xA80A ], + [ 0xA80C, 0xA822 ], + [ 0xA840, 0xA873 ], + [ 0xAC00, 0xD7A3 ], + [ 0xF900, 0xFA2D ], + [ 0xFA30, 0xFA6A ], + [ 0xFA70, 0xFAD9 ], + [ 0xFB00, 0xFB06 ], + [ 0xFB13, 0xFB17 ], + [ 0xFB1D, 0xFB1D ], + [ 0xFB1F, 0xFB28 ], + [ 0xFB2A, 0xFB36 ], + [ 0xFB38, 0xFB3C ], + [ 0xFB3E, 0xFB3E ], + [ 0xFB40, 0xFB41 ], + [ 0xFB43, 0xFB44 ], + [ 0xFB46, 0xFBB1 ], + [ 0xFBD3, 0xFD3D ], + [ 0xFD50, 0xFD8F ], + [ 0xFD92, 0xFDC7 ], + [ 0xFDF0, 0xFDFB ], + [ 0xFE70, 0xFE74 ], + [ 0xFE76, 0xFEFC ], + [ 0xFF21, 0xFF3A ], + [ 0xFF41, 0xFF5A ], + [ 0xFF66, 0xFFBE ], + [ 0xFFC2, 0xFFC7 ], + [ 0xFFCA, 0xFFCF ], + [ 0xFFD2, 0xFFD7 ], + [ 0xFFDA, 0xFFDC ], + [ 0x10000, 0x1000B ], + [ 0x1000D, 0x10026 ], + [ 0x10028, 0x1003A ], + [ 0x1003C, 0x1003D ], + [ 0x1003F, 0x1004D ], + [ 0x10050, 0x1005D ], + [ 0x10080, 0x100FA ], + [ 0x10300, 0x1031E ], + [ 0x10330, 0x10340 ], + [ 0x10342, 0x10349 ], + [ 0x10380, 0x1039D ], + [ 0x103A0, 0x103C3 ], + [ 0x103C8, 0x103CF ], + [ 0x10400, 0x1049D ], + [ 0x10800, 0x10805 ], + [ 0x10808, 0x10808 ], + [ 0x1080A, 0x10835 ], + [ 0x10837, 0x10838 ], + [ 0x1083C, 0x1083C ], + [ 0x1083F, 0x1083F ], + [ 0x10900, 0x10915 ], + [ 0x10A00, 0x10A00 ], + [ 0x10A10, 0x10A13 ], + [ 0x10A15, 0x10A17 ], + [ 0x10A19, 0x10A33 ], + [ 0x12000, 0x1236E ], + [ 0x1D400, 0x1D454 ], + [ 0x1D456, 0x1D49C ], + [ 0x1D49E, 0x1D49F ], + [ 0x1D4A2, 0x1D4A2 ], + [ 0x1D4A5, 0x1D4A6 ], + [ 0x1D4A9, 0x1D4AC ], + [ 0x1D4AE, 0x1D4B9 ], + [ 0x1D4BB, 0x1D4BB ], + [ 0x1D4BD, 0x1D4C3 ], + [ 0x1D4C5, 0x1D505 ], + [ 0x1D507, 0x1D50A ], + [ 0x1D50D, 0x1D514 ], + [ 0x1D516, 0x1D51C ], + [ 0x1D51E, 0x1D539 ], + [ 0x1D53B, 0x1D53E ], + [ 0x1D540, 0x1D544 ], + [ 0x1D546, 0x1D546 ], + [ 0x1D54A, 0x1D550 ], + [ 0x1D552, 0x1D6A5 ], + [ 0x1D6A8, 0x1D6C0 ], + [ 0x1D6C2, 0x1D6DA ], + [ 0x1D6DC, 0x1D6FA ], + [ 0x1D6FC, 0x1D714 ], + [ 0x1D716, 0x1D734 ], + [ 0x1D736, 0x1D74E ], + [ 0x1D750, 0x1D76E ], + [ 0x1D770, 0x1D788 ], + [ 0x1D78A, 0x1D7A8 ], + [ 0x1D7AA, 0x1D7C2 ], + [ 0x1D7C4, 0x1D7CB ], + [ 0x20000, 0x2A6D6 ], + [ 0x2F800, 0x2FA1D ], + ]; + + debug + { + for (int i = 0; i < table.length; i++) + { + assert(table[i][0] <= table[i][1]); + if (i < table.length - 1) + { + if (table[i][1] >= table[i + 1][0]) + printf("table[%d][1] = x%x, table[%d][0] = x%x\n", i, table[i][1], i + 1, table[i + 1][0]); + assert(table[i][1] < table[i + 1][0]); + } + } + } + + if (u < 0xAA) + { + if (u < 'A') + goto Lisnot; + if (u <= 'Z') + goto Lis; + if (u < 'a') + goto Lisnot; + if (u <= 'z') + goto Lis; + goto Lisnot; + } + + // Binary search + uint mid; + uint low; + uint high; + + low = 0; + high = table.length - 1; + while (cast(int)low <= cast(int)high) + { + mid = (low + high) >> 1; + if (u < table[mid][0]) + high = mid - 1; + else if (u > table[mid][1]) + low = mid + 1; + else + goto Lis; + } + +Lisnot: + debug + { + for (int i = 0; i < table.length; i++) + { + assert(u < table[i][0] || u > table[i][1]); + } + } + return 0; + +Lis: + debug + { + for (int i = 0; i < table.length; i++) + { + if (u >= table[i][0] && u <= table[i][1]) + return 1; + } + assert(0); // should have been in table + } + return 1; +} + +unittest +{ + for (uint i = 0; i < 0x80; i++) + { + if (i >= 'A' && i <= 'Z') + assert(isUniAlpha(i)); + else if (i >= 'a' && i <= 'z') + assert(isUniAlpha(i)); + else + assert(!isUniAlpha(i)); + } +} diff --git a/lphobos/std/utf.d b/lphobos/std/utf.d new file mode 100644 index 00000000..6b82b0ea --- /dev/null +++ b/lphobos/std/utf.d @@ -0,0 +1,969 @@ +// utf.d + +/* + * Copyright (C) 2003-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. + */ + +/******************************************** + * Encode and decode UTF-8, UTF-16 and UTF-32 strings. + * + * For Win32 systems, the C wchar_t type is UTF-16 and corresponds to the D + * wchar type. + * For linux systems, the C wchar_t type is UTF-32 and corresponds to + * the D utf.dchar type. + * + * UTF character support is restricted to (\u0000 <= character <= \U0010FFFF). + * + * See_Also: + * $(LINK2 http://en.wikipedia.org/wiki/Unicode, Wikipedia)
+ * $(LINK http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8)
+ * $(LINK http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335) + * Macros: + * WIKI = Phobos/StdUtf + */ + +module std.utf; + +private import std.stdio; + +//debug=utf; // uncomment to turn on debugging printf's + +deprecated class UtfError : Error +{ + size_t idx; // index in string of where error occurred + + this(char[] s, size_t i) + { + idx = i; + super(s); + } +} + +/********************************** + * Exception class that is thrown upon any errors. + */ + +class UtfException : Exception +{ + size_t idx; /// index in string of where error occurred + + this(char[] s, size_t i) + { + idx = i; + super(s); + } +} + +/******************************* + * Test if c is a valid UTF-32 character. + * + * \uFFFE and \uFFFF are considered valid by this function, + * as they are permitted for internal use by an application, + * but they are not allowed for interchange by the Unicode standard. + * + * Returns: true if it is, false if not. + */ + +bool isValidDchar(dchar c) +{ + /* Note: FFFE and FFFF are specifically permitted by the + * Unicode standard for application internal use, but are not + * allowed for interchange. + * (thanks to Arcane Jill) + */ + + return c < 0xD800 || + (c > 0xDFFF && c <= 0x10FFFF /*&& c != 0xFFFE && c != 0xFFFF*/); +} + +unittest +{ + debug(utf) printf("utf.isValidDchar.unittest\n"); + assert(isValidDchar(cast(dchar)'a') == true); + assert(isValidDchar(cast(dchar)0x1FFFFF) == false); +} + + +ubyte[256] UTF8stride = +[ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,5,5,5,5,6,6,0xFF,0xFF, +]; + +/** + * stride() returns the length of a UTF-8 sequence starting at index i + * in string s. + * Returns: + * The number of bytes in the UTF-8 sequence or + * 0xFF meaning s[i] is not the start of of UTF-8 sequence. + */ + +uint stride(char[] s, size_t i) +{ + return UTF8stride[s[i]]; +} + +/** + * stride() returns the length of a UTF-16 sequence starting at index i + * in string s. + */ + +uint stride(wchar[] s, size_t i) +{ uint u = s[i]; + return 1 + (u >= 0xD800 && u <= 0xDBFF); +} + +/** + * stride() returns the length of a UTF-32 sequence starting at index i + * in string s. + * Returns: The return value will always be 1. + */ + +uint stride(dchar[] s, size_t i) +{ + return 1; +} + +/******************************************* + * Given an index i into an array of characters s[], + * and assuming that index i is at the start of a UTF character, + * determine the number of UCS characters up to that index i. + */ + +size_t toUCSindex(char[] s, size_t i) +{ + size_t n; + size_t j; + size_t stride; + + for (j = 0; j < i; j += stride) + { + stride = UTF8stride[s[j]]; + if (stride == 0xFF) + goto Lerr; + n++; + } + if (j > i) + { + Lerr: + throw new UtfException("1invalid UTF-8 sequence", j); + } + return n; +} + +/** ditto */ + +size_t toUCSindex(wchar[] s, size_t i) +{ + size_t n; + size_t j; + + for (j = 0; j < i; ) + { uint u = s[j]; + + j += 1 + (u >= 0xD800 && u <= 0xDBFF); + n++; + } + if (j > i) + { + Lerr: + throw new UtfException("2invalid UTF-16 sequence", j); + } + return n; +} + +/** ditto */ + +size_t toUCSindex(dchar[] s, size_t i) +{ + return i; +} + +/****************************************** + * Given a UCS index n into an array of characters s[], return the UTF index. + */ + +size_t toUTFindex(char[] s, size_t n) +{ + size_t i; + + while (n--) + { + uint j = UTF8stride[s[i]]; + if (j == 0xFF) + throw new UtfException("3invalid UTF-8 sequence", i); + i += j; + } + return i; +} + +/** ditto */ + +size_t toUTFindex(wchar[] s, size_t n) +{ + size_t i; + + while (n--) + { wchar u = s[i]; + + i += 1 + (u >= 0xD800 && u <= 0xDBFF); + } + return i; +} + +/** ditto */ + +size_t toUTFindex(dchar[] s, size_t n) +{ + return n; +} + +/* =================== Decode ======================= */ + +/*************** + * Decodes and returns character starting at s[idx]. idx is advanced past the + * decoded character. If the character is not well formed, a UtfException is + * thrown and idx remains unchanged. + */ + +dchar decode(char[] s, inout size_t idx) + in + { + assert(idx >= 0 && idx < s.length); + } + out (result) + { + assert(isValidDchar(result)); + } + body + { + size_t len = s.length; + dchar V; + size_t i = idx; + char u = s[i]; + + if (u & 0x80) + { uint n; + char u2; + + /* The following encodings are valid, except for the 5 and 6 byte + * combinations: + * 0xxxxxxx + * 110xxxxx 10xxxxxx + * 1110xxxx 10xxxxxx 10xxxxxx + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + * 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + * 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + */ + for (n = 1; ; n++) + { + if (n > 4) + goto Lerr; // only do the first 4 of 6 encodings + if (((u << n) & 0x80) == 0) + { + if (n == 1) + goto Lerr; + break; + } + } + + // Pick off (7 - n) significant bits of B from first byte of octet + V = cast(dchar)(u & ((1 << (7 - n)) - 1)); + + if (i + (n - 1) >= len) + goto Lerr; // off end of string + + /* The following combinations are overlong, and illegal: + * 1100000x (10xxxxxx) + * 11100000 100xxxxx (10xxxxxx) + * 11110000 1000xxxx (10xxxxxx 10xxxxxx) + * 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx) + * 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx) + */ + u2 = s[i + 1]; + if ((u & 0xFE) == 0xC0 || + (u == 0xE0 && (u2 & 0xE0) == 0x80) || + (u == 0xF0 && (u2 & 0xF0) == 0x80) || + (u == 0xF8 && (u2 & 0xF8) == 0x80) || + (u == 0xFC && (u2 & 0xFC) == 0x80)) + goto Lerr; // overlong combination + + for (uint j = 1; j != n; j++) + { + u = s[i + j]; + if ((u & 0xC0) != 0x80) + goto Lerr; // trailing bytes are 10xxxxxx + V = (V << 6) | (u & 0x3F); + } + if (!isValidDchar(V)) + goto Lerr; + i += n; + } + else + { + V = cast(dchar) u; + i++; + } + + idx = i; + return V; + + Lerr: + //printf("\ndecode: idx = %d, i = %d, length = %d s = \n'%.*s'\n%x\n'%.*s'\n", idx, i, s.length, s, s[i], s[i .. length]); + throw new UtfException("4invalid UTF-8 sequence", i); + } + +unittest +{ size_t i; + dchar c; + + debug(utf) printf("utf.decode.unittest\n"); + + static char[] s1 = "abcd"; + i = 0; + c = decode(s1, i); + assert(c == cast(dchar)'a'); + assert(i == 1); + c = decode(s1, i); + assert(c == cast(dchar)'b'); + assert(i == 2); + + static char[] s2 = "\xC2\xA9"; + i = 0; + c = decode(s2, i); + assert(c == cast(dchar)'\u00A9'); + assert(i == 2); + + static char[] s3 = "\xE2\x89\xA0"; + i = 0; + c = decode(s3, i); + assert(c == cast(dchar)'\u2260'); + assert(i == 3); + + static char[][] s4 = + [ "\xE2\x89", // too short + "\xC0\x8A", + "\xE0\x80\x8A", + "\xF0\x80\x80\x8A", + "\xF8\x80\x80\x80\x8A", + "\xFC\x80\x80\x80\x80\x8A", + ]; + + for (int j = 0; j < s4.length; j++) + { + try + { + i = 0; + c = decode(s4[j], i); + assert(0); + } + catch (UtfException u) + { + i = 23; + delete u; + } + assert(i == 23); + } +} + +/** ditto */ + +dchar decode(wchar[] s, inout size_t idx) + in + { + assert(idx >= 0 && idx < s.length); + } + out (result) + { + assert(isValidDchar(result)); + } + body + { + char[] msg; + dchar V; + size_t i = idx; + uint u = s[i]; + + if (u & ~0x7F) + { if (u >= 0xD800 && u <= 0xDBFF) + { uint u2; + + if (i + 1 == s.length) + { msg = "surrogate UTF-16 high value past end of string"; + goto Lerr; + } + u2 = s[i + 1]; + if (u2 < 0xDC00 || u2 > 0xDFFF) + { msg = "surrogate UTF-16 low value out of range"; + goto Lerr; + } + u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00); + i += 2; + } + else if (u >= 0xDC00 && u <= 0xDFFF) + { msg = "unpaired surrogate UTF-16 value"; + goto Lerr; + } + else if (u == 0xFFFE || u == 0xFFFF) + { msg = "illegal UTF-16 value"; + goto Lerr; + } + else + i++; + } + else + { + i++; + } + + idx = i; + return cast(dchar)u; + + Lerr: + throw new UtfException(msg, i); + } + +/** ditto */ + +dchar decode(dchar[] s, inout size_t idx) + in + { + assert(idx >= 0 && idx < s.length); + } + body + { + size_t i = idx; + dchar c = s[i]; + + if (!isValidDchar(c)) + goto Lerr; + idx = i + 1; + return c; + + Lerr: + throw new UtfException("5invalid UTF-32 value", i); + } + + +/* =================== Encode ======================= */ + +/******************************* + * Encodes character c and appends it to array s[]. + */ + +void encode(inout char[] s, dchar c) + in + { + assert(isValidDchar(c)); + } + body + { + char[] r = s; + + if (c <= 0x7F) + { + r ~= cast(char) c; + } + else + { + char[4] buf; + uint L; + + if (c <= 0x7FF) + { + buf[0] = cast(char)(0xC0 | (c >> 6)); + buf[1] = cast(char)(0x80 | (c & 0x3F)); + L = 2; + } + else if (c <= 0xFFFF) + { + buf[0] = cast(char)(0xE0 | (c >> 12)); + buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F)); + buf[2] = cast(char)(0x80 | (c & 0x3F)); + L = 3; + } + else if (c <= 0x10FFFF) + { + buf[0] = cast(char)(0xF0 | (c >> 18)); + buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F)); + buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F)); + buf[3] = cast(char)(0x80 | (c & 0x3F)); + L = 4; + } + else + { + assert(0); + } + r ~= buf[0 .. L]; + } + s = r; + } + +unittest +{ + debug(utf) printf("utf.encode.unittest\n"); + + char[] s = "abcd"; + encode(s, cast(dchar)'a'); + assert(s.length == 5); + assert(s == "abcda"); + + encode(s, cast(dchar)'\u00A9'); + assert(s.length == 7); + assert(s == "abcda\xC2\xA9"); + //assert(s == "abcda\u00A9"); // BUG: fix compiler + + encode(s, cast(dchar)'\u2260'); + assert(s.length == 10); + assert(s == "abcda\xC2\xA9\xE2\x89\xA0"); +} + +/** ditto */ + +void encode(inout wchar[] s, dchar c) + in + { + assert(isValidDchar(c)); + } + body + { + wchar[] r = s; + + if (c <= 0xFFFF) + { + r ~= cast(wchar) c; + } + else + { + wchar[2] buf; + + buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800); + buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00); + r ~= buf; + } + s = r; + } + +/** ditto */ + +void encode(inout dchar[] s, dchar c) + in + { + assert(isValidDchar(c)); + } + body + { + s ~= c; + } + +/* =================== Validation ======================= */ + +/*********************************** + * Checks to see if string is well formed or not. Throws a UtfException if it is + * not. Use to check all untrusted input for correctness. + */ + +void validate(char[] s) +{ + size_t len = s.length; + size_t i; + + for (i = 0; i < len; ) + { + decode(s, i); + } +} + +/** ditto */ + +void validate(wchar[] s) +{ + size_t len = s.length; + size_t i; + + for (i = 0; i < len; ) + { + decode(s, i); + } +} + +/** ditto */ + +void validate(dchar[] s) +{ + size_t len = s.length; + size_t i; + + for (i = 0; i < len; ) + { + decode(s, i); + } +} + +/* =================== Conversion to UTF8 ======================= */ + +char[] toUTF8(char[4] buf, dchar c) + in + { + assert(isValidDchar(c)); + } + body + { + if (c <= 0x7F) + { + buf[0] = cast(char) c; + return buf[0 .. 1]; + } + else if (c <= 0x7FF) + { + buf[0] = cast(char)(0xC0 | (c >> 6)); + buf[1] = cast(char)(0x80 | (c & 0x3F)); + return buf[0 .. 2]; + } + else if (c <= 0xFFFF) + { + buf[0] = cast(char)(0xE0 | (c >> 12)); + buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F)); + buf[2] = cast(char)(0x80 | (c & 0x3F)); + return buf[0 .. 3]; + } + else if (c <= 0x10FFFF) + { + buf[0] = cast(char)(0xF0 | (c >> 18)); + buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F)); + buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F)); + buf[3] = cast(char)(0x80 | (c & 0x3F)); + return buf[0 .. 4]; + } + assert(0); + } + +/******************* + * Encodes string s into UTF-8 and returns the encoded string. + */ + +char[] toUTF8(char[] s) + in + { + validate(s); + } + body + { + return s; + } + +/** ditto */ + +char[] toUTF8(wchar[] s) +{ + char[] r; + size_t i; + size_t slen = s.length; + + r.length = slen; + + for (i = 0; i < slen; i++) + { wchar c = s[i]; + + if (c <= 0x7F) + r[i] = cast(char)c; // fast path for ascii + else + { + r.length = i; + foreach (dchar c; s[i .. slen]) + { + encode(r, c); + } + break; + } + } + return r; +} + +/** ditto */ + +char[] toUTF8(dchar[] s) +{ + char[] r; + size_t i; + size_t slen = s.length; + + r.length = slen; + + for (i = 0; i < slen; i++) + { dchar c = s[i]; + + if (c <= 0x7F) + r[i] = cast(char)c; // fast path for ascii + else + { + r.length = i; + foreach (dchar d; s[i .. slen]) + { + encode(r, d); + } + break; + } + } + return r; +} + +/* =================== Conversion to UTF16 ======================= */ + +wchar[] toUTF16(wchar[2] buf, dchar c) + in + { + assert(isValidDchar(c)); + } + body + { + if (c <= 0xFFFF) + { + buf[0] = cast(wchar) c; + return buf[0 .. 1]; + } + else + { + buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800); + buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00); + return buf[0 .. 2]; + } + } + +/**************** + * Encodes string s into UTF-16 and returns the encoded string. + * toUTF16z() is suitable for calling the 'W' functions in the Win32 API that take + * an LPWSTR or LPCWSTR argument. + */ + +wchar[] toUTF16(char[] s) +{ + wchar[] r; + size_t slen = s.length; + + r.length = slen; + r.length = 0; + for (size_t i = 0; i < slen; ) + { + dchar c = s[i]; + if (c <= 0x7F) + { + i++; + r ~= cast(wchar)c; + } + else + { + c = decode(s, i); + encode(r, c); + } + } + return r; +} + +/** ditto */ + +wchar* toUTF16z(char[] s) +{ + wchar[] r; + size_t slen = s.length; + + r.length = slen + 1; + r.length = 0; + for (size_t i = 0; i < slen; ) + { + dchar c = s[i]; + if (c <= 0x7F) + { + i++; + r ~= cast(wchar)c; + } + else + { + c = decode(s, i); + encode(r, c); + } + } + r ~= "\000"; + return r.ptr; +} + +/** ditto */ + +wchar[] toUTF16(wchar[] s) + in + { + validate(s); + } + body + { + return s; + } + +/** ditto */ + +wchar[] toUTF16(dchar[] s) +{ + wchar[] r; + size_t slen = s.length; + + r.length = slen; + r.length = 0; + for (size_t i = 0; i < slen; i++) + { + encode(r, s[i]); + } + return r; +} + +/* =================== Conversion to UTF32 ======================= */ + +/***** + * Encodes string s into UTF-32 and returns the encoded string. + */ + +dchar[] toUTF32(char[] s) +{ + dchar[] r; + size_t slen = s.length; + size_t j = 0; + + r.length = slen; // r[] will never be longer than s[] + for (size_t i = 0; i < slen; ) + { + dchar c = s[i]; + if (c >= 0x80) + c = decode(s, i); + else + i++; // c is ascii, no need for decode + r[j++] = c; + } + return r[0 .. j]; +} + +/** ditto */ + +dchar[] toUTF32(wchar[] s) +{ + dchar[] r; + size_t slen = s.length; + size_t j = 0; + + r.length = slen; // r[] will never be longer than s[] + for (size_t i = 0; i < slen; ) + { + dchar c = s[i]; + if (c >= 0x80) + c = decode(s, i); + else + i++; // c is ascii, no need for decode + r[j++] = c; + } + return r[0 .. j]; +} + +/** ditto */ + +dchar[] toUTF32(dchar[] s) + in + { + validate(s); + } + body + { + return s; + } + +/* ================================ tests ================================== */ + +unittest +{ + debug(utf) printf("utf.toUTF.unittest\n"); + + char[] c; + wchar[] w; + dchar[] d; + + c = "hello"; + w = toUTF16(c); + assert(w == "hello"); + d = toUTF32(c); + assert(d == "hello"); + + c = toUTF8(w); + assert(c == "hello"); + d = toUTF32(w); + assert(d == "hello"); + + c = toUTF8(d); + assert(c == "hello"); + w = toUTF16(d); + assert(w == "hello"); + + + c = "hel\u1234o"; + w = toUTF16(c); + assert(w == "hel\u1234o"); + d = toUTF32(c); + assert(d == "hel\u1234o"); + + c = toUTF8(w); + assert(c == "hel\u1234o"); + d = toUTF32(w); + assert(d == "hel\u1234o"); + + c = toUTF8(d); + assert(c == "hel\u1234o"); + w = toUTF16(d); + assert(w == "hel\u1234o"); + + + c = "he\U0010AAAAllo"; + w = toUTF16(c); + //foreach (wchar c; w) printf("c = x%x\n", c); + //foreach (wchar c; cast(wchar[])"he\U0010AAAAllo") printf("c = x%x\n", c); + assert(w == "he\U0010AAAAllo"); + d = toUTF32(c); + assert(d == "he\U0010AAAAllo"); + + c = toUTF8(w); + assert(c == "he\U0010AAAAllo"); + d = toUTF32(w); + assert(d == "he\U0010AAAAllo"); + + c = toUTF8(d); + assert(c == "he\U0010AAAAllo"); + w = toUTF16(d); + assert(w == "he\U0010AAAAllo"); +} diff --git a/premake.lua b/premake.lua index d98bf7b7..5f2f9191 100644 --- a/premake.lua +++ b/premake.lua @@ -21,13 +21,13 @@ package.bindir = "bin" package.name = "llvmdc" package.kind = "exe" package.language = "c++" -package.files = { matchfiles("dmd/*.c"), matchfiles("gen/*.c") } +package.files = { matchfiles("dmd/*.c"), matchfiles("gen/*.cpp") } package.excludes = { "dmd/idgen.c", "dmd/impcnvgen.c" } package.buildoptions = { "-x c++", "`llvm-config --cxxflags`" } package.linkoptions = { "`llvm-config --libs native bitwriter bitreader`", "`llvm-config --ldflags`" } package.defines = { "IN_LLVM", "_DH" } package.config.Release.defines = { "LLVMD_NO_LOGGER" } -package.config.Debug.buildoptions = { "-g" } +package.config.Debug.buildoptions = { "-g -O0" } --package.targetprefix = "llvm" package.includepaths = { ".", "dmd" } --package.postbuildcommands = { "cd runtime; ./build.sh; cd .." } diff --git a/test/arrays10.d b/test/arrays10.d new file mode 100644 index 00000000..9ee7311e --- /dev/null +++ b/test/arrays10.d @@ -0,0 +1,7 @@ +module arrays10; + +void main() +{ + int[] a = new int[10]; + a[] = 3; +} \ No newline at end of file diff --git a/test/arrays7.d b/test/arrays7.d index aa241ba1..6ae2163c 100644 --- a/test/arrays7.d +++ b/test/arrays7.d @@ -1,18 +1,29 @@ module arrays7; +pragma(LLVM_internal, "notypeinfo") struct S { int i; float f; long l; + + void print() + { + printf("%d %f %lx\n", i, f, l); + } } void main() { S[] arr; S s; + assert(arr.length == 0); arr ~= s; + assert(arr.length == 1); arr ~= S(1,2.64,0xFFFF_FFFF_FFFF); + assert(arr.length == 2); + arr[0].print(); + arr[1].print(); assert(arr[1].i == 1); assert(arr[1].f > 2.63 && arr[1].f < 2.65); assert(arr[1].l == 0xFFFF_FFFF_FFFF); diff --git a/test/arrays9.d b/test/arrays9.d new file mode 100644 index 00000000..afc2034e --- /dev/null +++ b/test/arrays9.d @@ -0,0 +1,8 @@ +module arrays9; + +const int[] g = [1,2,3,4]; + +void main() +{ + +} diff --git a/test/b.d b/test/b.d index 564b861d..ba239094 100644 --- a/test/b.d +++ b/test/b.d @@ -10,7 +10,7 @@ void main() { S s; int i = s.i; - int* p = &s.i; + /*int* p = &s.i; *p = 42; printf("%d == %d\n", *p, s.i); @@ -19,5 +19,5 @@ void main() *f = 3.1415; printf("%f == %f\n", *f, s.f[0]); s.f[0] = 123.456; - printf("%f == %f\n", *f, s.f[0]); + printf("%f == %f\n", *f, s.f[0]);*/ } diff --git a/test/bitops.d b/test/bitops.d index 5796e63a..8f706733 100644 --- a/test/bitops.d +++ b/test/bitops.d @@ -19,7 +19,7 @@ void main() assert((s>>1) == -5); assert((s>>>1) != -5); } - + { ushort a = 0xFFF0; ushort b = 0x0FFF; auto t = a; @@ -70,6 +70,6 @@ void main() s.i &= s.l; assert(s.i == 0x00FF_FF00); } - + printf(" SUCCESS\n"); } diff --git a/test/bug48.d b/test/bug48.d new file mode 100644 index 00000000..86169136 --- /dev/null +++ b/test/bug48.d @@ -0,0 +1,10 @@ +module bug48; + +size_t func(void *p) +{ + return cast(size_t)*cast(void* *)p; +} + +void main() +{ +} diff --git a/test/bug49.d b/test/bug49.d new file mode 100644 index 00000000..553971e9 --- /dev/null +++ b/test/bug49.d @@ -0,0 +1,16 @@ +module bug49; + +pragma(LLVM_internal, "notypeinfo") +struct S +{ + int i; + long l; +} + +void main() +{ + S s; + s.i = 0x__FFFF_FF00; + s.l = 0xFF00FF_FF00; + s.i &= s.l; +} diff --git a/test/bug50.d b/test/bug50.d new file mode 100644 index 00000000..5aca4ada --- /dev/null +++ b/test/bug50.d @@ -0,0 +1,28 @@ +module bug50; + +pragma(LLVM_internal, "notypeinfo") +struct S +{ + int i; + float f; + long l; + + void print() + { + printf("%d %f %lx\n", i, f, l); + } +} + +void main() +{ + S s; + s.print(); + s = S(1,2,3); + s.print(); + + S[] arr; + {arr ~= s;} + {arr[0].print();} + {arr ~= S(1,2,3);} + {arr[1].print();} +}