<commit_before>// @(#)root/core/meta:$Id$
// Author: Paul Russo   30/07/2012

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

/** \class TClingTypedefInfo
Emulation of the CINT TypedefInfo class.

The CINT C++ interpreter provides an interface to metadata about
a typedef through the TypedefInfo class.  This class provides the
same functionality, using an interface as close as possible to
TypedefInfo but the typedef metadata comes from the Clang C++
compiler, not CINT.
*/

#include "TClingTypedefInfo.h"

#include "TDictionary.h"
#include "TError.h"
#include "TMetaUtils.h"
#include "Rtypes.h" // for gDebug
#include "ThreadLocalStorage.h"

#include "cling/Interpreter/LookupHelper.h"
#include "cling/Utils/AST.h"
#include "clang/AST/Attr.h"

using namespace clang;

////////////////////////////////////////////////////////////////////////////////
/// Lookup named typedef and initialize the iterator to point to it.
/// Yields a non-iterable TClingTypedefInfo (fIter is invalid).

TClingTypedefInfo::TClingTypedefInfo(cling::Interpreter *interp,
                                     const char *name)
   : fInterp(interp), fFirstTime(true), fDescend(false), fDecl(0), fTitle("")
{
   Init(name);
}

TClingTypedefInfo::TClingTypedefInfo(cling::Interpreter *interp,
                                     const clang::TypedefNameDecl *TdefD)
   : fInterp(interp), fFirstTime(true), fDescend(false), fDecl(TdefD),
     fTitle("")
{
   // Initialize with a clang::TypedefDecl.
   // fIter is invalid; cannot call Next().
}

////////////////////////////////////////////////////////////////////////////////
/// Get the current typedef declaration.

const clang::Decl *TClingTypedefInfo::GetDecl() const
{
   return fDecl;
}

////////////////////////////////////////////////////////////////////////////////
/// Lookup named typedef and reset the iterator to point to it.

void TClingTypedefInfo::Init(const char *name)
{
   fDecl = 0;

   // Reset the iterator to invalid.
   fFirstTime = true;
   fDescend = false;
   fIter = clang::DeclContext::decl_iterator();
   fIterStack.clear();

   // Some trivial early exit, covering many cases in a cheap way.
   if (!name || !*name) return;
   const char lastChar = name[strlen(name) - 1];
   if (lastChar == '*' || lastChar == '&' || !strncmp(name, "const ", 6))
      return;

   // Ask the cling interpreter to lookup the name for us.
   const cling::LookupHelper& lh = fInterp->getLookupHelper();
   clang::QualType QT = lh.findType(name,
                                    gDebug > 5 ? cling::LookupHelper::WithDiagnostics
                                    : cling::LookupHelper::NoDiagnostics);
   if (QT.isNull()) {
      std::string buf = TClassEdit::InsertStd(name);
      if (buf != name) {
         QT = lh.findType(buf,
                          gDebug > 5 ? cling::LookupHelper::WithDiagnostics
                          : cling::LookupHelper::NoDiagnostics);
      }
      if (QT.isNull()) {
         return;
      }
   }
   const clang::TypedefType *td = QT->getAs<clang::TypedefType>();
   // if (fDecl && !llvm::isa<clang::TypedefDecl>(fDecl)) {
   if (!td) {
      // If what the lookup found is not a typedef, ignore it.
      return;
   }
   fDecl = td->getDecl();
}

////////////////////////////////////////////////////////////////////////////////
/// Return true if the current iterator position is valid.

bool TClingTypedefInfo::IsValid() const
{
   return fDecl;
}

////////////////////////////////////////////////////////////////////////////////
/// Increment the iterator, return true if new position is valid.

