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;
 }
 
--- a/tests/mini/norun_debug11.d	Sat May 09 08:58:41 2009 +0200
+++ b/tests/mini/norun_debug11.d	Sat May 09 08:58:55 2009 +0200
@@ -28,6 +28,6 @@
 
     auto ci = c.classinfo;
 
-    int* fail;
+    int* fail = cast(int*) 1;
     *fail = 0;
 }