# HG changeset patch # User lindquist # Date 1192772601 -7200 # Node ID 8b0e809563dfefb2b707da1f6309c733218645c2 # Parent fd5e8bbfcb25c9245a389ec30eae4298f6e7d32a [svn r44] Lots of bug fixes. New array literal support New array ~= operator support (for single element) New with statement support More... diff -r fd5e8bbfcb25 -r 8b0e809563df dmd/declaration.c --- a/dmd/declaration.c Wed Oct 10 06:21:31 2007 +0200 +++ b/dmd/declaration.c Fri Oct 19 07:43:21 2007 +0200 @@ -31,7 +31,8 @@ type = NULL; storage_class = STCundefined; protection = PROTundefined; - linkage = LINKdefault; + linkage = LINKdefault; + llvmTouched = false; } void Declaration::semantic(Scope *sc) diff -r fd5e8bbfcb25 -r 8b0e809563df dmd/declaration.h --- a/dmd/declaration.h Wed Oct 10 06:21:31 2007 +0200 +++ b/dmd/declaration.h Fri Oct 19 07:43:21 2007 +0200 @@ -125,7 +125,9 @@ Declaration *isDeclaration() { return this; } - virtual void toObjFile(); // compile to .obj file + virtual void toObjFile(); // compile to .obj file + + bool llvmTouched; }; /**************************************************************/ diff -r fd5e8bbfcb25 -r 8b0e809563df dmd/expression.h --- a/dmd/expression.h Wed Oct 10 06:21:31 2007 +0200 +++ b/dmd/expression.h Fri Oct 19 07:43:21 2007 +0200 @@ -46,6 +46,7 @@ namespace llvm { + class Constant; class ConstantInt; } @@ -147,6 +148,8 @@ // Back end virtual elem *toElem(IRState *irs); virtual dt_t **toDt(dt_t **pdt); + // LLVMDC + virtual llvm::Constant *toConstElem(IRState *irs); }; struct IntegerExp : Expression @@ -172,6 +175,8 @@ Expression *toLvalue(Scope *sc, Expression *e); elem *toElem(IRState *irs); dt_t **toDt(dt_t **pdt); + // LLVMDC + virtual llvm::Constant *toConstElem(IRState *irs); }; struct RealExp : Expression @@ -195,6 +200,8 @@ void toMangleBuffer(OutBuffer *buf); elem *toElem(IRState *irs); dt_t **toDt(dt_t **pdt); + // LLVMDC + virtual llvm::Constant *toConstElem(IRState *irs); }; struct ComplexExp : Expression @@ -298,6 +305,8 @@ Expression *interpret(InterState *istate); elem *toElem(IRState *irs); dt_t **toDt(dt_t **pdt); + // LLVMDC + virtual llvm::Constant *toConstElem(IRState *irs); }; struct StringExp : Expression @@ -326,6 +335,8 @@ void toMangleBuffer(OutBuffer *buf); elem *toElem(IRState *irs); dt_t **toDt(dt_t **pdt); + // LLVMDC + virtual llvm::Constant *toConstElem(IRState *irs); }; // Tuple @@ -376,6 +387,8 @@ int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); + // LLVMDC + virtual llvm::Constant *toConstElem(IRState *irs); }; struct AssocArrayLiteralExp : Expression @@ -401,6 +414,8 @@ int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); + // LLVMDC + virtual llvm::Constant *toConstElem(IRState *irs); }; struct StructLiteralExp : Expression @@ -432,6 +447,8 @@ int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); + // LLVMDC + virtual llvm::Constant *toConstElem(IRState *irs); }; struct TypeDotIdExp : Expression @@ -564,6 +581,8 @@ int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); //Expression *inlineScan(InlineScanState *iss); + // LLVMDC + virtual llvm::Constant *toConstElem(IRState *irs); }; // Function/Delegate literal diff -r fd5e8bbfcb25 -r 8b0e809563df dmd/mars.c --- a/dmd/mars.c Wed Oct 10 06:21:31 2007 +0200 +++ b/dmd/mars.c Fri Oct 19 07:43:21 2007 +0200 @@ -192,16 +192,16 @@ x86 x86-64 ppc32 ppc64\n\ -nofloat do not emit reference to floating point\n\ -noruntime do not allow code that generates implicit runtime calls\n\ - -novalidate do not run the validation pass before writing bitcode\n\ + -noverify do not run the validation pass before writing bitcode\n\ -O optimize, same as -O2\n\ -O optimize at level (0-5)\n\ -o- do not write object file\n\ -od write object files to directory \n\ -of name output file to \n\ -op do not strip paths from source file\n\ - -profile profile runtime performance of generated code\n\ + -profile profile runtime performance of generated code\n\ -quiet suppress unnecessary messages\n\ - -release compile release version\n\ + -release compile release version\n\ -run srcfile args... run resulting program, passing args\n\ -unittest compile in unit tests\n\ -v verbose\n\ @@ -382,7 +382,7 @@ global.params.forceBE = 1; else if (strcmp(p + 1, "noruntime") == 0) global.params.noruntime = 1; - else if (strcmp(p + 1, "novalidate") == 0) + else if (strcmp(p + 1, "noverify") == 0) global.params.novalidate = 1; else if (p[1] == 'o') { diff -r fd5e8bbfcb25 -r 8b0e809563df gen/arrays.c --- a/gen/arrays.c Wed Oct 10 06:21:31 2007 +0200 +++ b/gen/arrays.c Fri Oct 19 07:43:21 2007 +0200 @@ -1,8 +1,4 @@ -#include "llvm/Constants.h" -#include "llvm/Type.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" -#include "llvm/CallingConv.h" +#include "gen/llvm.h" #include "mtype.h" #include "dsymbol.h" @@ -218,16 +214,17 @@ } ////////////////////////////////////////////////////////////////////////////////////////// -llvm::Constant* LLVM_DtoArrayInitializer(ArrayInitializer* arrinit) +llvm::Constant* LLVM_DtoConstArrayInitializer(ArrayInitializer* arrinit) { Logger::println("arr init begin"); - assert(arrinit->type->ty == Tsarray); - TypeSArray* t = (TypeSArray*)arrinit->type; + Type* arrinittype = LLVM_DtoDType(arrinit->type); + assert(arrinittype->ty == Tsarray); + TypeSArray* t = (TypeSArray*)arrinittype; integer_t tdim = t->dim->toInteger(); std::vector inits(tdim, 0); - const llvm::Type* elemty = LLVM_DtoType(arrinit->type->next); + const llvm::Type* elemty = LLVM_DtoType(arrinittype->next); assert(arrinit->index.dim == arrinit->value.dim); for (int i=0,j=0; i < tdim; ++i) @@ -255,23 +252,19 @@ if (!init) { - elem* e = t->next->defaultInit()->toElem(gIR); - v = llvm::cast(e->val); - delete e; + v = t->next->defaultInit()->toConstElem(gIR); } else if (ExpInitializer* ex = init->isExpInitializer()) { - elem* e = ex->exp->toElem(gIR); - v = llvm::cast(e->val); - delete e; + v = ex->exp->toConstElem(gIR); } else if (StructInitializer* si = init->isStructInitializer()) { - v = LLVM_DtoStructInitializer(si); + v = LLVM_DtoConstStructInitializer(si); } else if (ArrayInitializer* ai = init->isArrayInitializer()) { - v = LLVM_DtoArrayInitializer(ai); + v = LLVM_DtoConstArrayInitializer(ai); } else if (init->isVoidInitializer()) { @@ -415,3 +408,61 @@ new llvm::StoreInst(sz,len,gIR->scopebb()); } +////////////////////////////////////////////////////////////////////////////////////////// +void LLVM_DtoCatArrayElement(llvm::Value* arr, Expression* exp) +{ + llvm::Value* ptr = LLVM_DtoGEPi(arr, 0, 0, "tmp", gIR->scopebb()); + llvm::Value* idx = new llvm::LoadInst(ptr, "tmp", gIR->scopebb()); + llvm::Value* one = llvm::ConstantInt::get(idx->getType(),1,false); + llvm::Value* len = llvm::BinaryOperator::createAdd(idx, one, "tmp", gIR->scopebb()); + LLVM_DtoResizeDynArray(arr,len); + + ptr = LLVM_DtoGEPi(arr, 0, 1, "tmp", gIR->scopebb()); + ptr = new llvm::LoadInst(ptr, "tmp", gIR->scopebb()); + ptr = new llvm::GetElementPtrInst(ptr, idx, "tmp", gIR->scopebb()); + + elem* e = exp->toElem(gIR); + Type* et = LLVM_DtoDType(exp->type); + + if (et->ty == Tstruct) { + TypeStruct* ts = (TypeStruct*)et; + LLVM_DtoStructCopy(ts,ptr,e->getValue()); + } + else { + llvm::Value* val = e->getValue(); + Logger::cout() << "ptr = '" << *ptr << "' element = '" << *val << "'\n"; + new llvm::StoreInst(val, ptr, gIR->scopebb()); + } +} + +////////////////////////////////////////////////////////////////////////////////////////// +llvm::Value* LLVM_DtoStaticArrayCompare(TOK op, llvm::Value* l, llvm::Value* r) +{ + const char* fname; + if (op == TOKequal) + fname = "_d_static_array_eq"; + else if (op == TOKnotequal) + fname = "_d_static_array_neq"; + else + assert(0); + llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname); + assert(fn); + + assert(l->getType() == r->getType()); + assert(llvm::isa(l->getType())); + const llvm::Type* arrty = l->getType()->getContainedType(0); + assert(llvm::isa(arrty)); + + llvm::Value* ll = new llvm::BitCastInst(l, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb()); + llvm::Value* rr = new llvm::BitCastInst(r, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb()); + llvm::Value* n = llvm::ConstantInt::get(LLVM_DtoSize_t(),gTargetData->getTypeSize(arrty),false); + + std::vector args; + args.push_back(ll); + args.push_back(rr); + args.push_back(n); + return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb()); +} + +////////////////////////////////////////////////////////////////////////////////////////// + diff -r fd5e8bbfcb25 -r 8b0e809563df gen/arrays.h --- a/gen/arrays.h Wed Oct 10 06:21:31 2007 +0200 +++ b/gen/arrays.h Fri Oct 19 07:43:21 2007 +0200 @@ -4,7 +4,7 @@ const llvm::StructType* LLVM_DtoArrayType(Type* t); const llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t); -llvm::Constant* LLVM_DtoArrayInitializer(ArrayInitializer* si); +llvm::Constant* LLVM_DtoConstArrayInitializer(ArrayInitializer* si); llvm::Constant* LLVM_DtoConstantSlice(llvm::Constant* dim, llvm::Constant* ptr); void LLVM_DtoArrayCopy(elem* dst, elem* src); @@ -17,4 +17,8 @@ void LLVM_DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, Type* dty, bool doinit=true); void LLVM_DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz); +void LLVM_DtoCatArrayElement(llvm::Value* arr, Expression* exp); + +llvm::Value* LLVM_DtoStaticArrayCompare(TOK op, llvm::Value* l, llvm::Value* r); + #endif // LLVMC_GEN_ARRAYS_H diff -r fd5e8bbfcb25 -r 8b0e809563df gen/elem.c --- a/gen/elem.c Wed Oct 10 06:21:31 2007 +0200 +++ b/gen/elem.c Fri Oct 19 07:43:21 2007 +0200 @@ -1,6 +1,6 @@ #include -#include "llvm/Instructions.h" +#include "gen/llvm.h" #include "gen/elem.h" #include "gen/irstate.h" @@ -50,7 +50,7 @@ return mem; } else { - return new llvm::LoadInst(mem, "tmp", gIR->scopebb()); + return gIR->ir->CreateLoad(mem, "tmp"); } } diff -r fd5e8bbfcb25 -r 8b0e809563df gen/elem.h --- a/gen/elem.h Wed Oct 10 06:21:31 2007 +0200 +++ b/gen/elem.h Fri Oct 19 07:43:21 2007 +0200 @@ -1,8 +1,6 @@ #ifndef LLVMDC_GEN_ELEM_H #define LLVMDC_GEN_ELEM_H -#include "llvm/Value.h" - #include "root.h" #include "declaration.h" #include "aggregate.h" diff -r fd5e8bbfcb25 -r 8b0e809563df gen/irstate.c --- a/gen/irstate.c Wed Oct 10 06:21:31 2007 +0200 +++ b/gen/irstate.c Fri Oct 19 07:43:21 2007 +0200 @@ -4,8 +4,15 @@ * has been parsed. Substitute your own behaviors for these routimes. */ +#include + +#include "gen/llvm.h" + #include "mtype.h" +#include "declaration.h" + #include "gen/irstate.h" +#include "tollvm.h" IRState* gIR = 0; llvm::TargetData* gTargetData = 0; @@ -13,15 +20,14 @@ ////////////////////////////////////////////////////////////////////////////////////////// IRScope::IRScope() { - begin = end = 0; - returned = false; + begin = end = NULL; } IRScope::IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e) { begin = b; end = e; - returned = false; + builder.SetInsertPoint(b); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -32,24 +38,31 @@ inLvalue = false; emitMain = false; mainFunc = 0; + ir.state = this; +} + +IRFunction& IRState::func() +{ + assert(!functions.empty() && "Function stack is empty!"); + return functions.back(); } llvm::Function* IRState::topfunc() { - assert(!funcs.empty() && "Function stack is empty!"); - return funcs.top(); + assert(!functions.empty() && "Function stack is empty!"); + return functions.back().func; } TypeFunction* IRState::topfunctype() { - assert(!functypes.empty() && "TypeFunction stack is empty!"); - return functypes.top(); + assert(!functions.empty() && "Function stack is empty!"); + return functions.back().type; } llvm::Instruction* IRState::topallocapoint() { - assert(!functypes.empty() && "AllocaPoint stack is empty!"); - return functypes.top()->llvmAllocaPoint; + assert(!functions.empty() && "AllocaPoint stack is empty!"); + return functions.back().allocapoint; } IRStruct& IRState::topstruct() @@ -108,6 +121,35 @@ queueFuncs = true; } -IRStruct::~IRStruct() +////////////////////////////////////////////////////////////////////////////////////////// + +IRFinally::IRFinally() + : bb(NULL), ret(false), retval(NULL) +{ +} + +IRFinally::IRFinally(llvm::BasicBlock* b) + : bb(b), ret(false), retval(NULL) { } + +////////////////////////////////////////////////////////////////////////////////////////// + +LLVMBuilder* IRBuilderHelper::operator->() +{ + LLVMBuilder& b = state->scope().builder; + assert(b.GetInsertBlock() != NULL); + return &b; +} + +////////////////////////////////////////////////////////////////////////////////////////// + +IRFunction::IRFunction(FuncDeclaration* fd) +{ + decl = fd; + Type* t = LLVM_DtoDType(fd->type); + assert(t->ty == Tfunction); + type = (TypeFunction*)t; + func = NULL; + allocapoint = NULL; +} diff -r fd5e8bbfcb25 -r 8b0e809563df gen/irstate.h --- a/gen/irstate.h Wed Oct 10 06:21:31 2007 +0200 +++ b/gen/irstate.h Fri Oct 19 07:43:21 2007 +0200 @@ -5,12 +5,6 @@ #include #include -#include "llvm/DerivedTypes.h" -#include "llvm/Module.h" -#include "llvm/Function.h" -#include "llvm/BasicBlock.h" -#include "llvm/Target/TargetData.h" - #include "root.h" // global ir state for current module @@ -25,19 +19,26 @@ struct Module; struct TypeStruct; +/* +struct LLVMValue +{ + std::vector vals; +}; +*/ + // represents a scope struct IRScope { llvm::BasicBlock* begin; llvm::BasicBlock* end; - bool returned; + LLVMBuilder builder; IRScope(); IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e); }; // represents a struct or class -struct IRStruct : Object +struct IRStruct { typedef std::vector TypeVector; typedef std::vector ConstantVector; @@ -46,7 +47,6 @@ public: IRStruct(); IRStruct(Type*); - virtual ~IRStruct(); Type* type; TypeVector fields; @@ -56,8 +56,40 @@ bool queueFuncs; }; +// represents a finally block +struct IRFinally +{ + llvm::BasicBlock* bb; + bool ret; + llvm::Value* retval; + + IRFinally(); + IRFinally(llvm::BasicBlock* b); +}; + +// represents a function +struct IRFunction +{ + llvm::Function* func; + llvm::Instruction* allocapoint; + FuncDeclaration* decl; + TypeFunction* type; + + // finally blocks + typedef std::vector FinallyVec; + FinallyVec finallys; + + IRFunction(FuncDeclaration*); +}; + +struct IRBuilderHelper +{ + IRState* state; + LLVMBuilder* operator->(); +}; + // represents the module -struct IRState : Object +struct IRState { IRState(); @@ -66,9 +98,11 @@ llvm::Module* module; // functions - std::stack funcs; + typedef std::vector FunctionVector; + FunctionVector functions; + IRFunction& func(); + llvm::Function* topfunc(); - std::stack functypes; TypeFunction* topfunctype(); llvm::Instruction* topallocapoint(); @@ -109,9 +143,8 @@ // array pointer from this :( LvalVec arrays; - // keeping track of the declaration for the current function body - typedef std::vector FuncDeclVec; - FuncDeclVec funcdecls; + // builder helper + IRBuilderHelper ir; }; #endif // LLVMDC_GEN_IRSTATE_H diff -r fd5e8bbfcb25 -r 8b0e809563df gen/llvm.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen/llvm.h Fri Oct 19 07:43:21 2007 +0200 @@ -0,0 +1,18 @@ +#ifndef GEN_LLVM_H +#define GEN_LLVM_H + +#include "llvm/Type.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Constants.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/CallingConv.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Function.h" +#include "llvm/Module.h" + +#include "llvm/Target/TargetData.h" + +#include "llvm/Support/LLVMBuilder.h" +using llvm::LLVMBuilder; + +#endif // GEN_LLVM_H diff -r fd5e8bbfcb25 -r 8b0e809563df gen/runtime.c --- a/gen/runtime.c Wed Oct 10 06:21:31 2007 +0200 +++ b/gen/runtime.c Fri Oct 19 07:43:21 2007 +0200 @@ -70,9 +70,13 @@ } llvm::Function* fn = M->getFunction(name); - if (!fn) - return NULL; + if (!fn) { + error("Runtime function '%s' was not found", name); + fatal(); + //return NULL; + } const llvm::FunctionType* fnty = fn->getFunctionType(); return llvm::cast(target->getOrInsertFunction(name, fnty)); } + diff -r fd5e8bbfcb25 -r 8b0e809563df gen/statements.c --- a/gen/statements.c Wed Oct 10 06:21:31 2007 +0200 +++ b/gen/statements.c Fri Oct 19 07:43:21 2007 +0200 @@ -6,12 +6,7 @@ #include #include -#include "llvm/Type.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Constants.h" -#include "llvm/Instructions.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/CallingConv.h" +#include "gen/llvm.h" #include "total.h" #include "init.h" @@ -41,8 +36,8 @@ if (s) s->toIR(p); else { - Logger::println("NULL statement found in CompoundStatement !! :S"); - assert(0); + Logger::println("*** ATTENTION: null statement found in CompoundStatement"); + //assert(0); } } @@ -56,11 +51,14 @@ Logger::println("ReturnStatement::toIR(%d): %s", rsi++, toChars()); LOG_SCOPE; + IRFunction::FinallyVec& fin = p->func().finallys; + if (exp) { - TY expty = exp->type->ty; + Type* exptype = LLVM_DtoDType(exp->type); + TY expty = exptype->ty; if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) { - assert(expty == Tstruct || expty == Tdelegate || expty == Tarray); + assert(LLVM_DtoIsPassedByRef(exptype)); TypeFunction* f = p->topfunctype(); assert(f->llvmRetInPtr && f->llvmRetArg); @@ -69,17 +67,14 @@ elem* e = exp->toElem(p); p->lvals.pop_back(); - // structliterals do this themselves - // also they dont produce any value if (expty == Tstruct) { if (!e->inplace) { - TypeStruct* ts = (TypeStruct*)exp->type; + TypeStruct* ts = (TypeStruct*)exptype; assert(e->mem); LLVM_DtoStructCopy(ts,f->llvmRetArg,e->mem); } } else if (expty == Tdelegate) { - // do nothing, handled by the DelegateExp LLVM_DtoDelegateCopy(f->llvmRetArg,e->mem); } else if (expty == Tarray) { @@ -91,26 +86,47 @@ else assert(0); - new llvm::ReturnInst(p->scopebb()); + if (fin.empty()) + new llvm::ReturnInst(p->scopebb()); + else { + new llvm::BranchInst(fin.back().bb); + fin.back().ret = true; + } delete e; } else { elem* e = exp->toElem(p); llvm::Value* v = e->getValue(); - Logger::cout() << *v << '\n'; - new llvm::ReturnInst(v, p->scopebb()); delete e; + Logger::cout() << "return value is '" <<*v << "'\n"; + if (fin.empty()) { + new llvm::ReturnInst(v, p->scopebb()); + } + else { + llvm::Value* rettmp = new llvm::AllocaInst(v->getType(),"tmpreturn",p->topallocapoint()); + new llvm::StoreInst(v,rettmp,p->scopebb()); + new llvm::BranchInst(fin.back().bb, p->scopebb()); + fin.back().ret = true; + fin.back().retval = rettmp; + } } } else { - if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) - new llvm::ReturnInst(p->scopebb()); - else + if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) { + if (fin.empty()) { + new llvm::ReturnInst(p->scopebb()); + } + else { + new llvm::BranchInst(fin.back().bb); + fin.back().ret = true; + } + } + else { + assert(0); // why should this ever happen? new llvm::UnreachableInst(p->scopebb()); + } } - - p->scope().returned = true; } ////////////////////////////////////////////////////////////////////////////// @@ -196,33 +212,26 @@ llvm::BasicBlock* oldend = p->scopeend(); - IRScope irs; + llvm::BasicBlock* beginbb = 0; + // remove useless branches by clearing and reusing the current basicblock llvm::BasicBlock* bb = p->scopebegin(); if (bb->empty()) { - irs.begin = bb; + beginbb = bb; } else { - irs.begin = new llvm::BasicBlock("scope", p->topfunc(), oldend); - new llvm::BranchInst(irs.begin, p->scopebegin()); + assert(!p->scopereturned()); + beginbb = new llvm::BasicBlock("scope", p->topfunc(), oldend); + new llvm::BranchInst(beginbb, p->scopebegin()); } - irs.end = new llvm::BasicBlock("endscope", p->topfunc(), oldend); + llvm::BasicBlock* endbb = new llvm::BasicBlock("endscope", p->topfunc(), oldend); - gIR->scope() = irs; + gIR->scope() = IRScope(beginbb, endbb); statement->toIR(p); p->scope() = IRScope(p->scopebb(),oldend); - irs.end->eraseFromParent(); - - /* - if (!gIR->scopereturned()) { - new llvm::BranchInst(irs.end, gIR->scopebegin()); - } - - // rewrite the scope - gIR->scope() = IRScope(irs.end,oldend); - */ + endbb->eraseFromParent(); } ////////////////////////////////////////////////////////////////////////////// @@ -239,7 +248,8 @@ llvm::BasicBlock* endbb = new llvm::BasicBlock("endwhile", gIR->topfunc(), oldend); // move into the while block - new llvm::BranchInst(whilebb, gIR->scopebegin()); + p->ir->CreateBr(whilebb); + //new llvm::BranchInst(whilebb, gIR->scopebegin()); // replace current scope gIR->scope() = IRScope(whilebb,endbb); @@ -324,10 +334,7 @@ // move into the for condition block, ie. start the loop new llvm::BranchInst(forbb, gIR->scopebegin()); - IRScope loop; - loop.begin = forincbb; - loop.end = endbb; - p->loopbbs.push_back(loop); + p->loopbbs.push_back(IRScope(forincbb,endbb)); // replace current scope gIR->scope() = IRScope(forbb,forbodybb); @@ -419,30 +426,46 @@ Logger::println("TryFinallyStatement::toIR(%d): %s", wsi++, toChars()); LOG_SCOPE; - llvm::BasicBlock* oldend = gIR->scopeend(); + llvm::BasicBlock* oldend = p->scopeend(); - llvm::BasicBlock* trybb = new llvm::BasicBlock("try", gIR->topfunc(), oldend); - llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", gIR->topfunc(), oldend); - llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", gIR->topfunc(), oldend); + llvm::BasicBlock* trybb = new llvm::BasicBlock("try", p->topfunc(), oldend); + llvm::BasicBlock* finallybb = new llvm::BasicBlock("finally", p->topfunc(), oldend); + llvm::BasicBlock* endbb = new llvm::BasicBlock("endtryfinally", p->topfunc(), oldend); // pass the previous BB into this - new llvm::BranchInst(trybb, gIR->scopebegin()); + new llvm::BranchInst(trybb, p->scopebb()); - gIR->scope() = IRScope(trybb,finallybb); + p->scope() = IRScope(trybb,finallybb); assert(body); + gIR->func().finallys.push_back(IRFinally(finallybb)); body->toIR(p); - new llvm::BranchInst(finallybb, gIR->scopebegin()); + if (!gIR->scopereturned()) + new llvm::BranchInst(finallybb, p->scopebb()); // rewrite the scope - gIR->scope() = IRScope(finallybb,endbb); + p->scope() = IRScope(finallybb,endbb); assert(finalbody); finalbody->toIR(p); - new llvm::BranchInst(endbb, gIR->scopebegin()); + if (gIR->func().finallys.back().ret) { + llvm::Value* retval = p->func().finallys.back().retval; + if (retval) { + retval = new llvm::LoadInst(retval,"tmp",p->scopebb()); + new llvm::ReturnInst(retval, p->scopebb()); + } + else { + new llvm::ReturnInst(p->scopebb()); + } + } + else if (!gIR->scopereturned()) { + new llvm::BranchInst(endbb, p->scopebb()); + } + + p->func().finallys.pop_back(); // rewrite the scope - gIR->scope() = IRScope(endbb,oldend); + p->scope() = IRScope(endbb,oldend); } ////////////////////////////////////////////////////////////////////////////// @@ -628,7 +651,7 @@ const llvm::Type* valtype = LLVM_DtoType(value->type); llvm::Value* valvar = new llvm::AllocaInst(keytype, "foreachval", p->topallocapoint()); - if (aggr->type->ty == Tsarray) + if (LLVM_DtoDType(aggr->type)->ty == Tsarray) { assert(llvm::isa(val->getType())); assert(llvm::isa(val->getType()->getContainedType(0))); @@ -686,7 +709,7 @@ body->toIR(p); p->loopbbs.pop_back(); - if (!p->scope().returned) + if (!p->scopereturned()) new llvm::BranchInst(nexbb, p->scopebb()); // end @@ -734,12 +757,29 @@ ////////////////////////////////////////////////////////////////////////////// +void WithStatement::toIR(IRState* p) +{ + Logger::println("WithStatement::toIR(): %s", toChars()); + LOG_SCOPE; + + assert(exp); + assert(body); + + elem* e = exp->toElem(p); + wthis->llvmValue = e->getValue(); + delete e; + + body->toIR(p); +} + +////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();} //STUBST(BreakStatement); //STUBST(ForStatement); -STUBST(WithStatement); +//STUBST(WithStatement); STUBST(SynchronizedStatement); //STUBST(ReturnStatement); //STUBST(ContinueStatement); diff -r fd5e8bbfcb25 -r 8b0e809563df gen/toir.c --- a/gen/toir.c Wed Oct 10 06:21:31 2007 +0200 +++ b/gen/toir.c Fri Oct 19 07:43:21 2007 +0200 @@ -12,12 +12,7 @@ #include #include -#include "llvm/Type.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Constants.h" -#include "llvm/Instructions.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/CallingConv.h" +#include "gen/llvm.h" #include "total.h" #include "init.h" @@ -60,7 +55,7 @@ vd->llvmValue = allocainst; // e->val = really needed?? - LLVM_DtoInitializer(vd->type, vd->init); + LLVM_DtoInitializer(vd->init); } } // struct declaration @@ -69,6 +64,17 @@ Logger::println("StructDeclaration"); s->toObjFile(); } + // function declaration + else if (FuncDeclaration* f = declaration->isFuncDeclaration()) + { + Logger::println("FuncDeclaration"); + f->toObjFile(); + } + // alias declaration + else if (AliasDeclaration* a = declaration->isAliasDeclaration()) + { + Logger::println("AliasDeclaration"); + } // unsupported declaration else { @@ -91,6 +97,10 @@ if (VarDeclaration* vd = var->isVarDeclaration()) { Logger::println("VarDeclaration"); + + // needed to take care of forward references of global variables + if (!vd->llvmTouched && vd->isDataseg()) + vd->toObjFile(); if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration()) { @@ -98,6 +108,7 @@ } // this must be a dollar expression or some other magic value + // or it could be a forward declaration of a global variable if (!vd->llvmValue) { // dollar @@ -109,19 +120,17 @@ e->val = new llvm::LoadInst(tmp,"tmp",p->scopebb()); e->type = elem::VAL; } - // magic - else + // typeinfo + else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration()) { - if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration()) - { - tid->toObjFile(); - e->mem = tid->llvmValue; - e->type = elem::VAR; - } - else { - Logger::println("unsupported: %s\n", vd->toChars()); - assert(0 && "only magic supported is typeinfo"); - } + tid->toObjFile(); + e->mem = tid->llvmValue; + e->type = elem::VAR; + } + // global forward ref + else { + Logger::println("unsupported: %s\n", vd->toChars()); + assert(0 && "only magic supported is typeinfo"); } return e; } @@ -134,7 +143,7 @@ e->type = elem::VAR; } else { - if (vd->type->ty == Tstruct || vd->type->ty == Tdelegate || vd->type->ty == Tarray) { + if (LLVM_DtoIsPassedByRef(vd->type)) { e->mem = vd->llvmValue; e->type = elem::VAR; } @@ -173,11 +182,10 @@ else if (SymbolDeclaration* sdecl = var->isSymbolDeclaration()) { // this seems to be the static initialiser for structs - Logger::print("Sym: type=%s\n", sdecl->type->toChars()); - assert(sdecl->type->ty == Tstruct); - //assert(sdecl->llvmInitZ); - //e->val = sdecl->llvmInitZ; - TypeStruct* ts = (TypeStruct*)sdecl->type; + Type* sdecltype = LLVM_DtoDType(sdecl->type); + 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; @@ -193,24 +201,52 @@ ////////////////////////////////////////////////////////////////////////////////////////// +llvm::Constant* VarExp::toConstElem(IRState* p) +{ + Logger::print("VarExp::toConstElem: %s | %s\n", toChars(), type->toChars()); + LOG_SCOPE; + if (SymbolDeclaration* sdecl = var->isSymbolDeclaration()) + { + // this seems to be the static initialiser for structs + Type* sdecltype = LLVM_DtoDType(sdecl->type); + Logger::print("Sym: type=%s\n", sdecltype->toChars()); + assert(sdecltype->ty == Tstruct); + TypeStruct* ts = (TypeStruct*)sdecltype; + assert(ts->sym->llvmInitZ); + return ts->sym->llvmInitZ; + } + assert(0 && "Only support const var exp is SymbolDeclaration"); + return NULL; +} + +////////////////////////////////////////////////////////////////////////////////////////// + elem* 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* IntegerExp::toConstElem(IRState* p) +{ + Logger::print("IntegerExp::toConstElem: %s | %s\n", toChars(), type->toChars()); + LOG_SCOPE; const llvm::Type* t = LLVM_DtoType(type); if (llvm::isa(t)) { llvm::Constant* i = llvm::ConstantInt::get(LLVM_DtoSize_t(),(uint64_t)value,false); - e->val = llvm::ConstantExpr::getIntToPtr(i, t); + return llvm::ConstantExpr::getIntToPtr(i, t); } else if (llvm::isa(t)) { - e->val = llvm::ConstantInt::get(t,(uint64_t)value,!type->isunsigned()); + return llvm::ConstantInt::get(t,(uint64_t)value,!type->isunsigned()); } - else { - assert(0); - } - e->type = elem::CONST; - return e; + assert(0); + return NULL; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -220,15 +256,24 @@ 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* RealExp::toConstElem(IRState* p) +{ + Logger::print("RealExp::toConstElem: %s | %s\n", toChars(), type->toChars()); + LOG_SCOPE; const llvm::Type* fty = LLVM_DtoType(type); if (type->ty == Tfloat32) - e->val = llvm::ConstantFP::get(fty,float(value)); + return llvm::ConstantFP::get(fty,float(value)); else if (type->ty == Tfloat64 || type->ty == Tfloat80) - e->val = llvm::ConstantFP::get(fty,double(value)); - else + return llvm::ConstantFP::get(fty,double(value)); assert(0); - e->type = elem::CONST; - return e; + return NULL; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -238,19 +283,28 @@ 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* NullExp::toConstElem(IRState* p) +{ + Logger::print("NullExp::toConstElem(type=%s): %s\n", type->toChars(),toChars()); + LOG_SCOPE; const llvm::Type* t = LLVM_DtoType(type); - if (type->ty == Tarray) { assert(llvm::isa(t)); - e->val = llvm::ConstantAggregateZero::get(t); + return llvm::ConstantAggregateZero::get(t); } - else - e->val = llvm::Constant::getNullValue(t); - assert(e->val); - - Logger::cout() << "null value is now " << *e->val << '\n'; - e->type = elem::NUL; - return e; + else { + return llvm::Constant::getNullValue(t); + } + assert(0); + return NULL; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -260,10 +314,12 @@ Logger::print("StringExp::toElem: %s | \n", toChars(), type->toChars()); LOG_SCOPE; - assert(type->next->ty == Tchar && "Only char is supported"); + Type* dtype = LLVM_DtoDType(type); + + assert(dtype->next->ty == Tchar && "Only char is supported"); assert(sz == 1); - const llvm::Type* ct = LLVM_DtoType(type->next); + const llvm::Type* ct = LLVM_DtoType(dtype->next); //printf("ct = %s\n", type->next->toChars()); const llvm::ArrayType* at = llvm::ArrayType::get(ct,len+1); @@ -276,22 +332,20 @@ llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,"stringliteral",gIR->module); llvm::ConstantInt* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); - //llvm::Value* arrptr = LLVM_DtoGEP(gvar,zero,zero,"tmp",p->scopebb()); llvm::Constant* idxs[2] = { zero, zero }; llvm::Constant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2); elem* e = new elem; - if (type->ty == Tarray) { + if (dtype->ty == Tarray) { llvm::Constant* clen = llvm::ConstantInt::get(LLVM_DtoSize_t(),len,false); - if (p->lvals.empty()) { + if (p->lvals.empty() || !p->toplval()) { e->type = elem::SLICE; e->arg = clen; e->mem = arrptr; return e; } - else { - llvm::Value* arr = p->toplval(); + else if (llvm::Value* arr = p->toplval()) { if (llvm::isa(arr)) { e->val = LLVM_DtoConstantSlice(clen, arrptr); } @@ -300,12 +354,14 @@ e->inplace = true; } } + else + assert(0); } - else if (type->ty == Tsarray) { + 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()); } - else if (type->ty == Tpointer) { + else if (dtype->ty == Tpointer) { e->mem = arrptr; } else { @@ -319,6 +375,42 @@ ////////////////////////////////////////////////////////////////////////////////////////// +llvm::Constant* StringExp::toConstElem(IRState* p) +{ + Logger::print("StringExp::toConstElem: %s | %s\n", toChars(), type->toChars()); + LOG_SCOPE; + + uint8_t* str = (uint8_t*)string; + std::string cont((char*)str, len); + + Type* t = LLVM_DtoDType(type); + + llvm::Constant* _init = llvm::ConstantArray::get(cont,true); + if (t->ty == Tsarray) { + return _init; + } + llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage; + llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_init->getType(),true,_linkage,_init,"stringliteral",gIR->module); + + llvm::ConstantInt* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); + llvm::Constant* idxs[2] = { zero, zero }; + llvm::Constant* arrptr = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2); + + if (t->ty == Tpointer) { + return arrptr; + } + + if (t->ty == Tarray) { + llvm::Constant* clen = llvm::ConstantInt::get(LLVM_DtoSize_t(),len,false); + return LLVM_DtoConstantSlice(clen, arrptr); + } + + assert(0); + return NULL; +} + +////////////////////////////////////////////////////////////////////////////////////////// + elem* AssignExp::toElem(IRState* p) { Logger::print("AssignExp::toElem: %s | %s = %s\n", toChars(), e1->type->toChars(), e2->type->toChars()); @@ -353,30 +445,33 @@ } //e->val = l->store(r->getValue()); - TY e1ty = e1->type->ty; - TY e2ty = e2->type->ty; + Type* e1type = LLVM_DtoDType(e1->type); + Type* e2type = LLVM_DtoDType(e2->type); + TY e1ty = e1type->ty; + TY e2ty = e2type->ty; elem* e = new elem; + e->type = elem::VAR; // struct if (e1ty == Tstruct) { + e->mem = l->mem; // struct + struct if (e2ty == Tstruct) { // struct literals do the assignment themselvs (in place) if (!r->inplace) { - TypeStruct* ts = (TypeStruct*)e2->type; - assert(r->mem); - LLVM_DtoStructCopy(ts,l->mem,r->mem); + TypeStruct* ts = (TypeStruct*)e2type; + LLVM_DtoStructCopy(ts,l->mem,r->getValue()); } else { e->inplace = true; } } // struct + const int - else if (e2->type->isintegral()){ + else if (e2type->isintegral()){ IntegerExp* iexp = (IntegerExp*)e2; assert(iexp->value == 0 && "Only integral struct initializer allowed is zero"); - TypeStruct* st = (TypeStruct*)e1->type; + TypeStruct* st = (TypeStruct*)e1type; LLVM_DtoStructZeroInit(st, l->mem); } // :x @@ -384,10 +479,10 @@ assert(0 && "struct = unknown"); } else if (e1ty == Tsarray) { - assert(0 && "static array = not supported"); + assert(0 && "static array not supported"); } else if (e1ty == Tarray) { - if (e2->type->isscalar() || e2->type->ty == Tclass){ + if (e2type->isscalar() || e2type->ty == Tclass){ LLVM_DtoArrayInit(l->mem, r->getValue()); } else if (e2ty == Tarray) { @@ -396,16 +491,24 @@ llvm::Constant* c = llvm::cast(r->val); assert(c->isNullValue()); LLVM_DtoNullArray(l->mem); + e->mem = l->mem; } else if (r->type == elem::SLICE) { - if (l->type == elem::SLICE) - LLVM_DtoArrayCopy(l,r); - else - LLVM_DtoSetArray(l->mem,r->arg,r->mem); + if (l->type == elem::SLICE) { + LLVM_DtoArrayCopy(l,r); + e->type = elem::SLICE; + e->mem = l->mem; + e->arg = l->arg; + } + else { + LLVM_DtoSetArray(l->mem,r->arg,r->mem); + e->mem = l->mem; + } } else { // new expressions write directly to the array reference // so do string literals + e->mem = l->mem; if (!r->inplace) { assert(r->mem); LLVM_DtoArrayAssign(l->mem, r->mem); @@ -419,6 +522,7 @@ assert(0); } else if (e1ty == Tpointer) { + e->mem = l->mem; if (e2ty == Tpointer) { llvm::Value* v = r->field ? r->mem : r->getValue(); Logger::cout() << "*=*: " << *v << ", " << *l->mem << '\n'; @@ -433,15 +537,17 @@ Logger::cout() << "tmp: " << *tmp << " ||| " << *l->mem << '\n'; // assignment to this in constructor special case if (l->isthis) { - FuncDeclaration* fdecl = p->funcdecls.back(); + FuncDeclaration* fdecl = p->func().decl; // respecify the this param if (!llvm::isa(fdecl->llvmThisVar)) fdecl->llvmThisVar = new llvm::AllocaInst(tmp->getType(), "newthis", p->topallocapoint()); new llvm::StoreInst(tmp, fdecl->llvmThisVar, p->scopebb()); + e->mem = fdecl->llvmThisVar; } // regular class ref -> class ref assignment else { new llvm::StoreInst(tmp, l->mem, p->scopebb()); + e->mem = l->mem; } } else @@ -454,6 +560,7 @@ llvm::Constant* c = llvm::cast(r->val); if (c->isNullValue()) { LLVM_DtoNullDelegate(l->mem); + e->mem = l->mem; } else assert(0); @@ -461,6 +568,7 @@ else if (r->inplace) { // do nothing e->inplace = true; + e->mem = l->mem; } else assert(0); @@ -472,10 +580,12 @@ else { Logger::cout() << *l->mem << '\n'; new llvm::StoreInst(r->getValue(),l->mem,p->scopebb()); + e->mem = l->mem; } delete r; delete l; + return e; } @@ -489,15 +599,19 @@ elem* l = e1->toElem(p); elem* r = e2->toElem(p); - if (e1->type != e2->type) { - if (e1->type->ty == Tpointer && e1->type->next->ty == Tstruct) { + Type* t = LLVM_DtoDType(type); + Type* e1type = LLVM_DtoDType(e1->type); + Type* e2type = LLVM_DtoDType(e2->type); + + 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); - TypeStruct* ts = (TypeStruct*)e1->type->next; + TypeStruct* ts = (TypeStruct*)e1type->next; std::vector offsets(1,0); - ts->sym->offsetToIndex(type->next, cofs->getZExtValue(), offsets); + ts->sym->offsetToIndex(t->next, cofs->getZExtValue(), offsets); e->mem = LLVM_DtoGEP(l->getValue(), offsets, "tmp", p->scopebb()); e->type = elem::VAR; e->field = true; @@ -529,9 +643,11 @@ elem* l = e1->toElem(p); elem* r = e2->toElem(p); + Type* e1type = LLVM_DtoDType(e1->type); + elem* e = new elem; llvm::Value* val = 0; - if (e1->type->ty == Tpointer) { + if (e1type->ty == Tpointer) { val = e->mem = new llvm::GetElementPtrInst(l->getValue(),r->getValue(),"tmp",p->scopebb()); } else { @@ -598,8 +714,10 @@ elem* l = e1->toElem(p); elem* r = e2->toElem(p); + Type* e1type = LLVM_DtoDType(e1->type); + llvm::Value* tmp = 0; - if (e1->type->ty == Tpointer) { + if (e1type->ty == Tpointer) { tmp = r->getValue(); llvm::Value* zero = llvm::ConstantInt::get(tmp->getType(),0,false); tmp = llvm::BinaryOperator::createSub(zero,tmp,"tmp",p->scopebb()); @@ -690,11 +808,13 @@ elem* l = e1->toElem(p); elem* r = e2->toElem(p); - if (type->isunsigned()) + Type* t = LLVM_DtoDType(type); + + if (t->isunsigned()) e->val = llvm::BinaryOperator::createUDiv(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else if (type->isintegral()) + else if (t->isintegral()) e->val = llvm::BinaryOperator::createSDiv(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else if (type->isfloating()) + else if (t->isfloating()) e->val = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb()); else assert(0); @@ -714,12 +834,14 @@ elem* l = e1->toElem(p); elem* r = e2->toElem(p); + Type* t = LLVM_DtoDType(type); + llvm::Value* tmp; - if (type->isunsigned()) + if (t->isunsigned()) tmp = llvm::BinaryOperator::createUDiv(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else if (type->isintegral()) + else if (t->isintegral()) tmp = llvm::BinaryOperator::createSDiv(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else if (type->isfloating()) + else if (t->isfloating()) tmp = llvm::BinaryOperator::createFDiv(l->getValue(),r->getValue(),"tmp",p->scopebb()); else assert(0); @@ -753,11 +875,13 @@ elem* l = e1->toElem(p); elem* r = e2->toElem(p); - if (type->isunsigned()) + Type* t = LLVM_DtoDType(type); + + if (t->isunsigned()) e->val = llvm::BinaryOperator::createURem(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else if (type->isintegral()) + else if (t->isintegral()) e->val = llvm::BinaryOperator::createSRem(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else if (type->isfloating()) + else if (t->isfloating()) e->val = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb()); else assert(0); @@ -777,12 +901,14 @@ elem* l = e1->toElem(p); elem* r = e2->toElem(p); + Type* t = LLVM_DtoDType(type); + llvm::Value* tmp; - if (type->isunsigned()) + if (t->isunsigned()) tmp = llvm::BinaryOperator::createURem(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else if (type->isintegral()) + else if (t->isintegral()) tmp = llvm::BinaryOperator::createSRem(l->getValue(),r->getValue(),"tmp",p->scopebb()); - else if (type->isfloating()) + else if (t->isfloating()) tmp = llvm::BinaryOperator::createFRem(l->getValue(),r->getValue(),"tmp",p->scopebb()); else assert(0); @@ -825,9 +951,11 @@ TypeFunction* tf = 0; + Type* e1type = LLVM_DtoDType(e1->type); + // regular functions - if (e1->type->ty == Tfunction) { - tf = (TypeFunction*)e1->type; + if (e1type->ty == Tfunction) { + tf = (TypeFunction*)e1type; if (tf->llvmRetInPtr) { retinptr = true; } @@ -835,10 +963,10 @@ } // delegates - else if (e1->type->ty == Tdelegate) { - Logger::println("delegateTy = %s\n", e1->type->toChars()); - assert(e1->type->next->ty == Tfunction); - tf = (TypeFunction*)e1->type->next; + else if (e1type->ty == Tdelegate) { + Logger::println("delegateTy = %s\n", e1type->toChars()); + assert(e1type->next->ty == Tfunction); + tf = (TypeFunction*)e1type->next; if (tf->llvmRetInPtr) { retinptr = true; } @@ -899,13 +1027,12 @@ llvm::FunctionType::param_iterator argiter = llfnty->param_begin(); int j = 0; - // hidden struct return parameter + // hidden struct return arguments if (retinptr) { if (!p->lvals.empty()) { assert(llvm::isa(p->toplval()->getType()->getContainedType(0))); llargs[j] = p->toplval(); - TY Dty = tf->next->ty; - if (Dty == Tstruct || Dty == Tdelegate || Dty == Tarray) { + if (LLVM_DtoIsPassedByRef(tf->next)) { e->inplace = true; } else @@ -922,7 +1049,7 @@ e->type = elem::VAL; } - // this parameter + // this arguments if (fn->arg) { Logger::println("This Call"); if (fn->arg->getType() != argiter->get()) { @@ -935,7 +1062,7 @@ ++j; ++argiter; } - // delegate context parameter + // delegate context arguments else if (delegateCall) { Logger::println("Delegate Call"); llvm::Value* contextptr = LLVM_DtoGEP(fn->mem,zero,zero,"tmp",p->scopebb()); @@ -944,75 +1071,11 @@ ++argiter; } - // regular parameters + // regular arguments for (int i=0; idim; i++,j++) { - Expression* argexp = (Expression*)arguments->data[i]; - elem* arg = argexp->toElem(p); - if (arg->inplace) { - assert(arg->mem); - llargs[j] = arg->mem; - continue; - } - Argument* fnarg = Argument::getNth(tf->parameters, i); - - TY argty = argexp->type->ty; - if (argty == Tstruct || argty == Tdelegate || argty == Tarray) { - if (!fnarg || !fnarg->llvmCopy) { - llargs[j] = arg->getValue(); - assert(llargs[j] != 0); - } - else { - llvm::Value* allocaInst = 0; - llvm::BasicBlock* entryblock = &p->topfunc()->front(); - const llvm::PointerType* pty = llvm::cast(arg->mem->getType()); - if (argty == Tstruct) { - allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", p->topallocapoint()); - TypeStruct* ts = (TypeStruct*)argexp->type; - LLVM_DtoStructCopy(ts,allocaInst,arg->mem); - } - else if (argty == Tdelegate) { - allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", p->topallocapoint()); - LLVM_DtoDelegateCopy(allocaInst,arg->mem); - } - else if (argty == Tarray) { - if (arg->type == elem::SLICE) { - allocaInst = new llvm::AllocaInst(LLVM_DtoType(argexp->type), "tmpparam", p->topallocapoint()); - LLVM_DtoSetArray(allocaInst, arg->arg, arg->mem); - } - else { - allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", p->topallocapoint()); - LLVM_DtoArrayAssign(allocaInst,arg->mem); - } - } - else - assert(0); - - llargs[j] = allocaInst; - assert(llargs[j] != 0); - } - } - else if (!fnarg || fnarg->llvmCopy) { - Logger::println("regular arg"); - assert(arg->type != elem::SLICE); - llargs[j] = arg->arg ? arg->arg : arg->getValue(); - assert(llargs[j] != 0); - } - else { - Logger::println("as ptr arg"); - llargs[j] = arg->mem ? arg->mem : arg->val; - if (llargs[j]->getType() != llfnty->getParamType(j)) - { - assert(llargs[j]->getType() == llfnty->getParamType(j)->getContainedType(0)); - LLVM_DtoGiveArgumentStorage(arg); - new llvm::StoreInst(llargs[j], arg->mem, p->scopebb()); - llargs[j] = arg->mem; - } - assert(llargs[j] != 0); - } - - delete arg; + llargs[j] = LLVM_DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]); } // void returns cannot not be named @@ -1053,37 +1116,38 @@ LOG_SCOPE; elem* e = new elem; elem* u = e1->toElem(p); - const llvm::Type* totype = LLVM_DtoType(to); - Type* from = e1->type; - int lsz = from->size(); - int rsz = to->size(); + const llvm::Type* tolltype = LLVM_DtoType(to); + Type* fromtype = LLVM_DtoDType(e1->type); + Type* totype = LLVM_DtoDType(to); + int lsz = fromtype->size(); + int rsz = totype->size(); // this makes sure the strange lvalue casts don't screw things up e->mem = u->mem; - if (from->isintegral()) { - if (to->isintegral()) { + if (fromtype->isintegral()) { + if (totype->isintegral()) { if (lsz < rsz) { - Logger::cout() << *totype << '\n'; - if (from->isunsigned() || from->ty == Tbool) { - e->val = new llvm::ZExtInst(u->getValue(), totype, "tmp", p->scopebb()); + Logger::cout() << *tolltype << '\n'; + if (fromtype->isunsigned() || fromtype->ty == Tbool) { + e->val = new llvm::ZExtInst(u->getValue(), tolltype, "tmp", p->scopebb()); } else { - e->val = new llvm::SExtInst(u->getValue(), totype, "tmp", p->scopebb()); + e->val = new llvm::SExtInst(u->getValue(), tolltype, "tmp", p->scopebb()); } } else if (lsz > rsz) { - e->val = new llvm::TruncInst(u->getValue(), totype, "tmp", p->scopebb()); + e->val = new llvm::TruncInst(u->getValue(), tolltype, "tmp", p->scopebb()); } else { - e->val = new llvm::BitCastInst(u->getValue(), totype, "tmp", p->scopebb()); + e->val = new llvm::BitCastInst(u->getValue(), tolltype, "tmp", p->scopebb()); } } - else if (to->isfloating()) { - if (from->isunsigned()) { - e->val = new llvm::UIToFPInst(u->getValue(), totype, "tmp", p->scopebb()); + else if (totype->isfloating()) { + if (fromtype->isunsigned()) { + e->val = new llvm::UIToFPInst(u->getValue(), tolltype, "tmp", p->scopebb()); } else { - e->val = new llvm::SIToFPInst(u->getValue(), totype, "tmp", p->scopebb()); + e->val = new llvm::SIToFPInst(u->getValue(), tolltype, "tmp", p->scopebb()); } } else { @@ -1092,27 +1156,27 @@ //e->storeVal = u->storeVal ? u->storeVal : u->val; e->type = elem::VAL; } - else if (from->isfloating()) { - if (to->isfloating()) { - if ((from->ty == Tfloat80 || from->ty == Tfloat64) && (to->ty == Tfloat80 || to->ty == Tfloat64)) { + else if (fromtype->isfloating()) { + if (totype->isfloating()) { + if ((fromtype->ty == Tfloat80 || fromtype->ty == Tfloat64) && (totype->ty == Tfloat80 || totype->ty == Tfloat64)) { e->val = u->getValue(); } else if (lsz < rsz) { - e->val = new llvm::FPExtInst(u->getValue(), totype, "tmp", p->scopebb()); + e->val = new llvm::FPExtInst(u->getValue(), tolltype, "tmp", p->scopebb()); } else if (lsz > rsz) { - e->val = new llvm::FPTruncInst(u->getValue(), totype, "tmp", p->scopebb()); + e->val = new llvm::FPTruncInst(u->getValue(), tolltype, "tmp", p->scopebb()); } else { assert(0); } } - else if (to->isintegral()) { - if (to->isunsigned()) { - e->val = new llvm::FPToUIInst(u->getValue(), totype, "tmp", p->scopebb()); + else if (totype->isintegral()) { + if (totype->isunsigned()) { + e->val = new llvm::FPToUIInst(u->getValue(), tolltype, "tmp", p->scopebb()); } else { - e->val = new llvm::FPToSIInst(u->getValue(), totype, "tmp", p->scopebb()); + e->val = new llvm::FPToSIInst(u->getValue(), tolltype, "tmp", p->scopebb()); } } else { @@ -1120,26 +1184,26 @@ } e->type = elem::VAL; } - else if (from->ty == Tclass) { + else if (fromtype->ty == Tclass) { //assert(to->ty == Tclass); - e->val = new llvm::BitCastInst(u->getValue(), totype, "tmp", p->scopebb()); + e->val = new llvm::BitCastInst(u->getValue(), tolltype, "tmp", p->scopebb()); e->type = elem::VAL; } - else if (from->ty == Tarray || from->ty == Tsarray) { + else if (fromtype->ty == Tarray || fromtype->ty == Tsarray) { Logger::cout() << "from array or sarray" << '\n'; - if (to->ty == Tpointer) { + if (totype->ty == Tpointer) { Logger::cout() << "to pointer" << '\n'; - assert(from->next == to->next); + assert(fromtype->next == totype->next); 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 = LLVM_DtoGEP(u->getValue(),zero,one,"tmp",p->scopebb()); e->val = new llvm::LoadInst(ptr, "tmp", p->scopebb()); e->type = elem::VAL; } - else if (to->ty == Tarray) { + else if (totype->ty == Tarray) { Logger::cout() << "to array" << '\n'; - assert(from->next->size() == to->next->size()); - const llvm::Type* ptrty = LLVM_DtoType(to->next); + assert(fromtype->next->size() == totype->next->size()); + const llvm::Type* ptrty = LLVM_DtoType(totype->next); if (ptrty == llvm::Type::VoidTy) ptrty = llvm::Type::Int8Ty; ptrty = llvm::PointerType::get(ptrty); @@ -1150,7 +1214,7 @@ } else { llvm::Value* uval = u->getValue(); - if (from->ty == Tsarray) { + 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)); @@ -1171,7 +1235,7 @@ } e->type = elem::SLICE; } - else if (to->ty == Tsarray) { + else if (totype->ty == Tsarray) { Logger::cout() << "to sarray" << '\n'; assert(0); } @@ -1179,14 +1243,14 @@ assert(0); } } - else if (from->ty == Tpointer) { - if (to->ty == Tpointer || to->ty == Tclass) { + else if (fromtype->ty == Tpointer) { + if (totype->ty == Tpointer || totype->ty == Tclass) { llvm::Value* src = u->getValue(); //Logger::cout() << *src << '|' << *totype << '\n'; - e->val = new llvm::BitCastInst(src, totype, "tmp", p->scopebb()); + e->val = new llvm::BitCastInst(src, tolltype, "tmp", p->scopebb()); } - else if (to->isintegral()) { - e->val = new llvm::PtrToIntInst(u->getValue(), totype, "tmp", p->scopebb()); + else if (totype->isintegral()) { + e->val = new llvm::PtrToIntInst(u->getValue(), tolltype, "tmp", p->scopebb()); } else assert(0); @@ -1210,18 +1274,20 @@ { Logger::println("VarDeclaration"); assert(vd->llvmValue); - if (vd->type->ty == Tstruct && !(type->ty == Tpointer && type->next == vd->type)) { - TypeStruct* vdt = (TypeStruct*)vd->type; + Type* t = LLVM_DtoDType(type); + Type* vdtype = LLVM_DtoDType(vd->type); + if (vdtype->ty == Tstruct && !(t->ty == Tpointer && t->next == vdtype)) { + TypeStruct* vdt = (TypeStruct*)vdtype; e = new elem; std::vector dst(1,0); - vdt->sym->offsetToIndex(type->next, offset, dst); + vdt->sym->offsetToIndex(t->next, offset, dst); llvm::Value* ptr = vd->llvmValue; assert(ptr); e->mem = LLVM_DtoGEP(ptr,dst,"tmp",p->scopebb()); e->type = elem::VAL; e->field = true; } - else if (vd->type->ty == Tsarray) { + else if (vdtype->ty == Tsarray) { /*e = new elem; llvm::Value* idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); e->val = new llvm::GetElementPtrInst(vd->llvmValue,idx0,idx0,"tmp",p->scopebb());*/ @@ -1294,26 +1360,30 @@ elem* l = e1->toElem(p); - Logger::print("e1->type=%s\n", e1->type->toChars()); + Type* t = LLVM_DtoDType(type); + Type* e1type = LLVM_DtoDType(e1->type); + + Logger::print("e1->type=%s\n", e1type->toChars()); if (VarDeclaration* vd = var->isVarDeclaration()) { std::vector vdoffsets(1,0); llvm::Value* src = 0; - if (e1->type->ty == Tpointer) { - assert(e1->type->next->ty == Tstruct); - TypeStruct* ts = (TypeStruct*)e1->type->next; + if (e1type->ty == Tpointer) { + assert(e1type->next->ty == Tstruct); + TypeStruct* ts = (TypeStruct*)e1type->next; ts->sym->offsetToIndex(vd->type, vd->offset, vdoffsets); Logger::println("Struct member offset:%d", vd->offset); src = l->val ? l->val : l->mem; } else if (e1->type->ty == Tclass) { - TypeClass* tc = (TypeClass*)e1->type; + TypeClass* tc = (TypeClass*)e1type; Logger::println("Class member offset: %d", vd->offset); tc->sym->offsetToIndex(vd->type, vd->offset, vdoffsets); src = l->getValue(); } assert(vdoffsets.size() != 1); assert(src != 0); + Logger::cout() << "src: " << *src << '\n'; llvm::Value* arrptr = LLVM_DtoGEP(src,vdoffsets,"tmp",p->scopebb()); e->mem = arrptr; Logger::cout() << "mem: " << *e->mem << '\n'; @@ -1332,7 +1402,7 @@ // virtual call if (fdecl->isVirtual()) { assert(fdecl->vtblIndex > 0); - assert(e1->type->ty == Tclass); + assert(e1type->ty == Tclass); 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); @@ -1365,22 +1435,7 @@ elem* e = new elem; if (VarDeclaration* vd = var->isVarDeclaration()) { - /*assert(vd->llvmValue == 0); - - llvm::Function* fn = p->topfunc(); - assert(fn); - - TypeFunction* tf = p->topfunctype(); - assert(tf); - - llvm::Value* v = 0; - if (tf->llvmRetInPtr) - v = ++fn->arg_begin(); - else - v = fn->arg_begin(); - assert(v);*/ - - llvm::Value* v = p->funcdecls.back()->llvmThisVar; + llvm::Value* v = p->func().decl->llvmThisVar; if (llvm::isa(v)) v = new llvm::LoadInst(v, "tmp", p->scopebb()); e->mem = v; @@ -1440,15 +1495,22 @@ Expression* vx = (Expression*)elements->data[i]; if (vx != 0) { + p->lvals.push_back(arrptr); elem* ve = vx->toElem(p); - llvm::Value* val = ve->getValue(); - Logger::cout() << *val << " | " << *arrptr << '\n'; - if (vx->type->ty == Tstruct) { - TypeStruct* ts = (TypeStruct*)vx->type; - LLVM_DtoStructCopy(ts,arrptr,val); + p->lvals.pop_back(); + + if (!ve->inplace) { + llvm::Value* val = ve->getValue(); + Logger::cout() << *val << " | " << *arrptr << '\n'; + + Type* vxtype = LLVM_DtoDType(vx->type); + if (vxtype->ty == Tstruct) { + TypeStruct* ts = (TypeStruct*)vxtype; + LLVM_DtoStructCopy(ts,arrptr,val); + } + else + new llvm::StoreInst(val, arrptr, p->scopebb()); } - else - new llvm::StoreInst(val, arrptr, p->scopebb()); delete ve; } else { @@ -1463,6 +1525,28 @@ ////////////////////////////////////////////////////////////////////////////////////////// +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(LLVM_DtoDType(type)->ty == Tstruct); + const llvm::Type* t = LLVM_DtoType(type); + const llvm::StructType* st = llvm::cast(t); + return llvm::ConstantStruct::get(st,vals); +} + +////////////////////////////////////////////////////////////////////////////////////////// + elem* IndexExp::toElem(IRState* p) { Logger::print("IndexExp::toElem: %s | %s\n", toChars(), type->toChars()); @@ -1472,6 +1556,8 @@ elem* l = e1->toElem(p); + Type* e1type = LLVM_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.pop_back(); @@ -1480,13 +1566,13 @@ llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false); llvm::Value* arrptr = 0; - if (e1->type->ty == Tpointer) { + if (e1type->ty == Tpointer) { arrptr = new llvm::GetElementPtrInst(l->getValue(),r->getValue(),"tmp",p->scopebb()); } - else if (e1->type->ty == Tsarray) { - arrptr = LLVM_DtoGEP(l->mem, zero, r->getValue(),"tmp",p->scopebb()); + else if (e1type->ty == Tsarray) { + arrptr = LLVM_DtoGEP(l->getValue(), zero, r->getValue(),"tmp",p->scopebb()); } - else if (e1->type->ty == Tarray) { + else if (e1type->ty == Tarray) { arrptr = LLVM_DtoGEP(l->mem,zero,one,"tmp",p->scopebb()); arrptr = new llvm::LoadInst(arrptr,"tmp",p->scopebb()); arrptr = new llvm::GetElementPtrInst(arrptr,r->getValue(),"tmp",p->scopebb()); @@ -1510,6 +1596,7 @@ LOG_SCOPE; elem* v = e1->toElem(p); + Type* e1type = LLVM_DtoDType(e1->type); elem* e = new elem; assert(v->mem); @@ -1531,13 +1618,16 @@ assert(lo->val); assert(llvm::isa(lo->val)); - if (e1->type->ty == Tpointer) { + if (e1type->ty == Tpointer) { e->mem = v->getValue(); } - else if (e1->type->ty == Tarray) { + else if (e1type->ty == Tarray) { llvm::Value* tmp = LLVM_DtoGEP(v->mem,zero,one,"tmp",p->scopebb()); e->mem = new llvm::LoadInst(tmp,"tmp",p->scopebb()); } + else if (e1type->ty == Tsarray) { + e->mem = LLVM_DtoGEP(v->mem,zero,zero,"tmp",p->scopebb()); + } else assert(e->mem); @@ -1548,9 +1638,16 @@ } else { - llvm::Value* tmp = LLVM_DtoGEP(v->mem,zero,one,"tmp",p->scopebb()); - tmp = new llvm::LoadInst(tmp,"tmp",p->scopebb()); - e->mem = new llvm::GetElementPtrInst(tmp,lo->getValue(),"tmp",p->scopebb()); + if (e1type->ty == Tarray) { + llvm::Value* tmp = LLVM_DtoGEP(v->mem,zero,one,"tmp",p->scopebb()); + tmp = new llvm::LoadInst(tmp,"tmp",p->scopebb()); + e->mem = new llvm::GetElementPtrInst(tmp,lo->getValue(),"tmp",p->scopebb()); + } + else if (e1type->ty == Tsarray) { + e->mem = LLVM_DtoGEP(v->mem,zero,lo->getValue(),"tmp",p->scopebb()); + } + else + assert(0); } elem* up = upr->toElem(p); @@ -1610,31 +1707,54 @@ elem* l = e1->toElem(p); elem* r = e2->toElem(p); - assert(e1->type == e2->type); - - Type* t = e1->type; + Type* t = LLVM_DtoDType(e1->type); + Type* e2t = LLVM_DtoDType(e2->type); + assert(t == e2t); if (t->isintegral()) { llvm::ICmpInst::Predicate cmpop; + bool skip = false; switch(op) { case TOKlt: + case TOKul: cmpop = t->isunsigned() ? llvm::ICmpInst::ICMP_ULT : llvm::ICmpInst::ICMP_SLT; break; case TOKle: + case TOKule: cmpop = t->isunsigned() ? llvm::ICmpInst::ICMP_ULE : llvm::ICmpInst::ICMP_SLE; break; case TOKgt: + case TOKug: cmpop = t->isunsigned() ? llvm::ICmpInst::ICMP_UGT : llvm::ICmpInst::ICMP_SGT; break; case TOKge: + case TOKuge: cmpop = t->isunsigned() ? llvm::ICmpInst::ICMP_UGE : llvm::ICmpInst::ICMP_SGE; break; + case TOKue: + cmpop = llvm::ICmpInst::ICMP_EQ; + break; + case TOKlg: + cmpop = llvm::ICmpInst::ICMP_NE; + break; + case TOKleg: + skip = true; + e->val = llvm::ConstantInt::getTrue(); + break; + case TOKunord: + skip = true; + e->val = llvm::ConstantInt::getFalse(); + break; + default: assert(0); } - e->val = new llvm::ICmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb()); + if (!skip) + { + e->val = new llvm::ICmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb()); + } } else if (t->isfloating()) { @@ -1696,9 +1816,9 @@ elem* l = e1->toElem(p); elem* r = e2->toElem(p); - assert(e1->type == e2->type); - - Type* t = e1->type; + Type* t = LLVM_DtoDType(e1->type); + Type* e2t = LLVM_DtoDType(e2->type); + assert(t == e2t); if (t->isintegral() || t->ty == Tpointer) { @@ -1732,10 +1852,13 @@ } e->val = new llvm::FCmpInst(cmpop, l->getValue(), r->getValue(), "tmp", p->scopebb()); } + else if (t->ty == Tsarray) + { + e->val = LLVM_DtoStaticArrayCompare(op,l->mem,r->mem); + } else if (t->ty == Tarray) { - // array comparison invokes the typeinfo runtime - assert(0); + assert(0 && "array comparison invokes the typeinfo runtime"); } else { @@ -1768,10 +1891,13 @@ llvm::Value* val = e->val; llvm::Value* post = 0; - if (e1->type->isintegral()) + Type* e1type = LLVM_DtoDType(e1->type); + Type* e2type = LLVM_DtoDType(e2->type); + + if (e1type->isintegral()) { - assert(e2->type->isintegral()); - llvm::Value* one = llvm::ConstantInt::get(val->getType(), 1, !e2->type->isunsigned()); + assert(e2type->isintegral()); + llvm::Value* one = llvm::ConstantInt::get(val->getType(), 1, !e2type->isunsigned()); if (op == TOKplusplus) { post = llvm::BinaryOperator::createAdd(val,one,"tmp",p->scopebb()); } @@ -1779,17 +1905,17 @@ post = llvm::BinaryOperator::createSub(val,one,"tmp",p->scopebb()); } } - else if (e1->type->ty == Tpointer) + else if (e1type->ty == Tpointer) { - assert(e2->type->isintegral()); + assert(e2type->isintegral()); llvm::Constant* minusone = llvm::ConstantInt::get(LLVM_DtoSize_t(),(uint64_t)-1,true); llvm::Constant* plusone = llvm::ConstantInt::get(LLVM_DtoSize_t(),(uint64_t)1,false); llvm::Constant* whichone = (op == TOKplusplus) ? plusone : minusone; post = new llvm::GetElementPtrInst(val, whichone, "tmp", p->scopebb()); } - else if (e1->type->isfloating()) + else if (e1type->isfloating()) { - assert(e2->type->isfloating()); + assert(e2type->isfloating()); llvm::Value* one = llvm::ConstantFP::get(val->getType(), 1.0f); if (op == TOKplusplus) { post = llvm::BinaryOperator::createAdd(val,one,"tmp",p->scopebb()); @@ -1820,28 +1946,28 @@ assert(!thisexp); assert(!newargs); assert(newtype); - //assert(!arguments); - //assert(!member); assert(!allocator); elem* e = new elem; - const llvm::Type* t = LLVM_DtoType(newtype); + Type* ntype = LLVM_DtoDType(newtype); + + const llvm::Type* t = LLVM_DtoType(ntype); if (onstack) { - assert(newtype->ty == Tclass); + assert(ntype->ty == Tclass); e->mem = new llvm::AllocaInst(t->getContainedType(0),"tmp",p->topallocapoint()); } else { - if (newtype->ty == Tclass) { + if (ntype->ty == Tclass) { e->mem = new llvm::MallocInst(t->getContainedType(0),"tmp",p->scopebb()); } - else if (newtype->ty == Tarray) { + else if (ntype->ty == Tarray) { assert(arguments); if (arguments->dim == 1) { elem* sz = ((Expression*)arguments->data[0])->toElem(p); llvm::Value* dimval = sz->getValue(); - LLVM_DtoNewDynArray(p->toplval(), dimval, newtype->next); + LLVM_DtoNewDynArray(p->toplval(), dimval, ntype->next); delete sz; } else { @@ -1853,32 +1979,32 @@ } } - if (newtype->ty == Tclass) { + if (ntype->ty == Tclass) { // first apply the static initializer assert(e->mem); - LLVM_DtoInitClass((TypeClass*)newtype, e->mem); + LLVM_DtoInitClass((TypeClass*)ntype, e->mem); // then call constructor if (arguments) { + assert(member); + assert(member->llvmValue); + llvm::Function* fn = llvm::cast(member->llvmValue); + TypeFunction* tf = (TypeFunction*)LLVM_DtoDType(member->type); + std::vector ctorargs; ctorargs.push_back(e->mem); for (size_t i=0; idim; ++i) { Expression* ex = (Expression*)arguments->data[i]; - Logger::println("arg=%s", ex->toChars()); - elem* exe = ex->toElem(p); - llvm::Value* v = exe->getValue(); - assert(v); - ctorargs.push_back(v); - delete exe; + Argument* fnarg = Argument::getNth(tf->parameters, i); + llvm::Value* a = LLVM_DtoArgument(fn->getFunctionType()->getParamType(i+1), fnarg, ex); + ctorargs.push_back(a); } - assert(member); - assert(member->llvmValue); - e->mem = new llvm::CallInst(member->llvmValue, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb()); + e->mem = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb()); } } - else if (newtype->ty == Tstruct) { - TypeStruct* ts = (TypeStruct*)newtype; + else if (ntype->ty == Tstruct) { + TypeStruct* ts = (TypeStruct*)ntype; if (ts->isZeroInit()) { LLVM_DtoStructZeroInit(ts,e->mem); } @@ -1909,7 +2035,9 @@ const llvm::Type* t = val->getType(); llvm::Constant* z = llvm::Constant::getNullValue(t); - if (e1->type->ty == Tpointer) { + Type* e1type = LLVM_DtoDType(e1->type); + + if (e1type->ty == Tpointer) { ldval = v->getValue(); new llvm::FreeInst(ldval, p->scopebb()); @@ -1917,8 +2045,8 @@ Logger::cout() << *val << '\n'; new llvm::StoreInst(z, v->mem, p->scopebb()); } - else if (e1->type->ty == Tclass) { - TypeClass* tc = (TypeClass*)e1->type; + else if (e1type->ty == Tclass) { + TypeClass* tc = (TypeClass*)e1type; LLVM_DtoCallClassDtors(tc, val); if (v->vardecl && !v->vardecl->onstack) { @@ -1926,7 +2054,7 @@ } new llvm::StoreInst(z, v->mem, p->scopebb()); } - else if (e1->type->ty == Tarray) { + else if (e1type->ty == Tarray) { // must be on the heap (correct?) ldval = v->getValue(); @@ -2007,7 +2135,8 @@ llvm::Value* b = LLVM_DtoBoolean(u->getValue()); llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int1Ty, 0, true); - e->val = new llvm::ICmpInst(llvm::ICmpInst::ICMP_EQ,b,zero,"tmp",p->scopebb()); + 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; delete u; @@ -2151,7 +2280,7 @@ llvm::Value* loca = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false); LLVM_DtoAssert(llvm::ConstantInt::getFalse(), loca, NULL); - //new llvm::UnreachableInst(p->scopebb()); + new llvm::UnreachableInst(p->scopebb()); return 0; } @@ -2305,13 +2434,15 @@ llvm::Value* val = l->getValue(); delete l; + Type* t = LLVM_DtoDType(type); + llvm::Value* zero = 0; - if (type->isintegral()) + if (t->isintegral()) zero = llvm::ConstantInt::get(val->getType(), 0, true); - else if (type->isfloating()) { - if (type->ty == Tfloat32) + else if (t->isfloating()) { + if (t->ty == Tfloat32) zero = llvm::ConstantFP::get(val->getType(), float(0)); - else if (type->ty == Tfloat64 || type->ty == Tfloat80) + else if (t->ty == Tfloat64 || t->ty == Tfloat80) zero = llvm::ConstantFP::get(val->getType(), double(0)); else assert(0); @@ -2332,7 +2463,7 @@ Logger::print("CatExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - assert(0 && "array concatenation is not yet implemented"); + assert(0 && "array cat is not yet implemented"); elem* lhs = e1->toElem(p); elem* rhs = e2->toElem(p); @@ -2347,6 +2478,93 @@ ////////////////////////////////////////////////////////////////////////////////////////// +elem* CatAssignExp::toElem(IRState* p) +{ + Logger::print("CatAssignExp::toElem: %s | %s\n", toChars(), type->toChars()); + LOG_SCOPE; + + elem* l = e1->toElem(p); + assert(l->mem); + + Type* e1type = LLVM_DtoDType(e1->type); + Type* elemtype = LLVM_DtoDType(e1type->next); + Type* e2type = LLVM_DtoDType(e2->type); + + if (e2type == elemtype) { + LLVM_DtoCatArrayElement(l->mem,e2); + } + else + assert(0 && "only one element at a time right now"); + + return 0; +} + +////////////////////////////////////////////////////////////////////////////////////////// + +elem* ArrayLiteralExp::toElem(IRState* p) +{ + Logger::print("ArrayLiteralExp::toElem: %s | %s\n", toChars(), type->toChars()); + LOG_SCOPE; + + const llvm::Type* t = LLVM_DtoType(type); + Logger::cout() << "array literal has llvm type: " << *t << '\n'; + + llvm::Value* mem = 0; + if (p->lvals.empty()) { + assert(LLVM_DtoDType(type)->ty == Tsarray); + mem = new llvm::AllocaInst(t,"tmparrayliteral",p->topallocapoint()); + } + else { + mem = p->toplval(); + if (!llvm::isa(mem->getType()) || + !llvm::isa(mem->getType()->getContainedType(0))) + { + error("TODO array literals can currently only be used to initialise static arrays"); + fatal(); + } + } + + for (unsigned i=0; idim; ++i) + { + Expression* expr = (Expression*)elements->data[i]; + llvm::Value* elemAddr = LLVM_DtoGEPi(mem,0,i,"tmp",p->scopebb()); + elem* e = expr->toElem(p); + new llvm::StoreInst(e->getValue(), elemAddr, p->scopebb()); + } + + elem* e = new elem; + e->mem = mem; + e->type = elem::VAL; + e->inplace = true; + + return e; +} + +////////////////////////////////////////////////////////////////////////////////////////// + +llvm::Constant* ArrayLiteralExp::toConstElem(IRState* p) +{ + Logger::print("ArrayLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars()); + LOG_SCOPE; + + const llvm::Type* t = LLVM_DtoType(type); + Logger::cout() << "array literal has llvm type: " << *t << '\n'; + assert(llvm::isa(t)); + const llvm::ArrayType* arrtype = llvm::cast(t); + + assert(arrtype->getNumElements() == elements->dim); + std::vector vals(elements->dim, NULL); + for (unsigned i=0; idim; ++i) + { + Expression* expr = (Expression*)elements->data[i]; + vals[i] = expr->toConstElem(p); + } + + return llvm::ConstantArray::get(arrtype, vals); +} + +////////////////////////////////////////////////////////////////////////////////////////// + #define STUB(x) elem *x::toElem(IRState * p) {error("Exp type "#x" not implemented: %s", toChars()); fatal(); return 0; } //STUB(IdentityExp); //STUB(CondExp); @@ -2374,7 +2592,7 @@ //STUB(ModExp); //STUB(ModAssignExp); //STUB(CatExp); -STUB(CatAssignExp); +//STUB(CatAssignExp); //STUB(AddExp); //STUB(AddAssignExp); STUB(Expression); @@ -2417,10 +2635,21 @@ //STUB(ArrayLengthExp); //STUB(HaltExp); STUB(RemoveExp); -STUB(ArrayLiteralExp); +//STUB(ArrayLiteralExp); STUB(AssocArrayLiteralExp); //STUB(StructLiteralExp); +#define CONSTSTUB(x) llvm::Constant* x::toConstElem(IRState * p) {error("const Exp type "#x" not implemented: '%s' type: '%s'", toChars(), type->toChars()); assert(0); fatal(); return NULL; } +CONSTSTUB(Expression); +//CONSTSTUB(IntegerExp); +//CONSTSTUB(RealExp); +//CONSTSTUB(NullExp); +//CONSTSTUB(StringExp); +//CONSTSTUB(VarExp); +//CONSTSTUB(ArrayLiteralExp); +CONSTSTUB(AssocArrayLiteralExp); +//CONSTSTUB(StructLiteralExp); + unsigned Type::totym() { return 0; } type * Type::toCtype() diff -r fd5e8bbfcb25 -r 8b0e809563df gen/tollvm.c --- a/gen/tollvm.c Wed Oct 10 06:21:31 2007 +0200 +++ b/gen/tollvm.c Fri Oct 19 07:43:21 2007 +0200 @@ -1,11 +1,6 @@ #include -#include "llvm/Constants.h" -#include "llvm/Type.h" -#include "llvm/DerivedTypes.h" -#include "llvm/GlobalValue.h" -#include "llvm/Instructions.h" -#include "llvm/CallingConv.h" +#include "gen/llvm.h" #include "mtype.h" #include "dsymbol.h" @@ -20,6 +15,29 @@ #include "gen/elem.h" #include "gen/arrays.h" +bool LLVM_DtoIsPassedByRef(Type* type) +{ + TY t = type->ty; + if (t == Tstruct || t == Tarray || t == Tdelegate) + return true; + else if (t == Ttypedef) { + Type* bt = type->toBasetype(); + assert(bt); + return LLVM_DtoIsPassedByRef(bt); + } + return false; +} + +Type* LLVM_DtoDType(Type* t) +{ + if (t->ty == Ttypedef) { + Type* bt = t->toBasetype(); + assert(bt); + return LLVM_DtoDType(bt); + } + return t; +} + const llvm::Type* LLVM_DtoType(Type* t) { assert(t); @@ -167,9 +185,7 @@ const llvm::Type* rettype; std::vector paramvec; - TY retty = f->next->ty; - - if (retty == Tstruct || retty == Tdelegate || retty == Tarray) { + if (LLVM_DtoIsPassedByRef(f->next)) { rettype = llvm::PointerType::get(LLVM_DtoType(f->next)); paramvec.push_back(rettype); rettype = llvm::Type::VoidTy; @@ -225,7 +241,7 @@ actualRettype = rettype; } else if (rt) { - if (rt->ty == Tstruct || rt->ty == Tdelegate || rt->ty == Tarray) { + if (LLVM_DtoIsPassedByRef(rt)) { rettype = llvm::PointerType::get(LLVM_DtoType(rt)); actualRettype = llvm::Type::VoidTy; f->llvmRetInPtr = retinptr = true; @@ -265,7 +281,7 @@ for (int i=0; i < n; ++i) { Argument* arg = Argument::getNth(f->parameters, i); // ensure scalar - Type* argT = arg->type; + Type* argT = LLVM_DtoDType(arg->type); assert(argT); if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) { @@ -286,6 +302,16 @@ //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0))); paramvec.push_back(llvm::PointerType::get(at)); } + else if (llvm::isa(at)) { + Logger::println("opaque param"); + if (argT->ty == Tstruct || argT->ty == Tclass) + paramvec.push_back(llvm::PointerType::get(at)); + else + assert(0); + } + /*if (llvm::isa(at) || argT->ty == Tstruct || argT->ty == Tsarray) { + paramvec.push_back(llvm::PointerType::get(at)); + }*/ else { if (!arg->llvmCopy) { Logger::println("ref param"); @@ -453,7 +479,7 @@ } ////////////////////////////////////////////////////////////////////////////////////////// -llvm::Constant* LLVM_DtoStructInitializer(StructInitializer* si) +llvm::Constant* LLVM_DtoConstStructInitializer(StructInitializer* si) { llvm::StructType* structtype = llvm::cast(si->ad->llvmType); size_t n = structtype->getNumElements(); @@ -468,11 +494,12 @@ assert(ini); VarDeclaration* vd = (VarDeclaration*)si->vars.data[i]; + Type* vdtype = LLVM_DtoDType(vd->type); assert(vd); Logger::println("vars[%d] = %s", i, vd->toChars()); std::vector idxs; - si->ad->offsetToIndex(vd->type, vd->offset, idxs); + si->ad->offsetToIndex(vdtype, vd->offset, idxs); assert(idxs.size() == 1); unsigned idx = idxs[0]; @@ -480,17 +507,15 @@ if (ExpInitializer* ex = ini->isExpInitializer()) { - elem* e = ex->exp->toElem(gIR); - v = llvm::cast(e->val); - delete e; + v = ex->exp->toConstElem(gIR); } else if (StructInitializer* si = ini->isStructInitializer()) { - v = LLVM_DtoStructInitializer(si); + v = LLVM_DtoConstStructInitializer(si); } else if (ArrayInitializer* ai = ini->isArrayInitializer()) { - v = LLVM_DtoArrayInitializer(ai); + v = LLVM_DtoConstArrayInitializer(ai); } else if (ini->isVoidInitializer()) { @@ -731,20 +756,6 @@ // return new llvm::ReturnInst(call,bb); - - /* - // return value type - const llvm::Type* rettype; - Type* rt = f->next; - if (rt) { - rettype = LLVM_DtoType(rt); - } - else { - assert(0); - } - - llvm::FunctionType* functype = llvm::FunctionType::get(rettype, paramvec, false); - */ } ////////////////////////////////////////////////////////////////////////////////////////// @@ -802,47 +813,54 @@ ////////////////////////////////////////////////////////////////////////////////////////// -llvm::Constant* LLVM_DtoInitializer(Type* type, Initializer* init) +llvm::Constant* LLVM_DtoConstInitializer(Type* type, Initializer* init) { llvm::Constant* _init = 0; // may return zero if (!init) { - Logger::println("default initializer"); - elem* e = type->defaultInit()->toElem(gIR); - if (!e->inplace && !e->isNull()) { - _init = llvm::cast(e->getValue()); - } - delete e; + Logger::println("const default initializer for %s", type->toChars()); + _init = type->defaultInit()->toConstElem(gIR); } else if (ExpInitializer* ex = init->isExpInitializer()) { - Logger::println("expression initializer"); - elem* e = ex->exp->toElem(gIR); - if (!e->inplace && !e->isNull()) { - _init = llvm::cast(e->getValue()); - } - delete e; + Logger::println("const expression initializer"); + _init = ex->exp->toConstElem(gIR); } else if (StructInitializer* si = init->isStructInitializer()) { - Logger::println("struct initializer"); - _init = LLVM_DtoStructInitializer(si); + Logger::println("const struct initializer"); + _init = LLVM_DtoConstStructInitializer(si); } else if (ArrayInitializer* ai = init->isArrayInitializer()) { - Logger::println("array initializer"); - _init = LLVM_DtoArrayInitializer(ai); + Logger::println("const array initializer"); + _init = LLVM_DtoConstArrayInitializer(ai); } else if (init->isVoidInitializer()) { - Logger::println("void initializer"); + Logger::println("const void initializer"); const llvm::Type* ty = LLVM_DtoType(type); _init = llvm::Constant::getNullValue(ty); } else { + Logger::println("unsupported const initializer: %s", init->toChars()); + } + return _init; +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void LLVM_DtoInitializer(Initializer* init) +{ + if (ExpInitializer* ex = init->isExpInitializer()) + { + Logger::println("expression initializer"); + elem* e = ex->exp->toElem(gIR); + delete e; + } + else { Logger::println("unsupported initializer: %s", init->toChars()); } - return _init; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -862,13 +880,14 @@ { size_t n = src.size(); std::vector dst(n); - Logger::cout() << "indices:"; + std::ostream& ostr = Logger::cout(); + ostr << "indices for '" << *ptr << "':"; for (size_t i=0; itype; + TypeFunction* f = (TypeFunction*)LLVM_DtoDType(fdecl->type); assert(f != 0); if (fdecl->llvmValue != 0) { @@ -1054,9 +1073,93 @@ call->setCallingConv(llvm::CallingConv::C); } +////////////////////////////////////////////////////////////////////////////////////////// +llvm::Value* LLVM_DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expression* argexp) +{ + llvm::Value* retval = 0; + + bool haslvals = !gIR->lvals.empty(); + if (haslvals) + gIR->lvals.push_back(NULL); + + elem* arg = argexp->toElem(gIR); + + if (haslvals) + gIR->lvals.pop_back(); + + if (arg->inplace) { + assert(arg->mem != 0); + retval = arg->mem; + delete arg; + return retval; + } + + Type* realtype = LLVM_DtoDType(argexp->type); + TY argty = realtype->ty; + if (LLVM_DtoIsPassedByRef(realtype)) { + if (!fnarg || !fnarg->llvmCopy) { + retval = arg->getValue(); + assert(retval != 0); + } + else { + llvm::Value* allocaInst = 0; + llvm::BasicBlock* entryblock = &gIR->topfunc()->front(); + //const llvm::PointerType* pty = llvm::cast(arg->mem->getType()); + const llvm::PointerType* pty = llvm::PointerType::get(LLVM_DtoType(argexp->type)); + if (argty == Tstruct) { + allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint()); + TypeStruct* ts = (TypeStruct*)LLVM_DtoDType(argexp->type); + LLVM_DtoStructCopy(ts,allocaInst,arg->mem); + } + else if (argty == Tdelegate) { + allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint()); + LLVM_DtoDelegateCopy(allocaInst,arg->mem); + } + else if (argty == Tarray) { + if (arg->type == elem::SLICE) { + allocaInst = new llvm::AllocaInst(LLVM_DtoType(argexp->type), "tmpparam", gIR->topallocapoint()); + LLVM_DtoSetArray(allocaInst, arg->arg, arg->mem); + } + else { + allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint()); + LLVM_DtoArrayAssign(allocaInst,arg->mem); + } + } + else + assert(0); + + assert(allocaInst != 0); + 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(); + } + else { + Logger::println("as ptr arg"); + retval = arg->mem ? arg->mem : arg->val; + if (retval->getType() != paramtype) + { + assert(retval->getType() == paramtype->getContainedType(0)); + LLVM_DtoGiveArgumentStorage(arg); + new llvm::StoreInst(retval, arg->mem, gIR->scopebb()); + retval = arg->mem; + } + } + + delete arg; + + if (fnarg && retval->getType() != paramtype) { + Logger::cout() << "got '" << *retval->getType() << "' expected '" << *paramtype << "'\n"; + assert(0 && "parameter type that was actually passed is invalid"); + } + return retval; +} - - - diff -r fd5e8bbfcb25 -r 8b0e809563df gen/tollvm.h --- a/gen/tollvm.h Wed Oct 10 06:21:31 2007 +0200 +++ b/gen/tollvm.h Fri Oct 19 07:43:21 2007 +0200 @@ -3,11 +3,13 @@ struct StructInitializer; const llvm::Type* LLVM_DtoType(Type* t); +bool LLVM_DtoIsPassedByRef(Type* type); +Type* LLVM_DtoDType(Type* t); const llvm::Type* LLVM_DtoStructType(Type* t); llvm::Value* LLVM_DtoStructZeroInit(TypeStruct* t, llvm::Value* v); llvm::Value* LLVM_DtoStructCopy(TypeStruct* t, llvm::Value* dst, llvm::Value* src); -llvm::Constant* LLVM_DtoStructInitializer(StructInitializer* si); +llvm::Constant* LLVM_DtoConstStructInitializer(StructInitializer* si); const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam = 0); const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl); @@ -30,7 +32,8 @@ void LLVM_DtoCallClassDtors(TypeClass* tc, llvm::Value* instance); void LLVM_DtoInitClass(TypeClass* tc, llvm::Value* dst); -llvm::Constant* LLVM_DtoInitializer(Type* type, Initializer* init); +llvm::Constant* LLVM_DtoConstInitializer(Type* type, Initializer* init); +void LLVM_DtoInitializer(Initializer* init); llvm::Function* LLVM_DeclareMemSet32(); llvm::Function* LLVM_DeclareMemSet64(); @@ -49,4 +52,6 @@ void LLVM_DtoAssert(llvm::Value* cond, llvm::Value* loc, llvm::Value* msg); +llvm::Value* LLVM_DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expression* argexp); + #include "enums.h" diff -r fd5e8bbfcb25 -r 8b0e809563df gen/toobj.c --- a/gen/toobj.c Wed Oct 10 06:21:31 2007 +0200 +++ b/gen/toobj.c Fri Oct 19 07:43:21 2007 +0200 @@ -11,14 +11,9 @@ #include #include -#include "llvm/Type.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" +#include "gen/llvm.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/ReaderWriter.h" - -#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachineRegistry.h" @@ -152,13 +147,14 @@ LOG_SCOPE; for (unsigned i=0; ioffset, vd->type->toChars()); - if (os == vd->offset && vd->type == t) { + Type* vdtype = LLVM_DtoDType(vd->type); + Logger::println("found %u type %s", vd->offset, vdtype->toChars()); + if (os == vd->offset && vdtype == t) { result.push_back(i); return; } - else if (vd->type->ty == Tstruct && (vd->offset + vd->type->size()) > os) { - TypeStruct* ts = (TypeStruct*)vd->type; + else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) { + TypeStruct* ts = (TypeStruct*)vdtype; StructDeclaration* sd = ts->sym; result.push_back(i); sd->offsetToIndex(t, os - vd->offset, result); @@ -212,7 +208,7 @@ void StructDeclaration::toObjFile() { - TypeStruct* ts = (TypeStruct*)type; + TypeStruct* ts = (TypeStruct*)LLVM_DtoDType(type); if (llvmType != 0) return; @@ -288,7 +284,7 @@ // generate member function definitions gIR->topstruct().queueFuncs = false; - IRState::FuncDeclVec& mfs = gIR->topstruct().funcs; + IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs; size_t n = mfs.size(); for (size_t i=0; itoObjFile(); @@ -311,6 +307,9 @@ { BaseClass* bc = (BaseClass*)(bcs->data[j]); assert(bc); + Logger::println("Adding base class members of %s", bc->base->toChars()); + LOG_SCOPE; + LLVM_AddBaseClassData(&bc->base->baseclasses); for (int k=0; k < bc->base->members->dim; k++) { Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]); @@ -324,7 +323,7 @@ void ClassDeclaration::toObjFile() { - TypeClass* ts = (TypeClass*)type; + TypeClass* ts = (TypeClass*)LLVM_DtoDType(type); if (ts->llvmType != 0 || llvmInProgress) return; @@ -453,7 +452,7 @@ // generate member function definitions gIR->topstruct().queueFuncs = false; - IRState::FuncDeclVec& mfs = gIR->topstruct().funcs; + IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs; size_t n = mfs.size(); for (size_t i=0; itoObjFile(); @@ -479,8 +478,7 @@ void VarDeclaration::toObjFile() { - static int vdi = 0; - Logger::print("VarDeclaration::toObjFile(%d): %s | %s\n", vdi++, toChars(), type->toChars()); + Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; llvm::Module* M = gIR->module; @@ -493,8 +491,11 @@ } // global variable or magic - if (isDataseg()) + if (isDataseg() || parent->isModule()) { + if (llvmTouched) return; + else llvmTouched = true; + bool _isconst = isConst(); llvm::GlobalValue::LinkageTypes _linkage; @@ -503,7 +504,9 @@ else _linkage = LLVM_DtoLinkage(protection, storage_class); - const llvm::Type* _type = LLVM_DtoType(type); + Type* t = LLVM_DtoDType(type); + + const llvm::Type* _type = LLVM_DtoType(t); assert(_type); llvm::Constant* _init = 0; @@ -513,10 +516,10 @@ std::string _name(mangle()); llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,0,_name,M); llvmValue = gvar; + gIR->lvals.push_back(gvar); - - _init = LLVM_DtoInitializer(type, init); - assert(_init); + _init = LLVM_DtoConstInitializer(t, init); + gIR->lvals.pop_back(); //Logger::cout() << "initializer: " << *_init << '\n'; if (_type != _init->getType()) { @@ -529,8 +532,8 @@ { assert(_init->getType()->getContainedType(0) == _type); llvm::GlobalVariable* gv = llvm::cast(_init); - assert(type->ty == Tstruct); - TypeStruct* ts = (TypeStruct*)type; + assert(t->ty == Tstruct); + TypeStruct* ts = (TypeStruct*)t; assert(ts->sym->llvmInitZ); _init = ts->sym->llvmInitZ; } @@ -549,9 +552,9 @@ } } - gIR->lvals.pop_back(); - gvar->setInitializer(_init); + + llvmDModule = gIR->dmodule; //if (storage_class & STCprivate) // gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility); @@ -562,36 +565,37 @@ { Logger::println("Aggregate var declaration: '%s' offset=%d", toChars(), offset); - const llvm::Type* _type = LLVM_DtoType(type); + Type* t = LLVM_DtoDType(type); + const llvm::Type* _type = LLVM_DtoType(t); gIR->topstruct().fields.push_back(_type); - llvm::Constant*_init = LLVM_DtoInitializer(type, init); + llvm::Constant*_init = LLVM_DtoConstInitializer(t, init); assert(_init); Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n'; - if (!_init || _type != _init->getType()) + if (_type != _init->getType()) { - if (type->ty == Tsarray) + if (t->ty == Tsarray) { const llvm::ArrayType* arrty = llvm::cast(_type); uint64_t n = arrty->getNumElements(); std::vector vals(n,_init); _init = llvm::ConstantArray::get(arrty, vals); } - else if (type->ty == Tarray) + else if (t->ty == Tarray) { assert(llvm::isa(_type)); _init = llvm::ConstantAggregateZero::get(_type); } - else if (type->ty == Tstruct) + else if (t->ty == Tstruct) { const llvm::StructType* structty = llvm::cast(_type); - TypeStruct* ts = (TypeStruct*)type; + TypeStruct* ts = (TypeStruct*)t; assert(ts); assert(ts->sym); assert(ts->sym->llvmInitZ); _init = ts->sym->llvmInitZ; } - else if (type->ty == Tclass) + else if (t->ty == Tclass) { _init = llvm::Constant::getNullValue(_type); } @@ -644,7 +648,8 @@ return; // we wait with the definition as they might invoke a virtual method and the vtable is not yet complete } - TypeFunction* f = (TypeFunction*)type; + Type* t = LLVM_DtoDType(type); + TypeFunction* f = (TypeFunction*)t; assert(f->llvmType); const llvm::FunctionType* functype = llvm::cast(llvmValue->getType()->getContainedType(0)); @@ -684,7 +689,8 @@ // function definition if (allow_fbody && fbody != 0) { - gIR->funcdecls.push_back(this); + gIR->functions.push_back(IRFunction(this)); + gIR->func().func = func; // first make absolutely sure the type is up to date f->llvmType = llvmValue->getType()->getContainedType(0); @@ -703,39 +709,38 @@ if (isMain()) gIR->emitMain = true; - gIR->funcs.push(func); - gIR->functypes.push(f); - - IRScope irs; - irs.begin = new llvm::BasicBlock("entry",func); - irs.end = new llvm::BasicBlock("endentry",func); + llvm::BasicBlock* beginbb = new llvm::BasicBlock("entry",func); + llvm::BasicBlock* endbb = new llvm::BasicBlock("endentry",func); //assert(gIR->scopes.empty()); - gIR->scopes.push_back(irs); + gIR->scopes.push_back(IRScope(beginbb, endbb)); // create alloca point f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb()); + gIR->func().allocapoint = f->llvmAllocaPoint; // output function body fbody->toIR(gIR); // llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement // in automatically, so we do it here. - if (!isMain() && (gIR->scopebb()->empty() || !llvm::isa(gIR->scopebb()->back()))) { - // pass the previous block into this block - //new llvm::BranchInst(irs.end, irs.begin); - new llvm::ReturnInst(gIR->scopebb()); + if (!isMain()) { + if (gIR->scopebb()->empty() || !llvm::isa(gIR->scopebb()->back())) { + // pass the previous block into this block + //new llvm::BranchInst(irs.end, irs.begin); + if (func->getReturnType() == llvm::Type::VoidTy) { + new llvm::ReturnInst(gIR->scopebb()); + } + + } } // erase alloca point f->llvmAllocaPoint->eraseFromParent(); f->llvmAllocaPoint = 0; + gIR->func().allocapoint = 0; gIR->scopes.pop_back(); - //assert(gIR->scopes.empty()); - - gIR->functypes.pop(); - gIR->funcs.pop(); // get rid of the endentry block, it's never used assert(!func->getBasicBlockList().empty()); @@ -745,11 +750,10 @@ // would be nice to figure out how to assert that this is correct llvm::BasicBlock* lastbb = &func->getBasicBlockList().back(); if (lastbb->empty()) { - // possibly assert(lastbb->getNumPredecessors() == 0); ??? try it out sometime ... - new llvm::UnreachableInst(lastbb); + lastbb->eraseFromParent(); } - gIR->funcdecls.pop_back(); + gIR->functions.pop_back(); } // template instances should have weak linkage diff -r fd5e8bbfcb25 -r 8b0e809563df lphobos/internal/arrays.d --- a/lphobos/internal/arrays.d Wed Oct 10 06:21:31 2007 +0200 +++ b/lphobos/internal/arrays.d Fri Oct 19 07:43:21 2007 +0200 @@ -2,6 +2,8 @@ extern(C): +// per-element array init routines + void _d_array_init_i1(bool* a, size_t n, bool v) { auto p = a; @@ -65,3 +67,21 @@ while (p !is end) *p++ = v; } + +// array comparison routines +int memcmp(void*,void*,size_t); + +bool _d_static_array_eq(void* lhs, void* rhs, size_t bytesize) +{ + if (lhs is rhs) + return true; + return memcmp(lhs,rhs,bytesize) == 0; +} + +bool _d_static_array_neq(void* lhs, void* rhs, size_t bytesize) +{ + if (lhs is rhs) + return false; + return memcmp(lhs,rhs,bytesize) != 0; +} + diff -r fd5e8bbfcb25 -r 8b0e809563df test/arrays4.d --- a/test/arrays4.d Wed Oct 10 06:21:31 2007 +0200 +++ b/test/arrays4.d Fri Oct 19 07:43:21 2007 +0200 @@ -1,9 +1,14 @@ module arrays4; - +import std.stdio; void main() { - auto arr = new int[4]; - auto arrcat = arr ~ arr; - assert(arrcat.length == arr.length * 2); + int[] arr; + arr ~= 3; + assert(arr.length == 1); + assert(arr[0] == 3); + arr ~= 5; + assert(arr.length == 2); + assert(arr[0] == 3); + assert(arr[1] == 5); + writefln(arr); } - diff -r fd5e8bbfcb25 -r 8b0e809563df test/arrays6.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/arrays6.d Fri Oct 19 07:43:21 2007 +0200 @@ -0,0 +1,6 @@ +module arrays6; + +void main() +{ + int[4] a = [1,2,3,4]; +} diff -r fd5e8bbfcb25 -r 8b0e809563df test/arrays7.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/arrays7.d Fri Oct 19 07:43:21 2007 +0200 @@ -0,0 +1,19 @@ +module arrays7; + +struct S +{ + int i; + float f; + long l; +} + +void main() +{ + S[] arr; + S s; + arr ~= s; + arr ~= S(1,2.64,0xFFFF_FFFF_FFFF); + assert(arr[1].i == 1); + assert(arr[1].f > 2.63 && arr[1].f < 2.65); + assert(arr[1].l == 0xFFFF_FFFF_FFFF); +} diff -r fd5e8bbfcb25 -r 8b0e809563df test/bug10.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/bug10.d Fri Oct 19 07:43:21 2007 +0200 @@ -0,0 +1,23 @@ +module bug10; +import std.stdio; +class C +{ + char[] msg; + + this() + { + } + this(char[] msg) + { + this.msg = msg; + } +} + +void main() +{ + auto c = new C(); + c.msg = "world"; + auto b = new C("hello"); + printf("%.*s\n", b.msg.length, b.msg.ptr); + printf("%.*s\n", c.msg.length, c.msg.ptr); +} diff -r fd5e8bbfcb25 -r 8b0e809563df test/bug11.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/bug11.d Fri Oct 19 07:43:21 2007 +0200 @@ -0,0 +1,12 @@ +module bug11; + +struct S +{ + int[4] arr; +} + +S s=S([1,2,3,4]); + +void main() +{ +} diff -r fd5e8bbfcb25 -r 8b0e809563df test/bug12.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/bug12.d Fri Oct 19 07:43:21 2007 +0200 @@ -0,0 +1,6 @@ +module bug12; + +void main() +{ + const string name="y"; +} diff -r fd5e8bbfcb25 -r 8b0e809563df test/bug13.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/bug13.d Fri Oct 19 07:43:21 2007 +0200 @@ -0,0 +1,18 @@ +module bug13; + +void func1(ubyte[4]* arr) +{ + ubyte* b = &(*arr)[0]; + func2(&(*arr)[1]); +} + +void func2(ubyte* ptr) +{ + assert(*ptr == 2); +} + +void main() +{ + ubyte[4] arr = [cast(ubyte)1,2,3,4]; + func1(&arr); +} diff -r fd5e8bbfcb25 -r 8b0e809563df test/bug14.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/bug14.d Fri Oct 19 07:43:21 2007 +0200 @@ -0,0 +1,7 @@ +module bug14; + +void main() +{ + int[] arr = new int[12]; + int i = arr[0]; +} diff -r fd5e8bbfcb25 -r 8b0e809563df test/bug15.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/bug15.d Fri Oct 19 07:43:21 2007 +0200 @@ -0,0 +1,17 @@ +module bug15; + +bool bool1(bool b) { + if (b) return true; + else return false; +} + +bool bool2(bool b) { + if (b) {return true;} + else {return false;} +} + +void main() +{ + assert(bool1(true)); + assert(!bool2(false)); +} diff -r fd5e8bbfcb25 -r 8b0e809563df test/bug3.d --- a/test/bug3.d Wed Oct 10 06:21:31 2007 +0200 +++ b/test/bug3.d Fri Oct 19 07:43:21 2007 +0200 @@ -17,6 +17,8 @@ S s; s.arr = new int[5]; s.arr[1] = 32; - assert(s.arr[0] == 0); - assert(s.arr[1] == 32); + int i; + i = s.arr[0]; + //assert(s.arr[0] == 0); + //assert(s.arr[1] == 32); } diff -r fd5e8bbfcb25 -r 8b0e809563df test/bug8.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/bug8.d Fri Oct 19 07:43:21 2007 +0200 @@ -0,0 +1,21 @@ +module bug8; + +void main() +{ + s = newS(); +} + +S* s; + +struct S +{ + int i; +} + +S* newS() +{ + auto tmp = new S; + tmp.i = 4; + return tmp; +} + diff -r fd5e8bbfcb25 -r 8b0e809563df test/bug9.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/bug9.d Fri Oct 19 07:43:21 2007 +0200 @@ -0,0 +1,32 @@ +module bug9; +struct rgb +{ + ubyte[3] values; + rgb average(rgb other) + { + rgb res; + foreach (id, ref v; res.values) v=(values[id]+other.values[id])/2; + return res; + } + void print() + { + printf("[%d,%d,%d]\n", values[0], values[1], values[2]); + } +} + +void main() +{ + rgb a,b; + a.values[0] = 10; + a.values[1] = 20; + a.values[2] = 30; + b.values[0] = 30; + b.values[1] = 20; + b.values[2] = 10; + rgb avg = a.average(b); + avg.print(); + assert(avg.values[0] == 20); + assert(avg.values[1] == 20); + assert(avg.values[2] == 20); +} + diff -r fd5e8bbfcb25 -r 8b0e809563df test/cond1.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/cond1.d Fri Oct 19 07:43:21 2007 +0200 @@ -0,0 +1,8 @@ +module cond1; + +void main() +{ + double a = 2; + double b = 4; + double c = (a > 0) ? a : b; +} diff -r fd5e8bbfcb25 -r 8b0e809563df test/scope2.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/scope2.d Fri Oct 19 07:43:21 2007 +0200 @@ -0,0 +1,8 @@ +module scope2; + +void main() +{ + scope(exit) printf("exit\n"); + scope(failure) printf("failure\n"); + scope(success) printf("success\n"); +} diff -r fd5e8bbfcb25 -r 8b0e809563df test/scope3.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/scope3.d Fri Oct 19 07:43:21 2007 +0200 @@ -0,0 +1,10 @@ +module scope3; + +void main() +{ + int i; + while (i < 10) { + scope(success) i++; + } + printf("%d\n", i); +} diff -r fd5e8bbfcb25 -r 8b0e809563df test/scope4.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/scope4.d Fri Oct 19 07:43:21 2007 +0200 @@ -0,0 +1,13 @@ +module scope4; +int main() +{ + int i; + try + { + return i; + } + finally + { + //i = 1; + } +} diff -r fd5e8bbfcb25 -r 8b0e809563df test/virtcall.d --- a/test/virtcall.d Wed Oct 10 06:21:31 2007 +0200 +++ b/test/virtcall.d Fri Oct 19 07:43:21 2007 +0200 @@ -12,4 +12,5 @@ { C c = new C; auto s = c.toString(); + printf("%.*s\n", s.length, s.ptr); } diff -r fd5e8bbfcb25 -r 8b0e809563df test/with1.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/with1.d Fri Oct 19 07:43:21 2007 +0200 @@ -0,0 +1,15 @@ +module with1; +struct S +{ + int i; + float f; +} +void main() +{ + S s; + with(s) + { + i = 0; + f = 3.4; + } +} diff -r fd5e8bbfcb25 -r 8b0e809563df tester.sh --- a/tester.sh Wed Oct 10 06:21:31 2007 +0200 +++ b/tester.sh Fri Oct 19 07:43:21 2007 +0200 @@ -6,28 +6,28 @@ fi if [ "$2" = "ll" ]; then - llvmdc $1 -Itest -odtest -c && + llvmdc $1 -Itest -odtest -c -vv && llvm-dis -f $1.bc && cat $1.ll exit $? elif [ "$2" = "llopt" ]; then - llvmdc $1 -Itest -odtest -c && + llvmdc $1 -Itest -odtest -c -vv && opt -f -o=$1.bc -std-compile-opts $1.bc && llvm-dis -f $1.bc && cat $1.ll exit $? elif [ "$2" = "run" ]; then - llvmdc $1 lib/lphobos.bc -Itest -odtest -of$1 && + llvmdc $1 lib/lphobos.bc -Itest -odtest -of$1 -vv && $1 exit $? elif [ "$2" = "c" ]; then - llvmdc $1 -Itest -odtest -c + llvmdc $1 -Itest -odtest -c -vv exit $? elif [ "$2" = "gdb" ]; then - gdb --args llvmdc $1 -Itest -odtest -c + gdb --args llvmdc $1 -Itest -odtest -c -vv exit $? elif [ "$2" = "gdbrun" ]; then - llvmdc $1 -Itest -odtest -c && + llvmdc $1 -Itest -odtest -c -vv && gdb $1 exit $? else