int TClingTypedefInfo::InternalNext()
{
   if (!*fIter) {
      // Iterator is already invalid.
      if (fFirstTime && fDecl) {
         std::string buf;
         clang::PrintingPolicy Policy(fDecl->getASTContext().getPrintingPolicy());
         llvm::raw_string_ostream stream(buf);
         llvm::dyn_cast<clang::NamedDecl>(fDecl)
            ->getNameForDiagnostic(stream, Policy, /*Qualified=*/false);
         stream.flush();
         Error("TClingTypedefInfo::InternalNext","Next called but iteration not prepared for %s!",buf.c_str());
      }
      return 0;
   }
   // Deserialization might happen during the iteration.
   cling::Interpreter::PushTransactionRAII pushedT(fInterp);
   while (true) {
      // Advance to next usable decl, or return if
      // there is no next usable decl.
      if (fFirstTime) {
         // The cint semantics are strange.
         fFirstTime = false;
      }
      else {
         // Advance the iterator one decl, descending into
         // the current decl context if necessary.
         if (!fDescend) {
            // Do not need to scan the decl context of the
            // current decl, move on to the next decl.
            ++fIter;
         }
         else {
            // Descend into the decl context of the current decl.
            fDescend = false;
            fIterStack.push_back(fIter);
            clang::DeclContext *dc = llvm::cast<clang::DeclContext>(*fIter);
            fIter = dc->decls_begin();
         }
         // Fix it if we went past the end.
         while (!*fIter && fIterStack.size()) {
            fIter = fIterStack.back();
            fIterStack.pop_back();
            ++fIter;
         }
         // Check for final termination.
         if (!*fIter) {
            // We have reached the end of the translation unit, all done.
            fDecl = 0;
            return 0;
         }
      }
      // Return if this decl is a typedef.
      if (llvm::isa<clang::TypedefNameDecl>(*fIter)) {
         fDecl = *fIter;
         return 1;
      }
      // Descend into namespaces and classes.
      clang::Decl::Kind dk = fIter->getKind();
      if ((dk == clang::Decl::Namespace) || (dk == clang::Decl::CXXRecord) ||
            (dk == clang::Decl::ClassTemplateSpecialization)) {
         fDescend = true;
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
/// Increment the iterator.

int TClingTypedefInfo::Next()
{
   return InternalNext();
}

////////////////////////////////////////////////////////////////////////////////
/// Return a bit mask of metadata about the current typedef.

long TClingTypedefInfo::Property() const
{
   if (!IsValid()) {
      return 0L;
   }
   long property = 0L;
   property |= kIsTypedef;
   const clang::TypedefNameDecl *td = llvm::dyn_cast<clang::TypedefNameDecl>(fDecl);
   clang::QualType qt = td->getUnderlyingType().getCanonicalType();
   if (qt.isConstQualified()) {
      property |= kIsConstant;
   }
   while (1) {
      if (qt->isArrayType()) {
         qt = llvm::cast<clang::ArrayType>(qt)->getElementType();
         continue;
      }
      else if (qt->isReferenceType()) {
         property |= kIsReference;
         qt = llvm::cast<clang::ReferenceType>(qt)->getPointeeType();
         continue;
      }
      else if (qt->isPointerType()) {
         property |= kIsPointer;
         if (qt.isConstQualified()) {
            property |= kIsConstPointer;
         }
         qt = llvm::cast<clang::PointerType>(qt)->getPointeeType();
         continue;
      }
      else if (qt->isMemberPointerType()) {
         qt = llvm::cast<clang::MemberPointerType>(qt)->getPointeeType();
         continue;
      }
      break;
   }
   if (qt->isBuiltinType()) {
      property |= kIsFundamental;
   }
   if (qt.isConstQualified()) {
      property |= kIsConstant;
   }
   return property;
}

////////////////////////////////////////////////////////////////////////////////
/// Return the size in bytes of the underlying type of the current typedef.

int TClingTypedefInfo::Size() const
{
   if (!IsValid()) {
      return 1;
   }
   clang::ASTContext &context = fDecl->getASTContext();
   const clang::TypedefNameDecl *td = llvm::dyn_cast<clang::TypedefNameDecl>(fDecl);
   clang::QualType qt = td->getUnderlyingType();
   if (qt->isDependentType()) {
      // The underlying type is dependent on a template parameter,
      // we have no idea what it is yet.
      return 0;
   }
   if (const clang::RecordType *rt = qt->getAs<clang::RecordType>()) {
      if (!rt->getDecl()->getDefinition()) {
         // This is a typedef to a forward-declared type.
         return 0;
      }
   }
   // Note: This is an int64_t.
   clang::CharUnits::QuantityType quantity =
      context.getTypeSizeInChars(qt).getQuantity();
   // Truncate cast to fit the CINT interface.
   return static_cast<int>(quantity);
}

////////////////////////////////////////////////////////////////////////////////
/// Get the name of the underlying type of the current typedef.

const char *TClingTypedefInfo::TrueName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
{
   if (!IsValid()) {
      return "(unknown)";
   }
   // Note: This must be static because we return a pointer to the internals.
   TTHREAD_TLS_DECL( std::string, truename);
   truename.clear();
   const clang::TypedefNameDecl *td = llvm::dyn_cast<clang::TypedefNameDecl>(fDecl);
   clang::QualType underlyingType = td->getUnderlyingType();
   if (underlyingType->isBooleanType()) {
      return "bool";
   }
   const clang::ASTContext &ctxt = fInterp->getCI()->getASTContext();
   ROOT::TMetaUtils::GetNormalizedName(truename, ctxt.getTypedefType(td), *fInterp, normCtxt);

   return truename.c_str();
}

////////////////////////////////////////////////////////////////////////////////
/// Get the name of the current typedef.

const char *TClingTypedefInfo::Name() const
{
   if (!IsValid()) {
      return "(unknown)";
   }
   // Note: This must be static because we return a pointer to the internals.
   TTHREAD_TLS_DECL( std::string, fullname);
   fullname.clear();
   const clang::TypedefNameDecl *td = llvm::dyn_cast<clang::TypedefNameDecl>(fDecl);
   const clang::ASTContext &ctxt = fDecl->getASTContext();
   ROOT::TMetaUtils::GetFullyQualifiedTypeName(fullname,ctxt.getTypedefType(td),*fInterp);
   return fullname.c_str();
}

////////////////////////////////////////////////////////////////////////////////

const char *TClingTypedefInfo::Title()
{
   if (!IsValid()) {
      return 0;
   }
   //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
   //if (fTitle.size())
   //   return fTitle.c_str();

   // Try to get the comment either from the annotation or the header file if present

   // Iterate over the redeclarations, we can have multiple definitions in the
   // redecl chain (came from merging of pcms).
   if (const TypedefNameDecl *TND = llvm::dyn_cast<TypedefNameDecl>(GetDecl())) {
      if ( (TND = ROOT::TMetaUtils::GetAnnotatedRedeclarable(TND)) ) {
         if (AnnotateAttr *A = TND->getAttr<AnnotateAttr>()) {
            fTitle = A->getAnnotation().str();
            return fTitle.c_str();
         }
      }
   }
   else if (!GetDecl()->isFromASTFile()) {
      // Try to get the comment from the header file if present
      // but not for decls from AST file, where rootcling would have
      // created an annotation
      fTitle = ROOT::TMetaUtils::GetComment(*GetDecl()).str();
   }
   return fTitle.c_str();
}

<commit_msg>Decls might get deserialized (see future tutorials/v7/simple.py).<commit_after>// @(#)root/core/meta:$Id$
// Author: Paul Russo   30/07/2012

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

/** \class TClingTypedefInfo
Emulation of the CINT TypedefInfo class.

The CINT C++ interpreter provides an interface to metadata about
a typedef through the TypedefInfo class.  This class provides the
same functionality, using an interface as close as possible to
TypedefInfo but the typedef metadata comes from the Clang C++
compiler, not CINT.
*/

#include "TClingTypedefInfo.h"

#include "TDictionary.h"
#include "TError.h"
#include "TMetaUtils.h"
#include "Rtypes.h" // for gDebug
#include "ThreadLocalStorage.h"

#include "cling/Interpreter/LookupHelper.h"
#include "cling/Utils/AST.h"
#include "clang/AST/Attr.h"

using namespace clang;

////////////////////////////////////////////////////////////////////////////////
/// Lookup named typedef and initialize the iterator to point to it.
/// Yields a non-iterable TClingTypedefInfo (fIter is invalid).

TClingTypedefInfo::TClingTypedefInfo(cling::Interpreter *interp,
                                     const char *name)
   : fInterp(interp), fFirstTime(true), fDescend(false), fDecl(0), fTitle("")
{
   Init(name);
}

TClingTypedefInfo::TClingTypedefInfo(cling::Interpreter *interp,
                                     const clang::TypedefNameDecl *TdefD)
   : fInterp(interp), fFirstTime(true), fDescend(false), fDecl(TdefD),
     fTitle("")
{
   // Initialize with a clang::TypedefDecl.
   // fIter is invalid; cannot call Next().
}

////////////////////////////////////////////////////////////////////////////////
/// Get the current typedef declaration.

const clang::Decl *TClingTypedefInfo::GetDecl() const
{
   return fDecl;
}

////////////////////////////////////////////////////////////////////////////////
/// Lookup named typedef and reset the iterator to point to it.

void TClingTypedefInfo::Init(const char *name)
{
   fDecl = 0;

   // Reset the iterator to invalid.
   fFirstTime = true;
   fDescend = false;
   fIter = clang::DeclContext::decl_iterator();
   fIterStack.clear();

   // Some trivial early exit, covering many cases in a cheap way.
   if (!name || !*name) return;
   const char lastChar = name[strlen(name) - 1];
   if (lastChar == '*' || lastChar == '&' || !strncmp(name, "const ", 6))
      return;

   // Ask the cling interpreter to lookup the name for us.
   const cling::LookupHelper& lh = fInterp->getLookupHelper();
   clang::QualType QT = lh.findType(name,
                                    gDebug > 5 ? cling::LookupHelper::WithDiagnostics
                                    : cling::LookupHelper::NoDiagnostics);
   if (QT.isNull()) {
      std::string buf = TClassEdit::InsertStd(name);
      if (buf != name) {
         QT = lh.findType(buf,
                          gDebug > 5 ? cling::LookupHelper::WithDiagnostics
                          : cling::LookupHelper::NoDiagnostics);
      }
      if (QT.isNull()) {
         return;
      }
   }
   const clang::TypedefType *td = QT->getAs<clang::TypedefType>();
   // if (fDecl && !llvm::isa<clang::TypedefDecl>(fDecl)) {
   if (!td) {
      // If what the lookup found is not a typedef, ignore it.
      return;
   }
   fDecl = td->getDecl();
}

////////////////////////////////////////////////////////////////////////////////
/// Return true if the current iterator position is valid.

bool TClingTypedefInfo::IsValid() const
{
   return fDecl;
}

////////////////////////////////////////////////////////////////////////////////
/// Increment the iterator, return true if new position is valid.

int TClingTypedefInfo::InternalNext()
{
   if (!*fIter) {
      // Iterator is already invalid.
      if (fFirstTime && fDecl) {
         std::string buf;
         clang::PrintingPolicy Policy(fDecl->getASTContext().getPrintingPolicy());
         llvm::raw_string_ostream stream(buf);
         llvm::dyn_cast<clang::NamedDecl>(fDecl)
            ->getNameForDiagnostic(stream, Policy, /*Qualified=*/false);
         stream.flush();
         Error("TClingTypedefInfo::InternalNext","Next called but iteration not prepared for %s!",buf.c_str());
      }
      return 0;
   }
   // Deserialization might happen during the iteration.
   cling::Interpreter::PushTransactionRAII pushedT(fInterp);
   while (true) {
      // Advance to next usable decl, or return if
      // there is no next usable decl.
      if (fFirstTime) {
         // The cint semantics are strange.
         fFirstTime = false;
      }
      else {
         // Advance the iterator one decl, descending into
         // the current decl context if necessary.
         if (!fDescend) {
            // Do not need to scan the decl context of the
            // current decl, move on to the next decl.
            ++fIter;
         }
         else {
            // Descend into the decl context of the current decl.
            fDescend = false;
            fIterStack.push_back(fIter);
            clang::DeclContext *dc = llvm::cast<clang::DeclContext>(*fIter);
            fIter = dc->decls_begin();
         }
         // Fix it if we went past the end.
         while (!*fIter && fIterStack.size()) {
            fIter = fIterStack.back();
            fIterStack.pop_back();
            ++fIter;
         }
         // Check for final termination.
         if (!*fIter) {
            // We have reached the end of the translation unit, all done.
            fDecl = 0;
            return 0;
         }
      }
      // Return if this decl is a typedef.
      if (llvm::isa<clang::TypedefNameDecl>(*fIter)) {
         fDecl = *fIter;
         return 1;
      }
      // Descend into namespaces and classes.
      clang::Decl::Kind dk = fIter->getKind();
      if ((dk == clang::Decl::Namespace) || (dk == clang::Decl::CXXRecord) ||
            (dk == clang::Decl::ClassTemplateSpecialization)) {
         fDescend = true;
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
/// Increment the iterator.

int TClingTypedefInfo::Next()
{
   return InternalNext();
}

////////////////////////////////////////////////////////////////////////////////
/// Return a bit mask of metadata about the current typedef.

long TClingTypedefInfo::Property() const
{
   if (!IsValid()) {
      return 0L;
   }
   long property = 0L;
   property |= kIsTypedef;
   const clang::TypedefNameDecl *td = llvm::dyn_cast<clang::TypedefNameDecl>(fDecl);
   clang::QualType qt = td->getUnderlyingType().getCanonicalType();
   if (qt.isConstQualified()) {
      property |= kIsConstant;
   }
   while (1) {
      if (qt->isArrayType()) {
         qt = llvm::cast<clang::ArrayType>(qt)->getElementType();
         continue;
      }
      else if (qt->isReferenceType()) {
         property |= kIsReference;
         qt = llvm::cast<clang::ReferenceType>(qt)->getPointeeType();
         continue;
      }
      else if (qt->isPointerType()) {
         property |= kIsPointer;
         if (qt.isConstQualified()) {
            property |= kIsConstPointer;
         }
         qt = llvm::cast<clang::PointerType>(qt)->getPointeeType();
         continue;
      }
      else if (qt->isMemberPointerType()) {
         qt = llvm::cast<clang::MemberPointerType>(qt)->getPointeeType();
         continue;
      }
      break;
   }
   if (qt->isBuiltinType()) {
      property |= kIsFundamental;
   }
   if (qt.isConstQualified()) {
      property |= kIsConstant;
   }
   return property;
}

////////////////////////////////////////////////////////////////////////////////
/// Return the size in bytes of the underlying type of the current typedef.

int TClingTypedefInfo::Size() const
{
   if (!IsValid()) {
      return 1;
   }
   clang::ASTContext &context = fDecl->getASTContext();
   const clang::TypedefNameDecl *td = llvm::dyn_cast<clang::TypedefNameDecl>(fDecl);
   clang::QualType qt = td->getUnderlyingType();
   if (qt->isDependentType()) {
      // The underlying type is dependent on a template parameter,
      // we have no idea what it is yet.
      return 0;
   }
   if (const clang::RecordType *rt = qt->getAs<clang::RecordType>()) {
      if (!rt->getDecl()->getDefinition()) {
         // This is a typedef to a forward-declared type.
         return 0;
      }
   }

   // Deserialization might happen during the size calculation.
   cling::Interpreter::PushTransactionRAII pushedT(fInterp);

   // Note: This is an int64_t.
   clang::CharUnits::QuantityType quantity =
      context.getTypeSizeInChars(qt).getQuantity();
   // Truncate cast to fit the CINT interface.
   return static_cast<int>(quantity);
}

////////////////////////////////////////////////////////////////////////////////
/// Get the name of the underlying type of the current typedef.

const char *TClingTypedefInfo::TrueName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
{
   if (!IsValid()) {
      return "(unknown)";
   }
   // Note: This must be static because we return a pointer to the internals.
   TTHREAD_TLS_DECL( std::string, truename);
   truename.clear();
   const clang::TypedefNameDecl *td = llvm::dyn_cast<clang::TypedefNameDecl>(fDecl);
   clang::QualType underlyingType = td->getUnderlyingType();
   if (underlyingType->isBooleanType()) {
      return "bool";
   }
   const clang::ASTContext &ctxt = fInterp->getCI()->getASTContext();
   ROOT::TMetaUtils::GetNormalizedName(truename, ctxt.getTypedefType(td), *fInterp, normCtxt);

   return truename.c_str();
}

////////////////////////////////////////////////////////////////////////////////
/// Get the name of the current typedef.

const char *TClingTypedefInfo::Name() const
{
   if (!IsValid()) {
      return "(unknown)";
   }
   // Note: This must be static because we return a pointer to the internals.
   TTHREAD_TLS_DECL( std::string, fullname);
   fullname.clear();
   const clang::TypedefNameDecl *td = llvm::dyn_cast<clang::TypedefNameDecl>(fDecl);
   const clang::ASTContext &ctxt = fDecl->getASTContext();
   ROOT::TMetaUtils::GetFullyQualifiedTypeName(fullname,ctxt.getTypedefType(td),*fInterp);
   return fullname.c_str();
}

////////////////////////////////////////////////////////////////////////////////

const char *TClingTypedefInfo::Title()
{
   if (!IsValid()) {
      return 0;
   }
   //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
   //if (fTitle.size())
   //   return fTitle.c_str();

   // Try to get the comment either from the annotation or the header file if present

   // Iterate over the redeclarations, we can have multiple definitions in the
   // redecl chain (came from merging of pcms).
   if (const TypedefNameDecl *TND = llvm::dyn_cast<TypedefNameDecl>(GetDecl())) {
      if ( (TND = ROOT::TMetaUtils::GetAnnotatedRedeclarable(TND)) ) {
         if (AnnotateAttr *A = TND->getAttr<AnnotateAttr>()) {
            fTitle = A->getAnnotation().str();
            return fTitle.c_str();
         }
      }
   }
   else if (!GetDecl()->isFromASTFile()) {
      // Try to get the comment from the header file if present
      // but not for decls from AST file, where rootcling would have
      // created an annotation
      fTitle = ROOT::TMetaUtils::GetComment(*GetDecl()).str();
   }
   return fTitle.c_str();
}

<|endoftext|>


<commit_before>#pragma once
/*
* Covariant Mozart Utility Library: Switcher
*
* This program 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 3 of the License, or
* any later version.
*
* This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) 2016 Michael Lee(李登淳)
* Email: China-LDC@outlook.com
* Github: https://github.com/mikecovlee
* Website: http://ldc.atd3.cn
*
* Version: 17.1.0
*/
#include "./base.hpp"
#include "./any.hpp"
#include "./function.hpp"
#include "./tuple.hpp"
#include <deque>

namespace cov {
	class switcher final {
	public:
		typedef cov::function<void()> case_type;
	private:
		std::deque<cov::tuple<cov::any,cov::function<void()>>> mCases;
		cov::function<void()> mDefault;
		const cov::any mCondition;
	public:
		switcher()=delete;
		switcher(const cov::any& val):mCondition(val) {}
		switcher(switcher&&) noexcept=delete;
		switcher(const switcher&)=delete;
		~switcher()=default;
		void add_case(const cov::any& head,const case_type& body) {
			if(object::show_warning&&head.type()!=mCondition.type())
				throw cov::warning("W0001");
			bool exsist=false;
			for(auto& it:mCases) {
				if(it.get<0>()==head) {
					exsist=true;
					if(object::show_warning)
						throw cov::warning("W0002");
					else
						it.get<1>()=body;
					break;
				}
			}
			if(!exsist)
				mCases.push_back(tuple<cov::any,cov::function<void()>>(head,body));
		}
		void add_default(const case_type& body) {
			if(mDefault.callable()&&object::show_warning)
				throw cov::warning("W0002");
			mDefault=body;
		}
		void perform() {
			for(auto& it:mCases) {
				if(it.get<0>()==mCondition&&it.get<1>().callable()) {
					it.get<1>().call();
					return;
				}
			}
			if(mDefault.callable())
				mDefault.call();
		}
	};
	class switcher_stack final {
		std::deque<switcher*> mStack;
	public:
		switcher_stack()=default;
		switcher_stack(switcher_stack&&) noexcept=delete;
		switcher_stack(const switcher_stack&)=delete;
		~switcher_stack() {
			for(auto&it:mStack)
				delete it;
		}
		switcher& top() {
			return *mStack.front();
		}
		void push(const cov::any& val) {
			mStack.push_front(new switcher(val));
		}
		void pop() {
			delete mStack.front();
			mStack.pop_front();
		}
	};
	switcher_stack cov_switchers;
}

#define Switch(obj) cov::cov_switchers.push(obj);
#define EndSwitch cov::cov_switchers.top().perform();cov::cov_switchers.pop();
#define Case(obj) cov::cov_switchers.top().add_case(obj,[&]{
#define Default cov::cov_switchers.top().add_default([&]{
#define EndCase });<commit_msg>修复与Windows.h共存时名称冲突的问题<commit_after>#pragma once
/*
* Covariant Mozart Utility Library: Switcher
*
* This program 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 3 of the License, or
* any later version.
*
* This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) 2016 Michael Lee(李登淳)
* Email: China-LDC@outlook.com
* Github: https://github.com/mikecovlee
* Website: http://ldc.atd3.cn
*
* Version: 17.1.0
*/
#include "./base.hpp"
#include "./any.hpp"
#include "./function.hpp"
#include "./tuple.hpp"
#include <deque>

namespace cov {
	class switcher final {
	public:
		typedef cov::function<void()> case_type;
	private:
		std::deque<cov::tuple<cov::any,cov::function<void()>>> mCases;
		cov::function<void()> mDefault;
		const cov::any mCondition;
	public:
		switcher()=delete;
		switcher(const cov::any& val):mCondition(val) {}
		switcher(switcher&&) noexcept=delete;
		switcher(const switcher&)=delete;
		~switcher()=default;
		void add_case(const cov::any& head,const case_type& body) {
			if(object::show_warning&&head.type()!=mCondition.type())
				throw cov::warning("W0001");
			bool exsist=false;
			for(auto& it:mCases) {
				if(it.get<0>()==head) {
					exsist=true;
					if(object::show_warning)
						throw cov::warning("W0002");
					else
						it.get<1>()=body;
					break;
				}
			}
			if(!exsist)
				mCases.push_back(tuple<cov::any,cov::function<void()>>(head,body));
		}
		void add_default(const case_type& body) {
			if(mDefault.callable()&&object::show_warning)
				throw cov::warning("W0002");
			mDefault=body;
		}
		void perform() {
			for(auto& it:mCases) {
				if(it.get<0>()==mCondition&&it.get<1>().callable()) {
					it.get<1>().call();
					return;
				}
			}
			if(mDefault.callable())
				mDefault.call();
		}
	};
	class switcher_stack final {
		std::deque<switcher*> mStack;
	public:
		switcher_stack()=default;
		switcher_stack(switcher_stack&&) noexcept=delete;
		switcher_stack(const switcher_stack&)=delete;
		~switcher_stack() {
			for(auto&it:mStack)
				delete it;
		}
		switcher& top() {
			return *mStack.front();
		}
		void push(const cov::any& val) {
			mStack.push_front(new switcher(val));
		}
		void pop() {
			delete mStack.front();
			mStack.pop_front();
		}
	};
	switcher_stack cov_switchers;
}

#define CovSwitch(obj) cov::cov_switchers.push(obj);
#define EndCovSwitch cov::cov_switchers.top().perform();cov::cov_switchers.pop();
#define CovCase(obj) cov::cov_switchers.top().add_case(obj,[&]{
#define CovDefault cov::cov_switchers.top().add_default([&]{
#define EndCovCase });<|endoftext|>


<commit_before>//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AsmPrinter class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Constants.h"
#include "llvm/Instruction.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

bool AsmPrinter::doInitialization(Module &M) {
  Mang = new Mangler(M, GlobalPrefix);
  return false;
}

bool AsmPrinter::doFinalization(Module &M) {
  delete Mang; Mang = 0;
  return false;
}

void AsmPrinter::setupMachineFunction(MachineFunction &MF) {
  // What's my mangled name?
  CurrentFnName = Mang->getValueName((Value*)MF.getFunction());
}

// emitAlignment - Emit an alignment directive to the specified power of two.
void AsmPrinter::emitAlignment(unsigned NumBits) const {
  if (AlignmentIsInBytes) NumBits = 1 << NumBits;
  O << AlignDirective << NumBits << "\n";
}

/// emitZeros - Emit a block of zeros.
///
void AsmPrinter::emitZeros(uint64_t NumZeros) const {
  if (NumZeros) {
    if (ZeroDirective)
      O << ZeroDirective << NumZeros << "\n";
    else {
      for (; NumZeros; --NumZeros)
        O << Data8bitsDirective << "0\n";
    }
  }
}

// Print out the specified constant, without a storage class.  Only the
// constants valid in constant expressions can occur here.
void AsmPrinter::emitConstantValueOnly(const Constant *CV) {
  if (CV->isNullValue() || isa<UndefValue>(CV))
    O << "0";
  else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
    assert(CB == ConstantBool::True);
    O << "1";
  } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
    if (((CI->getValue() << 32) >> 32) == CI->getValue())
      O << CI->getValue();
    else
      O << (uint64_t)CI->getValue();
  else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
    O << CI->getValue();
  else if (isa<GlobalValue>((Value*)CV)) {
    // This is a constant address for a global variable or function. Use the
    // name of the variable or function as the address value, possibly
    // decorating it with GlobalVarAddrPrefix/Suffix or
    // FunctionAddrPrefix/Suffix (these all default to "" )
    if (isa<Function>((Value*)CV))
      O << FunctionAddrPrefix << Mang->getValueName(CV) << FunctionAddrSuffix;
    else
      O << GlobalVarAddrPrefix << Mang->getValueName(CV) << GlobalVarAddrSuffix;
  } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
    const TargetData &TD = TM.getTargetData();
    switch(CE->getOpcode()) {
    case Instruction::GetElementPtr: {
      // generate a symbolic expression for the byte address
      const Constant *ptrVal = CE->getOperand(0);
      std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
      if (int64_t Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
        if (Offset)
          O << "(";
        emitConstantValueOnly(ptrVal);
        if (Offset > 0)
          O << ") + " << Offset;
        else if (Offset < 0)
          O << ") - " << -Offset;
      } else {
        emitConstantValueOnly(ptrVal);
      }
      break;
    }
    case Instruction::Cast: {
      // Support only non-converting or widening casts for now, that is, ones
      // that do not involve a change in value.  This assertion is really gross,
      // and may not even be a complete check.
      Constant *Op = CE->getOperand(0);
      const Type *OpTy = Op->getType(), *Ty = CE->getType();

      // Remember, kids, pointers can be losslessly converted back and forth
      // into 32-bit or wider integers, regardless of signedness. :-P
      assert(((isa<PointerType>(OpTy)
               && (Ty == Type::LongTy || Ty == Type::ULongTy
                   || Ty == Type::IntTy || Ty == Type::UIntTy))
              || (isa<PointerType>(Ty)
                  && (OpTy == Type::LongTy || OpTy == Type::ULongTy
                      || OpTy == Type::IntTy || OpTy == Type::UIntTy))
              || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
                   && OpTy->isLosslesslyConvertibleTo(Ty))))
             && "FIXME: Don't yet support this kind of constant cast expr");
      O << "(";
      emitConstantValueOnly(Op);
      O << ")";
      break;
    }
    case Instruction::Add:
      O << "(";
      emitConstantValueOnly(CE->getOperand(0));
      O << ") + (";
      emitConstantValueOnly(CE->getOperand(1));
      O << ")";
      break;
    default:
      assert(0 && "Unsupported operator!");
    }
  } else {
    assert(0 && "Unknown constant value!");
  }
}

/// toOctal - Convert the low order bits of X into an octal digit.
///
static inline char toOctal(int X) {
  return (X&7)+'0';
}

/// getAsCString - Return the specified array as a C compatible string, only if
/// the predicate isString is true.
///
static void printAsCString(std::ostream &O, const ConstantArray *CVA) {
  assert(CVA->isString() && "Array is not string compatible!");

  O << "\"";
  for (unsigned i = 0; i != CVA->getNumOperands(); ++i) {
    unsigned char C =
        (unsigned char)cast<ConstantInt>(CVA->getOperand(i))->getRawValue();

    if (C == '"') {
      O << "\\\"";
    } else if (C == '\\') {
      O << "\\\\";
    } else if (isprint(C)) {
      O << C;
    } else {
      switch(C) {
      case '\b': O << "\\b"; break;
      case '\f': O << "\\f"; break;
      case '\n': O << "\\n"; break;
      case '\r': O << "\\r"; break;
      case '\t': O << "\\t"; break;
      default:
        O << '\\';
        O << toOctal(C >> 6);
        O << toOctal(C >> 3);
        O << toOctal(C >> 0);
        break;
      }
    }
  }
  O << "\"";
}

/// emitGlobalConstant - Print a general LLVM constant to the .s file.
///
void AsmPrinter::emitGlobalConstant(const Constant *CV) {
  const TargetData &TD = TM.getTargetData();

  if (CV->isNullValue() || isa<UndefValue>(CV)) {
    emitZeros(TD.getTypeSize(CV->getType()));
    return;
  } else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
    if (CVA->isString()) {
      O << AsciiDirective;
      printAsCString(O, CVA);
      O << "\n";
    } else { // Not a string.  Print the values in successive locations
      for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
        emitGlobalConstant(CVA->getOperand(i));
    }
    return;
  } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
    // Print the fields in successive locations. Pad to align if needed!
    const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
    uint64_t sizeSoFar = 0;
    for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
      const Constant* field = CVS->getOperand(i);

      // Check if padding is needed and insert one or more 0s.
      uint64_t fieldSize = TD.getTypeSize(field->getType());
      uint64_t padSize = ((i == e-1? cvsLayout->StructSize
                           : cvsLayout->MemberOffsets[i+1])
                          - cvsLayout->MemberOffsets[i]) - fieldSize;
      sizeSoFar += fieldSize + padSize;

      // Now print the actual field value
      emitGlobalConstant(field);

      // Insert the field padding unless it's zero bytes...
      emitZeros(padSize);
    }
    assert(sizeSoFar == cvsLayout->StructSize &&
           "Layout of constant struct may be incorrect!");
    return;
  } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
    // FP Constants are printed as integer constants to avoid losing
    // precision...
    double Val = CFP->getValue();
    if (CFP->getType() == Type::DoubleTy) {
      if (Data64bitsDirective)
        O << Data64bitsDirective << DoubleToBits(Val) << "\t" << CommentString
          << " double value: " << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32)
          << "\t" << CommentString << " double most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(DoubleToBits(Val))
          << "\t" << CommentString << " double least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(DoubleToBits(Val))
          << "\t" << CommentString << " double least significant word " << Val
          << "\n";
        O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32)
          << "\t" << CommentString << " double most significant word " << Val
          << "\n";
      }
      return;
    } else {
      O << Data32bitsDirective << FloatToBits(Val) << "\t" << CommentString
        << " float " << Val << "\n";
      return;
    }
  } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
    if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
      uint64_t Val = CI->getRawValue();

      if (Data64bitsDirective)
        O << Data64bitsDirective << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
      }
      return;
    }
  }

  const Type *type = CV->getType();
  switch (type->getTypeID()) {
  case Type::BoolTyID:
  case Type::UByteTyID: case Type::SByteTyID:
    O << Data8bitsDirective;
    break;
  case Type::UShortTyID: case Type::ShortTyID:
    O << Data16bitsDirective;
    break;
  case Type::PointerTyID:
    if (TD.getPointerSize() == 8) {
      O << Data64bitsDirective;
      break;
    }
    //Fall through for pointer size == int size
  case Type::UIntTyID: case Type::IntTyID:
    O << Data32bitsDirective;
    break;
  case Type::ULongTyID: case Type::LongTyID:
    assert(Data64bitsDirective &&"Target cannot handle 64-bit constant exprs!");
    O << Data64bitsDirective;
    break;
  case Type::FloatTyID: case Type::DoubleTyID:
    assert (0 && "Should have already output floating point constant.");
  default:
    assert (0 && "Can't handle printing this type of thing");
    break;
  }
  emitConstantValueOnly(CV);
  O << "\n";
}
<commit_msg>add support for .asciz, and enable it by default.  If your target assemblerdoesn't support .asciz, just set AscizDirective to null in your asmprinter. This compiles C strings to:<commit_after>//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AsmPrinter class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Constants.h"
#include "llvm/Instruction.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

