diff --git a/CMakeLists.txt b/CMakeLists.txt index ab9a9364..7f18328a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,9 @@ if(MSVC) set(LIBCONFIG_DLL OFF CACHE BOOL "Use libconfig++ DLL instead of static library") endif() +include(CheckIncludeFile) +include(CheckLibraryExists) + # # Locate LLVM. # @@ -350,6 +353,35 @@ else() add_definitions(-D__LITTLE_ENDIAN__) endif() +# +# Check if libpthread is available. +# FIXME: Guard with LLVM_ENABLE_THREADS +# +if( NOT WIN32 OR CYGWIN ) + check_include_file(pthread.h HAVE_PTHREAD_H) + check_library_exists(pthread pthread_create "" HAVE_LIBPTHREAD) + if(HAVE_LIBPTHREAD) + set(PTHREAD_LIBS -lpthread) + endif() +endif() + +# +# Check if terminfo is available. +# FIXME: Guard with LLVM_ENABLE_TERMINFO +# +if( NOT WIN32 OR CYGWIN ) + set(HAVE_TERMINFO 0) + foreach(library tinfo terminfo curses ncurses ncursesw) + string(TOUPPER ${library} library_suffix) + check_library_exists(${library} setupterm "" HAVE_TERMINFO_${library_suffix}) + if(HAVE_TERMINFO_${library_suffix}) + set(HAVE_TERMINFO 1) + set(TERMINFO_LIBS "${library}") + break() + endif() + endforeach() +endif() + # # Set up the main ldc/ldc2 target. # @@ -374,7 +406,7 @@ set_target_properties( ) # LDFLAGS should actually be in target property LINK_FLAGS, but this works, and gets around linking problems -target_link_libraries(${LDC_LIB} ${LLVM_LIBRARIES} "${LLVM_LDFLAGS}") +target_link_libraries(${LDC_LIB} ${LLVM_LIBRARIES} ${PTHREAD_LIBS} ${TERMINFO_LIBS} "${LLVM_LDFLAGS}") if(WIN32) target_link_libraries(${LDC_LIB} imagehlp psapi) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") @@ -394,7 +426,7 @@ set_target_properties( COMPILE_FLAGS "${LLVM_CXXFLAGS} ${EXTRA_CXXFLAGS}" LINK_FLAGS "${SANITIZE_LDFLAGS}" ) -target_link_libraries(${LDC_EXE} ${LDC_LIB} ${LIBCONFIG++_LIBRARY}) +target_link_libraries(${LDC_EXE} ${LDC_LIB} ${LIBCONFIG++_LIBRARY} ${PTHREAD_LIBS} ${CMAKE_DL_LIBS} ${TERMINFO_LIBS}) if(MSVC) # Add a post build event in Visual Studio to copy the config file into Debug/Release folder add_custom_command(TARGET ${LDC_EXE} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/bin/${LDC_EXE}.conf $ COMMENT "Copy config file ${LDC_EXE}.conf") @@ -432,7 +464,7 @@ set_target_properties( COMPILE_FLAGS "${TABLEGEN_CXXFLAGS} ${LDC_CXXFLAGS}" LINK_FLAGS "${SANITIZE_LDFLAGS}" ) -target_link_libraries(gen_gccbuiltins ${LLVM_LIBRARIES} "${LLVM_LDFLAGS}") +target_link_libraries(gen_gccbuiltins ${LLVM_LIBRARIES} ${PTHREAD_LIBS} ${TERMINFO_LIBS} ${CMAKE_DL_LIBS} "${LLVM_LDFLAGS}") if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") target_link_libraries(gen_gccbuiltins dl) endif() @@ -463,7 +495,7 @@ set_target_properties(${LDMD_EXE} PROPERTIES # use symbols from libdl, ..., so LLVM_LDFLAGS must come _after_ them in the # command line. Maybe this could be improved using library groups, at least with # GNU ld. -target_link_libraries(${LDMD_EXE} ${LLVM_LIBRARIES} "${LLVM_LDFLAGS}") +target_link_libraries(${LDMD_EXE} ${LLVM_LIBRARIES} ${PTHREAD_LIBS} ${TERMINFO_LIBS} ${CMAKE_DL_LIBS} "${LLVM_LDFLAGS}") # # Test and runtime targets. Note that enable_testing() is order-sensitive! diff --git a/gen/functions.cpp b/gen/functions.cpp index 0fe7b721..5dc12229 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -52,6 +52,9 @@ llvm::FunctionType* DtoFunctionType(Type* type, IrFuncTy &irFty, Type* thistype, assert(f->next && "Encountered function type with invalid return type; " "trying to codegen function ignored by the frontend?"); + // Return cached type if available + if (irFty.funcType) return irFty.funcType; + TargetABI* abi = (f->linkage == LINKintrinsic ? TargetABI::getIntrinsic() : gABI); // Tell the ABI we're resolving a new function type abi->newFunctionType(f); @@ -285,11 +288,11 @@ llvm::FunctionType* DtoFunctionType(Type* type, IrFuncTy &irFty, Type* thistype, std::reverse(argtypes.begin() + beg, argtypes.end()); } - LLFunctionType* functype = LLFunctionType::get(irFty.ret->ltype, argtypes, irFty.c_vararg); + irFty.funcType = LLFunctionType::get(irFty.ret->ltype, argtypes, irFty.c_vararg); - Logger::cout() << "Final function type: " << *functype << "\n"; + Logger::cout() << "Final function type: " << *irFty.funcType << "\n"; - return functype; + return irFty.funcType; } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/passes/GarbageCollect2Stack.cpp b/gen/passes/GarbageCollect2Stack.cpp index efdbfd43..135acadc 100644 --- a/gen/passes/GarbageCollect2Stack.cpp +++ b/gen/passes/GarbageCollect2Stack.cpp @@ -56,6 +56,10 @@ using namespace llvm; +#if LDC_LLVM_VER < 302 +typedef TargetData DataLayout; +#endif + STATISTIC(NumGcToStack, "Number of calls promoted to constant-size allocas"); STATISTIC(NumToDynSize, "Number of calls promoted to dynamically-sized allocas"); STATISTIC(NumDeleted, "Number of GC calls deleted because the return value was unused"); @@ -66,11 +70,7 @@ SizeLimit("dgc2stack-size-limit", cl::init(1024), cl::Hidden, namespace { struct Analysis { -#if LDC_LLVM_VER >= 302 - DataLayout& TD; -#else - TargetData& TD; -#endif + DataLayout& DL; const Module& M; CallGraph* CG; CallGraphNode* CGNode; @@ -151,7 +151,7 @@ namespace { APInt Mask = APInt::getLowBitsSet(Bits, BitsLimit); Mask.flipAllBits(); APInt KnownZero(Bits, 0), KnownOne(Bits, 0); - ComputeMaskedBits(Val, KnownZero, KnownOne, &A.TD); + ComputeMaskedBits(Val, KnownZero, KnownOne, &A.DL); if ((KnownZero & Mask) != Mask) return false; @@ -171,7 +171,7 @@ namespace { Value* TypeInfo = CS.getArgument(TypeInfoArgNr); Ty = A.getTypeFor(TypeInfo); if (!Ty) return false; - return A.TD.getTypeAllocSize(Ty) < SizeLimit; + return A.DL.getTypeAllocSize(Ty) < SizeLimit; } }; @@ -207,7 +207,7 @@ namespace { // (set bits) inference algorithm is rather limited, this is // useful for experimenting. if (SizeLimit > 0) { - uint64_t ElemSize = A.TD.getTypeAllocSize(Ty); + uint64_t ElemSize = A.DL.getTypeAllocSize(Ty); if (!isKnownLessThan(arrSize, SizeLimit / ElemSize, A)) return false; } @@ -237,7 +237,7 @@ namespace { if (Initialized) { // For now, only zero-init is supported. - uint64_t size = A.TD.getTypeStoreSize(Ty); + uint64_t size = A.DL.getTypeStoreSize(Ty); Value* TypeSize = ConstantInt::get(arrSize->getType(), size); // Use the original B to put initialization at the // allocation site. @@ -295,7 +295,7 @@ namespace { return false; Ty =node->getOperand(CD_BodyType)->getType(); - return A.TD.getTypeAllocSize(Ty) < SizeLimit; + return A.DL.getTypeAllocSize(Ty) < SizeLimit; } // The default promote() should be fine. @@ -390,11 +390,7 @@ namespace { bool runOnFunction(Function &F); virtual void getAnalysisUsage(AnalysisUsage &AU) const { -#if LDC_LLVM_VER >= 302 AU.addRequired(); -#else - AU.addRequired(); -#endif AU.addRequired(); #if LDC_LLVM_VER >= 305 @@ -458,11 +454,7 @@ static bool isSafeToStackAllocate(Instruction* Alloc, Value* V, DominatorTree& D bool GarbageCollect2Stack::runOnFunction(Function &F) { DEBUG(errs() << "\nRunning -dgc2stack on function " << F.getName() << '\n'); -#if LDC_LLVM_VER >= 302 - DataLayout& TD = getAnalysis(); -#else - TargetData& TD = getAnalysis(); -#endif + DataLayout& DL = getAnalysis(); DominatorTree& DT = getAnalysis(); #if LDC_LLVM_VER >= 305 CallGraphWrapperPass* CGPass = getAnalysisIfAvailable(); @@ -472,7 +464,7 @@ bool GarbageCollect2Stack::runOnFunction(Function &F) { #endif CallGraphNode* CGNode = CG ? (*CG)[&F] : NULL; - Analysis A = { TD, *M, CG, CGNode }; + Analysis A = { DL, *M, CG, CGNode }; BasicBlock& Entry = F.getEntryBlock(); diff --git a/gen/passes/SimplifyDRuntimeCalls.cpp b/gen/passes/SimplifyDRuntimeCalls.cpp index fe0b7350..9571ce31 100644 --- a/gen/passes/SimplifyDRuntimeCalls.cpp +++ b/gen/passes/SimplifyDRuntimeCalls.cpp @@ -45,6 +45,10 @@ using namespace llvm; +#if LDC_LLVM_VER < 302 +typedef TargetData DataLayout; +#endif + STATISTIC(NumSimplified, "Number of runtime calls simplified"); STATISTIC(NumDeleted, "Number of runtime calls deleted"); @@ -59,11 +63,7 @@ namespace { protected: Function *Caller; bool* Changed; -#if LDC_LLVM_VER >= 302 - const DataLayout *TD; -#else - const TargetData *TD; -#endif + const DataLayout *DL; AliasAnalysis *AA; LLVMContext *Context; @@ -85,16 +85,11 @@ namespace { /// delete CI. virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B)=0; -#if LDC_LLVM_VER >= 302 - Value *OptimizeCall(CallInst *CI, bool& Changed, const DataLayout &TD, + Value *OptimizeCall(CallInst *CI, bool& Changed, const DataLayout &DL, AliasAnalysis& AA, IRBuilder<> &B) { -#else - Value *OptimizeCall(CallInst *CI, bool& Changed, const TargetData &TD, - AliasAnalysis& AA, IRBuilder<> &B) { -#endif Caller = CI->getParent()->getParent(); this->Changed = &Changed; - this->TD = &TD; + this->DL = &DL; this->AA = &AA; if (CI->getCalledFunction()) Context = &CI->getCalledFunction()->getContext(); @@ -112,14 +107,7 @@ Value *LibCallOptimization::CastToCStr(Value *V, IRBuilder<> &B) { /// expects that the size has type 'intptr_t' and Dst/Src are pointers. Value *LibCallOptimization::EmitMemCpy(Value *Dst, Value *Src, Value *Len, unsigned Align, IRBuilder<> &B) { - Module *M = Caller->getParent(); - Type* intTy = Len->getType(); - Type *VoidPtrTy = PointerType::getUnqual(B.getInt8Ty()); - Type *Tys[3] ={VoidPtrTy, VoidPtrTy, intTy}; - Value *MemCpy = Intrinsic::getDeclaration(M, Intrinsic::memcpy, llvm::makeArrayRef(Tys, 3)); - - return B.CreateCall5(MemCpy, CastToCStr(Dst, B), CastToCStr(Src, B), Len, - ConstantInt::get(B.getInt32Ty(), Align), B.getFalse()); + return B.CreateMemCpy(CastToCStr(Dst, B), CastToCStr(Src, B), Len, Align, false); } //===----------------------------------------------------------------------===// @@ -312,18 +300,10 @@ namespace { void InitOptimizations(); bool runOnFunction(Function &F); -#if LDC_LLVM_VER >= 302 bool runOnce(Function &F, const DataLayout& DL, AliasAnalysis& AA); -#else - bool runOnce(Function &F, const TargetData& TD, AliasAnalysis& AA); -#endif virtual void getAnalysisUsage(AnalysisUsage &AU) const { -#if LDC_LLVM_VER >= 302 AU.addRequired(); -#else - AU.addRequired(); -#endif AU.addRequired(); } }; @@ -373,11 +353,7 @@ bool SimplifyDRuntimeCalls::runOnFunction(Function &F) { if (Optimizations.empty()) InitOptimizations(); -#if LDC_LLVM_VER >= 302 - const DataLayout &TD = getAnalysis(); -#else - const TargetData &TD = getAnalysis(); -#endif + const DataLayout &DL = getAnalysis(); AliasAnalysis &AA = getAnalysis(); // Iterate to catch opportunities opened up by other optimizations, @@ -388,18 +364,14 @@ bool SimplifyDRuntimeCalls::runOnFunction(Function &F) { bool EverChanged = false; bool Changed; do { - Changed = runOnce(F, TD, AA); + Changed = runOnce(F, DL, AA); EverChanged |= Changed; } while (Changed); return EverChanged; } -#if LDC_LLVM_VER >= 302 -bool SimplifyDRuntimeCalls::runOnce(Function &F, const DataLayout& TD, AliasAnalysis& AA) { -#else -bool SimplifyDRuntimeCalls::runOnce(Function &F, const TargetData& TD, AliasAnalysis& AA) { -#endif +bool SimplifyDRuntimeCalls::runOnce(Function &F, const DataLayout& DL, AliasAnalysis& AA) { IRBuilder<> Builder(F.getContext()); bool Changed = false; @@ -426,7 +398,7 @@ bool SimplifyDRuntimeCalls::runOnce(Function &F, const TargetData& TD, AliasAnal Builder.SetInsertPoint(BB, I); // Try to optimize this call. - Value *Result = OMI->second->OptimizeCall(CI, Changed, TD, AA, Builder); + Value *Result = OMI->second->OptimizeCall(CI, Changed, DL, AA, Builder); if (Result == 0) continue; DEBUG(errs() << "SimplifyDRuntimeCalls simplified: " << *CI; diff --git a/ir/irfuncty.h b/ir/irfuncty.h index f2dfd419..8d6877f0 100644 --- a/ir/irfuncty.h +++ b/ir/irfuncty.h @@ -33,6 +33,7 @@ namespace llvm { class Value; class Instruction; class Function; + class FunctionType; } // represents a function type argument @@ -87,6 +88,9 @@ struct IrFuncTyArg // represents a function type struct IrFuncTy { + // The final LLVM type + llvm::FunctionType* funcType; + // return value IrFuncTyArg* ret; @@ -111,7 +115,8 @@ struct IrFuncTy bool reverseParams; IrFuncTy() - : ret(NULL), + : funcType(0), + ret(NULL), arg_sret(NULL), arg_this(NULL), arg_nest(NULL), @@ -126,7 +131,8 @@ struct IrFuncTy // Copy constructor and operator= seems to be required for MSC IrFuncTy(const IrFuncTy& rhs) - : ret(rhs.ret), + : funcType(ths.funcType), + ret(rhs.ret), args(IrFuncTy::ArgList(rhs.args)), arg_sret(rhs.arg_sret), arg_this(rhs.arg_this), @@ -139,6 +145,7 @@ struct IrFuncTy IrFuncTy& operator=(const IrFuncTy& rhs) { + funcType = rhs.funcType; ret = rhs.ret; args = IrFuncTy::ArgList(rhs.args); arg_sret = rhs.arg_sret; @@ -153,6 +160,7 @@ struct IrFuncTy #endif void reset() { + funcType = 0; ret = NULL; arg_sret = arg_this = arg_nest = arg_arguments = arg_argptr = NULL; #if defined(_MSC_VER)