blob: 2325279ede9ae00d15d2802245c98001117ae0ec [file] [log] [blame]
//===---- llvm-tree.cpp - Utility functions for working with GCC trees ----===//
//
// Copyright (C) 2010 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 defines utility functions for working with GCC trees.
//===----------------------------------------------------------------------===//
// Plugin headers
#include "llvm-tree.h"
// LLVM headers
#include "llvm/ADT/Twine.h"
// System headers
#include <gmp.h>
// GCC headers
extern "C" {
#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 "target.h"
#include "tree.h"
}
using namespace llvm;
/// concatIfNotEmpty - Concatenate the given strings if they are both non-empty.
/// Otherwise return the empty string.
static std::string concatIfNotEmpty(const std::string &Left,
const std::string &Right) {
if (Left.empty() || Right.empty())
return std::string();
return Left + Right;
}
/// getDescriptiveName - Return a helpful name for the given tree, or an empty
/// string if no sensible name was found. These names are used to make the IR
/// more readable, and have no official status.
std::string llvm::getDescriptiveName(tree t) {
if (!t) return std::string(); // Occurs when recursing.
// Name identifier nodes after their contents. This gives the desired effect
// when called recursively.
if (TREE_CODE(t) == IDENTIFIER_NODE)
return std::string(IDENTIFIER_POINTER(t), IDENTIFIER_LENGTH(t));
// Handle declarations of all kinds.
if (DECL_P(t)) {
// If the declaration comes with a name then use it.
if (DECL_NAME(t)) // Always an identifier node.
return std::string(IDENTIFIER_POINTER(DECL_NAME(t)),
IDENTIFIER_LENGTH(DECL_NAME(t)));
// Use a generic name for function results.
if (TREE_CODE(t) == RESULT_DECL)
return "<retval>";
// Labels have their own numeric unique identifiers.
if (TREE_CODE(t) == LABEL_DECL && LABEL_DECL_UID(t) != -1) {
Twine LUID(LABEL_DECL_UID(t));
return ("L" + LUID).str();
}
// Otherwise use the generic UID.
const char *Annotation = TREE_CODE(t) == CONST_DECL ? "C." : "D.";
Twine UID(DECL_UID(t));
return (Annotation + UID).str();
}
// Handle types of all kinds.
if (TYPE_P(t)) {
// If the type comes with a name then use it.
const std::string &TypeName = getDescriptiveName(TYPE_NAME(t));
if (!TypeName.empty()) {
// Annotate the name with a description of the type's class.
if (TREE_CODE(t) == ENUMERAL_TYPE)
return "enum." + TypeName;
if (TREE_CODE(t) == RECORD_TYPE)
return "struct." + TypeName;
if (TREE_CODE(t) == QUAL_UNION_TYPE)
return "qualunion." + TypeName;
if (TREE_CODE(t) == UNION_TYPE)
return "union." + TypeName;
return TypeName;
}
// Try to deduce a useful name.
if (TREE_CODE(t) == ARRAY_TYPE)
// If the element type is E, name the array E[] (regardless of the number
// of dimensions).
return concatIfNotEmpty(getDescriptiveName(TREE_TYPE(t)), "[]");
if (TREE_CODE(t) == COMPLEX_TYPE)
// If the element type is E, name the complex number complex.E.
return concatIfNotEmpty("complex.", getDescriptiveName(TREE_TYPE(t)));
if (TREE_CODE(t) == POINTER_TYPE)
// If the element type is E, name the pointer E*.
return concatIfNotEmpty(getDescriptiveName(TREE_TYPE(t)), "*");
if (TREE_CODE(t) == REFERENCE_TYPE)
// If the element type is E, name the reference E&.
return concatIfNotEmpty(getDescriptiveName(TREE_TYPE(t)), "&");
return TypeName;
}
// Handle SSA names.
if (TREE_CODE(t) == SSA_NAME) {
Twine NameVersion(SSA_NAME_VERSION(t));
return concatIfNotEmpty(getDescriptiveName(SSA_NAME_VAR(t)),
("_" + NameVersion).str());
}
// A mysterious tree, just give up.
return std::string();
}