bool AsmPrinter::doInitialization(Module &M) {
  Mang = new Mangler(M, GlobalPrefix);
  return false;
}

bool AsmPrinter::doFinalization(Module &M) {
  delete Mang; Mang = 0;
  return false;
}

void AsmPrinter::setupMachineFunction(MachineFunction &MF) {
  // What's my mangled name?
  CurrentFnName = Mang->getValueName((Value*)MF.getFunction());
}

// emitAlignment - Emit an alignment directive to the specified power of two.
void AsmPrinter::emitAlignment(unsigned NumBits) const {
  if (AlignmentIsInBytes) NumBits = 1 << NumBits;
  O << AlignDirective << NumBits << "\n";
}

/// emitZeros - Emit a block of zeros.
///
void AsmPrinter::emitZeros(uint64_t NumZeros) const {
  if (NumZeros) {
    if (ZeroDirective)
      O << ZeroDirective << NumZeros << "\n";
    else {
      for (; NumZeros; --NumZeros)
        O << Data8bitsDirective << "0\n";
    }
  }
}

// Print out the specified constant, without a storage class.  Only the
// constants valid in constant expressions can occur here.
void AsmPrinter::emitConstantValueOnly(const Constant *CV) {
  if (CV->isNullValue() || isa<UndefValue>(CV))
    O << "0";
  else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
    assert(CB == ConstantBool::True);
    O << "1";
  } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
    if (((CI->getValue() << 32) >> 32) == CI->getValue())
      O << CI->getValue();
    else
      O << (uint64_t)CI->getValue();
  else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
    O << CI->getValue();
  else if (isa<GlobalValue>((Value*)CV)) {
    // This is a constant address for a global variable or function. Use the
    // name of the variable or function as the address value, possibly
    // decorating it with GlobalVarAddrPrefix/Suffix or
    // FunctionAddrPrefix/Suffix (these all default to "" )
    if (isa<Function>((Value*)CV))
      O << FunctionAddrPrefix << Mang->getValueName(CV) << FunctionAddrSuffix;
    else
      O << GlobalVarAddrPrefix << Mang->getValueName(CV) << GlobalVarAddrSuffix;
  } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
    const TargetData &TD = TM.getTargetData();
    switch(CE->getOpcode()) {
    case Instruction::GetElementPtr: {
      // generate a symbolic expression for the byte address
      const Constant *ptrVal = CE->getOperand(0);
      std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
      if (int64_t Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
        if (Offset)
          O << "(";
        emitConstantValueOnly(ptrVal);
        if (Offset > 0)
          O << ") + " << Offset;
        else if (Offset < 0)
          O << ") - " << -Offset;
      } else {
        emitConstantValueOnly(ptrVal);
      }
      break;
    }
    case Instruction::Cast: {
      // Support only non-converting or widening casts for now, that is, ones
      // that do not involve a change in value.  This assertion is really gross,
      // and may not even be a complete check.
      Constant *Op = CE->getOperand(0);
      const Type *OpTy = Op->getType(), *Ty = CE->getType();

      // Remember, kids, pointers can be losslessly converted back and forth
      // into 32-bit or wider integers, regardless of signedness. :-P
      assert(((isa<PointerType>(OpTy)
               && (Ty == Type::LongTy || Ty == Type::ULongTy
                   || Ty == Type::IntTy || Ty == Type::UIntTy))
              || (isa<PointerType>(Ty)
                  && (OpTy == Type::LongTy || OpTy == Type::ULongTy
                      || OpTy == Type::IntTy || OpTy == Type::UIntTy))
              || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
                   && OpTy->isLosslesslyConvertibleTo(Ty))))
             && "FIXME: Don't yet support this kind of constant cast expr");
      O << "(";
      emitConstantValueOnly(Op);
      O << ")";
      break;
    }
    case Instruction::Add:
      O << "(";
      emitConstantValueOnly(CE->getOperand(0));
      O << ") + (";
      emitConstantValueOnly(CE->getOperand(1));
      O << ")";
      break;
    default:
      assert(0 && "Unsupported operator!");
    }
  } else {
    assert(0 && "Unknown constant value!");
  }
}

