Mercurial > projects > ldc
changeset 1321:d55945bcb02d
Automated merge with http://hg.dsource.org/projects/ldc
author | Christian Kamm <kamm incasoftware de> |
---|---|
date | Sat, 09 May 2009 08:58:55 +0200 |
parents | c32e27f9a61d (diff) 1ad5a58b5c9d (current diff) |
children | b8c2f3e05b52 |
files | |
diffstat | 7 files changed, 134 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/dmd/root/root.c Sat May 09 08:58:41 2009 +0200 +++ b/dmd/root/root.c Sat May 09 08:58:55 2009 +0200 @@ -1594,7 +1594,7 @@ void OutBuffer::write4(unsigned w) { reserve(4); - *(unsigned long *)(this->data + offset) = w; + *(unsigned *)(this->data + offset) = w; offset += 4; }
--- a/gen/metadata.h Sat May 09 08:58:41 2009 +0200 +++ b/gen/metadata.h Sat May 09 08:58:55 2009 +0200 @@ -15,13 +15,31 @@ /// The fields in the metadata node for a TypeInfo instance. /// (Its name will be TD_PREFIX ~ <Name of TypeInfo global>) enum TypeDataFields { - TD_Confirm, /// The TypeInfo this node is for + // TD_Confirm is disabled for now due to an LLVM bug when MDNodes contain + // globals (see http://llvm.org/PR4180 / http://llvm.org/PR4046 ) + TD_Confirm = -1,/// The TypeInfo this node is for. + TD_Type, /// A value of the LLVM type corresponding to this D type // Must be kept last: TD_NumFields /// The number of fields in TypeInfo metadata }; + +// *** Metadata for ClassInfo instances *** +#define CD_PREFIX "llvm.ldc.classinfo." + +/// The fields in the metadata node for a ClassInfo instance. +/// (Its name will be CD_PREFIX ~ <Name of ClassInfo global>) +enum ClassDataFields { + CD_BodyType, /// A value of the LLVM type corresponding to the class body. + CD_Finalize, /// True if this class (or a base class) has a destructor. + CD_CustomDelete,/// True if this class has an overridden delete operator. + + // Must be kept last + CD_NumFields /// The number of fields in ClassInfo metadata +}; + #endif #endif
--- a/gen/passes/GarbageCollect2Stack.cpp Sat May 09 08:58:41 2009 +0200 +++ b/gen/passes/GarbageCollect2Stack.cpp Sat May 09 08:58:55 2009 +0200 @@ -180,6 +180,53 @@ return alloca; } }; + + // FunctionInfo for _d_allocclass + class AllocClassFI : public FunctionInfo { + public: + virtual bool analyze(CallSite CS, const Analysis& A) { + // This call contains no TypeInfo parameter, so don't call the + // base class implementation here... + if (CS.arg_size() != 1) + return false; + Value* arg = CS.getArgument(0)->stripPointerCasts(); + GlobalVariable* ClassInfo = dyn_cast<GlobalVariable>(arg); + if (!ClassInfo) + return false; + + std::string metaname = CD_PREFIX; + metaname.append(ClassInfo->getNameStart(), ClassInfo->getNameEnd()); + + GlobalVariable* global = A.M.getGlobalVariable(metaname); + if (!global || !global->hasInitializer()) + return false; + + MDNode* node = dyn_cast<MDNode>(global->getInitializer()); + if (!node || node->getNumOperands() != CD_NumFields) + return false; + + // Inserting destructor calls is not implemented yet, so classes + // with destructors are ignored for now. + Constant* hasDestructor = dyn_cast<Constant>(node->getOperand(CD_Finalize)); + // We can't stack-allocate if the class has a custom deallocator + // (Custom allocators don't get turned into this runtime call, so + // those can be ignored) + Constant* hasCustomDelete = dyn_cast<Constant>(node->getOperand(CD_CustomDelete)); + if (hasDestructor == NULL || hasCustomDelete == NULL) + return false; + + if (ConstantExpr::getOr(hasDestructor, hasCustomDelete) + != ConstantInt::getFalse()) + return false; + + Ty = node->getOperand(CD_BodyType)->getType(); + return true; + } + + // The default promote() should be fine. + + AllocClassFI() : FunctionInfo(-1, true) {} + }; } @@ -197,6 +244,7 @@ FunctionInfo AllocMemoryT; ArrayFI NewArrayVT; ArrayFI NewArrayT; + AllocClassFI AllocClass; public: static char ID; // Pass identification @@ -233,6 +281,7 @@ KnownFunctions["_d_allocmemoryT"] = &AllocMemoryT; KnownFunctions["_d_newarrayvT"] = &NewArrayVT; KnownFunctions["_d_newarrayT"] = &NewArrayT; + KnownFunctions["_d_allocclass"] = &AllocClass; } static void RemoveCall(Instruction* Inst) { @@ -347,7 +396,7 @@ return NULL; if (node->getNumOperands() != TD_NumFields || - node->getOperand(TD_Confirm)->stripPointerCasts() != ti_global) + (TD_Confirm >= 0 && node->getOperand(TD_Confirm)->stripPointerCasts() != ti_global)) return NULL; return node->getOperand(TD_Type)->getType();
--- a/gen/passes/SimplifyDRuntimeCalls.cpp Sat May 09 08:58:41 2009 +0200 +++ b/gen/passes/SimplifyDRuntimeCalls.cpp Sat May 09 08:58:55 2009 +0200 @@ -29,6 +29,7 @@ using namespace llvm; STATISTIC(NumSimplified, "Number of runtime calls simplified"); +STATISTIC(NumDeleted, "Number of runtime calls deleted"); //===----------------------------------------------------------------------===// // Optimizer Base Class @@ -80,6 +81,11 @@ FT->getParamType(3) != FT->getReturnType()) return 0; + // Whether or not this allocates is irrelevant if the result isn't used. + // Just delete if that's the case. + if (CI->use_empty()) + return CI; + Value* NewLen = CI->getOperand(2); if (Constant* NewCst = dyn_cast<Constant>(NewLen)) { Value* Data = CI->getOperand(4); @@ -182,6 +188,8 @@ void InitOptimizations(); bool runOnFunction(Function &F); + bool runOnce(Function &F, const TargetData& TD); + virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired<TargetData>(); } @@ -233,6 +241,22 @@ const TargetData &TD = getAnalysis<TargetData>(); + // Iterate to catch opportunities opened up by other optimizations, + // such as calls that are only used as arguments to unused calls: + // When the second call gets deleted the first call will become unused, but + // without iteration we wouldn't notice if we inspected the first call + // before the second one. + bool EverChanged = false; + bool Changed; + do { + Changed = runOnce(F, TD); + EverChanged |= Changed; + } while (Changed); + + return EverChanged; +} + +bool SimplifyDRuntimeCalls::runOnce(Function &F, const TargetData& TD) { IRBuilder<> Builder; bool Changed = false; @@ -268,17 +292,24 @@ // Something changed! Changed = true; - ++NumSimplified; + + if (Result == CI) { + assert(CI->use_empty()); + ++NumDeleted; + } else { + ++NumSimplified; + + if (!CI->use_empty()) + CI->replaceAllUsesWith(Result); + + if (!Result->hasName()) + Result->takeName(CI); + } // Inspect the instruction after the call (which was potentially just // added) next. I = CI; ++I; - if (CI != Result && !CI->use_empty()) { - CI->replaceAllUsesWith(Result); - if (!Result->hasName()) - Result->takeName(CI); - } CI->eraseFromParent(); } }
--- a/gen/typinf.cpp Sat May 09 08:58:41 2009 +0200 +++ b/gen/typinf.cpp Sat May 09 08:58:55 2009 +0200 @@ -295,7 +295,8 @@ if (!meta && tid->tinfo->toBasetype()->ty < Terror) { // Construct the fields LLConstant* mdVals[TD_NumFields]; - mdVals[TD_Confirm] = llvm::cast<LLConstant>(irg->value); + if (TD_Confirm >= 0) + mdVals[TD_Confirm] = llvm::cast<LLConstant>(irg->value); mdVals[TD_Type] = llvm::UndefValue::get(DtoType(tid->tinfo)); // Construct the metadata llvm::MDNode* metadata = llvm::MDNode::get(mdVals, TD_NumFields);
--- a/ir/irclass.cpp Sat May 09 08:58:41 2009 +0200 +++ b/ir/irclass.cpp Sat May 09 08:58:55 2009 +0200 @@ -11,6 +11,7 @@ #include "gen/llvmhelpers.h" #include "gen/utils.h" #include "gen/arrays.h" +#include "gen/metadata.h" #include "ir/irstruct.h" #include "ir/irtypeclass.h" @@ -70,6 +71,29 @@ classInfo = new llvm::GlobalVariable( tc->getPA().get(), false, _linkage, NULL, initname, gIR->module); +#ifdef USE_METADATA + // Generate some metadata on this ClassInfo if it's for a class. + + ClassDeclaration* classdecl = aggrdecl->isClassDeclaration(); + if (classdecl && !aggrdecl->isInterfaceDeclaration()) { + // Gather information + const LLType* type = DtoType(aggrdecl->type); + const LLType* bodyType = llvm::cast<LLPointerType>(type)->getElementType(); + bool hasDestructor = (classdecl->dtor != NULL); + bool hasCustomDelete = (classdecl->aggDelete != NULL); + // Construct the fields + LLConstant* mdVals[CD_NumFields]; + mdVals[CD_BodyType] = llvm::UndefValue::get(bodyType); + mdVals[CD_Finalize] = LLConstantInt::get(LLType::Int1Ty, hasDestructor); + mdVals[CD_CustomDelete] = LLConstantInt::get(LLType::Int1Ty, hasCustomDelete); + // Construct the metadata + llvm::MDNode* metadata = llvm::MDNode::get(mdVals, CD_NumFields); + // Insert it into the module + new llvm::GlobalVariable(metadata->getType(), true, + METADATA_LINKAGE_TYPE, metadata, CD_PREFIX + initname, gIR->module); + } +#endif + return classInfo; }