diff --git a/dmd/declaration.h b/dmd/declaration.h index 83da7b2b..49b2eb28 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -509,6 +509,8 @@ struct FuncDeclaration : Declaration int cvMember(unsigned char *p); FuncDeclaration *isFuncDeclaration() { return this; } + + bool llvmQueued; }; struct FuncAliasDeclaration : FuncDeclaration diff --git a/dmd/func.c b/dmd/func.c index a75bbd28..7d3879e1 100644 --- a/dmd/func.c +++ b/dmd/func.c @@ -73,6 +73,7 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC s nrvo_can = 1; nrvo_var = NULL; shidden = NULL; + llvmQueued = false; } Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s) diff --git a/dmd/mars.c b/dmd/mars.c index 05ed7748..dd3fc955 100644 --- a/dmd/mars.c +++ b/dmd/mars.c @@ -349,7 +349,7 @@ int main(int argc, char *argv[]) global.params.Dversion = 1; else if (strcmp(p + 1, "w") == 0) global.params.warnings = 1; - else if (strcmp(p + 1, "O") == 0) + else if (p[1] == 'O') { global.params.optimize = 1; if (p[2] != 0) { diff --git a/dmd/mtype.c b/dmd/mtype.c index f27395e4..72f3c883 100644 --- a/dmd/mtype.c +++ b/dmd/mtype.c @@ -114,7 +114,7 @@ Type::Type(TY ty, Type *next) this->arrayof = NULL; this->vtinfo = NULL; this->ctype = NULL; - this->llvmType = 0; + this->llvmType = NULL; } Type *Type::syntaxCopy() diff --git a/dmd/mtype.h b/dmd/mtype.h index 2200e34c..7f0ab649 100644 --- a/dmd/mtype.h +++ b/dmd/mtype.h @@ -250,7 +250,7 @@ struct Type : Object virtual type *toCParamtype(); virtual Symbol *toSymbol(); - llvm::Type* llvmType; + const llvm::Type* llvmType; // For eliminating dynamic_cast virtual TypeBasic *isTypeBasic(); diff --git a/gen/arrays.c b/gen/arrays.c index 0b1688b3..f8159c2b 100644 --- a/gen/arrays.c +++ b/gen/arrays.c @@ -19,7 +19,7 @@ ////////////////////////////////////////////////////////////////////////////////////////// -llvm::StructType* LLVM_DtoArrayType(Type* t) +const llvm::StructType* LLVM_DtoArrayType(Type* t) { assert(t->next); const llvm::Type* at = LLVM_DtoType(t->next); @@ -51,7 +51,7 @@ llvm::StructType* LLVM_DtoArrayType(Type* t) ////////////////////////////////////////////////////////////////////////////////////////// -llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t) +const llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t) { if (t->llvmType) return llvm::cast(t->llvmType); @@ -63,7 +63,7 @@ llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t) TypeSArray* tsa = (TypeSArray*)t; assert(tsa->dim->type->isintegral()); - llvm::ArrayType* arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger()); + const llvm::ArrayType* arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger()); tsa->llvmType = arrty; return arrty; @@ -298,7 +298,7 @@ llvm::Constant* LLVM_DtoArrayInitializer(ArrayInitializer* arrinit) inits[i] = v; } - llvm::ArrayType* arrty = LLVM_DtoStaticArrayType(t); + const llvm::ArrayType* arrty = LLVM_DtoStaticArrayType(t); return llvm::ConstantArray::get(arrty, inits); } diff --git a/gen/arrays.h b/gen/arrays.h index cea91dcb..c70210ad 100644 --- a/gen/arrays.h +++ b/gen/arrays.h @@ -1,9 +1,9 @@ #ifndef LLVMC_GEN_ARRAYS_H #define LLVMC_GEN_ARRAYS_H -llvm::StructType* LLVM_DtoArrayType(Type* t); +const llvm::StructType* LLVM_DtoArrayType(Type* t); -llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t); +const llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t); llvm::Value* LLVM_DtoNullArray(llvm::Value* v); diff --git a/gen/elem.c b/gen/elem.c index b638e86a..fd691c25 100644 --- a/gen/elem.c +++ b/gen/elem.c @@ -17,6 +17,7 @@ elem::elem() type = NONE; inplace = false; field = false; + callconv = (unsigned)-1; vardecl = 0; funcdecl = 0; diff --git a/gen/elem.h b/gen/elem.h index dcba6b25..deb824d9 100644 --- a/gen/elem.h +++ b/gen/elem.h @@ -31,6 +31,7 @@ public: int type; bool inplace; bool field; + unsigned callconv; VarDeclaration* vardecl; FuncDeclaration* funcdecl; diff --git a/gen/toir.c b/gen/toir.c index 3b985a35..10e8ca74 100644 --- a/gen/toir.c +++ b/gen/toir.c @@ -954,6 +954,8 @@ elem* CallExp::toElem(IRState* p) // set calling convention if ((fn->funcdecl && (fn->funcdecl->llvmInternal != LLVMintrinsic)) || delegateCall) call->setCallingConv(LLVM_DtoCallingConv(dlink)); + else if (fn->callconv != (unsigned)-1) + call->setCallingConv(fn->callconv); delete fn; return e; @@ -1253,7 +1255,7 @@ elem* DotVarExp::toElem(IRState* p) funcval = LLVM_DtoGEP(funcval, zero, vtblidx, "tmp", p->scopebb()); funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb()); assert(funcval->getType() == fdecl->llvmValue->getType()); - //funcval = new llvm::BitCastInst(funcval, fdecl->llvmValue->getType(), "tmp", p->scopebb()); + e->callconv = LLVM_DtoCallingConv(fdecl->linkage); } e->val = funcval; e->type = elem::VAL; diff --git a/gen/tollvm.c b/gen/tollvm.c index 1341ade3..308ddca3 100644 --- a/gen/tollvm.c +++ b/gen/tollvm.c @@ -159,7 +159,7 @@ const llvm::Type* LLVM_DtoType(Type* t) ////////////////////////////////////////////////////////////////////////////////////////// -llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam) +const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam) { TypeFunction* f = (TypeFunction*)t; @@ -203,7 +203,7 @@ llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam) ////////////////////////////////////////////////////////////////////////////////////////// -llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl) +const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl) { TypeFunction* f = (TypeFunction*)fdecl->type; assert(f != 0); @@ -309,7 +309,7 @@ llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl) ////////////////////////////////////////////////////////////////////////////////////////// -llvm::StructType* LLVM_DtoDelegateType(Type* t) +const llvm::StructType* LLVM_DtoDelegateType(Type* t) { const llvm::Type* i8ptr = llvm::PointerType::get(llvm::Type::Int8Ty); const llvm::Type* func = LLVM_DtoFunctionType(t->next, i8ptr); @@ -323,7 +323,7 @@ llvm::StructType* LLVM_DtoDelegateType(Type* t) ////////////////////////////////////////////////////////////////////////////////////////// -llvm::Type* LLVM_DtoStructType(Type* t) +const llvm::Type* LLVM_DtoStructType(Type* t) { assert(0); std::vector types; @@ -763,26 +763,40 @@ void LLVM_DtoCallClassDtors(TypeClass* tc, llvm::Value* instance) void LLVM_DtoInitClass(TypeClass* tc, llvm::Value* dst) { - assert(tc->llvmInit); - assert(dst->getType() == tc->llvmInit->getType()); assert(gIR); assert(tc->llvmType); - uint64_t n = gTargetData->getTypeSize(tc->llvmType); - llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); + uint64_t size_t_size = gTargetData->getTypeSize(LLVM_DtoSize_t()); + uint64_t n = gTargetData->getTypeSize(tc->llvmType) - size_t_size; - llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); - llvm::Value* srcarr = new llvm::BitCastInst(tc->llvmInit,arrty,"tmp",gIR->scopebb()); + // set vtable field + llvm::Value* vtblvar = LLVM_DtoGEPi(dst,0,0,"tmp",gIR->scopebb()); + assert(tc->sym->llvmVtbl); + new llvm::StoreInst(tc->sym->llvmVtbl, vtblvar, gIR->scopebb()); - llvm::Function* fn = LLVM_DeclareMemCpy32(); - std::vector llargs; - llargs.resize(4); - llargs[0] = dstarr; - llargs[1] = srcarr; - llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); - llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); + // copy the static initializer + if (n > 0) { + assert(tc->llvmInit); + assert(dst->getType() == tc->llvmInit->getType()); - new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); + llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); + + llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); + dstarr = LLVM_DtoGEPi(dstarr,size_t_size,"tmp",gIR->scopebb()); + + llvm::Value* srcarr = new llvm::BitCastInst(tc->llvmInit,arrty,"tmp",gIR->scopebb()); + srcarr = LLVM_DtoGEPi(srcarr,size_t_size,"tmp",gIR->scopebb()); + + llvm::Function* fn = LLVM_DeclareMemCpy32(); + std::vector llargs; + llargs.resize(4); + llargs[0] = dstarr; + llargs[1] = srcarr; + llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); + llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); + + new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); + } } ////////////////////////////////////////////////////////////////////////////////////////// @@ -825,14 +839,19 @@ llvm::Constant* LLVM_DtoInitializer(Type* type, Initializer* init) return _init; } +////////////////////////////////////////////////////////////////////////////////////////// + llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, llvm::Value* i0, llvm::Value* i1, const std::string& var, llvm::BasicBlock* bb) { std::vector v(2); v[0] = i0; v[1] = i1; + Logger::cout() << "DtoGEP: " << *ptr << '\n'; return new llvm::GetElementPtrInst(ptr, v.begin(), v.end(), var, bb); } +////////////////////////////////////////////////////////////////////////////////////////// + llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, const std::vector& src, const std::string& var, llvm::BasicBlock* bb) { size_t n = src.size(); @@ -847,9 +866,32 @@ llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, const std::vector& src, con return new llvm::GetElementPtrInst(ptr, dst.begin(), dst.end(), var, bb); } +////////////////////////////////////////////////////////////////////////////////////////// + +llvm::Value* LLVM_DtoGEPi(llvm::Value* ptr, unsigned i, const std::string& var, llvm::BasicBlock* bb) +{ + return new llvm::GetElementPtrInst(ptr, llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false), var, bb); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +llvm::Value* LLVM_DtoGEPi(llvm::Value* ptr, unsigned i0, unsigned i1, const std::string& var, llvm::BasicBlock* bb) +{ + std::vector v(2); + v[0] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i0, false); + v[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i1, false); + return new llvm::GetElementPtrInst(ptr, v.begin(), v.end(), var, bb); +} + +////////////////////////////////////////////////////////////////////////////////////////// + llvm::Function* LLVM_DtoDeclareFunction(FuncDeclaration* fdecl) { + TypeFunction* f = (TypeFunction*)fdecl->type; + assert(f != 0); + if (fdecl->llvmValue != 0) { + assert(llvm::isa(fdecl->llvmValue)); return llvm::cast(fdecl->llvmValue); } @@ -863,9 +905,7 @@ llvm::Function* LLVM_DtoDeclareFunction(FuncDeclaration* fdecl) } // construct function - TypeFunction* f = (TypeFunction*)fdecl->type; - assert(f != 0); - llvm::FunctionType* functype = (f->llvmType == 0) ? LLVM_DtoFunctionType(fdecl) : llvm::cast(f->llvmType); + const llvm::FunctionType* functype = (f->llvmType == 0) ? LLVM_DtoFunctionType(fdecl) : llvm::cast(f->llvmType); // mangled name char* mangled_name = (fdecl->llvmInternal == LLVMintrinsic) ? fdecl->llvmInternal1 : fdecl->mangle(); @@ -881,6 +921,7 @@ llvm::Function* LLVM_DtoDeclareFunction(FuncDeclaration* fdecl) fdecl->llvmValue = func; f->llvmType = functype; + assert(llvm::isa(f->llvmType)); if (fdecl->isMain()) { gIR->mainFunc = func; diff --git a/gen/tollvm.h b/gen/tollvm.h index 38a54bcb..71beb1bb 100644 --- a/gen/tollvm.h +++ b/gen/tollvm.h @@ -4,16 +4,16 @@ struct StructInitializer; const llvm::Type* LLVM_DtoType(Type* t); -llvm::Type* LLVM_DtoStructType(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::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam = 0); -llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl); +const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam = 0); +const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl); llvm::Function* LLVM_DtoDeclareFunction(FuncDeclaration* fdecl); -llvm::StructType* LLVM_DtoDelegateType(Type* t); +const llvm::StructType* LLVM_DtoDelegateType(Type* t); llvm::Value* LLVM_DtoNullDelegate(llvm::Value* v); llvm::Value* LLVM_DtoDelegateCopy(llvm::Value* dst, llvm::Value* src); @@ -39,5 +39,7 @@ llvm::Function* LLVM_DeclareMemCpy64(); llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, llvm::Value* i0, llvm::Value* i1, const std::string& var, llvm::BasicBlock* bb); llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, const std::vector& src, const std::string& var, llvm::BasicBlock* bb); +llvm::Value* LLVM_DtoGEPi(llvm::Value* ptr, unsigned i0, const std::string& var, llvm::BasicBlock* bb); +llvm::Value* LLVM_DtoGEPi(llvm::Value* ptr, unsigned i0, unsigned i1, const std::string& var, llvm::BasicBlock* bb); #include "enums.h" diff --git a/gen/toobj.c b/gen/toobj.c index 29e5fe48..09477c72 100644 --- a/gen/toobj.c +++ b/gen/toobj.c @@ -80,18 +80,21 @@ Module::genobjfile() delete gTargetData; gTargetData = 0; + // emit the llvm main function if necessary + if (ir.emitMain) { + LLVM_DtoMain(); + } + // verify the llvm std::string verifyErr; + Logger::println("Verifying module..."); if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr)) { error("%s", verifyErr.c_str()); fatal(); } - - // emit the llvm main function if necessary - if (ir.emitMain) { - LLVM_DtoMain(); - } + else + Logger::println("Verification passed!"); // run passes // TODO @@ -386,6 +389,7 @@ void ClassDeclaration::toObjFile() if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { fd->toObjFile(); + assert(fd->llvmValue); llvm::Constant* c = llvm::cast(fd->llvmValue); sinits.push_back(c); sinits_ty.push_back(c->getType()); @@ -437,17 +441,11 @@ void ClassDeclaration::toObjFile() assert(svtblVar != 0); gIR->topstruct().inits[0] = svtblVar; - //assert(tk == gIR->topstruct().size()); - #ifndef LLVMD_NO_LOGGER - Logger::cout() << *structtype << '\n'; - //for (size_t k=0; ktopstruct().inits.size(); ++k) - // Logger::cout() << *gIR->topstruct().inits[k] << '\n'; - #endif _init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits); assert(_init); std::string initname(mangle()); initname.append("__initZ"); - Logger::cout() << *_init << '\n'; + //Logger::cout() << *_init << '\n'; llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, 0, initname, gIR->module); ts->llvmInit = initvar; if (define_vtable) { @@ -616,27 +614,33 @@ void FuncDeclaration::toObjFile() llvm::Function* func = LLVM_DtoDeclareFunction(this); if (!gIR->queueClassMethods.empty() && gIR->queueClassMethods.back()) { - Logger::println("queueing %s", toChars()); - assert(!gIR->classmethods.empty()); - gIR->classmethods.back().push_back(this); + if (!llvmQueued) { + Logger::println("queueing %s", toChars()); + assert(!gIR->classmethods.empty()); + gIR->classmethods.back().push_back(this); + llvmQueued = true; + } return; // we wait with the definition as they might invoke a virtual method and the vtable is not yet complete } TypeFunction* f = (TypeFunction*)type; - llvm::FunctionType* functype = llvm::cast(f->llvmType); + assert(f->llvmType); + const llvm::FunctionType* functype = llvm::cast(llvmValue->getType()->getContainedType(0)); // only members of the current module maybe be defined if (getModule() == gIR->dmodule) { + llvmDModule = gIR->dmodule; + bool allow_fbody = true; // handle static constructor / destructor if (isStaticCtorDeclaration() || isStaticDtorDeclaration()) { const llvm::ArrayType* sctor_type = llvm::ArrayType::get(llvm::PointerType::get(functype),1); //Logger::cout() << "static ctor type: " << *sctor_type << '\n'; - + llvm::Constant* sctor_func = llvm::cast(llvmValue); //Logger::cout() << "static ctor func: " << *sctor_func << '\n'; - + llvm::Constant* sctor_init = 0; if (llvmInternal == LLVMnull) { @@ -648,10 +652,9 @@ void FuncDeclaration::toObjFile() { sctor_init = llvm::ConstantArray::get(sctor_type,&sctor_func,1); } - + //Logger::cout() << "static ctor init: " << *sctor_init << '\n'; - - + // output the llvm.global_ctors array const char* varname = isStaticCtorDeclaration() ? "_d_module_ctor_array" : "_d_module_dtor_array"; llvm::GlobalVariable* sctor_arr = new llvm::GlobalVariable(sctor_type, false, llvm::GlobalValue::AppendingLinkage, sctor_init, varname, gIR->module); @@ -660,6 +663,9 @@ void FuncDeclaration::toObjFile() // function definition if (allow_fbody && fbody != 0) { + // first make absolutely sure the type is up to date + f->llvmType = llvmValue->getType()->getContainedType(0); + if (isMain()) gIR->emitMain = true; @@ -672,10 +678,10 @@ void FuncDeclaration::toObjFile() //assert(gIR->scopes.empty()); gIR->scopes.push_back(irs); - + // create alloca point f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb()); - + // output function body fbody->toIR(gIR); @@ -686,7 +692,7 @@ void FuncDeclaration::toObjFile() //new llvm::BranchInst(irs.end, irs.begin); new llvm::ReturnInst(gIR->scopebb()); } - + // erase alloca point f->llvmAllocaPoint->eraseFromParent(); f->llvmAllocaPoint = 0; @@ -710,8 +716,4 @@ void FuncDeclaration::toObjFile() } } } - - llvmDModule = gIR->dmodule; - - Logger::println("FuncDeclaration done\n"); } diff --git a/lib/llvmdcore.bc b/lib/llvmdcore.bc index 04c9615e..4a69a882 100644 Binary files a/lib/llvmdcore.bc and b/lib/llvmdcore.bc differ diff --git a/lphobos/llvm/intrinsic.d b/lphobos/llvm/intrinsic.d index a1e5f28f..70f3625d 100644 --- a/lphobos/llvm/intrinsic.d +++ b/lphobos/llvm/intrinsic.d @@ -29,10 +29,10 @@ pragma(LLVM_internal, "intrinsic", "llvm.pcmarker") pragma(LLVM_internal, "intrinsic", "llvm.prefetch") void llvm_prefetch(void* ptr, uint rw, uint locality); +*/ pragma(LLVM_internal, "intrinsic", "llvm.readcyclecounter") - ulong llvm_readcyclecounter(); -*/ + ulong readcyclecounter(); // standard C intrinsics pragma(LLVM_internal, "intrinsic", "llvm.memcpy.i32") diff --git a/runalltests.d b/runalltests.d new file mode 100644 index 00000000..b174cbd2 --- /dev/null +++ b/runalltests.d @@ -0,0 +1,33 @@ +module runalltests; + +import std.file; +import std.path; +import std.process; +import std.stdio; + +int main(string[] args) { + string[] good; + string[] bad; + + auto contents = listdir("test", "*.d"); + foreach(c; contents) { + if (system("./tester.sh "~getName(c)~" ll") != 0) { + bad ~= c; + } + else { + good ~= c; + } + } + + int ret = 0; + if (bad.length > 0) { + writefln(bad.length, '/', contents.length, " tests failed:"); + foreach(b; bad) { + writefln(" ",b); + } + ret = 1; + } + + writefln(good.length, '/', contents.length, " tests passed"); + return ret; +} diff --git a/test/classes6.d b/test/classes6.d index 9994e5a0..32cf5757 100644 --- a/test/classes6.d +++ b/test/classes6.d @@ -4,12 +4,34 @@ class C { void f() { - printf("hello world\n"); + printf("world\n"); } } +class D : C +{ + void f() + { + printf("moon\n"); + } +} + + +extern(C) +{ + void srand(uint seed); + int rand(); +} + +import llvm.intrinsic; + void main() { - scope c = new C; + C c; + srand(readcyclecounter()); + if (rand() % 2) + c = new C; + else + c = new D; c.f(); } diff --git a/test/classes7.d b/test/classes7.d new file mode 100644 index 00000000..2869d711 --- /dev/null +++ b/test/classes7.d @@ -0,0 +1,21 @@ +module classes7; + +class C +{ + int i=0; + void f() + { + i=42; + } + void g() + { + f(); + } +} + +void main() +{ + scope c = new C; + c.g(); + assert(c.i == 43); +} diff --git a/tester.sh b/tester.sh index ba1b6300..b1582f77 100755 --- a/tester.sh +++ b/tester.sh @@ -6,24 +6,30 @@ if [ -z $1 ]; then fi if [ "$2" = "ll" ]; then - make && llvmdc $1 -Itest -odtest -c && llvm-dis -f $1.bc && cat $1.ll exit $? +elif [ "$2" = "llopt" ]; then + llvmdc $1 -Itest -odtest -c && + opt -f -o=$1.bc -std-compile-opts $1.bc && + llvm-dis -f $1.bc && + cat $1.ll + exit $? elif [ "$2" = "run" ]; then - make && llvmdc $1 -Itest -odtest -of$1 && $1 exit $? elif [ "$2" = "c" ]; then - make && llvmdc $1 -Itest -odtest -c exit $? elif [ "$2" = "gdb" ]; then - make && gdb --args llvmdc $1 -Itest -odtest '-c' exit $? +elif [ "$2" = "gdbrun" ]; then + llvmdc $1 -Itest -odtest '-c' && + gdb $1 + exit $? else echo "bad command or filename" fi