/// toOctal - Convert the low order bits of X into an octal digit.
///
static inline char toOctal(int X) {
  return (X&7)+'0';
}

/// printAsCString - Print the specified array as a C compatible string, only if
/// the predicate isString is true.
///
static void printAsCString(std::ostream &O, const ConstantArray *CVA,
                           unsigned LastElt) {
  assert(CVA->isString() && "Array is not string compatible!");

  O << "\"";
  for (unsigned i = 0; i != LastElt; ++i) {
    unsigned char C =
        (unsigned char)cast<ConstantInt>(CVA->getOperand(i))->getRawValue();

    if (C == '"') {
      O << "\\\"";
    } else if (C == '\\') {
      O << "\\\\";
    } else if (isprint(C)) {
      O << C;
    } else {
      switch(C) {
      case '\b': O << "\\b"; break;
      case '\f': O << "\\f"; break;
      case '\n': O << "\\n"; break;
      case '\r': O << "\\r"; break;
      case '\t': O << "\\t"; break;
      default:
        O << '\\';
        O << toOctal(C >> 6);
        O << toOctal(C >> 3);
        O << toOctal(C >> 0);
        break;
      }
    }
  }
  O << "\"";
}

/// emitGlobalConstant - Print a general LLVM constant to the .s file.
///
void AsmPrinter::emitGlobalConstant(const Constant *CV) {
  const TargetData &TD = TM.getTargetData();

  if (CV->isNullValue() || isa<UndefValue>(CV)) {
    emitZeros(TD.getTypeSize(CV->getType()));
    return;
  } else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
    if (CVA->isString()) {
      unsigned NumElts = CVA->getNumOperands();
      if (AscizDirective && NumElts &&
          cast<ConstantInt>(CVA->getOperand(NumElts-1))->getRawValue() == 0) {
        O << AscizDirective;
        printAsCString(O, CVA, NumElts-1);
      } else {
        O << AsciiDirective;
        printAsCString(O, CVA, NumElts);
      }
      O << "\n";
    } else { // Not a string.  Print the values in successive locations
      for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
        emitGlobalConstant(CVA->getOperand(i));
    }
    return;
  } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
    // Print the fields in successive locations. Pad to align if needed!
    const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
    uint64_t sizeSoFar = 0;
    for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
      const Constant* field = CVS->getOperand(i);

      // Check if padding is needed and insert one or more 0s.
      uint64_t fieldSize = TD.getTypeSize(field->getType());
      uint64_t padSize = ((i == e-1? cvsLayout->StructSize
                           : cvsLayout->MemberOffsets[i+1])
                          - cvsLayout->MemberOffsets[i]) - fieldSize;
      sizeSoFar += fieldSize + padSize;

      // Now print the actual field value
      emitGlobalConstant(field);

      // Insert the field padding unless it's zero bytes...
      emitZeros(padSize);
    }
    assert(sizeSoFar == cvsLayout->StructSize &&
           "Layout of constant struct may be incorrect!");
    return;
  } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
    // FP Constants are printed as integer constants to avoid losing
    // precision...
    double Val = CFP->getValue();
    if (CFP->getType() == Type::DoubleTy) {
      if (Data64bitsDirective)
        O << Data64bitsDirective << DoubleToBits(Val) << "\t" << CommentString
          << " double value: " << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32)
          << "\t" << CommentString << " double most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(DoubleToBits(Val))
          << "\t" << CommentString << " double least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(DoubleToBits(Val))
          << "\t" << CommentString << " double least significant word " << Val
          << "\n";
        O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32)
          << "\t" << CommentString << " double most significant word " << Val
          << "\n";
      }
      return;
    } else {
      O << Data32bitsDirective << FloatToBits(Val) << "\t" << CommentString
        << " float " << Val << "\n";
      return;
    }
  } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
    if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
      uint64_t Val = CI->getRawValue();

      if (Data64bitsDirective)
        O << Data64bitsDirective << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
      }
      return;
    }
  }

  const Type *type = CV->getType();
  switch (type->getTypeID()) {
  case Type::BoolTyID:
  case Type::UByteTyID: case Type::SByteTyID:
    O << Data8bitsDirective;
    break;
  case Type::UShortTyID: case Type::ShortTyID:
    O << Data16bitsDirective;
    break;
  case Type::PointerTyID:
    if (TD.getPointerSize() == 8) {
      O << Data64bitsDirective;
      break;
    }
    //Fall through for pointer size == int size
  case Type::UIntTyID: case Type::IntTyID:
    O << Data32bitsDirective;
    break;
  case Type::ULongTyID: case Type::LongTyID:
    assert(Data64bitsDirective &&"Target cannot handle 64-bit constant exprs!");
    O << Data64bitsDirective;
    break;
  case Type::FloatTyID: case Type::DoubleTyID:
    assert (0 && "Should have already output floating point constant.");
  default:
    assert (0 && "Can't handle printing this type of thing");
    break;
  }
  emitConstantValueOnly(CV);
  O << "\n";
}
<|endoftext|>


