//=----------- Aliasing.cpp - Type-based alias analysis metadata ----------*-=// // // Copyright (C) 2012 to 2013 Duncan Sands. // // This file is part of DragonEgg. // // DragonEgg is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free Software // Foundation; either version 2, or (at your option) any later version. // // DragonEgg is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR // A PARTICULAR PURPOSE. See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along with // DragonEgg; see the file COPYING. If not, write to the Free Software // Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. // //===----------------------------------------------------------------------===// // This file declares routines for generating TBAA metadata from what GCC knows // about pointer aliasing. //===----------------------------------------------------------------------===// // Plugin headers #include "dragonegg/Aliasing.h" #include "llvm/ADT/SmallVector.h" // LLVM headers #include "llvm/ADT/Twine.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Metadata.h" // System headers #include #include // GCC headers #include "auto-host.h" #ifndef ENABLE_BUILD_WITH_CXX #include // Otherwise included by system.h with C linkage. extern "C" { #endif #include "config.h" // Stop GCC declaring 'getopt' as it can clash with the system's declaration. #undef HAVE_DECL_GETOPT #include "system.h" #include "coretypes.h" #include "tm.h" #include "tree.h" #include "alias.h" #ifndef ENABLE_BUILD_WITH_CXX } // extern "C" #endif // Trees header. #include "dragonegg/Trees.h" using namespace llvm; static LLVMContext &Context = getGlobalContext(); /// getTBAARoot - Return the root of the TBAA tree for this compilation unit. static MDNode *getTBAARoot() { static MDNode *Root; if (!Root) { // Create the root node. This must be unique to the compilation unit since // the names of the nodes we hang off it have no intrinsic meaning: nodes // from different compilation units must not be merged even if they have the // same name. MDBuilder MDHelper(Context); Root = MDHelper.createAnonymousTBAARoot(); } return Root; } /// describeAliasSet - Return TBAA metadata describing what a load from or store /// to the given tree may alias. MDNode *describeAliasSet(tree t) { alias_set_type alias_set = get_alias_set(t); // Alias set 0 is the root of the alias graph and can alias anything. A // negative value represents an unknown alias set, which as far as we know // may also alias anything. if (alias_set <= 0) return 0; // The difficulty here is that GCC's alias sets are the nodes of a directed // acyclic graph (DAG) rooted at 0, and in complicated cases it really is a // DAG and not a tree. This is due to record types: the DAG has a node for // each record type with, for every field, an edge from the node to the node // for the field's type. As a result the leaves of the DAG are usually scalar // types, with an incoming edge from every record type with a field with that // scalar type. On the other hand, LLVM requires TBAA nodes to form a tree. // In short we need to come up with a tree and a graph map (i.e. a map that // takes nodes to nodes and edges to edges) from GCC's DAG to this tree. (An // alternative is to complicate LLVM so that it too uses DAGs for TBAA). An // additional difficulty is that we don't actually know the edges in the DAG: // GCC's alias analysis interface does not expose them. All that we have is // alias_set_subset_of(s, t) which returns true iff there is a path from t to // s in the DAG. Finally, we don't know the nodes of the DAG either! We only // discover them progressively as we convert functions. // For the moment we take a very simple approach: we only use the leaf nodes // of GCC's DAG. This means that we do a good job for scalars and a poor job // for record types, including complex types. static std::map NodeTags; // Node -> metadata map. static SmallVector LeafNodes; // Current set of leaves. std::map::iterator I = NodeTags.find(alias_set); if (I != NodeTags.end()) return I->second; if (LeafNodes.empty()) // Check for a GCC special case: a node can have an edge to the root node. // This is handled automatically (below) except when there are not yet any // known leaf nodes. if (alias_set_subset_of(0, alias_set)) { NodeTags[alias_set] = 0; return 0; } // If there is a path from this node to any leaf node then it is not a leaf // node and can be discarded. for (unsigned i = 0, e = (unsigned) LeafNodes.size(); i != e; ++i) if (alias_set_subset_of(LeafNodes[i], alias_set)) { NodeTags[alias_set] = 0; return 0; } assert(!alias_set_subset_of(0, alias_set) && "'May alias' not transitive?"); // If there is a path from any leaf node to this one then no longer consider // that node to be a leaf. for (unsigned i = (unsigned) LeafNodes.size(); i;) { alias_set_type leaf_set = LeafNodes[--i]; if (alias_set_subset_of(alias_set, leaf_set)) { LeafNodes.erase(LeafNodes.begin() + i); MDNode *&LeafTag = NodeTags[leaf_set]; // It would be neat to strip the tbaa tag from any instructions using it // but it is simpler to just replace it with the root tag everywhere. LeafTag->replaceAllUsesWith(getTBAARoot()); LeafTag = 0; } } // Create metadata describing the new node hanging off root. The name doesn't // matter much but needs to be unique for the compilation unit. tree type = TYPE_CANONICAL(TYPE_MAIN_VARIANT(isa(t) ? t : TREE_TYPE(t))); std::string TreeName = ("alias set " + Twine(alias_set) + ": " + getDescriptiveName(type)).str(); MDBuilder MDHelper(Context); MDNode *AliasTag = MDHelper.createTBAANode(TreeName, getTBAARoot()); NodeTags[alias_set] = AliasTag; LeafNodes.push_back(alias_set); return AliasTag; }