<commit_before>//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AsmPrinter class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

bool AsmPrinter::doInitialization(Module &M) {
  Mang = new Mangler(M, GlobalPrefix);
  return false;
}

bool AsmPrinter::doFinalization(Module &M) {
  delete Mang; Mang = 0;
  return false;
}

void AsmPrinter::setupMachineFunction(MachineFunction &MF) {
  // What's my mangled name?
  CurrentFnName = Mang->getValueName(MF.getFunction());
}

// emitAlignment - Emit an alignment directive to the specified power of two.
void AsmPrinter::emitAlignment(unsigned NumBits, const GlobalValue *GV) const {
  if (GV && GV->getAlignment())
    NumBits = Log2_32(GV->getAlignment());
  if (NumBits == 0) return;   // No need to emit alignment.
  if (AlignmentIsInBytes) NumBits = 1 << NumBits;
  O << AlignDirective << NumBits << "\n";
}

/// emitZeros - Emit a block of zeros.
///
void AsmPrinter::emitZeros(uint64_t NumZeros) const {
  if (NumZeros) {
    if (ZeroDirective)
      O << ZeroDirective << NumZeros << "\n";
    else {
      for (; NumZeros; --NumZeros)
        O << Data8bitsDirective << "0\n";
    }
  }
}

// Print out the specified constant, without a storage class.  Only the
// constants valid in constant expressions can occur here.
void AsmPrinter::emitConstantValueOnly(const Constant *CV) {
  if (CV->isNullValue() || isa<UndefValue>(CV))
    O << "0";
  else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
    assert(CB == ConstantBool::True);
    O << "1";
  } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
    if (((CI->getValue() << 32) >> 32) == CI->getValue())
      O << CI->getValue();
    else
      O << (uint64_t)CI->getValue();
  else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
    O << CI->getValue();
  else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
    // This is a constant address for a global variable or function. Use the
    // name of the variable or function as the address value, possibly
    // decorating it with GlobalVarAddrPrefix/Suffix or
    // FunctionAddrPrefix/Suffix (these all default to "" )
    if (isa<Function>(GV))
      O << FunctionAddrPrefix << Mang->getValueName(GV) << FunctionAddrSuffix;
    else
      O << GlobalVarAddrPrefix << Mang->getValueName(GV) << GlobalVarAddrSuffix;
  } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
    const TargetData &TD = TM.getTargetData();
    switch(CE->getOpcode()) {
    case Instruction::GetElementPtr: {
      // generate a symbolic expression for the byte address
      const Constant *ptrVal = CE->getOperand(0);
      std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
      if (int64_t Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
        if (Offset)
          O << "(";
        emitConstantValueOnly(ptrVal);
        if (Offset > 0)
          O << ") + " << Offset;
        else if (Offset < 0)
          O << ") - " << -Offset;
      } else {
        emitConstantValueOnly(ptrVal);
      }
      break;
    }
    case Instruction::Cast: {
      // Support only non-converting or widening casts for now, that is, ones
      // that do not involve a change in value.  This assertion is really gross,
      // and may not even be a complete check.
      Constant *Op = CE->getOperand(0);
      const Type *OpTy = Op->getType(), *Ty = CE->getType();

      // Remember, kids, pointers can be losslessly converted back and forth
      // into 32-bit or wider integers, regardless of signedness. :-P
      assert(((isa<PointerType>(OpTy)
               && (Ty == Type::LongTy || Ty == Type::ULongTy
                   || Ty == Type::IntTy || Ty == Type::UIntTy))
              || (isa<PointerType>(Ty)
                  && (OpTy == Type::LongTy || OpTy == Type::ULongTy
                      || OpTy == Type::IntTy || OpTy == Type::UIntTy))
              || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
                   && OpTy->isLosslesslyConvertibleTo(Ty))))
             && "FIXME: Don't yet support this kind of constant cast expr");
      O << "(";
      emitConstantValueOnly(Op);
      O << ")";
      break;
    }
    case Instruction::Add:
      O << "(";
      emitConstantValueOnly(CE->getOperand(0));
      O << ") + (";
      emitConstantValueOnly(CE->getOperand(1));
      O << ")";
      break;
    default:
      assert(0 && "Unsupported operator!");
    }
  } else {
    assert(0 && "Unknown constant value!");
  }
}

/// toOctal - Convert the low order bits of X into an octal digit.
///
static inline char toOctal(int X) {
  return (X&7)+'0';
}

/// printAsCString - Print the specified array as a C compatible string, only if
/// the predicate isString is true.
///
static void printAsCString(std::ostream &O, const ConstantArray *CVA,
                           unsigned LastElt) {
  assert(CVA->isString() && "Array is not string compatible!");

  O << "\"";
  for (unsigned i = 0; i != LastElt; ++i) {
    unsigned char C =
        (unsigned char)cast<ConstantInt>(CVA->getOperand(i))->getRawValue();

    if (C == '"') {
      O << "\\\"";
    } else if (C == '\\') {
      O << "\\\\";
    } else if (isprint(C)) {
      O << C;
    } else {
      switch(C) {
      case '\b': O << "\\b"; break;
      case '\f': O << "\\f"; break;
      case '\n': O << "\\n"; break;
      case '\r': O << "\\r"; break;
      case '\t': O << "\\t"; break;
      default:
        O << '\\';
        O << toOctal(C >> 6);
        O << toOctal(C >> 3);
        O << toOctal(C >> 0);
        break;
      }
    }
  }
  O << "\"";
}

/// emitGlobalConstant - Print a general LLVM constant to the .s file.
///
void AsmPrinter::emitGlobalConstant(const Constant *CV) {
  const TargetData &TD = TM.getTargetData();

  if (CV->isNullValue() || isa<UndefValue>(CV)) {
    emitZeros(TD.getTypeSize(CV->getType()));
    return;
  } else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
    if (CVA->isString()) {
      unsigned NumElts = CVA->getNumOperands();
      if (AscizDirective && NumElts &&
          cast<ConstantInt>(CVA->getOperand(NumElts-1))->getRawValue() == 0) {
        O << AscizDirective;
        printAsCString(O, CVA, NumElts-1);
      } else {
        O << AsciiDirective;
        printAsCString(O, CVA, NumElts);
      }
      O << "\n";
    } else { // Not a string.  Print the values in successive locations
      for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
        emitGlobalConstant(CVA->getOperand(i));
    }
    return;
  } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
    // Print the fields in successive locations. Pad to align if needed!
    const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
    uint64_t sizeSoFar = 0;
    for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
      const Constant* field = CVS->getOperand(i);

      // Check if padding is needed and insert one or more 0s.
      uint64_t fieldSize = TD.getTypeSize(field->getType());
      uint64_t padSize = ((i == e-1? cvsLayout->StructSize
                           : cvsLayout->MemberOffsets[i+1])
                          - cvsLayout->MemberOffsets[i]) - fieldSize;
      sizeSoFar += fieldSize + padSize;

      // Now print the actual field value
      emitGlobalConstant(field);

      // Insert the field padding unless it's zero bytes...
      emitZeros(padSize);
    }
    assert(sizeSoFar == cvsLayout->StructSize &&
           "Layout of constant struct may be incorrect!");
    return;
  } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
    // FP Constants are printed as integer constants to avoid losing
    // precision...
    double Val = CFP->getValue();
    if (CFP->getType() == Type::DoubleTy) {
      if (Data64bitsDirective)
        O << Data64bitsDirective << DoubleToBits(Val) << "\t" << CommentString
          << " double value: " << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32)
          << "\t" << CommentString << " double most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(DoubleToBits(Val))
          << "\t" << CommentString << " double least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(DoubleToBits(Val))
          << "\t" << CommentString << " double least significant word " << Val
          << "\n";
        O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32)
          << "\t" << CommentString << " double most significant word " << Val
          << "\n";
      }
      return;
    } else {
      O << Data32bitsDirective << FloatToBits(Val) << "\t" << CommentString
        << " float " << Val << "\n";
      return;
    }
  } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
    if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
      uint64_t Val = CI->getRawValue();

      if (Data64bitsDirective)
        O << Data64bitsDirective << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
      }
      return;
    }
  }

  const Type *type = CV->getType();
  switch (type->getTypeID()) {
  case Type::BoolTyID:
  case Type::UByteTyID: case Type::SByteTyID:
    O << Data8bitsDirective;
    break;
  case Type::UShortTyID: case Type::ShortTyID:
    O << Data16bitsDirective;
    break;
  case Type::PointerTyID:
    if (TD.getPointerSize() == 8) {
      O << Data64bitsDirective;
      break;
    }
    //Fall through for pointer size == int size
  case Type::UIntTyID: case Type::IntTyID:
    O << Data32bitsDirective;
    break;
  case Type::ULongTyID: case Type::LongTyID:
    assert(Data64bitsDirective &&"Target cannot handle 64-bit constant exprs!");
    O << Data64bitsDirective;
    break;
  case Type::FloatTyID: case Type::DoubleTyID:
    assert (0 && "Should have already output floating point constant.");
  default:
    assert (0 && "Can't handle printing this type of thing");
    break;
  }
  emitConstantValueOnly(CV);
  O << "\n";
}
<commit_msg>Remove extraneous parents around constants when using a constant expr cast.<commit_after>//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AsmPrinter class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

bool AsmPrinter::doInitialization(Module &M) {
  Mang = new Mangler(M, GlobalPrefix);
  return false;
}

bool AsmPrinter::doFinalization(Module &M) {
  delete Mang; Mang = 0;
  return false;
}

void AsmPrinter::setupMachineFunction(MachineFunction &MF) {
  // What's my mangled name?
  CurrentFnName = Mang->getValueName(MF.getFunction());
}

// emitAlignment - Emit an alignment directive to the specified power of two.
void AsmPrinter::emitAlignment(unsigned NumBits, const GlobalValue *GV) const {
  if (GV && GV->getAlignment())
    NumBits = Log2_32(GV->getAlignment());
  if (NumBits == 0) return;   // No need to emit alignment.
  if (AlignmentIsInBytes) NumBits = 1 << NumBits;
  O << AlignDirective << NumBits << "\n";
}

/// emitZeros - Emit a block of zeros.
///
void AsmPrinter::emitZeros(uint64_t NumZeros) const {
  if (NumZeros) {
    if (ZeroDirective)
      O << ZeroDirective << NumZeros << "\n";
    else {
      for (; NumZeros; --NumZeros)
        O << Data8bitsDirective << "0\n";
    }
  }
}

// Print out the specified constant, without a storage class.  Only the
// constants valid in constant expressions can occur here.
void AsmPrinter::emitConstantValueOnly(const Constant *CV) {
  if (CV->isNullValue() || isa<UndefValue>(CV))
    O << "0";
  else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
    assert(CB == ConstantBool::True);
    O << "1";
  } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
    if (((CI->getValue() << 32) >> 32) == CI->getValue())
      O << CI->getValue();
    else
      O << (uint64_t)CI->getValue();
  else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
    O << CI->getValue();
  else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
    // This is a constant address for a global variable or function. Use the
    // name of the variable or function as the address value, possibly
    // decorating it with GlobalVarAddrPrefix/Suffix or
    // FunctionAddrPrefix/Suffix (these all default to "" )
    if (isa<Function>(GV))
      O << FunctionAddrPrefix << Mang->getValueName(GV) << FunctionAddrSuffix;
    else
      O << GlobalVarAddrPrefix << Mang->getValueName(GV) << GlobalVarAddrSuffix;
  } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
    const TargetData &TD = TM.getTargetData();
    switch(CE->getOpcode()) {
    case Instruction::GetElementPtr: {
      // generate a symbolic expression for the byte address
      const Constant *ptrVal = CE->getOperand(0);
      std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
      if (int64_t Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
        if (Offset)
          O << "(";
        emitConstantValueOnly(ptrVal);
        if (Offset > 0)
          O << ") + " << Offset;
        else if (Offset < 0)
          O << ") - " << -Offset;
      } else {
        emitConstantValueOnly(ptrVal);
      }
      break;
    }
    case Instruction::Cast: {
      // Support only non-converting or widening casts for now, that is, ones
      // that do not involve a change in value.  This assertion is really gross,
      // and may not even be a complete check.
      Constant *Op = CE->getOperand(0);
      const Type *OpTy = Op->getType(), *Ty = CE->getType();

      // Remember, kids, pointers can be losslessly converted back and forth
      // into 32-bit or wider integers, regardless of signedness. :-P
      assert(((isa<PointerType>(OpTy)
               && (Ty == Type::LongTy || Ty == Type::ULongTy
                   || Ty == Type::IntTy || Ty == Type::UIntTy))
              || (isa<PointerType>(Ty)
                  && (OpTy == Type::LongTy || OpTy == Type::ULongTy
                      || OpTy == Type::IntTy || OpTy == Type::UIntTy))
              || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
                   && OpTy->isLosslesslyConvertibleTo(Ty))))
             && "FIXME: Don't yet support this kind of constant cast expr");
      emitConstantValueOnly(Op);
      break;
    }
    case Instruction::Add:
      O << "(";
      emitConstantValueOnly(CE->getOperand(0));
      O << ") + (";
      emitConstantValueOnly(CE->getOperand(1));
      O << ")";
      break;
    default:
      assert(0 && "Unsupported operator!");
    }
  } else {
    assert(0 && "Unknown constant value!");
  }
}

/// toOctal - Convert the low order bits of X into an octal digit.
///
static inline char toOctal(int X) {
  return (X&7)+'0';
}

/// printAsCString - Print the specified array as a C compatible string, only if
/// the predicate isString is true.
///
static void printAsCString(std::ostream &O, const ConstantArray *CVA,
                           unsigned LastElt) {
  assert(CVA->isString() && "Array is not string compatible!");

  O << "\"";
  for (unsigned i = 0; i != LastElt; ++i) {
    unsigned char C =
        (unsigned char)cast<ConstantInt>(CVA->getOperand(i))->getRawValue();

    if (C == '"') {
      O << "\\\"";
    } else if (C == '\\') {
      O << "\\\\";
    } else if (isprint(C)) {
      O << C;
    } else {
      switch(C) {
      case '\b': O << "\\b"; break;
      case '\f': O << "\\f"; break;
      case '\n': O << "\\n"; break;
      case '\r': O << "\\r"; break;
      case '\t': O << "\\t"; break;
      default:
        O << '\\';
        O << toOctal(C >> 6);
        O << toOctal(C >> 3);
        O << toOctal(C >> 0);
        break;
      }
    }
  }
  O << "\"";
}

/// emitGlobalConstant - Print a general LLVM constant to the .s file.
///
void AsmPrinter::emitGlobalConstant(const Constant *CV) {
  const TargetData &TD = TM.getTargetData();

  if (CV->isNullValue() || isa<UndefValue>(CV)) {
    emitZeros(TD.getTypeSize(CV->getType()));
    return;
  } else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
    if (CVA->isString()) {
      unsigned NumElts = CVA->getNumOperands();
      if (AscizDirective && NumElts &&
          cast<ConstantInt>(CVA->getOperand(NumElts-1))->getRawValue() == 0) {
        O << AscizDirective;
        printAsCString(O, CVA, NumElts-1);
      } else {
        O << AsciiDirective;
        printAsCString(O, CVA, NumElts);
      }
      O << "\n";
    } else { // Not a string.  Print the values in successive locations
      for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
        emitGlobalConstant(CVA->getOperand(i));
    }
    return;
  } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
    // Print the fields in successive locations. Pad to align if needed!
    const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
    uint64_t sizeSoFar = 0;
    for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
      const Constant* field = CVS->getOperand(i);

      // Check if padding is needed and insert one or more 0s.
      uint64_t fieldSize = TD.getTypeSize(field->getType());
      uint64_t padSize = ((i == e-1? cvsLayout->StructSize
                           : cvsLayout->MemberOffsets[i+1])
                          - cvsLayout->MemberOffsets[i]) - fieldSize;
      sizeSoFar += fieldSize + padSize;

      // Now print the actual field value
      emitGlobalConstant(field);

      // Insert the field padding unless it's zero bytes...
      emitZeros(padSize);
    }
    assert(sizeSoFar == cvsLayout->StructSize &&
           "Layout of constant struct may be incorrect!");
    return;
  } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
    // FP Constants are printed as integer constants to avoid losing
    // precision...
    double Val = CFP->getValue();
    if (CFP->getType() == Type::DoubleTy) {
      if (Data64bitsDirective)
        O << Data64bitsDirective << DoubleToBits(Val) << "\t" << CommentString
          << " double value: " << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32)
          << "\t" << CommentString << " double most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(DoubleToBits(Val))
          << "\t" << CommentString << " double least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(DoubleToBits(Val))
          << "\t" << CommentString << " double least significant word " << Val
          << "\n";
        O << Data32bitsDirective << unsigned(DoubleToBits(Val) >> 32)
          << "\t" << CommentString << " double most significant word " << Val
          << "\n";
      }
      return;
    } else {
      O << Data32bitsDirective << FloatToBits(Val) << "\t" << CommentString
        << " float " << Val << "\n";
      return;
    }
  } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
    if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
      uint64_t Val = CI->getRawValue();

      if (Data64bitsDirective)
        O << Data64bitsDirective << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(Val)
          << "\t" << CommentString << " Double-word least significant word "
          << Val << "\n";
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t" << CommentString << " Double-word most significant word "
          << Val << "\n";
      }
      return;
    }
  }

  const Type *type = CV->getType();
  switch (type->getTypeID()) {
  case Type::BoolTyID:
  case Type::UByteTyID: case Type::SByteTyID:
    O << Data8bitsDirective;
    break;
  case Type::UShortTyID: case Type::ShortTyID:
    O << Data16bitsDirective;
    break;
  case Type::PointerTyID:
    if (TD.getPointerSize() == 8) {
      O << Data64bitsDirective;
      break;
    }
    //Fall through for pointer size == int size
  case Type::UIntTyID: case Type::IntTyID:
    O << Data32bitsDirective;
    break;
  case Type::ULongTyID: case Type::LongTyID:
    assert(Data64bitsDirective &&"Target cannot handle 64-bit constant exprs!");
    O << Data64bitsDirective;
    break;
  case Type::FloatTyID: case Type::DoubleTyID:
    assert (0 && "Should have already output floating point constant.");
  default:
    assert (0 && "Can't handle printing this type of thing");
    break;
  }
  emitConstantValueOnly(CV);
  O << "\n";
}
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/base_paths.h"
#include "base/file_util.h"
#include "media/base/yuv_convert.h"
#include "testing/gtest/include/gtest/gtest.h"

// Size of raw image.
static const int kWidth = 1280;
static const int kHeight = 720;
static const int kBpp = 4;

TEST(YuvConvertTest, Basic) {
  // Read YUV reference data from file.
  FilePath yuv_url;
  EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &yuv_url));
  yuv_url = yuv_url.Append(FILE_PATH_LITERAL("media"))
                   .Append(FILE_PATH_LITERAL("test"))
                   .Append(FILE_PATH_LITERAL("data"))
                   .Append(FILE_PATH_LITERAL("yuv_file"));
  const size_t size_of_yuv = kWidth * kHeight * 12 / 8;
  uint8* yuv_bytes = new uint8[size_of_yuv];
  EXPECT_EQ(size_of_yuv, file_util::ReadFile(yuv_url,
                                             reinterpret_cast<char*>(yuv_bytes),
                                             static_cast<int>(size_of_yuv)));

  // Read RGB reference data from file.
  // To keep the file smaller, only the first quarter of the file
  // is checked into SVN.
  FilePath rgb_url;
  EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &rgb_url));
  rgb_url = rgb_url.Append(FILE_PATH_LITERAL("media"))
                   .Append(FILE_PATH_LITERAL("test"))
                   .Append(FILE_PATH_LITERAL("data"))
                   .Append(FILE_PATH_LITERAL("rgb_file"));
  const size_t size_of_rgb = kWidth * kHeight * kBpp / 4;
  uint8* rgb_bytes = new uint8[size_of_rgb];
  EXPECT_EQ(size_of_rgb, file_util::ReadFile(rgb_url,
                                             reinterpret_cast<char*>(rgb_bytes),
                                             static_cast<int>(size_of_rgb)));

  // Convert a frame of YUV to 32 bit ARGB.
  const size_t size_of_rgb_converted = kWidth * kHeight * kBpp;
  uint8* rgb_converted_bytes = new uint8[size_of_rgb_converted];

  media::ConvertYV12ToRGB32(yuv_bytes,                             // Y plane
                            yuv_bytes + kWidth * kHeight,          // U plane
                            yuv_bytes + kWidth * kHeight * 5 / 4,  // V plane
                            rgb_converted_bytes,                   // Rgb output
                            kWidth, kHeight,                       // Dimensions
                            kWidth,                                // YStride
                            kWidth / 2,                            // UvStride
                            kWidth * kBpp);                        // RgbStride

  // Compare converted YUV to reference conversion file.
  int rgb_diff = memcmp(rgb_converted_bytes, rgb_bytes, size_of_rgb);

  EXPECT_EQ(rgb_diff, 0);
}

<commit_msg>Cast size_t to int for comparison with ReadFile return value. What gcc compile option checks sign on equality?  I'd like to test this, even if try server does not.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/base_paths.h"
#include "base/file_util.h"
#include "media/base/yuv_convert.h"
#include "testing/gtest/include/gtest/gtest.h"

// Size of raw image.
static const int kWidth = 1280;
static const int kHeight = 720;
static const int kBpp = 4;

TEST(YuvConvertTest, Basic) {
  // Read YUV reference data from file.
  FilePath yuv_url;
  EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &yuv_url));
  yuv_url = yuv_url.Append(FILE_PATH_LITERAL("media"))
                   .Append(FILE_PATH_LITERAL("test"))
                   .Append(FILE_PATH_LITERAL("data"))
                   .Append(FILE_PATH_LITERAL("yuv_file"));
  const size_t size_of_yuv = kWidth * kHeight * 12 / 8;
  uint8* yuv_bytes = new uint8[size_of_yuv];
  EXPECT_EQ(static_cast<int>(size_of_yuv),
            file_util::ReadFile(yuv_url,
                                reinterpret_cast<char*>(yuv_bytes),
                                static_cast<int>(size_of_yuv)));

  // Read RGB reference data from file.
  // To keep the file smaller, only the first quarter of the file
  // is checked into SVN.
  FilePath rgb_url;
  EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &rgb_url));
  rgb_url = rgb_url.Append(FILE_PATH_LITERAL("media"))
                   .Append(FILE_PATH_LITERAL("test"))
                   .Append(FILE_PATH_LITERAL("data"))
                   .Append(FILE_PATH_LITERAL("rgb_file"));
  const size_t size_of_rgb = kWidth * kHeight * kBpp / 4;
  uint8* rgb_bytes = new uint8[size_of_rgb];
  EXPECT_EQ(static_cast<int>(size_of_rgb),
            file_util::ReadFile(rgb_url,
                                reinterpret_cast<char*>(rgb_bytes),
                                static_cast<int>(size_of_rgb)));

  // Convert a frame of YUV to 32 bit ARGB.
  const size_t size_of_rgb_converted = kWidth * kHeight * kBpp;
  uint8* rgb_converted_bytes = new uint8[size_of_rgb_converted];

  media::ConvertYV12ToRGB32(yuv_bytes,                             // Y plane
                            yuv_bytes + kWidth * kHeight,          // U plane
                            yuv_bytes + kWidth * kHeight * 5 / 4,  // V plane
                            rgb_converted_bytes,                   // Rgb output
                            kWidth, kHeight,                       // Dimensions
                            kWidth,                                // YStride
                            kWidth / 2,                            // UvStride
                            kWidth * kBpp);                        // RgbStride

  // Compare converted YUV to reference conversion file.
  int rgb_diff = memcmp(rgb_converted_bytes, rgb_bytes, size_of_rgb);

  EXPECT_EQ(rgb_diff, 0);
}

<|endoftext|>


<commit_before>// @(#)root/gui:$Name:  $:$Id: TGWindow.cxx,v 1.12 2004/06/11 13:35:38 rdm Exp $
// Author: Fons Rademakers   28/12/97

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/
/**************************************************************************

    This source is based on Xclass95, a Win95-looking GUI toolkit.
    Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.

    Xclass95 is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

**************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TGWindow                                                             //
//                                                                      //
// ROOT GUI Window base class.                                          //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TGWindow.h"
#include "TMath.h"
#include "Riostream.h"

ClassImp(TGWindow)
ClassImp(TGUnknownWindowHandler)

Int_t TGWindow::fgCounter = 0;

//______________________________________________________________________________
TGWindow::TGWindow(const TGWindow *p, Int_t x, Int_t y, UInt_t w, UInt_t h,
                   UInt_t border, Int_t depth, UInt_t clss, void *visual,
                   SetWindowAttributes_t *attr, UInt_t wtype)
{
   // Create a new window. Parent p must exist. No specified arguments
   // result in values from parent to be taken (or defaults).

   UInt_t type = wtype;

   if (!p && gClient) p = gClient->GetRoot();
   if (p) {
      fClient = p->fClient;
      if (fClient->IsEditable()) type = wtype & ~1;

      fParent = p;
      fId = gVirtualX->CreateWindow(fParent->fId, x, y,
                                    TMath::Max(w, (UInt_t) 1),
                                    TMath::Max(h, (UInt_t) 1), border,
    			            depth, clss, visual, attr, type);
      fClient->RegisterWindow(this);
      fNeedRedraw = kFALSE;

      // name will be used in SavePrimitive methods
      fgCounter++;
      fName = "frame";
      fName += fgCounter;
   } else {
      Error("TGWindow", "no parent specified");
   }
}

//______________________________________________________________________________
TGWindow::TGWindow(TGClient *c, Window_t id, const TGWindow *parent)
{
   // Create a copy of a window.

   fClient = c;
   fId     = id;
   fParent = parent;
   fClient->RegisterWindow(this);
   fNeedRedraw = kFALSE;

   // name used in SavePrimitive methods
   fgCounter++;
   fName = "frame";
   fName += fgCounter;
}

//______________________________________________________________________________
TGWindow::~TGWindow()
{
   // Window destructor. Unregisters the window.

   if (fClient) {
      if (fParent == fClient->GetDefaultRoot()) DestroyWindow();
      fClient->UnregisterWindow(this);
   }
}

//______________________________________________________________________________
void TGWindow::SetWindowName(const char *name)
{
   // Set window name.

   TString wname = name;

   if (!name) {
      wname = ClassName();
      wname += "::" + fName;
   }
   gVirtualX->SetWindowName(fId, (char *)wname.Data());
}

//______________________________________________________________________________
const TGWindow *TGWindow::GetMainFrame() const
{
   // Returns top level main frame.

   return (fParent == fClient->GetDefaultRoot()) ? this : fParent->GetMainFrame();
}

//______________________________________________________________________________
void TGWindow::ReparentWindow(const TGWindow *p, Int_t x, Int_t y)
{
   // Reparent window, make p the new parent and position the window at
   // position (x,y) in new parent.

   if (p == fParent) return;

   if (p) gVirtualX->ReparentWindow(fId, p->GetId(), x, y);
   fParent = p;
}

//______________________________________________________________________________
void TGWindow::Move(Int_t x, Int_t y)
{
   // Move the window.

   gVirtualX->MoveWindow(fId, x, y);
}

//______________________________________________________________________________
void TGWindow::Resize(UInt_t w, UInt_t h)
{
   // Resize the window.

   gVirtualX->ResizeWindow(fId, TMath::Max(w, (UInt_t)1), TMath::Max(h, (UInt_t)1));
}

//______________________________________________________________________________
void TGWindow::MoveResize(Int_t x, Int_t y, UInt_t w, UInt_t h)
{
   // Move and resize the window.

   gVirtualX->MoveResizeWindow(fId, x, y, TMath::Max(w, (UInt_t)1), TMath::Max(h, (UInt_t)1));
}

//______________________________________________________________________________
Bool_t TGWindow::IsMapped()
{
   // Returns kTRUE if window is mapped on screen, kFALSE otherwise.

   WindowAttributes_t attr;

   gVirtualX->GetWindowAttributes(fId, attr);
   return (attr.fMapState != kIsUnmapped);
}

//______________________________________________________________________________
void TGWindow::Print(Option_t *) const
{
   // Print window id.

   cout << ClassName() << ":\t" << fId << endl;
}

//______________________________________________________________________________
Int_t TGWindow::GetCounter()
{
   // Return global window counter (total number of created windows).

   return fgCounter;
}
<commit_msg>create gClient when it does not exist, this can happen when libGui was loaded at program startup but not initialized because application is in batch mode.<commit_after>// @(#)root/gui:$Name:  $:$Id: TGWindow.cxx,v 1.13 2004/06/11 15:59:10 brun Exp $
// Author: Fons Rademakers   28/12/97

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/
/**************************************************************************

    This source is based on Xclass95, a Win95-looking GUI toolkit.
    Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.

    Xclass95 is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

**************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TGWindow                                                             //
//                                                                      //
// ROOT GUI Window base class.                                          //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TGWindow.h"
#include "TMath.h"
#include "Riostream.h"

ClassImp(TGWindow)
ClassImp(TGUnknownWindowHandler)

Int_t TGWindow::fgCounter = 0;

//______________________________________________________________________________
TGWindow::TGWindow(const TGWindow *p, Int_t x, Int_t y, UInt_t w, UInt_t h,
                   UInt_t border, Int_t depth, UInt_t clss, void *visual,
                   SetWindowAttributes_t *attr, UInt_t wtype)
{
   // Create a new window. Parent p must exist otherwise the root window
   // is taken as parent. No arguments specified results in values from
   // parent to be taken (or defaults).

   // this can only happen when libGui was loaded at program startup
   // but not initialized because application is in batch mode
   if (!gClient) new TGClient();

   UInt_t type = wtype;

   if (!p)
      p = gClient->GetRoot();

   fClient = p->fClient;
   if (fClient->IsEditable()) type = wtype & ~1;

   fParent = p;
   fId = gVirtualX->CreateWindow(fParent->fId, x, y,
                                 TMath::Max(w, (UInt_t) 1),
                                 TMath::Max(h, (UInt_t) 1), border,
                                 depth, clss, visual, attr, type);
   fClient->RegisterWindow(this);
   fNeedRedraw = kFALSE;

   // name will be used in SavePrimitive methods
   fgCounter++;
   fName = "frame";
   fName += fgCounter;
}

//______________________________________________________________________________
TGWindow::TGWindow(TGClient *c, Window_t id, const TGWindow *parent)
{
   // Create a copy of a window.

   fClient = c;
   fId     = id;
   fParent = parent;
   fClient->RegisterWindow(this);
   fNeedRedraw = kFALSE;

   // name used in SavePrimitive methods
   fgCounter++;
   fName = "frame";
   fName += fgCounter;
}

//______________________________________________________________________________
TGWindow::~TGWindow()
{
   // Window destructor. Unregisters the window.

   if (fClient) {
      if (fParent == fClient->GetDefaultRoot()) DestroyWindow();
      fClient->UnregisterWindow(this);
   }
}

//______________________________________________________________________________
void TGWindow::SetWindowName(const char *name)
{
   // Set window name.

   TString wname = name;

   if (!name) {
      wname = ClassName();
      wname += "::" + fName;
   }
   gVirtualX->SetWindowName(fId, (char *)wname.Data());
}

//______________________________________________________________________________
const TGWindow *TGWindow::GetMainFrame() const
{
   // Returns top level main frame.

   return (fParent == fClient->GetDefaultRoot()) ? this : fParent->GetMainFrame();
}

//______________________________________________________________________________
void TGWindow::ReparentWindow(const TGWindow *p, Int_t x, Int_t y)
{
   // Reparent window, make p the new parent and position the window at
   // position (x,y) in new parent.

   if (p == fParent) return;

   if (p) gVirtualX->ReparentWindow(fId, p->GetId(), x, y);
   fParent = p;
}

//______________________________________________________________________________
void TGWindow::Move(Int_t x, Int_t y)
{
   // Move the window.

   gVirtualX->MoveWindow(fId, x, y);
}

//______________________________________________________________________________
void TGWindow::Resize(UInt_t w, UInt_t h)
{
   // Resize the window.

   gVirtualX->ResizeWindow(fId, TMath::Max(w, (UInt_t)1), TMath::Max(h, (UInt_t)1));
}

//______________________________________________________________________________
void TGWindow::MoveResize(Int_t x, Int_t y, UInt_t w, UInt_t h)
{
   // Move and resize the window.

   gVirtualX->MoveResizeWindow(fId, x, y, TMath::Max(w, (UInt_t)1), TMath::Max(h, (UInt_t)1));
}

//______________________________________________________________________________
Bool_t TGWindow::IsMapped()
{
   // Returns kTRUE if window is mapped on screen, kFALSE otherwise.

   WindowAttributes_t attr;

   gVirtualX->GetWindowAttributes(fId, attr);
   return (attr.fMapState != kIsUnmapped);
}

//______________________________________________________________________________
void TGWindow::Print(Option_t *) const
{
   // Print window id.

   cout << ClassName() << ":\t" << fId << endl;
}

//______________________________________________________________________________
Int_t TGWindow::GetCounter()
{
   // Return global window counter (total number of created windows).

   return fgCounter;
}
<|endoftext|>