Add LLVM dependencies for Subzero. Change-Id: I5ab054a5622c9f9dee099f5a3a30c3bb4079ffeb Reviewed-on: https://swiftshader-review.googlesource.com/7291 Tested-by: Nicolas Capens <capn@google.com> Reviewed-by: Alexis Hétu <sugoi@google.com> Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/third_party/llvm-subzero/CREDITS.TXT b/third_party/llvm-subzero/CREDITS.TXT new file mode 100644 index 0000000..96a6e49 --- /dev/null +++ b/third_party/llvm-subzero/CREDITS.TXT
@@ -0,0 +1,475 @@ +This file is a partial list of people who have contributed to the LLVM +project. If you have contributed a patch or made some other contribution to +LLVM, please submit a patch to this file to add yourself, and it will be +done! + +The list is sorted by surname and formatted to allow easy grepping and +beautification by scripts. The fields are: name (N), email (E), web-address +(W), PGP key ID and fingerprint (P), description (D), snail-mail address +(S), and (I) IRC handle. + + +N: Vikram Adve +E: vadve@cs.uiuc.edu +W: http://www.cs.uiuc.edu/~vadve/ +D: The Sparc64 backend, provider of much wisdom, and motivator for LLVM + +N: Owen Anderson +E: resistor@mac.com +D: LCSSA pass and related LoopUnswitch work +D: GVNPRE pass, DataLayout refactoring, random improvements + +N: Henrik Bach +D: MingW Win32 API portability layer + +N: Aaron Ballman +E: aaron@aaronballman.com +D: __declspec attributes, Windows support, general bug fixing + +N: Nate Begeman +E: natebegeman@mac.com +D: PowerPC backend developer +D: Target-independent code generator and analysis improvements + +N: Daniel Berlin +E: dberlin@dberlin.org +D: ET-Forest implementation. +D: Sparse bitmap + +N: David Blaikie +E: dblaikie@gmail.com +D: General bug fixing/fit & finish, mostly in Clang + +N: Neil Booth +E: neil@daikokuya.co.uk +D: APFloat implementation. + +N: Misha Brukman +E: brukman+llvm@uiuc.edu +W: http://misha.brukman.net +D: Portions of X86 and Sparc JIT compilers, PowerPC backend +D: Incremental bitcode loader + +N: Cameron Buschardt +E: buschard@uiuc.edu +D: The `mem2reg' pass - promotes values stored in memory to registers + +N: Brendon Cahoon +E: bcahoon@codeaurora.org +D: Loop unrolling with run-time trip counts. + +N: Chandler Carruth +E: chandlerc@gmail.com +E: chandlerc@google.com +D: Hashing algorithms and interfaces +D: Inline cost analysis +D: Machine block placement pass +D: SROA + +N: Casey Carter +E: ccarter@uiuc.edu +D: Fixes to the Reassociation pass, various improvement patches + +N: Evan Cheng +E: evan.cheng@apple.com +D: ARM and X86 backends +D: Instruction scheduler improvements +D: Register allocator improvements +D: Loop optimizer improvements +D: Target-independent code generator improvements + +N: Dan Villiom Podlaski Christiansen +E: danchr@gmail.com +E: danchr@cs.au.dk +W: http://villiom.dk +D: LLVM Makefile improvements +D: Clang diagnostic & driver tweaks +S: Aarhus, Denmark + +N: Jeff Cohen +E: jeffc@jolt-lang.org +W: http://jolt-lang.org +D: Native Win32 API portability layer + +N: John T. Criswell +E: criswell@uiuc.edu +D: Original Autoconf support, documentation improvements, bug fixes + +N: Anshuman Dasgupta +E: adasgupt@codeaurora.org +D: Deterministic finite automaton based infrastructure for VLIW packetization + +N: Stefanus Du Toit +E: stefanus.du.toit@intel.com +D: Bug fixes and minor improvements + +N: Rafael Avila de Espindola +E: rafael.espindola@gmail.com +D: The ARM backend + +N: Dave Estes +E: cestes@codeaurora.org +D: AArch64 machine description for Cortex-A53 + +N: Alkis Evlogimenos +E: alkis@evlogimenos.com +D: Linear scan register allocator, many codegen improvements, Java frontend + +N: Hal Finkel +E: hfinkel@anl.gov +D: Basic-block autovectorization, PowerPC backend improvements + +N: Eric Fiselier +E: eric@efcs.ca +D: LIT patches and documentation. + +N: Ryan Flynn +E: pizza@parseerror.com +D: Miscellaneous bug fixes + +N: Brian Gaeke +E: gaeke@uiuc.edu +W: http://www.students.uiuc.edu/~gaeke/ +D: Portions of X86 static and JIT compilers; initial SparcV8 backend +D: Dynamic trace optimizer +D: FreeBSD/X86 compatibility fixes, the llvm-nm tool + +N: Nicolas Geoffray +E: nicolas.geoffray@lip6.fr +W: http://www-src.lip6.fr/homepages/Nicolas.Geoffray/ +D: PPC backend fixes for Linux + +N: Louis Gerbarg +E: lgg@apple.com +D: Portions of the PowerPC backend + +N: Saem Ghani +E: saemghani@gmail.com +D: Callgraph class cleanups + +N: Mikhail Glushenkov +E: foldr@codedgers.com +D: Author of llvmc2 + +N: Dan Gohman +E: sunfish@mozilla.com +D: Miscellaneous bug fixes +D: WebAssembly Backend + +N: David Goodwin +E: david@goodwinz.net +D: Thumb-2 code generator + +N: David Greene +E: greened@obbligato.org +D: Miscellaneous bug fixes +D: Register allocation refactoring + +N: Gabor Greif +E: ggreif@gmail.com +D: Improvements for space efficiency + +N: James Grosbach +E: grosbach@apple.com +I: grosbach +D: SjLj exception handling support +D: General fixes and improvements for the ARM back-end +D: MCJIT +D: ARM integrated assembler and assembly parser +D: Led effort for the backend formerly known as ARM64 + +N: Lang Hames +E: lhames@gmail.com +D: PBQP-based register allocator + +N: Gordon Henriksen +E: gordonhenriksen@mac.com +D: Pluggable GC support +D: C interface +D: Ocaml bindings + +N: Raul Fernandes Herbster +E: raul@dsc.ufcg.edu.br +D: JIT support for ARM + +N: Paolo Invernizzi +E: arathorn@fastwebnet.it +D: Visual C++ compatibility fixes + +N: Patrick Jenkins +E: patjenk@wam.umd.edu +D: Nightly Tester + +N: Dale Johannesen +E: dalej@apple.com +D: ARM constant islands improvements +D: Tail merging improvements +D: Rewrite X87 back end +D: Use APFloat for floating point constants widely throughout compiler +D: Implement X87 long double + +N: Brad Jones +E: kungfoomaster@nondot.org +D: Support for packed types + +N: Rod Kay +E: rkay@auroraux.org +D: Author of LLVM Ada bindings + +N: Eric Kidd +W: http://randomhacks.net/ +D: llvm-config script + +N: Anton Korobeynikov +E: asl@math.spbu.ru +D: Mingw32 fixes, cross-compiling support, stdcall/fastcall calling conv. +D: x86/linux PIC codegen, aliases, regparm/visibility attributes +D: Switch lowering refactoring + +N: Sumant Kowshik +E: kowshik@uiuc.edu +D: Author of the original C backend + +N: Benjamin Kramer +E: benny.kra@gmail.com +D: Miscellaneous bug fixes + +N: Sundeep Kushwaha +E: sundeepk@codeaurora.org +D: Implemented DFA-based target independent VLIW packetizer + +N: Christopher Lamb +E: christopher.lamb@gmail.com +D: aligned load/store support, parts of noalias and restrict support +D: vreg subreg infrastructure, X86 codegen improvements based on subregs +D: address spaces + +N: Jim Laskey +E: jlaskey@apple.com +D: Improvements to the PPC backend, instruction scheduling +D: Debug and Dwarf implementation +D: Auto upgrade mangler +D: llvm-gcc4 svn wrangler + +N: Chris Lattner +E: sabre@nondot.org +W: http://nondot.org/~sabre/ +D: Primary architect of LLVM + +N: Tanya Lattner (Tanya Brethour) +E: tonic@nondot.org +W: http://nondot.org/~tonic/ +D: The initial llvm-ar tool, converted regression testsuite to dejagnu +D: Modulo scheduling in the SparcV9 backend +D: Release manager (1.7+) + +N: Sylvestre Ledru +E: sylvestre@debian.org +W: http://sylvestre.ledru.info/ +W: http://llvm.org/apt/ +D: Debian and Ubuntu packaging +D: Continuous integration with jenkins + +N: Andrew Lenharth +E: alenhar2@cs.uiuc.edu +W: http://www.lenharth.org/~andrewl/ +D: Alpha backend +D: Sampling based profiling + +N: Nick Lewycky +E: nicholas@mxc.ca +D: PredicateSimplifier pass + +N: Tony Linthicum, et. al. +E: tlinth@codeaurora.org +D: Backend for Qualcomm's Hexagon VLIW processor. + +N: Bruno Cardoso Lopes +E: bruno.cardoso@gmail.com +I: bruno +W: http://brunocardoso.cc +D: Mips backend +D: Random ARM integrated assembler and assembly parser improvements +D: General X86 AVX1 support + +N: Duraid Madina +E: duraid@octopus.com.au +W: http://kinoko.c.u-tokyo.ac.jp/~duraid/ +D: IA64 backend, BigBlock register allocator + +N: John McCall +E: rjmccall@apple.com +D: Clang semantic analysis and IR generation + +N: Michael McCracken +E: michael.mccracken@gmail.com +D: Line number support for llvmgcc + +N: Vladimir Merzliakov +E: wanderer@rsu.ru +D: Test suite fixes for FreeBSD + +N: Scott Michel +E: scottm@aero.org +D: Added STI Cell SPU backend. + +N: Kai Nacke +E: kai@redstar.de +D: Support for implicit TLS model used with MS VC runtime +D: Dumping of Win64 EH structures + +N: Takumi Nakamura +E: geek4civic@gmail.com +E: chapuni@hf.rim.or.jp +D: Cygwin and MinGW support. +D: Win32 tweaks. +S: Yokohama, Japan + +N: Edward O'Callaghan +E: eocallaghan@auroraux.org +W: http://www.auroraux.org +D: Add Clang support with various other improvements to utils/NewNightlyTest.pl +D: Fix and maintain Solaris & AuroraUX support for llvm, various build warnings +D: and error clean ups. + +N: Morten Ofstad +E: morten@hue.no +D: Visual C++ compatibility fixes + +N: Jakob Stoklund Olesen +E: stoklund@2pi.dk +D: Machine code verifier +D: Blackfin backend +D: Fast register allocator +D: Greedy register allocator + +N: Richard Osborne +E: richard@xmos.com +D: XCore backend + +N: Piotr Padlewski +E: piotr.padlewski@gmail.com +D: !invariant.group metadata and other intrinsics for devirtualization in clang + +N: Devang Patel +E: dpatel@apple.com +D: LTO tool, PassManager rewrite, Loop Pass Manager, Loop Rotate +D: GCC PCH Integration (llvm-gcc), llvm-gcc improvements +D: Optimizer improvements, Loop Index Split + +N: Ana Pazos +E: apazos@codeaurora.org +D: Fixes and improvements to the AArch64 backend + +N: Wesley Peck +E: peckw@wesleypeck.com +W: http://wesleypeck.com/ +D: MicroBlaze backend + +N: Francois Pichet +E: pichet2000@gmail.com +D: MSVC support + +N: Adrian Prantl +E: aprantl@apple.com +D: Debug Information + +N: Vladimir Prus +W: http://vladimir_prus.blogspot.com +E: ghost@cs.msu.su +D: Made inst_iterator behave like a proper iterator, LowerConstantExprs pass + +N: Kalle Raiskila +E: kalle.rasikila@nokia.com +D: Some bugfixes to CellSPU + +N: Xerxes Ranby +E: xerxes@zafena.se +D: Cmake dependency chain and various bug fixes + +N: Alex Rosenberg +E: alexr@leftfield.org +I: arosenberg +D: ARM calling conventions rewrite, hard float support + +N: Chad Rosier +E: mcrosier@codeaurora.org +I: mcrosier +D: AArch64 fast instruction selection pass +D: Fixes and improvements to the ARM fast-isel pass +D: Fixes and improvements to the AArch64 backend + +N: Nadav Rotem +E: nadav.rotem@me.com +D: X86 code generation improvements, Loop Vectorizer. + +N: Roman Samoilov +E: roman@codedgers.com +D: MSIL backend + +N: Duncan Sands +E: baldrick@free.fr +I: baldrick +D: Ada support in llvm-gcc +D: Dragonegg plugin +D: Exception handling improvements +D: Type legalizer rewrite + +N: Ruchira Sasanka +E: sasanka@uiuc.edu +D: Graph coloring register allocator for the Sparc64 backend + +N: Arnold Schwaighofer +E: arnold.schwaighofer@gmail.com +D: Tail call optimization for the x86 backend + +N: Shantonu Sen +E: ssen@apple.com +D: Miscellaneous bug fixes + +N: Anand Shukla +E: ashukla@cs.uiuc.edu +D: The `paths' pass + +N: Michael J. Spencer +E: bigcheesegs@gmail.com +D: Shepherding Windows COFF support into MC. +D: Lots of Windows stuff. + +N: Reid Spencer +E: rspencer@reidspencer.com +W: http://reidspencer.com/ +D: Lots of stuff, see: http://wiki.llvm.org/index.php/User:Reid + +N: Alp Toker +E: alp@nuanti.com +W: http://atoker.com/ +D: C++ frontend next generation standards implementation + +N: Craig Topper +E: craig.topper@gmail.com +D: X86 codegen and disassembler improvements. AVX2 support. + +N: Edwin Torok +E: edwintorok@gmail.com +D: Miscellaneous bug fixes + +N: Adam Treat +E: manyoso@yahoo.com +D: C++ bugs filed, and C++ front-end bug fixes. + +N: Lauro Ramos Venancio +E: lauro.venancio@indt.org.br +D: ARM backend improvements +D: Thread Local Storage implementation + +N: Bill Wendling +I: wendling +E: isanbard@gmail.com +D: Release manager, IR Linker, LTO +D: Bunches of stuff + +N: Bob Wilson +E: bob.wilson@acm.org +D: Advanced SIMD (NEON) support in the ARM backend. +
diff --git a/third_party/llvm-subzero/LICENSE.TXT b/third_party/llvm-subzero/LICENSE.TXT new file mode 100644 index 0000000..555c8bb --- /dev/null +++ b/third_party/llvm-subzero/LICENSE.TXT
@@ -0,0 +1,68 @@ +============================================================================== +LLVM Release License +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2016 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +============================================================================== +Copyrights and Licenses for Third Party Software Distributed with LLVM: +============================================================================== +The LLVM software contains code written by third parties. Such software will +have its own individual LICENSE.TXT file in the directory in which it appears. +This file will describe the copyrights, license, and restrictions which apply +to that code. + +The disclaimer of warranty in the University of Illinois Open Source License +applies to all code in the LLVM Distribution, and nothing in any of the +other licenses gives permission to use the names of the LLVM Team or the +University of Illinois to endorse or promote products derived from this +Software. + +The following pieces of software have additional or alternate copyrights, +licenses, and/or restrictions: + +Program Directory +------- --------- +Google Test llvm/utils/unittest/googletest +OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} +pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT} +ARM contributions llvm/lib/Target/ARM/LICENSE.TXT +md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h
diff --git a/third_party/llvm-subzero/README.txt b/third_party/llvm-subzero/README.txt new file mode 100644 index 0000000..d7a90ec --- /dev/null +++ b/third_party/llvm-subzero/README.txt
@@ -0,0 +1,25 @@ +llvm-subzero +============ + +This directory and its subdirectories contain a subset of the source code for +LLVM, required by Subzero. + +The original README.txt content follows: + +Low Level Virtual Machine (LLVM) +================================ + +This directory and its subdirectories contain source code for LLVM, +a toolkit for the construction of highly optimized compilers, +optimizers, and runtime environments. + +LLVM is open source software. You may freely distribute it under the terms of +the license agreement found in LICENSE.txt. + +Please see the documentation provided in docs/ for further +assistance with LLVM, and in particular docs/GettingStarted.rst for getting +started with LLVM and docs/README.txt for an overview of LLVM's +documentation setup. + +If you are writing a package for LLVM, see docs/Packaging.rst for our +suggestions.
diff --git a/third_party/llvm-subzero/include/llvm-c/ErrorHandling.h b/third_party/llvm-subzero/include/llvm-c/ErrorHandling.h new file mode 100644 index 0000000..2059b3a --- /dev/null +++ b/third_party/llvm-subzero/include/llvm-c/ErrorHandling.h
@@ -0,0 +1,49 @@ +/*===-- llvm-c/ErrorHandling.h - Error Handling C Interface -------*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines the C interface to LLVM's error handling mechanism. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_ERROR_HANDLING_H +#define LLVM_C_ERROR_HANDLING_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*LLVMFatalErrorHandler)(const char *Reason); + +/** + * Install a fatal error handler. By default, if LLVM detects a fatal error, it + * will call exit(1). This may not be appropriate in many contexts. For example, + * doing exit(1) will bypass many crash reporting/tracing system tools. This + * function allows you to install a callback that will be invoked prior to the + * call to exit(1). + */ +void LLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler); + +/** + * Reset the fatal error handler. This resets LLVM's fatal error handling + * behavior to the default. + */ +void LLVMResetFatalErrorHandler(void); + +/** + * Enable LLVM's built-in stack trace code. This intercepts the OS's crash + * signals and prints which component of LLVM you were in at the time if the + * crash. + */ +void LLVMEnablePrettyStackTrace(void); + +#ifdef __cplusplus +} +#endif + +#endif
diff --git a/third_party/llvm-subzero/include/llvm-c/Support.h b/third_party/llvm-subzero/include/llvm-c/Support.h new file mode 100644 index 0000000..735d1fb --- /dev/null +++ b/third_party/llvm-subzero/include/llvm-c/Support.h
@@ -0,0 +1,65 @@ +/*===-- llvm-c/Support.h - Support C Interface --------------------*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines the C interface to the LLVM support library. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_SUPPORT_H +#define LLVM_C_SUPPORT_H + +#include "llvm/Support/DataTypes.h" +#include "llvm-c/Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This function permanently loads the dynamic library at the given path. + * It is safe to call this function multiple times for the same library. + * + * @see sys::DynamicLibrary::LoadLibraryPermanently() + */ +LLVMBool LLVMLoadLibraryPermanently(const char* Filename); + +/** + * This function parses the given arguments using the LLVM command line parser. + * Note that the only stable thing about this function is its signature; you + * cannot rely on any particular set of command line arguments being interpreted + * the same way across LLVM versions. + * + * @see llvm::cl::ParseCommandLineOptions() + */ +void LLVMParseCommandLineOptions(int argc, const char *const *argv, + const char *Overview); + +/** + * This function will search through all previously loaded dynamic + * libraries for the symbol \p symbolName. If it is found, the address of + * that symbol is returned. If not, null is returned. + * + * @see sys::DynamicLibrary::SearchForAddressOfSymbol() + */ +void *LLVMSearchForAddressOfSymbol(const char *symbolName); + +/** + * This functions permanently adds the symbol \p symbolName with the + * value \p symbolValue. These symbols are searched before any + * libraries. + * + * @see sys::DynamicLibrary::AddSymbol() + */ +void LLVMAddSymbol(const char *symbolName, void *symbolValue); + +#ifdef __cplusplus +} +#endif + +#endif
diff --git a/third_party/llvm-subzero/include/llvm-c/Types.h b/third_party/llvm-subzero/include/llvm-c/Types.h new file mode 100644 index 0000000..3d472a6 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm-c/Types.h
@@ -0,0 +1,131 @@ +/*===-- llvm-c/Support.h - C Interface Types declarations ---------*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines types used by the the C interface to LLVM. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TYPES_H +#define LLVM_C_TYPES_H + +#include "llvm/Support/DataTypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup LLVMCSupportTypes Types and Enumerations + * + * @{ + */ + +typedef int LLVMBool; + +/* Opaque types. */ + +/** + * LLVM uses a polymorphic type hierarchy which C cannot represent, therefore + * parameters must be passed as base types. Despite the declared types, most + * of the functions provided operate only on branches of the type hierarchy. + * The declared parameter names are descriptive and specify which type is + * required. Additionally, each type hierarchy is documented along with the + * functions that operate upon it. For more detail, refer to LLVM's C++ code. + * If in doubt, refer to Core.cpp, which performs parameter downcasts in the + * form unwrap<RequiredType>(Param). + */ + +/** + * Used to pass regions of memory through LLVM interfaces. + * + * @see llvm::MemoryBuffer + */ +typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef; + +/** + * The top-level container for all LLVM global data. See the LLVMContext class. + */ +typedef struct LLVMOpaqueContext *LLVMContextRef; + +/** + * The top-level container for all other LLVM Intermediate Representation (IR) + * objects. + * + * @see llvm::Module + */ +typedef struct LLVMOpaqueModule *LLVMModuleRef; + +/** + * Each value in the LLVM IR has a type, an LLVMTypeRef. + * + * @see llvm::Type + */ +typedef struct LLVMOpaqueType *LLVMTypeRef; + +/** + * Represents an individual value in LLVM IR. + * + * This models llvm::Value. + */ +typedef struct LLVMOpaqueValue *LLVMValueRef; + +/** + * Represents a basic block of instructions in LLVM IR. + * + * This models llvm::BasicBlock. + */ +typedef struct LLVMOpaqueBasicBlock *LLVMBasicBlockRef; + +/** + * Represents an LLVM basic block builder. + * + * This models llvm::IRBuilder. + */ +typedef struct LLVMOpaqueBuilder *LLVMBuilderRef; + +/** + * Interface used to provide a module to JIT or interpreter. + * This is now just a synonym for llvm::Module, but we have to keep using the + * different type to keep binary compatibility. + */ +typedef struct LLVMOpaqueModuleProvider *LLVMModuleProviderRef; + +/** @see llvm::PassManagerBase */ +typedef struct LLVMOpaquePassManager *LLVMPassManagerRef; + +/** @see llvm::PassRegistry */ +typedef struct LLVMOpaquePassRegistry *LLVMPassRegistryRef; + +/** + * Used to get the users and usees of a Value. + * + * @see llvm::Use */ +typedef struct LLVMOpaqueUse *LLVMUseRef; + +/** + * Used to represent an attributes. + * + * @see llvm::Attribute + */ +typedef struct LLVMOpaqueAttributeRef *LLVMAttributeRef; + +/** + * @see llvm::DiagnosticInfo + */ +typedef struct LLVMOpaqueDiagnosticInfo *LLVMDiagnosticInfoRef; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/APFloat.h b/third_party/llvm-subzero/include/llvm/ADT/APFloat.h new file mode 100644 index 0000000..3f6bd00 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/APFloat.h
@@ -0,0 +1,689 @@ +//===- llvm/ADT/APFloat.h - Arbitrary Precision Floating Point ---*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief +/// This file declares a class to represent arbitrary precision floating point +/// values and provide a variety of arithmetic operations on them. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_APFLOAT_H +#define LLVM_ADT_APFLOAT_H + +#include "llvm/ADT/APInt.h" + +namespace llvm { + +struct fltSemantics; +class APSInt; +class StringRef; + +template <typename T> class SmallVectorImpl; + +/// Enum that represents what fraction of the LSB truncated bits of an fp number +/// represent. +/// +/// This essentially combines the roles of guard and sticky bits. +enum lostFraction { // Example of truncated bits: + lfExactlyZero, // 000000 + lfLessThanHalf, // 0xxxxx x's not all zero + lfExactlyHalf, // 100000 + lfMoreThanHalf // 1xxxxx x's not all zero +}; + +/// \brief A self-contained host- and target-independent arbitrary-precision +/// floating-point software implementation. +/// +/// APFloat uses bignum integer arithmetic as provided by static functions in +/// the APInt class. The library will work with bignum integers whose parts are +/// any unsigned type at least 16 bits wide, but 64 bits is recommended. +/// +/// Written for clarity rather than speed, in particular with a view to use in +/// the front-end of a cross compiler so that target arithmetic can be correctly +/// performed on the host. Performance should nonetheless be reasonable, +/// particularly for its intended use. It may be useful as a base +/// implementation for a run-time library during development of a faster +/// target-specific one. +/// +/// All 5 rounding modes in the IEEE-754R draft are handled correctly for all +/// implemented operations. Currently implemented operations are add, subtract, +/// multiply, divide, fused-multiply-add, conversion-to-float, +/// conversion-to-integer and conversion-from-integer. New rounding modes +/// (e.g. away from zero) can be added with three or four lines of code. +/// +/// Four formats are built-in: IEEE single precision, double precision, +/// quadruple precision, and x87 80-bit extended double (when operating with +/// full extended precision). Adding a new format that obeys IEEE semantics +/// only requires adding two lines of code: a declaration and definition of the +/// format. +/// +/// All operations return the status of that operation as an exception bit-mask, +/// so multiple operations can be done consecutively with their results or-ed +/// together. The returned status can be useful for compiler diagnostics; e.g., +/// inexact, underflow and overflow can be easily diagnosed on constant folding, +/// and compiler optimizers can determine what exceptions would be raised by +/// folding operations and optimize, or perhaps not optimize, accordingly. +/// +/// At present, underflow tininess is detected after rounding; it should be +/// straight forward to add support for the before-rounding case too. +/// +/// The library reads hexadecimal floating point numbers as per C99, and +/// correctly rounds if necessary according to the specified rounding mode. +/// Syntax is required to have been validated by the caller. It also converts +/// floating point numbers to hexadecimal text as per the C99 %a and %A +/// conversions. The output precision (or alternatively the natural minimal +/// precision) can be specified; if the requested precision is less than the +/// natural precision the output is correctly rounded for the specified rounding +/// mode. +/// +/// It also reads decimal floating point numbers and correctly rounds according +/// to the specified rounding mode. +/// +/// Conversion to decimal text is not currently implemented. +/// +/// Non-zero finite numbers are represented internally as a sign bit, a 16-bit +/// signed exponent, and the significand as an array of integer parts. After +/// normalization of a number of precision P the exponent is within the range of +/// the format, and if the number is not denormal the P-th bit of the +/// significand is set as an explicit integer bit. For denormals the most +/// significant bit is shifted right so that the exponent is maintained at the +/// format's minimum, so that the smallest denormal has just the least +/// significant bit of the significand set. The sign of zeroes and infinities +/// is significant; the exponent and significand of such numbers is not stored, +/// but has a known implicit (deterministic) value: 0 for the significands, 0 +/// for zero exponent, all 1 bits for infinity exponent. For NaNs the sign and +/// significand are deterministic, although not really meaningful, and preserved +/// in non-conversion operations. The exponent is implicitly all 1 bits. +/// +/// APFloat does not provide any exception handling beyond default exception +/// handling. We represent Signaling NaNs via IEEE-754R 2008 6.2.1 should clause +/// by encoding Signaling NaNs with the first bit of its trailing significand as +/// 0. +/// +/// TODO +/// ==== +/// +/// Some features that may or may not be worth adding: +/// +/// Binary to decimal conversion (hard). +/// +/// Optional ability to detect underflow tininess before rounding. +/// +/// New formats: x87 in single and double precision mode (IEEE apart from +/// extended exponent range) (hard). +/// +/// New operations: sqrt, IEEE remainder, C90 fmod, nexttoward. +/// +class APFloat { +public: + + /// A signed type to represent a floating point numbers unbiased exponent. + typedef signed short ExponentType; + + /// \name Floating Point Semantics. + /// @{ + + static const fltSemantics IEEEhalf; + static const fltSemantics IEEEsingle; + static const fltSemantics IEEEdouble; + static const fltSemantics IEEEquad; + static const fltSemantics PPCDoubleDouble; + static const fltSemantics x87DoubleExtended; + + /// A Pseudo fltsemantic used to construct APFloats that cannot conflict with + /// anything real. + static const fltSemantics Bogus; + + /// @} + + static unsigned int semanticsPrecision(const fltSemantics &); + static ExponentType semanticsMinExponent(const fltSemantics &); + static ExponentType semanticsMaxExponent(const fltSemantics &); + static unsigned int semanticsSizeInBits(const fltSemantics &); + + /// IEEE-754R 5.11: Floating Point Comparison Relations. + enum cmpResult { + cmpLessThan, + cmpEqual, + cmpGreaterThan, + cmpUnordered + }; + + /// IEEE-754R 4.3: Rounding-direction attributes. + enum roundingMode { + rmNearestTiesToEven, + rmTowardPositive, + rmTowardNegative, + rmTowardZero, + rmNearestTiesToAway + }; + + /// IEEE-754R 7: Default exception handling. + /// + /// opUnderflow or opOverflow are always returned or-ed with opInexact. + enum opStatus { + opOK = 0x00, + opInvalidOp = 0x01, + opDivByZero = 0x02, + opOverflow = 0x04, + opUnderflow = 0x08, + opInexact = 0x10 + }; + + /// Category of internally-represented number. + enum fltCategory { + fcInfinity, + fcNaN, + fcNormal, + fcZero + }; + + /// Convenience enum used to construct an uninitialized APFloat. + enum uninitializedTag { + uninitialized + }; + + /// \name Constructors + /// @{ + + APFloat(const fltSemantics &); // Default construct to 0.0 + APFloat(const fltSemantics &, StringRef); + APFloat(const fltSemantics &, integerPart); + APFloat(const fltSemantics &, uninitializedTag); + APFloat(const fltSemantics &, const APInt &); + explicit APFloat(double d); + explicit APFloat(float f); + APFloat(const APFloat &); + APFloat(APFloat &&); + ~APFloat(); + + /// @} + + /// \brief Returns whether this instance allocated memory. + bool needsCleanup() const { return partCount() > 1; } + + /// \name Convenience "constructors" + /// @{ + + /// Factory for Positive and Negative Zero. + /// + /// \param Negative True iff the number should be negative. + static APFloat getZero(const fltSemantics &Sem, bool Negative = false) { + APFloat Val(Sem, uninitialized); + Val.makeZero(Negative); + return Val; + } + + /// Factory for Positive and Negative Infinity. + /// + /// \param Negative True iff the number should be negative. + static APFloat getInf(const fltSemantics &Sem, bool Negative = false) { + APFloat Val(Sem, uninitialized); + Val.makeInf(Negative); + return Val; + } + + /// Factory for QNaN values. + /// + /// \param Negative - True iff the NaN generated should be negative. + /// \param type - The unspecified fill bits for creating the NaN, 0 by + /// default. The value is truncated as necessary. + static APFloat getNaN(const fltSemantics &Sem, bool Negative = false, + unsigned type = 0) { + if (type) { + APInt fill(64, type); + return getQNaN(Sem, Negative, &fill); + } else { + return getQNaN(Sem, Negative, nullptr); + } + } + + /// Factory for QNaN values. + static APFloat getQNaN(const fltSemantics &Sem, bool Negative = false, + const APInt *payload = nullptr) { + return makeNaN(Sem, false, Negative, payload); + } + + /// Factory for SNaN values. + static APFloat getSNaN(const fltSemantics &Sem, bool Negative = false, + const APInt *payload = nullptr) { + return makeNaN(Sem, true, Negative, payload); + } + + /// Returns the largest finite number in the given semantics. + /// + /// \param Negative - True iff the number should be negative + static APFloat getLargest(const fltSemantics &Sem, bool Negative = false); + + /// Returns the smallest (by magnitude) finite number in the given semantics. + /// Might be denormalized, which implies a relative loss of precision. + /// + /// \param Negative - True iff the number should be negative + static APFloat getSmallest(const fltSemantics &Sem, bool Negative = false); + + /// Returns the smallest (by magnitude) normalized finite number in the given + /// semantics. + /// + /// \param Negative - True iff the number should be negative + static APFloat getSmallestNormalized(const fltSemantics &Sem, + bool Negative = false); + + /// Returns a float which is bitcasted from an all one value int. + /// + /// \param BitWidth - Select float type + /// \param isIEEE - If 128 bit number, select between PPC and IEEE + static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false); + + /// Returns the size of the floating point number (in bits) in the given + /// semantics. + static unsigned getSizeInBits(const fltSemantics &Sem); + + /// @} + + /// Used to insert APFloat objects, or objects that contain APFloat objects, + /// into FoldingSets. + void Profile(FoldingSetNodeID &NID) const; + + /// \name Arithmetic + /// @{ + + opStatus add(const APFloat &, roundingMode); + opStatus subtract(const APFloat &, roundingMode); + opStatus multiply(const APFloat &, roundingMode); + opStatus divide(const APFloat &, roundingMode); + /// IEEE remainder. + opStatus remainder(const APFloat &); + /// C fmod, or llvm frem. + opStatus mod(const APFloat &); + opStatus fusedMultiplyAdd(const APFloat &, const APFloat &, roundingMode); + opStatus roundToIntegral(roundingMode); + /// IEEE-754R 5.3.1: nextUp/nextDown. + opStatus next(bool nextDown); + + /// \brief Operator+ overload which provides the default + /// \c nmNearestTiesToEven rounding mode and *no* error checking. + APFloat operator+(const APFloat &RHS) const { + APFloat Result = *this; + Result.add(RHS, rmNearestTiesToEven); + return Result; + } + + /// \brief Operator- overload which provides the default + /// \c nmNearestTiesToEven rounding mode and *no* error checking. + APFloat operator-(const APFloat &RHS) const { + APFloat Result = *this; + Result.subtract(RHS, rmNearestTiesToEven); + return Result; + } + + /// \brief Operator* overload which provides the default + /// \c nmNearestTiesToEven rounding mode and *no* error checking. + APFloat operator*(const APFloat &RHS) const { + APFloat Result = *this; + Result.multiply(RHS, rmNearestTiesToEven); + return Result; + } + + /// \brief Operator/ overload which provides the default + /// \c nmNearestTiesToEven rounding mode and *no* error checking. + APFloat operator/(const APFloat &RHS) const { + APFloat Result = *this; + Result.divide(RHS, rmNearestTiesToEven); + return Result; + } + + /// @} + + /// \name Sign operations. + /// @{ + + void changeSign(); + void clearSign(); + void copySign(const APFloat &); + + /// \brief A static helper to produce a copy of an APFloat value with its sign + /// copied from some other APFloat. + static APFloat copySign(APFloat Value, const APFloat &Sign) { + Value.copySign(Sign); + return Value; + } + + /// @} + + /// \name Conversions + /// @{ + + opStatus convert(const fltSemantics &, roundingMode, bool *); + opStatus convertToInteger(integerPart *, unsigned int, bool, roundingMode, + bool *) const; + opStatus convertToInteger(APSInt &, roundingMode, bool *) const; + opStatus convertFromAPInt(const APInt &, bool, roundingMode); + opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int, + bool, roundingMode); + opStatus convertFromZeroExtendedInteger(const integerPart *, unsigned int, + bool, roundingMode); + opStatus convertFromString(StringRef, roundingMode); + APInt bitcastToAPInt() const; + double convertToDouble() const; + float convertToFloat() const; + + /// @} + + /// The definition of equality is not straightforward for floating point, so + /// we won't use operator==. Use one of the following, or write whatever it + /// is you really mean. + bool operator==(const APFloat &) const = delete; + + /// IEEE comparison with another floating point number (NaNs compare + /// unordered, 0==-0). + cmpResult compare(const APFloat &) const; + + /// Bitwise comparison for equality (QNaNs compare equal, 0!=-0). + bool bitwiseIsEqual(const APFloat &) const; + + /// Write out a hexadecimal representation of the floating point value to DST, + /// which must be of sufficient size, in the C99 form [-]0xh.hhhhp[+-]d. + /// Return the number of characters written, excluding the terminating NUL. + unsigned int convertToHexString(char *dst, unsigned int hexDigits, + bool upperCase, roundingMode) const; + + /// \name IEEE-754R 5.7.2 General operations. + /// @{ + + /// IEEE-754R isSignMinus: Returns true if and only if the current value is + /// negative. + /// + /// This applies to zeros and NaNs as well. + bool isNegative() const { return sign; } + + /// IEEE-754R isNormal: Returns true if and only if the current value is normal. + /// + /// This implies that the current value of the float is not zero, subnormal, + /// infinite, or NaN following the definition of normality from IEEE-754R. + bool isNormal() const { return !isDenormal() && isFiniteNonZero(); } + + /// Returns true if and only if the current value is zero, subnormal, or + /// normal. + /// + /// This means that the value is not infinite or NaN. + bool isFinite() const { return !isNaN() && !isInfinity(); } + + /// Returns true if and only if the float is plus or minus zero. + bool isZero() const { return category == fcZero; } + + /// IEEE-754R isSubnormal(): Returns true if and only if the float is a + /// denormal. + bool isDenormal() const; + + /// IEEE-754R isInfinite(): Returns true if and only if the float is infinity. + bool isInfinity() const { return category == fcInfinity; } + + /// Returns true if and only if the float is a quiet or signaling NaN. + bool isNaN() const { return category == fcNaN; } + + /// Returns true if and only if the float is a signaling NaN. + bool isSignaling() const; + + /// @} + + /// \name Simple Queries + /// @{ + + fltCategory getCategory() const { return category; } + const fltSemantics &getSemantics() const { return *semantics; } + bool isNonZero() const { return category != fcZero; } + bool isFiniteNonZero() const { return isFinite() && !isZero(); } + bool isPosZero() const { return isZero() && !isNegative(); } + bool isNegZero() const { return isZero() && isNegative(); } + + /// Returns true if and only if the number has the smallest possible non-zero + /// magnitude in the current semantics. + bool isSmallest() const; + + /// Returns true if and only if the number has the largest possible finite + /// magnitude in the current semantics. + bool isLargest() const; + + /// Returns true if and only if the number is an exact integer. + bool isInteger() const; + + /// @} + + APFloat &operator=(const APFloat &); + APFloat &operator=(APFloat &&); + + /// \brief Overload to compute a hash code for an APFloat value. + /// + /// Note that the use of hash codes for floating point values is in general + /// frought with peril. Equality is hard to define for these values. For + /// example, should negative and positive zero hash to different codes? Are + /// they equal or not? This hash value implementation specifically + /// emphasizes producing different codes for different inputs in order to + /// be used in canonicalization and memoization. As such, equality is + /// bitwiseIsEqual, and 0 != -0. + friend hash_code hash_value(const APFloat &Arg); + + /// Converts this value into a decimal string. + /// + /// \param FormatPrecision The maximum number of digits of + /// precision to output. If there are fewer digits available, + /// zero padding will not be used unless the value is + /// integral and small enough to be expressed in + /// FormatPrecision digits. 0 means to use the natural + /// precision of the number. + /// \param FormatMaxPadding The maximum number of zeros to + /// consider inserting before falling back to scientific + /// notation. 0 means to always use scientific notation. + /// + /// Number Precision MaxPadding Result + /// ------ --------- ---------- ------ + /// 1.01E+4 5 2 10100 + /// 1.01E+4 4 2 1.01E+4 + /// 1.01E+4 5 1 1.01E+4 + /// 1.01E-2 5 2 0.0101 + /// 1.01E-2 4 2 0.0101 + /// 1.01E-2 4 1 1.01E-2 + void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision = 0, + unsigned FormatMaxPadding = 3) const; + + /// If this value has an exact multiplicative inverse, store it in inv and + /// return true. + bool getExactInverse(APFloat *inv) const; + + /// \brief Enumeration of \c ilogb error results. + enum IlogbErrorKinds { + IEK_Zero = INT_MIN+1, + IEK_NaN = INT_MIN, + IEK_Inf = INT_MAX + }; + + /// \brief Returns the exponent of the internal representation of the APFloat. + /// + /// Because the radix of APFloat is 2, this is equivalent to floor(log2(x)). + /// For special APFloat values, this returns special error codes: + /// + /// NaN -> \c IEK_NaN + /// 0 -> \c IEK_Zero + /// Inf -> \c IEK_Inf + /// + friend int ilogb(const APFloat &Arg); + + /// \brief Returns: X * 2^Exp for integral exponents. + friend APFloat scalbn(APFloat X, int Exp, roundingMode); + + friend APFloat frexp(const APFloat &X, int &Exp, roundingMode); + +private: + + /// \name Simple Queries + /// @{ + + integerPart *significandParts(); + const integerPart *significandParts() const; + unsigned int partCount() const; + + /// @} + + /// \name Significand operations. + /// @{ + + integerPart addSignificand(const APFloat &); + integerPart subtractSignificand(const APFloat &, integerPart); + lostFraction addOrSubtractSignificand(const APFloat &, bool subtract); + lostFraction multiplySignificand(const APFloat &, const APFloat *); + lostFraction divideSignificand(const APFloat &); + void incrementSignificand(); + void initialize(const fltSemantics *); + void shiftSignificandLeft(unsigned int); + lostFraction shiftSignificandRight(unsigned int); + unsigned int significandLSB() const; + unsigned int significandMSB() const; + void zeroSignificand(); + /// Return true if the significand excluding the integral bit is all ones. + bool isSignificandAllOnes() const; + /// Return true if the significand excluding the integral bit is all zeros. + bool isSignificandAllZeros() const; + + /// @} + + /// \name Arithmetic on special values. + /// @{ + + opStatus addOrSubtractSpecials(const APFloat &, bool subtract); + opStatus divideSpecials(const APFloat &); + opStatus multiplySpecials(const APFloat &); + opStatus modSpecials(const APFloat &); + + /// @} + + /// \name Special value setters. + /// @{ + + void makeLargest(bool Neg = false); + void makeSmallest(bool Neg = false); + void makeNaN(bool SNaN = false, bool Neg = false, + const APInt *fill = nullptr); + static APFloat makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative, + const APInt *fill); + void makeInf(bool Neg = false); + void makeZero(bool Neg = false); + void makeQuiet(); + + /// @} + + /// \name Miscellany + /// @{ + + bool convertFromStringSpecials(StringRef str); + opStatus normalize(roundingMode, lostFraction); + opStatus addOrSubtract(const APFloat &, roundingMode, bool subtract); + cmpResult compareAbsoluteValue(const APFloat &) const; + opStatus handleOverflow(roundingMode); + bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const; + opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool, + roundingMode, bool *) const; + opStatus convertFromUnsignedParts(const integerPart *, unsigned int, + roundingMode); + opStatus convertFromHexadecimalString(StringRef, roundingMode); + opStatus convertFromDecimalString(StringRef, roundingMode); + char *convertNormalToHexString(char *, unsigned int, bool, + roundingMode) const; + opStatus roundSignificandWithExponent(const integerPart *, unsigned int, int, + roundingMode); + + /// @} + + APInt convertHalfAPFloatToAPInt() const; + APInt convertFloatAPFloatToAPInt() const; + APInt convertDoubleAPFloatToAPInt() const; + APInt convertQuadrupleAPFloatToAPInt() const; + APInt convertF80LongDoubleAPFloatToAPInt() const; + APInt convertPPCDoubleDoubleAPFloatToAPInt() const; + void initFromAPInt(const fltSemantics *Sem, const APInt &api); + void initFromHalfAPInt(const APInt &api); + void initFromFloatAPInt(const APInt &api); + void initFromDoubleAPInt(const APInt &api); + void initFromQuadrupleAPInt(const APInt &api); + void initFromF80LongDoubleAPInt(const APInt &api); + void initFromPPCDoubleDoubleAPInt(const APInt &api); + + void assign(const APFloat &); + void copySignificand(const APFloat &); + void freeSignificand(); + + /// The semantics that this value obeys. + const fltSemantics *semantics; + + /// A binary fraction with an explicit integer bit. + /// + /// The significand must be at least one bit wider than the target precision. + union Significand { + integerPart part; + integerPart *parts; + } significand; + + /// The signed unbiased exponent of the value. + ExponentType exponent; + + /// What kind of floating point number this is. + /// + /// Only 2 bits are required, but VisualStudio incorrectly sign extends it. + /// Using the extra bit keeps it from failing under VisualStudio. + fltCategory category : 3; + + /// Sign bit of the number. + unsigned int sign : 1; +}; + +/// See friend declarations above. +/// +/// These additional declarations are required in order to compile LLVM with IBM +/// xlC compiler. +hash_code hash_value(const APFloat &Arg); +int ilogb(const APFloat &Arg); +APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode); + +/// \brief Equivalent of C standard library function. +/// +/// While the C standard says Exp is an unspecified value for infinity and nan, +/// this returns INT_MAX for infinities, and INT_MIN for NaNs. +APFloat frexp(const APFloat &Val, int &Exp, APFloat::roundingMode RM); + +/// \brief Returns the absolute value of the argument. +inline APFloat abs(APFloat X) { + X.clearSign(); + return X; +} + +/// Implements IEEE minNum semantics. Returns the smaller of the 2 arguments if +/// both are not NaN. If either argument is a NaN, returns the other argument. +LLVM_READONLY +inline APFloat minnum(const APFloat &A, const APFloat &B) { + if (A.isNaN()) + return B; + if (B.isNaN()) + return A; + return (B.compare(A) == APFloat::cmpLessThan) ? B : A; +} + +/// Implements IEEE maxNum semantics. Returns the larger of the 2 arguments if +/// both are not NaN. If either argument is a NaN, returns the other argument. +LLVM_READONLY +inline APFloat maxnum(const APFloat &A, const APFloat &B) { + if (A.isNaN()) + return B; + if (B.isNaN()) + return A; + return (A.compare(B) == APFloat::cmpLessThan) ? B : A; +} + +} // namespace llvm + +#endif // LLVM_ADT_APFLOAT_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/APInt.h b/third_party/llvm-subzero/include/llvm/ADT/APInt.h new file mode 100644 index 0000000..23c6c14 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/APInt.h
@@ -0,0 +1,1972 @@ +//===-- llvm/ADT/APInt.h - For Arbitrary Precision Integer -----*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file implements a class to represent arbitrary precision +/// integral constant values and operations on them. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_APINT_H +#define LLVM_ADT_APINT_H + +#include "llvm/Support/Compiler.h" +#include "llvm/Support/MathExtras.h" +#include <cassert> +#include <climits> +#include <cstring> +#include <string> + +namespace llvm { +class FoldingSetNodeID; +class StringRef; +class hash_code; +class raw_ostream; + +template <typename T> class SmallVectorImpl; +template <typename T> class ArrayRef; + +// An unsigned host type used as a single part of a multi-part +// bignum. +typedef uint64_t integerPart; + +const unsigned int host_char_bit = 8; +const unsigned int integerPartWidth = + host_char_bit * static_cast<unsigned int>(sizeof(integerPart)); + +class APInt; + +inline APInt operator-(APInt); + +//===----------------------------------------------------------------------===// +// APInt Class +//===----------------------------------------------------------------------===// + +/// \brief Class for arbitrary precision integers. +/// +/// APInt is a functional replacement for common case unsigned integer type like +/// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width +/// integer sizes and large integer value types such as 3-bits, 15-bits, or more +/// than 64-bits of precision. APInt provides a variety of arithmetic operators +/// and methods to manipulate integer values of any bit-width. It supports both +/// the typical integer arithmetic and comparison operations as well as bitwise +/// manipulation. +/// +/// The class has several invariants worth noting: +/// * All bit, byte, and word positions are zero-based. +/// * Once the bit width is set, it doesn't change except by the Truncate, +/// SignExtend, or ZeroExtend operations. +/// * All binary operators must be on APInt instances of the same bit width. +/// Attempting to use these operators on instances with different bit +/// widths will yield an assertion. +/// * The value is stored canonically as an unsigned value. For operations +/// where it makes a difference, there are both signed and unsigned variants +/// of the operation. For example, sdiv and udiv. However, because the bit +/// widths must be the same, operations such as Mul and Add produce the same +/// results regardless of whether the values are interpreted as signed or +/// not. +/// * In general, the class tries to follow the style of computation that LLVM +/// uses in its IR. This simplifies its use for LLVM. +/// +class APInt { + unsigned BitWidth; ///< The number of bits in this APInt. + + /// This union is used to store the integer value. When the + /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal. + union { + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t *pVal; ///< Used to store the >64 bits integer value. + }; + + /// This enum is used to hold the constants we needed for APInt. + enum { + /// Bits in a word + APINT_BITS_PER_WORD = + static_cast<unsigned int>(sizeof(uint64_t)) * CHAR_BIT, + /// Byte size of a word + APINT_WORD_SIZE = static_cast<unsigned int>(sizeof(uint64_t)) + }; + + friend struct DenseMapAPIntKeyInfo; + + /// \brief Fast internal constructor + /// + /// This constructor is used only internally for speed of construction of + /// temporaries. It is unsafe for general use so it is not public. + APInt(uint64_t *val, unsigned bits) : BitWidth(bits), pVal(val) {} + + /// \brief Determine if this APInt just has one word to store value. + /// + /// \returns true if the number of bits <= 64, false otherwise. + bool isSingleWord() const { return BitWidth <= APINT_BITS_PER_WORD; } + + /// \brief Determine which word a bit is in. + /// + /// \returns the word position for the specified bit position. + static unsigned whichWord(unsigned bitPosition) { + return bitPosition / APINT_BITS_PER_WORD; + } + + /// \brief Determine which bit in a word a bit is in. + /// + /// \returns the bit position in a word for the specified bit position + /// in the APInt. + static unsigned whichBit(unsigned bitPosition) { + return bitPosition % APINT_BITS_PER_WORD; + } + + /// \brief Get a single bit mask. + /// + /// \returns a uint64_t with only bit at "whichBit(bitPosition)" set + /// This method generates and returns a uint64_t (word) mask for a single + /// bit at a specific bit position. This is used to mask the bit in the + /// corresponding word. + static uint64_t maskBit(unsigned bitPosition) { + return 1ULL << whichBit(bitPosition); + } + + /// \brief Clear unused high order bits + /// + /// This method is used internally to clear the top "N" bits in the high order + /// word that are not used by the APInt. This is needed after the most + /// significant word is assigned a value to ensure that those bits are + /// zero'd out. + APInt &clearUnusedBits() { + // Compute how many bits are used in the final word + unsigned wordBits = BitWidth % APINT_BITS_PER_WORD; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shift is the same size as + // the word size (64). + return *this; + + // Mask out the high bits. + uint64_t mask = ~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - wordBits); + if (isSingleWord()) + VAL &= mask; + else + pVal[getNumWords() - 1] &= mask; + return *this; + } + + /// \brief Get the word corresponding to a bit position + /// \returns the corresponding word for the specified bit position. + uint64_t getWord(unsigned bitPosition) const { + return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; + } + + /// \brief Convert a char array into an APInt + /// + /// \param radix 2, 8, 10, 16, or 36 + /// Converts a string into a number. The string must be non-empty + /// and well-formed as a number of the given base. The bit-width + /// must be sufficient to hold the result. + /// + /// This is used by the constructors that take string arguments. + /// + /// StringRef::getAsInteger is superficially similar but (1) does + /// not assume that the string is well-formed and (2) grows the + /// result to hold the input. + void fromString(unsigned numBits, StringRef str, uint8_t radix); + + /// \brief An internal division function for dividing APInts. + /// + /// This is used by the toString method to divide by the radix. It simply + /// provides a more convenient form of divide for internal use since KnuthDiv + /// has specific constraints on its inputs. If those constraints are not met + /// then it provides a simpler form of divide. + static void divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS, + unsigned rhsWords, APInt *Quotient, APInt *Remainder); + + /// out-of-line slow case for inline constructor + void initSlowCase(uint64_t val, bool isSigned); + + /// shared code between two array constructors + void initFromArray(ArrayRef<uint64_t> array); + + /// out-of-line slow case for inline copy constructor + void initSlowCase(const APInt &that); + + /// out-of-line slow case for shl + APInt shlSlowCase(unsigned shiftAmt) const; + + /// out-of-line slow case for operator& + APInt AndSlowCase(const APInt &RHS) const; + + /// out-of-line slow case for operator| + APInt OrSlowCase(const APInt &RHS) const; + + /// out-of-line slow case for operator^ + APInt XorSlowCase(const APInt &RHS) const; + + /// out-of-line slow case for operator= + APInt &AssignSlowCase(const APInt &RHS); + + /// out-of-line slow case for operator== + bool EqualSlowCase(const APInt &RHS) const; + + /// out-of-line slow case for operator== + bool EqualSlowCase(uint64_t Val) const; + + /// out-of-line slow case for countLeadingZeros + unsigned countLeadingZerosSlowCase() const; + + /// out-of-line slow case for countTrailingOnes + unsigned countTrailingOnesSlowCase() const; + + /// out-of-line slow case for countPopulation + unsigned countPopulationSlowCase() const; + +public: + /// \name Constructors + /// @{ + + /// \brief Create a new APInt of numBits width, initialized as val. + /// + /// If isSigned is true then val is treated as if it were a signed value + /// (i.e. as an int64_t) and the appropriate sign extension to the bit width + /// will be done. Otherwise, no sign extension occurs (high order bits beyond + /// the range of val are zero filled). + /// + /// \param numBits the bit width of the constructed APInt + /// \param val the initial value of the APInt + /// \param isSigned how to treat signedness of val + APInt(unsigned numBits, uint64_t val, bool isSigned = false) + : BitWidth(numBits), VAL(0) { + assert(BitWidth && "bitwidth too small"); + if (isSingleWord()) + VAL = val; + else + initSlowCase(val, isSigned); + clearUnusedBits(); + } + + /// \brief Construct an APInt of numBits width, initialized as bigVal[]. + /// + /// Note that bigVal.size() can be smaller or larger than the corresponding + /// bit width but any extraneous bits will be dropped. + /// + /// \param numBits the bit width of the constructed APInt + /// \param bigVal a sequence of words to form the initial value of the APInt + APInt(unsigned numBits, ArrayRef<uint64_t> bigVal); + + /// Equivalent to APInt(numBits, ArrayRef<uint64_t>(bigVal, numWords)), but + /// deprecated because this constructor is prone to ambiguity with the + /// APInt(unsigned, uint64_t, bool) constructor. + /// + /// If this overload is ever deleted, care should be taken to prevent calls + /// from being incorrectly captured by the APInt(unsigned, uint64_t, bool) + /// constructor. + APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]); + + /// \brief Construct an APInt from a string representation. + /// + /// This constructor interprets the string \p str in the given radix. The + /// interpretation stops when the first character that is not suitable for the + /// radix is encountered, or the end of the string. Acceptable radix values + /// are 2, 8, 10, 16, and 36. It is an error for the value implied by the + /// string to require more bits than numBits. + /// + /// \param numBits the bit width of the constructed APInt + /// \param str the string to be interpreted + /// \param radix the radix to use for the conversion + APInt(unsigned numBits, StringRef str, uint8_t radix); + + /// Simply makes *this a copy of that. + /// @brief Copy Constructor. + APInt(const APInt &that) : BitWidth(that.BitWidth), VAL(0) { + if (isSingleWord()) + VAL = that.VAL; + else + initSlowCase(that); + } + + /// \brief Move Constructor. + APInt(APInt &&that) : BitWidth(that.BitWidth), VAL(that.VAL) { + that.BitWidth = 0; + } + + /// \brief Destructor. + ~APInt() { + if (needsCleanup()) + delete[] pVal; + } + + /// \brief Default constructor that creates an uninteresting APInt + /// representing a 1-bit zero value. + /// + /// This is useful for object deserialization (pair this with the static + /// method Read). + explicit APInt() : BitWidth(1), VAL(0) {} + + /// \brief Returns whether this instance allocated memory. + bool needsCleanup() const { return !isSingleWord(); } + + /// Used to insert APInt objects, or objects that contain APInt objects, into + /// FoldingSets. + void Profile(FoldingSetNodeID &id) const; + + /// @} + /// \name Value Tests + /// @{ + + /// \brief Determine sign of this APInt. + /// + /// This tests the high bit of this APInt to determine if it is set. + /// + /// \returns true if this APInt is negative, false otherwise + bool isNegative() const { return (*this)[BitWidth - 1]; } + + /// \brief Determine if this APInt Value is non-negative (>= 0) + /// + /// This tests the high bit of the APInt to determine if it is unset. + bool isNonNegative() const { return !isNegative(); } + + /// \brief Determine if this APInt Value is positive. + /// + /// This tests if the value of this APInt is positive (> 0). Note + /// that 0 is not a positive value. + /// + /// \returns true if this APInt is positive. + bool isStrictlyPositive() const { return isNonNegative() && !!*this; } + + /// \brief Determine if all bits are set + /// + /// This checks to see if the value has all bits of the APInt are set or not. + bool isAllOnesValue() const { + if (isSingleWord()) + return VAL == ~integerPart(0) >> (APINT_BITS_PER_WORD - BitWidth); + return countPopulationSlowCase() == BitWidth; + } + + /// \brief Determine if this is the largest unsigned value. + /// + /// This checks to see if the value of this APInt is the maximum unsigned + /// value for the APInt's bit width. + bool isMaxValue() const { return isAllOnesValue(); } + + /// \brief Determine if this is the largest signed value. + /// + /// This checks to see if the value of this APInt is the maximum signed + /// value for the APInt's bit width. + bool isMaxSignedValue() const { + return !isNegative() && countPopulation() == BitWidth - 1; + } + + /// \brief Determine if this is the smallest unsigned value. + /// + /// This checks to see if the value of this APInt is the minimum unsigned + /// value for the APInt's bit width. + bool isMinValue() const { return !*this; } + + /// \brief Determine if this is the smallest signed value. + /// + /// This checks to see if the value of this APInt is the minimum signed + /// value for the APInt's bit width. + bool isMinSignedValue() const { + return isNegative() && isPowerOf2(); + } + + /// \brief Check if this APInt has an N-bits unsigned integer value. + bool isIntN(unsigned N) const { + assert(N && "N == 0 ???"); + return getActiveBits() <= N; + } + + /// \brief Check if this APInt has an N-bits signed integer value. + bool isSignedIntN(unsigned N) const { + assert(N && "N == 0 ???"); + return getMinSignedBits() <= N; + } + + /// \brief Check if this APInt's value is a power of two greater than zero. + /// + /// \returns true if the argument APInt value is a power of two > 0. + bool isPowerOf2() const { + if (isSingleWord()) + return isPowerOf2_64(VAL); + return countPopulationSlowCase() == 1; + } + + /// \brief Check if the APInt's value is returned by getSignBit. + /// + /// \returns true if this is the value returned by getSignBit. + bool isSignBit() const { return isMinSignedValue(); } + + /// \brief Convert APInt to a boolean value. + /// + /// This converts the APInt to a boolean value as a test against zero. + bool getBoolValue() const { return !!*this; } + + /// If this value is smaller than the specified limit, return it, otherwise + /// return the limit value. This causes the value to saturate to the limit. + uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const { + return (getActiveBits() > 64 || getZExtValue() > Limit) ? Limit + : getZExtValue(); + } + + /// \brief Check if the APInt consists of a repeated bit pattern. + /// + /// e.g. 0x01010101 satisfies isSplat(8). + /// \param SplatSizeInBits The size of the pattern in bits. Must divide bit + /// width without remainder. + bool isSplat(unsigned SplatSizeInBits) const; + + /// @} + /// \name Value Generators + /// @{ + + /// \brief Gets maximum unsigned value of APInt for specific bit width. + static APInt getMaxValue(unsigned numBits) { + return getAllOnesValue(numBits); + } + + /// \brief Gets maximum signed value of APInt for a specific bit width. + static APInt getSignedMaxValue(unsigned numBits) { + APInt API = getAllOnesValue(numBits); + API.clearBit(numBits - 1); + return API; + } + + /// \brief Gets minimum unsigned value of APInt for a specific bit width. + static APInt getMinValue(unsigned numBits) { return APInt(numBits, 0); } + + /// \brief Gets minimum signed value of APInt for a specific bit width. + static APInt getSignedMinValue(unsigned numBits) { + APInt API(numBits, 0); + API.setBit(numBits - 1); + return API; + } + + /// \brief Get the SignBit for a specific bit width. + /// + /// This is just a wrapper function of getSignedMinValue(), and it helps code + /// readability when we want to get a SignBit. + static APInt getSignBit(unsigned BitWidth) { + return getSignedMinValue(BitWidth); + } + + /// \brief Get the all-ones value. + /// + /// \returns the all-ones value for an APInt of the specified bit-width. + static APInt getAllOnesValue(unsigned numBits) { + return APInt(numBits, UINT64_MAX, true); + } + + /// \brief Get the '0' value. + /// + /// \returns the '0' value for an APInt of the specified bit-width. + static APInt getNullValue(unsigned numBits) { return APInt(numBits, 0); } + + /// \brief Compute an APInt containing numBits highbits from this APInt. + /// + /// Get an APInt with the same BitWidth as this APInt, just zero mask + /// the low bits and right shift to the least significant bit. + /// + /// \returns the high "numBits" bits of this APInt. + APInt getHiBits(unsigned numBits) const; + + /// \brief Compute an APInt containing numBits lowbits from this APInt. + /// + /// Get an APInt with the same BitWidth as this APInt, just zero mask + /// the high bits. + /// + /// \returns the low "numBits" bits of this APInt. + APInt getLoBits(unsigned numBits) const; + + /// \brief Return an APInt with exactly one bit set in the result. + static APInt getOneBitSet(unsigned numBits, unsigned BitNo) { + APInt Res(numBits, 0); + Res.setBit(BitNo); + return Res; + } + + /// \brief Get a value with a block of bits set. + /// + /// Constructs an APInt value that has a contiguous range of bits set. The + /// bits from loBit (inclusive) to hiBit (exclusive) will be set. All other + /// bits will be zero. For example, with parameters(32, 0, 16) you would get + /// 0x0000FFFF. If hiBit is less than loBit then the set bits "wrap". For + /// example, with parameters (32, 28, 4), you would get 0xF000000F. + /// + /// \param numBits the intended bit width of the result + /// \param loBit the index of the lowest bit set. + /// \param hiBit the index of the highest bit set. + /// + /// \returns An APInt value with the requested bits set. + static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit) { + assert(hiBit <= numBits && "hiBit out of range"); + assert(loBit < numBits && "loBit out of range"); + if (hiBit < loBit) + return getLowBitsSet(numBits, hiBit) | + getHighBitsSet(numBits, numBits - loBit); + return getLowBitsSet(numBits, hiBit - loBit).shl(loBit); + } + + /// \brief Get a value with high bits set + /// + /// Constructs an APInt value that has the top hiBitsSet bits set. + /// + /// \param numBits the bitwidth of the result + /// \param hiBitsSet the number of high-order bits set in the result. + static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet) { + assert(hiBitsSet <= numBits && "Too many bits to set!"); + // Handle a degenerate case, to avoid shifting by word size + if (hiBitsSet == 0) + return APInt(numBits, 0); + unsigned shiftAmt = numBits - hiBitsSet; + // For small values, return quickly + if (numBits <= APINT_BITS_PER_WORD) + return APInt(numBits, ~0ULL << shiftAmt); + return getAllOnesValue(numBits).shl(shiftAmt); + } + + /// \brief Get a value with low bits set + /// + /// Constructs an APInt value that has the bottom loBitsSet bits set. + /// + /// \param numBits the bitwidth of the result + /// \param loBitsSet the number of low-order bits set in the result. + static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet) { + assert(loBitsSet <= numBits && "Too many bits to set!"); + // Handle a degenerate case, to avoid shifting by word size + if (loBitsSet == 0) + return APInt(numBits, 0); + if (loBitsSet == APINT_BITS_PER_WORD) + return APInt(numBits, UINT64_MAX); + // For small values, return quickly. + if (loBitsSet <= APINT_BITS_PER_WORD) + return APInt(numBits, UINT64_MAX >> (APINT_BITS_PER_WORD - loBitsSet)); + return getAllOnesValue(numBits).lshr(numBits - loBitsSet); + } + + /// \brief Return a value containing V broadcasted over NewLen bits. + static APInt getSplat(unsigned NewLen, const APInt &V) { + assert(NewLen >= V.getBitWidth() && "Can't splat to smaller bit width!"); + + APInt Val = V.zextOrSelf(NewLen); + for (unsigned I = V.getBitWidth(); I < NewLen; I <<= 1) + Val |= Val << I; + + return Val; + } + + /// \brief Determine if two APInts have the same value, after zero-extending + /// one of them (if needed!) to ensure that the bit-widths match. + static bool isSameValue(const APInt &I1, const APInt &I2) { + if (I1.getBitWidth() == I2.getBitWidth()) + return I1 == I2; + + if (I1.getBitWidth() > I2.getBitWidth()) + return I1 == I2.zext(I1.getBitWidth()); + + return I1.zext(I2.getBitWidth()) == I2; + } + + /// \brief Overload to compute a hash_code for an APInt value. + friend hash_code hash_value(const APInt &Arg); + + /// This function returns a pointer to the internal storage of the APInt. + /// This is useful for writing out the APInt in binary form without any + /// conversions. + const uint64_t *getRawData() const { + if (isSingleWord()) + return &VAL; + return &pVal[0]; + } + + /// @} + /// \name Unary Operators + /// @{ + + /// \brief Postfix increment operator. + /// + /// \returns a new APInt value representing *this incremented by one + const APInt operator++(int) { + APInt API(*this); + ++(*this); + return API; + } + + /// \brief Prefix increment operator. + /// + /// \returns *this incremented by one + APInt &operator++(); + + /// \brief Postfix decrement operator. + /// + /// \returns a new APInt representing *this decremented by one. + const APInt operator--(int) { + APInt API(*this); + --(*this); + return API; + } + + /// \brief Prefix decrement operator. + /// + /// \returns *this decremented by one. + APInt &operator--(); + + /// \brief Unary bitwise complement operator. + /// + /// Performs a bitwise complement operation on this APInt. + /// + /// \returns an APInt that is the bitwise complement of *this + APInt operator~() const { + APInt Result(*this); + Result.flipAllBits(); + return Result; + } + + /// \brief Logical negation operator. + /// + /// Performs logical negation operation on this APInt. + /// + /// \returns true if *this is zero, false otherwise. + bool operator!() const { + if (isSingleWord()) + return !VAL; + + for (unsigned i = 0; i != getNumWords(); ++i) + if (pVal[i]) + return false; + return true; + } + + /// @} + /// \name Assignment Operators + /// @{ + + /// \brief Copy assignment operator. + /// + /// \returns *this after assignment of RHS. + APInt &operator=(const APInt &RHS) { + // If the bitwidths are the same, we can avoid mucking with memory + if (isSingleWord() && RHS.isSingleWord()) { + VAL = RHS.VAL; + BitWidth = RHS.BitWidth; + return clearUnusedBits(); + } + + return AssignSlowCase(RHS); + } + + /// @brief Move assignment operator. + APInt &operator=(APInt &&that) { + if (!isSingleWord()) { + // The MSVC STL shipped in 2013 requires that self move assignment be a + // no-op. Otherwise algorithms like stable_sort will produce answers + // where half of the output is left in a moved-from state. + if (this == &that) + return *this; + delete[] pVal; + } + + // Use memcpy so that type based alias analysis sees both VAL and pVal + // as modified. + memcpy(&VAL, &that.VAL, sizeof(uint64_t)); + + // If 'this == &that', avoid zeroing our own bitwidth by storing to 'that' + // first. + unsigned ThatBitWidth = that.BitWidth; + that.BitWidth = 0; + BitWidth = ThatBitWidth; + + return *this; + } + + /// \brief Assignment operator. + /// + /// The RHS value is assigned to *this. If the significant bits in RHS exceed + /// the bit width, the excess bits are truncated. If the bit width is larger + /// than 64, the value is zero filled in the unspecified high order bits. + /// + /// \returns *this after assignment of RHS value. + APInt &operator=(uint64_t RHS); + + /// \brief Bitwise AND assignment operator. + /// + /// Performs a bitwise AND operation on this APInt and RHS. The result is + /// assigned to *this. + /// + /// \returns *this after ANDing with RHS. + APInt &operator&=(const APInt &RHS); + + /// \brief Bitwise OR assignment operator. + /// + /// Performs a bitwise OR operation on this APInt and RHS. The result is + /// assigned *this; + /// + /// \returns *this after ORing with RHS. + APInt &operator|=(const APInt &RHS); + + /// \brief Bitwise OR assignment operator. + /// + /// Performs a bitwise OR operation on this APInt and RHS. RHS is + /// logically zero-extended or truncated to match the bit-width of + /// the LHS. + APInt &operator|=(uint64_t RHS) { + if (isSingleWord()) { + VAL |= RHS; + clearUnusedBits(); + } else { + pVal[0] |= RHS; + } + return *this; + } + + /// \brief Bitwise XOR assignment operator. + /// + /// Performs a bitwise XOR operation on this APInt and RHS. The result is + /// assigned to *this. + /// + /// \returns *this after XORing with RHS. + APInt &operator^=(const APInt &RHS); + + /// \brief Multiplication assignment operator. + /// + /// Multiplies this APInt by RHS and assigns the result to *this. + /// + /// \returns *this + APInt &operator*=(const APInt &RHS); + + /// \brief Addition assignment operator. + /// + /// Adds RHS to *this and assigns the result to *this. + /// + /// \returns *this + APInt &operator+=(const APInt &RHS); + APInt &operator+=(uint64_t RHS); + + /// \brief Subtraction assignment operator. + /// + /// Subtracts RHS from *this and assigns the result to *this. + /// + /// \returns *this + APInt &operator-=(const APInt &RHS); + APInt &operator-=(uint64_t RHS); + + /// \brief Left-shift assignment function. + /// + /// Shifts *this left by shiftAmt and assigns the result to *this. + /// + /// \returns *this after shifting left by shiftAmt + APInt &operator<<=(unsigned shiftAmt) { + *this = shl(shiftAmt); + return *this; + } + + /// @} + /// \name Binary Operators + /// @{ + + /// \brief Bitwise AND operator. + /// + /// Performs a bitwise AND operation on *this and RHS. + /// + /// \returns An APInt value representing the bitwise AND of *this and RHS. + APInt operator&(const APInt &RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(getBitWidth(), VAL & RHS.VAL); + return AndSlowCase(RHS); + } + APInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APInt &RHS) const { + return this->operator&(RHS); + } + + /// \brief Bitwise OR operator. + /// + /// Performs a bitwise OR operation on *this and RHS. + /// + /// \returns An APInt value representing the bitwise OR of *this and RHS. + APInt operator|(const APInt &RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(getBitWidth(), VAL | RHS.VAL); + return OrSlowCase(RHS); + } + + /// \brief Bitwise OR function. + /// + /// Performs a bitwise or on *this and RHS. This is implemented by simply + /// calling operator|. + /// + /// \returns An APInt value representing the bitwise OR of *this and RHS. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APInt &RHS) const { + return this->operator|(RHS); + } + + /// \brief Bitwise XOR operator. + /// + /// Performs a bitwise XOR operation on *this and RHS. + /// + /// \returns An APInt value representing the bitwise XOR of *this and RHS. + APInt operator^(const APInt &RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(BitWidth, VAL ^ RHS.VAL); + return XorSlowCase(RHS); + } + + /// \brief Bitwise XOR function. + /// + /// Performs a bitwise XOR operation on *this and RHS. This is implemented + /// through the usage of operator^. + /// + /// \returns An APInt value representing the bitwise XOR of *this and RHS. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APInt &RHS) const { + return this->operator^(RHS); + } + + /// \brief Multiplication operator. + /// + /// Multiplies this APInt by RHS and returns the result. + APInt operator*(const APInt &RHS) const; + + /// \brief Left logical shift operator. + /// + /// Shifts this APInt left by \p Bits and returns the result. + APInt operator<<(unsigned Bits) const { return shl(Bits); } + + /// \brief Left logical shift operator. + /// + /// Shifts this APInt left by \p Bits and returns the result. + APInt operator<<(const APInt &Bits) const { return shl(Bits); } + + /// \brief Arithmetic right-shift function. + /// + /// Arithmetic right-shift this APInt by shiftAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT ashr(unsigned shiftAmt) const; + + /// \brief Logical right-shift function. + /// + /// Logical right-shift this APInt by shiftAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT lshr(unsigned shiftAmt) const; + + /// \brief Left-shift function. + /// + /// Left-shift this APInt by shiftAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT shl(unsigned shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount"); + if (isSingleWord()) { + if (shiftAmt >= BitWidth) + return APInt(BitWidth, 0); // avoid undefined shift results + return APInt(BitWidth, VAL << shiftAmt); + } + return shlSlowCase(shiftAmt); + } + + /// \brief Rotate left by rotateAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotl(unsigned rotateAmt) const; + + /// \brief Rotate right by rotateAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotr(unsigned rotateAmt) const; + + /// \brief Arithmetic right-shift function. + /// + /// Arithmetic right-shift this APInt by shiftAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT ashr(const APInt &shiftAmt) const; + + /// \brief Logical right-shift function. + /// + /// Logical right-shift this APInt by shiftAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT lshr(const APInt &shiftAmt) const; + + /// \brief Left-shift function. + /// + /// Left-shift this APInt by shiftAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT shl(const APInt &shiftAmt) const; + + /// \brief Rotate left by rotateAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotl(const APInt &rotateAmt) const; + + /// \brief Rotate right by rotateAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotr(const APInt &rotateAmt) const; + + /// \brief Unsigned division operation. + /// + /// Perform an unsigned divide operation on this APInt by RHS. Both this and + /// RHS are treated as unsigned quantities for purposes of this division. + /// + /// \returns a new APInt value containing the division result + APInt LLVM_ATTRIBUTE_UNUSED_RESULT udiv(const APInt &RHS) const; + + /// \brief Signed division function for APInt. + /// + /// Signed divide this APInt by APInt RHS. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sdiv(const APInt &RHS) const; + + /// \brief Unsigned remainder operation. + /// + /// Perform an unsigned remainder operation on this APInt with RHS being the + /// divisor. Both this and RHS are treated as unsigned quantities for purposes + /// of this operation. Note that this is a true remainder operation and not a + /// modulo operation because the sign follows the sign of the dividend which + /// is *this. + /// + /// \returns a new APInt value containing the remainder result + APInt LLVM_ATTRIBUTE_UNUSED_RESULT urem(const APInt &RHS) const; + + /// \brief Function for signed remainder operation. + /// + /// Signed remainder operation on APInt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT srem(const APInt &RHS) const; + + /// \brief Dual division/remainder interface. + /// + /// Sometimes it is convenient to divide two APInt values and obtain both the + /// quotient and remainder. This function does both operations in the same + /// computation making it a little more efficient. The pair of input arguments + /// may overlap with the pair of output arguments. It is safe to call + /// udivrem(X, Y, X, Y), for example. + static void udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, + APInt &Remainder); + + static void sdivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, + APInt &Remainder); + + // Operations that return overflow indicators. + APInt sadd_ov(const APInt &RHS, bool &Overflow) const; + APInt uadd_ov(const APInt &RHS, bool &Overflow) const; + APInt ssub_ov(const APInt &RHS, bool &Overflow) const; + APInt usub_ov(const APInt &RHS, bool &Overflow) const; + APInt sdiv_ov(const APInt &RHS, bool &Overflow) const; + APInt smul_ov(const APInt &RHS, bool &Overflow) const; + APInt umul_ov(const APInt &RHS, bool &Overflow) const; + APInt sshl_ov(const APInt &Amt, bool &Overflow) const; + APInt ushl_ov(const APInt &Amt, bool &Overflow) const; + + /// \brief Array-indexing support. + /// + /// \returns the bit value at bitPosition + bool operator[](unsigned bitPosition) const { + assert(bitPosition < getBitWidth() && "Bit position out of bounds!"); + return (maskBit(bitPosition) & + (isSingleWord() ? VAL : pVal[whichWord(bitPosition)])) != + 0; + } + + /// @} + /// \name Comparison Operators + /// @{ + + /// \brief Equality operator. + /// + /// Compares this APInt with RHS for the validity of the equality + /// relationship. + bool operator==(const APInt &RHS) const { + assert(BitWidth == RHS.BitWidth && "Comparison requires equal bit widths"); + if (isSingleWord()) + return VAL == RHS.VAL; + return EqualSlowCase(RHS); + } + + /// \brief Equality operator. + /// + /// Compares this APInt with a uint64_t for the validity of the equality + /// relationship. + /// + /// \returns true if *this == Val + bool operator==(uint64_t Val) const { + if (isSingleWord()) + return VAL == Val; + return EqualSlowCase(Val); + } + + /// \brief Equality comparison. + /// + /// Compares this APInt with RHS for the validity of the equality + /// relationship. + /// + /// \returns true if *this == Val + bool eq(const APInt &RHS) const { return (*this) == RHS; } + + /// \brief Inequality operator. + /// + /// Compares this APInt with RHS for the validity of the inequality + /// relationship. + /// + /// \returns true if *this != Val + bool operator!=(const APInt &RHS) const { return !((*this) == RHS); } + + /// \brief Inequality operator. + /// + /// Compares this APInt with a uint64_t for the validity of the inequality + /// relationship. + /// + /// \returns true if *this != Val + bool operator!=(uint64_t Val) const { return !((*this) == Val); } + + /// \brief Inequality comparison + /// + /// Compares this APInt with RHS for the validity of the inequality + /// relationship. + /// + /// \returns true if *this != Val + bool ne(const APInt &RHS) const { return !((*this) == RHS); } + + /// \brief Unsigned less than comparison + /// + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// + /// \returns true if *this < RHS when both are considered unsigned. + bool ult(const APInt &RHS) const; + + /// \brief Unsigned less than comparison + /// + /// Regards both *this as an unsigned quantity and compares it with RHS for + /// the validity of the less-than relationship. + /// + /// \returns true if *this < RHS when considered unsigned. + bool ult(uint64_t RHS) const { + return getActiveBits() > 64 ? false : getZExtValue() < RHS; + } + + /// \brief Signed less than comparison + /// + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-than relationship. + /// + /// \returns true if *this < RHS when both are considered signed. + bool slt(const APInt &RHS) const; + + /// \brief Signed less than comparison + /// + /// Regards both *this as a signed quantity and compares it with RHS for + /// the validity of the less-than relationship. + /// + /// \returns true if *this < RHS when considered signed. + bool slt(int64_t RHS) const { + return getMinSignedBits() > 64 ? isNegative() : getSExtValue() < RHS; + } + + /// \brief Unsigned less or equal comparison + /// + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// + /// \returns true if *this <= RHS when both are considered unsigned. + bool ule(const APInt &RHS) const { return ult(RHS) || eq(RHS); } + + /// \brief Unsigned less or equal comparison + /// + /// Regards both *this as an unsigned quantity and compares it with RHS for + /// the validity of the less-or-equal relationship. + /// + /// \returns true if *this <= RHS when considered unsigned. + bool ule(uint64_t RHS) const { return !ugt(RHS); } + + /// \brief Signed less or equal comparison + /// + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// + /// \returns true if *this <= RHS when both are considered signed. + bool sle(const APInt &RHS) const { return slt(RHS) || eq(RHS); } + + /// \brief Signed less or equal comparison + /// + /// Regards both *this as a signed quantity and compares it with RHS for the + /// validity of the less-or-equal relationship. + /// + /// \returns true if *this <= RHS when considered signed. + bool sle(uint64_t RHS) const { return !sgt(RHS); } + + /// \brief Unsigned greather than comparison + /// + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// + /// \returns true if *this > RHS when both are considered unsigned. + bool ugt(const APInt &RHS) const { return !ult(RHS) && !eq(RHS); } + + /// \brief Unsigned greater than comparison + /// + /// Regards both *this as an unsigned quantity and compares it with RHS for + /// the validity of the greater-than relationship. + /// + /// \returns true if *this > RHS when considered unsigned. + bool ugt(uint64_t RHS) const { + return getActiveBits() > 64 ? true : getZExtValue() > RHS; + } + + /// \brief Signed greather than comparison + /// + /// Regards both *this and RHS as signed quantities and compares them for the + /// validity of the greater-than relationship. + /// + /// \returns true if *this > RHS when both are considered signed. + bool sgt(const APInt &RHS) const { return !slt(RHS) && !eq(RHS); } + + /// \brief Signed greater than comparison + /// + /// Regards both *this as a signed quantity and compares it with RHS for + /// the validity of the greater-than relationship. + /// + /// \returns true if *this > RHS when considered signed. + bool sgt(int64_t RHS) const { + return getMinSignedBits() > 64 ? !isNegative() : getSExtValue() > RHS; + } + + /// \brief Unsigned greater or equal comparison + /// + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// + /// \returns true if *this >= RHS when both are considered unsigned. + bool uge(const APInt &RHS) const { return !ult(RHS); } + + /// \brief Unsigned greater or equal comparison + /// + /// Regards both *this as an unsigned quantity and compares it with RHS for + /// the validity of the greater-or-equal relationship. + /// + /// \returns true if *this >= RHS when considered unsigned. + bool uge(uint64_t RHS) const { return !ult(RHS); } + + /// \brief Signed greather or equal comparison + /// + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// + /// \returns true if *this >= RHS when both are considered signed. + bool sge(const APInt &RHS) const { return !slt(RHS); } + + /// \brief Signed greater or equal comparison + /// + /// Regards both *this as a signed quantity and compares it with RHS for + /// the validity of the greater-or-equal relationship. + /// + /// \returns true if *this >= RHS when considered signed. + bool sge(int64_t RHS) const { return !slt(RHS); } + + /// This operation tests if there are any pairs of corresponding bits + /// between this APInt and RHS that are both set. + bool intersects(const APInt &RHS) const { return (*this & RHS) != 0; } + + /// @} + /// \name Resizing Operators + /// @{ + + /// \brief Truncate to new width. + /// + /// Truncate the APInt to a specified width. It is an error to specify a width + /// that is greater than or equal to the current width. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(unsigned width) const; + + /// \brief Sign extend to a new width. + /// + /// This operation sign extends the APInt to a new width. If the high order + /// bit is set, the fill on the left will be done with 1 bits, otherwise zero. + /// It is an error to specify a width that is less than or equal to the + /// current width. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sext(unsigned width) const; + + /// \brief Zero extend to a new width. + /// + /// This operation zero extends the APInt to a new width. The high order bits + /// are filled with 0 bits. It is an error to specify a width that is less + /// than or equal to the current width. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT zext(unsigned width) const; + + /// \brief Sign extend or truncate to width + /// + /// Make this APInt have the bit width given by \p width. The value is sign + /// extended, truncated, or left alone to make it that width. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sextOrTrunc(unsigned width) const; + + /// \brief Zero extend or truncate to width + /// + /// Make this APInt have the bit width given by \p width. The value is zero + /// extended, truncated, or left alone to make it that width. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT zextOrTrunc(unsigned width) const; + + /// \brief Sign extend or truncate to width + /// + /// Make this APInt have the bit width given by \p width. The value is sign + /// extended, or left alone to make it that width. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sextOrSelf(unsigned width) const; + + /// \brief Zero extend or truncate to width + /// + /// Make this APInt have the bit width given by \p width. The value is zero + /// extended, or left alone to make it that width. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT zextOrSelf(unsigned width) const; + + /// @} + /// \name Bit Manipulation Operators + /// @{ + + /// \brief Set every bit to 1. + void setAllBits() { + if (isSingleWord()) + VAL = UINT64_MAX; + else { + // Set all the bits in all the words. + for (unsigned i = 0; i < getNumWords(); ++i) + pVal[i] = UINT64_MAX; + } + // Clear the unused ones + clearUnusedBits(); + } + + /// \brief Set a given bit to 1. + /// + /// Set the given bit to 1 whose position is given as "bitPosition". + void setBit(unsigned bitPosition); + + /// \brief Set every bit to 0. + void clearAllBits() { + if (isSingleWord()) + VAL = 0; + else + memset(pVal, 0, getNumWords() * APINT_WORD_SIZE); + } + + /// \brief Set a given bit to 0. + /// + /// Set the given bit to 0 whose position is given as "bitPosition". + void clearBit(unsigned bitPosition); + + /// \brief Toggle every bit to its opposite value. + void flipAllBits() { + if (isSingleWord()) + VAL ^= UINT64_MAX; + else { + for (unsigned i = 0; i < getNumWords(); ++i) + pVal[i] ^= UINT64_MAX; + } + clearUnusedBits(); + } + + /// \brief Toggles a given bit to its opposite value. + /// + /// Toggle a given bit to its opposite value whose position is given + /// as "bitPosition". + void flipBit(unsigned bitPosition); + + /// @} + /// \name Value Characterization Functions + /// @{ + + /// \brief Return the number of bits in the APInt. + unsigned getBitWidth() const { return BitWidth; } + + /// \brief Get the number of words. + /// + /// Here one word's bitwidth equals to that of uint64_t. + /// + /// \returns the number of words to hold the integer value of this APInt. + unsigned getNumWords() const { return getNumWords(BitWidth); } + + /// \brief Get the number of words. + /// + /// *NOTE* Here one word's bitwidth equals to that of uint64_t. + /// + /// \returns the number of words to hold the integer value with a given bit + /// width. + static unsigned getNumWords(unsigned BitWidth) { + return ((uint64_t)BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; + } + + /// \brief Compute the number of active bits in the value + /// + /// This function returns the number of active bits which is defined as the + /// bit width minus the number of leading zeros. This is used in several + /// computations to see how "wide" the value is. + unsigned getActiveBits() const { return BitWidth - countLeadingZeros(); } + + /// \brief Compute the number of active words in the value of this APInt. + /// + /// This is used in conjunction with getActiveData to extract the raw value of + /// the APInt. + unsigned getActiveWords() const { + unsigned numActiveBits = getActiveBits(); + return numActiveBits ? whichWord(numActiveBits - 1) + 1 : 1; + } + + /// \brief Get the minimum bit size for this signed APInt + /// + /// Computes the minimum bit width for this APInt while considering it to be a + /// signed (and probably negative) value. If the value is not negative, this + /// function returns the same value as getActiveBits()+1. Otherwise, it + /// returns the smallest bit width that will retain the negative value. For + /// example, -1 can be written as 0b1 or 0xFFFFFFFFFF. 0b1 is shorter and so + /// for -1, this function will always return 1. + unsigned getMinSignedBits() const { + if (isNegative()) + return BitWidth - countLeadingOnes() + 1; + return getActiveBits() + 1; + } + + /// \brief Get zero extended value + /// + /// This method attempts to return the value of this APInt as a zero extended + /// uint64_t. The bitwidth must be <= 64 or the value must fit within a + /// uint64_t. Otherwise an assertion will result. + uint64_t getZExtValue() const { + if (isSingleWord()) + return VAL; + assert(getActiveBits() <= 64 && "Too many bits for uint64_t"); + return pVal[0]; + } + + /// \brief Get sign extended value + /// + /// This method attempts to return the value of this APInt as a sign extended + /// int64_t. The bit width must be <= 64 or the value must fit within an + /// int64_t. Otherwise an assertion will result. + int64_t getSExtValue() const { + if (isSingleWord()) + return int64_t(VAL << (APINT_BITS_PER_WORD - BitWidth)) >> + (APINT_BITS_PER_WORD - BitWidth); + assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); + return int64_t(pVal[0]); + } + + /// \brief Get bits required for string value. + /// + /// This method determines how many bits are required to hold the APInt + /// equivalent of the string given by \p str. + static unsigned getBitsNeeded(StringRef str, uint8_t radix); + + /// \brief The APInt version of the countLeadingZeros functions in + /// MathExtras.h. + /// + /// It counts the number of zeros from the most significant bit to the first + /// one bit. + /// + /// \returns BitWidth if the value is zero, otherwise returns the number of + /// zeros from the most significant bit to the first one bits. + unsigned countLeadingZeros() const { + if (isSingleWord()) { + unsigned unusedBits = APINT_BITS_PER_WORD - BitWidth; + return llvm::countLeadingZeros(VAL) - unusedBits; + } + return countLeadingZerosSlowCase(); + } + + /// \brief Count the number of leading one bits. + /// + /// This function is an APInt version of the countLeadingOnes + /// functions in MathExtras.h. It counts the number of ones from the most + /// significant bit to the first zero bit. + /// + /// \returns 0 if the high order bit is not set, otherwise returns the number + /// of 1 bits from the most significant to the least + unsigned countLeadingOnes() const; + + /// Computes the number of leading bits of this APInt that are equal to its + /// sign bit. + unsigned getNumSignBits() const { + return isNegative() ? countLeadingOnes() : countLeadingZeros(); + } + + /// \brief Count the number of trailing zero bits. + /// + /// This function is an APInt version of the countTrailingZeros + /// functions in MathExtras.h. It counts the number of zeros from the least + /// significant bit to the first set bit. + /// + /// \returns BitWidth if the value is zero, otherwise returns the number of + /// zeros from the least significant bit to the first one bit. + unsigned countTrailingZeros() const; + + /// \brief Count the number of trailing one bits. + /// + /// This function is an APInt version of the countTrailingOnes + /// functions in MathExtras.h. It counts the number of ones from the least + /// significant bit to the first zero bit. + /// + /// \returns BitWidth if the value is all ones, otherwise returns the number + /// of ones from the least significant bit to the first zero bit. + unsigned countTrailingOnes() const { + if (isSingleWord()) + return llvm::countTrailingOnes(VAL); + return countTrailingOnesSlowCase(); + } + + /// \brief Count the number of bits set. + /// + /// This function is an APInt version of the countPopulation functions + /// in MathExtras.h. It counts the number of 1 bits in the APInt value. + /// + /// \returns 0 if the value is zero, otherwise returns the number of set bits. + unsigned countPopulation() const { + if (isSingleWord()) + return llvm::countPopulation(VAL); + return countPopulationSlowCase(); + } + + /// @} + /// \name Conversion Functions + /// @{ + void print(raw_ostream &OS, bool isSigned) const; + + /// Converts an APInt to a string and append it to Str. Str is commonly a + /// SmallString. + void toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed, + bool formatAsCLiteral = false) const; + + /// Considers the APInt to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 16, or 36. + void toStringUnsigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { + toString(Str, Radix, false, false); + } + + /// Considers the APInt to be signed and converts it into a string in the + /// radix given. The radix can be 2, 8, 10, 16, or 36. + void toStringSigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { + toString(Str, Radix, true, false); + } + + /// \brief Return the APInt as a std::string. + /// + /// Note that this is an inefficient method. It is better to pass in a + /// SmallVector/SmallString to the methods above to avoid thrashing the heap + /// for the string. + std::string toString(unsigned Radix, bool Signed) const; + + /// \returns a byte-swapped representation of this APInt Value. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT byteSwap() const; + + /// \returns the value with the bit representation reversed of this APInt + /// Value. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT reverseBits() const; + + /// \brief Converts this APInt to a double value. + double roundToDouble(bool isSigned) const; + + /// \brief Converts this unsigned APInt to a double value. + double roundToDouble() const { return roundToDouble(false); } + + /// \brief Converts this signed APInt to a double value. + double signedRoundToDouble() const { return roundToDouble(true); } + + /// \brief Converts APInt bits to a double + /// + /// The conversion does not do a translation from integer to double, it just + /// re-interprets the bits as a double. Note that it is valid to do this on + /// any bit width. Exactly 64 bits will be translated. + double bitsToDouble() const { + union { + uint64_t I; + double D; + } T; + T.I = (isSingleWord() ? VAL : pVal[0]); + return T.D; + } + + /// \brief Converts APInt bits to a double + /// + /// The conversion does not do a translation from integer to float, it just + /// re-interprets the bits as a float. Note that it is valid to do this on + /// any bit width. Exactly 32 bits will be translated. + float bitsToFloat() const { + union { + unsigned I; + float F; + } T; + T.I = unsigned((isSingleWord() ? VAL : pVal[0])); + return T.F; + } + + /// \brief Converts a double to APInt bits. + /// + /// The conversion does not do a translation from double to integer, it just + /// re-interprets the bits of the double. + static APInt LLVM_ATTRIBUTE_UNUSED_RESULT doubleToBits(double V) { + union { + uint64_t I; + double D; + } T; + T.D = V; + return APInt(sizeof T * CHAR_BIT, T.I); + } + + /// \brief Converts a float to APInt bits. + /// + /// The conversion does not do a translation from float to integer, it just + /// re-interprets the bits of the float. + static APInt LLVM_ATTRIBUTE_UNUSED_RESULT floatToBits(float V) { + union { + unsigned I; + float F; + } T; + T.F = V; + return APInt(sizeof T * CHAR_BIT, T.I); + } + + /// @} + /// \name Mathematics Operations + /// @{ + + /// \returns the floor log base 2 of this APInt. + unsigned logBase2() const { return BitWidth - 1 - countLeadingZeros(); } + + /// \returns the ceil log base 2 of this APInt. + unsigned ceilLogBase2() const { + APInt temp(*this); + --temp; + return BitWidth - temp.countLeadingZeros(); + } + + /// \returns the nearest log base 2 of this APInt. Ties round up. + /// + /// NOTE: When we have a BitWidth of 1, we define: + /// + /// log2(0) = UINT32_MAX + /// log2(1) = 0 + /// + /// to get around any mathematical concerns resulting from + /// referencing 2 in a space where 2 does no exist. + unsigned nearestLogBase2() const { + // Special case when we have a bitwidth of 1. If VAL is 1, then we + // get 0. If VAL is 0, we get UINT64_MAX which gets truncated to + // UINT32_MAX. + if (BitWidth == 1) + return VAL - 1; + + // Handle the zero case. + if (!getBoolValue()) + return UINT32_MAX; + + // The non-zero case is handled by computing: + // + // nearestLogBase2(x) = logBase2(x) + x[logBase2(x)-1]. + // + // where x[i] is referring to the value of the ith bit of x. + unsigned lg = logBase2(); + return lg + unsigned((*this)[lg - 1]); + } + + /// \returns the log base 2 of this APInt if its an exact power of two, -1 + /// otherwise + int32_t exactLogBase2() const { + if (!isPowerOf2()) + return -1; + return logBase2(); + } + + /// \brief Compute the square root + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sqrt() const; + + /// \brief Get the absolute value; + /// + /// If *this is < 0 then return -(*this), otherwise *this; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT abs() const { + if (isNegative()) + return -(*this); + return *this; + } + + /// \returns the multiplicative inverse for a given modulo. + APInt multiplicativeInverse(const APInt &modulo) const; + + /// @} + /// \name Support for division by constant + /// @{ + + /// Calculate the magic number for signed division by a constant. + struct ms; + ms magic() const; + + /// Calculate the magic number for unsigned division by a constant. + struct mu; + mu magicu(unsigned LeadingZeros = 0) const; + + /// @} + /// \name Building-block Operations for APInt and APFloat + /// @{ + + // These building block operations operate on a representation of arbitrary + // precision, two's-complement, bignum integer values. They should be + // sufficient to implement APInt and APFloat bignum requirements. Inputs are + // generally a pointer to the base of an array of integer parts, representing + // an unsigned bignum, and a count of how many parts there are. + + /// Sets the least significant part of a bignum to the input value, and zeroes + /// out higher parts. + static void tcSet(integerPart *, integerPart, unsigned int); + + /// Assign one bignum to another. + static void tcAssign(integerPart *, const integerPart *, unsigned int); + + /// Returns true if a bignum is zero, false otherwise. + static bool tcIsZero(const integerPart *, unsigned int); + + /// Extract the given bit of a bignum; returns 0 or 1. Zero-based. + static int tcExtractBit(const integerPart *, unsigned int bit); + + /// Copy the bit vector of width srcBITS from SRC, starting at bit srcLSB, to + /// DST, of dstCOUNT parts, such that the bit srcLSB becomes the least + /// significant bit of DST. All high bits above srcBITS in DST are + /// zero-filled. + static void tcExtract(integerPart *, unsigned int dstCount, + const integerPart *, unsigned int srcBits, + unsigned int srcLSB); + + /// Set the given bit of a bignum. Zero-based. + static void tcSetBit(integerPart *, unsigned int bit); + + /// Clear the given bit of a bignum. Zero-based. + static void tcClearBit(integerPart *, unsigned int bit); + + /// Returns the bit number of the least or most significant set bit of a + /// number. If the input number has no bits set -1U is returned. + static unsigned int tcLSB(const integerPart *, unsigned int); + static unsigned int tcMSB(const integerPart *parts, unsigned int n); + + /// Negate a bignum in-place. + static void tcNegate(integerPart *, unsigned int); + + /// DST += RHS + CARRY where CARRY is zero or one. Returns the carry flag. + static integerPart tcAdd(integerPart *, const integerPart *, + integerPart carry, unsigned); + + /// DST -= RHS + CARRY where CARRY is zero or one. Returns the carry flag. + static integerPart tcSubtract(integerPart *, const integerPart *, + integerPart carry, unsigned); + + /// DST += SRC * MULTIPLIER + PART if add is true + /// DST = SRC * MULTIPLIER + PART if add is false + /// + /// Requires 0 <= DSTPARTS <= SRCPARTS + 1. If DST overlaps SRC they must + /// start at the same point, i.e. DST == SRC. + /// + /// If DSTPARTS == SRC_PARTS + 1 no overflow occurs and zero is returned. + /// Otherwise DST is filled with the least significant DSTPARTS parts of the + /// result, and if all of the omitted higher parts were zero return zero, + /// otherwise overflow occurred and return one. + static int tcMultiplyPart(integerPart *dst, const integerPart *src, + integerPart multiplier, integerPart carry, + unsigned int srcParts, unsigned int dstParts, + bool add); + + /// DST = LHS * RHS, where DST has the same width as the operands and is + /// filled with the least significant parts of the result. Returns one if + /// overflow occurred, otherwise zero. DST must be disjoint from both + /// operands. + static int tcMultiply(integerPart *, const integerPart *, const integerPart *, + unsigned); + + /// DST = LHS * RHS, where DST has width the sum of the widths of the + /// operands. No overflow occurs. DST must be disjoint from both + /// operands. Returns the number of parts required to hold the result. + static unsigned int tcFullMultiply(integerPart *, const integerPart *, + const integerPart *, unsigned, unsigned); + + /// If RHS is zero LHS and REMAINDER are left unchanged, return one. + /// Otherwise set LHS to LHS / RHS with the fractional part discarded, set + /// REMAINDER to the remainder, return zero. i.e. + /// + /// OLD_LHS = RHS * LHS + REMAINDER + /// + /// SCRATCH is a bignum of the same size as the operands and result for use by + /// the routine; its contents need not be initialized and are destroyed. LHS, + /// REMAINDER and SCRATCH must be distinct. + static int tcDivide(integerPart *lhs, const integerPart *rhs, + integerPart *remainder, integerPart *scratch, + unsigned int parts); + + /// Shift a bignum left COUNT bits. Shifted in bits are zero. There are no + /// restrictions on COUNT. + static void tcShiftLeft(integerPart *, unsigned int parts, + unsigned int count); + + /// Shift a bignum right COUNT bits. Shifted in bits are zero. There are no + /// restrictions on COUNT. + static void tcShiftRight(integerPart *, unsigned int parts, + unsigned int count); + + /// The obvious AND, OR and XOR and complement operations. + static void tcAnd(integerPart *, const integerPart *, unsigned int); + static void tcOr(integerPart *, const integerPart *, unsigned int); + static void tcXor(integerPart *, const integerPart *, unsigned int); + static void tcComplement(integerPart *, unsigned int); + + /// Comparison (unsigned) of two bignums. + static int tcCompare(const integerPart *, const integerPart *, unsigned int); + + /// Increment a bignum in-place. Return the carry flag. + static integerPart tcIncrement(integerPart *, unsigned int); + + /// Decrement a bignum in-place. Return the borrow flag. + static integerPart tcDecrement(integerPart *, unsigned int); + + /// Set the least significant BITS and clear the rest. + static void tcSetLeastSignificantBits(integerPart *, unsigned int, + unsigned int bits); + + /// \brief debug method + void dump() const; + + /// @} +}; + +/// Magic data for optimising signed division by a constant. +struct APInt::ms { + APInt m; ///< magic number + unsigned s; ///< shift amount +}; + +/// Magic data for optimising unsigned division by a constant. +struct APInt::mu { + APInt m; ///< magic number + bool a; ///< add indicator + unsigned s; ///< shift amount +}; + +inline bool operator==(uint64_t V1, const APInt &V2) { return V2 == V1; } + +inline bool operator!=(uint64_t V1, const APInt &V2) { return V2 != V1; } + +inline raw_ostream &operator<<(raw_ostream &OS, const APInt &I) { + I.print(OS, true); + return OS; +} + +inline APInt operator-(APInt v) { + v.flipAllBits(); + ++v; + return v; +} + +inline APInt operator+(APInt a, const APInt &b) { + a += b; + return a; +} + +inline APInt operator+(const APInt &a, APInt &&b) { + b += a; + return std::move(b); +} + +inline APInt operator+(APInt a, uint64_t RHS) { + a += RHS; + return a; +} + +inline APInt operator+(uint64_t LHS, APInt b) { + b += LHS; + return b; +} + +inline APInt operator-(APInt a, const APInt &b) { + a -= b; + return a; +} + +inline APInt operator-(const APInt &a, APInt &&b) { + b = -std::move(b); + b += a; + return std::move(b); +} + +inline APInt operator-(APInt a, uint64_t RHS) { + a -= RHS; + return a; +} + +inline APInt operator-(uint64_t LHS, APInt b) { + b = -std::move(b); + b += LHS; + return b; +} + + +namespace APIntOps { + +/// \brief Determine the smaller of two APInts considered to be signed. +inline const APInt &smin(const APInt &A, const APInt &B) { + return A.slt(B) ? A : B; +} + +/// \brief Determine the larger of two APInts considered to be signed. +inline const APInt &smax(const APInt &A, const APInt &B) { + return A.sgt(B) ? A : B; +} + +/// \brief Determine the smaller of two APInts considered to be signed. +inline const APInt &umin(const APInt &A, const APInt &B) { + return A.ult(B) ? A : B; +} + +/// \brief Determine the larger of two APInts considered to be unsigned. +inline const APInt &umax(const APInt &A, const APInt &B) { + return A.ugt(B) ? A : B; +} + +/// \brief Check if the specified APInt has a N-bits unsigned integer value. +inline bool isIntN(unsigned N, const APInt &APIVal) { return APIVal.isIntN(N); } + +/// \brief Check if the specified APInt has a N-bits signed integer value. +inline bool isSignedIntN(unsigned N, const APInt &APIVal) { + return APIVal.isSignedIntN(N); +} + +/// \returns true if the argument APInt value is a sequence of ones starting at +/// the least significant bit with the remainder zero. +inline bool isMask(unsigned numBits, const APInt &APIVal) { + return numBits <= APIVal.getBitWidth() && + APIVal == APInt::getLowBitsSet(APIVal.getBitWidth(), numBits); +} + +/// \returns true if the argument is a non-empty sequence of ones starting at +/// the least significant bit with the remainder zero (32 bit version). +/// Ex. isMask(0x0000FFFFU) == true. +inline bool isMask(const APInt &Value) { + return (Value != 0) && ((Value + 1) & Value) == 0; +} + +/// \brief Return true if the argument APInt value contains a sequence of ones +/// with the remainder zero. +inline bool isShiftedMask(unsigned numBits, const APInt &APIVal) { + return isMask(numBits, (APIVal - APInt(numBits, 1)) | APIVal); +} + +/// \brief Returns a byte-swapped representation of the specified APInt Value. +inline APInt byteSwap(const APInt &APIVal) { return APIVal.byteSwap(); } + +/// \brief Returns the floor log base 2 of the specified APInt value. +inline unsigned logBase2(const APInt &APIVal) { return APIVal.logBase2(); } + +/// \brief Compute GCD of two APInt values. +/// +/// This function returns the greatest common divisor of the two APInt values +/// using Euclid's algorithm. +/// +/// \returns the greatest common divisor of Val1 and Val2 +APInt GreatestCommonDivisor(const APInt &Val1, const APInt &Val2); + +/// \brief Converts the given APInt to a double value. +/// +/// Treats the APInt as an unsigned value for conversion purposes. +inline double RoundAPIntToDouble(const APInt &APIVal) { + return APIVal.roundToDouble(); +} + +/// \brief Converts the given APInt to a double value. +/// +/// Treats the APInt as a signed value for conversion purposes. +inline double RoundSignedAPIntToDouble(const APInt &APIVal) { + return APIVal.signedRoundToDouble(); +} + +/// \brief Converts the given APInt to a float vlalue. +inline float RoundAPIntToFloat(const APInt &APIVal) { + return float(RoundAPIntToDouble(APIVal)); +} + +/// \brief Converts the given APInt to a float value. +/// +/// Treast the APInt as a signed value for conversion purposes. +inline float RoundSignedAPIntToFloat(const APInt &APIVal) { + return float(APIVal.signedRoundToDouble()); +} + +/// \brief Converts the given double value into a APInt. +/// +/// This function convert a double value to an APInt value. +APInt RoundDoubleToAPInt(double Double, unsigned width); + +/// \brief Converts a float value into a APInt. +/// +/// Converts a float value into an APInt value. +inline APInt RoundFloatToAPInt(float Float, unsigned width) { + return RoundDoubleToAPInt(double(Float), width); +} + +/// \brief Arithmetic right-shift function. +/// +/// Arithmetic right-shift the APInt by shiftAmt. +inline APInt ashr(const APInt &LHS, unsigned shiftAmt) { + return LHS.ashr(shiftAmt); +} + +/// \brief Logical right-shift function. +/// +/// Logical right-shift the APInt by shiftAmt. +inline APInt lshr(const APInt &LHS, unsigned shiftAmt) { + return LHS.lshr(shiftAmt); +} + +/// \brief Left-shift function. +/// +/// Left-shift the APInt by shiftAmt. +inline APInt shl(const APInt &LHS, unsigned shiftAmt) { + return LHS.shl(shiftAmt); +} + +/// \brief Signed division function for APInt. +/// +/// Signed divide APInt LHS by APInt RHS. +inline APInt sdiv(const APInt &LHS, const APInt &RHS) { return LHS.sdiv(RHS); } + +/// \brief Unsigned division function for APInt. +/// +/// Unsigned divide APInt LHS by APInt RHS. +inline APInt udiv(const APInt &LHS, const APInt &RHS) { return LHS.udiv(RHS); } + +/// \brief Function for signed remainder operation. +/// +/// Signed remainder operation on APInt. +inline APInt srem(const APInt &LHS, const APInt &RHS) { return LHS.srem(RHS); } + +/// \brief Function for unsigned remainder operation. +/// +/// Unsigned remainder operation on APInt. +inline APInt urem(const APInt &LHS, const APInt &RHS) { return LHS.urem(RHS); } + +/// \brief Function for multiplication operation. +/// +/// Performs multiplication on APInt values. +inline APInt mul(const APInt &LHS, const APInt &RHS) { return LHS * RHS; } + +/// \brief Function for addition operation. +/// +/// Performs addition on APInt values. +inline APInt add(const APInt &LHS, const APInt &RHS) { return LHS + RHS; } + +/// \brief Function for subtraction operation. +/// +/// Performs subtraction on APInt values. +inline APInt sub(const APInt &LHS, const APInt &RHS) { return LHS - RHS; } + +/// \brief Bitwise AND function for APInt. +/// +/// Performs bitwise AND operation on APInt LHS and +/// APInt RHS. +inline APInt And(const APInt &LHS, const APInt &RHS) { return LHS & RHS; } + +/// \brief Bitwise OR function for APInt. +/// +/// Performs bitwise OR operation on APInt LHS and APInt RHS. +inline APInt Or(const APInt &LHS, const APInt &RHS) { return LHS | RHS; } + +/// \brief Bitwise XOR function for APInt. +/// +/// Performs bitwise XOR operation on APInt. +inline APInt Xor(const APInt &LHS, const APInt &RHS) { return LHS ^ RHS; } + +/// \brief Bitwise complement function. +/// +/// Performs a bitwise complement operation on APInt. +inline APInt Not(const APInt &APIVal) { return ~APIVal; } + +} // End of APIntOps namespace + +// See friend declaration above. This additional declaration is required in +// order to compile LLVM with IBM xlC compiler. +hash_code hash_value(const APInt &Arg); +} // End of llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/ArrayRef.h b/third_party/llvm-subzero/include/llvm/ADT/ArrayRef.h new file mode 100644 index 0000000..c1d66c6 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/ArrayRef.h
@@ -0,0 +1,447 @@ +//===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ARRAYREF_H +#define LLVM_ADT_ARRAYREF_H + +#include "llvm/ADT/Hashing.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/SmallVector.h" +#include <array> +#include <vector> + +namespace llvm { + /// ArrayRef - Represent a constant reference to an array (0 or more elements + /// consecutively in memory), i.e. a start pointer and a length. It allows + /// various APIs to take consecutive elements easily and conveniently. + /// + /// This class does not own the underlying data, it is expected to be used in + /// situations where the data resides in some other buffer, whose lifetime + /// extends past that of the ArrayRef. For this reason, it is not in general + /// safe to store an ArrayRef. + /// + /// This is intended to be trivially copyable, so it should be passed by + /// value. + template<typename T> + class ArrayRef { + public: + typedef const T *iterator; + typedef const T *const_iterator; + typedef size_t size_type; + + typedef std::reverse_iterator<iterator> reverse_iterator; + + private: + /// The start of the array, in an external buffer. + const T *Data; + + /// The number of elements. + size_type Length; + + public: + /// @name Constructors + /// @{ + + /// Construct an empty ArrayRef. + /*implicit*/ ArrayRef() : Data(nullptr), Length(0) {} + + /// Construct an empty ArrayRef from None. + /*implicit*/ ArrayRef(NoneType) : Data(nullptr), Length(0) {} + + /// Construct an ArrayRef from a single element. + /*implicit*/ ArrayRef(const T &OneElt) + : Data(&OneElt), Length(1) {} + + /// Construct an ArrayRef from a pointer and length. + /*implicit*/ ArrayRef(const T *data, size_t length) + : Data(data), Length(length) {} + + /// Construct an ArrayRef from a range. + ArrayRef(const T *begin, const T *end) + : Data(begin), Length(end - begin) {} + + /// Construct an ArrayRef from a SmallVector. This is templated in order to + /// avoid instantiating SmallVectorTemplateCommon<T> whenever we + /// copy-construct an ArrayRef. + template<typename U> + /*implicit*/ ArrayRef(const SmallVectorTemplateCommon<T, U> &Vec) + : Data(Vec.data()), Length(Vec.size()) { + } + + /// Construct an ArrayRef from a std::vector. + template<typename A> + /*implicit*/ ArrayRef(const std::vector<T, A> &Vec) + : Data(Vec.data()), Length(Vec.size()) {} + + /// Construct an ArrayRef from a std::array + template <size_t N> + /*implicit*/ LLVM_CONSTEXPR ArrayRef(const std::array<T, N> &Arr) + : Data(Arr.data()), Length(N) {} + + /// Construct an ArrayRef from a C array. + template <size_t N> + /*implicit*/ LLVM_CONSTEXPR ArrayRef(const T (&Arr)[N]) + : Data(Arr), Length(N) {} + + /// Construct an ArrayRef from a std::initializer_list. + /*implicit*/ ArrayRef(const std::initializer_list<T> &Vec) + : Data(Vec.begin() == Vec.end() ? (T*)nullptr : Vec.begin()), + Length(Vec.size()) {} + + /// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to + /// ensure that only ArrayRefs of pointers can be converted. + template <typename U> + ArrayRef( + const ArrayRef<U *> &A, + typename std::enable_if< + std::is_convertible<U *const *, T const *>::value>::type * = nullptr) + : Data(A.data()), Length(A.size()) {} + + /// Construct an ArrayRef<const T*> from a SmallVector<T*>. This is + /// templated in order to avoid instantiating SmallVectorTemplateCommon<T> + /// whenever we copy-construct an ArrayRef. + template<typename U, typename DummyT> + /*implicit*/ ArrayRef( + const SmallVectorTemplateCommon<U *, DummyT> &Vec, + typename std::enable_if< + std::is_convertible<U *const *, T const *>::value>::type * = nullptr) + : Data(Vec.data()), Length(Vec.size()) { + } + + /// Construct an ArrayRef<const T*> from std::vector<T*>. This uses SFINAE + /// to ensure that only vectors of pointers can be converted. + template<typename U, typename A> + ArrayRef(const std::vector<U *, A> &Vec, + typename std::enable_if< + std::is_convertible<U *const *, T const *>::value>::type* = 0) + : Data(Vec.data()), Length(Vec.size()) {} + + /// @} + /// @name Simple Operations + /// @{ + + iterator begin() const { return Data; } + iterator end() const { return Data + Length; } + + reverse_iterator rbegin() const { return reverse_iterator(end()); } + reverse_iterator rend() const { return reverse_iterator(begin()); } + + /// empty - Check if the array is empty. + bool empty() const { return Length == 0; } + + const T *data() const { return Data; } + + /// size - Get the array size. + size_t size() const { return Length; } + + /// front - Get the first element. + const T &front() const { + assert(!empty()); + return Data[0]; + } + + /// back - Get the last element. + const T &back() const { + assert(!empty()); + return Data[Length-1]; + } + + // copy - Allocate copy in Allocator and return ArrayRef<T> to it. + template <typename Allocator> ArrayRef<T> copy(Allocator &A) { + T *Buff = A.template Allocate<T>(Length); + std::uninitialized_copy(begin(), end(), Buff); + return ArrayRef<T>(Buff, Length); + } + + /// equals - Check for element-wise equality. + bool equals(ArrayRef RHS) const { + if (Length != RHS.Length) + return false; + return std::equal(begin(), end(), RHS.begin()); + } + + /// slice(n) - Chop off the first N elements of the array. + LLVM_ATTRIBUTE_UNUSED_RESULT + ArrayRef<T> slice(size_t N) const { + assert(N <= size() && "Invalid specifier"); + return ArrayRef<T>(data()+N, size()-N); + } + + /// slice(n, m) - Chop off the first N elements of the array, and keep M + /// elements in the array. + LLVM_ATTRIBUTE_UNUSED_RESULT + ArrayRef<T> slice(size_t N, size_t M) const { + assert(N+M <= size() && "Invalid specifier"); + return ArrayRef<T>(data()+N, M); + } + + /// \brief Drop the first \p N elements of the array. + LLVM_ATTRIBUTE_UNUSED_RESULT + ArrayRef<T> drop_front(size_t N = 1) const { + assert(size() >= N && "Dropping more elements than exist"); + return slice(N, size() - N); + } + + /// \brief Drop the last \p N elements of the array. + LLVM_ATTRIBUTE_UNUSED_RESULT + ArrayRef<T> drop_back(size_t N = 1) const { + assert(size() >= N && "Dropping more elements than exist"); + return slice(0, size() - N); + } + + /// \brief Return a copy of *this with only the first \p N elements. + LLVM_ATTRIBUTE_UNUSED_RESULT + ArrayRef<T> take_front(size_t N = 1) const { + if (N >= size()) + return *this; + return drop_back(size() - N); + } + + /// \brief Return a copy of *this with only the last \p N elements. + LLVM_ATTRIBUTE_UNUSED_RESULT + ArrayRef<T> take_back(size_t N = 1) const { + if (N >= size()) + return *this; + return drop_front(size() - N); + } + + /// @} + /// @name Operator Overloads + /// @{ + const T &operator[](size_t Index) const { + assert(Index < Length && "Invalid index!"); + return Data[Index]; + } + + /// @} + /// @name Expensive Operations + /// @{ + std::vector<T> vec() const { + return std::vector<T>(Data, Data+Length); + } + + /// @} + /// @name Conversion operators + /// @{ + operator std::vector<T>() const { + return std::vector<T>(Data, Data+Length); + } + + /// @} + }; + + /// MutableArrayRef - Represent a mutable reference to an array (0 or more + /// elements consecutively in memory), i.e. a start pointer and a length. It + /// allows various APIs to take and modify consecutive elements easily and + /// conveniently. + /// + /// This class does not own the underlying data, it is expected to be used in + /// situations where the data resides in some other buffer, whose lifetime + /// extends past that of the MutableArrayRef. For this reason, it is not in + /// general safe to store a MutableArrayRef. + /// + /// This is intended to be trivially copyable, so it should be passed by + /// value. + template<typename T> + class MutableArrayRef : public ArrayRef<T> { + public: + typedef T *iterator; + + typedef std::reverse_iterator<iterator> reverse_iterator; + + /// Construct an empty MutableArrayRef. + /*implicit*/ MutableArrayRef() : ArrayRef<T>() {} + + /// Construct an empty MutableArrayRef from None. + /*implicit*/ MutableArrayRef(NoneType) : ArrayRef<T>() {} + + /// Construct an MutableArrayRef from a single element. + /*implicit*/ MutableArrayRef(T &OneElt) : ArrayRef<T>(OneElt) {} + + /// Construct an MutableArrayRef from a pointer and length. + /*implicit*/ MutableArrayRef(T *data, size_t length) + : ArrayRef<T>(data, length) {} + + /// Construct an MutableArrayRef from a range. + MutableArrayRef(T *begin, T *end) : ArrayRef<T>(begin, end) {} + + /// Construct an MutableArrayRef from a SmallVector. + /*implicit*/ MutableArrayRef(SmallVectorImpl<T> &Vec) + : ArrayRef<T>(Vec) {} + + /// Construct a MutableArrayRef from a std::vector. + /*implicit*/ MutableArrayRef(std::vector<T> &Vec) + : ArrayRef<T>(Vec) {} + + /// Construct an ArrayRef from a std::array + template <size_t N> + /*implicit*/ LLVM_CONSTEXPR MutableArrayRef(std::array<T, N> &Arr) + : ArrayRef<T>(Arr) {} + + /// Construct an MutableArrayRef from a C array. + template <size_t N> + /*implicit*/ LLVM_CONSTEXPR MutableArrayRef(T (&Arr)[N]) + : ArrayRef<T>(Arr) {} + + T *data() const { return const_cast<T*>(ArrayRef<T>::data()); } + + iterator begin() const { return data(); } + iterator end() const { return data() + this->size(); } + + reverse_iterator rbegin() const { return reverse_iterator(end()); } + reverse_iterator rend() const { return reverse_iterator(begin()); } + + /// front - Get the first element. + T &front() const { + assert(!this->empty()); + return data()[0]; + } + + /// back - Get the last element. + T &back() const { + assert(!this->empty()); + return data()[this->size()-1]; + } + + /// slice(n) - Chop off the first N elements of the array. + LLVM_ATTRIBUTE_UNUSED_RESULT + MutableArrayRef<T> slice(size_t N) const { + assert(N <= this->size() && "Invalid specifier"); + return MutableArrayRef<T>(data()+N, this->size()-N); + } + + /// slice(n, m) - Chop off the first N elements of the array, and keep M + /// elements in the array. + LLVM_ATTRIBUTE_UNUSED_RESULT + MutableArrayRef<T> slice(size_t N, size_t M) const { + assert(N+M <= this->size() && "Invalid specifier"); + return MutableArrayRef<T>(data()+N, M); + } + + /// \brief Drop the first \p N elements of the array. + LLVM_ATTRIBUTE_UNUSED_RESULT + MutableArrayRef<T> drop_front(size_t N = 1) const { + assert(this->size() >= N && "Dropping more elements than exist"); + return slice(N, this->size() - N); + } + + LLVM_ATTRIBUTE_UNUSED_RESULT + MutableArrayRef<T> drop_back(size_t N = 1) const { + assert(this->size() >= N && "Dropping more elements than exist"); + return slice(0, this->size() - N); + } + + /// \brief Return a copy of *this with only the first \p N elements. + LLVM_ATTRIBUTE_UNUSED_RESULT + MutableArrayRef<T> take_front(size_t N = 1) const { + if (N >= this->size()) + return *this; + return drop_back(this->size() - N); + } + + /// \brief Return a copy of *this with only the last \p N elements. + LLVM_ATTRIBUTE_UNUSED_RESULT + MutableArrayRef<T> take_back(size_t N = 1) const { + if (N >= this->size()) + return *this; + return drop_front(this->size() - N); + } + + /// @} + /// @name Operator Overloads + /// @{ + T &operator[](size_t Index) const { + assert(Index < this->size() && "Invalid index!"); + return data()[Index]; + } + }; + + /// @name ArrayRef Convenience constructors + /// @{ + + /// Construct an ArrayRef from a single element. + template<typename T> + ArrayRef<T> makeArrayRef(const T &OneElt) { + return OneElt; + } + + /// Construct an ArrayRef from a pointer and length. + template<typename T> + ArrayRef<T> makeArrayRef(const T *data, size_t length) { + return ArrayRef<T>(data, length); + } + + /// Construct an ArrayRef from a range. + template<typename T> + ArrayRef<T> makeArrayRef(const T *begin, const T *end) { + return ArrayRef<T>(begin, end); + } + + /// Construct an ArrayRef from a SmallVector. + template <typename T> + ArrayRef<T> makeArrayRef(const SmallVectorImpl<T> &Vec) { + return Vec; + } + + /// Construct an ArrayRef from a SmallVector. + template <typename T, unsigned N> + ArrayRef<T> makeArrayRef(const SmallVector<T, N> &Vec) { + return Vec; + } + + /// Construct an ArrayRef from a std::vector. + template<typename T> + ArrayRef<T> makeArrayRef(const std::vector<T> &Vec) { + return Vec; + } + + /// Construct an ArrayRef from an ArrayRef (no-op) (const) + template <typename T> ArrayRef<T> makeArrayRef(const ArrayRef<T> &Vec) { + return Vec; + } + + /// Construct an ArrayRef from an ArrayRef (no-op) + template <typename T> ArrayRef<T> &makeArrayRef(ArrayRef<T> &Vec) { + return Vec; + } + + /// Construct an ArrayRef from a C array. + template<typename T, size_t N> + ArrayRef<T> makeArrayRef(const T (&Arr)[N]) { + return ArrayRef<T>(Arr); + } + + /// @} + /// @name ArrayRef Comparison Operators + /// @{ + + template<typename T> + inline bool operator==(ArrayRef<T> LHS, ArrayRef<T> RHS) { + return LHS.equals(RHS); + } + + template<typename T> + inline bool operator!=(ArrayRef<T> LHS, ArrayRef<T> RHS) { + return !(LHS == RHS); + } + + /// @} + + // ArrayRefs can be treated like a POD type. + template <typename T> struct isPodLike; + template <typename T> struct isPodLike<ArrayRef<T> > { + static const bool value = true; + }; + + template <typename T> hash_code hash_value(ArrayRef<T> S) { + return hash_combine_range(S.begin(), S.end()); + } +} // end namespace llvm + +#endif // LLVM_ADT_ARRAYREF_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/BitVector.h b/third_party/llvm-subzero/include/llvm/ADT/BitVector.h new file mode 100644 index 0000000..6614371 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/BitVector.h
@@ -0,0 +1,591 @@ +//===- llvm/ADT/BitVector.h - Bit vectors -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the BitVector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_BITVECTOR_H +#define LLVM_ADT_BITVECTOR_H + +#include "llvm/Support/MathExtras.h" +#include <algorithm> +#include <cassert> +#include <climits> +#include <cstdint> +#include <cstdlib> +#include <cstring> + +namespace llvm { + +class BitVector { + typedef unsigned long BitWord; + + enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * CHAR_BIT }; + + static_assert(BITWORD_SIZE == 64 || BITWORD_SIZE == 32, + "Unsupported word size"); + + BitWord *Bits; // Actual bits. + unsigned Size; // Size of bitvector in bits. + unsigned Capacity; // Number of BitWords allocated in the Bits array. + +public: + typedef unsigned size_type; + // Encapsulation of a single bit. + class reference { + friend class BitVector; + + BitWord *WordRef; + unsigned BitPos; + + reference(); // Undefined + + public: + reference(BitVector &b, unsigned Idx) { + WordRef = &b.Bits[Idx / BITWORD_SIZE]; + BitPos = Idx % BITWORD_SIZE; + } + + reference(const reference&) = default; + + reference &operator=(reference t) { + *this = bool(t); + return *this; + } + + reference& operator=(bool t) { + if (t) + *WordRef |= BitWord(1) << BitPos; + else + *WordRef &= ~(BitWord(1) << BitPos); + return *this; + } + + operator bool() const { + return ((*WordRef) & (BitWord(1) << BitPos)) != 0; + } + }; + + + /// BitVector default ctor - Creates an empty bitvector. + BitVector() : Size(0), Capacity(0) { + Bits = nullptr; + } + + /// BitVector ctor - Creates a bitvector of specified number of bits. All + /// bits are initialized to the specified value. + explicit BitVector(unsigned s, bool t = false) : Size(s) { + Capacity = NumBitWords(s); + Bits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); + init_words(Bits, Capacity, t); + if (t) + clear_unused_bits(); + } + + /// BitVector copy ctor. + BitVector(const BitVector &RHS) : Size(RHS.size()) { + if (Size == 0) { + Bits = nullptr; + Capacity = 0; + return; + } + + Capacity = NumBitWords(RHS.size()); + Bits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); + std::memcpy(Bits, RHS.Bits, Capacity * sizeof(BitWord)); + } + + BitVector(BitVector &&RHS) + : Bits(RHS.Bits), Size(RHS.Size), Capacity(RHS.Capacity) { + RHS.Bits = nullptr; + RHS.Size = RHS.Capacity = 0; + } + + ~BitVector() { + std::free(Bits); + } + + /// empty - Tests whether there are no bits in this bitvector. + bool empty() const { return Size == 0; } + + /// size - Returns the number of bits in this bitvector. + size_type size() const { return Size; } + + /// count - Returns the number of bits which are set. + size_type count() const { + unsigned NumBits = 0; + for (unsigned i = 0; i < NumBitWords(size()); ++i) + NumBits += countPopulation(Bits[i]); + return NumBits; + } + + /// any - Returns true if any bit is set. + bool any() const { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + if (Bits[i] != 0) + return true; + return false; + } + + /// all - Returns true if all bits are set. + bool all() const { + for (unsigned i = 0; i < Size / BITWORD_SIZE; ++i) + if (Bits[i] != ~0UL) + return false; + + // If bits remain check that they are ones. The unused bits are always zero. + if (unsigned Remainder = Size % BITWORD_SIZE) + return Bits[Size / BITWORD_SIZE] == (1UL << Remainder) - 1; + + return true; + } + + /// none - Returns true if none of the bits are set. + bool none() const { + return !any(); + } + + /// find_first - Returns the index of the first set bit, -1 if none + /// of the bits are set. + int find_first() const { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + if (Bits[i] != 0) + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); + return -1; + } + + /// find_next - Returns the index of the next set bit following the + /// "Prev" bit. Returns -1 if the next set bit is not found. + int find_next(unsigned Prev) const { + ++Prev; + if (Prev >= Size) + return -1; + + unsigned WordPos = Prev / BITWORD_SIZE; + unsigned BitPos = Prev % BITWORD_SIZE; + BitWord Copy = Bits[WordPos]; + // Mask off previous bits. + Copy &= ~0UL << BitPos; + + if (Copy != 0) + return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); + + // Check subsequent words. + for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i) + if (Bits[i] != 0) + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); + return -1; + } + + /// clear - Clear all bits. + void clear() { + Size = 0; + } + + /// resize - Grow or shrink the bitvector. + void resize(unsigned N, bool t = false) { + if (N > Capacity * BITWORD_SIZE) { + unsigned OldCapacity = Capacity; + grow(N); + init_words(&Bits[OldCapacity], (Capacity-OldCapacity), t); + } + + // Set any old unused bits that are now included in the BitVector. This + // may set bits that are not included in the new vector, but we will clear + // them back out below. + if (N > Size) + set_unused_bits(t); + + // Update the size, and clear out any bits that are now unused + unsigned OldSize = Size; + Size = N; + if (t || N < OldSize) + clear_unused_bits(); + } + + void reserve(unsigned N) { + if (N > Capacity * BITWORD_SIZE) + grow(N); + } + + // Set, reset, flip + BitVector &set() { + init_words(Bits, Capacity, true); + clear_unused_bits(); + return *this; + } + + BitVector &set(unsigned Idx) { + assert(Bits && "Bits never allocated"); + Bits[Idx / BITWORD_SIZE] |= BitWord(1) << (Idx % BITWORD_SIZE); + return *this; + } + + /// set - Efficiently set a range of bits in [I, E) + BitVector &set(unsigned I, unsigned E) { + assert(I <= E && "Attempted to set backwards range!"); + assert(E <= size() && "Attempted to set out-of-bounds range!"); + + if (I == E) return *this; + + if (I / BITWORD_SIZE == E / BITWORD_SIZE) { + BitWord EMask = 1UL << (E % BITWORD_SIZE); + BitWord IMask = 1UL << (I % BITWORD_SIZE); + BitWord Mask = EMask - IMask; + Bits[I / BITWORD_SIZE] |= Mask; + return *this; + } + + BitWord PrefixMask = ~0UL << (I % BITWORD_SIZE); + Bits[I / BITWORD_SIZE] |= PrefixMask; + I = alignTo(I, BITWORD_SIZE); + + for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE) + Bits[I / BITWORD_SIZE] = ~0UL; + + BitWord PostfixMask = (1UL << (E % BITWORD_SIZE)) - 1; + if (I < E) + Bits[I / BITWORD_SIZE] |= PostfixMask; + + return *this; + } + + BitVector &reset() { + init_words(Bits, Capacity, false); + return *this; + } + + BitVector &reset(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] &= ~(BitWord(1) << (Idx % BITWORD_SIZE)); + return *this; + } + + /// reset - Efficiently reset a range of bits in [I, E) + BitVector &reset(unsigned I, unsigned E) { + assert(I <= E && "Attempted to reset backwards range!"); + assert(E <= size() && "Attempted to reset out-of-bounds range!"); + + if (I == E) return *this; + + if (I / BITWORD_SIZE == E / BITWORD_SIZE) { + BitWord EMask = 1UL << (E % BITWORD_SIZE); + BitWord IMask = 1UL << (I % BITWORD_SIZE); + BitWord Mask = EMask - IMask; + Bits[I / BITWORD_SIZE] &= ~Mask; + return *this; + } + + BitWord PrefixMask = ~0UL << (I % BITWORD_SIZE); + Bits[I / BITWORD_SIZE] &= ~PrefixMask; + I = alignTo(I, BITWORD_SIZE); + + for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE) + Bits[I / BITWORD_SIZE] = 0UL; + + BitWord PostfixMask = (1UL << (E % BITWORD_SIZE)) - 1; + if (I < E) + Bits[I / BITWORD_SIZE] &= ~PostfixMask; + + return *this; + } + + BitVector &flip() { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + Bits[i] = ~Bits[i]; + clear_unused_bits(); + return *this; + } + + BitVector &flip(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] ^= BitWord(1) << (Idx % BITWORD_SIZE); + return *this; + } + + // Indexing. + reference operator[](unsigned Idx) { + assert (Idx < Size && "Out-of-bounds Bit access."); + return reference(*this, Idx); + } + + bool operator[](unsigned Idx) const { + assert (Idx < Size && "Out-of-bounds Bit access."); + BitWord Mask = BitWord(1) << (Idx % BITWORD_SIZE); + return (Bits[Idx / BITWORD_SIZE] & Mask) != 0; + } + + bool test(unsigned Idx) const { + return (*this)[Idx]; + } + + /// Test if any common bits are set. + bool anyCommon(const BitVector &RHS) const { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + for (unsigned i = 0, e = std::min(ThisWords, RHSWords); i != e; ++i) + if (Bits[i] & RHS.Bits[i]) + return true; + return false; + } + + // Comparison operators. + bool operator==(const BitVector &RHS) const { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + unsigned i; + for (i = 0; i != std::min(ThisWords, RHSWords); ++i) + if (Bits[i] != RHS.Bits[i]) + return false; + + // Verify that any extra words are all zeros. + if (i != ThisWords) { + for (; i != ThisWords; ++i) + if (Bits[i]) + return false; + } else if (i != RHSWords) { + for (; i != RHSWords; ++i) + if (RHS.Bits[i]) + return false; + } + return true; + } + + bool operator!=(const BitVector &RHS) const { + return !(*this == RHS); + } + + /// Intersection, union, disjoint union. + BitVector &operator&=(const BitVector &RHS) { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + unsigned i; + for (i = 0; i != std::min(ThisWords, RHSWords); ++i) + Bits[i] &= RHS.Bits[i]; + + // Any bits that are just in this bitvector become zero, because they aren't + // in the RHS bit vector. Any words only in RHS are ignored because they + // are already zero in the LHS. + for (; i != ThisWords; ++i) + Bits[i] = 0; + + return *this; + } + + /// reset - Reset bits that are set in RHS. Same as *this &= ~RHS. + BitVector &reset(const BitVector &RHS) { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + unsigned i; + for (i = 0; i != std::min(ThisWords, RHSWords); ++i) + Bits[i] &= ~RHS.Bits[i]; + return *this; + } + + /// test - Check if (This - RHS) is zero. + /// This is the same as reset(RHS) and any(). + bool test(const BitVector &RHS) const { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + unsigned i; + for (i = 0; i != std::min(ThisWords, RHSWords); ++i) + if ((Bits[i] & ~RHS.Bits[i]) != 0) + return true; + + for (; i != ThisWords ; ++i) + if (Bits[i] != 0) + return true; + + return false; + } + + BitVector &operator|=(const BitVector &RHS) { + if (size() < RHS.size()) + resize(RHS.size()); + for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i) + Bits[i] |= RHS.Bits[i]; + return *this; + } + + BitVector &operator^=(const BitVector &RHS) { + if (size() < RHS.size()) + resize(RHS.size()); + for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i) + Bits[i] ^= RHS.Bits[i]; + return *this; + } + + // Assignment operator. + const BitVector &operator=(const BitVector &RHS) { + if (this == &RHS) return *this; + + Size = RHS.size(); + unsigned RHSWords = NumBitWords(Size); + if (Size <= Capacity * BITWORD_SIZE) { + if (Size) + std::memcpy(Bits, RHS.Bits, RHSWords * sizeof(BitWord)); + clear_unused_bits(); + return *this; + } + + // Grow the bitvector to have enough elements. + Capacity = RHSWords; + assert(Capacity > 0 && "negative capacity?"); + BitWord *NewBits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); + std::memcpy(NewBits, RHS.Bits, Capacity * sizeof(BitWord)); + + // Destroy the old bits. + std::free(Bits); + Bits = NewBits; + + return *this; + } + + const BitVector &operator=(BitVector &&RHS) { + if (this == &RHS) return *this; + + std::free(Bits); + Bits = RHS.Bits; + Size = RHS.Size; + Capacity = RHS.Capacity; + + RHS.Bits = nullptr; + RHS.Size = RHS.Capacity = 0; + + return *this; + } + + void swap(BitVector &RHS) { + std::swap(Bits, RHS.Bits); + std::swap(Size, RHS.Size); + std::swap(Capacity, RHS.Capacity); + } + + //===--------------------------------------------------------------------===// + // Portable bit mask operations. + //===--------------------------------------------------------------------===// + // + // These methods all operate on arrays of uint32_t, each holding 32 bits. The + // fixed word size makes it easier to work with literal bit vector constants + // in portable code. + // + // The LSB in each word is the lowest numbered bit. The size of a portable + // bit mask is always a whole multiple of 32 bits. If no bit mask size is + // given, the bit mask is assumed to cover the entire BitVector. + + /// setBitsInMask - Add '1' bits from Mask to this vector. Don't resize. + /// This computes "*this |= Mask". + void setBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { + applyMask<true, false>(Mask, MaskWords); + } + + /// clearBitsInMask - Clear any bits in this vector that are set in Mask. + /// Don't resize. This computes "*this &= ~Mask". + void clearBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { + applyMask<false, false>(Mask, MaskWords); + } + + /// setBitsNotInMask - Add a bit to this vector for every '0' bit in Mask. + /// Don't resize. This computes "*this |= ~Mask". + void setBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { + applyMask<true, true>(Mask, MaskWords); + } + + /// clearBitsNotInMask - Clear a bit in this vector for every '0' bit in Mask. + /// Don't resize. This computes "*this &= Mask". + void clearBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { + applyMask<false, true>(Mask, MaskWords); + } + +private: + unsigned NumBitWords(unsigned S) const { + return (S + BITWORD_SIZE-1) / BITWORD_SIZE; + } + + // Set the unused bits in the high words. + void set_unused_bits(bool t = true) { + // Set high words first. + unsigned UsedWords = NumBitWords(Size); + if (Capacity > UsedWords) + init_words(&Bits[UsedWords], (Capacity-UsedWords), t); + + // Then set any stray high bits of the last used word. + unsigned ExtraBits = Size % BITWORD_SIZE; + if (ExtraBits) { + BitWord ExtraBitMask = ~0UL << ExtraBits; + if (t) + Bits[UsedWords-1] |= ExtraBitMask; + else + Bits[UsedWords-1] &= ~ExtraBitMask; + } + } + + // Clear the unused bits in the high words. + void clear_unused_bits() { + set_unused_bits(false); + } + + void grow(unsigned NewSize) { + Capacity = std::max(NumBitWords(NewSize), Capacity * 2); + assert(Capacity > 0 && "realloc-ing zero space"); + Bits = (BitWord *)std::realloc(Bits, Capacity * sizeof(BitWord)); + + clear_unused_bits(); + } + + void init_words(BitWord *B, unsigned NumWords, bool t) { + memset(B, 0 - (int)t, NumWords*sizeof(BitWord)); + } + + template<bool AddBits, bool InvertMask> + void applyMask(const uint32_t *Mask, unsigned MaskWords) { + static_assert(BITWORD_SIZE % 32 == 0, "Unsupported BitWord size."); + MaskWords = std::min(MaskWords, (size() + 31) / 32); + const unsigned Scale = BITWORD_SIZE / 32; + unsigned i; + for (i = 0; MaskWords >= Scale; ++i, MaskWords -= Scale) { + BitWord BW = Bits[i]; + // This inner loop should unroll completely when BITWORD_SIZE > 32. + for (unsigned b = 0; b != BITWORD_SIZE; b += 32) { + uint32_t M = *Mask++; + if (InvertMask) M = ~M; + if (AddBits) BW |= BitWord(M) << b; + else BW &= ~(BitWord(M) << b); + } + Bits[i] = BW; + } + for (unsigned b = 0; MaskWords; b += 32, --MaskWords) { + uint32_t M = *Mask++; + if (InvertMask) M = ~M; + if (AddBits) Bits[i] |= BitWord(M) << b; + else Bits[i] &= ~(BitWord(M) << b); + } + if (AddBits) + clear_unused_bits(); + } + +public: + /// Return the size (in bytes) of the bit vector. + size_t getMemorySize() const { return Capacity * sizeof(BitWord); } +}; + +static inline size_t capacity_in_bytes(const BitVector &X) { + return X.getMemorySize(); +} + +} // end namespace llvm + +namespace std { + /// Implement std::swap in terms of BitVector swap. + inline void + swap(llvm::BitVector &LHS, llvm::BitVector &RHS) { + LHS.swap(RHS); + } +} // end namespace std + +#endif // LLVM_ADT_BITVECTOR_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/DenseMap.h b/third_party/llvm-subzero/include/llvm/ADT/DenseMap.h new file mode 100644 index 0000000..f3910b1 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/DenseMap.h
@@ -0,0 +1,1121 @@ +//===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the DenseMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DENSEMAP_H +#define LLVM_ADT_DENSEMAP_H + +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/EpochTracker.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/type_traits.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstring> +#include <iterator> +#include <limits> +#include <new> +#include <utility> + +namespace llvm { + +namespace detail { + +// We extend a pair to allow users to override the bucket type with their own +// implementation without requiring two members. +template <typename KeyT, typename ValueT> +struct DenseMapPair : public std::pair<KeyT, ValueT> { + KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; } + const KeyT &getFirst() const { return std::pair<KeyT, ValueT>::first; } + ValueT &getSecond() { return std::pair<KeyT, ValueT>::second; } + const ValueT &getSecond() const { return std::pair<KeyT, ValueT>::second; } +}; + +} // end namespace detail + +template < + typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo<KeyT>, + typename Bucket = detail::DenseMapPair<KeyT, ValueT>, bool IsConst = false> +class DenseMapIterator; + +template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT, + typename BucketT> +class DenseMapBase : public DebugEpochBase { +public: + typedef unsigned size_type; + typedef KeyT key_type; + typedef ValueT mapped_type; + typedef BucketT value_type; + + typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT> iterator; + typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT, true> + const_iterator; + inline iterator begin() { + // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets(). + return empty() ? end() : iterator(getBuckets(), getBucketsEnd(), *this); + } + inline iterator end() { + return iterator(getBucketsEnd(), getBucketsEnd(), *this, true); + } + inline const_iterator begin() const { + return empty() ? end() + : const_iterator(getBuckets(), getBucketsEnd(), *this); + } + inline const_iterator end() const { + return const_iterator(getBucketsEnd(), getBucketsEnd(), *this, true); + } + + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { + return getNumEntries() == 0; + } + unsigned size() const { return getNumEntries(); } + + /// Grow the densemap so that it can contain at least \p NumEntries items + /// before resizing again. + void reserve(size_type NumEntries) { + auto NumBuckets = getMinBucketToReserveForEntries(NumEntries); + incrementEpoch(); + if (NumBuckets > getNumBuckets()) + grow(NumBuckets); + } + + void clear() { + incrementEpoch(); + if (getNumEntries() == 0 && getNumTombstones() == 0) return; + + // If the capacity of the array is huge, and the # elements used is small, + // shrink the array. + if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) { + shrink_and_clear(); + return; + } + + const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + unsigned NumEntries = getNumEntries(); + for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) { + if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { + P->getSecond().~ValueT(); + --NumEntries; + } + P->getFirst() = EmptyKey; + } + } + assert(NumEntries == 0 && "Node count imbalance!"); + setNumEntries(0); + setNumTombstones(0); + } + + /// Return 1 if the specified key is in the map, 0 otherwise. + size_type count(const KeyT &Val) const { + const BucketT *TheBucket; + return LookupBucketFor(Val, TheBucket) ? 1 : 0; + } + + iterator find(const KeyT &Val) { + BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return iterator(TheBucket, getBucketsEnd(), *this, true); + return end(); + } + const_iterator find(const KeyT &Val) const { + const BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return const_iterator(TheBucket, getBucketsEnd(), *this, true); + return end(); + } + + /// Alternate version of find() which allows a different, and possibly + /// less expensive, key type. + /// The DenseMapInfo is responsible for supplying methods + /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key + /// type used. + template<class LookupKeyT> + iterator find_as(const LookupKeyT &Val) { + BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return iterator(TheBucket, getBucketsEnd(), *this, true); + return end(); + } + template<class LookupKeyT> + const_iterator find_as(const LookupKeyT &Val) const { + const BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return const_iterator(TheBucket, getBucketsEnd(), *this, true); + return end(); + } + + /// lookup - Return the entry for the specified key, or a default + /// constructed value if no such entry exists. + ValueT lookup(const KeyT &Val) const { + const BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return TheBucket->getSecond(); + return ValueT(); + } + + // Inserts key,value pair into the map if the key isn't already in the map. + // If the key is already in the map, it returns false and doesn't update the + // value. + std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) { + return try_emplace(KV.first, KV.second); + } + + // Inserts key,value pair into the map if the key isn't already in the map. + // If the key is already in the map, it returns false and doesn't update the + // value. + std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) { + return try_emplace(std::move(KV.first), std::move(KV.second)); + } + + // Inserts key,value pair into the map if the key isn't already in the map. + // The value is constructed in-place if the key is not in the map, otherwise + // it is not moved. + template <typename... Ts> + std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&... Args) { + BucketT *TheBucket; + if (LookupBucketFor(Key, TheBucket)) + return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), + false); // Already in map. + + // Otherwise, insert the new element. + TheBucket = + InsertIntoBucket(TheBucket, std::move(Key), std::forward<Ts>(Args)...); + return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), + true); + } + + // Inserts key,value pair into the map if the key isn't already in the map. + // The value is constructed in-place if the key is not in the map, otherwise + // it is not moved. + template <typename... Ts> + std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&... Args) { + BucketT *TheBucket; + if (LookupBucketFor(Key, TheBucket)) + return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), + false); // Already in map. + + // Otherwise, insert the new element. + TheBucket = InsertIntoBucket(TheBucket, Key, std::forward<Ts>(Args)...); + return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), + true); + } + + /// Alternate version of insert() which allows a different, and possibly + /// less expensive, key type. + /// The DenseMapInfo is responsible for supplying methods + /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key + /// type used. + template <typename LookupKeyT> + std::pair<iterator, bool> insert_as(std::pair<KeyT, ValueT> &&KV, + const LookupKeyT &Val) { + BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), + false); // Already in map. + + // Otherwise, insert the new element. + TheBucket = InsertIntoBucketWithLookup(TheBucket, std::move(KV.first), + std::move(KV.second), Val); + return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), + true); + } + + /// insert - Range insertion of pairs. + template<typename InputIt> + void insert(InputIt I, InputIt E) { + for (; I != E; ++I) + insert(*I); + } + + bool erase(const KeyT &Val) { + BucketT *TheBucket; + if (!LookupBucketFor(Val, TheBucket)) + return false; // not in map. + + TheBucket->getSecond().~ValueT(); + TheBucket->getFirst() = getTombstoneKey(); + decrementNumEntries(); + incrementNumTombstones(); + return true; + } + void erase(iterator I) { + BucketT *TheBucket = &*I; + TheBucket->getSecond().~ValueT(); + TheBucket->getFirst() = getTombstoneKey(); + decrementNumEntries(); + incrementNumTombstones(); + } + + value_type& FindAndConstruct(const KeyT &Key) { + BucketT *TheBucket; + if (LookupBucketFor(Key, TheBucket)) + return *TheBucket; + + return *InsertIntoBucket(TheBucket, Key); + } + + ValueT &operator[](const KeyT &Key) { + return FindAndConstruct(Key).second; + } + + value_type& FindAndConstruct(KeyT &&Key) { + BucketT *TheBucket; + if (LookupBucketFor(Key, TheBucket)) + return *TheBucket; + + return *InsertIntoBucket(TheBucket, std::move(Key)); + } + + ValueT &operator[](KeyT &&Key) { + return FindAndConstruct(std::move(Key)).second; + } + + /// isPointerIntoBucketsArray - Return true if the specified pointer points + /// somewhere into the DenseMap's array of buckets (i.e. either to a key or + /// value in the DenseMap). + bool isPointerIntoBucketsArray(const void *Ptr) const { + return Ptr >= getBuckets() && Ptr < getBucketsEnd(); + } + + /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets + /// array. In conjunction with the previous method, this can be used to + /// determine whether an insertion caused the DenseMap to reallocate. + const void *getPointerIntoBucketsArray() const { return getBuckets(); } + +protected: + DenseMapBase() = default; + + void destroyAll() { + if (getNumBuckets() == 0) // Nothing to do. + return; + + const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) + P->getSecond().~ValueT(); + P->getFirst().~KeyT(); + } + } + + void initEmpty() { + setNumEntries(0); + setNumTombstones(0); + + assert((getNumBuckets() & (getNumBuckets()-1)) == 0 && + "# initial buckets must be a power of two!"); + const KeyT EmptyKey = getEmptyKey(); + for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B) + ::new (&B->getFirst()) KeyT(EmptyKey); + } + + /// Returns the number of buckets to allocate to ensure that the DenseMap can + /// accommodate \p NumEntries without need to grow(). + unsigned getMinBucketToReserveForEntries(unsigned NumEntries) { + // Ensure that "NumEntries * 4 < NumBuckets * 3" + if (NumEntries == 0) + return 0; + // +1 is required because of the strict equality. + // For example if NumEntries is 48, we need to return 401. + return NextPowerOf2(NumEntries * 4 / 3 + 1); + } + + void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) { + initEmpty(); + + // Insert all the old elements. + const KeyT EmptyKey = getEmptyKey(); + const KeyT TombstoneKey = getTombstoneKey(); + for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) { + if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) { + // Insert the key/value into the new table. + BucketT *DestBucket; + bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket); + (void)FoundVal; // silence warning. + assert(!FoundVal && "Key already in new map?"); + DestBucket->getFirst() = std::move(B->getFirst()); + ::new (&DestBucket->getSecond()) ValueT(std::move(B->getSecond())); + incrementNumEntries(); + + // Free the value. + B->getSecond().~ValueT(); + } + B->getFirst().~KeyT(); + } + } + + template <typename OtherBaseT> + void copyFrom( + const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT, BucketT> &other) { + assert(&other != this); + assert(getNumBuckets() == other.getNumBuckets()); + + setNumEntries(other.getNumEntries()); + setNumTombstones(other.getNumTombstones()); + + if (isPodLike<KeyT>::value && isPodLike<ValueT>::value) + memcpy(getBuckets(), other.getBuckets(), + getNumBuckets() * sizeof(BucketT)); + else + for (size_t i = 0; i < getNumBuckets(); ++i) { + ::new (&getBuckets()[i].getFirst()) + KeyT(other.getBuckets()[i].getFirst()); + if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) && + !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey())) + ::new (&getBuckets()[i].getSecond()) + ValueT(other.getBuckets()[i].getSecond()); + } + } + + static unsigned getHashValue(const KeyT &Val) { + return KeyInfoT::getHashValue(Val); + } + template<typename LookupKeyT> + static unsigned getHashValue(const LookupKeyT &Val) { + return KeyInfoT::getHashValue(Val); + } + static const KeyT getEmptyKey() { + return KeyInfoT::getEmptyKey(); + } + static const KeyT getTombstoneKey() { + return KeyInfoT::getTombstoneKey(); + } + +private: + unsigned getNumEntries() const { + return static_cast<const DerivedT *>(this)->getNumEntries(); + } + void setNumEntries(unsigned Num) { + static_cast<DerivedT *>(this)->setNumEntries(Num); + } + void incrementNumEntries() { + setNumEntries(getNumEntries() + 1); + } + void decrementNumEntries() { + setNumEntries(getNumEntries() - 1); + } + unsigned getNumTombstones() const { + return static_cast<const DerivedT *>(this)->getNumTombstones(); + } + void setNumTombstones(unsigned Num) { + static_cast<DerivedT *>(this)->setNumTombstones(Num); + } + void incrementNumTombstones() { + setNumTombstones(getNumTombstones() + 1); + } + void decrementNumTombstones() { + setNumTombstones(getNumTombstones() - 1); + } + const BucketT *getBuckets() const { + return static_cast<const DerivedT *>(this)->getBuckets(); + } + BucketT *getBuckets() { + return static_cast<DerivedT *>(this)->getBuckets(); + } + unsigned getNumBuckets() const { + return static_cast<const DerivedT *>(this)->getNumBuckets(); + } + BucketT *getBucketsEnd() { + return getBuckets() + getNumBuckets(); + } + const BucketT *getBucketsEnd() const { + return getBuckets() + getNumBuckets(); + } + + void grow(unsigned AtLeast) { + static_cast<DerivedT *>(this)->grow(AtLeast); + } + + void shrink_and_clear() { + static_cast<DerivedT *>(this)->shrink_and_clear(); + } + + template <typename KeyArg, typename... ValueArgs> + BucketT *InsertIntoBucket(BucketT *TheBucket, KeyArg &&Key, + ValueArgs &&... Values) { + TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket); + + TheBucket->getFirst() = std::forward<KeyArg>(Key); + ::new (&TheBucket->getSecond()) ValueT(std::forward<ValueArgs>(Values)...); + return TheBucket; + } + + template <typename LookupKeyT> + BucketT *InsertIntoBucketWithLookup(BucketT *TheBucket, KeyT &&Key, + ValueT &&Value, LookupKeyT &Lookup) { + TheBucket = InsertIntoBucketImpl(Key, Lookup, TheBucket); + + TheBucket->getFirst() = std::move(Key); + ::new (&TheBucket->getSecond()) ValueT(std::move(Value)); + return TheBucket; + } + + template <typename LookupKeyT> + BucketT *InsertIntoBucketImpl(const KeyT &Key, const LookupKeyT &Lookup, + BucketT *TheBucket) { + incrementEpoch(); + + // If the load of the hash table is more than 3/4, or if fewer than 1/8 of + // the buckets are empty (meaning that many are filled with tombstones), + // grow the table. + // + // The later case is tricky. For example, if we had one empty bucket with + // tons of tombstones, failing lookups (e.g. for insertion) would have to + // probe almost the entire table until it found the empty bucket. If the + // table completely filled with tombstones, no lookup would ever succeed, + // causing infinite loops in lookup. + unsigned NewNumEntries = getNumEntries() + 1; + unsigned NumBuckets = getNumBuckets(); + if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) { + this->grow(NumBuckets * 2); + LookupBucketFor(Lookup, TheBucket); + NumBuckets = getNumBuckets(); + } else if (LLVM_UNLIKELY(NumBuckets-(NewNumEntries+getNumTombstones()) <= + NumBuckets/8)) { + this->grow(NumBuckets); + LookupBucketFor(Lookup, TheBucket); + } + assert(TheBucket); + + // Only update the state after we've grown our bucket space appropriately + // so that when growing buckets we have self-consistent entry count. + incrementNumEntries(); + + // If we are writing over a tombstone, remember this. + const KeyT EmptyKey = getEmptyKey(); + if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey)) + decrementNumTombstones(); + + return TheBucket; + } + + /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in + /// FoundBucket. If the bucket contains the key and a value, this returns + /// true, otherwise it returns a bucket with an empty marker or tombstone and + /// returns false. + template<typename LookupKeyT> + bool LookupBucketFor(const LookupKeyT &Val, + const BucketT *&FoundBucket) const { + const BucketT *BucketsPtr = getBuckets(); + const unsigned NumBuckets = getNumBuckets(); + + if (NumBuckets == 0) { + FoundBucket = nullptr; + return false; + } + + // FoundTombstone - Keep track of whether we find a tombstone while probing. + const BucketT *FoundTombstone = nullptr; + const KeyT EmptyKey = getEmptyKey(); + const KeyT TombstoneKey = getTombstoneKey(); + assert(!KeyInfoT::isEqual(Val, EmptyKey) && + !KeyInfoT::isEqual(Val, TombstoneKey) && + "Empty/Tombstone value shouldn't be inserted into map!"); + + unsigned BucketNo = getHashValue(Val) & (NumBuckets-1); + unsigned ProbeAmt = 1; + while (true) { + const BucketT *ThisBucket = BucketsPtr + BucketNo; + // Found Val's bucket? If so, return it. + if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) { + FoundBucket = ThisBucket; + return true; + } + + // If we found an empty bucket, the key doesn't exist in the set. + // Insert it and return the default value. + if (LLVM_LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) { + // If we've already seen a tombstone while probing, fill it in instead + // of the empty bucket we eventually probed to. + FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; + return false; + } + + // If this is a tombstone, remember it. If Val ends up not in the map, we + // prefer to return it than something that would require more probing. + if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) && + !FoundTombstone) + FoundTombstone = ThisBucket; // Remember the first tombstone found. + + // Otherwise, it's a hash collision or a tombstone, continue quadratic + // probing. + BucketNo += ProbeAmt++; + BucketNo &= (NumBuckets-1); + } + } + + template <typename LookupKeyT> + bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) { + const BucketT *ConstFoundBucket; + bool Result = const_cast<const DenseMapBase *>(this) + ->LookupBucketFor(Val, ConstFoundBucket); + FoundBucket = const_cast<BucketT *>(ConstFoundBucket); + return Result; + } + +public: + /// Return the approximate size (in bytes) of the actual map. + /// This is just the raw memory used by DenseMap. + /// If entries are pointers to objects, the size of the referenced objects + /// are not included. + size_t getMemorySize() const { + return getNumBuckets() * sizeof(BucketT); + } +}; + +template <typename KeyT, typename ValueT, + typename KeyInfoT = DenseMapInfo<KeyT>, + typename BucketT = detail::DenseMapPair<KeyT, ValueT>> +class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>, + KeyT, ValueT, KeyInfoT, BucketT> { + // Lift some types from the dependent base class into this class for + // simplicity of referring to them. + typedef DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT> BaseT; + friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>; + + BucketT *Buckets; + unsigned NumEntries; + unsigned NumTombstones; + unsigned NumBuckets; + +public: + /// Create a DenseMap wth an optional \p InitialReserve that guarantee that + /// this number of elements can be inserted in the map without grow() + explicit DenseMap(unsigned InitialReserve = 0) { init(InitialReserve); } + + DenseMap(const DenseMap &other) : BaseT() { + init(0); + copyFrom(other); + } + + DenseMap(DenseMap &&other) : BaseT() { + init(0); + swap(other); + } + + template<typename InputIt> + DenseMap(const InputIt &I, const InputIt &E) { + init(std::distance(I, E)); + this->insert(I, E); + } + + ~DenseMap() { + this->destroyAll(); + operator delete(Buckets); + } + + void swap(DenseMap& RHS) { + this->incrementEpoch(); + RHS.incrementEpoch(); + std::swap(Buckets, RHS.Buckets); + std::swap(NumEntries, RHS.NumEntries); + std::swap(NumTombstones, RHS.NumTombstones); + std::swap(NumBuckets, RHS.NumBuckets); + } + + DenseMap& operator=(const DenseMap& other) { + if (&other != this) + copyFrom(other); + return *this; + } + + DenseMap& operator=(DenseMap &&other) { + this->destroyAll(); + operator delete(Buckets); + init(0); + swap(other); + return *this; + } + + void copyFrom(const DenseMap& other) { + this->destroyAll(); + operator delete(Buckets); + if (allocateBuckets(other.NumBuckets)) { + this->BaseT::copyFrom(other); + } else { + NumEntries = 0; + NumTombstones = 0; + } + } + + void init(unsigned InitNumEntries) { + auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries); + if (allocateBuckets(InitBuckets)) { + this->BaseT::initEmpty(); + } else { + NumEntries = 0; + NumTombstones = 0; + } + } + + void grow(unsigned AtLeast) { + unsigned OldNumBuckets = NumBuckets; + BucketT *OldBuckets = Buckets; + + allocateBuckets(std::max<unsigned>(64, static_cast<unsigned>(NextPowerOf2(AtLeast-1)))); + assert(Buckets); + if (!OldBuckets) { + this->BaseT::initEmpty(); + return; + } + + this->moveFromOldBuckets(OldBuckets, OldBuckets+OldNumBuckets); + + // Free the old table. + operator delete(OldBuckets); + } + + void shrink_and_clear() { + unsigned OldNumEntries = NumEntries; + this->destroyAll(); + + // Reduce the number of buckets. + unsigned NewNumBuckets = 0; + if (OldNumEntries) + NewNumBuckets = std::max(64, 1 << (Log2_32_Ceil(OldNumEntries) + 1)); + if (NewNumBuckets == NumBuckets) { + this->BaseT::initEmpty(); + return; + } + + operator delete(Buckets); + init(NewNumBuckets); + } + +private: + unsigned getNumEntries() const { + return NumEntries; + } + void setNumEntries(unsigned Num) { + NumEntries = Num; + } + + unsigned getNumTombstones() const { + return NumTombstones; + } + void setNumTombstones(unsigned Num) { + NumTombstones = Num; + } + + BucketT *getBuckets() const { + return Buckets; + } + + unsigned getNumBuckets() const { + return NumBuckets; + } + + bool allocateBuckets(unsigned Num) { + NumBuckets = Num; + if (NumBuckets == 0) { + Buckets = nullptr; + return false; + } + + Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT) * NumBuckets)); + return true; + } +}; + +template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4, + typename KeyInfoT = DenseMapInfo<KeyT>, + typename BucketT = detail::DenseMapPair<KeyT, ValueT>> +class SmallDenseMap + : public DenseMapBase< + SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT, + ValueT, KeyInfoT, BucketT> { + // Lift some types from the dependent base class into this class for + // simplicity of referring to them. + typedef DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT> BaseT; + friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>; + + unsigned Small : 1; + unsigned NumEntries : 31; + unsigned NumTombstones; + + struct LargeRep { + BucketT *Buckets; + unsigned NumBuckets; + }; + + /// A "union" of an inline bucket array and the struct representing + /// a large bucket. This union will be discriminated by the 'Small' bit. + AlignedCharArrayUnion<BucketT[InlineBuckets], LargeRep> storage; + +public: + explicit SmallDenseMap(unsigned NumInitBuckets = 0) { + init(NumInitBuckets); + } + + SmallDenseMap(const SmallDenseMap &other) : BaseT() { + init(0); + copyFrom(other); + } + + SmallDenseMap(SmallDenseMap &&other) : BaseT() { + init(0); + swap(other); + } + + template<typename InputIt> + SmallDenseMap(const InputIt &I, const InputIt &E) { + init(NextPowerOf2(std::distance(I, E))); + this->insert(I, E); + } + + ~SmallDenseMap() { + this->destroyAll(); + deallocateBuckets(); + } + + void swap(SmallDenseMap& RHS) { + unsigned TmpNumEntries = RHS.NumEntries; + RHS.NumEntries = NumEntries; + NumEntries = TmpNumEntries; + std::swap(NumTombstones, RHS.NumTombstones); + + const KeyT EmptyKey = this->getEmptyKey(); + const KeyT TombstoneKey = this->getTombstoneKey(); + if (Small && RHS.Small) { + // If we're swapping inline bucket arrays, we have to cope with some of + // the tricky bits of DenseMap's storage system: the buckets are not + // fully initialized. Thus we swap every key, but we may have + // a one-directional move of the value. + for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { + BucketT *LHSB = &getInlineBuckets()[i], + *RHSB = &RHS.getInlineBuckets()[i]; + bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(LHSB->getFirst(), TombstoneKey)); + bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(RHSB->getFirst(), TombstoneKey)); + if (hasLHSValue && hasRHSValue) { + // Swap together if we can... + std::swap(*LHSB, *RHSB); + continue; + } + // Swap separately and handle any assymetry. + std::swap(LHSB->getFirst(), RHSB->getFirst()); + if (hasLHSValue) { + ::new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond())); + LHSB->getSecond().~ValueT(); + } else if (hasRHSValue) { + ::new (&LHSB->getSecond()) ValueT(std::move(RHSB->getSecond())); + RHSB->getSecond().~ValueT(); + } + } + return; + } + if (!Small && !RHS.Small) { + std::swap(getLargeRep()->Buckets, RHS.getLargeRep()->Buckets); + std::swap(getLargeRep()->NumBuckets, RHS.getLargeRep()->NumBuckets); + return; + } + + SmallDenseMap &SmallSide = Small ? *this : RHS; + SmallDenseMap &LargeSide = Small ? RHS : *this; + + // First stash the large side's rep and move the small side across. + LargeRep TmpRep = std::move(*LargeSide.getLargeRep()); + LargeSide.getLargeRep()->~LargeRep(); + LargeSide.Small = true; + // This is similar to the standard move-from-old-buckets, but the bucket + // count hasn't actually rotated in this case. So we have to carefully + // move construct the keys and values into their new locations, but there + // is no need to re-hash things. + for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { + BucketT *NewB = &LargeSide.getInlineBuckets()[i], + *OldB = &SmallSide.getInlineBuckets()[i]; + ::new (&NewB->getFirst()) KeyT(std::move(OldB->getFirst())); + OldB->getFirst().~KeyT(); + if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(NewB->getFirst(), TombstoneKey)) { + ::new (&NewB->getSecond()) ValueT(std::move(OldB->getSecond())); + OldB->getSecond().~ValueT(); + } + } + + // The hard part of moving the small buckets across is done, just move + // the TmpRep into its new home. + SmallSide.Small = false; + new (SmallSide.getLargeRep()) LargeRep(std::move(TmpRep)); + } + + SmallDenseMap& operator=(const SmallDenseMap& other) { + if (&other != this) + copyFrom(other); + return *this; + } + + SmallDenseMap& operator=(SmallDenseMap &&other) { + this->destroyAll(); + deallocateBuckets(); + init(0); + swap(other); + return *this; + } + + void copyFrom(const SmallDenseMap& other) { + this->destroyAll(); + deallocateBuckets(); + Small = true; + if (other.getNumBuckets() > InlineBuckets) { + Small = false; + new (getLargeRep()) LargeRep(allocateBuckets(other.getNumBuckets())); + } + this->BaseT::copyFrom(other); + } + + void init(unsigned InitBuckets) { + Small = true; + if (InitBuckets > InlineBuckets) { + Small = false; + new (getLargeRep()) LargeRep(allocateBuckets(InitBuckets)); + } + this->BaseT::initEmpty(); + } + + void grow(unsigned AtLeast) { + if (AtLeast >= InlineBuckets) + AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast-1)); + + if (Small) { + if (AtLeast < InlineBuckets) + return; // Nothing to do. + + // First move the inline buckets into a temporary storage. + AlignedCharArrayUnion<BucketT[InlineBuckets]> TmpStorage; + BucketT *TmpBegin = reinterpret_cast<BucketT *>(TmpStorage.buffer); + BucketT *TmpEnd = TmpBegin; + + // Loop over the buckets, moving non-empty, non-tombstones into the + // temporary storage. Have the loop move the TmpEnd forward as it goes. + const KeyT EmptyKey = this->getEmptyKey(); + const KeyT TombstoneKey = this->getTombstoneKey(); + for (BucketT *P = getBuckets(), *E = P + InlineBuckets; P != E; ++P) { + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { + assert(size_t(TmpEnd - TmpBegin) < InlineBuckets && + "Too many inline buckets!"); + ::new (&TmpEnd->getFirst()) KeyT(std::move(P->getFirst())); + ::new (&TmpEnd->getSecond()) ValueT(std::move(P->getSecond())); + ++TmpEnd; + P->getSecond().~ValueT(); + } + P->getFirst().~KeyT(); + } + + // Now make this map use the large rep, and move all the entries back + // into it. + Small = false; + new (getLargeRep()) LargeRep(allocateBuckets(AtLeast)); + this->moveFromOldBuckets(TmpBegin, TmpEnd); + return; + } + + LargeRep OldRep = std::move(*getLargeRep()); + getLargeRep()->~LargeRep(); + if (AtLeast <= InlineBuckets) { + Small = true; + } else { + new (getLargeRep()) LargeRep(allocateBuckets(AtLeast)); + } + + this->moveFromOldBuckets(OldRep.Buckets, OldRep.Buckets+OldRep.NumBuckets); + + // Free the old table. + operator delete(OldRep.Buckets); + } + + void shrink_and_clear() { + unsigned OldSize = this->size(); + this->destroyAll(); + + // Reduce the number of buckets. + unsigned NewNumBuckets = 0; + if (OldSize) { + NewNumBuckets = 1 << (Log2_32_Ceil(OldSize) + 1); + if (NewNumBuckets > InlineBuckets && NewNumBuckets < 64u) + NewNumBuckets = 64; + } + if ((Small && NewNumBuckets <= InlineBuckets) || + (!Small && NewNumBuckets == getLargeRep()->NumBuckets)) { + this->BaseT::initEmpty(); + return; + } + + deallocateBuckets(); + init(NewNumBuckets); + } + +private: + unsigned getNumEntries() const { + return NumEntries; + } + void setNumEntries(unsigned Num) { + // NumEntries is hardcoded to be 31 bits wide. + assert(Num < (1U << 31) && "Cannot support more than 1<<31 entries"); + NumEntries = Num; + } + + unsigned getNumTombstones() const { + return NumTombstones; + } + void setNumTombstones(unsigned Num) { + NumTombstones = Num; + } + + const BucketT *getInlineBuckets() const { + assert(Small); + // Note that this cast does not violate aliasing rules as we assert that + // the memory's dynamic type is the small, inline bucket buffer, and the + // 'storage.buffer' static type is 'char *'. + return reinterpret_cast<const BucketT *>(storage.buffer); + } + BucketT *getInlineBuckets() { + return const_cast<BucketT *>( + const_cast<const SmallDenseMap *>(this)->getInlineBuckets()); + } + const LargeRep *getLargeRep() const { + assert(!Small); + // Note, same rule about aliasing as with getInlineBuckets. + return reinterpret_cast<const LargeRep *>(storage.buffer); + } + LargeRep *getLargeRep() { + return const_cast<LargeRep *>( + const_cast<const SmallDenseMap *>(this)->getLargeRep()); + } + + const BucketT *getBuckets() const { + return Small ? getInlineBuckets() : getLargeRep()->Buckets; + } + BucketT *getBuckets() { + return const_cast<BucketT *>( + const_cast<const SmallDenseMap *>(this)->getBuckets()); + } + unsigned getNumBuckets() const { + return Small ? InlineBuckets : getLargeRep()->NumBuckets; + } + + void deallocateBuckets() { + if (Small) + return; + + operator delete(getLargeRep()->Buckets); + getLargeRep()->~LargeRep(); + } + + LargeRep allocateBuckets(unsigned Num) { + assert(Num > InlineBuckets && "Must allocate more buckets than are inline"); + LargeRep Rep = { + static_cast<BucketT*>(operator new(sizeof(BucketT) * Num)), Num + }; + return Rep; + } +}; + +template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket, + bool IsConst> +class DenseMapIterator : DebugEpochBase::HandleBase { + typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true> ConstIterator; + friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>; + friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>; + +public: + typedef ptrdiff_t difference_type; + typedef typename std::conditional<IsConst, const Bucket, Bucket>::type + value_type; + typedef value_type *pointer; + typedef value_type &reference; + typedef std::forward_iterator_tag iterator_category; + +private: + pointer Ptr, End; + +public: + DenseMapIterator() : Ptr(nullptr), End(nullptr) {} + + DenseMapIterator(pointer Pos, pointer E, const DebugEpochBase &Epoch, + bool NoAdvance = false) + : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E) { + assert(isHandleInSync() && "invalid construction!"); + if (!NoAdvance) AdvancePastEmptyBuckets(); + } + + // Converting ctor from non-const iterators to const iterators. SFINAE'd out + // for const iterator destinations so it doesn't end up as a user defined copy + // constructor. + template <bool IsConstSrc, + typename = typename std::enable_if<!IsConstSrc && IsConst>::type> + DenseMapIterator( + const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I) + : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End) {} + + reference operator*() const { + assert(isHandleInSync() && "invalid iterator access!"); + return *Ptr; + } + pointer operator->() const { + assert(isHandleInSync() && "invalid iterator access!"); + return Ptr; + } + + bool operator==(const ConstIterator &RHS) const { + assert((!Ptr || isHandleInSync()) && "handle not in sync!"); + assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!"); + assert(getEpochAddress() == RHS.getEpochAddress() && + "comparing incomparable iterators!"); + return Ptr == RHS.Ptr; + } + bool operator!=(const ConstIterator &RHS) const { + assert((!Ptr || isHandleInSync()) && "handle not in sync!"); + assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!"); + assert(getEpochAddress() == RHS.getEpochAddress() && + "comparing incomparable iterators!"); + return Ptr != RHS.Ptr; + } + + inline DenseMapIterator& operator++() { // Preincrement + assert(isHandleInSync() && "invalid iterator access!"); + ++Ptr; + AdvancePastEmptyBuckets(); + return *this; + } + DenseMapIterator operator++(int) { // Postincrement + assert(isHandleInSync() && "invalid iterator access!"); + DenseMapIterator tmp = *this; ++*this; return tmp; + } + +private: + void AdvancePastEmptyBuckets() { + const KeyT Empty = KeyInfoT::getEmptyKey(); + const KeyT Tombstone = KeyInfoT::getTombstoneKey(); + + while (Ptr != End && (KeyInfoT::isEqual(Ptr->getFirst(), Empty) || + KeyInfoT::isEqual(Ptr->getFirst(), Tombstone))) + ++Ptr; + } +}; + +template<typename KeyT, typename ValueT, typename KeyInfoT> +static inline size_t +capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT> &X) { + return X.getMemorySize(); +} + +} // end namespace llvm + +#endif // LLVM_ADT_DENSEMAP_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/DenseMapInfo.h b/third_party/llvm-subzero/include/llvm/ADT/DenseMapInfo.h new file mode 100644 index 0000000..18c692e --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/DenseMapInfo.h
@@ -0,0 +1,251 @@ +//===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines DenseMapInfo traits for DenseMap. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DENSEMAPINFO_H +#define LLVM_ADT_DENSEMAPINFO_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/type_traits.h" + +namespace llvm { + +template<typename T> +struct DenseMapInfo { + //static inline T getEmptyKey(); + //static inline T getTombstoneKey(); + //static unsigned getHashValue(const T &Val); + //static bool isEqual(const T &LHS, const T &RHS); +}; + +template <typename T> struct CachedHash { + CachedHash(T Val) : Val(std::move(Val)) { + Hash = DenseMapInfo<T>::getHashValue(Val); + } + CachedHash(T Val, unsigned Hash) : Val(std::move(Val)), Hash(Hash) {} + T Val; + unsigned Hash; +}; + +// Provide DenseMapInfo for all CachedHash<T>. +template <typename T> struct DenseMapInfo<CachedHash<T>> { + static CachedHash<T> getEmptyKey() { + T N = DenseMapInfo<T>::getEmptyKey(); + return {N, 0}; + } + static CachedHash<T> getTombstoneKey() { + T N = DenseMapInfo<T>::getTombstoneKey(); + return {N, 0}; + } + static unsigned getHashValue(CachedHash<T> Val) { + assert(!isEqual(Val, getEmptyKey()) && "Cannot hash the empty key!"); + assert(!isEqual(Val, getTombstoneKey()) && + "Cannot hash the tombstone key!"); + return Val.Hash; + } + static bool isEqual(CachedHash<T> A, CachedHash<T> B) { + return DenseMapInfo<T>::isEqual(A.Val, B.Val); + } +}; + +// Provide DenseMapInfo for all pointers. +template<typename T> +struct DenseMapInfo<T*> { + static inline T* getEmptyKey() { + uintptr_t Val = static_cast<uintptr_t>(-1); + Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable; + return reinterpret_cast<T*>(Val); + } + static inline T* getTombstoneKey() { + uintptr_t Val = static_cast<uintptr_t>(-2); + Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable; + return reinterpret_cast<T*>(Val); + } + static unsigned getHashValue(const T *PtrVal) { + return (unsigned((uintptr_t)PtrVal) >> 4) ^ + (unsigned((uintptr_t)PtrVal) >> 9); + } + static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; } +}; + +// Provide DenseMapInfo for chars. +template<> struct DenseMapInfo<char> { + static inline char getEmptyKey() { return ~0; } + static inline char getTombstoneKey() { return ~0 - 1; } + static unsigned getHashValue(const char& Val) { return Val * 37U; } + static bool isEqual(const char &LHS, const char &RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for unsigned ints. +template<> struct DenseMapInfo<unsigned> { + static inline unsigned getEmptyKey() { return ~0U; } + static inline unsigned getTombstoneKey() { return ~0U - 1; } + static unsigned getHashValue(const unsigned& Val) { return Val * 37U; } + static bool isEqual(const unsigned& LHS, const unsigned& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for unsigned longs. +template<> struct DenseMapInfo<unsigned long> { + static inline unsigned long getEmptyKey() { return ~0UL; } + static inline unsigned long getTombstoneKey() { return ~0UL - 1L; } + static unsigned getHashValue(const unsigned long& Val) { + return (unsigned)(Val * 37UL); + } + static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for unsigned long longs. +template<> struct DenseMapInfo<unsigned long long> { + static inline unsigned long long getEmptyKey() { return ~0ULL; } + static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; } + static unsigned getHashValue(const unsigned long long& Val) { + return (unsigned)(Val * 37ULL); + } + static bool isEqual(const unsigned long long& LHS, + const unsigned long long& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for ints. +template<> struct DenseMapInfo<int> { + static inline int getEmptyKey() { return 0x7fffffff; } + static inline int getTombstoneKey() { return -0x7fffffff - 1; } + static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); } + static bool isEqual(const int& LHS, const int& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for longs. +template<> struct DenseMapInfo<long> { + static inline long getEmptyKey() { + return (1UL << (sizeof(long) * 8 - 1)) - 1UL; + } + static inline long getTombstoneKey() { return getEmptyKey() - 1L; } + static unsigned getHashValue(const long& Val) { + return (unsigned)(Val * 37UL); + } + static bool isEqual(const long& LHS, const long& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for long longs. +template<> struct DenseMapInfo<long long> { + static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; } + static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; } + static unsigned getHashValue(const long long& Val) { + return (unsigned)(Val * 37ULL); + } + static bool isEqual(const long long& LHS, + const long long& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for all pairs whose members have info. +template<typename T, typename U> +struct DenseMapInfo<std::pair<T, U> > { + typedef std::pair<T, U> Pair; + typedef DenseMapInfo<T> FirstInfo; + typedef DenseMapInfo<U> SecondInfo; + + static inline Pair getEmptyKey() { + return std::make_pair(FirstInfo::getEmptyKey(), + SecondInfo::getEmptyKey()); + } + static inline Pair getTombstoneKey() { + return std::make_pair(FirstInfo::getTombstoneKey(), + SecondInfo::getTombstoneKey()); + } + static unsigned getHashValue(const Pair& PairVal) { + uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32 + | (uint64_t)SecondInfo::getHashValue(PairVal.second); + key += ~(key << 32); + key ^= (key >> 22); + key += ~(key << 13); + key ^= (key >> 8); + key += (key << 3); + key ^= (key >> 15); + key += ~(key << 27); + key ^= (key >> 31); + return (unsigned)key; + } + static bool isEqual(const Pair &LHS, const Pair &RHS) { + return FirstInfo::isEqual(LHS.first, RHS.first) && + SecondInfo::isEqual(LHS.second, RHS.second); + } +}; + +// Provide DenseMapInfo for StringRefs. +template <> struct DenseMapInfo<StringRef> { + static inline StringRef getEmptyKey() { + return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(0)), + 0); + } + static inline StringRef getTombstoneKey() { + return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(1)), + 0); + } + static unsigned getHashValue(StringRef Val) { + assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!"); + assert(Val.data() != getTombstoneKey().data() && + "Cannot hash the tombstone key!"); + return (unsigned)(hash_value(Val)); + } + static bool isEqual(StringRef LHS, StringRef RHS) { + if (RHS.data() == getEmptyKey().data()) + return LHS.data() == getEmptyKey().data(); + if (RHS.data() == getTombstoneKey().data()) + return LHS.data() == getTombstoneKey().data(); + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for ArrayRefs. +template <typename T> struct DenseMapInfo<ArrayRef<T>> { + static inline ArrayRef<T> getEmptyKey() { + return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(0)), + size_t(0)); + } + static inline ArrayRef<T> getTombstoneKey() { + return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(1)), + size_t(0)); + } + static unsigned getHashValue(ArrayRef<T> Val) { + assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!"); + assert(Val.data() != getTombstoneKey().data() && + "Cannot hash the tombstone key!"); + return (unsigned)(hash_value(Val)); + } + static bool isEqual(ArrayRef<T> LHS, ArrayRef<T> RHS) { + if (RHS.data() == getEmptyKey().data()) + return LHS.data() == getEmptyKey().data(); + if (RHS.data() == getTombstoneKey().data()) + return LHS.data() == getTombstoneKey().data(); + return LHS == RHS; + } +}; + +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/EpochTracker.h b/third_party/llvm-subzero/include/llvm/ADT/EpochTracker.h new file mode 100644 index 0000000..582d581 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/EpochTracker.h
@@ -0,0 +1,99 @@ +//===- llvm/ADT/EpochTracker.h - ADT epoch tracking --------------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes. +// These can be used to write iterators that are fail-fast when LLVM is built +// with asserts enabled. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_EPOCH_TRACKER_H +#define LLVM_ADT_EPOCH_TRACKER_H + +#include "llvm/Config/llvm-config.h" + +#include <cstdint> + +namespace llvm { + +#ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS + +class DebugEpochBase { +public: + void incrementEpoch() {} + + class HandleBase { + public: + HandleBase() = default; + explicit HandleBase(const DebugEpochBase *) {} + bool isHandleInSync() const { return true; } + const void *getEpochAddress() const { return nullptr; } + }; +}; + +#else + +/// \brief A base class for data structure classes wishing to make iterators +/// ("handles") pointing into themselves fail-fast. When building without +/// asserts, this class is empty and does nothing. +/// +/// DebugEpochBase does not by itself track handles pointing into itself. The +/// expectation is that routines touching the handles will poll on +/// isHandleInSync at appropriate points to assert that the handle they're using +/// is still valid. +/// +class DebugEpochBase { + uint64_t Epoch; + +public: + DebugEpochBase() : Epoch(0) {} + + /// \brief Calling incrementEpoch invalidates all handles pointing into the + /// calling instance. + void incrementEpoch() { ++Epoch; } + + /// \brief The destructor calls incrementEpoch to make use-after-free bugs + /// more likely to crash deterministically. + ~DebugEpochBase() { incrementEpoch(); } + + /// \brief A base class for iterator classes ("handles") that wish to poll for + /// iterator invalidating modifications in the underlying data structure. + /// When LLVM is built without asserts, this class is empty and does nothing. + /// + /// HandleBase does not track the parent data structure by itself. It expects + /// the routines modifying the data structure to call incrementEpoch when they + /// make an iterator-invalidating modification. + /// + class HandleBase { + const uint64_t *EpochAddress; + uint64_t EpochAtCreation; + + public: + HandleBase() : EpochAddress(nullptr), EpochAtCreation(UINT64_MAX) {} + + explicit HandleBase(const DebugEpochBase *Parent) + : EpochAddress(&Parent->Epoch), EpochAtCreation(Parent->Epoch) {} + + /// \brief Returns true if the DebugEpochBase this Handle is linked to has + /// not called incrementEpoch on itself since the creation of this + /// HandleBase instance. + bool isHandleInSync() const { return *EpochAddress == EpochAtCreation; } + + /// \brief Returns a pointer to the epoch word stored in the data structure + /// this handle points into. Can be used to check if two iterators point + /// into the same data structure. + const void *getEpochAddress() const { return EpochAddress; } + }; +}; + +#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS + +} // namespace llvm + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/FoldingSet.h b/third_party/llvm-subzero/include/llvm/ADT/FoldingSet.h new file mode 100644 index 0000000..f16258a --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/FoldingSet.h
@@ -0,0 +1,764 @@ +//===-- llvm/ADT/FoldingSet.h - Uniquing Hash Set ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a hash set that can be used to remove duplication of nodes +// in a graph. This code was originally created by Chris Lattner for use with +// SelectionDAGCSEMap, but was isolated to provide use across the llvm code set. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_FOLDINGSET_H +#define LLVM_ADT_FOLDINGSET_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator.h" +#include "llvm/Support/Allocator.h" + +namespace llvm { +/// This folding set used for two purposes: +/// 1. Given information about a node we want to create, look up the unique +/// instance of the node in the set. If the node already exists, return +/// it, otherwise return the bucket it should be inserted into. +/// 2. Given a node that has already been created, remove it from the set. +/// +/// This class is implemented as a single-link chained hash table, where the +/// "buckets" are actually the nodes themselves (the next pointer is in the +/// node). The last node points back to the bucket to simplify node removal. +/// +/// Any node that is to be included in the folding set must be a subclass of +/// FoldingSetNode. The node class must also define a Profile method used to +/// establish the unique bits of data for the node. The Profile method is +/// passed a FoldingSetNodeID object which is used to gather the bits. Just +/// call one of the Add* functions defined in the FoldingSetImpl::NodeID class. +/// NOTE: That the folding set does not own the nodes and it is the +/// responsibility of the user to dispose of the nodes. +/// +/// Eg. +/// class MyNode : public FoldingSetNode { +/// private: +/// std::string Name; +/// unsigned Value; +/// public: +/// MyNode(const char *N, unsigned V) : Name(N), Value(V) {} +/// ... +/// void Profile(FoldingSetNodeID &ID) const { +/// ID.AddString(Name); +/// ID.AddInteger(Value); +/// } +/// ... +/// }; +/// +/// To define the folding set itself use the FoldingSet template; +/// +/// Eg. +/// FoldingSet<MyNode> MyFoldingSet; +/// +/// Four public methods are available to manipulate the folding set; +/// +/// 1) If you have an existing node that you want add to the set but unsure +/// that the node might already exist then call; +/// +/// MyNode *M = MyFoldingSet.GetOrInsertNode(N); +/// +/// If The result is equal to the input then the node has been inserted. +/// Otherwise, the result is the node existing in the folding set, and the +/// input can be discarded (use the result instead.) +/// +/// 2) If you are ready to construct a node but want to check if it already +/// exists, then call FindNodeOrInsertPos with a FoldingSetNodeID of the bits to +/// check; +/// +/// FoldingSetNodeID ID; +/// ID.AddString(Name); +/// ID.AddInteger(Value); +/// void *InsertPoint; +/// +/// MyNode *M = MyFoldingSet.FindNodeOrInsertPos(ID, InsertPoint); +/// +/// If found then M with be non-NULL, else InsertPoint will point to where it +/// should be inserted using InsertNode. +/// +/// 3) If you get a NULL result from FindNodeOrInsertPos then you can as a new +/// node with FindNodeOrInsertPos; +/// +/// InsertNode(N, InsertPoint); +/// +/// 4) Finally, if you want to remove a node from the folding set call; +/// +/// bool WasRemoved = RemoveNode(N); +/// +/// The result indicates whether the node existed in the folding set. + +class FoldingSetNodeID; +class StringRef; + +//===----------------------------------------------------------------------===// +/// FoldingSetImpl - Implements the folding set functionality. The main +/// structure is an array of buckets. Each bucket is indexed by the hash of +/// the nodes it contains. The bucket itself points to the nodes contained +/// in the bucket via a singly linked list. The last node in the list points +/// back to the bucket to facilitate node removal. +/// +class FoldingSetImpl { + virtual void anchor(); // Out of line virtual method. + +protected: + /// Buckets - Array of bucket chains. + /// + void **Buckets; + + /// NumBuckets - Length of the Buckets array. Always a power of 2. + /// + unsigned NumBuckets; + + /// NumNodes - Number of nodes in the folding set. Growth occurs when NumNodes + /// is greater than twice the number of buckets. + unsigned NumNodes; + + explicit FoldingSetImpl(unsigned Log2InitSize = 6); + FoldingSetImpl(FoldingSetImpl &&Arg); + FoldingSetImpl &operator=(FoldingSetImpl &&RHS); + ~FoldingSetImpl(); + +public: + //===--------------------------------------------------------------------===// + /// Node - This class is used to maintain the singly linked bucket list in + /// a folding set. + /// + class Node { + private: + // NextInFoldingSetBucket - next link in the bucket list. + void *NextInFoldingSetBucket; + + public: + Node() : NextInFoldingSetBucket(nullptr) {} + + // Accessors + void *getNextInBucket() const { return NextInFoldingSetBucket; } + void SetNextInBucket(void *N) { NextInFoldingSetBucket = N; } + }; + + /// clear - Remove all nodes from the folding set. + void clear(); + + /// RemoveNode - Remove a node from the folding set, returning true if one + /// was removed or false if the node was not in the folding set. + bool RemoveNode(Node *N); + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and return + /// it instead. + Node *GetOrInsertNode(Node *N); + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos); + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. InsertPos must be obtained from + /// FindNodeOrInsertPos. + void InsertNode(Node *N, void *InsertPos); + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. + void InsertNode(Node *N) { + Node *Inserted = GetOrInsertNode(N); + (void)Inserted; + assert(Inserted == N && "Node already inserted!"); + } + + /// size - Returns the number of nodes in the folding set. + unsigned size() const { return NumNodes; } + + /// empty - Returns true if there are no nodes in the folding set. + bool empty() const { return NumNodes == 0; } + + /// reserve - Increase the number of buckets such that adding the + /// EltCount-th node won't cause a rebucket operation. reserve is permitted + /// to allocate more space than requested by EltCount. + void reserve(unsigned EltCount); + /// capacity - Returns the number of nodes permitted in the folding set + /// before a rebucket operation is performed. + unsigned capacity() { + // We allow a load factor of up to 2.0, + // so that means our capacity is NumBuckets * 2 + return NumBuckets * 2; + } + +private: + /// GrowHashTable - Double the size of the hash table and rehash everything. + void GrowHashTable(); + + /// GrowBucketCount - resize the hash table and rehash everything. + /// NewBucketCount must be a power of two, and must be greater than the old + /// bucket count. + void GrowBucketCount(unsigned NewBucketCount); +protected: + /// GetNodeProfile - Instantiations of the FoldingSet template implement + /// this function to gather data bits for the given node. + virtual void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const = 0; + /// NodeEquals - Instantiations of the FoldingSet template implement + /// this function to compare the given node with the given ID. + virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash, + FoldingSetNodeID &TempID) const=0; + /// ComputeNodeHash - Instantiations of the FoldingSet template implement + /// this function to compute a hash value for the given node. + virtual unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const = 0; +}; + +//===----------------------------------------------------------------------===// + +template<typename T> struct FoldingSetTrait; + +/// DefaultFoldingSetTrait - This class provides default implementations +/// for FoldingSetTrait implementations. +/// +template<typename T> struct DefaultFoldingSetTrait { + static void Profile(const T &X, FoldingSetNodeID &ID) { + X.Profile(ID); + } + static void Profile(T &X, FoldingSetNodeID &ID) { + X.Profile(ID); + } + + // Equals - Test if the profile for X would match ID, using TempID + // to compute a temporary ID if necessary. The default implementation + // just calls Profile and does a regular comparison. Implementations + // can override this to provide more efficient implementations. + static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash, + FoldingSetNodeID &TempID); + + // ComputeHash - Compute a hash value for X, using TempID to + // compute a temporary ID if necessary. The default implementation + // just calls Profile and does a regular hash computation. + // Implementations can override this to provide more efficient + // implementations. + static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID); +}; + +/// FoldingSetTrait - This trait class is used to define behavior of how +/// to "profile" (in the FoldingSet parlance) an object of a given type. +/// The default behavior is to invoke a 'Profile' method on an object, but +/// through template specialization the behavior can be tailored for specific +/// types. Combined with the FoldingSetNodeWrapper class, one can add objects +/// to FoldingSets that were not originally designed to have that behavior. +template<typename T> struct FoldingSetTrait + : public DefaultFoldingSetTrait<T> {}; + +template<typename T, typename Ctx> struct ContextualFoldingSetTrait; + +/// DefaultContextualFoldingSetTrait - Like DefaultFoldingSetTrait, but +/// for ContextualFoldingSets. +template<typename T, typename Ctx> +struct DefaultContextualFoldingSetTrait { + static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) { + X.Profile(ID, Context); + } + static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash, + FoldingSetNodeID &TempID, Ctx Context); + static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID, + Ctx Context); +}; + +/// ContextualFoldingSetTrait - Like FoldingSetTrait, but for +/// ContextualFoldingSets. +template<typename T, typename Ctx> struct ContextualFoldingSetTrait + : public DefaultContextualFoldingSetTrait<T, Ctx> {}; + +//===--------------------------------------------------------------------===// +/// FoldingSetNodeIDRef - This class describes a reference to an interned +/// FoldingSetNodeID, which can be a useful to store node id data rather +/// than using plain FoldingSetNodeIDs, since the 32-element SmallVector +/// is often much larger than necessary, and the possibility of heap +/// allocation means it requires a non-trivial destructor call. +class FoldingSetNodeIDRef { + const unsigned *Data; + size_t Size; + +public: + FoldingSetNodeIDRef() : Data(nullptr), Size(0) {} + FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {} + + /// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef, + /// used to lookup the node in the FoldingSetImpl. + unsigned ComputeHash() const; + + bool operator==(FoldingSetNodeIDRef) const; + + bool operator!=(FoldingSetNodeIDRef RHS) const { return !(*this == RHS); } + + /// Used to compare the "ordering" of two nodes as defined by the + /// profiled bits and their ordering defined by memcmp(). + bool operator<(FoldingSetNodeIDRef) const; + + const unsigned *getData() const { return Data; } + size_t getSize() const { return Size; } +}; + +//===--------------------------------------------------------------------===// +/// FoldingSetNodeID - This class is used to gather all the unique data bits of +/// a node. When all the bits are gathered this class is used to produce a +/// hash value for the node. +/// +class FoldingSetNodeID { + /// Bits - Vector of all the data bits that make the node unique. + /// Use a SmallVector to avoid a heap allocation in the common case. + SmallVector<unsigned, 32> Bits; + +public: + FoldingSetNodeID() {} + + FoldingSetNodeID(FoldingSetNodeIDRef Ref) + : Bits(Ref.getData(), Ref.getData() + Ref.getSize()) {} + + /// Add* - Add various data types to Bit data. + /// + void AddPointer(const void *Ptr); + void AddInteger(signed I); + void AddInteger(unsigned I); + void AddInteger(long I); + void AddInteger(unsigned long I); + void AddInteger(long long I); + void AddInteger(unsigned long long I); + void AddBoolean(bool B) { AddInteger(B ? 1U : 0U); } + void AddString(StringRef String); + void AddNodeID(const FoldingSetNodeID &ID); + + template <typename T> + inline void Add(const T &x) { FoldingSetTrait<T>::Profile(x, *this); } + + /// clear - Clear the accumulated profile, allowing this FoldingSetNodeID + /// object to be used to compute a new profile. + inline void clear() { Bits.clear(); } + + /// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used + /// to lookup the node in the FoldingSetImpl. + unsigned ComputeHash() const; + + /// operator== - Used to compare two nodes to each other. + /// + bool operator==(const FoldingSetNodeID &RHS) const; + bool operator==(const FoldingSetNodeIDRef RHS) const; + + bool operator!=(const FoldingSetNodeID &RHS) const { return !(*this == RHS); } + bool operator!=(const FoldingSetNodeIDRef RHS) const { return !(*this ==RHS);} + + /// Used to compare the "ordering" of two nodes as defined by the + /// profiled bits and their ordering defined by memcmp(). + bool operator<(const FoldingSetNodeID &RHS) const; + bool operator<(const FoldingSetNodeIDRef RHS) const; + + /// Intern - Copy this node's data to a memory region allocated from the + /// given allocator and return a FoldingSetNodeIDRef describing the + /// interned data. + FoldingSetNodeIDRef Intern(BumpPtrAllocator &Allocator) const; +}; + +// Convenience type to hide the implementation of the folding set. +typedef FoldingSetImpl::Node FoldingSetNode; +template<class T> class FoldingSetIterator; +template<class T> class FoldingSetBucketIterator; + +// Definitions of FoldingSetTrait and ContextualFoldingSetTrait functions, which +// require the definition of FoldingSetNodeID. +template<typename T> +inline bool +DefaultFoldingSetTrait<T>::Equals(T &X, const FoldingSetNodeID &ID, + unsigned /*IDHash*/, + FoldingSetNodeID &TempID) { + FoldingSetTrait<T>::Profile(X, TempID); + return TempID == ID; +} +template<typename T> +inline unsigned +DefaultFoldingSetTrait<T>::ComputeHash(T &X, FoldingSetNodeID &TempID) { + FoldingSetTrait<T>::Profile(X, TempID); + return TempID.ComputeHash(); +} +template<typename T, typename Ctx> +inline bool +DefaultContextualFoldingSetTrait<T, Ctx>::Equals(T &X, + const FoldingSetNodeID &ID, + unsigned /*IDHash*/, + FoldingSetNodeID &TempID, + Ctx Context) { + ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context); + return TempID == ID; +} +template<typename T, typename Ctx> +inline unsigned +DefaultContextualFoldingSetTrait<T, Ctx>::ComputeHash(T &X, + FoldingSetNodeID &TempID, + Ctx Context) { + ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context); + return TempID.ComputeHash(); +} + +//===----------------------------------------------------------------------===// +/// FoldingSet - This template class is used to instantiate a specialized +/// implementation of the folding set to the node class T. T must be a +/// subclass of FoldingSetNode and implement a Profile function. +/// +/// Note that this set type is movable and move-assignable. However, its +/// moved-from state is not a valid state for anything other than +/// move-assigning and destroying. This is primarily to enable movable APIs +/// that incorporate these objects. +template <class T> class FoldingSet final : public FoldingSetImpl { +private: + /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a + /// way to convert nodes into a unique specifier. + void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const override { + T *TN = static_cast<T *>(N); + FoldingSetTrait<T>::Profile(*TN, ID); + } + /// NodeEquals - Instantiations may optionally provide a way to compare a + /// node with a specified ID. + bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash, + FoldingSetNodeID &TempID) const override { + T *TN = static_cast<T *>(N); + return FoldingSetTrait<T>::Equals(*TN, ID, IDHash, TempID); + } + /// ComputeNodeHash - Instantiations may optionally provide a way to compute a + /// hash value directly from a node. + unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const override { + T *TN = static_cast<T *>(N); + return FoldingSetTrait<T>::ComputeHash(*TN, TempID); + } + +public: + explicit FoldingSet(unsigned Log2InitSize = 6) + : FoldingSetImpl(Log2InitSize) {} + + FoldingSet(FoldingSet &&Arg) : FoldingSetImpl(std::move(Arg)) {} + FoldingSet &operator=(FoldingSet &&RHS) { + (void)FoldingSetImpl::operator=(std::move(RHS)); + return *this; + } + + typedef FoldingSetIterator<T> iterator; + iterator begin() { return iterator(Buckets); } + iterator end() { return iterator(Buckets+NumBuckets); } + + typedef FoldingSetIterator<const T> const_iterator; + const_iterator begin() const { return const_iterator(Buckets); } + const_iterator end() const { return const_iterator(Buckets+NumBuckets); } + + typedef FoldingSetBucketIterator<T> bucket_iterator; + + bucket_iterator bucket_begin(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1))); + } + + bucket_iterator bucket_end(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true); + } + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and + /// return it instead. + T *GetOrInsertNode(Node *N) { + return static_cast<T *>(FoldingSetImpl::GetOrInsertNode(N)); + } + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { + return static_cast<T *>(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos)); + } +}; + +//===----------------------------------------------------------------------===// +/// ContextualFoldingSet - This template class is a further refinement +/// of FoldingSet which provides a context argument when calling +/// Profile on its nodes. Currently, that argument is fixed at +/// initialization time. +/// +/// T must be a subclass of FoldingSetNode and implement a Profile +/// function with signature +/// void Profile(llvm::FoldingSetNodeID &, Ctx); +template <class T, class Ctx> +class ContextualFoldingSet final : public FoldingSetImpl { + // Unfortunately, this can't derive from FoldingSet<T> because the + // construction vtable for FoldingSet<T> requires + // FoldingSet<T>::GetNodeProfile to be instantiated, which in turn + // requires a single-argument T::Profile(). + +private: + Ctx Context; + + /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a + /// way to convert nodes into a unique specifier. + void GetNodeProfile(FoldingSetImpl::Node *N, + FoldingSetNodeID &ID) const override { + T *TN = static_cast<T *>(N); + ContextualFoldingSetTrait<T, Ctx>::Profile(*TN, ID, Context); + } + bool NodeEquals(FoldingSetImpl::Node *N, const FoldingSetNodeID &ID, + unsigned IDHash, FoldingSetNodeID &TempID) const override { + T *TN = static_cast<T *>(N); + return ContextualFoldingSetTrait<T, Ctx>::Equals(*TN, ID, IDHash, TempID, + Context); + } + unsigned ComputeNodeHash(FoldingSetImpl::Node *N, + FoldingSetNodeID &TempID) const override { + T *TN = static_cast<T *>(N); + return ContextualFoldingSetTrait<T, Ctx>::ComputeHash(*TN, TempID, Context); + } + +public: + explicit ContextualFoldingSet(Ctx Context, unsigned Log2InitSize = 6) + : FoldingSetImpl(Log2InitSize), Context(Context) + {} + + Ctx getContext() const { return Context; } + + typedef FoldingSetIterator<T> iterator; + iterator begin() { return iterator(Buckets); } + iterator end() { return iterator(Buckets+NumBuckets); } + + typedef FoldingSetIterator<const T> const_iterator; + const_iterator begin() const { return const_iterator(Buckets); } + const_iterator end() const { return const_iterator(Buckets+NumBuckets); } + + typedef FoldingSetBucketIterator<T> bucket_iterator; + + bucket_iterator bucket_begin(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1))); + } + + bucket_iterator bucket_end(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true); + } + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' + /// and return it instead. + T *GetOrInsertNode(Node *N) { + return static_cast<T *>(FoldingSetImpl::GetOrInsertNode(N)); + } + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it + /// exists, return it. If not, return the insertion token that will + /// make insertion faster. + T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { + return static_cast<T *>(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos)); + } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetVector - This template class combines a FoldingSet and a vector +/// to provide the interface of FoldingSet but with deterministic iteration +/// order based on the insertion order. T must be a subclass of FoldingSetNode +/// and implement a Profile function. +template <class T, class VectorT = SmallVector<T*, 8> > +class FoldingSetVector { + FoldingSet<T> Set; + VectorT Vector; + +public: + explicit FoldingSetVector(unsigned Log2InitSize = 6) + : Set(Log2InitSize) { + } + + typedef pointee_iterator<typename VectorT::iterator> iterator; + iterator begin() { return Vector.begin(); } + iterator end() { return Vector.end(); } + + typedef pointee_iterator<typename VectorT::const_iterator> const_iterator; + const_iterator begin() const { return Vector.begin(); } + const_iterator end() const { return Vector.end(); } + + /// clear - Remove all nodes from the folding set. + void clear() { Set.clear(); Vector.clear(); } + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { + return Set.FindNodeOrInsertPos(ID, InsertPos); + } + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and + /// return it instead. + T *GetOrInsertNode(T *N) { + T *Result = Set.GetOrInsertNode(N); + if (Result == N) Vector.push_back(N); + return Result; + } + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. InsertPos must be obtained from + /// FindNodeOrInsertPos. + void InsertNode(T *N, void *InsertPos) { + Set.InsertNode(N, InsertPos); + Vector.push_back(N); + } + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. + void InsertNode(T *N) { + Set.InsertNode(N); + Vector.push_back(N); + } + + /// size - Returns the number of nodes in the folding set. + unsigned size() const { return Set.size(); } + + /// empty - Returns true if there are no nodes in the folding set. + bool empty() const { return Set.empty(); } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetIteratorImpl - This is the common iterator support shared by all +/// folding sets, which knows how to walk the folding set hash table. +class FoldingSetIteratorImpl { +protected: + FoldingSetNode *NodePtr; + FoldingSetIteratorImpl(void **Bucket); + void advance(); + +public: + bool operator==(const FoldingSetIteratorImpl &RHS) const { + return NodePtr == RHS.NodePtr; + } + bool operator!=(const FoldingSetIteratorImpl &RHS) const { + return NodePtr != RHS.NodePtr; + } +}; + +template <class T> class FoldingSetIterator : public FoldingSetIteratorImpl { +public: + explicit FoldingSetIterator(void **Bucket) : FoldingSetIteratorImpl(Bucket) {} + + T &operator*() const { + return *static_cast<T*>(NodePtr); + } + + T *operator->() const { + return static_cast<T*>(NodePtr); + } + + inline FoldingSetIterator &operator++() { // Preincrement + advance(); + return *this; + } + FoldingSetIterator operator++(int) { // Postincrement + FoldingSetIterator tmp = *this; ++*this; return tmp; + } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetBucketIteratorImpl - This is the common bucket iterator support +/// shared by all folding sets, which knows how to walk a particular bucket +/// of a folding set hash table. + +class FoldingSetBucketIteratorImpl { +protected: + void *Ptr; + + explicit FoldingSetBucketIteratorImpl(void **Bucket); + + FoldingSetBucketIteratorImpl(void **Bucket, bool) + : Ptr(Bucket) {} + + void advance() { + void *Probe = static_cast<FoldingSetNode*>(Ptr)->getNextInBucket(); + uintptr_t x = reinterpret_cast<uintptr_t>(Probe) & ~0x1; + Ptr = reinterpret_cast<void*>(x); + } + +public: + bool operator==(const FoldingSetBucketIteratorImpl &RHS) const { + return Ptr == RHS.Ptr; + } + bool operator!=(const FoldingSetBucketIteratorImpl &RHS) const { + return Ptr != RHS.Ptr; + } +}; + +template <class T> +class FoldingSetBucketIterator : public FoldingSetBucketIteratorImpl { +public: + explicit FoldingSetBucketIterator(void **Bucket) : + FoldingSetBucketIteratorImpl(Bucket) {} + + FoldingSetBucketIterator(void **Bucket, bool) : + FoldingSetBucketIteratorImpl(Bucket, true) {} + + T &operator*() const { return *static_cast<T*>(Ptr); } + T *operator->() const { return static_cast<T*>(Ptr); } + + inline FoldingSetBucketIterator &operator++() { // Preincrement + advance(); + return *this; + } + FoldingSetBucketIterator operator++(int) { // Postincrement + FoldingSetBucketIterator tmp = *this; ++*this; return tmp; + } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetNodeWrapper - This template class is used to "wrap" arbitrary +/// types in an enclosing object so that they can be inserted into FoldingSets. +template <typename T> +class FoldingSetNodeWrapper : public FoldingSetNode { + T data; + +public: + template <typename... Ts> + explicit FoldingSetNodeWrapper(Ts &&... Args) + : data(std::forward<Ts>(Args)...) {} + + void Profile(FoldingSetNodeID &ID) { FoldingSetTrait<T>::Profile(data, ID); } + + T &getValue() { return data; } + const T &getValue() const { return data; } + + operator T&() { return data; } + operator const T&() const { return data; } +}; + +//===----------------------------------------------------------------------===// +/// FastFoldingSetNode - This is a subclass of FoldingSetNode which stores +/// a FoldingSetNodeID value rather than requiring the node to recompute it +/// each time it is needed. This trades space for speed (which can be +/// significant if the ID is long), and it also permits nodes to drop +/// information that would otherwise only be required for recomputing an ID. +class FastFoldingSetNode : public FoldingSetNode { + FoldingSetNodeID FastID; + +protected: + explicit FastFoldingSetNode(const FoldingSetNodeID &ID) : FastID(ID) {} + +public: + void Profile(FoldingSetNodeID &ID) const { ID.AddNodeID(FastID); } +}; + +//===----------------------------------------------------------------------===// +// Partial specializations of FoldingSetTrait. + +template<typename T> struct FoldingSetTrait<T*> { + static inline void Profile(T *X, FoldingSetNodeID &ID) { + ID.AddPointer(X); + } +}; +template <typename T1, typename T2> +struct FoldingSetTrait<std::pair<T1, T2>> { + static inline void Profile(const std::pair<T1, T2> &P, + llvm::FoldingSetNodeID &ID) { + ID.Add(P.first); + ID.Add(P.second); + } +}; +} // End of namespace llvm. + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/Hashing.h b/third_party/llvm-subzero/include/llvm/ADT/Hashing.h new file mode 100644 index 0000000..c3b5741 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/Hashing.h
@@ -0,0 +1,661 @@ +//===-- llvm/ADT/Hashing.h - Utilities for hashing --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the newly proposed standard C++ interfaces for hashing +// arbitrary data and building hash functions for user-defined types. This +// interface was originally proposed in N3333[1] and is currently under review +// for inclusion in a future TR and/or standard. +// +// The primary interfaces provide are comprised of one type and three functions: +// +// -- 'hash_code' class is an opaque type representing the hash code for some +// data. It is the intended product of hashing, and can be used to implement +// hash tables, checksumming, and other common uses of hashes. It is not an +// integer type (although it can be converted to one) because it is risky +// to assume much about the internals of a hash_code. In particular, each +// execution of the program has a high probability of producing a different +// hash_code for a given input. Thus their values are not stable to save or +// persist, and should only be used during the execution for the +// construction of hashing datastructures. +// +// -- 'hash_value' is a function designed to be overloaded for each +// user-defined type which wishes to be used within a hashing context. It +// should be overloaded within the user-defined type's namespace and found +// via ADL. Overloads for primitive types are provided by this library. +// +// -- 'hash_combine' and 'hash_combine_range' are functions designed to aid +// programmers in easily and intuitively combining a set of data into +// a single hash_code for their object. They should only logically be used +// within the implementation of a 'hash_value' routine or similar context. +// +// Note that 'hash_combine_range' contains very special logic for hashing +// a contiguous array of integers or pointers. This logic is *extremely* fast, +// on a modern Intel "Gainestown" Xeon (Nehalem uarch) @2.2 GHz, these were +// benchmarked at over 6.5 GiB/s for large keys, and <20 cycles/hash for keys +// under 32-bytes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_HASHING_H +#define LLVM_ADT_HASHING_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/SwapByteOrder.h" +#include "llvm/Support/type_traits.h" +#include <algorithm> +#include <cassert> +#include <cstring> +#include <string> +#include <utility> + +namespace llvm { + +/// \brief An opaque object representing a hash code. +/// +/// This object represents the result of hashing some entity. It is intended to +/// be used to implement hashtables or other hashing-based data structures. +/// While it wraps and exposes a numeric value, this value should not be +/// trusted to be stable or predictable across processes or executions. +/// +/// In order to obtain the hash_code for an object 'x': +/// \code +/// using llvm::hash_value; +/// llvm::hash_code code = hash_value(x); +/// \endcode +class hash_code { + size_t value; + +public: + /// \brief Default construct a hash_code. + /// Note that this leaves the value uninitialized. + hash_code() = default; + + /// \brief Form a hash code directly from a numerical value. + hash_code(size_t value) : value(value) {} + + /// \brief Convert the hash code to its numerical value for use. + /*explicit*/ operator size_t() const { return value; } + + friend bool operator==(const hash_code &lhs, const hash_code &rhs) { + return lhs.value == rhs.value; + } + friend bool operator!=(const hash_code &lhs, const hash_code &rhs) { + return lhs.value != rhs.value; + } + + /// \brief Allow a hash_code to be directly run through hash_value. + friend size_t hash_value(const hash_code &code) { return code.value; } +}; + +/// \brief Compute a hash_code for any integer value. +/// +/// Note that this function is intended to compute the same hash_code for +/// a particular value without regard to the pre-promotion type. This is in +/// contrast to hash_combine which may produce different hash_codes for +/// differing argument types even if they would implicit promote to a common +/// type without changing the value. +template <typename T> +typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::type +hash_value(T value); + +/// \brief Compute a hash_code for a pointer's address. +/// +/// N.B.: This hashes the *address*. Not the value and not the type. +template <typename T> hash_code hash_value(const T *ptr); + +/// \brief Compute a hash_code for a pair of objects. +template <typename T, typename U> +hash_code hash_value(const std::pair<T, U> &arg); + +/// \brief Compute a hash_code for a standard string. +template <typename T> +hash_code hash_value(const std::basic_string<T> &arg); + + +/// \brief Override the execution seed with a fixed value. +/// +/// This hashing library uses a per-execution seed designed to change on each +/// run with high probability in order to ensure that the hash codes are not +/// attackable and to ensure that output which is intended to be stable does +/// not rely on the particulars of the hash codes produced. +/// +/// That said, there are use cases where it is important to be able to +/// reproduce *exactly* a specific behavior. To that end, we provide a function +/// which will forcibly set the seed to a fixed value. This must be done at the +/// start of the program, before any hashes are computed. Also, it cannot be +/// undone. This makes it thread-hostile and very hard to use outside of +/// immediately on start of a simple program designed for reproducible +/// behavior. +void set_fixed_execution_hash_seed(size_t fixed_value); + + +// All of the implementation details of actually computing the various hash +// code values are held within this namespace. These routines are included in +// the header file mainly to allow inlining and constant propagation. +namespace hashing { +namespace detail { + +inline uint64_t fetch64(const char *p) { + uint64_t result; + memcpy(&result, p, sizeof(result)); + if (sys::IsBigEndianHost) + sys::swapByteOrder(result); + return result; +} + +inline uint32_t fetch32(const char *p) { + uint32_t result; + memcpy(&result, p, sizeof(result)); + if (sys::IsBigEndianHost) + sys::swapByteOrder(result); + return result; +} + +/// Some primes between 2^63 and 2^64 for various uses. +static const uint64_t k0 = 0xc3a5c85c97cb3127ULL; +static const uint64_t k1 = 0xb492b66fbe98f273ULL; +static const uint64_t k2 = 0x9ae16a3b2f90404fULL; +static const uint64_t k3 = 0xc949d7c7509e6557ULL; + +/// \brief Bitwise right rotate. +/// Normally this will compile to a single instruction, especially if the +/// shift is a manifest constant. +inline uint64_t rotate(uint64_t val, size_t shift) { + // Avoid shifting by 64: doing so yields an undefined result. + return shift == 0 ? val : ((val >> shift) | (val << (64 - shift))); +} + +inline uint64_t shift_mix(uint64_t val) { + return val ^ (val >> 47); +} + +inline uint64_t hash_16_bytes(uint64_t low, uint64_t high) { + // Murmur-inspired hashing. + const uint64_t kMul = 0x9ddfea08eb382d69ULL; + uint64_t a = (low ^ high) * kMul; + a ^= (a >> 47); + uint64_t b = (high ^ a) * kMul; + b ^= (b >> 47); + b *= kMul; + return b; +} + +inline uint64_t hash_1to3_bytes(const char *s, size_t len, uint64_t seed) { + uint8_t a = s[0]; + uint8_t b = s[len >> 1]; + uint8_t c = s[len - 1]; + uint32_t y = static_cast<uint32_t>(a) + (static_cast<uint32_t>(b) << 8); + uint32_t z = len + (static_cast<uint32_t>(c) << 2); + return shift_mix(y * k2 ^ z * k3 ^ seed) * k2; +} + +inline uint64_t hash_4to8_bytes(const char *s, size_t len, uint64_t seed) { + uint64_t a = fetch32(s); + return hash_16_bytes(len + (a << 3), seed ^ fetch32(s + len - 4)); +} + +inline uint64_t hash_9to16_bytes(const char *s, size_t len, uint64_t seed) { + uint64_t a = fetch64(s); + uint64_t b = fetch64(s + len - 8); + return hash_16_bytes(seed ^ a, rotate(b + len, len)) ^ b; +} + +inline uint64_t hash_17to32_bytes(const char *s, size_t len, uint64_t seed) { + uint64_t a = fetch64(s) * k1; + uint64_t b = fetch64(s + 8); + uint64_t c = fetch64(s + len - 8) * k2; + uint64_t d = fetch64(s + len - 16) * k0; + return hash_16_bytes(rotate(a - b, 43) + rotate(c ^ seed, 30) + d, + a + rotate(b ^ k3, 20) - c + len + seed); +} + +inline uint64_t hash_33to64_bytes(const char *s, size_t len, uint64_t seed) { + uint64_t z = fetch64(s + 24); + uint64_t a = fetch64(s) + (len + fetch64(s + len - 16)) * k0; + uint64_t b = rotate(a + z, 52); + uint64_t c = rotate(a, 37); + a += fetch64(s + 8); + c += rotate(a, 7); + a += fetch64(s + 16); + uint64_t vf = a + z; + uint64_t vs = b + rotate(a, 31) + c; + a = fetch64(s + 16) + fetch64(s + len - 32); + z = fetch64(s + len - 8); + b = rotate(a + z, 52); + c = rotate(a, 37); + a += fetch64(s + len - 24); + c += rotate(a, 7); + a += fetch64(s + len - 16); + uint64_t wf = a + z; + uint64_t ws = b + rotate(a, 31) + c; + uint64_t r = shift_mix((vf + ws) * k2 + (wf + vs) * k0); + return shift_mix((seed ^ (r * k0)) + vs) * k2; +} + +inline uint64_t hash_short(const char *s, size_t length, uint64_t seed) { + if (length >= 4 && length <= 8) + return hash_4to8_bytes(s, length, seed); + if (length > 8 && length <= 16) + return hash_9to16_bytes(s, length, seed); + if (length > 16 && length <= 32) + return hash_17to32_bytes(s, length, seed); + if (length > 32) + return hash_33to64_bytes(s, length, seed); + if (length != 0) + return hash_1to3_bytes(s, length, seed); + + return k2 ^ seed; +} + +/// \brief The intermediate state used during hashing. +/// Currently, the algorithm for computing hash codes is based on CityHash and +/// keeps 56 bytes of arbitrary state. +struct hash_state { + uint64_t h0, h1, h2, h3, h4, h5, h6; + + /// \brief Create a new hash_state structure and initialize it based on the + /// seed and the first 64-byte chunk. + /// This effectively performs the initial mix. + static hash_state create(const char *s, uint64_t seed) { + hash_state state = { + 0, seed, hash_16_bytes(seed, k1), rotate(seed ^ k1, 49), + seed * k1, shift_mix(seed), 0 }; + state.h6 = hash_16_bytes(state.h4, state.h5); + state.mix(s); + return state; + } + + /// \brief Mix 32-bytes from the input sequence into the 16-bytes of 'a' + /// and 'b', including whatever is already in 'a' and 'b'. + static void mix_32_bytes(const char *s, uint64_t &a, uint64_t &b) { + a += fetch64(s); + uint64_t c = fetch64(s + 24); + b = rotate(b + a + c, 21); + uint64_t d = a; + a += fetch64(s + 8) + fetch64(s + 16); + b += rotate(a, 44) + d; + a += c; + } + + /// \brief Mix in a 64-byte buffer of data. + /// We mix all 64 bytes even when the chunk length is smaller, but we + /// record the actual length. + void mix(const char *s) { + h0 = rotate(h0 + h1 + h3 + fetch64(s + 8), 37) * k1; + h1 = rotate(h1 + h4 + fetch64(s + 48), 42) * k1; + h0 ^= h6; + h1 += h3 + fetch64(s + 40); + h2 = rotate(h2 + h5, 33) * k1; + h3 = h4 * k1; + h4 = h0 + h5; + mix_32_bytes(s, h3, h4); + h5 = h2 + h6; + h6 = h1 + fetch64(s + 16); + mix_32_bytes(s + 32, h5, h6); + std::swap(h2, h0); + } + + /// \brief Compute the final 64-bit hash code value based on the current + /// state and the length of bytes hashed. + uint64_t finalize(size_t length) { + return hash_16_bytes(hash_16_bytes(h3, h5) + shift_mix(h1) * k1 + h2, + hash_16_bytes(h4, h6) + shift_mix(length) * k1 + h0); + } +}; + + +/// \brief A global, fixed seed-override variable. +/// +/// This variable can be set using the \see llvm::set_fixed_execution_seed +/// function. See that function for details. Do not, under any circumstances, +/// set or read this variable. +extern size_t fixed_seed_override; + +inline size_t get_execution_seed() { + // FIXME: This needs to be a per-execution seed. This is just a placeholder + // implementation. Switching to a per-execution seed is likely to flush out + // instability bugs and so will happen as its own commit. + // + // However, if there is a fixed seed override set the first time this is + // called, return that instead of the per-execution seed. + const uint64_t seed_prime = 0xff51afd7ed558ccdULL; + static size_t seed = fixed_seed_override ? fixed_seed_override + : (size_t)seed_prime; + return seed; +} + + +/// \brief Trait to indicate whether a type's bits can be hashed directly. +/// +/// A type trait which is true if we want to combine values for hashing by +/// reading the underlying data. It is false if values of this type must +/// first be passed to hash_value, and the resulting hash_codes combined. +// +// FIXME: We want to replace is_integral_or_enum and is_pointer here with +// a predicate which asserts that comparing the underlying storage of two +// values of the type for equality is equivalent to comparing the two values +// for equality. For all the platforms we care about, this holds for integers +// and pointers, but there are platforms where it doesn't and we would like to +// support user-defined types which happen to satisfy this property. +template <typename T> struct is_hashable_data + : std::integral_constant<bool, ((is_integral_or_enum<T>::value || + std::is_pointer<T>::value) && + 64 % sizeof(T) == 0)> {}; + +// Special case std::pair to detect when both types are viable and when there +// is no alignment-derived padding in the pair. This is a bit of a lie because +// std::pair isn't truly POD, but it's close enough in all reasonable +// implementations for our use case of hashing the underlying data. +template <typename T, typename U> struct is_hashable_data<std::pair<T, U> > + : std::integral_constant<bool, (is_hashable_data<T>::value && + is_hashable_data<U>::value && + (sizeof(T) + sizeof(U)) == + sizeof(std::pair<T, U>))> {}; + +/// \brief Helper to get the hashable data representation for a type. +/// This variant is enabled when the type itself can be used. +template <typename T> +typename std::enable_if<is_hashable_data<T>::value, T>::type +get_hashable_data(const T &value) { + return value; +} +/// \brief Helper to get the hashable data representation for a type. +/// This variant is enabled when we must first call hash_value and use the +/// result as our data. +template <typename T> +typename std::enable_if<!is_hashable_data<T>::value, size_t>::type +get_hashable_data(const T &value) { + using ::llvm::hash_value; + return hash_value(value); +} + +/// \brief Helper to store data from a value into a buffer and advance the +/// pointer into that buffer. +/// +/// This routine first checks whether there is enough space in the provided +/// buffer, and if not immediately returns false. If there is space, it +/// copies the underlying bytes of value into the buffer, advances the +/// buffer_ptr past the copied bytes, and returns true. +template <typename T> +bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value, + size_t offset = 0) { + size_t store_size = sizeof(value) - offset; + if (buffer_ptr + store_size > buffer_end) + return false; + const char *value_data = reinterpret_cast<const char *>(&value); + memcpy(buffer_ptr, value_data + offset, store_size); + buffer_ptr += store_size; + return true; +} + +/// \brief Implement the combining of integral values into a hash_code. +/// +/// This overload is selected when the value type of the iterator is +/// integral. Rather than computing a hash_code for each object and then +/// combining them, this (as an optimization) directly combines the integers. +template <typename InputIteratorT> +hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) { + const size_t seed = get_execution_seed(); + char buffer[64], *buffer_ptr = buffer; + char *const buffer_end = std::end(buffer); + while (first != last && store_and_advance(buffer_ptr, buffer_end, + get_hashable_data(*first))) + ++first; + if (first == last) + return hash_short(buffer, buffer_ptr - buffer, seed); + assert(buffer_ptr == buffer_end); + + hash_state state = state.create(buffer, seed); + size_t length = 64; + while (first != last) { + // Fill up the buffer. We don't clear it, which re-mixes the last round + // when only a partial 64-byte chunk is left. + buffer_ptr = buffer; + while (first != last && store_and_advance(buffer_ptr, buffer_end, + get_hashable_data(*first))) + ++first; + + // Rotate the buffer if we did a partial fill in order to simulate doing + // a mix of the last 64-bytes. That is how the algorithm works when we + // have a contiguous byte sequence, and we want to emulate that here. + std::rotate(buffer, buffer_ptr, buffer_end); + + // Mix this chunk into the current state. + state.mix(buffer); + length += buffer_ptr - buffer; + }; + + return state.finalize(length); +} + +/// \brief Implement the combining of integral values into a hash_code. +/// +/// This overload is selected when the value type of the iterator is integral +/// and when the input iterator is actually a pointer. Rather than computing +/// a hash_code for each object and then combining them, this (as an +/// optimization) directly combines the integers. Also, because the integers +/// are stored in contiguous memory, this routine avoids copying each value +/// and directly reads from the underlying memory. +template <typename ValueT> +typename std::enable_if<is_hashable_data<ValueT>::value, hash_code>::type +hash_combine_range_impl(ValueT *first, ValueT *last) { + const size_t seed = get_execution_seed(); + const char *s_begin = reinterpret_cast<const char *>(first); + const char *s_end = reinterpret_cast<const char *>(last); + const size_t length = std::distance(s_begin, s_end); + if (length <= 64) + return hash_short(s_begin, length, seed); + + const char *s_aligned_end = s_begin + (length & ~63); + hash_state state = state.create(s_begin, seed); + s_begin += 64; + while (s_begin != s_aligned_end) { + state.mix(s_begin); + s_begin += 64; + } + if (length & 63) + state.mix(s_end - 64); + + return state.finalize(length); +} + +} // namespace detail +} // namespace hashing + + +/// \brief Compute a hash_code for a sequence of values. +/// +/// This hashes a sequence of values. It produces the same hash_code as +/// 'hash_combine(a, b, c, ...)', but can run over arbitrary sized sequences +/// and is significantly faster given pointers and types which can be hashed as +/// a sequence of bytes. +template <typename InputIteratorT> +hash_code hash_combine_range(InputIteratorT first, InputIteratorT last) { + return ::llvm::hashing::detail::hash_combine_range_impl(first, last); +} + + +// Implementation details for hash_combine. +namespace hashing { +namespace detail { + +/// \brief Helper class to manage the recursive combining of hash_combine +/// arguments. +/// +/// This class exists to manage the state and various calls involved in the +/// recursive combining of arguments used in hash_combine. It is particularly +/// useful at minimizing the code in the recursive calls to ease the pain +/// caused by a lack of variadic functions. +struct hash_combine_recursive_helper { + char buffer[64]; + hash_state state; + const size_t seed; + +public: + /// \brief Construct a recursive hash combining helper. + /// + /// This sets up the state for a recursive hash combine, including getting + /// the seed and buffer setup. + hash_combine_recursive_helper() + : seed(get_execution_seed()) {} + + /// \brief Combine one chunk of data into the current in-flight hash. + /// + /// This merges one chunk of data into the hash. First it tries to buffer + /// the data. If the buffer is full, it hashes the buffer into its + /// hash_state, empties it, and then merges the new chunk in. This also + /// handles cases where the data straddles the end of the buffer. + template <typename T> + char *combine_data(size_t &length, char *buffer_ptr, char *buffer_end, T data) { + if (!store_and_advance(buffer_ptr, buffer_end, data)) { + // Check for skew which prevents the buffer from being packed, and do + // a partial store into the buffer to fill it. This is only a concern + // with the variadic combine because that formation can have varying + // argument types. + size_t partial_store_size = buffer_end - buffer_ptr; + memcpy(buffer_ptr, &data, partial_store_size); + + // If the store fails, our buffer is full and ready to hash. We have to + // either initialize the hash state (on the first full buffer) or mix + // this buffer into the existing hash state. Length tracks the *hashed* + // length, not the buffered length. + if (length == 0) { + state = state.create(buffer, seed); + length = 64; + } else { + // Mix this chunk into the current state and bump length up by 64. + state.mix(buffer); + length += 64; + } + // Reset the buffer_ptr to the head of the buffer for the next chunk of + // data. + buffer_ptr = buffer; + + // Try again to store into the buffer -- this cannot fail as we only + // store types smaller than the buffer. + if (!store_and_advance(buffer_ptr, buffer_end, data, + partial_store_size)) + abort(); + } + return buffer_ptr; + } + + /// \brief Recursive, variadic combining method. + /// + /// This function recurses through each argument, combining that argument + /// into a single hash. + template <typename T, typename ...Ts> + hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, + const T &arg, const Ts &...args) { + buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg)); + + // Recurse to the next argument. + return combine(length, buffer_ptr, buffer_end, args...); + } + + /// \brief Base case for recursive, variadic combining. + /// + /// The base case when combining arguments recursively is reached when all + /// arguments have been handled. It flushes the remaining buffer and + /// constructs a hash_code. + hash_code combine(size_t length, char *buffer_ptr, char *buffer_end) { + // Check whether the entire set of values fit in the buffer. If so, we'll + // use the optimized short hashing routine and skip state entirely. + if (length == 0) + return hash_short(buffer, buffer_ptr - buffer, seed); + + // Mix the final buffer, rotating it if we did a partial fill in order to + // simulate doing a mix of the last 64-bytes. That is how the algorithm + // works when we have a contiguous byte sequence, and we want to emulate + // that here. + std::rotate(buffer, buffer_ptr, buffer_end); + + // Mix this chunk into the current state. + state.mix(buffer); + length += buffer_ptr - buffer; + + return state.finalize(length); + } +}; + +} // namespace detail +} // namespace hashing + +/// \brief Combine values into a single hash_code. +/// +/// This routine accepts a varying number of arguments of any type. It will +/// attempt to combine them into a single hash_code. For user-defined types it +/// attempts to call a \see hash_value overload (via ADL) for the type. For +/// integer and pointer types it directly combines their data into the +/// resulting hash_code. +/// +/// The result is suitable for returning from a user's hash_value +/// *implementation* for their user-defined type. Consumers of a type should +/// *not* call this routine, they should instead call 'hash_value'. +template <typename ...Ts> hash_code hash_combine(const Ts &...args) { + // Recursively hash each argument using a helper class. + ::llvm::hashing::detail::hash_combine_recursive_helper helper; + return helper.combine(0, helper.buffer, helper.buffer + 64, args...); +} + +// Implementation details for implementations of hash_value overloads provided +// here. +namespace hashing { +namespace detail { + +/// \brief Helper to hash the value of a single integer. +/// +/// Overloads for smaller integer types are not provided to ensure consistent +/// behavior in the presence of integral promotions. Essentially, +/// "hash_value('4')" and "hash_value('0' + 4)" should be the same. +inline hash_code hash_integer_value(uint64_t value) { + // Similar to hash_4to8_bytes but using a seed instead of length. + const uint64_t seed = get_execution_seed(); + const char *s = reinterpret_cast<const char *>(&value); + const uint64_t a = fetch32(s); + return hash_16_bytes(seed + (a << 3), fetch32(s + 4)); +} + +} // namespace detail +} // namespace hashing + +// Declared and documented above, but defined here so that any of the hashing +// infrastructure is available. +template <typename T> +typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::type +hash_value(T value) { + return ::llvm::hashing::detail::hash_integer_value( + static_cast<uint64_t>(value)); +} + +// Declared and documented above, but defined here so that any of the hashing +// infrastructure is available. +template <typename T> hash_code hash_value(const T *ptr) { + return ::llvm::hashing::detail::hash_integer_value( + reinterpret_cast<uintptr_t>(ptr)); +} + +// Declared and documented above, but defined here so that any of the hashing +// infrastructure is available. +template <typename T, typename U> +hash_code hash_value(const std::pair<T, U> &arg) { + return hash_combine(arg.first, arg.second); +} + +// Declared and documented above, but defined here so that any of the hashing +// infrastructure is available. +template <typename T> +hash_code hash_value(const std::basic_string<T> &arg) { + return hash_combine_range(arg.begin(), arg.end()); +} + +} // namespace llvm + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/IntrusiveRefCntPtr.h b/third_party/llvm-subzero/include/llvm/ADT/IntrusiveRefCntPtr.h new file mode 100644 index 0000000..3417e9c --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/IntrusiveRefCntPtr.h
@@ -0,0 +1,288 @@ +//== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines IntrusiveRefCntPtr, a template class that +// implements a "smart" pointer for objects that maintain their own +// internal reference count, and RefCountedBase/RefCountedBaseVPTR, two +// generic base classes for objects that wish to have their lifetimes +// managed using reference counting. +// +// IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added +// LLVM-style casting. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H +#define LLVM_ADT_INTRUSIVEREFCNTPTR_H + +#include <atomic> +#include <cassert> +#include <cstddef> + +namespace llvm { + + template <class T> + class IntrusiveRefCntPtr; + +//===----------------------------------------------------------------------===// +/// RefCountedBase - A generic base class for objects that wish to +/// have their lifetimes managed using reference counts. Classes +/// subclass RefCountedBase to obtain such functionality, and are +/// typically handled with IntrusiveRefCntPtr "smart pointers" (see below) +/// which automatically handle the management of reference counts. +/// Objects that subclass RefCountedBase should not be allocated on +/// the stack, as invoking "delete" (which is called when the +/// reference count hits 0) on such objects is an error. +//===----------------------------------------------------------------------===// + template <class Derived> + class RefCountedBase { + mutable unsigned ref_cnt; + + public: + RefCountedBase() : ref_cnt(0) {} + RefCountedBase(const RefCountedBase &) : ref_cnt(0) {} + + void Retain() const { ++ref_cnt; } + void Release() const { + assert (ref_cnt > 0 && "Reference count is already zero."); + if (--ref_cnt == 0) delete static_cast<const Derived*>(this); + } + }; + +//===----------------------------------------------------------------------===// +/// RefCountedBaseVPTR - A class that has the same function as +/// RefCountedBase, but with a virtual destructor. Should be used +/// instead of RefCountedBase for classes that already have virtual +/// methods to enforce dynamic allocation via 'new'. Classes that +/// inherit from RefCountedBaseVPTR can't be allocated on stack - +/// attempting to do this will produce a compile error. +//===----------------------------------------------------------------------===// + class RefCountedBaseVPTR { + mutable unsigned ref_cnt; + virtual void anchor(); + + protected: + RefCountedBaseVPTR() : ref_cnt(0) {} + RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {} + + virtual ~RefCountedBaseVPTR() {} + + void Retain() const { ++ref_cnt; } + void Release() const { + assert (ref_cnt > 0 && "Reference count is already zero."); + if (--ref_cnt == 0) delete this; + } + + template <typename T> + friend struct IntrusiveRefCntPtrInfo; + }; + + + template <typename T> struct IntrusiveRefCntPtrInfo { + static void retain(T *obj) { obj->Retain(); } + static void release(T *obj) { obj->Release(); } + }; + +/// \brief A thread-safe version of \c llvm::RefCountedBase. +/// +/// A generic base class for objects that wish to have their lifetimes managed +/// using reference counts. Classes subclass \c ThreadSafeRefCountedBase to +/// obtain such functionality, and are typically handled with +/// \c IntrusiveRefCntPtr "smart pointers" which automatically handle the +/// management of reference counts. +template <class Derived> +class ThreadSafeRefCountedBase { + mutable std::atomic<int> RefCount; + +protected: + ThreadSafeRefCountedBase() : RefCount(0) {} + +public: + void Retain() const { RefCount.fetch_add(1, std::memory_order_relaxed); } + + void Release() const { + int NewRefCount = RefCount.fetch_sub(1, std::memory_order_acq_rel) - 1; + assert(NewRefCount >= 0 && "Reference count was already zero."); + if (NewRefCount == 0) + delete static_cast<const Derived*>(this); + } +}; + +//===----------------------------------------------------------------------===// +/// IntrusiveRefCntPtr - A template class that implements a "smart pointer" +/// that assumes the wrapped object has a reference count associated +/// with it that can be managed via calls to +/// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers +/// manage reference counts via the RAII idiom: upon creation of +/// smart pointer the reference count of the wrapped object is +/// incremented and upon destruction of the smart pointer the +/// reference count is decremented. This class also safely handles +/// wrapping NULL pointers. +/// +/// Reference counting is implemented via calls to +/// Obj->Retain()/Obj->Release(). Release() is required to destroy +/// the object when the reference count reaches zero. Inheriting from +/// RefCountedBase/RefCountedBaseVPTR takes care of this +/// automatically. +//===----------------------------------------------------------------------===// + template <typename T> + class IntrusiveRefCntPtr { + T* Obj; + + public: + typedef T element_type; + + explicit IntrusiveRefCntPtr() : Obj(nullptr) {} + + IntrusiveRefCntPtr(T* obj) : Obj(obj) { + retain(); + } + + IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) { + retain(); + } + + IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) { + S.Obj = nullptr; + } + + template <class X> + IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.get()) { + S.Obj = nullptr; + } + + template <class X> + IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S) + : Obj(S.get()) { + retain(); + } + + IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) { + swap(S); + return *this; + } + + ~IntrusiveRefCntPtr() { release(); } + + T& operator*() const { return *Obj; } + + T* operator->() const { return Obj; } + + T* get() const { return Obj; } + + explicit operator bool() const { return Obj; } + + void swap(IntrusiveRefCntPtr& other) { + T* tmp = other.Obj; + other.Obj = Obj; + Obj = tmp; + } + + void reset() { + release(); + Obj = nullptr; + } + + void resetWithoutRelease() { + Obj = nullptr; + } + + private: + void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); } + void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); } + + template <typename X> + friend class IntrusiveRefCntPtr; + }; + + template<class T, class U> + inline bool operator==(const IntrusiveRefCntPtr<T>& A, + const IntrusiveRefCntPtr<U>& B) + { + return A.get() == B.get(); + } + + template<class T, class U> + inline bool operator!=(const IntrusiveRefCntPtr<T>& A, + const IntrusiveRefCntPtr<U>& B) + { + return A.get() != B.get(); + } + + template<class T, class U> + inline bool operator==(const IntrusiveRefCntPtr<T>& A, + U* B) + { + return A.get() == B; + } + + template<class T, class U> + inline bool operator!=(const IntrusiveRefCntPtr<T>& A, + U* B) + { + return A.get() != B; + } + + template<class T, class U> + inline bool operator==(T* A, + const IntrusiveRefCntPtr<U>& B) + { + return A == B.get(); + } + + template<class T, class U> + inline bool operator!=(T* A, + const IntrusiveRefCntPtr<U>& B) + { + return A != B.get(); + } + + template <class T> + bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { + return !B; + } + + template <class T> + bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { + return B == A; + } + + template <class T> + bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { + return !(A == B); + } + + template <class T> + bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { + return !(A == B); + } + +//===----------------------------------------------------------------------===// +// LLVM-style downcasting support for IntrusiveRefCntPtr objects +//===----------------------------------------------------------------------===// + + template <typename From> struct simplify_type; + + template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > { + typedef T* SimpleType; + static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) { + return Val.get(); + } + }; + + template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > { + typedef /*const*/ T* SimpleType; + static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) { + return Val.get(); + } + }; + +} // end namespace llvm + +#endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/None.h b/third_party/llvm-subzero/include/llvm/ADT/None.h new file mode 100644 index 0000000..d69ec17 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/None.h
@@ -0,0 +1,26 @@ +//===-- None.h - Simple null value for implicit construction ------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides None, an enumerator for use in implicit constructors +// of various (usually templated) types to make such construction more +// terse. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_NONE_H +#define LLVM_ADT_NONE_H + +namespace llvm { +/// \brief A simple null object to allow implicit construction of Optional<T> +/// and similar types without having to spell out the specialization's name. +enum class NoneType { None }; +const NoneType None = None; +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/Optional.h b/third_party/llvm-subzero/include/llvm/ADT/Optional.h new file mode 100644 index 0000000..20568c5 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/Optional.h
@@ -0,0 +1,289 @@ +//===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Optional, a template class modeled in the spirit of +// OCaml's 'opt' variant. The idea is to strongly type whether or not +// a value can be optional. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_OPTIONAL_H +#define LLVM_ADT_OPTIONAL_H + +#include "llvm/ADT/None.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/Compiler.h" +#include <cassert> +#include <new> +#include <utility> + +namespace llvm { + +template<typename T> +class Optional { + AlignedCharArrayUnion<T> storage; + bool hasVal; +public: + typedef T value_type; + + Optional(NoneType) : hasVal(false) {} + explicit Optional() : hasVal(false) {} + Optional(const T &y) : hasVal(true) { + new (storage.buffer) T(y); + } + Optional(const Optional &O) : hasVal(O.hasVal) { + if (hasVal) + new (storage.buffer) T(*O); + } + + Optional(T &&y) : hasVal(true) { + new (storage.buffer) T(std::forward<T>(y)); + } + Optional(Optional<T> &&O) : hasVal(O) { + if (O) { + new (storage.buffer) T(std::move(*O)); + O.reset(); + } + } + Optional &operator=(T &&y) { + if (hasVal) + **this = std::move(y); + else { + new (storage.buffer) T(std::move(y)); + hasVal = true; + } + return *this; + } + Optional &operator=(Optional &&O) { + if (!O) + reset(); + else { + *this = std::move(*O); + O.reset(); + } + return *this; + } + + /// Create a new object by constructing it in place with the given arguments. + template<typename ...ArgTypes> + void emplace(ArgTypes &&...Args) { + reset(); + hasVal = true; + new (storage.buffer) T(std::forward<ArgTypes>(Args)...); + } + + static inline Optional create(const T* y) { + return y ? Optional(*y) : Optional(); + } + + // FIXME: these assignments (& the equivalent const T&/const Optional& ctors) + // could be made more efficient by passing by value, possibly unifying them + // with the rvalue versions above - but this could place a different set of + // requirements (notably: the existence of a default ctor) when implemented + // in that way. Careful SFINAE to avoid such pitfalls would be required. + Optional &operator=(const T &y) { + if (hasVal) + **this = y; + else { + new (storage.buffer) T(y); + hasVal = true; + } + return *this; + } + + Optional &operator=(const Optional &O) { + if (!O) + reset(); + else + *this = *O; + return *this; + } + + void reset() { + if (hasVal) { + (**this).~T(); + hasVal = false; + } + } + + ~Optional() { + reset(); + } + + const T* getPointer() const { assert(hasVal); return reinterpret_cast<const T*>(storage.buffer); } + T* getPointer() { assert(hasVal); return reinterpret_cast<T*>(storage.buffer); } + const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } + T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } + + explicit operator bool() const { return hasVal; } + bool hasValue() const { return hasVal; } + const T* operator->() const { return getPointer(); } + T* operator->() { return getPointer(); } + const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } + T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } + + template <typename U> + LLVM_CONSTEXPR T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION { + return hasValue() ? getValue() : std::forward<U>(value); + } + +#if LLVM_HAS_RVALUE_REFERENCE_THIS + T&& getValue() && { assert(hasVal); return std::move(*getPointer()); } + T&& operator*() && { assert(hasVal); return std::move(*getPointer()); } + + template <typename U> + T getValueOr(U &&value) && { + return hasValue() ? std::move(getValue()) : std::forward<U>(value); + } +#endif +}; + +template <typename T> struct isPodLike; +template <typename T> struct isPodLike<Optional<T> > { + // An Optional<T> is pod-like if T is. + static const bool value = isPodLike<T>::value; +}; + +template <typename T, typename U> +bool operator==(const Optional<T> &X, const Optional<U> &Y) { + if (X && Y) + return *X == *Y; + return X.hasValue() == Y.hasValue(); +} + +template <typename T, typename U> +bool operator!=(const Optional<T> &X, const Optional<U> &Y) { + return !(X == Y); +} + +template <typename T, typename U> +bool operator<(const Optional<T> &X, const Optional<U> &Y) { + if (X && Y) + return *X < *Y; + return X.hasValue() < Y.hasValue(); +} + +template <typename T, typename U> +bool operator<=(const Optional<T> &X, const Optional<U> &Y) { + return !(Y < X); +} + +template <typename T, typename U> +bool operator>(const Optional<T> &X, const Optional<U> &Y) { + return Y < X; +} + +template <typename T, typename U> +bool operator>=(const Optional<T> &X, const Optional<U> &Y) { + return !(X < Y); +} + +template<typename T> +bool operator==(const Optional<T> &X, NoneType) { + return !X; +} + +template<typename T> +bool operator==(NoneType, const Optional<T> &X) { + return X == None; +} + +template<typename T> +bool operator!=(const Optional<T> &X, NoneType) { + return !(X == None); +} + +template<typename T> +bool operator!=(NoneType, const Optional<T> &X) { + return X != None; +} + +template <typename T> bool operator<(const Optional<T> &X, NoneType) { + return false; +} + +template <typename T> bool operator<(NoneType, const Optional<T> &X) { + return X.hasValue(); +} + +template <typename T> bool operator<=(const Optional<T> &X, NoneType) { + return !(None < X); +} + +template <typename T> bool operator<=(NoneType, const Optional<T> &X) { + return !(X < None); +} + +template <typename T> bool operator>(const Optional<T> &X, NoneType) { + return None < X; +} + +template <typename T> bool operator>(NoneType, const Optional<T> &X) { + return X < None; +} + +template <typename T> bool operator>=(const Optional<T> &X, NoneType) { + return None <= X; +} + +template <typename T> bool operator>=(NoneType, const Optional<T> &X) { + return X <= None; +} + +template <typename T> bool operator==(const Optional<T> &X, const T &Y) { + return X && *X == Y; +} + +template <typename T> bool operator==(const T &X, const Optional<T> &Y) { + return Y && X == *Y; +} + +template <typename T> bool operator!=(const Optional<T> &X, const T &Y) { + return !(X == Y); +} + +template <typename T> bool operator!=(const T &X, const Optional<T> &Y) { + return !(X == Y); +} + +template <typename T> bool operator<(const Optional<T> &X, const T &Y) { + return !X || *X < Y; +} + +template <typename T> bool operator<(const T &X, const Optional<T> &Y) { + return Y && X < *Y; +} + +template <typename T> bool operator<=(const Optional<T> &X, const T &Y) { + return !(Y < X); +} + +template <typename T> bool operator<=(const T &X, const Optional<T> &Y) { + return !(Y < X); +} + +template <typename T> bool operator>(const Optional<T> &X, const T &Y) { + return Y < X; +} + +template <typename T> bool operator>(const T &X, const Optional<T> &Y) { + return Y < X; +} + +template <typename T> bool operator>=(const Optional<T> &X, const T &Y) { + return !(X < Y); +} + +template <typename T> bool operator>=(const T &X, const Optional<T> &Y) { + return !(X < Y); +} + +} // end llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/PointerIntPair.h b/third_party/llvm-subzero/include/llvm/ADT/PointerIntPair.h new file mode 100644 index 0000000..83fbf12 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/PointerIntPair.h
@@ -0,0 +1,223 @@ +//===- llvm/ADT/PointerIntPair.h - Pair for pointer and int -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PointerIntPair class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POINTERINTPAIR_H +#define LLVM_ADT_POINTERINTPAIR_H + +#include "llvm/Support/Compiler.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include <cassert> +#include <limits> + +namespace llvm { + +template <typename T> struct DenseMapInfo; + +template <typename PointerT, unsigned IntBits, typename PtrTraits> +struct PointerIntPairInfo; + +/// PointerIntPair - This class implements a pair of a pointer and small +/// integer. It is designed to represent this in the space required by one +/// pointer by bitmangling the integer into the low part of the pointer. This +/// can only be done for small integers: typically up to 3 bits, but it depends +/// on the number of bits available according to PointerLikeTypeTraits for the +/// type. +/// +/// Note that PointerIntPair always puts the IntVal part in the highest bits +/// possible. For example, PointerIntPair<void*, 1, bool> will put the bit for +/// the bool into bit #2, not bit #0, which allows the low two bits to be used +/// for something else. For example, this allows: +/// PointerIntPair<PointerIntPair<void*, 1, bool>, 1, bool> +/// ... and the two bools will land in different bits. +/// +template <typename PointerTy, unsigned IntBits, typename IntType = unsigned, + typename PtrTraits = PointerLikeTypeTraits<PointerTy>, + typename Info = PointerIntPairInfo<PointerTy, IntBits, PtrTraits>> +class PointerIntPair { + intptr_t Value; + +public: + PointerIntPair() : Value(0) {} + PointerIntPair(PointerTy PtrVal, IntType IntVal) { + setPointerAndInt(PtrVal, IntVal); + } + explicit PointerIntPair(PointerTy PtrVal) { initWithPointer(PtrVal); } + + PointerTy getPointer() const { return Info::getPointer(Value); } + + IntType getInt() const { + return (IntType)Info::getInt(Value); + } + + void setPointer(PointerTy PtrVal) { + Value = Info::updatePointer(Value, PtrVal); + } + + void setInt(IntType IntVal) { + Value = Info::updateInt(Value, static_cast<intptr_t>(IntVal)); + } + + void initWithPointer(PointerTy PtrVal) { + Value = Info::updatePointer(0, PtrVal); + } + + void setPointerAndInt(PointerTy PtrVal, IntType IntVal) { + Value = Info::updateInt(Info::updatePointer(0, PtrVal), + static_cast<intptr_t>(IntVal)); + } + + PointerTy const *getAddrOfPointer() const { + return const_cast<PointerIntPair *>(this)->getAddrOfPointer(); + } + + PointerTy *getAddrOfPointer() { + assert(Value == reinterpret_cast<intptr_t>(getPointer()) && + "Can only return the address if IntBits is cleared and " + "PtrTraits doesn't change the pointer"); + return reinterpret_cast<PointerTy *>(&Value); + } + + void *getOpaqueValue() const { return reinterpret_cast<void *>(Value); } + void setFromOpaqueValue(void *Val) { + Value = reinterpret_cast<intptr_t>(Val); + } + + static PointerIntPair getFromOpaqueValue(void *V) { + PointerIntPair P; + P.setFromOpaqueValue(V); + return P; + } + + // Allow PointerIntPairs to be created from const void * if and only if the + // pointer type could be created from a const void *. + static PointerIntPair getFromOpaqueValue(const void *V) { + (void)PtrTraits::getFromVoidPointer(V); + return getFromOpaqueValue(const_cast<void *>(V)); + } + + bool operator==(const PointerIntPair &RHS) const { + return Value == RHS.Value; + } + bool operator!=(const PointerIntPair &RHS) const { + return Value != RHS.Value; + } + bool operator<(const PointerIntPair &RHS) const { return Value < RHS.Value; } + bool operator>(const PointerIntPair &RHS) const { return Value > RHS.Value; } + bool operator<=(const PointerIntPair &RHS) const { + return Value <= RHS.Value; + } + bool operator>=(const PointerIntPair &RHS) const { + return Value >= RHS.Value; + } +}; + +template <typename PointerT, unsigned IntBits, typename PtrTraits> +struct PointerIntPairInfo { + static_assert(PtrTraits::NumLowBitsAvailable < + std::numeric_limits<uintptr_t>::digits, + "cannot use a pointer type that has all bits free"); + static_assert(IntBits <= PtrTraits::NumLowBitsAvailable, + "PointerIntPair with integer size too large for pointer"); + enum : uintptr_t { + /// PointerBitMask - The bits that come from the pointer. + PointerBitMask = + ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable) - 1), + + /// IntShift - The number of low bits that we reserve for other uses, and + /// keep zero. + IntShift = (uintptr_t)PtrTraits::NumLowBitsAvailable - IntBits, + + /// IntMask - This is the unshifted mask for valid bits of the int type. + IntMask = (uintptr_t)(((intptr_t)1 << IntBits) - 1), + + // ShiftedIntMask - This is the bits for the integer shifted in place. + ShiftedIntMask = (uintptr_t)(IntMask << IntShift) + }; + + static PointerT getPointer(intptr_t Value) { + return PtrTraits::getFromVoidPointer( + reinterpret_cast<void *>(Value & PointerBitMask)); + } + + static intptr_t getInt(intptr_t Value) { + return (Value >> IntShift) & IntMask; + } + + static intptr_t updatePointer(intptr_t OrigValue, PointerT Ptr) { + intptr_t PtrWord = + reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(Ptr)); + assert((PtrWord & ~PointerBitMask) == 0 && + "Pointer is not sufficiently aligned"); + // Preserve all low bits, just update the pointer. + return PtrWord | (OrigValue & ~PointerBitMask); + } + + static intptr_t updateInt(intptr_t OrigValue, intptr_t Int) { + intptr_t IntWord = static_cast<intptr_t>(Int); + assert((IntWord & ~IntMask) == 0 && "Integer too large for field"); + + // Preserve all bits other than the ones we are updating. + return (OrigValue & ~ShiftedIntMask) | IntWord << IntShift; + } +}; + +template <typename T> struct isPodLike; +template <typename PointerTy, unsigned IntBits, typename IntType> +struct isPodLike<PointerIntPair<PointerTy, IntBits, IntType>> { + static const bool value = true; +}; + +// Provide specialization of DenseMapInfo for PointerIntPair. +template <typename PointerTy, unsigned IntBits, typename IntType> +struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType>> { + typedef PointerIntPair<PointerTy, IntBits, IntType> Ty; + static Ty getEmptyKey() { + uintptr_t Val = static_cast<uintptr_t>(-1); + Val <<= PointerLikeTypeTraits<Ty>::NumLowBitsAvailable; + return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val)); + } + static Ty getTombstoneKey() { + uintptr_t Val = static_cast<uintptr_t>(-2); + Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable; + return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val)); + } + static unsigned getHashValue(Ty V) { + uintptr_t IV = reinterpret_cast<uintptr_t>(V.getOpaqueValue()); + return unsigned(IV) ^ unsigned(IV >> 9); + } + static bool isEqual(const Ty &LHS, const Ty &RHS) { return LHS == RHS; } +}; + +// Teach SmallPtrSet that PointerIntPair is "basically a pointer". +template <typename PointerTy, unsigned IntBits, typename IntType, + typename PtrTraits> +class PointerLikeTypeTraits< + PointerIntPair<PointerTy, IntBits, IntType, PtrTraits>> { +public: + static inline void * + getAsVoidPointer(const PointerIntPair<PointerTy, IntBits, IntType> &P) { + return P.getOpaqueValue(); + } + static inline PointerIntPair<PointerTy, IntBits, IntType> + getFromVoidPointer(void *P) { + return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P); + } + static inline PointerIntPair<PointerTy, IntBits, IntType> + getFromVoidPointer(const void *P) { + return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P); + } + enum { NumLowBitsAvailable = PtrTraits::NumLowBitsAvailable - IntBits }; +}; + +} // end namespace llvm +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/PointerUnion.h b/third_party/llvm-subzero/include/llvm/ADT/PointerUnion.h new file mode 100644 index 0000000..6b3fe57 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/PointerUnion.h
@@ -0,0 +1,474 @@ +//===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PointerUnion class, which is a discriminated union of +// pointer types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POINTERUNION_H +#define LLVM_ADT_POINTERUNION_H + +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +template <typename T> struct PointerUnionTypeSelectorReturn { + typedef T Return; +}; + +/// Get a type based on whether two types are the same or not. +/// +/// For: +/// +/// \code +/// typedef typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return Ret; +/// \endcode +/// +/// Ret will be EQ type if T1 is same as T2 or NE type otherwise. +template <typename T1, typename T2, typename RET_EQ, typename RET_NE> +struct PointerUnionTypeSelector { + typedef typename PointerUnionTypeSelectorReturn<RET_NE>::Return Return; +}; + +template <typename T, typename RET_EQ, typename RET_NE> +struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> { + typedef typename PointerUnionTypeSelectorReturn<RET_EQ>::Return Return; +}; + +template <typename T1, typename T2, typename RET_EQ, typename RET_NE> +struct PointerUnionTypeSelectorReturn< + PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>> { + typedef + typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return Return; +}; + +/// Provide PointerLikeTypeTraits for void* that is used by PointerUnion +/// for the two template arguments. +template <typename PT1, typename PT2> class PointerUnionUIntTraits { +public: + static inline void *getAsVoidPointer(void *P) { return P; } + static inline void *getFromVoidPointer(void *P) { return P; } + enum { + PT1BitsAv = (int)(PointerLikeTypeTraits<PT1>::NumLowBitsAvailable), + PT2BitsAv = (int)(PointerLikeTypeTraits<PT2>::NumLowBitsAvailable), + NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv + }; +}; + +/// A discriminated union of two pointer types, with the discriminator in the +/// low bit of the pointer. +/// +/// This implementation is extremely efficient in space due to leveraging the +/// low bits of the pointer, while exposing a natural and type-safe API. +/// +/// Common use patterns would be something like this: +/// PointerUnion<int*, float*> P; +/// P = (int*)0; +/// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0" +/// X = P.get<int*>(); // ok. +/// Y = P.get<float*>(); // runtime assertion failure. +/// Z = P.get<double*>(); // compile time failure. +/// P = (float*)0; +/// Y = P.get<float*>(); // ok. +/// X = P.get<int*>(); // runtime assertion failure. +template <typename PT1, typename PT2> class PointerUnion { +public: + typedef PointerIntPair<void *, 1, bool, PointerUnionUIntTraits<PT1, PT2>> + ValTy; + +private: + ValTy Val; + + struct IsPT1 { + static const int Num = 0; + }; + struct IsPT2 { + static const int Num = 1; + }; + template <typename T> struct UNION_DOESNT_CONTAIN_TYPE {}; + +public: + PointerUnion() {} + + PointerUnion(PT1 V) + : Val(const_cast<void *>( + PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {} + PointerUnion(PT2 V) + : Val(const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), + 1) {} + + /// Test if the pointer held in the union is null, regardless of + /// which type it is. + bool isNull() const { + // Convert from the void* to one of the pointer types, to make sure that + // we recursively strip off low bits if we have a nested PointerUnion. + return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer()); + } + explicit operator bool() const { return !isNull(); } + + /// Test if the Union currently holds the type matching T. + template <typename T> int is() const { + typedef typename ::llvm::PointerUnionTypeSelector< + PT1, T, IsPT1, ::llvm::PointerUnionTypeSelector< + PT2, T, IsPT2, UNION_DOESNT_CONTAIN_TYPE<T>>>::Return + Ty; + int TyNo = Ty::Num; + return static_cast<int>(Val.getInt()) == TyNo; + } + + /// Returns the value of the specified pointer type. + /// + /// If the specified pointer type is incorrect, assert. + template <typename T> T get() const { + assert(is<T>() && "Invalid accessor called"); + return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer()); + } + + /// Returns the current pointer if it is of the specified pointer type, + /// otherwises returns null. + template <typename T> T dyn_cast() const { + if (is<T>()) + return get<T>(); + return T(); + } + + /// If the union is set to the first pointer type get an address pointing to + /// it. + PT1 const *getAddrOfPtr1() const { + return const_cast<PointerUnion *>(this)->getAddrOfPtr1(); + } + + /// If the union is set to the first pointer type get an address pointing to + /// it. + PT1 *getAddrOfPtr1() { + assert(is<PT1>() && "Val is not the first pointer"); + assert( + get<PT1>() == Val.getPointer() && + "Can't get the address because PointerLikeTypeTraits changes the ptr"); + return (PT1 *)Val.getAddrOfPointer(); + } + + /// Assignment from nullptr which just clears the union. + const PointerUnion &operator=(std::nullptr_t) { + Val.initWithPointer(nullptr); + return *this; + } + + /// Assignment operators - Allow assigning into this union from either + /// pointer type, setting the discriminator to remember what it came from. + const PointerUnion &operator=(const PT1 &RHS) { + Val.initWithPointer( + const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS))); + return *this; + } + const PointerUnion &operator=(const PT2 &RHS) { + Val.setPointerAndInt( + const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)), + 1); + return *this; + } + + void *getOpaqueValue() const { return Val.getOpaqueValue(); } + static inline PointerUnion getFromOpaqueValue(void *VP) { + PointerUnion V; + V.Val = ValTy::getFromOpaqueValue(VP); + return V; + } +}; + +template <typename PT1, typename PT2> +static bool operator==(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) { + return lhs.getOpaqueValue() == rhs.getOpaqueValue(); +} + +template <typename PT1, typename PT2> +static bool operator!=(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) { + return lhs.getOpaqueValue() != rhs.getOpaqueValue(); +} + +template <typename PT1, typename PT2> +static bool operator<(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) { + return lhs.getOpaqueValue() < rhs.getOpaqueValue(); +} + +// Teach SmallPtrSet that PointerUnion is "basically a pointer", that has +// # low bits available = min(PT1bits,PT2bits)-1. +template <typename PT1, typename PT2> +class PointerLikeTypeTraits<PointerUnion<PT1, PT2>> { +public: + static inline void *getAsVoidPointer(const PointerUnion<PT1, PT2> &P) { + return P.getOpaqueValue(); + } + static inline PointerUnion<PT1, PT2> getFromVoidPointer(void *P) { + return PointerUnion<PT1, PT2>::getFromOpaqueValue(P); + } + + // The number of bits available are the min of the two pointer types. + enum { + NumLowBitsAvailable = PointerLikeTypeTraits< + typename PointerUnion<PT1, PT2>::ValTy>::NumLowBitsAvailable + }; +}; + +/// A pointer union of three pointer types. See documentation for PointerUnion +/// for usage. +template <typename PT1, typename PT2, typename PT3> class PointerUnion3 { +public: + typedef PointerUnion<PT1, PT2> InnerUnion; + typedef PointerUnion<InnerUnion, PT3> ValTy; + +private: + ValTy Val; + + struct IsInnerUnion { + ValTy Val; + IsInnerUnion(ValTy val) : Val(val) {} + template <typename T> int is() const { + return Val.template is<InnerUnion>() && + Val.template get<InnerUnion>().template is<T>(); + } + template <typename T> T get() const { + return Val.template get<InnerUnion>().template get<T>(); + } + }; + + struct IsPT3 { + ValTy Val; + IsPT3(ValTy val) : Val(val) {} + template <typename T> int is() const { return Val.template is<T>(); } + template <typename T> T get() const { return Val.template get<T>(); } + }; + +public: + PointerUnion3() {} + + PointerUnion3(PT1 V) { Val = InnerUnion(V); } + PointerUnion3(PT2 V) { Val = InnerUnion(V); } + PointerUnion3(PT3 V) { Val = V; } + + /// Test if the pointer held in the union is null, regardless of + /// which type it is. + bool isNull() const { return Val.isNull(); } + explicit operator bool() const { return !isNull(); } + + /// Test if the Union currently holds the type matching T. + template <typename T> int is() const { + // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3. + typedef typename ::llvm::PointerUnionTypeSelector< + PT1, T, IsInnerUnion, + ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3>>::Return + Ty; + return Ty(Val).template is<T>(); + } + + /// Returns the value of the specified pointer type. + /// + /// If the specified pointer type is incorrect, assert. + template <typename T> T get() const { + assert(is<T>() && "Invalid accessor called"); + // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3. + typedef typename ::llvm::PointerUnionTypeSelector< + PT1, T, IsInnerUnion, + ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3>>::Return + Ty; + return Ty(Val).template get<T>(); + } + + /// Returns the current pointer if it is of the specified pointer type, + /// otherwises returns null. + template <typename T> T dyn_cast() const { + if (is<T>()) + return get<T>(); + return T(); + } + + /// Assignment from nullptr which just clears the union. + const PointerUnion3 &operator=(std::nullptr_t) { + Val = nullptr; + return *this; + } + + /// Assignment operators - Allow assigning into this union from either + /// pointer type, setting the discriminator to remember what it came from. + const PointerUnion3 &operator=(const PT1 &RHS) { + Val = InnerUnion(RHS); + return *this; + } + const PointerUnion3 &operator=(const PT2 &RHS) { + Val = InnerUnion(RHS); + return *this; + } + const PointerUnion3 &operator=(const PT3 &RHS) { + Val = RHS; + return *this; + } + + void *getOpaqueValue() const { return Val.getOpaqueValue(); } + static inline PointerUnion3 getFromOpaqueValue(void *VP) { + PointerUnion3 V; + V.Val = ValTy::getFromOpaqueValue(VP); + return V; + } +}; + +// Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has +// # low bits available = min(PT1bits,PT2bits,PT2bits)-2. +template <typename PT1, typename PT2, typename PT3> +class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3>> { +public: + static inline void *getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) { + return P.getOpaqueValue(); + } + static inline PointerUnion3<PT1, PT2, PT3> getFromVoidPointer(void *P) { + return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P); + } + + // The number of bits available are the min of the two pointer types. + enum { + NumLowBitsAvailable = PointerLikeTypeTraits< + typename PointerUnion3<PT1, PT2, PT3>::ValTy>::NumLowBitsAvailable + }; +}; + +/// A pointer union of four pointer types. See documentation for PointerUnion +/// for usage. +template <typename PT1, typename PT2, typename PT3, typename PT4> +class PointerUnion4 { +public: + typedef PointerUnion<PT1, PT2> InnerUnion1; + typedef PointerUnion<PT3, PT4> InnerUnion2; + typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy; + +private: + ValTy Val; + +public: + PointerUnion4() {} + + PointerUnion4(PT1 V) { Val = InnerUnion1(V); } + PointerUnion4(PT2 V) { Val = InnerUnion1(V); } + PointerUnion4(PT3 V) { Val = InnerUnion2(V); } + PointerUnion4(PT4 V) { Val = InnerUnion2(V); } + + /// Test if the pointer held in the union is null, regardless of + /// which type it is. + bool isNull() const { return Val.isNull(); } + explicit operator bool() const { return !isNull(); } + + /// Test if the Union currently holds the type matching T. + template <typename T> int is() const { + // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2. + typedef typename ::llvm::PointerUnionTypeSelector< + PT1, T, InnerUnion1, ::llvm::PointerUnionTypeSelector< + PT2, T, InnerUnion1, InnerUnion2>>::Return Ty; + return Val.template is<Ty>() && Val.template get<Ty>().template is<T>(); + } + + /// Returns the value of the specified pointer type. + /// + /// If the specified pointer type is incorrect, assert. + template <typename T> T get() const { + assert(is<T>() && "Invalid accessor called"); + // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2. + typedef typename ::llvm::PointerUnionTypeSelector< + PT1, T, InnerUnion1, ::llvm::PointerUnionTypeSelector< + PT2, T, InnerUnion1, InnerUnion2>>::Return Ty; + return Val.template get<Ty>().template get<T>(); + } + + /// Returns the current pointer if it is of the specified pointer type, + /// otherwises returns null. + template <typename T> T dyn_cast() const { + if (is<T>()) + return get<T>(); + return T(); + } + + /// Assignment from nullptr which just clears the union. + const PointerUnion4 &operator=(std::nullptr_t) { + Val = nullptr; + return *this; + } + + /// Assignment operators - Allow assigning into this union from either + /// pointer type, setting the discriminator to remember what it came from. + const PointerUnion4 &operator=(const PT1 &RHS) { + Val = InnerUnion1(RHS); + return *this; + } + const PointerUnion4 &operator=(const PT2 &RHS) { + Val = InnerUnion1(RHS); + return *this; + } + const PointerUnion4 &operator=(const PT3 &RHS) { + Val = InnerUnion2(RHS); + return *this; + } + const PointerUnion4 &operator=(const PT4 &RHS) { + Val = InnerUnion2(RHS); + return *this; + } + + void *getOpaqueValue() const { return Val.getOpaqueValue(); } + static inline PointerUnion4 getFromOpaqueValue(void *VP) { + PointerUnion4 V; + V.Val = ValTy::getFromOpaqueValue(VP); + return V; + } +}; + +// Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has +// # low bits available = min(PT1bits,PT2bits,PT2bits)-2. +template <typename PT1, typename PT2, typename PT3, typename PT4> +class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4>> { +public: + static inline void * + getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) { + return P.getOpaqueValue(); + } + static inline PointerUnion4<PT1, PT2, PT3, PT4> getFromVoidPointer(void *P) { + return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P); + } + + // The number of bits available are the min of the two pointer types. + enum { + NumLowBitsAvailable = PointerLikeTypeTraits< + typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>::NumLowBitsAvailable + }; +}; + +// Teach DenseMap how to use PointerUnions as keys. +template <typename T, typename U> struct DenseMapInfo<PointerUnion<T, U>> { + typedef PointerUnion<T, U> Pair; + typedef DenseMapInfo<T> FirstInfo; + typedef DenseMapInfo<U> SecondInfo; + + static inline Pair getEmptyKey() { return Pair(FirstInfo::getEmptyKey()); } + static inline Pair getTombstoneKey() { + return Pair(FirstInfo::getTombstoneKey()); + } + static unsigned getHashValue(const Pair &PairVal) { + intptr_t key = (intptr_t)PairVal.getOpaqueValue(); + return DenseMapInfo<intptr_t>::getHashValue(key); + } + static bool isEqual(const Pair &LHS, const Pair &RHS) { + return LHS.template is<T>() == RHS.template is<T>() && + (LHS.template is<T>() ? FirstInfo::isEqual(LHS.template get<T>(), + RHS.template get<T>()) + : SecondInfo::isEqual(LHS.template get<U>(), + RHS.template get<U>())); + } +}; + +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/STLExtras.h b/third_party/llvm-subzero/include/llvm/ADT/STLExtras.h new file mode 100644 index 0000000..e6215e4 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/STLExtras.h
@@ -0,0 +1,631 @@ +//===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some templates that are useful if you are working with the +// STL at all. +// +// No library is required when using these functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STLEXTRAS_H +#define LLVM_ADT_STLEXTRAS_H + +#include <algorithm> // for std::all_of +#include <cassert> +#include <cstddef> // for std::size_t +#include <cstdlib> // for qsort +#include <functional> +#include <iterator> +#include <memory> +#include <utility> // for std::pair + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { +namespace detail { + +template <typename RangeT> +using IterOfRange = decltype(std::begin(std::declval<RangeT>())); + +} // End detail namespace + +//===----------------------------------------------------------------------===// +// Extra additions to <functional> +//===----------------------------------------------------------------------===// + +template<class Ty> +struct identity : public std::unary_function<Ty, Ty> { + Ty &operator()(Ty &self) const { + return self; + } + const Ty &operator()(const Ty &self) const { + return self; + } +}; + +template<class Ty> +struct less_ptr : public std::binary_function<Ty, Ty, bool> { + bool operator()(const Ty* left, const Ty* right) const { + return *left < *right; + } +}; + +template<class Ty> +struct greater_ptr : public std::binary_function<Ty, Ty, bool> { + bool operator()(const Ty* left, const Ty* right) const { + return *right < *left; + } +}; + +/// An efficient, type-erasing, non-owning reference to a callable. This is +/// intended for use as the type of a function parameter that is not used +/// after the function in question returns. +/// +/// This class does not own the callable, so it is not in general safe to store +/// a function_ref. +template<typename Fn> class function_ref; + +template<typename Ret, typename ...Params> +class function_ref<Ret(Params...)> { + Ret (*callback)(intptr_t callable, Params ...params); + intptr_t callable; + + template<typename Callable> + static Ret callback_fn(intptr_t callable, Params ...params) { + return (*reinterpret_cast<Callable*>(callable))( + std::forward<Params>(params)...); + } + +public: + template <typename Callable> + function_ref(Callable &&callable, + typename std::enable_if< + !std::is_same<typename std::remove_reference<Callable>::type, + function_ref>::value>::type * = nullptr) + : callback(callback_fn<typename std::remove_reference<Callable>::type>), + callable(reinterpret_cast<intptr_t>(&callable)) {} + Ret operator()(Params ...params) const { + return callback(callable, std::forward<Params>(params)...); + } +}; + +// deleter - Very very very simple method that is used to invoke operator +// delete on something. It is used like this: +// +// for_each(V.begin(), B.end(), deleter<Interval>); +// +template <class T> +inline void deleter(T *Ptr) { + delete Ptr; +} + + + +//===----------------------------------------------------------------------===// +// Extra additions to <iterator> +//===----------------------------------------------------------------------===// + +// mapped_iterator - This is a simple iterator adapter that causes a function to +// be dereferenced whenever operator* is invoked on the iterator. +// +template <class RootIt, class UnaryFunc> +class mapped_iterator { + RootIt current; + UnaryFunc Fn; +public: + typedef typename std::iterator_traits<RootIt>::iterator_category + iterator_category; + typedef typename std::iterator_traits<RootIt>::difference_type + difference_type; + typedef typename std::result_of< + UnaryFunc(decltype(*std::declval<RootIt>()))> + ::type value_type; + + typedef void pointer; + //typedef typename UnaryFunc::result_type *pointer; + typedef void reference; // Can't modify value returned by fn + + typedef RootIt iterator_type; + + inline const RootIt &getCurrent() const { return current; } + inline const UnaryFunc &getFunc() const { return Fn; } + + inline explicit mapped_iterator(const RootIt &I, UnaryFunc F) + : current(I), Fn(F) {} + + inline value_type operator*() const { // All this work to do this + return Fn(*current); // little change + } + + mapped_iterator &operator++() { + ++current; + return *this; + } + mapped_iterator &operator--() { + --current; + return *this; + } + mapped_iterator operator++(int) { + mapped_iterator __tmp = *this; + ++current; + return __tmp; + } + mapped_iterator operator--(int) { + mapped_iterator __tmp = *this; + --current; + return __tmp; + } + mapped_iterator operator+(difference_type n) const { + return mapped_iterator(current + n, Fn); + } + mapped_iterator &operator+=(difference_type n) { + current += n; + return *this; + } + mapped_iterator operator-(difference_type n) const { + return mapped_iterator(current - n, Fn); + } + mapped_iterator &operator-=(difference_type n) { + current -= n; + return *this; + } + reference operator[](difference_type n) const { return *(*this + n); } + + bool operator!=(const mapped_iterator &X) const { return !operator==(X); } + bool operator==(const mapped_iterator &X) const { + return current == X.current; + } + bool operator<(const mapped_iterator &X) const { return current < X.current; } + + difference_type operator-(const mapped_iterator &X) const { + return current - X.current; + } +}; + +template <class Iterator, class Func> +inline mapped_iterator<Iterator, Func> +operator+(typename mapped_iterator<Iterator, Func>::difference_type N, + const mapped_iterator<Iterator, Func> &X) { + return mapped_iterator<Iterator, Func>(X.getCurrent() - N, X.getFunc()); +} + + +// map_iterator - Provide a convenient way to create mapped_iterators, just like +// make_pair is useful for creating pairs... +// +template <class ItTy, class FuncTy> +inline mapped_iterator<ItTy, FuncTy> map_iterator(const ItTy &I, FuncTy F) { + return mapped_iterator<ItTy, FuncTy>(I, F); +} + +/// Helper to determine if type T has a member called rbegin(). +template <typename Ty> class has_rbegin_impl { + typedef char yes[1]; + typedef char no[2]; + + template <typename Inner> + static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr); + + template <typename> + static no& test(...); + +public: + static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes); +}; + +/// Metafunction to determine if T& or T has a member called rbegin(). +template <typename Ty> +struct has_rbegin : has_rbegin_impl<typename std::remove_reference<Ty>::type> { +}; + +// Returns an iterator_range over the given container which iterates in reverse. +// Note that the container must have rbegin()/rend() methods for this to work. +template <typename ContainerTy> +auto reverse(ContainerTy &&C, + typename std::enable_if<has_rbegin<ContainerTy>::value>::type * = + nullptr) -> decltype(make_range(C.rbegin(), C.rend())) { + return make_range(C.rbegin(), C.rend()); +} + +// Returns a std::reverse_iterator wrapped around the given iterator. +template <typename IteratorTy> +std::reverse_iterator<IteratorTy> make_reverse_iterator(IteratorTy It) { + return std::reverse_iterator<IteratorTy>(It); +} + +// Returns an iterator_range over the given container which iterates in reverse. +// Note that the container must have begin()/end() methods which return +// bidirectional iterators for this to work. +template <typename ContainerTy> +auto reverse( + ContainerTy &&C, + typename std::enable_if<!has_rbegin<ContainerTy>::value>::type * = nullptr) + -> decltype(make_range(llvm::make_reverse_iterator(std::end(C)), + llvm::make_reverse_iterator(std::begin(C)))) { + return make_range(llvm::make_reverse_iterator(std::end(C)), + llvm::make_reverse_iterator(std::begin(C))); +} + +/// An iterator adaptor that filters the elements of given inner iterators. +/// +/// The predicate parameter should be a callable object that accepts the wrapped +/// iterator's reference type and returns a bool. When incrementing or +/// decrementing the iterator, it will call the predicate on each element and +/// skip any where it returns false. +/// +/// \code +/// int A[] = { 1, 2, 3, 4 }; +/// auto R = make_filter_range(A, [](int N) { return N % 2 == 1; }); +/// // R contains { 1, 3 }. +/// \endcode +template <typename WrappedIteratorT, typename PredicateT> +class filter_iterator + : public iterator_adaptor_base< + filter_iterator<WrappedIteratorT, PredicateT>, WrappedIteratorT, + typename std::common_type< + std::forward_iterator_tag, + typename std::iterator_traits< + WrappedIteratorT>::iterator_category>::type> { + using BaseT = iterator_adaptor_base< + filter_iterator<WrappedIteratorT, PredicateT>, WrappedIteratorT, + typename std::common_type< + std::forward_iterator_tag, + typename std::iterator_traits<WrappedIteratorT>::iterator_category>:: + type>; + + struct PayloadType { + WrappedIteratorT End; + PredicateT Pred; + }; + + Optional<PayloadType> Payload; + + void findNextValid() { + assert(Payload && "Payload should be engaged when findNextValid is called"); + while (this->I != Payload->End && !Payload->Pred(*this->I)) + BaseT::operator++(); + } + + // Construct the begin iterator. The begin iterator requires to know where end + // is, so that it can properly stop when it hits end. + filter_iterator(WrappedIteratorT Begin, WrappedIteratorT End, PredicateT Pred) + : BaseT(std::move(Begin)), + Payload(PayloadType{std::move(End), std::move(Pred)}) { + findNextValid(); + } + + // Construct the end iterator. It's not incrementable, so Payload doesn't + // have to be engaged. + filter_iterator(WrappedIteratorT End) : BaseT(End) {} + +public: + using BaseT::operator++; + + filter_iterator &operator++() { + BaseT::operator++(); + findNextValid(); + return *this; + } + + template <typename RT, typename PT> + friend iterator_range<filter_iterator<detail::IterOfRange<RT>, PT>> + make_filter_range(RT &&, PT); +}; + +/// Convenience function that takes a range of elements and a predicate, +/// and return a new filter_iterator range. +/// +/// FIXME: Currently if RangeT && is a rvalue reference to a temporary, the +/// lifetime of that temporary is not kept by the returned range object, and the +/// temporary is going to be dropped on the floor after the make_iterator_range +/// full expression that contains this function call. +template <typename RangeT, typename PredicateT> +iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>> +make_filter_range(RangeT &&Range, PredicateT Pred) { + using FilterIteratorT = + filter_iterator<detail::IterOfRange<RangeT>, PredicateT>; + return make_range(FilterIteratorT(std::begin(std::forward<RangeT>(Range)), + std::end(std::forward<RangeT>(Range)), + std::move(Pred)), + FilterIteratorT(std::end(std::forward<RangeT>(Range)))); +} + +//===----------------------------------------------------------------------===// +// Extra additions to <utility> +//===----------------------------------------------------------------------===// + +/// \brief Function object to check whether the first component of a std::pair +/// compares less than the first component of another std::pair. +struct less_first { + template <typename T> bool operator()(const T &lhs, const T &rhs) const { + return lhs.first < rhs.first; + } +}; + +/// \brief Function object to check whether the second component of a std::pair +/// compares less than the second component of another std::pair. +struct less_second { + template <typename T> bool operator()(const T &lhs, const T &rhs) const { + return lhs.second < rhs.second; + } +}; + +// A subset of N3658. More stuff can be added as-needed. + +/// \brief Represents a compile-time sequence of integers. +template <class T, T... I> struct integer_sequence { + typedef T value_type; + + static LLVM_CONSTEXPR size_t size() { return sizeof...(I); } +}; + +/// \brief Alias for the common case of a sequence of size_ts. +template <size_t... I> +struct index_sequence : integer_sequence<std::size_t, I...> {}; + +template <std::size_t N, std::size_t... I> +struct build_index_impl : build_index_impl<N - 1, N - 1, I...> {}; +template <std::size_t... I> +struct build_index_impl<0, I...> : index_sequence<I...> {}; + +/// \brief Creates a compile-time integer sequence for a parameter pack. +template <class... Ts> +struct index_sequence_for : build_index_impl<sizeof...(Ts)> {}; + +/// Utility type to build an inheritance chain that makes it easy to rank +/// overload candidates. +template <int N> struct rank : rank<N - 1> {}; +template <> struct rank<0> {}; + +//===----------------------------------------------------------------------===// +// Extra additions for arrays +//===----------------------------------------------------------------------===// + +/// Find the length of an array. +template <class T, std::size_t N> +LLVM_CONSTEXPR inline size_t array_lengthof(T (&)[N]) { + return N; +} + +/// Adapt std::less<T> for array_pod_sort. +template<typename T> +inline int array_pod_sort_comparator(const void *P1, const void *P2) { + if (std::less<T>()(*reinterpret_cast<const T*>(P1), + *reinterpret_cast<const T*>(P2))) + return -1; + if (std::less<T>()(*reinterpret_cast<const T*>(P2), + *reinterpret_cast<const T*>(P1))) + return 1; + return 0; +} + +/// get_array_pod_sort_comparator - This is an internal helper function used to +/// get type deduction of T right. +template<typename T> +inline int (*get_array_pod_sort_comparator(const T &)) + (const void*, const void*) { + return array_pod_sort_comparator<T>; +} + + +/// array_pod_sort - This sorts an array with the specified start and end +/// extent. This is just like std::sort, except that it calls qsort instead of +/// using an inlined template. qsort is slightly slower than std::sort, but +/// most sorts are not performance critical in LLVM and std::sort has to be +/// template instantiated for each type, leading to significant measured code +/// bloat. This function should generally be used instead of std::sort where +/// possible. +/// +/// This function assumes that you have simple POD-like types that can be +/// compared with std::less and can be moved with memcpy. If this isn't true, +/// you should use std::sort. +/// +/// NOTE: If qsort_r were portable, we could allow a custom comparator and +/// default to std::less. +template<class IteratorTy> +inline void array_pod_sort(IteratorTy Start, IteratorTy End) { + // Don't inefficiently call qsort with one element or trigger undefined + // behavior with an empty sequence. + auto NElts = End - Start; + if (NElts <= 1) return; + qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start)); +} + +template <class IteratorTy> +inline void array_pod_sort( + IteratorTy Start, IteratorTy End, + int (*Compare)( + const typename std::iterator_traits<IteratorTy>::value_type *, + const typename std::iterator_traits<IteratorTy>::value_type *)) { + // Don't inefficiently call qsort with one element or trigger undefined + // behavior with an empty sequence. + auto NElts = End - Start; + if (NElts <= 1) return; + qsort(&*Start, NElts, sizeof(*Start), + reinterpret_cast<int (*)(const void *, const void *)>(Compare)); +} + +//===----------------------------------------------------------------------===// +// Extra additions to <algorithm> +//===----------------------------------------------------------------------===// + +/// For a container of pointers, deletes the pointers and then clears the +/// container. +template<typename Container> +void DeleteContainerPointers(Container &C) { + for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I) + delete *I; + C.clear(); +} + +/// In a container of pairs (usually a map) whose second element is a pointer, +/// deletes the second elements and then clears the container. +template<typename Container> +void DeleteContainerSeconds(Container &C) { + for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I) + delete I->second; + C.clear(); +} + +/// Provide wrappers to std::all_of which take ranges instead of having to pass +/// begin/end explicitly. +template<typename R, class UnaryPredicate> +bool all_of(R &&Range, UnaryPredicate &&P) { + return std::all_of(Range.begin(), Range.end(), + std::forward<UnaryPredicate>(P)); +} + +/// Provide wrappers to std::any_of which take ranges instead of having to pass +/// begin/end explicitly. +template <typename R, class UnaryPredicate> +bool any_of(R &&Range, UnaryPredicate &&P) { + return std::any_of(Range.begin(), Range.end(), + std::forward<UnaryPredicate>(P)); +} + +/// Provide wrappers to std::none_of which take ranges instead of having to pass +/// begin/end explicitly. +template <typename R, class UnaryPredicate> +bool none_of(R &&Range, UnaryPredicate &&P) { + return std::none_of(Range.begin(), Range.end(), + std::forward<UnaryPredicate>(P)); +} + +/// Provide wrappers to std::find which take ranges instead of having to pass +/// begin/end explicitly. +template<typename R, class T> +auto find(R &&Range, const T &val) -> decltype(Range.begin()) { + return std::find(Range.begin(), Range.end(), val); +} + +/// Provide wrappers to std::find_if which take ranges instead of having to pass +/// begin/end explicitly. +template <typename R, class T> +auto find_if(R &&Range, const T &Pred) -> decltype(Range.begin()) { + return std::find_if(Range.begin(), Range.end(), Pred); +} + +/// Provide wrappers to std::remove_if which take ranges instead of having to +/// pass begin/end explicitly. +template<typename R, class UnaryPredicate> +auto remove_if(R &&Range, UnaryPredicate &&P) -> decltype(Range.begin()) { + return std::remove_if(Range.begin(), Range.end(), P); +} + +/// Wrapper function around std::find to detect if an element exists +/// in a container. +template <typename R, typename E> +bool is_contained(R &&Range, const E &Element) { + return std::find(Range.begin(), Range.end(), Element) != Range.end(); +} + +/// Wrapper function around std::count_if to count the number of times an +/// element satisfying a given predicate occurs in a range. +template <typename R, typename UnaryPredicate> +auto count_if(R &&Range, UnaryPredicate &&P) + -> typename std::iterator_traits<decltype(Range.begin())>::difference_type { + return std::count_if(Range.begin(), Range.end(), P); +} + +/// Wrapper function around std::transform to apply a function to a range and +/// store the result elsewhere. +template <typename R, class OutputIt, typename UnaryPredicate> +OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate &&P) { + return std::transform(Range.begin(), Range.end(), d_first, + std::forward<UnaryPredicate>(P)); +} + +//===----------------------------------------------------------------------===// +// Extra additions to <memory> +//===----------------------------------------------------------------------===// + +// Implement make_unique according to N3656. + +/// \brief Constructs a `new T()` with the given args and returns a +/// `unique_ptr<T>` which owns the object. +/// +/// Example: +/// +/// auto p = make_unique<int>(); +/// auto p = make_unique<std::tuple<int, int>>(0, 1); +template <class T, class... Args> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Args &&... args) { + return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); +} + +/// \brief Constructs a `new T[n]` with the given args and returns a +/// `unique_ptr<T[]>` which owns the object. +/// +/// \param n size of the new array. +/// +/// Example: +/// +/// auto p = make_unique<int[]>(2); // value-initializes the array with 0's. +template <class T> +typename std::enable_if<std::is_array<T>::value && std::extent<T>::value == 0, + std::unique_ptr<T>>::type +make_unique(size_t n) { + return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]()); +} + +/// This function isn't used and is only here to provide better compile errors. +template <class T, class... Args> +typename std::enable_if<std::extent<T>::value != 0>::type +make_unique(Args &&...) = delete; + +struct FreeDeleter { + void operator()(void* v) { + ::free(v); + } +}; + +template<typename First, typename Second> +struct pair_hash { + size_t operator()(const std::pair<First, Second> &P) const { + return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second); + } +}; + +/// A functor like C++14's std::less<void> in its absence. +struct less { + template <typename A, typename B> bool operator()(A &&a, B &&b) const { + return std::forward<A>(a) < std::forward<B>(b); + } +}; + +/// A functor like C++14's std::equal<void> in its absence. +struct equal { + template <typename A, typename B> bool operator()(A &&a, B &&b) const { + return std::forward<A>(a) == std::forward<B>(b); + } +}; + +/// Binary functor that adapts to any other binary functor after dereferencing +/// operands. +template <typename T> struct deref { + T func; + // Could be further improved to cope with non-derivable functors and + // non-binary functors (should be a variadic template member function + // operator()). + template <typename A, typename B> + auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) { + assert(lhs); + assert(rhs); + return func(*lhs, *rhs); + } +}; + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/SmallPtrSet.h b/third_party/llvm-subzero/include/llvm/ADT/SmallPtrSet.h new file mode 100644 index 0000000..eaed6aa --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/SmallPtrSet.h
@@ -0,0 +1,406 @@ +//===- llvm/ADT/SmallPtrSet.h - 'Normally small' pointer set ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the SmallPtrSet class. See the doxygen comment for +// SmallPtrSetImplBase for more details on the algorithm used. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLPTRSET_H +#define LLVM_ADT_SMALLPTRSET_H + +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include <cassert> +#include <cstddef> +#include <cstring> +#include <cstdlib> +#include <iterator> +#include <utility> + +namespace llvm { + +class SmallPtrSetIteratorImpl; + +/// SmallPtrSetImplBase - This is the common code shared among all the +/// SmallPtrSet<>'s, which is almost everything. SmallPtrSet has two modes, one +/// for small and one for large sets. +/// +/// Small sets use an array of pointers allocated in the SmallPtrSet object, +/// which is treated as a simple array of pointers. When a pointer is added to +/// the set, the array is scanned to see if the element already exists, if not +/// the element is 'pushed back' onto the array. If we run out of space in the +/// array, we grow into the 'large set' case. SmallSet should be used when the +/// sets are often small. In this case, no memory allocation is used, and only +/// light-weight and cache-efficient scanning is used. +/// +/// Large sets use a classic exponentially-probed hash table. Empty buckets are +/// represented with an illegal pointer value (-1) to allow null pointers to be +/// inserted. Tombstones are represented with another illegal pointer value +/// (-2), to allow deletion. The hash table is resized when the table is 3/4 or +/// more. When this happens, the table is doubled in size. +/// +class SmallPtrSetImplBase { + friend class SmallPtrSetIteratorImpl; + +protected: + /// SmallArray - Points to a fixed size set of buckets, used in 'small mode'. + const void **SmallArray; + /// CurArray - This is the current set of buckets. If equal to SmallArray, + /// then the set is in 'small mode'. + const void **CurArray; + /// CurArraySize - The allocated size of CurArray, always a power of two. + unsigned CurArraySize; + + /// Number of elements in CurArray that contain a value or are a tombstone. + /// If small, all these elements are at the beginning of CurArray and the rest + /// is uninitialized. + unsigned NumNonEmpty; + /// Number of tombstones in CurArray. + unsigned NumTombstones; + + // Helpers to copy and move construct a SmallPtrSet. + SmallPtrSetImplBase(const void **SmallStorage, + const SmallPtrSetImplBase &that); + SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize, + SmallPtrSetImplBase &&that); + explicit SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize) + : SmallArray(SmallStorage), CurArray(SmallStorage), + CurArraySize(SmallSize), NumNonEmpty(0), NumTombstones(0) { + assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 && + "Initial size must be a power of two!"); + } + ~SmallPtrSetImplBase() { + if (!isSmall()) + free(CurArray); + } + +public: + typedef unsigned size_type; + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return size() == 0; } + size_type size() const { return NumNonEmpty - NumTombstones; } + + void clear() { + // If the capacity of the array is huge, and the # elements used is small, + // shrink the array. + if (!isSmall()) { + if (size() * 4 < CurArraySize && CurArraySize > 32) + return shrink_and_clear(); + // Fill the array with empty markers. + memset(CurArray, -1, CurArraySize * sizeof(void *)); + } + + NumNonEmpty = 0; + NumTombstones = 0; + } + +protected: + static void *getTombstoneMarker() { return reinterpret_cast<void*>(-2); } + static void *getEmptyMarker() { + // Note that -1 is chosen to make clear() efficiently implementable with + // memset and because it's not a valid pointer value. + return reinterpret_cast<void*>(-1); + } + + const void **EndPointer() const { + return isSmall() ? CurArray + NumNonEmpty : CurArray + CurArraySize; + } + + /// insert_imp - This returns true if the pointer was new to the set, false if + /// it was already in the set. This is hidden from the client so that the + /// derived class can check that the right type of pointer is passed in. + std::pair<const void *const *, bool> insert_imp(const void *Ptr) { + if (isSmall()) { + // Check to see if it is already in the set. + const void **LastTombstone = nullptr; + for (const void **APtr = SmallArray, **E = SmallArray + NumNonEmpty; + APtr != E; ++APtr) { + const void *Value = *APtr; + if (Value == Ptr) + return std::make_pair(APtr, false); + if (Value == getTombstoneMarker()) + LastTombstone = APtr; + } + + // Did we find any tombstone marker? + if (LastTombstone != nullptr) { + *LastTombstone = Ptr; + --NumTombstones; + return std::make_pair(LastTombstone, true); + } + + // Nope, there isn't. If we stay small, just 'pushback' now. + if (NumNonEmpty < CurArraySize) { + SmallArray[NumNonEmpty++] = Ptr; + return std::make_pair(SmallArray + (NumNonEmpty - 1), true); + } + // Otherwise, hit the big set case, which will call grow. + } + return insert_imp_big(Ptr); + } + + /// erase_imp - If the set contains the specified pointer, remove it and + /// return true, otherwise return false. This is hidden from the client so + /// that the derived class can check that the right type of pointer is passed + /// in. + bool erase_imp(const void * Ptr); + + bool count_imp(const void * Ptr) const { + if (isSmall()) { + // Linear search for the item. + for (const void *const *APtr = SmallArray, + *const *E = SmallArray + NumNonEmpty; APtr != E; ++APtr) + if (*APtr == Ptr) + return true; + return false; + } + + // Big set case. + return *FindBucketFor(Ptr) == Ptr; + } + +private: + bool isSmall() const { return CurArray == SmallArray; } + + std::pair<const void *const *, bool> insert_imp_big(const void *Ptr); + + const void * const *FindBucketFor(const void *Ptr) const; + void shrink_and_clear(); + + /// Grow - Allocate a larger backing store for the buckets and move it over. + void Grow(unsigned NewSize); + + void operator=(const SmallPtrSetImplBase &RHS) = delete; + +protected: + /// swap - Swaps the elements of two sets. + /// Note: This method assumes that both sets have the same small size. + void swap(SmallPtrSetImplBase &RHS); + + void CopyFrom(const SmallPtrSetImplBase &RHS); + void MoveFrom(unsigned SmallSize, SmallPtrSetImplBase &&RHS); + +private: + /// Code shared by MoveFrom() and move constructor. + void MoveHelper(unsigned SmallSize, SmallPtrSetImplBase &&RHS); + /// Code shared by CopyFrom() and copy constructor. + void CopyHelper(const SmallPtrSetImplBase &RHS); +}; + +/// SmallPtrSetIteratorImpl - This is the common base class shared between all +/// instances of SmallPtrSetIterator. +class SmallPtrSetIteratorImpl { +protected: + const void *const *Bucket; + const void *const *End; + +public: + explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E) + : Bucket(BP), End(E) { + AdvanceIfNotValid(); + } + + bool operator==(const SmallPtrSetIteratorImpl &RHS) const { + return Bucket == RHS.Bucket; + } + bool operator!=(const SmallPtrSetIteratorImpl &RHS) const { + return Bucket != RHS.Bucket; + } + +protected: + /// AdvanceIfNotValid - If the current bucket isn't valid, advance to a bucket + /// that is. This is guaranteed to stop because the end() bucket is marked + /// valid. + void AdvanceIfNotValid() { + assert(Bucket <= End); + while (Bucket != End && + (*Bucket == SmallPtrSetImplBase::getEmptyMarker() || + *Bucket == SmallPtrSetImplBase::getTombstoneMarker())) + ++Bucket; + } +}; + +/// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet. +template<typename PtrTy> +class SmallPtrSetIterator : public SmallPtrSetIteratorImpl { + typedef PointerLikeTypeTraits<PtrTy> PtrTraits; + +public: + typedef PtrTy value_type; + typedef PtrTy reference; + typedef PtrTy pointer; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + explicit SmallPtrSetIterator(const void *const *BP, const void *const *E) + : SmallPtrSetIteratorImpl(BP, E) {} + + // Most methods provided by baseclass. + + const PtrTy operator*() const { + assert(Bucket < End); + return PtrTraits::getFromVoidPointer(const_cast<void*>(*Bucket)); + } + + inline SmallPtrSetIterator& operator++() { // Preincrement + ++Bucket; + AdvanceIfNotValid(); + return *this; + } + + SmallPtrSetIterator operator++(int) { // Postincrement + SmallPtrSetIterator tmp = *this; ++*this; return tmp; + } +}; + +/// RoundUpToPowerOfTwo - This is a helper template that rounds N up to the next +/// power of two (which means N itself if N is already a power of two). +template<unsigned N> +struct RoundUpToPowerOfTwo; + +/// RoundUpToPowerOfTwoH - If N is not a power of two, increase it. This is a +/// helper template used to implement RoundUpToPowerOfTwo. +template<unsigned N, bool isPowerTwo> +struct RoundUpToPowerOfTwoH { + enum { Val = N }; +}; +template<unsigned N> +struct RoundUpToPowerOfTwoH<N, false> { + enum { + // We could just use NextVal = N+1, but this converges faster. N|(N-1) sets + // the right-most zero bits to one all at once, e.g. 0b0011000 -> 0b0011111. + Val = RoundUpToPowerOfTwo<(N|(N-1)) + 1>::Val + }; +}; + +template<unsigned N> +struct RoundUpToPowerOfTwo { + enum { Val = RoundUpToPowerOfTwoH<N, (N&(N-1)) == 0>::Val }; +}; + +/// \brief A templated base class for \c SmallPtrSet which provides the +/// typesafe interface that is common across all small sizes. +/// +/// This is particularly useful for passing around between interface boundaries +/// to avoid encoding a particular small size in the interface boundary. +template <typename PtrType> +class SmallPtrSetImpl : public SmallPtrSetImplBase { + typedef PointerLikeTypeTraits<PtrType> PtrTraits; + + SmallPtrSetImpl(const SmallPtrSetImpl &) = delete; + +protected: + // Constructors that forward to the base. + SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that) + : SmallPtrSetImplBase(SmallStorage, that) {} + SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize, + SmallPtrSetImpl &&that) + : SmallPtrSetImplBase(SmallStorage, SmallSize, std::move(that)) {} + explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize) + : SmallPtrSetImplBase(SmallStorage, SmallSize) {} + +public: + typedef SmallPtrSetIterator<PtrType> iterator; + typedef SmallPtrSetIterator<PtrType> const_iterator; + + /// Inserts Ptr if and only if there is no element in the container equal to + /// Ptr. The bool component of the returned pair is true if and only if the + /// insertion takes place, and the iterator component of the pair points to + /// the element equal to Ptr. + std::pair<iterator, bool> insert(PtrType Ptr) { + auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr)); + return std::make_pair(iterator(p.first, EndPointer()), p.second); + } + + /// erase - If the set contains the specified pointer, remove it and return + /// true, otherwise return false. + bool erase(PtrType Ptr) { + return erase_imp(PtrTraits::getAsVoidPointer(Ptr)); + } + + /// count - Return 1 if the specified pointer is in the set, 0 otherwise. + size_type count(PtrType Ptr) const { + return count_imp(PtrTraits::getAsVoidPointer(Ptr)) ? 1 : 0; + } + + template <typename IterT> + void insert(IterT I, IterT E) { + for (; I != E; ++I) + insert(*I); + } + + inline iterator begin() const { + return iterator(CurArray, EndPointer()); + } + inline iterator end() const { + const void *const *End = EndPointer(); + return iterator(End, End); + } +}; + +/// SmallPtrSet - This class implements a set which is optimized for holding +/// SmallSize or less elements. This internally rounds up SmallSize to the next +/// power of two if it is not already a power of two. See the comments above +/// SmallPtrSetImplBase for details of the algorithm. +template<class PtrType, unsigned SmallSize> +class SmallPtrSet : public SmallPtrSetImpl<PtrType> { + // In small mode SmallPtrSet uses linear search for the elements, so it is + // not a good idea to choose this value too high. You may consider using a + // DenseSet<> instead if you expect many elements in the set. + static_assert(SmallSize <= 32, "SmallSize should be small"); + + typedef SmallPtrSetImpl<PtrType> BaseT; + + // Make sure that SmallSize is a power of two, round up if not. + enum { SmallSizePowTwo = RoundUpToPowerOfTwo<SmallSize>::Val }; + /// SmallStorage - Fixed size storage used in 'small mode'. + const void *SmallStorage[SmallSizePowTwo]; + +public: + SmallPtrSet() : BaseT(SmallStorage, SmallSizePowTwo) {} + SmallPtrSet(const SmallPtrSet &that) : BaseT(SmallStorage, that) {} + SmallPtrSet(SmallPtrSet &&that) + : BaseT(SmallStorage, SmallSizePowTwo, std::move(that)) {} + + template<typename It> + SmallPtrSet(It I, It E) : BaseT(SmallStorage, SmallSizePowTwo) { + this->insert(I, E); + } + + SmallPtrSet<PtrType, SmallSize> & + operator=(const SmallPtrSet<PtrType, SmallSize> &RHS) { + if (&RHS != this) + this->CopyFrom(RHS); + return *this; + } + + SmallPtrSet<PtrType, SmallSize>& + operator=(SmallPtrSet<PtrType, SmallSize> &&RHS) { + if (&RHS != this) + this->MoveFrom(SmallSizePowTwo, std::move(RHS)); + return *this; + } + + /// swap - Swaps the elements of two sets. + void swap(SmallPtrSet<PtrType, SmallSize> &RHS) { + SmallPtrSetImplBase::swap(RHS); + } +}; +} + +namespace std { + /// Implement std::swap in terms of SmallPtrSet swap. + template<class T, unsigned N> + inline void swap(llvm::SmallPtrSet<T, N> &LHS, llvm::SmallPtrSet<T, N> &RHS) { + LHS.swap(RHS); + } +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/SmallString.h b/third_party/llvm-subzero/include/llvm/ADT/SmallString.h new file mode 100644 index 0000000..e569f54 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/SmallString.h
@@ -0,0 +1,297 @@ +//===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the SmallString class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLSTRING_H +#define LLVM_ADT_SMALLSTRING_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +/// SmallString - A SmallString is just a SmallVector with methods and accessors +/// that make it work better as a string (e.g. operator+ etc). +template<unsigned InternalLen> +class SmallString : public SmallVector<char, InternalLen> { +public: + /// Default ctor - Initialize to empty. + SmallString() {} + + /// Initialize from a StringRef. + SmallString(StringRef S) : SmallVector<char, InternalLen>(S.begin(), S.end()) {} + + /// Initialize with a range. + template<typename ItTy> + SmallString(ItTy S, ItTy E) : SmallVector<char, InternalLen>(S, E) {} + + // Note that in order to add new overloads for append & assign, we have to + // duplicate the inherited versions so as not to inadvertently hide them. + + /// @} + /// @name String Assignment + /// @{ + + /// Assign from a repeated element. + void assign(size_t NumElts, char Elt) { + this->SmallVectorImpl<char>::assign(NumElts, Elt); + } + + /// Assign from an iterator pair. + template<typename in_iter> + void assign(in_iter S, in_iter E) { + this->clear(); + SmallVectorImpl<char>::append(S, E); + } + + /// Assign from a StringRef. + void assign(StringRef RHS) { + this->clear(); + SmallVectorImpl<char>::append(RHS.begin(), RHS.end()); + } + + /// Assign from a SmallVector. + void assign(const SmallVectorImpl<char> &RHS) { + this->clear(); + SmallVectorImpl<char>::append(RHS.begin(), RHS.end()); + } + + /// @} + /// @name String Concatenation + /// @{ + + /// Append from an iterator pair. + template<typename in_iter> + void append(in_iter S, in_iter E) { + SmallVectorImpl<char>::append(S, E); + } + + void append(size_t NumInputs, char Elt) { + SmallVectorImpl<char>::append(NumInputs, Elt); + } + + + /// Append from a StringRef. + void append(StringRef RHS) { + SmallVectorImpl<char>::append(RHS.begin(), RHS.end()); + } + + /// Append from a SmallVector. + void append(const SmallVectorImpl<char> &RHS) { + SmallVectorImpl<char>::append(RHS.begin(), RHS.end()); + } + + /// @} + /// @name String Comparison + /// @{ + + /// Check for string equality. This is more efficient than compare() when + /// the relative ordering of inequal strings isn't needed. + bool equals(StringRef RHS) const { + return str().equals(RHS); + } + + /// Check for string equality, ignoring case. + bool equals_lower(StringRef RHS) const { + return str().equals_lower(RHS); + } + + /// Compare two strings; the result is -1, 0, or 1 if this string is + /// lexicographically less than, equal to, or greater than the \p RHS. + int compare(StringRef RHS) const { + return str().compare(RHS); + } + + /// compare_lower - Compare two strings, ignoring case. + int compare_lower(StringRef RHS) const { + return str().compare_lower(RHS); + } + + /// compare_numeric - Compare two strings, treating sequences of digits as + /// numbers. + int compare_numeric(StringRef RHS) const { + return str().compare_numeric(RHS); + } + + /// @} + /// @name String Predicates + /// @{ + + /// startswith - Check if this string starts with the given \p Prefix. + bool startswith(StringRef Prefix) const { + return str().startswith(Prefix); + } + + /// endswith - Check if this string ends with the given \p Suffix. + bool endswith(StringRef Suffix) const { + return str().endswith(Suffix); + } + + /// @} + /// @name String Searching + /// @{ + + /// find - Search for the first character \p C in the string. + /// + /// \return - The index of the first occurrence of \p C, or npos if not + /// found. + size_t find(char C, size_t From = 0) const { + return str().find(C, From); + } + + /// Search for the first string \p Str in the string. + /// + /// \returns The index of the first occurrence of \p Str, or npos if not + /// found. + size_t find(StringRef Str, size_t From = 0) const { + return str().find(Str, From); + } + + /// Search for the last character \p C in the string. + /// + /// \returns The index of the last occurrence of \p C, or npos if not + /// found. + size_t rfind(char C, size_t From = StringRef::npos) const { + return str().rfind(C, From); + } + + /// Search for the last string \p Str in the string. + /// + /// \returns The index of the last occurrence of \p Str, or npos if not + /// found. + size_t rfind(StringRef Str) const { + return str().rfind(Str); + } + + /// Find the first character in the string that is \p C, or npos if not + /// found. Same as find. + size_t find_first_of(char C, size_t From = 0) const { + return str().find_first_of(C, From); + } + + /// Find the first character in the string that is in \p Chars, or npos if + /// not found. + /// + /// Complexity: O(size() + Chars.size()) + size_t find_first_of(StringRef Chars, size_t From = 0) const { + return str().find_first_of(Chars, From); + } + + /// Find the first character in the string that is not \p C or npos if not + /// found. + size_t find_first_not_of(char C, size_t From = 0) const { + return str().find_first_not_of(C, From); + } + + /// Find the first character in the string that is not in the string + /// \p Chars, or npos if not found. + /// + /// Complexity: O(size() + Chars.size()) + size_t find_first_not_of(StringRef Chars, size_t From = 0) const { + return str().find_first_not_of(Chars, From); + } + + /// Find the last character in the string that is \p C, or npos if not + /// found. + size_t find_last_of(char C, size_t From = StringRef::npos) const { + return str().find_last_of(C, From); + } + + /// Find the last character in the string that is in \p C, or npos if not + /// found. + /// + /// Complexity: O(size() + Chars.size()) + size_t find_last_of( + StringRef Chars, size_t From = StringRef::npos) const { + return str().find_last_of(Chars, From); + } + + /// @} + /// @name Helpful Algorithms + /// @{ + + /// Return the number of occurrences of \p C in the string. + size_t count(char C) const { + return str().count(C); + } + + /// Return the number of non-overlapped occurrences of \p Str in the + /// string. + size_t count(StringRef Str) const { + return str().count(Str); + } + + /// @} + /// @name Substring Operations + /// @{ + + /// Return a reference to the substring from [Start, Start + N). + /// + /// \param Start The index of the starting character in the substring; if + /// the index is npos or greater than the length of the string then the + /// empty substring will be returned. + /// + /// \param N The number of characters to included in the substring. If \p N + /// exceeds the number of characters remaining in the string, the string + /// suffix (starting with \p Start) will be returned. + StringRef substr(size_t Start, size_t N = StringRef::npos) const { + return str().substr(Start, N); + } + + /// Return a reference to the substring from [Start, End). + /// + /// \param Start The index of the starting character in the substring; if + /// the index is npos or greater than the length of the string then the + /// empty substring will be returned. + /// + /// \param End The index following the last character to include in the + /// substring. If this is npos, or less than \p Start, or exceeds the + /// number of characters remaining in the string, the string suffix + /// (starting with \p Start) will be returned. + StringRef slice(size_t Start, size_t End) const { + return str().slice(Start, End); + } + + // Extra methods. + + /// Explicit conversion to StringRef. + StringRef str() const { return StringRef(this->begin(), this->size()); } + + // TODO: Make this const, if it's safe... + const char* c_str() { + this->push_back(0); + this->pop_back(); + return this->data(); + } + + /// Implicit conversion to StringRef. + operator StringRef() const { return str(); } + + // Extra operators. + const SmallString &operator=(StringRef RHS) { + this->clear(); + return *this += RHS; + } + + SmallString &operator+=(StringRef RHS) { + this->append(RHS.begin(), RHS.end()); + return *this; + } + SmallString &operator+=(char C) { + this->push_back(C); + return *this; + } +}; + +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/SmallVector.h b/third_party/llvm-subzero/include/llvm/ADT/SmallVector.h new file mode 100644 index 0000000..9403579 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/SmallVector.h
@@ -0,0 +1,927 @@ +//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the SmallVector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLVECTOR_H +#define LLVM_ADT_SMALLVECTOR_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/type_traits.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdlib> +#include <cstring> +#include <initializer_list> +#include <iterator> +#include <memory> + +namespace llvm { + +/// This is all the non-templated stuff common to all SmallVectors. +class SmallVectorBase { +protected: + void *BeginX, *EndX, *CapacityX; + +protected: + SmallVectorBase(void *FirstEl, size_t Size) + : BeginX(FirstEl), EndX(FirstEl), CapacityX((char*)FirstEl+Size) {} + + /// This is an implementation of the grow() method which only works + /// on POD-like data types and is out of line to reduce code duplication. + void grow_pod(void *FirstEl, size_t MinSizeInBytes, size_t TSize); + +public: + /// This returns size()*sizeof(T). + size_t size_in_bytes() const { + return size_t((char*)EndX - (char*)BeginX); + } + + /// capacity_in_bytes - This returns capacity()*sizeof(T). + size_t capacity_in_bytes() const { + return size_t((char*)CapacityX - (char*)BeginX); + } + + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return BeginX == EndX; } +}; + +template <typename T, unsigned N> struct SmallVectorStorage; + +/// This is the part of SmallVectorTemplateBase which does not depend on whether +/// the type T is a POD. The extra dummy template argument is used by ArrayRef +/// to avoid unnecessarily requiring T to be complete. +template <typename T, typename = void> +class SmallVectorTemplateCommon : public SmallVectorBase { +private: + template <typename, unsigned> friend struct SmallVectorStorage; + + // Allocate raw space for N elements of type T. If T has a ctor or dtor, we + // don't want it to be automatically run, so we need to represent the space as + // something else. Use an array of char of sufficient alignment. + typedef llvm::AlignedCharArrayUnion<T> U; + U FirstEl; + // Space after 'FirstEl' is clobbered, do not add any instance vars after it. + +protected: + SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(&FirstEl, Size) {} + + void grow_pod(size_t MinSizeInBytes, size_t TSize) { + SmallVectorBase::grow_pod(&FirstEl, MinSizeInBytes, TSize); + } + + /// Return true if this is a smallvector which has not had dynamic + /// memory allocated for it. + bool isSmall() const { + return BeginX == static_cast<const void*>(&FirstEl); + } + + /// Put this vector in a state of being small. + void resetToSmall() { + BeginX = EndX = CapacityX = &FirstEl; + } + + void setEnd(T *P) { this->EndX = P; } +public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T *iterator; + typedef const T *const_iterator; + + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + + typedef T &reference; + typedef const T &const_reference; + typedef T *pointer; + typedef const T *const_pointer; + + // forward iterator creation methods. + LLVM_ATTRIBUTE_ALWAYS_INLINE + iterator begin() { return (iterator)this->BeginX; } + LLVM_ATTRIBUTE_ALWAYS_INLINE + const_iterator begin() const { return (const_iterator)this->BeginX; } + LLVM_ATTRIBUTE_ALWAYS_INLINE + iterator end() { return (iterator)this->EndX; } + LLVM_ATTRIBUTE_ALWAYS_INLINE + const_iterator end() const { return (const_iterator)this->EndX; } +protected: + iterator capacity_ptr() { return (iterator)this->CapacityX; } + const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;} +public: + + // reverse iterator creation methods. + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin());} + + LLVM_ATTRIBUTE_ALWAYS_INLINE + size_type size() const { return end()-begin(); } + size_type max_size() const { return size_type(-1) / sizeof(T); } + + /// Return the total number of elements in the currently allocated buffer. + size_t capacity() const { return capacity_ptr() - begin(); } + + /// Return a pointer to the vector's buffer, even if empty(). + pointer data() { return pointer(begin()); } + /// Return a pointer to the vector's buffer, even if empty(). + const_pointer data() const { return const_pointer(begin()); } + + LLVM_ATTRIBUTE_ALWAYS_INLINE + reference operator[](size_type idx) { + assert(idx < size()); + return begin()[idx]; + } + LLVM_ATTRIBUTE_ALWAYS_INLINE + const_reference operator[](size_type idx) const { + assert(idx < size()); + return begin()[idx]; + } + + reference front() { + assert(!empty()); + return begin()[0]; + } + const_reference front() const { + assert(!empty()); + return begin()[0]; + } + + reference back() { + assert(!empty()); + return end()[-1]; + } + const_reference back() const { + assert(!empty()); + return end()[-1]; + } +}; + +/// SmallVectorTemplateBase<isPodLike = false> - This is where we put method +/// implementations that are designed to work with non-POD-like T's. +template <typename T, bool isPodLike> +class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> { +protected: + SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {} + + static void destroy_range(T *S, T *E) { + while (S != E) { + --E; + E->~T(); + } + } + + /// Move the range [I, E) into the uninitialized memory starting with "Dest", + /// constructing elements as needed. + template<typename It1, typename It2> + static void uninitialized_move(It1 I, It1 E, It2 Dest) { + std::uninitialized_copy(std::make_move_iterator(I), + std::make_move_iterator(E), Dest); + } + + /// Copy the range [I, E) onto the uninitialized memory starting with "Dest", + /// constructing elements as needed. + template<typename It1, typename It2> + static void uninitialized_copy(It1 I, It1 E, It2 Dest) { + std::uninitialized_copy(I, E, Dest); + } + + /// Grow the allocated memory (without initializing new elements), doubling + /// the size of the allocated memory. Guarantees space for at least one more + /// element, or MinSize more elements if specified. + void grow(size_t MinSize = 0); + +public: + void push_back(const T &Elt) { + if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + this->grow(); + ::new ((void*) this->end()) T(Elt); + this->setEnd(this->end()+1); + } + + void push_back(T &&Elt) { + if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + this->grow(); + ::new ((void*) this->end()) T(::std::move(Elt)); + this->setEnd(this->end()+1); + } + + void pop_back() { + this->setEnd(this->end()-1); + this->end()->~T(); + } +}; + +// Define this out-of-line to dissuade the C++ compiler from inlining it. +template <typename T, bool isPodLike> +void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) { + size_t CurCapacity = this->capacity(); + size_t CurSize = this->size(); + // Always grow, even from zero. + size_t NewCapacity = size_t(NextPowerOf2(CurCapacity+2)); + if (NewCapacity < MinSize) + NewCapacity = MinSize; + T *NewElts = static_cast<T*>(malloc(NewCapacity*sizeof(T))); + + // Move the elements over. + this->uninitialized_move(this->begin(), this->end(), NewElts); + + // Destroy the original elements. + destroy_range(this->begin(), this->end()); + + // If this wasn't grown from the inline copy, deallocate the old space. + if (!this->isSmall()) + free(this->begin()); + + this->setEnd(NewElts+CurSize); + this->BeginX = NewElts; + this->CapacityX = this->begin()+NewCapacity; +} + + +/// SmallVectorTemplateBase<isPodLike = true> - This is where we put method +/// implementations that are designed to work with POD-like T's. +template <typename T> +class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> { +protected: + SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {} + + // No need to do a destroy loop for POD's. + static void destroy_range(T *, T *) {} + + /// Move the range [I, E) onto the uninitialized memory + /// starting with "Dest", constructing elements into it as needed. + template<typename It1, typename It2> + static void uninitialized_move(It1 I, It1 E, It2 Dest) { + // Just do a copy. + uninitialized_copy(I, E, Dest); + } + + /// Copy the range [I, E) onto the uninitialized memory + /// starting with "Dest", constructing elements into it as needed. + template<typename It1, typename It2> + static void uninitialized_copy(It1 I, It1 E, It2 Dest) { + // Arbitrary iterator types; just use the basic implementation. + std::uninitialized_copy(I, E, Dest); + } + + /// Copy the range [I, E) onto the uninitialized memory + /// starting with "Dest", constructing elements into it as needed. + template <typename T1, typename T2> + static void uninitialized_copy( + T1 *I, T1 *E, T2 *Dest, + typename std::enable_if<std::is_same<typename std::remove_const<T1>::type, + T2>::value>::type * = nullptr) { + // Use memcpy for PODs iterated by pointers (which includes SmallVector + // iterators): std::uninitialized_copy optimizes to memmove, but we can + // use memcpy here. Note that I and E are iterators and thus might be + // invalid for memcpy if they are equal. + if (I != E) + memcpy(Dest, I, (E - I) * sizeof(T)); + } + + /// Double the size of the allocated memory, guaranteeing space for at + /// least one more element or MinSize if specified. + void grow(size_t MinSize = 0) { + this->grow_pod(MinSize*sizeof(T), sizeof(T)); + } +public: + void push_back(const T &Elt) { + if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + this->grow(); + memcpy(this->end(), &Elt, sizeof(T)); + this->setEnd(this->end()+1); + } + + void pop_back() { + this->setEnd(this->end()-1); + } +}; + + +/// This class consists of common code factored out of the SmallVector class to +/// reduce code duplication based on the SmallVector 'N' template parameter. +template <typename T> +class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> { + typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass; + + SmallVectorImpl(const SmallVectorImpl&) = delete; +public: + typedef typename SuperClass::iterator iterator; + typedef typename SuperClass::const_iterator const_iterator; + typedef typename SuperClass::size_type size_type; + +protected: + // Default ctor - Initialize to empty. + explicit SmallVectorImpl(unsigned N) + : SmallVectorTemplateBase<T, isPodLike<T>::value>(N*sizeof(T)) { + } + +public: + ~SmallVectorImpl() { + // Destroy the constructed elements in the vector. + this->destroy_range(this->begin(), this->end()); + + // If this wasn't grown from the inline copy, deallocate the old space. + if (!this->isSmall()) + free(this->begin()); + } + + + void clear() { + this->destroy_range(this->begin(), this->end()); + this->EndX = this->BeginX; + } + + void resize(size_type N) { + if (N < this->size()) { + this->destroy_range(this->begin()+N, this->end()); + this->setEnd(this->begin()+N); + } else if (N > this->size()) { + if (this->capacity() < N) + this->grow(N); + for (auto I = this->end(), E = this->begin() + N; I != E; ++I) + new (&*I) T(); + this->setEnd(this->begin()+N); + } + } + + void resize(size_type N, const T &NV) { + if (N < this->size()) { + this->destroy_range(this->begin()+N, this->end()); + this->setEnd(this->begin()+N); + } else if (N > this->size()) { + if (this->capacity() < N) + this->grow(N); + std::uninitialized_fill(this->end(), this->begin()+N, NV); + this->setEnd(this->begin()+N); + } + } + + void reserve(size_type N) { + if (this->capacity() < N) + this->grow(N); + } + + T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() { + T Result = ::std::move(this->back()); + this->pop_back(); + return Result; + } + + void swap(SmallVectorImpl &RHS); + + /// Add the specified range to the end of the SmallVector. + template<typename in_iter> + void append(in_iter in_start, in_iter in_end) { + size_type NumInputs = std::distance(in_start, in_end); + // Grow allocated space if needed. + if (NumInputs > size_type(this->capacity_ptr()-this->end())) + this->grow(this->size()+NumInputs); + + // Copy the new elements over. + this->uninitialized_copy(in_start, in_end, this->end()); + this->setEnd(this->end() + NumInputs); + } + + /// Add the specified range to the end of the SmallVector. + void append(size_type NumInputs, const T &Elt) { + // Grow allocated space if needed. + if (NumInputs > size_type(this->capacity_ptr()-this->end())) + this->grow(this->size()+NumInputs); + + // Copy the new elements over. + std::uninitialized_fill_n(this->end(), NumInputs, Elt); + this->setEnd(this->end() + NumInputs); + } + + void append(std::initializer_list<T> IL) { + append(IL.begin(), IL.end()); + } + + void assign(size_type NumElts, const T &Elt) { + clear(); + if (this->capacity() < NumElts) + this->grow(NumElts); + this->setEnd(this->begin()+NumElts); + std::uninitialized_fill(this->begin(), this->end(), Elt); + } + + void assign(std::initializer_list<T> IL) { + clear(); + append(IL); + } + + iterator erase(const_iterator CI) { + // Just cast away constness because this is a non-const member function. + iterator I = const_cast<iterator>(CI); + + assert(I >= this->begin() && "Iterator to erase is out of bounds."); + assert(I < this->end() && "Erasing at past-the-end iterator."); + + iterator N = I; + // Shift all elts down one. + std::move(I+1, this->end(), I); + // Drop the last elt. + this->pop_back(); + return(N); + } + + iterator erase(const_iterator CS, const_iterator CE) { + // Just cast away constness because this is a non-const member function. + iterator S = const_cast<iterator>(CS); + iterator E = const_cast<iterator>(CE); + + assert(S >= this->begin() && "Range to erase is out of bounds."); + assert(S <= E && "Trying to erase invalid range."); + assert(E <= this->end() && "Trying to erase past the end."); + + iterator N = S; + // Shift all elts down. + iterator I = std::move(E, this->end(), S); + // Drop the last elts. + this->destroy_range(I, this->end()); + this->setEnd(I); + return(N); + } + + iterator insert(iterator I, T &&Elt) { + if (I == this->end()) { // Important special case for empty vector. + this->push_back(::std::move(Elt)); + return this->end()-1; + } + + assert(I >= this->begin() && "Insertion iterator is out of bounds."); + assert(I <= this->end() && "Inserting past the end of the vector."); + + if (this->EndX >= this->CapacityX) { + size_t EltNo = I-this->begin(); + this->grow(); + I = this->begin()+EltNo; + } + + ::new ((void*) this->end()) T(::std::move(this->back())); + // Push everything else over. + std::move_backward(I, this->end()-1, this->end()); + this->setEnd(this->end()+1); + + // If we just moved the element we're inserting, be sure to update + // the reference. + T *EltPtr = &Elt; + if (I <= EltPtr && EltPtr < this->EndX) + ++EltPtr; + + *I = ::std::move(*EltPtr); + return I; + } + + iterator insert(iterator I, const T &Elt) { + if (I == this->end()) { // Important special case for empty vector. + this->push_back(Elt); + return this->end()-1; + } + + assert(I >= this->begin() && "Insertion iterator is out of bounds."); + assert(I <= this->end() && "Inserting past the end of the vector."); + + if (this->EndX >= this->CapacityX) { + size_t EltNo = I-this->begin(); + this->grow(); + I = this->begin()+EltNo; + } + ::new ((void*) this->end()) T(std::move(this->back())); + // Push everything else over. + std::move_backward(I, this->end()-1, this->end()); + this->setEnd(this->end()+1); + + // If we just moved the element we're inserting, be sure to update + // the reference. + const T *EltPtr = &Elt; + if (I <= EltPtr && EltPtr < this->EndX) + ++EltPtr; + + *I = *EltPtr; + return I; + } + + iterator insert(iterator I, size_type NumToInsert, const T &Elt) { + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I - this->begin(); + + if (I == this->end()) { // Important special case for empty vector. + append(NumToInsert, Elt); + return this->begin()+InsertElt; + } + + assert(I >= this->begin() && "Insertion iterator is out of bounds."); + assert(I <= this->end() && "Inserting past the end of the vector."); + + // Ensure there is enough space. + reserve(this->size() + NumToInsert); + + // Uninvalidate the iterator. + I = this->begin()+InsertElt; + + // If there are more elements between the insertion point and the end of the + // range than there are being inserted, we can use a simple approach to + // insertion. Since we already reserved space, we know that this won't + // reallocate the vector. + if (size_t(this->end()-I) >= NumToInsert) { + T *OldEnd = this->end(); + append(std::move_iterator<iterator>(this->end() - NumToInsert), + std::move_iterator<iterator>(this->end())); + + // Copy the existing elements that get replaced. + std::move_backward(I, OldEnd-NumToInsert, OldEnd); + + std::fill_n(I, NumToInsert, Elt); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Move over the elements that we're about to overwrite. + T *OldEnd = this->end(); + this->setEnd(this->end() + NumToInsert); + size_t NumOverwritten = OldEnd-I; + this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); + + // Replace the overwritten part. + std::fill_n(I, NumOverwritten, Elt); + + // Insert the non-overwritten middle part. + std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); + return I; + } + + template<typename ItTy> + iterator insert(iterator I, ItTy From, ItTy To) { + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I - this->begin(); + + if (I == this->end()) { // Important special case for empty vector. + append(From, To); + return this->begin()+InsertElt; + } + + assert(I >= this->begin() && "Insertion iterator is out of bounds."); + assert(I <= this->end() && "Inserting past the end of the vector."); + + size_t NumToInsert = std::distance(From, To); + + // Ensure there is enough space. + reserve(this->size() + NumToInsert); + + // Uninvalidate the iterator. + I = this->begin()+InsertElt; + + // If there are more elements between the insertion point and the end of the + // range than there are being inserted, we can use a simple approach to + // insertion. Since we already reserved space, we know that this won't + // reallocate the vector. + if (size_t(this->end()-I) >= NumToInsert) { + T *OldEnd = this->end(); + append(std::move_iterator<iterator>(this->end() - NumToInsert), + std::move_iterator<iterator>(this->end())); + + // Copy the existing elements that get replaced. + std::move_backward(I, OldEnd-NumToInsert, OldEnd); + + std::copy(From, To, I); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Move over the elements that we're about to overwrite. + T *OldEnd = this->end(); + this->setEnd(this->end() + NumToInsert); + size_t NumOverwritten = OldEnd-I; + this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); + + // Replace the overwritten part. + for (T *J = I; NumOverwritten > 0; --NumOverwritten) { + *J = *From; + ++J; ++From; + } + + // Insert the non-overwritten middle part. + this->uninitialized_copy(From, To, OldEnd); + return I; + } + + void insert(iterator I, std::initializer_list<T> IL) { + insert(I, IL.begin(), IL.end()); + } + + template <typename... ArgTypes> void emplace_back(ArgTypes &&... Args) { + if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + this->grow(); + ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...); + this->setEnd(this->end() + 1); + } + + SmallVectorImpl &operator=(const SmallVectorImpl &RHS); + + SmallVectorImpl &operator=(SmallVectorImpl &&RHS); + + bool operator==(const SmallVectorImpl &RHS) const { + if (this->size() != RHS.size()) return false; + return std::equal(this->begin(), this->end(), RHS.begin()); + } + bool operator!=(const SmallVectorImpl &RHS) const { + return !(*this == RHS); + } + + bool operator<(const SmallVectorImpl &RHS) const { + return std::lexicographical_compare(this->begin(), this->end(), + RHS.begin(), RHS.end()); + } + + /// Set the array size to \p N, which the current array must have enough + /// capacity for. + /// + /// This does not construct or destroy any elements in the vector. + /// + /// Clients can use this in conjunction with capacity() to write past the end + /// of the buffer when they know that more elements are available, and only + /// update the size later. This avoids the cost of value initializing elements + /// which will only be overwritten. + void set_size(size_type N) { + assert(N <= this->capacity()); + this->setEnd(this->begin() + N); + } +}; + + +template <typename T> +void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) { + if (this == &RHS) return; + + // We can only avoid copying elements if neither vector is small. + if (!this->isSmall() && !RHS.isSmall()) { + std::swap(this->BeginX, RHS.BeginX); + std::swap(this->EndX, RHS.EndX); + std::swap(this->CapacityX, RHS.CapacityX); + return; + } + if (RHS.size() > this->capacity()) + this->grow(RHS.size()); + if (this->size() > RHS.capacity()) + RHS.grow(this->size()); + + // Swap the shared elements. + size_t NumShared = this->size(); + if (NumShared > RHS.size()) NumShared = RHS.size(); + for (size_type i = 0; i != NumShared; ++i) + std::swap((*this)[i], RHS[i]); + + // Copy over the extra elts. + if (this->size() > RHS.size()) { + size_t EltDiff = this->size() - RHS.size(); + this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end()); + RHS.setEnd(RHS.end()+EltDiff); + this->destroy_range(this->begin()+NumShared, this->end()); + this->setEnd(this->begin()+NumShared); + } else if (RHS.size() > this->size()) { + size_t EltDiff = RHS.size() - this->size(); + this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end()); + this->setEnd(this->end() + EltDiff); + this->destroy_range(RHS.begin()+NumShared, RHS.end()); + RHS.setEnd(RHS.begin()+NumShared); + } +} + +template <typename T> +SmallVectorImpl<T> &SmallVectorImpl<T>:: + operator=(const SmallVectorImpl<T> &RHS) { + // Avoid self-assignment. + if (this == &RHS) return *this; + + // If we already have sufficient space, assign the common elements, then + // destroy any excess. + size_t RHSSize = RHS.size(); + size_t CurSize = this->size(); + if (CurSize >= RHSSize) { + // Assign common elements. + iterator NewEnd; + if (RHSSize) + NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin()); + else + NewEnd = this->begin(); + + // Destroy excess elements. + this->destroy_range(NewEnd, this->end()); + + // Trim. + this->setEnd(NewEnd); + return *this; + } + + // If we have to grow to have enough elements, destroy the current elements. + // This allows us to avoid copying them during the grow. + // FIXME: don't do this if they're efficiently moveable. + if (this->capacity() < RHSSize) { + // Destroy current elements. + this->destroy_range(this->begin(), this->end()); + this->setEnd(this->begin()); + CurSize = 0; + this->grow(RHSSize); + } else if (CurSize) { + // Otherwise, use assignment for the already-constructed elements. + std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin()); + } + + // Copy construct the new elements in place. + this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(), + this->begin()+CurSize); + + // Set end. + this->setEnd(this->begin()+RHSSize); + return *this; +} + +template <typename T> +SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) { + // Avoid self-assignment. + if (this == &RHS) return *this; + + // If the RHS isn't small, clear this vector and then steal its buffer. + if (!RHS.isSmall()) { + this->destroy_range(this->begin(), this->end()); + if (!this->isSmall()) free(this->begin()); + this->BeginX = RHS.BeginX; + this->EndX = RHS.EndX; + this->CapacityX = RHS.CapacityX; + RHS.resetToSmall(); + return *this; + } + + // If we already have sufficient space, assign the common elements, then + // destroy any excess. + size_t RHSSize = RHS.size(); + size_t CurSize = this->size(); + if (CurSize >= RHSSize) { + // Assign common elements. + iterator NewEnd = this->begin(); + if (RHSSize) + NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd); + + // Destroy excess elements and trim the bounds. + this->destroy_range(NewEnd, this->end()); + this->setEnd(NewEnd); + + // Clear the RHS. + RHS.clear(); + + return *this; + } + + // If we have to grow to have enough elements, destroy the current elements. + // This allows us to avoid copying them during the grow. + // FIXME: this may not actually make any sense if we can efficiently move + // elements. + if (this->capacity() < RHSSize) { + // Destroy current elements. + this->destroy_range(this->begin(), this->end()); + this->setEnd(this->begin()); + CurSize = 0; + this->grow(RHSSize); + } else if (CurSize) { + // Otherwise, use assignment for the already-constructed elements. + std::move(RHS.begin(), RHS.begin()+CurSize, this->begin()); + } + + // Move-construct the new elements in place. + this->uninitialized_move(RHS.begin()+CurSize, RHS.end(), + this->begin()+CurSize); + + // Set end. + this->setEnd(this->begin()+RHSSize); + + RHS.clear(); + return *this; +} + +/// Storage for the SmallVector elements which aren't contained in +/// SmallVectorTemplateCommon. There are 'N-1' elements here. The remaining '1' +/// element is in the base class. This is specialized for the N=1 and N=0 cases +/// to avoid allocating unnecessary storage. +template <typename T, unsigned N> +struct SmallVectorStorage { + typename SmallVectorTemplateCommon<T>::U InlineElts[N - 1]; +}; +template <typename T> struct SmallVectorStorage<T, 1> {}; +template <typename T> struct SmallVectorStorage<T, 0> {}; + +/// This is a 'vector' (really, a variable-sized array), optimized +/// for the case when the array is small. It contains some number of elements +/// in-place, which allows it to avoid heap allocation when the actual number of +/// elements is below that threshold. This allows normal "small" cases to be +/// fast without losing generality for large inputs. +/// +/// Note that this does not attempt to be exception safe. +/// +template <typename T, unsigned N> +class SmallVector : public SmallVectorImpl<T> { + /// Inline space for elements which aren't stored in the base class. + SmallVectorStorage<T, N> Storage; +public: + SmallVector() : SmallVectorImpl<T>(N) { + } + + explicit SmallVector(size_t Size, const T &Value = T()) + : SmallVectorImpl<T>(N) { + this->assign(Size, Value); + } + + template<typename ItTy> + SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) { + this->append(S, E); + } + + template <typename RangeTy> + explicit SmallVector(const llvm::iterator_range<RangeTy> &R) + : SmallVectorImpl<T>(N) { + this->append(R.begin(), R.end()); + } + + SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) { + this->assign(IL); + } + + SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) { + if (!RHS.empty()) + SmallVectorImpl<T>::operator=(RHS); + } + + const SmallVector &operator=(const SmallVector &RHS) { + SmallVectorImpl<T>::operator=(RHS); + return *this; + } + + SmallVector(SmallVector &&RHS) : SmallVectorImpl<T>(N) { + if (!RHS.empty()) + SmallVectorImpl<T>::operator=(::std::move(RHS)); + } + + const SmallVector &operator=(SmallVector &&RHS) { + SmallVectorImpl<T>::operator=(::std::move(RHS)); + return *this; + } + + SmallVector(SmallVectorImpl<T> &&RHS) : SmallVectorImpl<T>(N) { + if (!RHS.empty()) + SmallVectorImpl<T>::operator=(::std::move(RHS)); + } + + const SmallVector &operator=(SmallVectorImpl<T> &&RHS) { + SmallVectorImpl<T>::operator=(::std::move(RHS)); + return *this; + } + + const SmallVector &operator=(std::initializer_list<T> IL) { + this->assign(IL); + return *this; + } +}; + +template<typename T, unsigned N> +static inline size_t capacity_in_bytes(const SmallVector<T, N> &X) { + return X.capacity_in_bytes(); +} + +} // End llvm namespace + +namespace std { + /// Implement std::swap in terms of SmallVector swap. + template<typename T> + inline void + swap(llvm::SmallVectorImpl<T> &LHS, llvm::SmallVectorImpl<T> &RHS) { + LHS.swap(RHS); + } + + /// Implement std::swap in terms of SmallVector swap. + template<typename T, unsigned N> + inline void + swap(llvm::SmallVector<T, N> &LHS, llvm::SmallVector<T, N> &RHS) { + LHS.swap(RHS); + } +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/Statistic.h b/third_party/llvm-subzero/include/llvm/ADT/Statistic.h new file mode 100644 index 0000000..c541383 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/Statistic.h
@@ -0,0 +1,173 @@ +//===-- llvm/ADT/Statistic.h - Easy way to expose stats ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the 'Statistic' class, which is designed to be an easy way +// to expose various metrics from passes. These statistics are printed at the +// end of a run (from llvm_shutdown), when the -stats command line option is +// passed on the command line. +// +// This is useful for reporting information like the number of instructions +// simplified, optimized or removed by various transformations, like this: +// +// static Statistic NumInstsKilled("gcse", "Number of instructions killed"); +// +// Later, in the code: ++NumInstsKilled; +// +// NOTE: Statistics *must* be declared as global variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STATISTIC_H +#define LLVM_ADT_STATISTIC_H + +#include "llvm/Support/Atomic.h" +#include "llvm/Support/Compiler.h" +#include <atomic> +#include <memory> + +namespace llvm { + +class raw_ostream; +class raw_fd_ostream; + +class Statistic { +public: + const char *DebugType; + const char *Name; + const char *Desc; + std::atomic<unsigned> Value; + bool Initialized; + + unsigned getValue() const { return Value.load(std::memory_order_relaxed); } + const char *getDebugType() const { return DebugType; } + const char *getName() const { return Name; } + const char *getDesc() const { return Desc; } + + /// construct - This should only be called for non-global statistics. + void construct(const char *debugtype, const char *name, const char *desc) { + DebugType = debugtype; + Name = name; + Desc = desc; + Value = 0; + Initialized = false; + } + + // Allow use of this class as the value itself. + operator unsigned() const { return getValue(); } + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) + const Statistic &operator=(unsigned Val) { + Value.store(Val, std::memory_order_relaxed); + return init(); + } + + const Statistic &operator++() { + Value.fetch_add(1, std::memory_order_relaxed); + return init(); + } + + unsigned operator++(int) { + init(); + return Value.fetch_add(1, std::memory_order_relaxed); + } + + const Statistic &operator--() { + Value.fetch_sub(1, std::memory_order_relaxed); + return init(); + } + + unsigned operator--(int) { + init(); + return Value.fetch_sub(1, std::memory_order_relaxed); + } + + const Statistic &operator+=(unsigned V) { + if (V == 0) + return *this; + Value.fetch_add(V, std::memory_order_relaxed); + return init(); + } + + const Statistic &operator-=(unsigned V) { + if (V == 0) + return *this; + Value.fetch_sub(V, std::memory_order_relaxed); + return init(); + } + +#else // Statistics are disabled in release builds. + + const Statistic &operator=(unsigned Val) { + return *this; + } + + const Statistic &operator++() { + return *this; + } + + unsigned operator++(int) { + return 0; + } + + const Statistic &operator--() { + return *this; + } + + unsigned operator--(int) { + return 0; + } + + const Statistic &operator+=(const unsigned &V) { + return *this; + } + + const Statistic &operator-=(const unsigned &V) { + return *this; + } + +#endif // !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) + +protected: + Statistic &init() { + bool tmp = Initialized; + sys::MemoryFence(); + if (!tmp) RegisterStatistic(); + TsanHappensAfter(this); + return *this; + } + + void RegisterStatistic(); +}; + +// STATISTIC - A macro to make definition of statistics really simple. This +// automatically passes the DEBUG_TYPE of the file into the statistic. +#define STATISTIC(VARNAME, DESC) \ + static llvm::Statistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC, {0}, false} + +/// \brief Enable the collection and printing of statistics. +void EnableStatistics(); + +/// \brief Check if statistics are enabled. +bool AreStatisticsEnabled(); + +/// \brief Return a file stream to print our output on. +std::unique_ptr<raw_fd_ostream> CreateInfoOutputFile(); + +/// \brief Print statistics to the file returned by CreateInfoOutputFile(). +void PrintStatistics(); + +/// \brief Print statistics to the given output stream. +void PrintStatistics(raw_ostream &OS); + +/// Print statistics in JSON format. +void PrintStatisticsJSON(raw_ostream &OS); + +} // end namespace llvm + +#endif // LLVM_ADT_STATISTIC_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/StringExtras.h b/third_party/llvm-subzero/include/llvm/ADT/StringExtras.h new file mode 100644 index 0000000..05513e1 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/StringExtras.h
@@ -0,0 +1,202 @@ +//===-- llvm/ADT/StringExtras.h - Useful string functions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some functions that are useful when dealing with strings. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGEXTRAS_H +#define LLVM_ADT_STRINGEXTRAS_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include <iterator> + +namespace llvm { +class raw_ostream; +template<typename T> class SmallVectorImpl; + +/// hexdigit - Return the hexadecimal character for the +/// given number \p X (which should be less than 16). +static inline char hexdigit(unsigned X, bool LowerCase = false) { + const char HexChar = LowerCase ? 'a' : 'A'; + return X < 10 ? '0' + X : HexChar + X - 10; +} + +/// Construct a string ref from a boolean. +static inline StringRef toStringRef(bool B) { + return StringRef(B ? "true" : "false"); +} + +/// Interpret the given character \p C as a hexadecimal digit and return its +/// value. +/// +/// If \p C is not a valid hex digit, -1U is returned. +static inline unsigned hexDigitValue(char C) { + if (C >= '0' && C <= '9') return C-'0'; + if (C >= 'a' && C <= 'f') return C-'a'+10U; + if (C >= 'A' && C <= 'F') return C-'A'+10U; + return -1U; +} + +static inline std::string utohexstr(uint64_t X, bool LowerCase = false) { + char Buffer[17]; + char *BufPtr = std::end(Buffer); + + if (X == 0) *--BufPtr = '0'; + + while (X) { + unsigned char Mod = static_cast<unsigned char>(X) & 15; + *--BufPtr = hexdigit(Mod, LowerCase); + X >>= 4; + } + + return std::string(BufPtr, std::end(Buffer)); +} + +/// Convert buffer \p Input to its hexadecimal representation. +/// The returned string is double the size of \p Input. +static inline std::string toHex(StringRef Input) { + static const char *const LUT = "0123456789ABCDEF"; + size_t Length = Input.size(); + + std::string Output; + Output.reserve(2 * Length); + for (size_t i = 0; i < Length; ++i) { + const unsigned char c = Input[i]; + Output.push_back(LUT[c >> 4]); + Output.push_back(LUT[c & 15]); + } + return Output; +} + +static inline std::string utostr(uint64_t X, bool isNeg = false) { + char Buffer[21]; + char *BufPtr = std::end(Buffer); + + if (X == 0) *--BufPtr = '0'; // Handle special case... + + while (X) { + *--BufPtr = '0' + char(X % 10); + X /= 10; + } + + if (isNeg) *--BufPtr = '-'; // Add negative sign... + return std::string(BufPtr, std::end(Buffer)); +} + + +static inline std::string itostr(int64_t X) { + if (X < 0) + return utostr(static_cast<uint64_t>(-X), true); + else + return utostr(static_cast<uint64_t>(X)); +} + +/// StrInStrNoCase - Portable version of strcasestr. Locates the first +/// occurrence of string 's1' in string 's2', ignoring case. Returns +/// the offset of s2 in s1 or npos if s2 cannot be found. +StringRef::size_type StrInStrNoCase(StringRef s1, StringRef s2); + +/// getToken - This function extracts one token from source, ignoring any +/// leading characters that appear in the Delimiters string, and ending the +/// token at any of the characters that appear in the Delimiters string. If +/// there are no tokens in the source string, an empty string is returned. +/// The function returns a pair containing the extracted token and the +/// remaining tail string. +std::pair<StringRef, StringRef> getToken(StringRef Source, + StringRef Delimiters = " \t\n\v\f\r"); + +/// SplitString - Split up the specified string according to the specified +/// delimiters, appending the result fragments to the output list. +void SplitString(StringRef Source, + SmallVectorImpl<StringRef> &OutFragments, + StringRef Delimiters = " \t\n\v\f\r"); + +/// HashString - Hash function for strings. +/// +/// This is the Bernstein hash function. +// +// FIXME: Investigate whether a modified bernstein hash function performs +// better: http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx +// X*33+c -> X*33^c +static inline unsigned HashString(StringRef Str, unsigned Result = 0) { + for (StringRef::size_type i = 0, e = Str.size(); i != e; ++i) + Result = Result * 33 + (unsigned char)Str[i]; + return Result; +} + +/// Returns the English suffix for an ordinal integer (-st, -nd, -rd, -th). +static inline StringRef getOrdinalSuffix(unsigned Val) { + // It is critically important that we do this perfectly for + // user-written sequences with over 100 elements. + switch (Val % 100) { + case 11: + case 12: + case 13: + return "th"; + default: + switch (Val % 10) { + case 1: return "st"; + case 2: return "nd"; + case 3: return "rd"; + default: return "th"; + } + } +} + +/// PrintEscapedString - Print each character of the specified string, escaping +/// it if it is not printable or if it is an escape char. +void PrintEscapedString(StringRef Name, raw_ostream &Out); + +template <typename IteratorT> +inline std::string join_impl(IteratorT Begin, IteratorT End, + StringRef Separator, std::input_iterator_tag) { + std::string S; + if (Begin == End) + return S; + + S += (*Begin); + while (++Begin != End) { + S += Separator; + S += (*Begin); + } + return S; +} + +template <typename IteratorT> +inline std::string join_impl(IteratorT Begin, IteratorT End, + StringRef Separator, std::forward_iterator_tag) { + std::string S; + if (Begin == End) + return S; + + size_t Len = (std::distance(Begin, End) - 1) * Separator.size(); + for (IteratorT I = Begin; I != End; ++I) + Len += (*Begin).size(); + S.reserve(Len); + S += (*Begin); + while (++Begin != End) { + S += Separator; + S += (*Begin); + } + return S; +} + +/// Joins the strings in the range [Begin, End), adding Separator between +/// the elements. +template <typename IteratorT> +inline std::string join(IteratorT Begin, IteratorT End, StringRef Separator) { + typedef typename std::iterator_traits<IteratorT>::iterator_category tag; + return join_impl(Begin, End, Separator, tag()); +} + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/StringMap.h b/third_party/llvm-subzero/include/llvm/ADT/StringMap.h new file mode 100644 index 0000000..5c048b1 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/StringMap.h
@@ -0,0 +1,503 @@ +//===--- StringMap.h - String Hash table map interface ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the StringMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGMAP_H +#define LLVM_ADT_STRINGMAP_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include <cstring> +#include <utility> + +namespace llvm { + template<typename ValueT> + class StringMapConstIterator; + template<typename ValueT> + class StringMapIterator; + template<typename ValueTy> + class StringMapEntry; + +/// StringMapEntryBase - Shared base class of StringMapEntry instances. +class StringMapEntryBase { + unsigned StrLen; + +public: + explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {} + + unsigned getKeyLength() const { return StrLen; } +}; + +/// StringMapImpl - This is the base class of StringMap that is shared among +/// all of its instantiations. +class StringMapImpl { +protected: + // Array of NumBuckets pointers to entries, null pointers are holes. + // TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed + // by an array of the actual hash values as unsigned integers. + StringMapEntryBase **TheTable; + unsigned NumBuckets; + unsigned NumItems; + unsigned NumTombstones; + unsigned ItemSize; + +protected: + explicit StringMapImpl(unsigned itemSize) + : TheTable(nullptr), + // Initialize the map with zero buckets to allocation. + NumBuckets(0), NumItems(0), NumTombstones(0), ItemSize(itemSize) {} + StringMapImpl(StringMapImpl &&RHS) + : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets), + NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones), + ItemSize(RHS.ItemSize) { + RHS.TheTable = nullptr; + RHS.NumBuckets = 0; + RHS.NumItems = 0; + RHS.NumTombstones = 0; + } + + StringMapImpl(unsigned InitSize, unsigned ItemSize); + unsigned RehashTable(unsigned BucketNo = 0); + + /// LookupBucketFor - Look up the bucket that the specified string should end + /// up in. If it already exists as a key in the map, the Item pointer for the + /// specified bucket will be non-null. Otherwise, it will be null. In either + /// case, the FullHashValue field of the bucket will be set to the hash value + /// of the string. + unsigned LookupBucketFor(StringRef Key); + + /// FindKey - Look up the bucket that contains the specified key. If it exists + /// in the map, return the bucket number of the key. Otherwise return -1. + /// This does not modify the map. + int FindKey(StringRef Key) const; + + /// RemoveKey - Remove the specified StringMapEntry from the table, but do not + /// delete it. This aborts if the value isn't in the table. + void RemoveKey(StringMapEntryBase *V); + + /// RemoveKey - Remove the StringMapEntry for the specified key from the + /// table, returning it. If the key is not in the table, this returns null. + StringMapEntryBase *RemoveKey(StringRef Key); + + /// Allocate the table with the specified number of buckets and otherwise + /// setup the map as empty. + void init(unsigned Size); + +public: + static StringMapEntryBase *getTombstoneVal() { + uintptr_t Val = static_cast<uintptr_t>(-1); + Val <<= PointerLikeTypeTraits<StringMapEntryBase *>::NumLowBitsAvailable; + return reinterpret_cast<StringMapEntryBase *>(Val); + } + + unsigned getNumBuckets() const { return NumBuckets; } + unsigned getNumItems() const { return NumItems; } + + bool empty() const { return NumItems == 0; } + unsigned size() const { return NumItems; } + + void swap(StringMapImpl &Other) { + std::swap(TheTable, Other.TheTable); + std::swap(NumBuckets, Other.NumBuckets); + std::swap(NumItems, Other.NumItems); + std::swap(NumTombstones, Other.NumTombstones); + } +}; + +/// StringMapEntry - This is used to represent one value that is inserted into +/// a StringMap. It contains the Value itself and the key: the string length +/// and data. +template<typename ValueTy> +class StringMapEntry : public StringMapEntryBase { + StringMapEntry(StringMapEntry &E) = delete; + +public: + ValueTy second; + + explicit StringMapEntry(unsigned strLen) + : StringMapEntryBase(strLen), second() {} + template <typename... InitTy> + StringMapEntry(unsigned strLen, InitTy &&... InitVals) + : StringMapEntryBase(strLen), second(std::forward<InitTy>(InitVals)...) {} + + StringRef getKey() const { + return StringRef(getKeyData(), getKeyLength()); + } + + const ValueTy &getValue() const { return second; } + ValueTy &getValue() { return second; } + + void setValue(const ValueTy &V) { second = V; } + + /// getKeyData - Return the start of the string data that is the key for this + /// value. The string data is always stored immediately after the + /// StringMapEntry object. + const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);} + + StringRef first() const { return StringRef(getKeyData(), getKeyLength()); } + + /// Create a StringMapEntry for the specified key construct the value using + /// \p InitiVals. + template <typename AllocatorTy, typename... InitTy> + static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator, + InitTy &&... InitVals) { + unsigned KeyLength = Key.size(); + + // Allocate a new item with space for the string at the end and a null + // terminator. + unsigned AllocSize = static_cast<unsigned>(sizeof(StringMapEntry))+ + KeyLength+1; + unsigned Alignment = alignOf<StringMapEntry>(); + + StringMapEntry *NewItem = + static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment)); + + // Construct the value. + new (NewItem) StringMapEntry(KeyLength, std::forward<InitTy>(InitVals)...); + + // Copy the string information. + char *StrBuffer = const_cast<char*>(NewItem->getKeyData()); + if (KeyLength > 0) + memcpy(StrBuffer, Key.data(), KeyLength); + StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients. + return NewItem; + } + + /// Create - Create a StringMapEntry with normal malloc/free. + template <typename... InitType> + static StringMapEntry *Create(StringRef Key, InitType &&... InitVal) { + MallocAllocator A; + return Create(Key, A, std::forward<InitType>(InitVal)...); + } + + static StringMapEntry *Create(StringRef Key) { + return Create(Key, ValueTy()); + } + + /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded + /// into a StringMapEntry, return the StringMapEntry itself. + static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) { + char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>); + return *reinterpret_cast<StringMapEntry*>(Ptr); + } + + /// Destroy - Destroy this StringMapEntry, releasing memory back to the + /// specified allocator. + template<typename AllocatorTy> + void Destroy(AllocatorTy &Allocator) { + // Free memory referenced by the item. + unsigned AllocSize = + static_cast<unsigned>(sizeof(StringMapEntry)) + getKeyLength() + 1; + this->~StringMapEntry(); + Allocator.Deallocate(static_cast<void *>(this), AllocSize); + } + + /// Destroy this object, releasing memory back to the malloc allocator. + void Destroy() { + MallocAllocator A; + Destroy(A); + } +}; + +/// StringMap - This is an unconventional map that is specialized for handling +/// keys that are "strings", which are basically ranges of bytes. This does some +/// funky memory allocation and hashing things to make it extremely efficient, +/// storing the string data *after* the value in the map. +template<typename ValueTy, typename AllocatorTy = MallocAllocator> +class StringMap : public StringMapImpl { + AllocatorTy Allocator; + +public: + typedef StringMapEntry<ValueTy> MapEntryTy; + + StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {} + explicit StringMap(unsigned InitialSize) + : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {} + + explicit StringMap(AllocatorTy A) + : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {} + + StringMap(unsigned InitialSize, AllocatorTy A) + : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))), + Allocator(A) {} + + StringMap(std::initializer_list<std::pair<StringRef, ValueTy>> List) + : StringMapImpl(List.size(), static_cast<unsigned>(sizeof(MapEntryTy))) { + for (const auto &P : List) { + insert(P); + } + } + + StringMap(StringMap &&RHS) + : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {} + + StringMap &operator=(StringMap RHS) { + StringMapImpl::swap(RHS); + std::swap(Allocator, RHS.Allocator); + return *this; + } + + StringMap(const StringMap &RHS) : + StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), + Allocator(RHS.Allocator) { + if (RHS.empty()) + return; + + // Allocate TheTable of the same size as RHS's TheTable, and set the + // sentinel appropriately (and NumBuckets). + init(RHS.NumBuckets); + unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1), + *RHSHashTable = (unsigned *)(RHS.TheTable + NumBuckets + 1); + + NumItems = RHS.NumItems; + NumTombstones = RHS.NumTombstones; + for (unsigned I = 0, E = NumBuckets; I != E; ++I) { + StringMapEntryBase *Bucket = RHS.TheTable[I]; + if (!Bucket || Bucket == getTombstoneVal()) { + TheTable[I] = Bucket; + continue; + } + + TheTable[I] = MapEntryTy::Create( + static_cast<MapEntryTy *>(Bucket)->getKey(), Allocator, + static_cast<MapEntryTy *>(Bucket)->getValue()); + HashTable[I] = RHSHashTable[I]; + } + + // Note that here we've copied everything from the RHS into this object, + // tombstones included. We could, instead, have re-probed for each key to + // instantiate this new object without any tombstone buckets. The + // assumption here is that items are rarely deleted from most StringMaps, + // and so tombstones are rare, so the cost of re-probing for all inputs is + // not worthwhile. + } + + AllocatorTy &getAllocator() { return Allocator; } + const AllocatorTy &getAllocator() const { return Allocator; } + + typedef const char* key_type; + typedef ValueTy mapped_type; + typedef StringMapEntry<ValueTy> value_type; + typedef size_t size_type; + + typedef StringMapConstIterator<ValueTy> const_iterator; + typedef StringMapIterator<ValueTy> iterator; + + iterator begin() { + return iterator(TheTable, NumBuckets == 0); + } + iterator end() { + return iterator(TheTable+NumBuckets, true); + } + const_iterator begin() const { + return const_iterator(TheTable, NumBuckets == 0); + } + const_iterator end() const { + return const_iterator(TheTable+NumBuckets, true); + } + + iterator find(StringRef Key) { + int Bucket = FindKey(Key); + if (Bucket == -1) return end(); + return iterator(TheTable+Bucket, true); + } + + const_iterator find(StringRef Key) const { + int Bucket = FindKey(Key); + if (Bucket == -1) return end(); + return const_iterator(TheTable+Bucket, true); + } + + /// lookup - Return the entry for the specified key, or a default + /// constructed value if no such entry exists. + ValueTy lookup(StringRef Key) const { + const_iterator it = find(Key); + if (it != end()) + return it->second; + return ValueTy(); + } + + /// Lookup the ValueTy for the \p Key, or create a default constructed value + /// if the key is not in the map. + ValueTy &operator[](StringRef Key) { return try_emplace(Key).first->second; } + + /// count - Return 1 if the element is in the map, 0 otherwise. + size_type count(StringRef Key) const { + return find(Key) == end() ? 0 : 1; + } + + /// insert - Insert the specified key/value pair into the map. If the key + /// already exists in the map, return false and ignore the request, otherwise + /// insert it and return true. + bool insert(MapEntryTy *KeyValue) { + unsigned BucketNo = LookupBucketFor(KeyValue->getKey()); + StringMapEntryBase *&Bucket = TheTable[BucketNo]; + if (Bucket && Bucket != getTombstoneVal()) + return false; // Already exists in map. + + if (Bucket == getTombstoneVal()) + --NumTombstones; + Bucket = KeyValue; + ++NumItems; + assert(NumItems + NumTombstones <= NumBuckets); + + RehashTable(); + return true; + } + + /// insert - Inserts the specified key/value pair into the map if the key + /// isn't already in the map. The bool component of the returned pair is true + /// if and only if the insertion takes place, and the iterator component of + /// the pair points to the element with key equivalent to the key of the pair. + std::pair<iterator, bool> insert(std::pair<StringRef, ValueTy> KV) { + return try_emplace(KV.first, std::move(KV.second)); + } + + /// Emplace a new element for the specified key into the map if the key isn't + /// already in the map. The bool component of the returned pair is true + /// if and only if the insertion takes place, and the iterator component of + /// the pair points to the element with key equivalent to the key of the pair. + template <typename... ArgsTy> + std::pair<iterator, bool> try_emplace(StringRef Key, ArgsTy &&... Args) { + unsigned BucketNo = LookupBucketFor(Key); + StringMapEntryBase *&Bucket = TheTable[BucketNo]; + if (Bucket && Bucket != getTombstoneVal()) + return std::make_pair(iterator(TheTable + BucketNo, false), + false); // Already exists in map. + + if (Bucket == getTombstoneVal()) + --NumTombstones; + Bucket = MapEntryTy::Create(Key, Allocator, std::forward<ArgsTy>(Args)...); + ++NumItems; + assert(NumItems + NumTombstones <= NumBuckets); + + BucketNo = RehashTable(BucketNo); + return std::make_pair(iterator(TheTable + BucketNo, false), true); + } + + // clear - Empties out the StringMap + void clear() { + if (empty()) return; + + // Zap all values, resetting the keys back to non-present (not tombstone), + // which is safe because we're removing all elements. + for (unsigned I = 0, E = NumBuckets; I != E; ++I) { + StringMapEntryBase *&Bucket = TheTable[I]; + if (Bucket && Bucket != getTombstoneVal()) { + static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator); + } + Bucket = nullptr; + } + + NumItems = 0; + NumTombstones = 0; + } + + /// remove - Remove the specified key/value pair from the map, but do not + /// erase it. This aborts if the key is not in the map. + void remove(MapEntryTy *KeyValue) { + RemoveKey(KeyValue); + } + + void erase(iterator I) { + MapEntryTy &V = *I; + remove(&V); + V.Destroy(Allocator); + } + + bool erase(StringRef Key) { + iterator I = find(Key); + if (I == end()) return false; + erase(I); + return true; + } + + ~StringMap() { + // Delete all the elements in the map, but don't reset the elements + // to default values. This is a copy of clear(), but avoids unnecessary + // work not required in the destructor. + if (!empty()) { + for (unsigned I = 0, E = NumBuckets; I != E; ++I) { + StringMapEntryBase *Bucket = TheTable[I]; + if (Bucket && Bucket != getTombstoneVal()) { + static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator); + } + } + } + free(TheTable); + } +}; + +template <typename ValueTy> class StringMapConstIterator { +protected: + StringMapEntryBase **Ptr; + +public: + typedef StringMapEntry<ValueTy> value_type; + + StringMapConstIterator() : Ptr(nullptr) { } + + explicit StringMapConstIterator(StringMapEntryBase **Bucket, + bool NoAdvance = false) + : Ptr(Bucket) { + if (!NoAdvance) AdvancePastEmptyBuckets(); + } + + const value_type &operator*() const { + return *static_cast<StringMapEntry<ValueTy>*>(*Ptr); + } + const value_type *operator->() const { + return static_cast<StringMapEntry<ValueTy>*>(*Ptr); + } + + bool operator==(const StringMapConstIterator &RHS) const { + return Ptr == RHS.Ptr; + } + bool operator!=(const StringMapConstIterator &RHS) const { + return Ptr != RHS.Ptr; + } + + inline StringMapConstIterator& operator++() { // Preincrement + ++Ptr; + AdvancePastEmptyBuckets(); + return *this; + } + StringMapConstIterator operator++(int) { // Postincrement + StringMapConstIterator tmp = *this; ++*this; return tmp; + } + +private: + void AdvancePastEmptyBuckets() { + while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal()) + ++Ptr; + } +}; + +template<typename ValueTy> +class StringMapIterator : public StringMapConstIterator<ValueTy> { +public: + StringMapIterator() {} + explicit StringMapIterator(StringMapEntryBase **Bucket, + bool NoAdvance = false) + : StringMapConstIterator<ValueTy>(Bucket, NoAdvance) { + } + StringMapEntry<ValueTy> &operator*() const { + return *static_cast<StringMapEntry<ValueTy>*>(*this->Ptr); + } + StringMapEntry<ValueTy> *operator->() const { + return static_cast<StringMapEntry<ValueTy>*>(*this->Ptr); + } +}; +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/StringRef.h b/third_party/llvm-subzero/include/llvm/ADT/StringRef.h new file mode 100644 index 0000000..37c214c --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/StringRef.h
@@ -0,0 +1,693 @@ +//===--- StringRef.h - Constant String Reference Wrapper --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGREF_H +#define LLVM_ADT_STRINGREF_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Compiler.h" +#include <algorithm> +#include <cassert> +#include <cstring> +#include <limits> +#include <string> +#include <utility> + +namespace llvm { + template <typename T> + class SmallVectorImpl; + class APInt; + class hash_code; + class StringRef; + + /// Helper functions for StringRef::getAsInteger. + bool getAsUnsignedInteger(StringRef Str, unsigned Radix, + unsigned long long &Result); + + bool getAsSignedInteger(StringRef Str, unsigned Radix, long long &Result); + + /// StringRef - Represent a constant reference to a string, i.e. a character + /// array and a length, which need not be null terminated. + /// + /// This class does not own the string data, it is expected to be used in + /// situations where the character data resides in some other buffer, whose + /// lifetime extends past that of the StringRef. For this reason, it is not in + /// general safe to store a StringRef. + class StringRef { + public: + typedef const char *iterator; + typedef const char *const_iterator; + static const size_t npos = ~size_t(0); + typedef size_t size_type; + + private: + /// The start of the string, in an external buffer. + const char *Data; + + /// The length of the string. + size_t Length; + + // Workaround memcmp issue with null pointers (undefined behavior) + // by providing a specialized version + LLVM_ATTRIBUTE_ALWAYS_INLINE + static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) { + if (Length == 0) { return 0; } + return ::memcmp(Lhs,Rhs,Length); + } + + public: + /// @name Constructors + /// @{ + + /// Construct an empty string ref. + /*implicit*/ StringRef() : Data(nullptr), Length(0) {} + + /// Construct a string ref from a cstring. + /*implicit*/ StringRef(const char *Str) + : Data(Str) { + assert(Str && "StringRef cannot be built from a NULL argument"); + Length = ::strlen(Str); // invoking strlen(NULL) is undefined behavior + } + + /// Construct a string ref from a pointer and length. + LLVM_ATTRIBUTE_ALWAYS_INLINE + /*implicit*/ StringRef(const char *data, size_t length) + : Data(data), Length(length) { + assert((data || length == 0) && + "StringRef cannot be built from a NULL argument with non-null length"); + } + + /// Construct a string ref from an std::string. + LLVM_ATTRIBUTE_ALWAYS_INLINE + /*implicit*/ StringRef(const std::string &Str) + : Data(Str.data()), Length(Str.length()) {} + + /// @} + /// @name Iterators + /// @{ + + iterator begin() const { return Data; } + + iterator end() const { return Data + Length; } + + const unsigned char *bytes_begin() const { + return reinterpret_cast<const unsigned char *>(begin()); + } + const unsigned char *bytes_end() const { + return reinterpret_cast<const unsigned char *>(end()); + } + iterator_range<const unsigned char *> bytes() const { + return make_range(bytes_begin(), bytes_end()); + } + + /// @} + /// @name String Operations + /// @{ + + /// data - Get a pointer to the start of the string (which may not be null + /// terminated). + LLVM_ATTRIBUTE_ALWAYS_INLINE + const char *data() const { return Data; } + + /// empty - Check if the string is empty. + LLVM_ATTRIBUTE_ALWAYS_INLINE + bool empty() const { return Length == 0; } + + /// size - Get the string size. + LLVM_ATTRIBUTE_ALWAYS_INLINE + size_t size() const { return Length; } + + /// front - Get the first character in the string. + char front() const { + assert(!empty()); + return Data[0]; + } + + /// back - Get the last character in the string. + char back() const { + assert(!empty()); + return Data[Length-1]; + } + + // copy - Allocate copy in Allocator and return StringRef to it. + template <typename Allocator> StringRef copy(Allocator &A) const { + // Don't request a length 0 copy from the allocator. + if (empty()) + return StringRef(); + char *S = A.template Allocate<char>(Length); + std::copy(begin(), end(), S); + return StringRef(S, Length); + } + + /// equals - Check for string equality, this is more efficient than + /// compare() when the relative ordering of inequal strings isn't needed. + LLVM_ATTRIBUTE_ALWAYS_INLINE + bool equals(StringRef RHS) const { + return (Length == RHS.Length && + compareMemory(Data, RHS.Data, RHS.Length) == 0); + } + + /// equals_lower - Check for string equality, ignoring case. + bool equals_lower(StringRef RHS) const { + return Length == RHS.Length && compare_lower(RHS) == 0; + } + + /// compare - Compare two strings; the result is -1, 0, or 1 if this string + /// is lexicographically less than, equal to, or greater than the \p RHS. + LLVM_ATTRIBUTE_ALWAYS_INLINE + int compare(StringRef RHS) const { + // Check the prefix for a mismatch. + if (int Res = compareMemory(Data, RHS.Data, std::min(Length, RHS.Length))) + return Res < 0 ? -1 : 1; + + // Otherwise the prefixes match, so we only need to check the lengths. + if (Length == RHS.Length) + return 0; + return Length < RHS.Length ? -1 : 1; + } + + /// compare_lower - Compare two strings, ignoring case. + int compare_lower(StringRef RHS) const; + + /// compare_numeric - Compare two strings, treating sequences of digits as + /// numbers. + int compare_numeric(StringRef RHS) const; + + /// \brief Determine the edit distance between this string and another + /// string. + /// + /// \param Other the string to compare this string against. + /// + /// \param AllowReplacements whether to allow character + /// replacements (change one character into another) as a single + /// operation, rather than as two operations (an insertion and a + /// removal). + /// + /// \param MaxEditDistance If non-zero, the maximum edit distance that + /// this routine is allowed to compute. If the edit distance will exceed + /// that maximum, returns \c MaxEditDistance+1. + /// + /// \returns the minimum number of character insertions, removals, + /// or (if \p AllowReplacements is \c true) replacements needed to + /// transform one of the given strings into the other. If zero, + /// the strings are identical. + unsigned edit_distance(StringRef Other, bool AllowReplacements = true, + unsigned MaxEditDistance = 0) const; + + /// str - Get the contents as an std::string. + std::string str() const { + if (!Data) return std::string(); + return std::string(Data, Length); + } + + /// @} + /// @name Operator Overloads + /// @{ + + char operator[](size_t Index) const { + assert(Index < Length && "Invalid index!"); + return Data[Index]; + } + + /// @} + /// @name Type Conversions + /// @{ + + operator std::string() const { + return str(); + } + + /// @} + /// @name String Predicates + /// @{ + + /// Check if this string starts with the given \p Prefix. + LLVM_ATTRIBUTE_ALWAYS_INLINE + bool startswith(StringRef Prefix) const { + return Length >= Prefix.Length && + compareMemory(Data, Prefix.Data, Prefix.Length) == 0; + } + + /// Check if this string starts with the given \p Prefix, ignoring case. + bool startswith_lower(StringRef Prefix) const; + + /// Check if this string ends with the given \p Suffix. + LLVM_ATTRIBUTE_ALWAYS_INLINE + bool endswith(StringRef Suffix) const { + return Length >= Suffix.Length && + compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0; + } + + /// Check if this string ends with the given \p Suffix, ignoring case. + bool endswith_lower(StringRef Suffix) const; + + /// @} + /// @name String Searching + /// @{ + + /// Search for the first character \p C in the string. + /// + /// \returns The index of the first occurrence of \p C, or npos if not + /// found. + LLVM_ATTRIBUTE_ALWAYS_INLINE + size_t find(char C, size_t From = 0) const { + size_t FindBegin = std::min(From, Length); + if (FindBegin < Length) { // Avoid calling memchr with nullptr. + // Just forward to memchr, which is faster than a hand-rolled loop. + if (const void *P = ::memchr(Data + FindBegin, C, Length - FindBegin)) + return static_cast<const char *>(P) - Data; + } + return npos; + } + + /// Search for the first string \p Str in the string. + /// + /// \returns The index of the first occurrence of \p Str, or npos if not + /// found. + size_t find(StringRef Str, size_t From = 0) const; + + /// Search for the last character \p C in the string. + /// + /// \returns The index of the last occurrence of \p C, or npos if not + /// found. + size_t rfind(char C, size_t From = npos) const { + From = std::min(From, Length); + size_t i = From; + while (i != 0) { + --i; + if (Data[i] == C) + return i; + } + return npos; + } + + /// Search for the last string \p Str in the string. + /// + /// \returns The index of the last occurrence of \p Str, or npos if not + /// found. + size_t rfind(StringRef Str) const; + + /// Find the first character in the string that is \p C, or npos if not + /// found. Same as find. + size_t find_first_of(char C, size_t From = 0) const { + return find(C, From); + } + + /// Find the first character in the string that is in \p Chars, or npos if + /// not found. + /// + /// Complexity: O(size() + Chars.size()) + size_t find_first_of(StringRef Chars, size_t From = 0) const; + + /// Find the first character in the string that is not \p C or npos if not + /// found. + size_t find_first_not_of(char C, size_t From = 0) const; + + /// Find the first character in the string that is not in the string + /// \p Chars, or npos if not found. + /// + /// Complexity: O(size() + Chars.size()) + size_t find_first_not_of(StringRef Chars, size_t From = 0) const; + + /// Find the last character in the string that is \p C, or npos if not + /// found. + size_t find_last_of(char C, size_t From = npos) const { + return rfind(C, From); + } + + /// Find the last character in the string that is in \p C, or npos if not + /// found. + /// + /// Complexity: O(size() + Chars.size()) + size_t find_last_of(StringRef Chars, size_t From = npos) const; + + /// Find the last character in the string that is not \p C, or npos if not + /// found. + size_t find_last_not_of(char C, size_t From = npos) const; + + /// Find the last character in the string that is not in \p Chars, or + /// npos if not found. + /// + /// Complexity: O(size() + Chars.size()) + size_t find_last_not_of(StringRef Chars, size_t From = npos) const; + + /// Return true if the given string is a substring of *this, and false + /// otherwise. + LLVM_ATTRIBUTE_ALWAYS_INLINE + bool contains(StringRef Other) const { return find(Other) != npos; } + + /// @} + /// @name Helpful Algorithms + /// @{ + + /// Return the number of occurrences of \p C in the string. + size_t count(char C) const { + size_t Count = 0; + for (size_t i = 0, e = Length; i != e; ++i) + if (Data[i] == C) + ++Count; + return Count; + } + + /// Return the number of non-overlapped occurrences of \p Str in + /// the string. + size_t count(StringRef Str) const; + + /// Parse the current string as an integer of the specified radix. If + /// \p Radix is specified as zero, this does radix autosensing using + /// extended C rules: 0 is octal, 0x is hex, 0b is binary. + /// + /// If the string is invalid or if only a subset of the string is valid, + /// this returns true to signify the error. The string is considered + /// erroneous if empty or if it overflows T. + template <typename T> + typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type + getAsInteger(unsigned Radix, T &Result) const { + long long LLVal; + if (getAsSignedInteger(*this, Radix, LLVal) || + static_cast<T>(LLVal) != LLVal) + return true; + Result = LLVal; + return false; + } + + template <typename T> + typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type + getAsInteger(unsigned Radix, T &Result) const { + unsigned long long ULLVal; + // The additional cast to unsigned long long is required to avoid the + // Visual C++ warning C4805: '!=' : unsafe mix of type 'bool' and type + // 'unsigned __int64' when instantiating getAsInteger with T = bool. + if (getAsUnsignedInteger(*this, Radix, ULLVal) || + static_cast<unsigned long long>(static_cast<T>(ULLVal)) != ULLVal) + return true; + Result = ULLVal; + return false; + } + + /// Parse the current string as an integer of the specified \p Radix, or of + /// an autosensed radix if the \p Radix given is 0. The current value in + /// \p Result is discarded, and the storage is changed to be wide enough to + /// store the parsed integer. + /// + /// \returns true if the string does not solely consist of a valid + /// non-empty number in the appropriate base. + /// + /// APInt::fromString is superficially similar but assumes the + /// string is well-formed in the given radix. + bool getAsInteger(unsigned Radix, APInt &Result) const; + + /// @} + /// @name String Operations + /// @{ + + // Convert the given ASCII string to lowercase. + std::string lower() const; + + /// Convert the given ASCII string to uppercase. + std::string upper() const; + + /// @} + /// @name Substring Operations + /// @{ + + /// Return a reference to the substring from [Start, Start + N). + /// + /// \param Start The index of the starting character in the substring; if + /// the index is npos or greater than the length of the string then the + /// empty substring will be returned. + /// + /// \param N The number of characters to included in the substring. If N + /// exceeds the number of characters remaining in the string, the string + /// suffix (starting with \p Start) will be returned. + LLVM_ATTRIBUTE_ALWAYS_INLINE + LLVM_ATTRIBUTE_UNUSED_RESULT + StringRef substr(size_t Start, size_t N = npos) const { + Start = std::min(Start, Length); + return StringRef(Data + Start, std::min(N, Length - Start)); + } + + /// Return a StringRef equal to 'this' but with only the first \p N + /// elements remaining. If \p N is greater than the length of the + /// string, the entire string is returned. + LLVM_ATTRIBUTE_ALWAYS_INLINE + LLVM_ATTRIBUTE_UNUSED_RESULT + StringRef take_front(size_t N = 1) const { + if (N >= size()) + return *this; + return drop_back(size() - N); + } + + /// Return a StringRef equal to 'this' but with only the first \p N + /// elements remaining. If \p N is greater than the length of the + /// string, the entire string is returned. + LLVM_ATTRIBUTE_ALWAYS_INLINE + LLVM_ATTRIBUTE_UNUSED_RESULT + StringRef take_back(size_t N = 1) const { + if (N >= size()) + return *this; + return drop_front(size() - N); + } + + /// Return a StringRef equal to 'this' but with the first \p N elements + /// dropped. + LLVM_ATTRIBUTE_ALWAYS_INLINE + LLVM_ATTRIBUTE_UNUSED_RESULT + StringRef drop_front(size_t N = 1) const { + assert(size() >= N && "Dropping more elements than exist"); + return substr(N); + } + + /// Return a StringRef equal to 'this' but with the last \p N elements + /// dropped. + LLVM_ATTRIBUTE_ALWAYS_INLINE + LLVM_ATTRIBUTE_UNUSED_RESULT + StringRef drop_back(size_t N = 1) const { + assert(size() >= N && "Dropping more elements than exist"); + return substr(0, size()-N); + } + + /// Returns true if this StringRef has the given prefix and removes that + /// prefix. + LLVM_ATTRIBUTE_ALWAYS_INLINE + LLVM_ATTRIBUTE_UNUSED_RESULT + bool consume_front(StringRef Prefix) { + if (!startswith(Prefix)) + return false; + + *this = drop_front(Prefix.size()); + return true; + } + + /// Returns true if this StringRef has the given suffix and removes that + /// suffix. + LLVM_ATTRIBUTE_ALWAYS_INLINE + LLVM_ATTRIBUTE_UNUSED_RESULT + bool consume_back(StringRef Suffix) { + if (!endswith(Suffix)) + return false; + + *this = drop_back(Suffix.size()); + return true; + } + + /// Return a reference to the substring from [Start, End). + /// + /// \param Start The index of the starting character in the substring; if + /// the index is npos or greater than the length of the string then the + /// empty substring will be returned. + /// + /// \param End The index following the last character to include in the + /// substring. If this is npos or exceeds the number of characters + /// remaining in the string, the string suffix (starting with \p Start) + /// will be returned. If this is less than \p Start, an empty string will + /// be returned. + LLVM_ATTRIBUTE_ALWAYS_INLINE + LLVM_ATTRIBUTE_UNUSED_RESULT + StringRef slice(size_t Start, size_t End) const { + Start = std::min(Start, Length); + End = std::min(std::max(Start, End), Length); + return StringRef(Data + Start, End - Start); + } + + /// Split into two substrings around the first occurrence of a separator + /// character. + /// + /// If \p Separator is in the string, then the result is a pair (LHS, RHS) + /// such that (*this == LHS + Separator + RHS) is true and RHS is + /// maximal. If \p Separator is not in the string, then the result is a + /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). + /// + /// \param Separator The character to split on. + /// \returns The split substrings. + std::pair<StringRef, StringRef> split(char Separator) const { + size_t Idx = find(Separator); + if (Idx == npos) + return std::make_pair(*this, StringRef()); + return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); + } + + /// Split into two substrings around the first occurrence of a separator + /// string. + /// + /// If \p Separator is in the string, then the result is a pair (LHS, RHS) + /// such that (*this == LHS + Separator + RHS) is true and RHS is + /// maximal. If \p Separator is not in the string, then the result is a + /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). + /// + /// \param Separator - The string to split on. + /// \return - The split substrings. + std::pair<StringRef, StringRef> split(StringRef Separator) const { + size_t Idx = find(Separator); + if (Idx == npos) + return std::make_pair(*this, StringRef()); + return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos)); + } + + /// Split into substrings around the occurrences of a separator string. + /// + /// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most + /// \p MaxSplit splits are done and consequently <= \p MaxSplit + 1 + /// elements are added to A. + /// If \p KeepEmpty is false, empty strings are not added to \p A. They + /// still count when considering \p MaxSplit + /// An useful invariant is that + /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true + /// + /// \param A - Where to put the substrings. + /// \param Separator - The string to split on. + /// \param MaxSplit - The maximum number of times the string is split. + /// \param KeepEmpty - True if empty substring should be added. + void split(SmallVectorImpl<StringRef> &A, + StringRef Separator, int MaxSplit = -1, + bool KeepEmpty = true) const; + + /// Split into substrings around the occurrences of a separator character. + /// + /// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most + /// \p MaxSplit splits are done and consequently <= \p MaxSplit + 1 + /// elements are added to A. + /// If \p KeepEmpty is false, empty strings are not added to \p A. They + /// still count when considering \p MaxSplit + /// An useful invariant is that + /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true + /// + /// \param A - Where to put the substrings. + /// \param Separator - The string to split on. + /// \param MaxSplit - The maximum number of times the string is split. + /// \param KeepEmpty - True if empty substring should be added. + void split(SmallVectorImpl<StringRef> &A, char Separator, int MaxSplit = -1, + bool KeepEmpty = true) const; + + /// Split into two substrings around the last occurrence of a separator + /// character. + /// + /// If \p Separator is in the string, then the result is a pair (LHS, RHS) + /// such that (*this == LHS + Separator + RHS) is true and RHS is + /// minimal. If \p Separator is not in the string, then the result is a + /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). + /// + /// \param Separator - The character to split on. + /// \return - The split substrings. + std::pair<StringRef, StringRef> rsplit(char Separator) const { + size_t Idx = rfind(Separator); + if (Idx == npos) + return std::make_pair(*this, StringRef()); + return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); + } + + /// Return string with consecutive \p Char characters starting from the + /// the left removed. + LLVM_ATTRIBUTE_UNUSED_RESULT + StringRef ltrim(char Char) const { + return drop_front(std::min(Length, find_first_not_of(Char))); + } + + /// Return string with consecutive characters in \p Chars starting from + /// the left removed. + LLVM_ATTRIBUTE_UNUSED_RESULT + StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const { + return drop_front(std::min(Length, find_first_not_of(Chars))); + } + + /// Return string with consecutive \p Char characters starting from the + /// right removed. + LLVM_ATTRIBUTE_UNUSED_RESULT + StringRef rtrim(char Char) const { + return drop_back(Length - std::min(Length, find_last_not_of(Char) + 1)); + } + + /// Return string with consecutive characters in \p Chars starting from + /// the right removed. + LLVM_ATTRIBUTE_UNUSED_RESULT + StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const { + return drop_back(Length - std::min(Length, find_last_not_of(Chars) + 1)); + } + + /// Return string with consecutive \p Char characters starting from the + /// left and right removed. + LLVM_ATTRIBUTE_UNUSED_RESULT + StringRef trim(char Char) const { + return ltrim(Char).rtrim(Char); + } + + /// Return string with consecutive characters in \p Chars starting from + /// the left and right removed. + LLVM_ATTRIBUTE_UNUSED_RESULT + StringRef trim(StringRef Chars = " \t\n\v\f\r") const { + return ltrim(Chars).rtrim(Chars); + } + + /// @} + }; + + /// @name StringRef Comparison Operators + /// @{ + + LLVM_ATTRIBUTE_ALWAYS_INLINE + inline bool operator==(StringRef LHS, StringRef RHS) { + return LHS.equals(RHS); + } + + LLVM_ATTRIBUTE_ALWAYS_INLINE + inline bool operator!=(StringRef LHS, StringRef RHS) { + return !(LHS == RHS); + } + + inline bool operator<(StringRef LHS, StringRef RHS) { + return LHS.compare(RHS) == -1; + } + + inline bool operator<=(StringRef LHS, StringRef RHS) { + return LHS.compare(RHS) != 1; + } + + inline bool operator>(StringRef LHS, StringRef RHS) { + return LHS.compare(RHS) == 1; + } + + inline bool operator>=(StringRef LHS, StringRef RHS) { + return LHS.compare(RHS) != -1; + } + + inline std::string &operator+=(std::string &buffer, StringRef string) { + return buffer.append(string.data(), string.size()); + } + + /// @} + + /// \brief Compute a hash_code for a StringRef. + hash_code hash_value(StringRef S); + + // StringRefs can be treated like a POD type. + template <typename T> struct isPodLike; + template <> struct isPodLike<StringRef> { static const bool value = true; }; +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/StringSwitch.h b/third_party/llvm-subzero/include/llvm/ADT/StringSwitch.h new file mode 100644 index 0000000..bd200fc --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/StringSwitch.h
@@ -0,0 +1,181 @@ +//===--- StringSwitch.h - Switch-on-literal-string Construct --------------===/ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===/ +// +// This file implements the StringSwitch template, which mimics a switch() +// statement whose cases are string literals. +// +//===----------------------------------------------------------------------===/ +#ifndef LLVM_ADT_STRINGSWITCH_H +#define LLVM_ADT_STRINGSWITCH_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" +#include <cassert> +#include <cstring> + +namespace llvm { + +/// \brief A switch()-like statement whose cases are string literals. +/// +/// The StringSwitch class is a simple form of a switch() statement that +/// determines whether the given string matches one of the given string +/// literals. The template type parameter \p T is the type of the value that +/// will be returned from the string-switch expression. For example, +/// the following code switches on the name of a color in \c argv[i]: +/// +/// \code +/// Color color = StringSwitch<Color>(argv[i]) +/// .Case("red", Red) +/// .Case("orange", Orange) +/// .Case("yellow", Yellow) +/// .Case("green", Green) +/// .Case("blue", Blue) +/// .Case("indigo", Indigo) +/// .Cases("violet", "purple", Violet) +/// .Default(UnknownColor); +/// \endcode +template<typename T, typename R = T> +class StringSwitch { + /// \brief The string we are matching. + StringRef Str; + + /// \brief The pointer to the result of this switch statement, once known, + /// null before that. + const T *Result; + +public: + LLVM_ATTRIBUTE_ALWAYS_INLINE + explicit StringSwitch(StringRef S) + : Str(S), Result(nullptr) { } + + // StringSwitch is not copyable. + StringSwitch(const StringSwitch &) = delete; + void operator=(const StringSwitch &) = delete; + + StringSwitch(StringSwitch &&other) { + *this = std::move(other); + } + StringSwitch &operator=(StringSwitch &&other) { + Str = other.Str; + Result = other.Result; + return *this; + } + + ~StringSwitch() = default; + + template<unsigned N> + LLVM_ATTRIBUTE_ALWAYS_INLINE + StringSwitch& Case(const char (&S)[N], const T& Value) { + if (!Result && N-1 == Str.size() && + (std::memcmp(S, Str.data(), N-1) == 0)) { + Result = &Value; + } + + return *this; + } + + template<unsigned N> + LLVM_ATTRIBUTE_ALWAYS_INLINE + StringSwitch& EndsWith(const char (&S)[N], const T &Value) { + if (!Result && Str.size() >= N-1 && + std::memcmp(S, Str.data() + Str.size() + 1 - N, N-1) == 0) { + Result = &Value; + } + + return *this; + } + + template<unsigned N> + LLVM_ATTRIBUTE_ALWAYS_INLINE + StringSwitch& StartsWith(const char (&S)[N], const T &Value) { + if (!Result && Str.size() >= N-1 && + std::memcmp(S, Str.data(), N-1) == 0) { + Result = &Value; + } + + return *this; + } + + template<unsigned N0, unsigned N1> + LLVM_ATTRIBUTE_ALWAYS_INLINE + StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], + const T& Value) { + if (!Result && ( + (N0-1 == Str.size() && std::memcmp(S0, Str.data(), N0-1) == 0) || + (N1-1 == Str.size() && std::memcmp(S1, Str.data(), N1-1) == 0))) { + Result = &Value; + } + + return *this; + } + + template<unsigned N0, unsigned N1, unsigned N2> + LLVM_ATTRIBUTE_ALWAYS_INLINE + StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], + const char (&S2)[N2], const T& Value) { + if (!Result && ( + (N0-1 == Str.size() && std::memcmp(S0, Str.data(), N0-1) == 0) || + (N1-1 == Str.size() && std::memcmp(S1, Str.data(), N1-1) == 0) || + (N2-1 == Str.size() && std::memcmp(S2, Str.data(), N2-1) == 0))) { + Result = &Value; + } + + return *this; + } + + template<unsigned N0, unsigned N1, unsigned N2, unsigned N3> + LLVM_ATTRIBUTE_ALWAYS_INLINE + StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], + const char (&S2)[N2], const char (&S3)[N3], + const T& Value) { + if (!Result && ( + (N0-1 == Str.size() && std::memcmp(S0, Str.data(), N0-1) == 0) || + (N1-1 == Str.size() && std::memcmp(S1, Str.data(), N1-1) == 0) || + (N2-1 == Str.size() && std::memcmp(S2, Str.data(), N2-1) == 0) || + (N3-1 == Str.size() && std::memcmp(S3, Str.data(), N3-1) == 0))) { + Result = &Value; + } + + return *this; + } + + template<unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4> + LLVM_ATTRIBUTE_ALWAYS_INLINE + StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], + const char (&S2)[N2], const char (&S3)[N3], + const char (&S4)[N4], const T& Value) { + if (!Result && ( + (N0-1 == Str.size() && std::memcmp(S0, Str.data(), N0-1) == 0) || + (N1-1 == Str.size() && std::memcmp(S1, Str.data(), N1-1) == 0) || + (N2-1 == Str.size() && std::memcmp(S2, Str.data(), N2-1) == 0) || + (N3-1 == Str.size() && std::memcmp(S3, Str.data(), N3-1) == 0) || + (N4-1 == Str.size() && std::memcmp(S4, Str.data(), N4-1) == 0))) { + Result = &Value; + } + + return *this; + } + + LLVM_ATTRIBUTE_ALWAYS_INLINE + R Default(const T& Value) const { + if (Result) + return *Result; + + return Value; + } + + LLVM_ATTRIBUTE_ALWAYS_INLINE + operator R() const { + assert(Result && "Fell off the end of a string-switch"); + return *Result; + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_STRINGSWITCH_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/Triple.h b/third_party/llvm-subzero/include/llvm/ADT/Triple.h new file mode 100644 index 0000000..b98f840 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/Triple.h
@@ -0,0 +1,727 @@ +//===-- llvm/ADT/Triple.h - Target triple helper class ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_TRIPLE_H +#define LLVM_ADT_TRIPLE_H + +#include "llvm/ADT/Twine.h" + +// Some system headers or GCC predefined macros conflict with identifiers in +// this file. Undefine them here. +#undef NetBSD +#undef mips +#undef sparc + +namespace llvm { + +/// Triple - Helper class for working with autoconf configuration names. For +/// historical reasons, we also call these 'triples' (they used to contain +/// exactly three fields). +/// +/// Configuration names are strings in the canonical form: +/// ARCHITECTURE-VENDOR-OPERATING_SYSTEM +/// or +/// ARCHITECTURE-VENDOR-OPERATING_SYSTEM-ENVIRONMENT +/// +/// This class is used for clients which want to support arbitrary +/// configuration names, but also want to implement certain special +/// behavior for particular configurations. This class isolates the mapping +/// from the components of the configuration name to well known IDs. +/// +/// At its core the Triple class is designed to be a wrapper for a triple +/// string; the constructor does not change or normalize the triple string. +/// Clients that need to handle the non-canonical triples that users often +/// specify should use the normalize method. +/// +/// See autoconf/config.guess for a glimpse into what configuration names +/// look like in practice. +class Triple { +public: + enum ArchType { + UnknownArch, + + arm, // ARM (little endian): arm, armv.*, xscale + armeb, // ARM (big endian): armeb + aarch64, // AArch64 (little endian): aarch64 + aarch64_be, // AArch64 (big endian): aarch64_be + avr, // AVR: Atmel AVR microcontroller + bpfel, // eBPF or extended BPF or 64-bit BPF (little endian) + bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian) + hexagon, // Hexagon: hexagon + mips, // MIPS: mips, mipsallegrex + mipsel, // MIPSEL: mipsel, mipsallegrexel + mips64, // MIPS64: mips64 + mips64el, // MIPS64EL: mips64el + msp430, // MSP430: msp430 + ppc, // PPC: powerpc + ppc64, // PPC64: powerpc64, ppu + ppc64le, // PPC64LE: powerpc64le + r600, // R600: AMD GPUs HD2XXX - HD6XXX + amdgcn, // AMDGCN: AMD GCN GPUs + sparc, // Sparc: sparc + sparcv9, // Sparcv9: Sparcv9 + sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant + systemz, // SystemZ: s390x + tce, // TCE (http://tce.cs.tut.fi/): tce + thumb, // Thumb (little endian): thumb, thumbv.* + thumbeb, // Thumb (big endian): thumbeb + x86, // X86: i[3-9]86 + x86_64, // X86-64: amd64, x86_64 + xcore, // XCore: xcore + nvptx, // NVPTX: 32-bit + nvptx64, // NVPTX: 64-bit + le32, // le32: generic little-endian 32-bit CPU (PNaCl) + le64, // le64: generic little-endian 64-bit CPU (PNaCl) + amdil, // AMDIL + amdil64, // AMDIL with 64-bit pointers + hsail, // AMD HSAIL + hsail64, // AMD HSAIL with 64-bit pointers + spir, // SPIR: standard portable IR for OpenCL 32-bit version + spir64, // SPIR: standard portable IR for OpenCL 64-bit version + kalimba, // Kalimba: generic kalimba + shave, // SHAVE: Movidius vector VLIW processors + lanai, // Lanai: Lanai 32-bit + wasm32, // WebAssembly with 32-bit pointers + wasm64, // WebAssembly with 64-bit pointers + renderscript32, // 32-bit RenderScript + renderscript64, // 64-bit RenderScript + LastArchType = renderscript64 + }; + enum SubArchType { + NoSubArch, + + ARMSubArch_v8_2a, + ARMSubArch_v8_1a, + ARMSubArch_v8, + ARMSubArch_v8m_baseline, + ARMSubArch_v8m_mainline, + ARMSubArch_v7, + ARMSubArch_v7em, + ARMSubArch_v7m, + ARMSubArch_v7s, + ARMSubArch_v7k, + ARMSubArch_v6, + ARMSubArch_v6m, + ARMSubArch_v6k, + ARMSubArch_v6t2, + ARMSubArch_v5, + ARMSubArch_v5te, + ARMSubArch_v4t, + + KalimbaSubArch_v3, + KalimbaSubArch_v4, + KalimbaSubArch_v5 + }; + enum VendorType { + UnknownVendor, + + Apple, + PC, + SCEI, + BGP, + BGQ, + Freescale, + IBM, + ImaginationTechnologies, + MipsTechnologies, + NVIDIA, + CSR, + Myriad, + AMD, + Mesa, + LastVendorType = Mesa + }; + enum OSType { + UnknownOS, + + CloudABI, + Darwin, + DragonFly, + FreeBSD, + IOS, + KFreeBSD, + Linux, + Lv2, // PS3 + MacOSX, + NetBSD, + OpenBSD, + Solaris, + Win32, + Haiku, + Minix, + RTEMS, + NaCl, // Native Client + CNK, // BG/P Compute-Node Kernel + Bitrig, + AIX, + CUDA, // NVIDIA CUDA + NVCL, // NVIDIA OpenCL + AMDHSA, // AMD HSA Runtime + PS4, + ELFIAMCU, + TvOS, // Apple tvOS + WatchOS, // Apple watchOS + Mesa3D, + LastOSType = Mesa3D + }; + enum EnvironmentType { + UnknownEnvironment, + + GNU, + GNUABI64, + GNUEABI, + GNUEABIHF, + GNUX32, + CODE16, + EABI, + EABIHF, + Android, + Musl, + MuslEABI, + MuslEABIHF, + + MSVC, + Itanium, + Cygnus, + AMDOpenCL, + CoreCLR, + LastEnvironmentType = CoreCLR + }; + enum ObjectFormatType { + UnknownObjectFormat, + + COFF, + ELF, + MachO, + }; + +private: + std::string Data; + + /// The parsed arch type. + ArchType Arch; + + /// The parsed subarchitecture type. + SubArchType SubArch; + + /// The parsed vendor type. + VendorType Vendor; + + /// The parsed OS type. + OSType OS; + + /// The parsed Environment type. + EnvironmentType Environment; + + /// The object format type. + ObjectFormatType ObjectFormat; + +public: + /// @name Constructors + /// @{ + + /// Default constructor is the same as an empty string and leaves all + /// triple fields unknown. + Triple() : Data(), Arch(), Vendor(), OS(), Environment(), ObjectFormat() {} + + explicit Triple(const Twine &Str); + Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr); + Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr, + const Twine &EnvironmentStr); + + bool operator==(const Triple &Other) const { + return Arch == Other.Arch && SubArch == Other.SubArch && + Vendor == Other.Vendor && OS == Other.OS && + Environment == Other.Environment && + ObjectFormat == Other.ObjectFormat; + } + + /// @} + /// @name Normalization + /// @{ + + /// normalize - Turn an arbitrary machine specification into the canonical + /// triple form (or something sensible that the Triple class understands if + /// nothing better can reasonably be done). In particular, it handles the + /// common case in which otherwise valid components are in the wrong order. + static std::string normalize(StringRef Str); + + /// Return the normalized form of this triple's string. + std::string normalize() const { return normalize(Data); } + + /// @} + /// @name Typed Component Access + /// @{ + + /// getArch - Get the parsed architecture type of this triple. + ArchType getArch() const { return Arch; } + + /// getSubArch - get the parsed subarchitecture type for this triple. + SubArchType getSubArch() const { return SubArch; } + + /// getVendor - Get the parsed vendor type of this triple. + VendorType getVendor() const { return Vendor; } + + /// getOS - Get the parsed operating system type of this triple. + OSType getOS() const { return OS; } + + /// hasEnvironment - Does this triple have the optional environment + /// (fourth) component? + bool hasEnvironment() const { + return getEnvironmentName() != ""; + } + + /// getEnvironment - Get the parsed environment type of this triple. + EnvironmentType getEnvironment() const { return Environment; } + + /// Parse the version number from the OS name component of the + /// triple, if present. + /// + /// For example, "fooos1.2.3" would return (1, 2, 3). + /// + /// If an entry is not defined, it will be returned as 0. + void getEnvironmentVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const; + + /// getFormat - Get the object format for this triple. + ObjectFormatType getObjectFormat() const { return ObjectFormat; } + + /// getOSVersion - Parse the version number from the OS name component of the + /// triple, if present. + /// + /// For example, "fooos1.2.3" would return (1, 2, 3). + /// + /// If an entry is not defined, it will be returned as 0. + void getOSVersion(unsigned &Major, unsigned &Minor, unsigned &Micro) const; + + /// getOSMajorVersion - Return just the major version number, this is + /// specialized because it is a common query. + unsigned getOSMajorVersion() const { + unsigned Maj, Min, Micro; + getOSVersion(Maj, Min, Micro); + return Maj; + } + + /// getMacOSXVersion - Parse the version number as with getOSVersion and then + /// translate generic "darwin" versions to the corresponding OS X versions. + /// This may also be called with IOS triples but the OS X version number is + /// just set to a constant 10.4.0 in that case. Returns true if successful. + bool getMacOSXVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const; + + /// getiOSVersion - Parse the version number as with getOSVersion. This should + /// only be called with IOS or generic triples. + void getiOSVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const; + + /// getWatchOSVersion - Parse the version number as with getOSVersion. This + /// should only be called with WatchOS or generic triples. + void getWatchOSVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const; + + /// @} + /// @name Direct Component Access + /// @{ + + const std::string &str() const { return Data; } + + const std::string &getTriple() const { return Data; } + + /// getArchName - Get the architecture (first) component of the + /// triple. + StringRef getArchName() const; + + /// getVendorName - Get the vendor (second) component of the triple. + StringRef getVendorName() const; + + /// getOSName - Get the operating system (third) component of the + /// triple. + StringRef getOSName() const; + + /// getEnvironmentName - Get the optional environment (fourth) + /// component of the triple, or "" if empty. + StringRef getEnvironmentName() const; + + /// getOSAndEnvironmentName - Get the operating system and optional + /// environment components as a single string (separated by a '-' + /// if the environment component is present). + StringRef getOSAndEnvironmentName() const; + + /// @} + /// @name Convenience Predicates + /// @{ + + /// Test whether the architecture is 64-bit + /// + /// Note that this tests for 64-bit pointer width, and nothing else. Note + /// that we intentionally expose only three predicates, 64-bit, 32-bit, and + /// 16-bit. The inner details of pointer width for particular architectures + /// is not summed up in the triple, and so only a coarse grained predicate + /// system is provided. + bool isArch64Bit() const; + + /// Test whether the architecture is 32-bit + /// + /// Note that this tests for 32-bit pointer width, and nothing else. + bool isArch32Bit() const; + + /// Test whether the architecture is 16-bit + /// + /// Note that this tests for 16-bit pointer width, and nothing else. + bool isArch16Bit() const; + + /// isOSVersionLT - Helper function for doing comparisons against version + /// numbers included in the target triple. + bool isOSVersionLT(unsigned Major, unsigned Minor = 0, + unsigned Micro = 0) const { + unsigned LHS[3]; + getOSVersion(LHS[0], LHS[1], LHS[2]); + + if (LHS[0] != Major) + return LHS[0] < Major; + if (LHS[1] != Minor) + return LHS[1] < Minor; + if (LHS[2] != Micro) + return LHS[1] < Micro; + + return false; + } + + bool isOSVersionLT(const Triple &Other) const { + unsigned RHS[3]; + Other.getOSVersion(RHS[0], RHS[1], RHS[2]); + return isOSVersionLT(RHS[0], RHS[1], RHS[2]); + } + + /// isMacOSXVersionLT - Comparison function for checking OS X version + /// compatibility, which handles supporting skewed version numbering schemes + /// used by the "darwin" triples. + bool isMacOSXVersionLT(unsigned Major, unsigned Minor = 0, + unsigned Micro = 0) const { + assert(isMacOSX() && "Not an OS X triple!"); + + // If this is OS X, expect a sane version number. + if (getOS() == Triple::MacOSX) + return isOSVersionLT(Major, Minor, Micro); + + // Otherwise, compare to the "Darwin" number. + assert(Major == 10 && "Unexpected major version"); + return isOSVersionLT(Minor + 4, Micro, 0); + } + + /// isMacOSX - Is this a Mac OS X triple. For legacy reasons, we support both + /// "darwin" and "osx" as OS X triples. + bool isMacOSX() const { + return getOS() == Triple::Darwin || getOS() == Triple::MacOSX; + } + + /// Is this an iOS triple. + /// Note: This identifies tvOS as a variant of iOS. If that ever + /// changes, i.e., if the two operating systems diverge or their version + /// numbers get out of sync, that will need to be changed. + /// watchOS has completely different version numbers so it is not included. + bool isiOS() const { + return getOS() == Triple::IOS || isTvOS(); + } + + /// Is this an Apple tvOS triple. + bool isTvOS() const { + return getOS() == Triple::TvOS; + } + + /// Is this an Apple watchOS triple. + bool isWatchOS() const { + return getOS() == Triple::WatchOS; + } + + bool isWatchABI() const { + return getSubArch() == Triple::ARMSubArch_v7k; + } + + /// isOSDarwin - Is this a "Darwin" OS (OS X, iOS, or watchOS). + bool isOSDarwin() const { + return isMacOSX() || isiOS() || isWatchOS(); + } + + bool isOSNetBSD() const { + return getOS() == Triple::NetBSD; + } + + bool isOSOpenBSD() const { + return getOS() == Triple::OpenBSD; + } + + bool isOSFreeBSD() const { + return getOS() == Triple::FreeBSD; + } + + bool isOSDragonFly() const { return getOS() == Triple::DragonFly; } + + bool isOSSolaris() const { + return getOS() == Triple::Solaris; + } + + bool isOSBitrig() const { + return getOS() == Triple::Bitrig; + } + + bool isOSIAMCU() const { + return getOS() == Triple::ELFIAMCU; + } + + bool isGNUEnvironment() const { + EnvironmentType Env = getEnvironment(); + return Env == Triple::GNU || Env == Triple::GNUABI64 || + Env == Triple::GNUEABI || Env == Triple::GNUEABIHF || + Env == Triple::GNUX32; + } + + /// Checks if the environment could be MSVC. + bool isWindowsMSVCEnvironment() const { + return getOS() == Triple::Win32 && + (getEnvironment() == Triple::UnknownEnvironment || + getEnvironment() == Triple::MSVC); + } + + /// Checks if the environment is MSVC. + bool isKnownWindowsMSVCEnvironment() const { + return getOS() == Triple::Win32 && getEnvironment() == Triple::MSVC; + } + + bool isWindowsCoreCLREnvironment() const { + return getOS() == Triple::Win32 && getEnvironment() == Triple::CoreCLR; + } + + bool isWindowsItaniumEnvironment() const { + return getOS() == Triple::Win32 && getEnvironment() == Triple::Itanium; + } + + bool isWindowsCygwinEnvironment() const { + return getOS() == Triple::Win32 && getEnvironment() == Triple::Cygnus; + } + + bool isWindowsGNUEnvironment() const { + return getOS() == Triple::Win32 && getEnvironment() == Triple::GNU; + } + + /// Tests for either Cygwin or MinGW OS + bool isOSCygMing() const { + return isWindowsCygwinEnvironment() || isWindowsGNUEnvironment(); + } + + /// Is this a "Windows" OS targeting a "MSVCRT.dll" environment. + bool isOSMSVCRT() const { + return isWindowsMSVCEnvironment() || isWindowsGNUEnvironment() || + isWindowsItaniumEnvironment(); + } + + /// Tests whether the OS is Windows. + bool isOSWindows() const { + return getOS() == Triple::Win32; + } + + /// Tests whether the OS is NaCl (Native Client) + bool isOSNaCl() const { + return getOS() == Triple::NaCl; + } + + /// Tests whether the OS is Linux. + bool isOSLinux() const { + return getOS() == Triple::Linux; + } + + /// Tests whether the OS is kFreeBSD. + bool isOSKFreeBSD() const { + return getOS() == Triple::KFreeBSD; + } + + /// Tests whether the OS uses glibc. + bool isOSGlibc() const { + return getOS() == Triple::Linux || getOS() == Triple::KFreeBSD; + } + + /// Tests whether the OS uses the ELF binary format. + bool isOSBinFormatELF() const { + return getObjectFormat() == Triple::ELF; + } + + /// Tests whether the OS uses the COFF binary format. + bool isOSBinFormatCOFF() const { + return getObjectFormat() == Triple::COFF; + } + + /// Tests whether the environment is MachO. + bool isOSBinFormatMachO() const { + return getObjectFormat() == Triple::MachO; + } + + /// Tests whether the target is the PS4 CPU + bool isPS4CPU() const { + return getArch() == Triple::x86_64 && + getVendor() == Triple::SCEI && + getOS() == Triple::PS4; + } + + /// Tests whether the target is the PS4 platform + bool isPS4() const { + return getVendor() == Triple::SCEI && + getOS() == Triple::PS4; + } + + /// Tests whether the target is Android + bool isAndroid() const { return getEnvironment() == Triple::Android; } + + /// Tests whether the environment is musl-libc + bool isMusl() const { + return getEnvironment() == Triple::Musl || + getEnvironment() == Triple::MuslEABI || + getEnvironment() == Triple::MuslEABIHF; + } + + /// Tests whether the target is NVPTX (32- or 64-bit). + bool isNVPTX() const { + return getArch() == Triple::nvptx || getArch() == Triple::nvptx64; + } + + /// Tests wether the target supports comdat + bool supportsCOMDAT() const { return !isOSBinFormatMachO(); } + + /// @} + /// @name Mutators + /// @{ + + /// setArch - Set the architecture (first) component of the triple + /// to a known type. + void setArch(ArchType Kind); + + /// setVendor - Set the vendor (second) component of the triple to a + /// known type. + void setVendor(VendorType Kind); + + /// setOS - Set the operating system (third) component of the triple + /// to a known type. + void setOS(OSType Kind); + + /// setEnvironment - Set the environment (fourth) component of the triple + /// to a known type. + void setEnvironment(EnvironmentType Kind); + + /// setObjectFormat - Set the object file format + void setObjectFormat(ObjectFormatType Kind); + + /// setTriple - Set all components to the new triple \p Str. + void setTriple(const Twine &Str); + + /// setArchName - Set the architecture (first) component of the + /// triple by name. + void setArchName(StringRef Str); + + /// setVendorName - Set the vendor (second) component of the triple + /// by name. + void setVendorName(StringRef Str); + + /// setOSName - Set the operating system (third) component of the + /// triple by name. + void setOSName(StringRef Str); + + /// setEnvironmentName - Set the optional environment (fourth) + /// component of the triple by name. + void setEnvironmentName(StringRef Str); + + /// setOSAndEnvironmentName - Set the operating system and optional + /// environment components with a single string. + void setOSAndEnvironmentName(StringRef Str); + + /// @} + /// @name Helpers to build variants of a particular triple. + /// @{ + + /// Form a triple with a 32-bit variant of the current architecture. + /// + /// This can be used to move across "families" of architectures where useful. + /// + /// \returns A new triple with a 32-bit architecture or an unknown + /// architecture if no such variant can be found. + llvm::Triple get32BitArchVariant() const; + + /// Form a triple with a 64-bit variant of the current architecture. + /// + /// This can be used to move across "families" of architectures where useful. + /// + /// \returns A new triple with a 64-bit architecture or an unknown + /// architecture if no such variant can be found. + llvm::Triple get64BitArchVariant() const; + + /// Form a triple with a big endian variant of the current architecture. + /// + /// This can be used to move across "families" of architectures where useful. + /// + /// \returns A new triple with a big endian architecture or an unknown + /// architecture if no such variant can be found. + llvm::Triple getBigEndianArchVariant() const; + + /// Form a triple with a little endian variant of the current architecture. + /// + /// This can be used to move across "families" of architectures where useful. + /// + /// \returns A new triple with a little endian architecture or an unknown + /// architecture if no such variant can be found. + llvm::Triple getLittleEndianArchVariant() const; + + /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting. + /// + /// \param Arch the architecture name (e.g., "armv7s"). If it is an empty + /// string then the triple's arch name is used. + StringRef getARMCPUForArch(StringRef Arch = StringRef()) const; + + /// Tests whether the target triple is little endian. + /// + /// \returns true if the triple is little endian, false otherwise. + bool isLittleEndian() const; + + /// @} + /// @name Static helpers for IDs. + /// @{ + + /// getArchTypeName - Get the canonical name for the \p Kind architecture. + static const char *getArchTypeName(ArchType Kind); + + /// getArchTypePrefix - Get the "prefix" canonical name for the \p Kind + /// architecture. This is the prefix used by the architecture specific + /// builtins, and is suitable for passing to \see + /// Intrinsic::getIntrinsicForGCCBuiltin(). + /// + /// \return - The architecture prefix, or 0 if none is defined. + static const char *getArchTypePrefix(ArchType Kind); + + /// getVendorTypeName - Get the canonical name for the \p Kind vendor. + static const char *getVendorTypeName(VendorType Kind); + + /// getOSTypeName - Get the canonical name for the \p Kind operating system. + static const char *getOSTypeName(OSType Kind); + + /// getEnvironmentTypeName - Get the canonical name for the \p Kind + /// environment. + static const char *getEnvironmentTypeName(EnvironmentType Kind); + + /// @} + /// @name Static helpers for converting alternate architecture names. + /// @{ + + /// getArchTypeForLLVMName - The canonical type for the given LLVM + /// architecture name (e.g., "x86"). + static ArchType getArchTypeForLLVMName(StringRef Str); + + /// @} +}; + +} // End llvm namespace + + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/Twine.h b/third_party/llvm-subzero/include/llvm/ADT/Twine.h new file mode 100644 index 0000000..81b1a6d --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/Twine.h
@@ -0,0 +1,540 @@ +//===-- Twine.h - Fast Temporary String Concatenation -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_TWINE_H +#define LLVM_ADT_TWINE_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" +#include <cassert> +#include <string> + +namespace llvm { + class raw_ostream; + + /// Twine - A lightweight data structure for efficiently representing the + /// concatenation of temporary values as strings. + /// + /// A Twine is a kind of rope, it represents a concatenated string using a + /// binary-tree, where the string is the preorder of the nodes. Since the + /// Twine can be efficiently rendered into a buffer when its result is used, + /// it avoids the cost of generating temporary values for intermediate string + /// results -- particularly in cases when the Twine result is never + /// required. By explicitly tracking the type of leaf nodes, we can also avoid + /// the creation of temporary strings for conversions operations (such as + /// appending an integer to a string). + /// + /// A Twine is not intended for use directly and should not be stored, its + /// implementation relies on the ability to store pointers to temporary stack + /// objects which may be deallocated at the end of a statement. Twines should + /// only be used accepted as const references in arguments, when an API wishes + /// to accept possibly-concatenated strings. + /// + /// Twines support a special 'null' value, which always concatenates to form + /// itself, and renders as an empty string. This can be returned from APIs to + /// effectively nullify any concatenations performed on the result. + /// + /// \b Implementation + /// + /// Given the nature of a Twine, it is not possible for the Twine's + /// concatenation method to construct interior nodes; the result must be + /// represented inside the returned value. For this reason a Twine object + /// actually holds two values, the left- and right-hand sides of a + /// concatenation. We also have nullary Twine objects, which are effectively + /// sentinel values that represent empty strings. + /// + /// Thus, a Twine can effectively have zero, one, or two children. The \see + /// isNullary(), \see isUnary(), and \see isBinary() predicates exist for + /// testing the number of children. + /// + /// We maintain a number of invariants on Twine objects (FIXME: Why): + /// - Nullary twines are always represented with their Kind on the left-hand + /// side, and the Empty kind on the right-hand side. + /// - Unary twines are always represented with the value on the left-hand + /// side, and the Empty kind on the right-hand side. + /// - If a Twine has another Twine as a child, that child should always be + /// binary (otherwise it could have been folded into the parent). + /// + /// These invariants are check by \see isValid(). + /// + /// \b Efficiency Considerations + /// + /// The Twine is designed to yield efficient and small code for common + /// situations. For this reason, the concat() method is inlined so that + /// concatenations of leaf nodes can be optimized into stores directly into a + /// single stack allocated object. + /// + /// In practice, not all compilers can be trusted to optimize concat() fully, + /// so we provide two additional methods (and accompanying operator+ + /// overloads) to guarantee that particularly important cases (cstring plus + /// StringRef) codegen as desired. + class Twine { + /// NodeKind - Represent the type of an argument. + enum NodeKind : unsigned char { + /// An empty string; the result of concatenating anything with it is also + /// empty. + NullKind, + + /// The empty string. + EmptyKind, + + /// A pointer to a Twine instance. + TwineKind, + + /// A pointer to a C string instance. + CStringKind, + + /// A pointer to an std::string instance. + StdStringKind, + + /// A pointer to a StringRef instance. + StringRefKind, + + /// A pointer to a SmallString instance. + SmallStringKind, + + /// A char value, to render as a character. + CharKind, + + /// An unsigned int value, to render as an unsigned decimal integer. + DecUIKind, + + /// An int value, to render as a signed decimal integer. + DecIKind, + + /// A pointer to an unsigned long value, to render as an unsigned decimal + /// integer. + DecULKind, + + /// A pointer to a long value, to render as a signed decimal integer. + DecLKind, + + /// A pointer to an unsigned long long value, to render as an unsigned + /// decimal integer. + DecULLKind, + + /// A pointer to a long long value, to render as a signed decimal integer. + DecLLKind, + + /// A pointer to a uint64_t value, to render as an unsigned hexadecimal + /// integer. + UHexKind + }; + + union Child + { + const Twine *twine; + const char *cString; + const std::string *stdString; + const StringRef *stringRef; + const SmallVectorImpl<char> *smallString; + char character; + unsigned int decUI; + int decI; + const unsigned long *decUL; + const long *decL; + const unsigned long long *decULL; + const long long *decLL; + const uint64_t *uHex; + }; + + private: + /// LHS - The prefix in the concatenation, which may be uninitialized for + /// Null or Empty kinds. + Child LHS; + /// RHS - The suffix in the concatenation, which may be uninitialized for + /// Null or Empty kinds. + Child RHS; + /// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). + NodeKind LHSKind; + /// RHSKind - The NodeKind of the right hand side, \see getRHSKind(). + NodeKind RHSKind; + + private: + /// Construct a nullary twine; the kind must be NullKind or EmptyKind. + explicit Twine(NodeKind Kind) + : LHSKind(Kind), RHSKind(EmptyKind) { + assert(isNullary() && "Invalid kind!"); + } + + /// Construct a binary twine. + explicit Twine(const Twine &LHS, const Twine &RHS) + : LHSKind(TwineKind), RHSKind(TwineKind) { + this->LHS.twine = &LHS; + this->RHS.twine = &RHS; + assert(isValid() && "Invalid twine!"); + } + + /// Construct a twine from explicit values. + explicit Twine(Child LHS, NodeKind LHSKind, Child RHS, NodeKind RHSKind) + : LHS(LHS), RHS(RHS), LHSKind(LHSKind), RHSKind(RHSKind) { + assert(isValid() && "Invalid twine!"); + } + + /// Since the intended use of twines is as temporary objects, assignments + /// when concatenating might cause undefined behavior or stack corruptions + Twine &operator=(const Twine &Other) = delete; + + /// Check for the null twine. + bool isNull() const { + return getLHSKind() == NullKind; + } + + /// Check for the empty twine. + bool isEmpty() const { + return getLHSKind() == EmptyKind; + } + + /// Check if this is a nullary twine (null or empty). + bool isNullary() const { + return isNull() || isEmpty(); + } + + /// Check if this is a unary twine. + bool isUnary() const { + return getRHSKind() == EmptyKind && !isNullary(); + } + + /// Check if this is a binary twine. + bool isBinary() const { + return getLHSKind() != NullKind && getRHSKind() != EmptyKind; + } + + /// Check if this is a valid twine (satisfying the invariants on + /// order and number of arguments). + bool isValid() const { + // Nullary twines always have Empty on the RHS. + if (isNullary() && getRHSKind() != EmptyKind) + return false; + + // Null should never appear on the RHS. + if (getRHSKind() == NullKind) + return false; + + // The RHS cannot be non-empty if the LHS is empty. + if (getRHSKind() != EmptyKind && getLHSKind() == EmptyKind) + return false; + + // A twine child should always be binary. + if (getLHSKind() == TwineKind && + !LHS.twine->isBinary()) + return false; + if (getRHSKind() == TwineKind && + !RHS.twine->isBinary()) + return false; + + return true; + } + + /// Get the NodeKind of the left-hand side. + NodeKind getLHSKind() const { return LHSKind; } + + /// Get the NodeKind of the right-hand side. + NodeKind getRHSKind() const { return RHSKind; } + + /// Print one child from a twine. + void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const; + + /// Print the representation of one child from a twine. + void printOneChildRepr(raw_ostream &OS, Child Ptr, + NodeKind Kind) const; + + public: + /// @name Constructors + /// @{ + + /// Construct from an empty string. + /*implicit*/ Twine() : LHSKind(EmptyKind), RHSKind(EmptyKind) { + assert(isValid() && "Invalid twine!"); + } + + Twine(const Twine &) = default; + + /// Construct from a C string. + /// + /// We take care here to optimize "" into the empty twine -- this will be + /// optimized out for string constants. This allows Twine arguments have + /// default "" values, without introducing unnecessary string constants. + /*implicit*/ Twine(const char *Str) + : RHSKind(EmptyKind) { + if (Str[0] != '\0') { + LHS.cString = Str; + LHSKind = CStringKind; + } else + LHSKind = EmptyKind; + + assert(isValid() && "Invalid twine!"); + } + + /// Construct from an std::string. + /*implicit*/ Twine(const std::string &Str) + : LHSKind(StdStringKind), RHSKind(EmptyKind) { + LHS.stdString = &Str; + assert(isValid() && "Invalid twine!"); + } + + /// Construct from a StringRef. + /*implicit*/ Twine(const StringRef &Str) + : LHSKind(StringRefKind), RHSKind(EmptyKind) { + LHS.stringRef = &Str; + assert(isValid() && "Invalid twine!"); + } + + /// Construct from a SmallString. + /*implicit*/ Twine(const SmallVectorImpl<char> &Str) + : LHSKind(SmallStringKind), RHSKind(EmptyKind) { + LHS.smallString = &Str; + assert(isValid() && "Invalid twine!"); + } + + /// Construct from a char. + explicit Twine(char Val) + : LHSKind(CharKind), RHSKind(EmptyKind) { + LHS.character = Val; + } + + /// Construct from a signed char. + explicit Twine(signed char Val) + : LHSKind(CharKind), RHSKind(EmptyKind) { + LHS.character = static_cast<char>(Val); + } + + /// Construct from an unsigned char. + explicit Twine(unsigned char Val) + : LHSKind(CharKind), RHSKind(EmptyKind) { + LHS.character = static_cast<char>(Val); + } + + /// Construct a twine to print \p Val as an unsigned decimal integer. + explicit Twine(unsigned Val) + : LHSKind(DecUIKind), RHSKind(EmptyKind) { + LHS.decUI = Val; + } + + /// Construct a twine to print \p Val as a signed decimal integer. + explicit Twine(int Val) + : LHSKind(DecIKind), RHSKind(EmptyKind) { + LHS.decI = Val; + } + + /// Construct a twine to print \p Val as an unsigned decimal integer. + explicit Twine(const unsigned long &Val) + : LHSKind(DecULKind), RHSKind(EmptyKind) { + LHS.decUL = &Val; + } + + /// Construct a twine to print \p Val as a signed decimal integer. + explicit Twine(const long &Val) + : LHSKind(DecLKind), RHSKind(EmptyKind) { + LHS.decL = &Val; + } + + /// Construct a twine to print \p Val as an unsigned decimal integer. + explicit Twine(const unsigned long long &Val) + : LHSKind(DecULLKind), RHSKind(EmptyKind) { + LHS.decULL = &Val; + } + + /// Construct a twine to print \p Val as a signed decimal integer. + explicit Twine(const long long &Val) + : LHSKind(DecLLKind), RHSKind(EmptyKind) { + LHS.decLL = &Val; + } + + // FIXME: Unfortunately, to make sure this is as efficient as possible we + // need extra binary constructors from particular types. We can't rely on + // the compiler to be smart enough to fold operator+()/concat() down to the + // right thing. Yet. + + /// Construct as the concatenation of a C string and a StringRef. + /*implicit*/ Twine(const char *LHS, const StringRef &RHS) + : LHSKind(CStringKind), RHSKind(StringRefKind) { + this->LHS.cString = LHS; + this->RHS.stringRef = &RHS; + assert(isValid() && "Invalid twine!"); + } + + /// Construct as the concatenation of a StringRef and a C string. + /*implicit*/ Twine(const StringRef &LHS, const char *RHS) + : LHSKind(StringRefKind), RHSKind(CStringKind) { + this->LHS.stringRef = &LHS; + this->RHS.cString = RHS; + assert(isValid() && "Invalid twine!"); + } + + /// Create a 'null' string, which is an empty string that always + /// concatenates to form another empty string. + static Twine createNull() { + return Twine(NullKind); + } + + /// @} + /// @name Numeric Conversions + /// @{ + + // Construct a twine to print \p Val as an unsigned hexadecimal integer. + static Twine utohexstr(const uint64_t &Val) { + Child LHS, RHS; + LHS.uHex = &Val; + RHS.twine = nullptr; + return Twine(LHS, UHexKind, RHS, EmptyKind); + } + + /// @} + /// @name Predicate Operations + /// @{ + + /// Check if this twine is trivially empty; a false return value does not + /// necessarily mean the twine is empty. + bool isTriviallyEmpty() const { + return isNullary(); + } + + /// Return true if this twine can be dynamically accessed as a single + /// StringRef value with getSingleStringRef(). + bool isSingleStringRef() const { + if (getRHSKind() != EmptyKind) return false; + + switch (getLHSKind()) { + case EmptyKind: + case CStringKind: + case StdStringKind: + case StringRefKind: + case SmallStringKind: + return true; + default: + return false; + } + } + + /// @} + /// @name String Operations + /// @{ + + Twine concat(const Twine &Suffix) const; + + /// @} + /// @name Output & Conversion. + /// @{ + + /// Return the twine contents as a std::string. + std::string str() const; + + /// Append the concatenated string into the given SmallString or SmallVector. + void toVector(SmallVectorImpl<char> &Out) const; + + /// This returns the twine as a single StringRef. This method is only valid + /// if isSingleStringRef() is true. + StringRef getSingleStringRef() const { + assert(isSingleStringRef() &&"This cannot be had as a single stringref!"); + switch (getLHSKind()) { + default: llvm_unreachable("Out of sync with isSingleStringRef"); + case EmptyKind: return StringRef(); + case CStringKind: return StringRef(LHS.cString); + case StdStringKind: return StringRef(*LHS.stdString); + case StringRefKind: return *LHS.stringRef; + case SmallStringKind: + return StringRef(LHS.smallString->data(), LHS.smallString->size()); + } + } + + /// This returns the twine as a single StringRef if it can be + /// represented as such. Otherwise the twine is written into the given + /// SmallVector and a StringRef to the SmallVector's data is returned. + StringRef toStringRef(SmallVectorImpl<char> &Out) const { + if (isSingleStringRef()) + return getSingleStringRef(); + toVector(Out); + return StringRef(Out.data(), Out.size()); + } + + /// This returns the twine as a single null terminated StringRef if it + /// can be represented as such. Otherwise the twine is written into the + /// given SmallVector and a StringRef to the SmallVector's data is returned. + /// + /// The returned StringRef's size does not include the null terminator. + StringRef toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const; + + /// Write the concatenated string represented by this twine to the + /// stream \p OS. + void print(raw_ostream &OS) const; + + /// Dump the concatenated string represented by this twine to stderr. + void dump() const; + + /// Write the representation of this twine to the stream \p OS. + void printRepr(raw_ostream &OS) const; + + /// Dump the representation of this twine to stderr. + void dumpRepr() const; + + /// @} + }; + + /// @name Twine Inline Implementations + /// @{ + + inline Twine Twine::concat(const Twine &Suffix) const { + // Concatenation with null is null. + if (isNull() || Suffix.isNull()) + return Twine(NullKind); + + // Concatenation with empty yields the other side. + if (isEmpty()) + return Suffix; + if (Suffix.isEmpty()) + return *this; + + // Otherwise we need to create a new node, taking care to fold in unary + // twines. + Child NewLHS, NewRHS; + NewLHS.twine = this; + NewRHS.twine = &Suffix; + NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind; + if (isUnary()) { + NewLHS = LHS; + NewLHSKind = getLHSKind(); + } + if (Suffix.isUnary()) { + NewRHS = Suffix.LHS; + NewRHSKind = Suffix.getLHSKind(); + } + + return Twine(NewLHS, NewLHSKind, NewRHS, NewRHSKind); + } + + inline Twine operator+(const Twine &LHS, const Twine &RHS) { + return LHS.concat(RHS); + } + + /// Additional overload to guarantee simplified codegen; this is equivalent to + /// concat(). + + inline Twine operator+(const char *LHS, const StringRef &RHS) { + return Twine(LHS, RHS); + } + + /// Additional overload to guarantee simplified codegen; this is equivalent to + /// concat(). + + inline Twine operator+(const StringRef &LHS, const char *RHS) { + return Twine(LHS, RHS); + } + + inline raw_ostream &operator<<(raw_ostream &OS, const Twine &RHS) { + RHS.print(OS); + return OS; + } + + /// @} +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/edit_distance.h b/third_party/llvm-subzero/include/llvm/ADT/edit_distance.h new file mode 100644 index 0000000..06a01b1 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/edit_distance.h
@@ -0,0 +1,103 @@ +//===-- llvm/ADT/edit_distance.h - Array edit distance function --- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a Levenshtein distance function that works for any two +// sequences, with each element of each sequence being analogous to a character +// in a string. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_EDIT_DISTANCE_H +#define LLVM_ADT_EDIT_DISTANCE_H + +#include "llvm/ADT/ArrayRef.h" +#include <algorithm> +#include <memory> + +namespace llvm { + +/// \brief Determine the edit distance between two sequences. +/// +/// \param FromArray the first sequence to compare. +/// +/// \param ToArray the second sequence to compare. +/// +/// \param AllowReplacements whether to allow element replacements (change one +/// element into another) as a single operation, rather than as two operations +/// (an insertion and a removal). +/// +/// \param MaxEditDistance If non-zero, the maximum edit distance that this +/// routine is allowed to compute. If the edit distance will exceed that +/// maximum, returns \c MaxEditDistance+1. +/// +/// \returns the minimum number of element insertions, removals, or (if +/// \p AllowReplacements is \c true) replacements needed to transform one of +/// the given sequences into the other. If zero, the sequences are identical. +template<typename T> +unsigned ComputeEditDistance(ArrayRef<T> FromArray, ArrayRef<T> ToArray, + bool AllowReplacements = true, + unsigned MaxEditDistance = 0) { + // The algorithm implemented below is the "classic" + // dynamic-programming algorithm for computing the Levenshtein + // distance, which is described here: + // + // http://en.wikipedia.org/wiki/Levenshtein_distance + // + // Although the algorithm is typically described using an m x n + // array, only one row plus one element are used at a time, so this + // implementation just keeps one vector for the row. To update one entry, + // only the entries to the left, top, and top-left are needed. The left + // entry is in Row[x-1], the top entry is what's in Row[x] from the last + // iteration, and the top-left entry is stored in Previous. + typename ArrayRef<T>::size_type m = FromArray.size(); + typename ArrayRef<T>::size_type n = ToArray.size(); + + const unsigned SmallBufferSize = 64; + unsigned SmallBuffer[SmallBufferSize]; + std::unique_ptr<unsigned[]> Allocated; + unsigned *Row = SmallBuffer; + if (n + 1 > SmallBufferSize) { + Row = new unsigned[n + 1]; + Allocated.reset(Row); + } + + for (unsigned i = 1; i <= n; ++i) + Row[i] = i; + + for (typename ArrayRef<T>::size_type y = 1; y <= m; ++y) { + Row[0] = y; + unsigned BestThisRow = Row[0]; + + unsigned Previous = y - 1; + for (typename ArrayRef<T>::size_type x = 1; x <= n; ++x) { + int OldRow = Row[x]; + if (AllowReplacements) { + Row[x] = std::min( + Previous + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u), + std::min(Row[x-1], Row[x])+1); + } + else { + if (FromArray[y-1] == ToArray[x-1]) Row[x] = Previous; + else Row[x] = std::min(Row[x-1], Row[x]) + 1; + } + Previous = OldRow; + BestThisRow = std::min(BestThisRow, Row[x]); + } + + if (MaxEditDistance && BestThisRow > MaxEditDistance) + return MaxEditDistance + 1; + } + + unsigned Result = Row[n]; + return Result; +} + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/ilist.h b/third_party/llvm-subzero/include/llvm/ADT/ilist.h new file mode 100644 index 0000000..ce5af68 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/ilist.h
@@ -0,0 +1,457 @@ +//==-- llvm/ADT/ilist.h - Intrusive Linked List Template ---------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines classes to implement an intrusive doubly linked list class +// (i.e. each node of the list must contain a next and previous field for the +// list. +// +// The ilist class itself should be a plug in replacement for list. This list +// replacement does not provide a constant time size() method, so be careful to +// use empty() when you really want to know if it's empty. +// +// The ilist class is implemented as a circular list. The list itself contains +// a sentinel node, whose Next points at begin() and whose Prev points at +// rbegin(). The sentinel node itself serves as end() and rend(). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_H +#define LLVM_ADT_ILIST_H + +#include "llvm/ADT/simple_ilist.h" +#include "llvm/Support/Compiler.h" +#include <cassert> +#include <cstddef> +#include <iterator> +#include <type_traits> + +namespace llvm { + +/// Use new/delete by default for iplist and ilist. +/// +/// Specialize this to get different behaviour for allocation-related API. (If +/// you really want new/delete, consider just using std::list.) +/// +/// \see ilist_noalloc_traits +template <typename NodeTy> struct ilist_alloc_traits { + static NodeTy *createNode(const NodeTy &V) { return new NodeTy(V); } + static void deleteNode(NodeTy *V) { delete V; } +}; + +/// Custom traits to disable node creation and do nothing on deletion. +/// +/// Specialize ilist_alloc_traits to inherit from this to disable the +/// non-intrusive parts of iplist and/or ilist. It has no createNode function, +/// and deleteNode does nothing. +/// +/// \code +/// template <> +/// struct ilist_alloc_traits<MyType> : ilist_noalloc_traits<MyType> {}; +/// \endcode +template <typename NodeTy> struct ilist_noalloc_traits { + static void deleteNode(NodeTy *V) {} +}; + +/// Callbacks do nothing by default in iplist and ilist. +/// +/// Specialize this for to use callbacks for when nodes change their list +/// membership. +template <typename NodeTy> struct ilist_callback_traits { + void addNodeToList(NodeTy *) {} + void removeNodeFromList(NodeTy *) {} + + /// Callback before transferring nodes to this list. + /// + /// \pre \c this!=&OldList + template <class Iterator> + void transferNodesFromList(ilist_callback_traits &OldList, Iterator /*first*/, + Iterator /*last*/) { + (void)OldList; + } +}; + +/// A fragment for template traits for intrusive list that provides default +/// node related operations. +/// +/// TODO: Remove this layer of indirection. It's not necessary. +template <typename NodeTy> +struct ilist_node_traits : ilist_alloc_traits<NodeTy>, + ilist_callback_traits<NodeTy> {}; + +/// Default template traits for intrusive list. +/// +/// By inheriting from this, you can easily use default implementations for all +/// common operations. +/// +/// TODO: Remove this customization point. Specializing ilist_traits is +/// already fully general. +template <typename NodeTy> +struct ilist_default_traits : public ilist_node_traits<NodeTy> {}; + +/// Template traits for intrusive list. +/// +/// Customize callbacks and allocation semantics. +template <typename NodeTy> +struct ilist_traits : public ilist_default_traits<NodeTy> {}; + +/// Const traits should never be instantiated. +template <typename Ty> struct ilist_traits<const Ty> {}; + +namespace ilist_detail { + +template <class T> T &make(); + +/// Type trait to check for a traits class that has a getNext member (as a +/// canary for any of the ilist_nextprev_traits API). +template <class TraitsT, class NodeT> struct HasGetNext { + typedef char Yes[1]; + typedef char No[2]; + template <size_t N> struct SFINAE {}; + + template <class U> + static Yes &test(U *I, decltype(I->getNext(&make<NodeT>())) * = 0); + template <class> static No &test(...); + +public: + static const bool value = sizeof(test<TraitsT>(nullptr)) == sizeof(Yes); +}; + +/// Type trait to check for a traits class that has a createSentinel member (as +/// a canary for any of the ilist_sentinel_traits API). +template <class TraitsT> struct HasCreateSentinel { + typedef char Yes[1]; + typedef char No[2]; + + template <class U> + static Yes &test(U *I, decltype(I->createSentinel()) * = 0); + template <class> static No &test(...); + +public: + static const bool value = sizeof(test<TraitsT>(nullptr)) == sizeof(Yes); +}; + +template <class TraitsT, class NodeT> struct HasObsoleteCustomization { + static const bool value = + HasGetNext<TraitsT, NodeT>::value || HasCreateSentinel<TraitsT>::value; +}; + +} // end namespace ilist_detail + +//===----------------------------------------------------------------------===// +// +/// A wrapper around an intrusive list with callbacks and non-intrusive +/// ownership. +/// +/// This wraps a purely intrusive list (like simple_ilist) with a configurable +/// traits class. The traits can implement callbacks and customize the +/// ownership semantics. +/// +/// This is a subset of ilist functionality that can safely be used on nodes of +/// polymorphic types, i.e. a heterogeneous list with a common base class that +/// holds the next/prev pointers. The only state of the list itself is an +/// ilist_sentinel, which holds pointers to the first and last nodes in the +/// list. +template <class IntrusiveListT, class TraitsT> +class iplist_impl : public TraitsT, IntrusiveListT { + typedef IntrusiveListT base_list_type; + +public: + typedef typename base_list_type::pointer pointer; + typedef typename base_list_type::const_pointer const_pointer; + typedef typename base_list_type::reference reference; + typedef typename base_list_type::const_reference const_reference; + typedef typename base_list_type::value_type value_type; + typedef typename base_list_type::size_type size_type; + typedef typename base_list_type::difference_type difference_type; + typedef typename base_list_type::iterator iterator; + typedef typename base_list_type::const_iterator const_iterator; + typedef typename base_list_type::reverse_iterator reverse_iterator; + typedef + typename base_list_type::const_reverse_iterator const_reverse_iterator; + +private: + // TODO: Drop this assertion and the transitive type traits anytime after + // v4.0 is branched (i.e,. keep them for one release to help out-of-tree code + // update). + static_assert( + !ilist_detail::HasObsoleteCustomization<TraitsT, value_type>::value, + "ilist customization points have changed!"); + + static bool op_less(const_reference L, const_reference R) { return L < R; } + static bool op_equal(const_reference L, const_reference R) { return L == R; } + + // Copying intrusively linked nodes doesn't make sense. + iplist_impl(const iplist_impl &) = delete; + void operator=(const iplist_impl &) = delete; + +public: + iplist_impl() = default; + ~iplist_impl() { clear(); } + + // Miscellaneous inspection routines. + size_type max_size() const { return size_type(-1); } + + using base_list_type::begin; + using base_list_type::end; + using base_list_type::rbegin; + using base_list_type::rend; + using base_list_type::empty; + using base_list_type::front; + using base_list_type::back; + + void swap(iplist_impl &RHS) { + assert(0 && "Swap does not use list traits callback correctly yet!"); + base_list_type::swap(RHS); + } + + iterator insert(iterator where, pointer New) { + this->addNodeToList(New); // Notify traits that we added a node... + return base_list_type::insert(where, *New); + } + + iterator insert(iterator where, const_reference New) { + return this->insert(where, new value_type(New)); + } + + iterator insertAfter(iterator where, pointer New) { + if (empty()) + return insert(begin(), New); + else + return insert(++where, New); + } + + pointer remove(iterator &IT) { + pointer Node = &*IT++; + this->removeNodeFromList(Node); // Notify traits that we removed a node... + base_list_type::remove(*Node); + return Node; + } + + pointer remove(const iterator &IT) { + iterator MutIt = IT; + return remove(MutIt); + } + + pointer remove(pointer IT) { return remove(iterator(IT)); } + pointer remove(reference IT) { return remove(iterator(IT)); } + + // erase - remove a node from the controlled sequence... and delete it. + iterator erase(iterator where) { + this->deleteNode(remove(where)); + return where; + } + + iterator erase(pointer IT) { return erase(iterator(IT)); } + iterator erase(reference IT) { return erase(iterator(IT)); } + + /// Remove all nodes from the list like clear(), but do not call + /// removeNodeFromList() or deleteNode(). + /// + /// This should only be used immediately before freeing nodes in bulk to + /// avoid traversing the list and bringing all the nodes into cache. + void clearAndLeakNodesUnsafely() { base_list_type::clear(); } + +private: + // transfer - The heart of the splice function. Move linked list nodes from + // [first, last) into position. + // + void transfer(iterator position, iplist_impl &L2, iterator first, iterator last) { + if (position == last) + return; + + if (this != &L2) // Notify traits we moved the nodes... + this->transferNodesFromList(L2, first, last); + + base_list_type::splice(position, L2, first, last); + } + +public: + + //===----------------------------------------------------------------------=== + // Functionality derived from other functions defined above... + // + + using base_list_type::size; + + iterator erase(iterator first, iterator last) { + while (first != last) + first = erase(first); + return last; + } + + void clear() { erase(begin(), end()); } + + // Front and back inserters... + void push_front(pointer val) { insert(begin(), val); } + void push_back(pointer val) { insert(end(), val); } + void pop_front() { + assert(!empty() && "pop_front() on empty list!"); + erase(begin()); + } + void pop_back() { + assert(!empty() && "pop_back() on empty list!"); + iterator t = end(); erase(--t); + } + + // Special forms of insert... + template<class InIt> void insert(iterator where, InIt first, InIt last) { + for (; first != last; ++first) insert(where, *first); + } + + // Splice members - defined in terms of transfer... + void splice(iterator where, iplist_impl &L2) { + if (!L2.empty()) + transfer(where, L2, L2.begin(), L2.end()); + } + void splice(iterator where, iplist_impl &L2, iterator first) { + iterator last = first; ++last; + if (where == first || where == last) return; // No change + transfer(where, L2, first, last); + } + void splice(iterator where, iplist_impl &L2, iterator first, iterator last) { + if (first != last) transfer(where, L2, first, last); + } + void splice(iterator where, iplist_impl &L2, reference N) { + splice(where, L2, iterator(N)); + } + void splice(iterator where, iplist_impl &L2, pointer N) { + splice(where, L2, iterator(N)); + } + + template <class Compare> + void merge(iplist_impl &Right, Compare comp) { + if (this == &Right) + return; + this->transferNodesFromList(Right, Right.begin(), Right.end()); + base_list_type::merge(Right, comp); + } + void merge(iplist_impl &Right) { return merge(Right, op_less); } + + using base_list_type::sort; + + /// \brief Get the previous node, or \c nullptr for the list head. + pointer getPrevNode(reference N) const { + auto I = N.getIterator(); + if (I == begin()) + return nullptr; + return &*std::prev(I); + } + /// \brief Get the previous node, or \c nullptr for the list head. + const_pointer getPrevNode(const_reference N) const { + return getPrevNode(const_cast<reference >(N)); + } + + /// \brief Get the next node, or \c nullptr for the list tail. + pointer getNextNode(reference N) const { + auto Next = std::next(N.getIterator()); + if (Next == end()) + return nullptr; + return &*Next; + } + /// \brief Get the next node, or \c nullptr for the list tail. + const_pointer getNextNode(const_reference N) const { + return getNextNode(const_cast<reference >(N)); + } +}; + +/// An intrusive list with ownership and callbacks specified/controlled by +/// ilist_traits, only with API safe for polymorphic types. +template <class T> +class iplist : public iplist_impl<simple_ilist<T>, ilist_traits<T>> {}; + +/// An intrusive list with ownership and callbacks specified/controlled by +/// ilist_traits, with API that is unsafe for polymorphic types. +template <class T> class ilist : public iplist<T> { + typedef iplist<T> base_list_type; + +public: + typedef typename base_list_type::size_type size_type; + typedef typename base_list_type::iterator iterator; + typedef typename base_list_type::value_type value_type; + typedef typename base_list_type::const_reference const_reference; + + ilist() {} + ilist(const ilist &right) : base_list_type() { + insert(this->begin(), right.begin(), right.end()); + } + explicit ilist(size_type count) { + insert(this->begin(), count, value_type()); + } + ilist(size_type count, const_reference val) { + insert(this->begin(), count, val); + } + template<class InIt> ilist(InIt first, InIt last) { + insert(this->begin(), first, last); + } + + // bring hidden functions into scope + using base_list_type::insert; + using base_list_type::push_front; + using base_list_type::push_back; + + // Main implementation here - Insert for a node passed by value... + iterator insert(iterator where, const_reference val) { + return insert(where, this->createNode(val)); + } + + + // Front and back inserters... + void push_front(const_reference val) { insert(this->begin(), val); } + void push_back(const_reference val) { insert(this->end(), val); } + + void insert(iterator where, size_type count, const_reference val) { + for (; count != 0; --count) insert(where, val); + } + + // Assign special forms... + void assign(size_type count, const_reference val) { + iterator I = this->begin(); + for (; I != this->end() && count != 0; ++I, --count) + *I = val; + if (count != 0) + insert(this->end(), val, val); + else + erase(I, this->end()); + } + template<class InIt> void assign(InIt first1, InIt last1) { + iterator first2 = this->begin(), last2 = this->end(); + for ( ; first1 != last1 && first2 != last2; ++first1, ++first2) + *first1 = *first2; + if (first2 == last2) + erase(first1, last1); + else + insert(last1, first2, last2); + } + + + // Resize members... + void resize(size_type newsize, value_type val) { + iterator i = this->begin(); + size_type len = 0; + for ( ; i != this->end() && len < newsize; ++i, ++len) /* empty*/ ; + + if (len == newsize) + erase(i, this->end()); + else // i == end() + insert(this->end(), newsize - len, val); + } + void resize(size_type newsize) { resize(newsize, value_type()); } +}; + +} // End llvm namespace + +namespace std { + // Ensure that swap uses the fast list swap... + template<class Ty> + void swap(llvm::iplist<Ty> &Left, llvm::iplist<Ty> &Right) { + Left.swap(Right); + } +} // End 'std' extensions... + +#endif // LLVM_ADT_ILIST_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/ilist_base.h b/third_party/llvm-subzero/include/llvm/ADT/ilist_base.h new file mode 100644 index 0000000..a41696d --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/ilist_base.h
@@ -0,0 +1,93 @@ +//===- llvm/ADT/ilist_base.h - Intrusive List Base ---------------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_BASE_H +#define LLVM_ADT_ILIST_BASE_H + +#include "llvm/ADT/ilist_node_base.h" +#include <cassert> +#include <cstddef> +#include <type_traits> + +namespace llvm { + +/// Implementations of list algorithms using ilist_node_base. +class ilist_base { +public: + static void insertBeforeImpl(ilist_node_base &Next, ilist_node_base &N) { + ilist_node_base &Prev = *Next.getPrev(); + N.setNext(&Next); + N.setPrev(&Prev); + Prev.setNext(&N); + Next.setPrev(&N); + } + + static void removeImpl(ilist_node_base &N) { + ilist_node_base *Prev = N.getPrev(); + ilist_node_base *Next = N.getNext(); + Next->setPrev(Prev); + Prev->setNext(Next); + + // Not strictly necessary, but helps catch a class of bugs. + N.setPrev(nullptr); + N.setNext(nullptr); + } + + static void removeRangeImpl(ilist_node_base &First, ilist_node_base &Last) { + ilist_node_base *Prev = First.getPrev(); + ilist_node_base *Final = Last.getPrev(); + Last.setPrev(Prev); + Prev->setNext(&Last); + + // Not strictly necessary, but helps catch a class of bugs. + First.setPrev(nullptr); + Final->setNext(nullptr); + } + + static void transferBeforeImpl(ilist_node_base &Next, ilist_node_base &First, + ilist_node_base &Last) { + if (&Next == &Last || &First == &Last) + return; + + // Position cannot be contained in the range to be transferred. + assert(&Next != &First && + // Check for the most common mistake. + "Insertion point can't be one of the transferred nodes"); + + ilist_node_base &Final = *Last.getPrev(); + + // Detach from old list/position. + First.getPrev()->setNext(&Last); + Last.setPrev(First.getPrev()); + + // Splice [First, Final] into its new list/position. + ilist_node_base &Prev = *Next.getPrev(); + Final.setNext(&Next); + First.setPrev(&Prev); + Prev.setNext(&First); + Next.setPrev(&Final); + } + + template <class T> static void insertBefore(T &Next, T &N) { + insertBeforeImpl(Next, N); + } + + template <class T> static void remove(T &N) { removeImpl(N); } + template <class T> static void removeRange(T &First, T &Last) { + removeRangeImpl(First, Last); + } + + template <class T> static void transferBefore(T &Next, T &First, T &Last) { + transferBeforeImpl(Next, First, Last); + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_ILIST_BASE_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/ilist_iterator.h b/third_party/llvm-subzero/include/llvm/ADT/ilist_iterator.h new file mode 100644 index 0000000..d106d0c --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/ilist_iterator.h
@@ -0,0 +1,170 @@ +//===- llvm/ADT/ilist_iterator.h - Intrusive List Iterator -------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_ITERATOR_H +#define LLVM_ADT_ILIST_ITERATOR_H + +#include "llvm/ADT/ilist_node.h" +#include <cassert> +#include <cstddef> +#include <iterator> +#include <type_traits> + +namespace llvm { + +namespace ilist_detail { + +template <class NodeTy> struct ConstCorrectNodeType { + typedef ilist_node<NodeTy> type; +}; +template <class NodeTy> struct ConstCorrectNodeType<const NodeTy> { + typedef const ilist_node<NodeTy> type; +}; + +template <bool IsReverse = false> struct IteratorHelper { + template <class T> static void increment(T *&I) { + I = ilist_node_access::getNext(*I); + } + template <class T> static void decrement(T *&I) { + I = ilist_node_access::getPrev(*I); + } +}; +template <> struct IteratorHelper<true> { + template <class T> static void increment(T *&I) { + IteratorHelper<false>::decrement(I); + } + template <class T> static void decrement(T *&I) { + IteratorHelper<false>::increment(I); + } +}; + +} // end namespace ilist_detail + +/// Iterator for intrusive lists based on ilist_node. +template <typename NodeTy, bool IsReverse> class ilist_iterator { +public: + typedef NodeTy value_type; + typedef value_type *pointer; + typedef value_type &reference; + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + typedef typename std::add_const<value_type>::type *const_pointer; + typedef typename std::add_const<value_type>::type &const_reference; + + typedef typename ilist_detail::ConstCorrectNodeType<NodeTy>::type node_type; + typedef node_type *node_pointer; + typedef node_type &node_reference; + +private: + node_pointer NodePtr; + +public: + /// Create from an ilist_node. + explicit ilist_iterator(node_reference N) : NodePtr(&N) {} + + explicit ilist_iterator(pointer NP) + : NodePtr(ilist_node_access::getNodePtr(NP)) {} + explicit ilist_iterator(reference NR) + : NodePtr(ilist_node_access::getNodePtr(&NR)) {} + ilist_iterator() : NodePtr(nullptr) {} + + // This is templated so that we can allow constructing a const iterator from + // a nonconst iterator... + template <class node_ty> + ilist_iterator( + const ilist_iterator<node_ty, IsReverse> &RHS, + typename std::enable_if<std::is_convertible<node_ty *, NodeTy *>::value, + void *>::type = nullptr) + : NodePtr(RHS.getNodePtr()) {} + + // This is templated so that we can allow assigning to a const iterator from + // a nonconst iterator... + template <class node_ty> + const ilist_iterator & + operator=(const ilist_iterator<node_ty, IsReverse> &RHS) { + NodePtr = RHS.getNodePtr(); + return *this; + } + + /// Convert from an iterator to its reverse. + /// + /// TODO: Roll this into the implicit constructor once we're sure that no one + /// is relying on the std::reverse_iterator off-by-one semantics. + ilist_iterator<NodeTy, !IsReverse> getReverse() const { + if (NodePtr) + return ilist_iterator<NodeTy, !IsReverse>(*NodePtr); + return ilist_iterator<NodeTy, !IsReverse>(); + } + + void reset(pointer NP) { NodePtr = NP; } + + // Accessors... + reference operator*() const { + assert(!NodePtr->isKnownSentinel()); + return *ilist_node_access::getValuePtr(NodePtr); + } + pointer operator->() const { return &operator*(); } + + // Comparison operators + friend bool operator==(const ilist_iterator &LHS, const ilist_iterator &RHS) { + return LHS.NodePtr == RHS.NodePtr; + } + friend bool operator!=(const ilist_iterator &LHS, const ilist_iterator &RHS) { + return LHS.NodePtr != RHS.NodePtr; + } + + // Increment and decrement operators... + ilist_iterator &operator--() { + ilist_detail::IteratorHelper<IsReverse>::decrement(NodePtr); + return *this; + } + ilist_iterator &operator++() { + ilist_detail::IteratorHelper<IsReverse>::increment(NodePtr); + return *this; + } + ilist_iterator operator--(int) { + ilist_iterator tmp = *this; + --*this; + return tmp; + } + ilist_iterator operator++(int) { + ilist_iterator tmp = *this; + ++*this; + return tmp; + } + + /// Get the underlying ilist_node. + node_pointer getNodePtr() const { return static_cast<node_pointer>(NodePtr); } +}; + +template <typename From> struct simplify_type; + +/// Allow ilist_iterators to convert into pointers to a node automatically when +/// used by the dyn_cast, cast, isa mechanisms... +/// +/// FIXME: remove this, since there is no implicit conversion to NodeTy. +template <typename NodeTy> struct simplify_type<ilist_iterator<NodeTy>> { + typedef NodeTy *SimpleType; + + static SimpleType getSimplifiedValue(ilist_iterator<NodeTy> &Node) { + return &*Node; + } +}; +template <typename NodeTy> struct simplify_type<const ilist_iterator<NodeTy>> { + typedef /*const*/ NodeTy *SimpleType; + + static SimpleType getSimplifiedValue(const ilist_iterator<NodeTy> &Node) { + return &*Node; + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_ILIST_ITERATOR_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/ilist_node.h b/third_party/llvm-subzero/include/llvm/ADT/ilist_node.h new file mode 100644 index 0000000..a5e2f5e --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/ilist_node.h
@@ -0,0 +1,169 @@ +//==-- llvm/ADT/ilist_node.h - Intrusive Linked List Helper ------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ilist_node class template, which is a convenient +// base class for creating classes that can be used with ilists. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_NODE_H +#define LLVM_ADT_ILIST_NODE_H + +#include "llvm/ADT/ilist_node_base.h" + +namespace llvm { + +template<typename NodeTy> +struct ilist_traits; + +struct ilist_node_access; +template <typename NodeTy, bool IsReverse = false> class ilist_iterator; +template <typename NodeTy> class ilist_sentinel; + +/// Templated wrapper class. +template <typename NodeTy> class ilist_node : ilist_node_base { + friend class ilist_base; + friend struct ilist_node_access; + friend struct ilist_traits<NodeTy>; + friend class ilist_iterator<NodeTy, false>; + friend class ilist_iterator<NodeTy, true>; + friend class ilist_sentinel<NodeTy>; + +protected: + ilist_node() = default; + +private: + ilist_node *getPrev() { + return static_cast<ilist_node *>(ilist_node_base::getPrev()); + } + ilist_node *getNext() { + return static_cast<ilist_node *>(ilist_node_base::getNext()); + } + + const ilist_node *getPrev() const { + return static_cast<ilist_node *>(ilist_node_base::getPrev()); + } + const ilist_node *getNext() const { + return static_cast<ilist_node *>(ilist_node_base::getNext()); + } + + void setPrev(ilist_node *N) { ilist_node_base::setPrev(N); } + void setNext(ilist_node *N) { ilist_node_base::setNext(N); } + +public: + ilist_iterator<NodeTy> getIterator() { return ilist_iterator<NodeTy>(*this); } + ilist_iterator<const NodeTy> getIterator() const { + return ilist_iterator<const NodeTy>(*this); + } + + using ilist_node_base::isKnownSentinel; +}; + +/// An access class for ilist_node private API. +/// +/// This gives access to the private parts of ilist nodes. Nodes for an ilist +/// should friend this class if they inherit privately from ilist_node. +/// +/// Using this class outside of the ilist implementation is unsupported. +struct ilist_node_access { + template <typename T> static ilist_node<T> *getNodePtr(T *N) { return N; } + template <typename T> static const ilist_node<T> *getNodePtr(const T *N) { + return N; + } + template <typename T> static T *getValuePtr(ilist_node<T> *N) { + return static_cast<T *>(N); + } + template <typename T> static const T *getValuePtr(const ilist_node<T> *N) { + return static_cast<const T *>(N); + } + + template <typename T> static ilist_node<T> *getPrev(ilist_node<T> &N) { + return N.getPrev(); + } + template <typename T> static ilist_node<T> *getNext(ilist_node<T> &N) { + return N.getNext(); + } + template <typename T> + static const ilist_node<T> *getPrev(const ilist_node<T> &N) { + return N.getPrev(); + } + template <typename T> + static const ilist_node<T> *getNext(const ilist_node<T> &N) { + return N.getNext(); + } +}; + +template <typename NodeTy> class ilist_sentinel : public ilist_node<NodeTy> { +public: + ilist_sentinel() { + ilist_node_base::initializeSentinel(); + reset(); + } + + void reset() { + this->setPrev(this); + this->setNext(this); + } + + bool empty() const { return this == this->getPrev(); } +}; + +/// An ilist node that can access its parent list. +/// +/// Requires \c NodeTy to have \a getParent() to find the parent node, and the +/// \c ParentTy to have \a getSublistAccess() to get a reference to the list. +template <typename NodeTy, typename ParentTy> +class ilist_node_with_parent : public ilist_node<NodeTy> { +protected: + ilist_node_with_parent() = default; + +private: + /// Forward to NodeTy::getParent(). + /// + /// Note: do not use the name "getParent()". We want a compile error + /// (instead of recursion) when the subclass fails to implement \a + /// getParent(). + const ParentTy *getNodeParent() const { + return static_cast<const NodeTy *>(this)->getParent(); + } + +public: + /// @name Adjacent Node Accessors + /// @{ + /// \brief Get the previous node, or \c nullptr for the list head. + NodeTy *getPrevNode() { + // Should be separated to a reused function, but then we couldn't use auto + // (and would need the type of the list). + const auto &List = + getNodeParent()->*(ParentTy::getSublistAccess((NodeTy *)nullptr)); + return List.getPrevNode(*static_cast<NodeTy *>(this)); + } + /// \brief Get the previous node, or \c nullptr for the list head. + const NodeTy *getPrevNode() const { + return const_cast<ilist_node_with_parent *>(this)->getPrevNode(); + } + + /// \brief Get the next node, or \c nullptr for the list tail. + NodeTy *getNextNode() { + // Should be separated to a reused function, but then we couldn't use auto + // (and would need the type of the list). + const auto &List = + getNodeParent()->*(ParentTy::getSublistAccess((NodeTy *)nullptr)); + return List.getNextNode(*static_cast<NodeTy *>(this)); + } + /// \brief Get the next node, or \c nullptr for the list tail. + const NodeTy *getNextNode() const { + return const_cast<ilist_node_with_parent *>(this)->getNextNode(); + } + /// @} +}; + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/ilist_node_base.h b/third_party/llvm-subzero/include/llvm/ADT/ilist_node_base.h new file mode 100644 index 0000000..6a46876 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/ilist_node_base.h
@@ -0,0 +1,47 @@ +//===- llvm/ADT/ilist_node_base.h - Intrusive List Node Base -----*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_NODE_BASE_H +#define LLVM_ADT_ILIST_NODE_BASE_H + +#include "llvm/ADT/PointerIntPair.h" + +namespace llvm { + +/// Base class for ilist nodes. +class ilist_node_base { +#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS + PointerIntPair<ilist_node_base *, 1> PrevAndSentinel; +#else + ilist_node_base *Prev = nullptr; +#endif + ilist_node_base *Next = nullptr; + +public: +#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS + void setPrev(ilist_node_base *Prev) { PrevAndSentinel.setPointer(Prev); } + ilist_node_base *getPrev() const { return PrevAndSentinel.getPointer(); } + + bool isKnownSentinel() const { return PrevAndSentinel.getInt(); } + void initializeSentinel() { PrevAndSentinel.setInt(true); } +#else + void setPrev(ilist_node_base *Prev) { this->Prev = Prev; } + ilist_node_base *getPrev() const { return Prev; } + + bool isKnownSentinel() const { return false; } + void initializeSentinel() {} +#endif + + void setNext(ilist_node_base *Next) { this->Next = Next; } + ilist_node_base *getNext() const { return Next; } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_ILIST_NODE_BASE_H
diff --git a/third_party/llvm-subzero/include/llvm/ADT/iterator.h b/third_party/llvm-subzero/include/llvm/ADT/iterator.h new file mode 100644 index 0000000..30b8ac1 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/iterator.h
@@ -0,0 +1,278 @@ +//===- iterator.h - Utilities for using and defining iterators --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ITERATOR_H +#define LLVM_ADT_ITERATOR_H + +#include <cstddef> +#include <iterator> + +namespace llvm { + +/// \brief CRTP base class which implements the entire standard iterator facade +/// in terms of a minimal subset of the interface. +/// +/// Use this when it is reasonable to implement most of the iterator +/// functionality in terms of a core subset. If you need special behavior or +/// there are performance implications for this, you may want to override the +/// relevant members instead. +/// +/// Note, one abstraction that this does *not* provide is implementing +/// subtraction in terms of addition by negating the difference. Negation isn't +/// always information preserving, and I can see very reasonable iterator +/// designs where this doesn't work well. It doesn't really force much added +/// boilerplate anyways. +/// +/// Another abstraction that this doesn't provide is implementing increment in +/// terms of addition of one. These aren't equivalent for all iterator +/// categories, and respecting that adds a lot of complexity for little gain. +template <typename DerivedT, typename IteratorCategoryT, typename T, + typename DifferenceTypeT = std::ptrdiff_t, typename PointerT = T *, + typename ReferenceT = T &> +class iterator_facade_base + : public std::iterator<IteratorCategoryT, T, DifferenceTypeT, PointerT, + ReferenceT> { +protected: + enum { + IsRandomAccess = + std::is_base_of<std::random_access_iterator_tag, IteratorCategoryT>::value, + IsBidirectional = + std::is_base_of<std::bidirectional_iterator_tag, IteratorCategoryT>::value, + }; + + /// A proxy object for computing a reference via indirecting a copy of an + /// iterator. This is used in APIs which need to produce a reference via + /// indirection but for which the iterator object might be a temporary. The + /// proxy preserves the iterator internally and exposes the indirected + /// reference via a conversion operator. + class ReferenceProxy { + friend iterator_facade_base; + + DerivedT I; + + ReferenceProxy(DerivedT I) : I(std::move(I)) {} + + public: + operator ReferenceT() const { return *I; } + }; + +public: + DerivedT operator+(DifferenceTypeT n) const { + static_assert( + IsRandomAccess, + "The '+' operator is only defined for random access iterators."); + DerivedT tmp = *static_cast<const DerivedT *>(this); + tmp += n; + return tmp; + } + friend DerivedT operator+(DifferenceTypeT n, const DerivedT &i) { + static_assert( + IsRandomAccess, + "The '+' operator is only defined for random access iterators."); + return i + n; + } + DerivedT operator-(DifferenceTypeT n) const { + static_assert( + IsRandomAccess, + "The '-' operator is only defined for random access iterators."); + DerivedT tmp = *static_cast<const DerivedT *>(this); + tmp -= n; + return tmp; + } + + DerivedT &operator++() { + return static_cast<DerivedT *>(this)->operator+=(1); + } + DerivedT operator++(int) { + DerivedT tmp = *static_cast<DerivedT *>(this); + ++*static_cast<DerivedT *>(this); + return tmp; + } + DerivedT &operator--() { + static_assert( + IsBidirectional, + "The decrement operator is only defined for bidirectional iterators."); + return static_cast<DerivedT *>(this)->operator-=(1); + } + DerivedT operator--(int) { + static_assert( + IsBidirectional, + "The decrement operator is only defined for bidirectional iterators."); + DerivedT tmp = *static_cast<DerivedT *>(this); + --*static_cast<DerivedT *>(this); + return tmp; + } + + bool operator!=(const DerivedT &RHS) const { + return !static_cast<const DerivedT *>(this)->operator==(RHS); + } + + bool operator>(const DerivedT &RHS) const { + static_assert( + IsRandomAccess, + "Relational operators are only defined for random access iterators."); + return !static_cast<const DerivedT *>(this)->operator<(RHS) && + !static_cast<const DerivedT *>(this)->operator==(RHS); + } + bool operator<=(const DerivedT &RHS) const { + static_assert( + IsRandomAccess, + "Relational operators are only defined for random access iterators."); + return !static_cast<const DerivedT *>(this)->operator>(RHS); + } + bool operator>=(const DerivedT &RHS) const { + static_assert( + IsRandomAccess, + "Relational operators are only defined for random access iterators."); + return !static_cast<const DerivedT *>(this)->operator<(RHS); + } + + PointerT operator->() const { + return &static_cast<const DerivedT *>(this)->operator*(); + } + ReferenceProxy operator[](DifferenceTypeT n) const { + static_assert(IsRandomAccess, + "Subscripting is only defined for random access iterators."); + return ReferenceProxy(static_cast<const DerivedT *>(this)->operator+(n)); + } +}; + +/// \brief CRTP base class for adapting an iterator to a different type. +/// +/// This class can be used through CRTP to adapt one iterator into another. +/// Typically this is done through providing in the derived class a custom \c +/// operator* implementation. Other methods can be overridden as well. +template < + typename DerivedT, typename WrappedIteratorT, + typename IteratorCategoryT = + typename std::iterator_traits<WrappedIteratorT>::iterator_category, + typename T = typename std::iterator_traits<WrappedIteratorT>::value_type, + typename DifferenceTypeT = + typename std::iterator_traits<WrappedIteratorT>::difference_type, + typename PointerT = typename std::conditional< + std::is_same<T, typename std::iterator_traits< + WrappedIteratorT>::value_type>::value, + typename std::iterator_traits<WrappedIteratorT>::pointer, T *>::type, + typename ReferenceT = typename std::conditional< + std::is_same<T, typename std::iterator_traits< + WrappedIteratorT>::value_type>::value, + typename std::iterator_traits<WrappedIteratorT>::reference, T &>::type, + // Don't provide these, they are mostly to act as aliases below. + typename WrappedTraitsT = std::iterator_traits<WrappedIteratorT>> +class iterator_adaptor_base + : public iterator_facade_base<DerivedT, IteratorCategoryT, T, + DifferenceTypeT, PointerT, ReferenceT> { + typedef typename iterator_adaptor_base::iterator_facade_base BaseT; + +protected: + WrappedIteratorT I; + + iterator_adaptor_base() = default; + + explicit iterator_adaptor_base(WrappedIteratorT u) : I(std::move(u)) {} + + const WrappedIteratorT &wrapped() const { return I; } + +public: + typedef DifferenceTypeT difference_type; + + DerivedT &operator+=(difference_type n) { + static_assert( + BaseT::IsRandomAccess, + "The '+=' operator is only defined for random access iterators."); + I += n; + return *static_cast<DerivedT *>(this); + } + DerivedT &operator-=(difference_type n) { + static_assert( + BaseT::IsRandomAccess, + "The '-=' operator is only defined for random access iterators."); + I -= n; + return *static_cast<DerivedT *>(this); + } + using BaseT::operator-; + difference_type operator-(const DerivedT &RHS) const { + static_assert( + BaseT::IsRandomAccess, + "The '-' operator is only defined for random access iterators."); + return I - RHS.I; + } + + // We have to explicitly provide ++ and -- rather than letting the facade + // forward to += because WrappedIteratorT might not support +=. + using BaseT::operator++; + DerivedT &operator++() { + ++I; + return *static_cast<DerivedT *>(this); + } + using BaseT::operator--; + DerivedT &operator--() { + static_assert( + BaseT::IsBidirectional, + "The decrement operator is only defined for bidirectional iterators."); + --I; + return *static_cast<DerivedT *>(this); + } + + bool operator==(const DerivedT &RHS) const { return I == RHS.I; } + bool operator<(const DerivedT &RHS) const { + static_assert( + BaseT::IsRandomAccess, + "Relational operators are only defined for random access iterators."); + return I < RHS.I; + } + + ReferenceT operator*() const { return *I; } +}; + +/// \brief An iterator type that allows iterating over the pointees via some +/// other iterator. +/// +/// The typical usage of this is to expose a type that iterates over Ts, but +/// which is implemented with some iterator over T*s: +/// +/// \code +/// typedef pointee_iterator<SmallVectorImpl<T *>::iterator> iterator; +/// \endcode +template <typename WrappedIteratorT, + typename T = typename std::remove_reference< + decltype(**std::declval<WrappedIteratorT>())>::type> +struct pointee_iterator + : iterator_adaptor_base< + pointee_iterator<WrappedIteratorT>, WrappedIteratorT, + typename std::iterator_traits<WrappedIteratorT>::iterator_category, + T> { + pointee_iterator() = default; + template <typename U> + pointee_iterator(U &&u) + : pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u)) {} + + T &operator*() const { return **this->I; } +}; + +template <typename WrappedIteratorT, + typename T = decltype(&*std::declval<WrappedIteratorT>())> +class pointer_iterator + : public iterator_adaptor_base<pointer_iterator<WrappedIteratorT>, + WrappedIteratorT, T> { + mutable T Ptr; + +public: + pointer_iterator() {} + + explicit pointer_iterator(WrappedIteratorT u) + : pointer_iterator::iterator_adaptor_base(std::move(u)) {} + + T &operator*() { return Ptr = &*this->I; } + const T &operator*() const { return Ptr = &*this->I; } +}; + +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/iterator_range.h b/third_party/llvm-subzero/include/llvm/ADT/iterator_range.h new file mode 100644 index 0000000..3dd679b --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/iterator_range.h
@@ -0,0 +1,68 @@ +//===- iterator_range.h - A range adaptor for iterators ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This provides a very simple, boring adaptor for a begin and end iterator +/// into a range type. This should be used to build range views that work well +/// with range based for loops and range based constructors. +/// +/// Note that code here follows more standards-based coding conventions as it +/// is mirroring proposed interfaces for standardization. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ITERATOR_RANGE_H +#define LLVM_ADT_ITERATOR_RANGE_H + +#include <utility> +#include <iterator> + +namespace llvm { + +/// \brief A range adaptor for a pair of iterators. +/// +/// This just wraps two iterators into a range-compatible interface. Nothing +/// fancy at all. +template <typename IteratorT> +class iterator_range { + IteratorT begin_iterator, end_iterator; + +public: + //TODO: Add SFINAE to test that the Container's iterators match the range's + // iterators. + template <typename Container> + iterator_range(Container &&c) + //TODO: Consider ADL/non-member begin/end calls. + : begin_iterator(c.begin()), end_iterator(c.end()) {} + iterator_range(IteratorT begin_iterator, IteratorT end_iterator) + : begin_iterator(std::move(begin_iterator)), + end_iterator(std::move(end_iterator)) {} + + IteratorT begin() const { return begin_iterator; } + IteratorT end() const { return end_iterator; } +}; + +/// \brief Convenience function for iterating over sub-ranges. +/// +/// This provides a bit of syntactic sugar to make using sub-ranges +/// in for loops a bit easier. Analogous to std::make_pair(). +template <class T> iterator_range<T> make_range(T x, T y) { + return iterator_range<T>(std::move(x), std::move(y)); +} + +template <typename T> iterator_range<T> make_range(std::pair<T, T> p) { + return iterator_range<T>(std::move(p.first), std::move(p.second)); +} + +template<typename T> +iterator_range<decltype(begin(std::declval<T>()))> drop_begin(T &&t, int n) { + return make_range(std::next(begin(t), n), end(t)); +} +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/ADT/simple_ilist.h b/third_party/llvm-subzero/include/llvm/ADT/simple_ilist.h new file mode 100644 index 0000000..f9983d8 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/ADT/simple_ilist.h
@@ -0,0 +1,269 @@ +//===- llvm/ADT/simple_ilist.h - Simple Intrusive List ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SIMPLE_ILIST_H +#define LLVM_ADT_SIMPLE_ILIST_H + +#include "llvm/ADT/ilist_base.h" +#include "llvm/ADT/ilist_iterator.h" +#include "llvm/ADT/ilist_node.h" +#include <algorithm> +#include <cassert> +#include <cstddef> + +namespace llvm { + +/// A simple intrusive list implementation. +/// +/// This is a simple intrusive list for a \c T that inherits from \c +/// ilist_node<T>. The list never takes ownership of anything inserted in it. +/// +/// Unlike \a iplist<T> and \a ilist<T>, \a simple_ilist<T> never allocates or +/// deletes values, and has no callback traits. +/// +/// The API for adding nodes include \a push_front(), \a push_back(), and \a +/// insert(). These all take values by reference (not by pointer), except for +/// the range version of \a insert(). +/// +/// There are three sets of API for discarding nodes from the list: \a +/// remove(), which takes a reference to the node to remove, \a erase(), which +/// takes an iterator or iterator range and returns the next one, and \a +/// clear(), which empties out the container. All three are constant time +/// operations. None of these deletes any nodes; in particular, if there is a +/// single node in the list, then these have identical semantics: +/// \li \c L.remove(L.front()); +/// \li \c L.erase(L.begin()); +/// \li \c L.clear(); +/// +/// As a convenience for callers, there are parallel APIs that take a \c +/// Disposer (such as \c std::default_delete<T>): \a removeAndDispose(), \a +/// eraseAndDispose(), and \a clearAndDispose(). These have different names +/// because the extra semantic is otherwise non-obvious. They are equivalent +/// to calling \a std::for_each() on the range to be discarded. +template <typename T> class simple_ilist : ilist_base, ilist_node_access { + ilist_sentinel<T> Sentinel; + +public: + typedef T value_type; + typedef T *pointer; + typedef T &reference; + typedef const T *const_pointer; + typedef const T &const_reference; + typedef ilist_iterator<T> iterator; + typedef ilist_iterator<const T> const_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef ilist_iterator<const T, true> const_reverse_iterator; + typedef ilist_iterator<T, true> reverse_iterator; + + simple_ilist() = default; + ~simple_ilist() = default; + + // No copy constructors. + simple_ilist(const simple_ilist &) = delete; + simple_ilist &operator=(const simple_ilist &) = delete; + + // Move constructors. + simple_ilist(simple_ilist &&X) { splice(end(), X); } + simple_ilist &operator=(simple_ilist &&X) { + clear(); + splice(end(), X); + return *this; + } + + iterator begin() { return ++iterator(Sentinel); } + const_iterator begin() const { return ++const_iterator(Sentinel); } + iterator end() { return iterator(Sentinel); } + const_iterator end() const { return const_iterator(Sentinel); } + reverse_iterator rbegin() { return ++reverse_iterator(Sentinel); } + const_reverse_iterator rbegin() const { + return ++const_reverse_iterator(Sentinel); + } + reverse_iterator rend() { return reverse_iterator(Sentinel); } + const_reverse_iterator rend() const { + return const_reverse_iterator(Sentinel); + } + + /// Check if the list is empty in constant time. + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return Sentinel.empty(); } + + /// Calculate the size of the list in linear time. + size_type LLVM_ATTRIBUTE_UNUSED_RESULT size() const { + return std::distance(begin(), end()); + } + + reference front() { return *begin(); } + const_reference front() const { return *begin(); } + reference back() { return *rbegin(); } + const_reference back() const { return *rbegin(); } + + /// Insert a node at the front; never copies. + void push_front(reference Node) { insert(begin(), Node); } + + /// Insert a node at the back; never copies. + void push_back(reference Node) { insert(end(), Node); } + + /// Remove the node at the front; never deletes. + void pop_front() { erase(begin()); } + + /// Remove the node at the back; never deletes. + void pop_back() { erase(--end()); } + + /// Swap with another list in place using std::swap. + void swap(simple_ilist &X) { std::swap(*this, X); } + + /// Insert a node by reference; never copies. + iterator insert(iterator I, reference Node) { + ilist_base::insertBefore(*I.getNodePtr(), *this->getNodePtr(&Node)); + return iterator(&Node); + } + + /// Insert a range of nodes; never copies. + template <class Iterator> + void insert(iterator I, Iterator First, Iterator Last) { + for (; First != Last; ++First) + insert(I, *First); + } + + /// Remove a node by reference; never deletes. + /// + /// \see \a erase() for removing by iterator. + /// \see \a removeAndDispose() if the node should be deleted. + void remove(reference N) { ilist_base::remove(*this->getNodePtr(&N)); } + + /// Remove a node by reference and dispose of it. + template <class Disposer> + void removeAndDispose(reference N, Disposer dispose) { + remove(N); + dispose(&N); + } + + /// Remove a node by iterator; never deletes. + /// + /// \see \a remove() for removing by reference. + /// \see \a eraseAndDispose() it the node should be deleted. + iterator erase(iterator I) { + assert(I != end() && "Cannot remove end of list!"); + remove(*I++); + return I; + } + + /// Remove a range of nodes; never deletes. + /// + /// \see \a eraseAndDispose() if the nodes should be deleted. + iterator erase(iterator First, iterator Last) { + ilist_base::removeRange(*First.getNodePtr(), *Last.getNodePtr()); + return Last; + } + + /// Remove a node by iterator and dispose of it. + template <class Disposer> + iterator eraseAndDispose(iterator I, Disposer dispose) { + auto Next = std::next(I); + erase(I); + dispose(&*I); + return Next; + } + + /// Remove a range of nodes and dispose of them. + template <class Disposer> + iterator eraseAndDispose(iterator First, iterator Last, Disposer dispose) { + while (First != Last) + First = eraseAndDispose(First, dispose); + return Last; + } + + /// Clear the list; never deletes. + /// + /// \see \a clearAndDispose() if the nodes should be deleted. + void clear() { Sentinel.reset(); } + + /// Clear the list and dispose of the nodes. + template <class Disposer> void clearAndDispose(Disposer dispose) { + eraseAndDispose(begin(), end(), dispose); + } + + /// Splice in another list. + void splice(iterator I, simple_ilist &L2) { + splice(I, L2, L2.begin(), L2.end()); + } + + /// Splice in a node from another list. + void splice(iterator I, simple_ilist &L2, iterator Node) { + splice(I, L2, Node, std::next(Node)); + } + + /// Splice in a range of nodes from another list. + void splice(iterator I, simple_ilist &, iterator First, iterator Last) { + ilist_base::transferBefore(*I.getNodePtr(), *First.getNodePtr(), + *Last.getNodePtr()); + } + + /// Merge in another list. + /// + /// \pre \c this and \p RHS are sorted. + ///@{ + void merge(simple_ilist &RHS) { merge(RHS, std::less<T>()); } + template <class Compare> void merge(simple_ilist &RHS, Compare comp); + ///@} + + /// Sort the list. + ///@{ + void sort() { sort(std::less<T>()); } + template <class Compare> void sort(Compare comp); + ///@} +}; + +template <class T> +template <class Compare> +void simple_ilist<T>::merge(simple_ilist<T> &RHS, Compare comp) { + if (this == &RHS || RHS.empty()) + return; + iterator LI = begin(), LE = end(); + iterator RI = RHS.begin(), RE = RHS.end(); + while (LI != LE) { + if (comp(*RI, *LI)) { + // Transfer a run of at least size 1 from RHS to LHS. + iterator RunStart = RI++; + RI = std::find_if(RI, RE, [&](reference RV) { return !comp(RV, *LI); }); + splice(LI, RHS, RunStart, RI); + if (RI == RE) + return; + } + ++LI; + } + // Transfer the remaining RHS nodes once LHS is finished. + splice(LE, RHS, RI, RE); +} + +template <class T> +template <class Compare> +void simple_ilist<T>::sort(Compare comp) { + // Vacuously sorted. + if (empty() || std::next(begin()) == end()) + return; + + // Split the list in the middle. + iterator Center = begin(), End = begin(); + while (End != end() && ++End != end()) { + ++Center; + ++End; + } + simple_ilist<T> RHS; + RHS.splice(RHS.end(), *this, Center, end()); + + // Sort the sublists and merge back together. + sort(comp); + RHS.sort(comp); + merge(RHS, comp); +} + +} // end namespace llvm + +#endif // LLVM_ADT_SIMPLE_ILIST_H
diff --git a/third_party/llvm-subzero/include/llvm/Config/config.h b/third_party/llvm-subzero/include/llvm/Config/config.h new file mode 100644 index 0000000..2d77390 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Config/config.h
@@ -0,0 +1,584 @@ +/* include/llvm/Config/config.h.cmake corresponding to config.h.in. */ + +#ifndef CONFIG_H +#define CONFIG_H + +/* Exported configuration */ +#include "llvm/Config/llvm-config.h" + +/* Bug report URL. */ +#define BUG_REPORT_URL "http://llvm.org/bugs/" + +/* Define if you want backtraces on crash */ +#define ENABLE_BACKTRACES + +/* Define to enable crash overrides */ +#define ENABLE_CRASH_OVERRIDES + +/* Define to disable C++ atexit */ +#define DISABLE_LLVM_DYLIB_ATEXIT + +/* Define if position independent code is enabled */ +#define ENABLE_PIC + +/* Define if timestamp information (e.g., __DATE__) is allowed */ +#define ENABLE_TIMESTAMPS 1 + +/* Define to 1 if you have the `arc4random' function. */ +/* #undef HAVE_DECL_ARC4RANDOM */ + +/* Define to 1 if you have the `backtrace' function. */ +/* #undef HAVE_BACKTRACE */ + +/* Define to 1 if you have the `bcopy' function. */ +#undef HAVE_BCOPY + +/* Define to 1 if you have the `closedir' function. */ +/* #undef HAVE_CLOSEDIR */ + +/* Define to 1 if you have the <cxxabi.h> header file. */ +/* #undef HAVE_CXXABI_H */ + +/* Define to 1 if you have the <CrashReporterClient.h> header file. */ +#undef HAVE_CRASHREPORTERCLIENT_H + +/* can use __crashreporter_info__ */ +#undef HAVE_CRASHREPORTER_INFO + +/* Define to 1 if you have the declaration of `strerror_s', and to 0 if you +don't. */ +#define HAVE_DECL_STRERROR_S 1 + +/* Define to 1 if you have the DIA SDK installed, and to 0 if you don't. */ +/* #undef HAVE_DIA_SDK */ + +/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'. +*/ +/* #undef HAVE_DIRENT_H */ + +/* Define if you have the GNU dld library. */ +#undef HAVE_DLD + +/* Define to 1 if you have the `dlerror' function. */ +/* #undef HAVE_DLERROR */ + +/* Define to 1 if you have the <dlfcn.h> header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define if dlopen() is available on this platform. */ +/* #undef HAVE_DLOPEN */ + +/* Define if you have the _dyld_func_lookup function. */ +#undef HAVE_DYLD + +/* Define to 1 if you have the <errno.h> header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the <execinfo.h> header file. */ +/* #undef HAVE_EXECINFO_H */ + +/* Define to 1 if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the <fenv.h> header file. */ +#define HAVE_FENV_H 1 + +/* Define if libffi is available on this platform. */ +/* #undef HAVE_FFI_CALL */ + +/* Define to 1 if you have the <ffi/ffi.h> header file. */ +/* #undef HAVE_FFI_FFI_H */ + +/* Define to 1 if you have the <ffi.h> header file. */ +/* #undef HAVE_FFI_H */ + +/* Define to 1 if you have the `futimes' function. */ +/* #undef HAVE_FUTIMES */ + +/* Define to 1 if you have the `futimens' function */ +/* #undef HAVE_FUTIMENS */ + +/* Define to 1 if you have the `getcwd' function. */ +/* #undef HAVE_GETCWD */ + +/* Define to 1 if you have the `getpagesize' function. */ +/* #undef HAVE_GETPAGESIZE */ + +/* Define to 1 if you have the `getrlimit' function. */ +/* #undef HAVE_GETRLIMIT */ + +/* Define to 1 if you have the `getrusage' function. */ +/* #undef HAVE_GETRUSAGE */ + +/* Define to 1 if you have the `gettimeofday' function. */ +/* #undef HAVE_GETTIMEOFDAY */ + +/* Define to 1 if the system has the type `int64_t'. */ +#define HAVE_INT64_T 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `isatty' function. */ +/* #undef HAVE_ISATTY */ + +/* Define if you have the libdl library or equivalent. */ +/* #undef HAVE_LIBDL */ + +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + +/* Define to 1 if you have the `ole32' library (-lole32). */ +#undef HAVE_LIBOLE32 + +/* Define to 1 if you have the `psapi' library (-lpsapi). */ +/* #undef HAVE_LIBPSAPI */ + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +/* #undef HAVE_LIBPTHREAD */ + +/* Define to 1 if you have the `shell32' library (-lshell32). */ +/* #undef HAVE_LIBSHELL32 */ + +/* Define to 1 if you have the 'z' library (-lz). */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if you have the 'edit' library (-ledit). */ +/* #undef HAVE_LIBEDIT */ + +/* Define to 1 if you have the <limits.h> header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the <link.h> header file. */ +/* #undef HAVE_LINK_H */ + +/* Define if you can use -rdynamic. */ +#define HAVE_LINK_EXPORT_DYNAMIC 1 + +/* Define if you can use -Wl,-R. to pass -R. to the linker, in order to add +the current directory to the dynamic linker search path. */ +#undef HAVE_LINK_R + +/* Define to 1 if you have the `longjmp' function. */ +/* #undef HAVE_LONGJMP */ + +/* Define to 1 if you have the <mach/mach.h> header file. */ +/* #undef HAVE_MACH_MACH_H */ + +/* Define to 1 if you have the <mach-o/dyld.h> header file. */ +/* #undef HAVE_MACH_O_DYLD_H */ + +/* Define if mallinfo() is available on this platform. */ +/* #undef HAVE_MALLINFO */ + +/* Define to 1 if you have the <malloc.h> header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the <malloc/malloc.h> header file. */ +/* #undef HAVE_MALLOC_MALLOC_H */ + +/* Define to 1 if you have the `malloc_zone_statistics' function. */ +/* #undef HAVE_MALLOC_ZONE_STATISTICS */ + +/* Define to 1 if you have the `mallctl` function. */ +/* #undef HAVE_MALLCTL */ + +/* Define to 1 if you have the `mkdtemp' function. */ +/* #undef HAVE_MKDTEMP */ + +/* Define to 1 if you have the `mkstemp' function. */ +/* #undef HAVE_MKSTEMP */ + +/* Define to 1 if you have the `mktemp' function. */ +/* #undef HAVE_MKTEMP */ + +/* Define to 1 if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if mmap() uses MAP_ANONYMOUS to map anonymous pages, or undefine if +it uses MAP_ANON */ +#undef HAVE_MMAP_ANONYMOUS + +/* Define if mmap() can map files into memory */ +#undef HAVE_MMAP_FILE + +/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ +/* #undef HAVE_NDIR_H */ + +/* Define to 1 if you have the `opendir' function. */ +/* #undef HAVE_OPENDIR */ + +/* Define to 1 if you have the `posix_spawn' function. */ +/* #undef HAVE_POSIX_SPAWN */ + +/* Define to 1 if you have the `pread' function. */ +/* #undef HAVE_PREAD */ + +/* Define if libtool can extract symbol lists from object files. */ +#undef HAVE_PRELOADED_SYMBOLS + +/* Define to have the %a format string */ +#undef HAVE_PRINTF_A + +/* Have pthread_getspecific */ +/* #undef HAVE_PTHREAD_GETSPECIFIC */ + +/* Define to 1 if you have the <pthread.h> header file. */ +/* #undef HAVE_PTHREAD_H */ + +/* Have pthread_mutex_lock */ +/* #undef HAVE_PTHREAD_MUTEX_LOCK */ + +/* Have pthread_rwlock_init */ +/* #undef HAVE_PTHREAD_RWLOCK_INIT */ + +/* Define to 1 if srand48/lrand48/drand48 exist in <stdlib.h> */ +/* #undef HAVE_RAND48 */ + +/* Define to 1 if you have the `readdir' function. */ +/* #undef HAVE_READDIR */ + +/* Define to 1 if you have the `realpath' function. */ +/* #undef HAVE_REALPATH */ + +/* Define to 1 if you have the `sbrk' function. */ +/* #undef HAVE_SBRK */ + +/* Define to 1 if you have the `setenv' function. */ +/* #undef HAVE_SETENV */ + +/* Define to 1 if you have the `setjmp' function. */ +/* #undef HAVE_SETJMP */ + +/* Define to 1 if you have the `setrlimit' function. */ +/* #undef HAVE_SETRLIMIT */ + +/* Define if you have the shl_load function. */ +#undef HAVE_SHL_LOAD + +/* Define to 1 if you have the `siglongjmp' function. */ +/* #undef HAVE_SIGLONGJMP */ + +/* Define to 1 if you have the <signal.h> header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the `sigsetjmp' function. */ +/* #undef HAVE_SIGSETJMP */ + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Set to 1 if the std::isinf function is found in <cmath> */ +#undef HAVE_STD_ISINF_IN_CMATH + +/* Set to 1 if the std::isnan function is found in <cmath> */ +#undef HAVE_STD_ISNAN_IN_CMATH + +/* Define to 1 if you have the `strdup' function. */ +/* #undef HAVE_STRDUP */ + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the `strerror_r' function. */ +/* #undef HAVE_STRERROR_R */ + +/* Define to 1 if you have the `strtoll' function. */ +#define HAVE_STRTOLL 1 + +/* Define to 1 if you have the `strtoq' function. */ +/* #undef HAVE_STRTOQ */ + +/* Define to 1 if you have the `sysconf' function. */ +#undef HAVE_SYSCONF + +/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'. +*/ +/* #undef HAVE_SYS_DIR_H */ + +/* Define to 1 if you have the <sys/ioctl.h> header file. */ +/* #undef HAVE_SYS_IOCTL_H */ + +/* Define to 1 if you have the <sys/mman.h> header file. */ +/* #undef HAVE_SYS_MMAN_H */ + +/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'. +*/ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define to 1 if you have the <sys/param.h> header file. */ +/* #undef HAVE_SYS_PARAM_H */ + +/* Define to 1 if you have the <sys/resource.h> header file. */ +/* #undef HAVE_SYS_RESOURCE_H */ + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/time.h> header file. */ +/* #undef HAVE_SYS_TIME_H */ + +/* Define to 1 if you have the <sys/types.h> header file. */ +/* #undef HAVE_SYS_TYPES_H */ + +/* Define to 1 if you have the <sys/uio.h> header file. */ +/* #undef HAVE_SYS_UIO_H */ + +/* Define if the setupterm() function is supported this platform. */ +/* #undef HAVE_TERMINFO */ + +/* Define to 1 if you have the <termios.h> header file. */ +/* #undef HAVE_TERMIOS_H */ + +/* Define to 1 if the system has the type `uint64_t'. */ +#define HAVE_UINT64_T 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +/* #undef HAVE_UNISTD_H */ + +/* Define to 1 if you have the <utime.h> header file. */ +/* #undef HAVE_UTIME_H */ + +/* Define to 1 if the system has the type `u_int64_t'. */ +/* #undef HAVE_U_INT64_T */ + +/* Define to 1 if you have the <valgrind/valgrind.h> header file. */ +/* #undef HAVE_VALGRIND_VALGRIND_H */ + +/* Define to 1 if you have the `writev' function. */ +/* #undef HAVE_WRITEV */ + +/* Define to 1 if you have the <zlib.h> header file. */ +/* #undef HAVE_ZLIB_H */ + +/* Have host's _alloca */ +/* #undef HAVE__ALLOCA */ + +/* Have host's __alloca */ +/* #undef HAVE___ALLOCA */ + +/* Have host's __ashldi3 */ +/* #undef HAVE___ASHLDI3 */ + +/* Have host's __ashrdi3 */ +/* #undef HAVE___ASHRDI3 */ + +/* Have host's __chkstk */ +/* #undef HAVE___CHKSTK */ + +/* Have host's __chkstk_ms */ +/* #undef HAVE___CHKSTK_MS */ + +/* Have host's __cmpdi2 */ +/* #undef HAVE___CMPDI2 */ + +/* Have host's __divdi3 */ +/* #undef HAVE___DIVDI3 */ + +/* Define to 1 if you have the `__dso_handle' function. */ +#undef HAVE___DSO_HANDLE + +/* Have host's __fixdfdi */ +/* #undef HAVE___FIXDFDI */ + +/* Have host's __fixsfdi */ +/* #undef HAVE___FIXSFDI */ + +/* Have host's __floatdidf */ +/* #undef HAVE___FLOATDIDF */ + +/* Have host's __lshrdi3 */ +/* #undef HAVE___LSHRDI3 */ + +/* Have host's __main */ +/* #undef HAVE___MAIN */ + +/* Have host's __moddi3 */ +/* #undef HAVE___MODDI3 */ + +/* Have host's __udivdi3 */ +/* #undef HAVE___UDIVDI3 */ + +/* Have host's __umoddi3 */ +/* #undef HAVE___UMODDI3 */ + +/* Have host's ___chkstk */ +/* #undef HAVE____CHKSTK */ + +/* Have host's ___chkstk_ms */ +/* #undef HAVE____CHKSTK_MS */ + +/* Linker version detected at compile time. */ +#undef HOST_LINK_VERSION + +/* Installation directory for binary executables */ +/* #undef LLVM_BINDIR */ + +/* Time at which LLVM was configured */ +/* #undef LLVM_CONFIGTIME */ + +/* Installation directory for data files */ +/* #undef LLVM_DATADIR */ + +/* Target triple LLVM will generate code for by default +* Doesn't use `cmakedefine` because it is allowed to be empty. +*/ +#define LLVM_DEFAULT_TARGET_TRIPLE "i686-pc-win32" + +/* Installation directory for documentation */ +/* #undef LLVM_DOCSDIR */ + +/* Define if LLVM is built with asserts and checks that change the layout of +client-visible data structures. */ +#define LLVM_ENABLE_ABI_BREAKING_CHECKS + +/* Define if threads enabled */ +#define LLVM_ENABLE_THREADS 1 + +/* Define if zlib compression is available */ +#define LLVM_ENABLE_ZLIB 0 + +/* Installation directory for config files */ +/* #undef LLVM_ETCDIR */ + +/* Has gcc/MSVC atomic intrinsics */ +#define LLVM_HAS_ATOMICS 1 + +/* Host triple LLVM will be executed on */ +#define LLVM_HOST_TRIPLE "i686-pc-win32" + +/* Installation directory for include files */ +/* #undef LLVM_INCLUDEDIR */ + +/* Installation directory for .info files */ +/* #undef LLVM_INFODIR */ + +/* Installation directory for man pages */ +/* #undef LLVM_MANDIR */ + +/* LLVM architecture name for the native architecture, if available */ +#define LLVM_NATIVE_ARCH X86 + +/* LLVM name for the native AsmParser init function, if available */ +#define LLVM_NATIVE_ASMPARSER LLVMInitializeX86AsmParser + +/* LLVM name for the native AsmPrinter init function, if available */ +#define LLVM_NATIVE_ASMPRINTER LLVMInitializeX86AsmPrinter + +/* LLVM name for the native Disassembler init function, if available */ +#define LLVM_NATIVE_DISASSEMBLER LLVMInitializeX86Disassembler + +/* LLVM name for the native Target init function, if available */ +#define LLVM_NATIVE_TARGET LLVMInitializeX86Target + +/* LLVM name for the native TargetInfo init function, if available */ +#define LLVM_NATIVE_TARGETINFO LLVMInitializeX86TargetInfo + +/* LLVM name for the native target MC init function, if available */ +#define LLVM_NATIVE_TARGETMC LLVMInitializeX86TargetMC + +/* Define if this is Unixish platform */ +/* #undef LLVM_ON_UNIX */ + +/* Define if this is Win32ish platform */ +#define LLVM_ON_WIN32 1 + +/* Installation prefix directory */ +#define LLVM_PREFIX "C:/Program Files (x86)/LLVM" + +/* Define if we have the Intel JIT API runtime support library */ +/* #undef LLVM_USE_INTEL_JITEVENTS */ + +/* Define if we have the oprofile JIT-support library */ +/* #undef LLVM_USE_OPROFILE */ + +/* Major version of the LLVM API */ +#define LLVM_VERSION_MAJOR 3 + +/* Minor version of the LLVM API */ +#define LLVM_VERSION_MINOR 8 + +/* Patch version of the LLVM API */ +#define LLVM_VERSION_PATCH 1 + +/* LLVM version string */ +#define LLVM_VERSION_STRING "3.8.1" + +/* Define if we link Polly to the tools */ +/* #undef LINK_POLLY_INTO_TOOLS */ + +/* Define if the OS needs help to load dependent libraries for dlopen(). */ +/* #undef LTDL_DLOPEN_DEPLIBS */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. +*/ +#undef LTDL_OBJDIR + +/* Define to the extension used for shared libraries, say, ".so". */ +#define LTDL_SHLIB_EXT ".dll" + +/* Define to the system default library search path. */ +/* #undef LTDL_SYSSEARCHPATH */ + +/* Define if /dev/zero should be used when mapping RWX memory, or undefine if +its not necessary */ +#undef NEED_DEV_ZERO_FOR_MMAP + +/* Define if dlsym() requires a leading underscore in symbol names. */ +#undef NEED_USCORE + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "http://llvm.org/bugs/" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "LLVM" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "LLVM 3.8.1" + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "3.8.1" + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */ +#undef STAT_MACROS_BROKEN + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ +#undef TIME_WITH_SYS_TIME + +/* Define to 1 if your <sys/time.h> declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Type of 1st arg on ELM Callback */ +#define WIN32_ELMCB_PCSTR PCSTR + +/* Define to `int' if <sys/types.h> does not define. */ +#undef pid_t + +/* Define to `unsigned int' if <sys/types.h> does not define. */ +#undef size_t + +/* Define to a function replacing strtoll */ +/* #undef strtoll */ + +/* Define to a function implementing strtoull */ +/* #undef strtoull */ + +/* Define to a function implementing stricmp */ +#define stricmp _stricmp + +/* Define to a function implementing strdup */ +#define strdup _strdup + +/* Define to 1 if you have the `_chsize_s' function. */ +#define HAVE__CHSIZE_S 1 + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Config/llvm-config.h b/third_party/llvm-subzero/include/llvm/Config/llvm-config.h new file mode 100644 index 0000000..9a2ee7c --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Config/llvm-config.h
@@ -0,0 +1,106 @@ +/*===-- llvm/config/llvm-config.h - llvm configure variable -------*- C -*-===*/ +/* */ +/* The LLVM Compiler Infrastructure */ +/* */ +/* This file is distributed under the University of Illinois Open Source */ +/* License. See LICENSE.TXT for details. */ +/* */ +/*===----------------------------------------------------------------------===*/ + +/* This file enumerates all of the llvm variables from configure so that + they can be in exported headers and won't override package specific + directives. This is a C file so we can include it in the llvm-c headers. */ + +/* To avoid multiple inclusions of these variables when we include the exported + headers and config.h, conditionally include these. */ +/* TODO: This is a bit of a hack. */ +#ifndef CONFIG_H + +/* Installation directory for binary executables */ +/* #undef LLVM_BINDIR */ + +/* Time at which LLVM was configured */ +/* #undef LLVM_CONFIGTIME */ + +/* Installation directory for data files */ +/* #undef LLVM_DATADIR */ + +/* Installation directory for documentation */ +/* #undef LLVM_DOCSDIR */ + +/* Installation directory for config files */ +/* #undef LLVM_ETCDIR */ + +/* Has gcc/MSVC atomic intrinsics */ +#define LLVM_HAS_ATOMICS 1 + +/* Host triple we were built on */ +#define LLVM_HOSTTRIPLE "i686-pc-win32" + +/* Installation directory for include files */ +/* #undef LLVM_INCLUDEDIR */ + +/* Installation directory for .info files */ +/* #undef LLVM_INFODIR */ + +/* Installation directory for libraries */ +/* #undef LLVM_LIBDIR */ + +/* Installation directory for man pages */ +/* #undef LLVM_MANDIR */ + +/* LLVM architecture name for the native architecture, if available */ +#define LLVM_NATIVE_ARCH X86 + +/* LLVM name for the native AsmParser init function, if available */ +/* #undef LLVM_NATIVE_ASMPARSER */ + +/* LLVM name for the native AsmPrinter init function, if available */ +#define LLVM_NATIVE_ASMPRINTER LLVMInitializeX86AsmPrinter + +/* LLVM name for the native Target init function, if available */ +#define LLVM_NATIVE_TARGET LLVMInitializeX86Target + +/* LLVM name for the native TargetInfo init function, if available */ +#define LLVM_NATIVE_TARGETINFO LLVMInitializeX86TargetInfo + +/* LLVM name for the native target MC init function, if available */ +#define LLVM_NATIVE_TARGETMC LLVMInitializeX86TargetMC + +/* Define if this is Unixish platform */ +/* #undef LLVM_ON_UNIX */ + +/* Define if this is Win32ish platform */ +#define LLVM_ON_WIN32 1 + +/* Define to path to circo program if found or 'echo circo' otherwise */ +/* #undef LLVM_PATH_CIRCO */ + +/* Define to path to dot program if found or 'echo dot' otherwise */ +/* #undef LLVM_PATH_DOT */ + +/* Define to path to dotty program if found or 'echo dotty' otherwise */ +/* #undef LLVM_PATH_DOTTY */ + +/* Define to path to fdp program if found or 'echo fdp' otherwise */ +/* #undef LLVM_PATH_FDP */ + +/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ +/* #undef LLVM_PATH_GRAPHVIZ */ + +/* Define to path to gv program if found or 'echo gv' otherwise */ +/* #undef LLVM_PATH_GV */ + +/* Define to path to neato program if found or 'echo neato' otherwise */ +/* #undef LLVM_PATH_NEATO */ + +/* Define to path to twopi program if found or 'echo twopi' otherwise */ +/* #undef LLVM_PATH_TWOPI */ + +/* Define to path to xdot.py program if found or 'echo xdot.py' otherwise */ +/* #undef LLVM_PATH_XDOT_PY */ + +/* Installation prefix directory */ +#define LLVM_PREFIX "C:/Program Files (x86)/LLVM" + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Argument.h b/third_party/llvm-subzero/include/llvm/IR/Argument.h new file mode 100644 index 0000000..d8b280a --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/Argument.h
@@ -0,0 +1,152 @@ +//===-- llvm/Argument.h - Definition of the Argument class ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Argument class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_ARGUMENT_H +#define LLVM_IR_ARGUMENT_H + +#include "llvm/ADT/Twine.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/Value.h" + +namespace llvm { + +template <typename NodeTy> class SymbolTableListTraits; + +/// \brief LLVM Argument representation +/// +/// This class represents an incoming formal argument to a Function. A formal +/// argument, since it is ``formal'', does not contain an actual value but +/// instead represents the type, argument number, and attributes of an argument +/// for a specific function. When used in the body of said function, the +/// argument of course represents the value of the actual argument that the +/// function was called with. +class Argument : public Value, public ilist_node<Argument> { + virtual void anchor(); + Function *Parent; + + friend class SymbolTableListTraits<Argument>; + void setParent(Function *parent); + +public: + /// \brief Constructor. + /// + /// If \p F is specified, the argument is inserted at the end of the argument + /// list for \p F. + explicit Argument(Type *Ty, const Twine &Name = "", Function *F = nullptr); + + inline const Function *getParent() const { return Parent; } + inline Function *getParent() { return Parent; } + + /// \brief Return the index of this formal argument in its containing + /// function. + /// + /// For example in "void foo(int a, float b)" a is 0 and b is 1. + unsigned getArgNo() const; + + /// \brief Return true if this argument has the nonnull attribute on it in + /// its containing function. Also returns true if at least one byte is known + /// to be dereferenceable and the pointer is in addrspace(0). + bool hasNonNullAttr() const; + + /// \brief If this argument has the dereferenceable attribute on it in its + /// containing function, return the number of bytes known to be + /// dereferenceable. Otherwise, zero is returned. + uint64_t getDereferenceableBytes() const; + + /// \brief If this argument has the dereferenceable_or_null attribute on + /// it in its containing function, return the number of bytes known to be + /// dereferenceable. Otherwise, zero is returned. + uint64_t getDereferenceableOrNullBytes() const; + + /// \brief Return true if this argument has the byval attribute on it in its + /// containing function. + bool hasByValAttr() const; + + /// \brief Return true if this argument has the swiftself attribute. + bool hasSwiftSelfAttr() const; + + /// \brief Return true if this argument has the swifterror attribute. + bool hasSwiftErrorAttr() const; + + /// \brief Return true if this argument has the byval attribute or inalloca + /// attribute on it in its containing function. These attributes both + /// represent arguments being passed by value. + bool hasByValOrInAllocaAttr() const; + + /// \brief If this is a byval or inalloca argument, return its alignment. + unsigned getParamAlignment() const; + + /// \brief Return true if this argument has the nest attribute on it in its + /// containing function. + bool hasNestAttr() const; + + /// \brief Return true if this argument has the noalias attribute on it in its + /// containing function. + bool hasNoAliasAttr() const; + + /// \brief Return true if this argument has the nocapture attribute on it in + /// its containing function. + bool hasNoCaptureAttr() const; + + /// \brief Return true if this argument has the sret attribute on it in its + /// containing function. + bool hasStructRetAttr() const; + + /// \brief Return true if this argument has the returned attribute on it in + /// its containing function. + bool hasReturnedAttr() const; + + /// \brief Return true if this argument has the readonly or readnone attribute + /// on it in its containing function. + bool onlyReadsMemory() const; + + /// \brief Return true if this argument has the inalloca attribute on it in + /// its containing function. + bool hasInAllocaAttr() const; + + /// \brief Return true if this argument has the zext attribute on it in its + /// containing function. + bool hasZExtAttr() const; + + /// \brief Return true if this argument has the sext attribute on it in its + /// containing function. + bool hasSExtAttr() const; + + /// \brief Add a Attribute to an argument. + void addAttr(AttributeSet AS); + + void addAttr(Attribute::AttrKind Kind) { + addAttr(AttributeSet::get(getContext(), getArgNo() + 1, Kind)); + } + + /// \brief Remove a Attribute from an argument. + void removeAttr(AttributeSet AS); + + void removeAttr(Attribute::AttrKind Kind) { + removeAttr(AttributeSet::get(getContext(), getArgNo() + 1, Kind)); + } + + /// \brief Checks if an argument has a given attribute. + bool hasAttribute(Attribute::AttrKind Kind) const; + + /// \brief Method for support type inquiry through isa, cast, and + /// dyn_cast. + static inline bool classof(const Value *V) { + return V->getValueID() == ArgumentVal; + } +}; + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Attributes.h b/third_party/llvm-subzero/include/llvm/IR/Attributes.h new file mode 100644 index 0000000..5ef0371 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/Attributes.h
@@ -0,0 +1,612 @@ +//===-- llvm/Attributes.h - Container for Attributes ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file contains the simple types necessary to represent the +/// attributes associated with functions and their calls. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_ATTRIBUTES_H +#define LLVM_IR_ATTRIBUTES_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/Optional.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm-c/Types.h" +#include <bitset> +#include <cassert> +#include <map> +#include <string> + +namespace llvm { + +class AttrBuilder; +class AttributeImpl; +class AttributeSetImpl; +class AttributeSetNode; +class Constant; +template<typename T> struct DenseMapInfo; +class Function; +class LLVMContext; +class Type; + +//===----------------------------------------------------------------------===// +/// \class +/// \brief Functions, function parameters, and return types can have attributes +/// to indicate how they should be treated by optimizations and code +/// generation. This class represents one of those attributes. It's light-weight +/// and should be passed around by-value. +class Attribute { +public: + /// This enumeration lists the attributes that can be associated with + /// parameters, function results, or the function itself. + /// + /// Note: The `uwtable' attribute is about the ABI or the user mandating an + /// entry in the unwind table. The `nounwind' attribute is about an exception + /// passing by the function. + /// + /// In a theoretical system that uses tables for profiling and SjLj for + /// exceptions, they would be fully independent. In a normal system that uses + /// tables for both, the semantics are: + /// + /// nil = Needs an entry because an exception might pass by. + /// nounwind = No need for an entry + /// uwtable = Needs an entry because the ABI says so and because + /// an exception might pass by. + /// uwtable + nounwind = Needs an entry because the ABI says so. + + enum AttrKind { + // IR-Level Attributes + None, ///< No attributes have been set + #define GET_ATTR_ENUM + #include "llvm/IR/Attributes.inc" + EndAttrKinds ///< Sentinal value useful for loops + }; + +private: + AttributeImpl *pImpl; + Attribute(AttributeImpl *A) : pImpl(A) {} + +public: + Attribute() : pImpl(nullptr) {} + + //===--------------------------------------------------------------------===// + // Attribute Construction + //===--------------------------------------------------------------------===// + + /// \brief Return a uniquified Attribute object. + static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val = 0); + static Attribute get(LLVMContext &Context, StringRef Kind, + StringRef Val = StringRef()); + + /// \brief Return a uniquified Attribute object that has the specific + /// alignment set. + static Attribute getWithAlignment(LLVMContext &Context, uint64_t Align); + static Attribute getWithStackAlignment(LLVMContext &Context, uint64_t Align); + static Attribute getWithDereferenceableBytes(LLVMContext &Context, + uint64_t Bytes); + static Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context, + uint64_t Bytes); + static Attribute getWithAllocSizeArgs(LLVMContext &Context, + unsigned ElemSizeArg, + const Optional<unsigned> &NumElemsArg); + + //===--------------------------------------------------------------------===// + // Attribute Accessors + //===--------------------------------------------------------------------===// + + /// \brief Return true if the attribute is an Attribute::AttrKind type. + bool isEnumAttribute() const; + + /// \brief Return true if the attribute is an integer attribute. + bool isIntAttribute() const; + + /// \brief Return true if the attribute is a string (target-dependent) + /// attribute. + bool isStringAttribute() const; + + /// \brief Return true if the attribute is present. + bool hasAttribute(AttrKind Val) const; + + /// \brief Return true if the target-dependent attribute is present. + bool hasAttribute(StringRef Val) const; + + /// \brief Return the attribute's kind as an enum (Attribute::AttrKind). This + /// requires the attribute to be an enum or integer attribute. + Attribute::AttrKind getKindAsEnum() const; + + /// \brief Return the attribute's value as an integer. This requires that the + /// attribute be an integer attribute. + uint64_t getValueAsInt() const; + + /// \brief Return the attribute's kind as a string. This requires the + /// attribute to be a string attribute. + StringRef getKindAsString() const; + + /// \brief Return the attribute's value as a string. This requires the + /// attribute to be a string attribute. + StringRef getValueAsString() const; + + /// \brief Returns the alignment field of an attribute as a byte alignment + /// value. + unsigned getAlignment() const; + + /// \brief Returns the stack alignment field of an attribute as a byte + /// alignment value. + unsigned getStackAlignment() const; + + /// \brief Returns the number of dereferenceable bytes from the + /// dereferenceable attribute. + uint64_t getDereferenceableBytes() const; + + /// \brief Returns the number of dereferenceable_or_null bytes from the + /// dereferenceable_or_null attribute. + uint64_t getDereferenceableOrNullBytes() const; + + /// Returns the argument numbers for the allocsize attribute (or pair(0, 0) + /// if not known). + std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const; + + /// \brief The Attribute is converted to a string of equivalent mnemonic. This + /// is, presumably, for writing out the mnemonics for the assembly writer. + std::string getAsString(bool InAttrGrp = false) const; + + /// \brief Equality and non-equality operators. + bool operator==(Attribute A) const { return pImpl == A.pImpl; } + bool operator!=(Attribute A) const { return pImpl != A.pImpl; } + + /// \brief Less-than operator. Useful for sorting the attributes list. + bool operator<(Attribute A) const; + + void Profile(FoldingSetNodeID &ID) const { + ID.AddPointer(pImpl); + } + + /// \brief Return a raw pointer that uniquely identifies this attribute. + void *getRawPointer() const { + return pImpl; + } + + /// \brief Get an attribute from a raw pointer created by getRawPointer. + static Attribute fromRawPointer(void *RawPtr) { + return Attribute(reinterpret_cast<AttributeImpl*>(RawPtr)); + } +}; + +// Specialized opaque value conversions. +inline LLVMAttributeRef wrap(Attribute Attr) { + return reinterpret_cast<LLVMAttributeRef>(Attr.getRawPointer()); +} + +// Specialized opaque value conversions. +inline Attribute unwrap(LLVMAttributeRef Attr) { + return Attribute::fromRawPointer(Attr); +} + +//===----------------------------------------------------------------------===// +/// \class +/// \brief This class holds the attributes for a function, its return value, and +/// its parameters. You access the attributes for each of them via an index into +/// the AttributeSet object. The function attributes are at index +/// `AttributeSet::FunctionIndex', the return value is at index +/// `AttributeSet::ReturnIndex', and the attributes for the parameters start at +/// index `1'. +class AttributeSet { +public: + enum AttrIndex : unsigned { + ReturnIndex = 0U, + FunctionIndex = ~0U + }; + +private: + friend class AttrBuilder; + friend class AttributeSetImpl; + friend class AttributeSetNode; + template <typename Ty> friend struct DenseMapInfo; + + /// \brief The attributes that we are managing. This can be null to represent + /// the empty attributes list. + AttributeSetImpl *pImpl; + + /// \brief The attributes for the specified index are returned. + AttributeSetNode *getAttributes(unsigned Index) const; + + /// \brief Create an AttributeSet with the specified parameters in it. + static AttributeSet get(LLVMContext &C, + ArrayRef<std::pair<unsigned, Attribute> > Attrs); + static AttributeSet get(LLVMContext &C, + ArrayRef<std::pair<unsigned, + AttributeSetNode*> > Attrs); + + static AttributeSet getImpl(LLVMContext &C, + ArrayRef<std::pair<unsigned, + AttributeSetNode*> > Attrs); + + explicit AttributeSet(AttributeSetImpl *LI) : pImpl(LI) {} + +public: + AttributeSet() : pImpl(nullptr) {} + + //===--------------------------------------------------------------------===// + // AttributeSet Construction and Mutation + //===--------------------------------------------------------------------===// + + /// \brief Return an AttributeSet with the specified parameters in it. + static AttributeSet get(LLVMContext &C, ArrayRef<AttributeSet> Attrs); + static AttributeSet get(LLVMContext &C, unsigned Index, + ArrayRef<Attribute::AttrKind> Kinds); + static AttributeSet get(LLVMContext &C, unsigned Index, + ArrayRef<StringRef> Kind); + static AttributeSet get(LLVMContext &C, unsigned Index, const AttrBuilder &B); + + /// \brief Add an attribute to the attribute set at the given index. Because + /// attribute sets are immutable, this returns a new set. + AttributeSet addAttribute(LLVMContext &C, unsigned Index, + Attribute::AttrKind Kind) const; + + /// \brief Add an attribute to the attribute set at the given index. Because + /// attribute sets are immutable, this returns a new set. + AttributeSet addAttribute(LLVMContext &C, unsigned Index, StringRef Kind, + StringRef Value = StringRef()) const; + + /// Add an attribute to the attribute set at the given indices. Because + /// attribute sets are immutable, this returns a new set. + AttributeSet addAttribute(LLVMContext &C, ArrayRef<unsigned> Indices, + Attribute A) const; + + /// \brief Add attributes to the attribute set at the given index. Because + /// attribute sets are immutable, this returns a new set. + AttributeSet addAttributes(LLVMContext &C, unsigned Index, + AttributeSet Attrs) const; + + /// \brief Remove the specified attribute at the specified index from this + /// attribute list. Because attribute lists are immutable, this returns the + /// new list. + AttributeSet removeAttribute(LLVMContext &C, unsigned Index, + Attribute::AttrKind Kind) const; + + /// \brief Remove the specified attribute at the specified index from this + /// attribute list. Because attribute lists are immutable, this returns the + /// new list. + AttributeSet removeAttribute(LLVMContext &C, unsigned Index, + StringRef Kind) const; + + /// \brief Remove the specified attributes at the specified index from this + /// attribute list. Because attribute lists are immutable, this returns the + /// new list. + AttributeSet removeAttributes(LLVMContext &C, unsigned Index, + AttributeSet Attrs) const; + + /// \brief Remove the specified attributes at the specified index from this + /// attribute list. Because attribute lists are immutable, this returns the + /// new list. + AttributeSet removeAttributes(LLVMContext &C, unsigned Index, + const AttrBuilder &Attrs) const; + + /// \brief Add the dereferenceable attribute to the attribute set at the given + /// index. Because attribute sets are immutable, this returns a new set. + AttributeSet addDereferenceableAttr(LLVMContext &C, unsigned Index, + uint64_t Bytes) const; + + /// \brief Add the dereferenceable_or_null attribute to the attribute set at + /// the given index. Because attribute sets are immutable, this returns a new + /// set. + AttributeSet addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index, + uint64_t Bytes) const; + + /// Add the allocsize attribute to the attribute set at the given index. + /// Because attribute sets are immutable, this returns a new set. + AttributeSet addAllocSizeAttr(LLVMContext &C, unsigned Index, + unsigned ElemSizeArg, + const Optional<unsigned> &NumElemsArg); + + //===--------------------------------------------------------------------===// + // AttributeSet Accessors + //===--------------------------------------------------------------------===// + + /// \brief Retrieve the LLVM context. + LLVMContext &getContext() const; + + /// \brief The attributes for the specified index are returned. + AttributeSet getParamAttributes(unsigned Index) const; + + /// \brief The attributes for the ret value are returned. + AttributeSet getRetAttributes() const; + + /// \brief The function attributes are returned. + AttributeSet getFnAttributes() const; + + /// \brief Return true if the attribute exists at the given index. + bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const; + + /// \brief Return true if the attribute exists at the given index. + bool hasAttribute(unsigned Index, StringRef Kind) const; + + /// \brief Return true if attribute exists at the given index. + bool hasAttributes(unsigned Index) const; + + /// \brief Equivalent to hasAttribute(AttributeSet::FunctionIndex, Kind) but + /// may be faster. + bool hasFnAttribute(Attribute::AttrKind Kind) const; + + /// \brief Return true if the specified attribute is set for at least one + /// parameter or for the return value. If Index is not nullptr, the index + /// of a parameter with the specified attribute is provided. + bool hasAttrSomewhere(Attribute::AttrKind Kind, + unsigned *Index = nullptr) const; + + /// \brief Return the attribute object that exists at the given index. + Attribute getAttribute(unsigned Index, Attribute::AttrKind Kind) const; + + /// \brief Return the attribute object that exists at the given index. + Attribute getAttribute(unsigned Index, StringRef Kind) const; + + /// \brief Return the alignment for the specified function parameter. + unsigned getParamAlignment(unsigned Index) const; + + /// \brief Get the stack alignment. + unsigned getStackAlignment(unsigned Index) const; + + /// \brief Get the number of dereferenceable bytes (or zero if unknown). + uint64_t getDereferenceableBytes(unsigned Index) const; + + /// \brief Get the number of dereferenceable_or_null bytes (or zero if + /// unknown). + uint64_t getDereferenceableOrNullBytes(unsigned Index) const; + + /// Get the allocsize argument numbers (or pair(0, 0) if unknown). + std::pair<unsigned, Optional<unsigned>> + getAllocSizeArgs(unsigned Index) const; + + /// \brief Return the attributes at the index as a string. + std::string getAsString(unsigned Index, bool InAttrGrp = false) const; + + typedef ArrayRef<Attribute>::iterator iterator; + + iterator begin(unsigned Slot) const; + iterator end(unsigned Slot) const; + + /// operator==/!= - Provide equality predicates. + bool operator==(const AttributeSet &RHS) const { + return pImpl == RHS.pImpl; + } + bool operator!=(const AttributeSet &RHS) const { + return pImpl != RHS.pImpl; + } + + //===--------------------------------------------------------------------===// + // AttributeSet Introspection + //===--------------------------------------------------------------------===// + + // FIXME: Remove this. + uint64_t Raw(unsigned Index) const; + + /// \brief Return a raw pointer that uniquely identifies this attribute list. + void *getRawPointer() const { + return pImpl; + } + + /// \brief Return true if there are no attributes. + bool isEmpty() const { + return getNumSlots() == 0; + } + + /// \brief Return the number of slots used in this attribute list. This is + /// the number of arguments that have an attribute set on them (including the + /// function itself). + unsigned getNumSlots() const; + + /// \brief Return the index for the given slot. + unsigned getSlotIndex(unsigned Slot) const; + + /// \brief Return the attributes at the given slot. + AttributeSet getSlotAttributes(unsigned Slot) const; + + void dump() const; +}; + +//===----------------------------------------------------------------------===// +/// \class +/// \brief Provide DenseMapInfo for AttributeSet. +template<> struct DenseMapInfo<AttributeSet> { + static inline AttributeSet getEmptyKey() { + uintptr_t Val = static_cast<uintptr_t>(-1); + Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable; + return AttributeSet(reinterpret_cast<AttributeSetImpl*>(Val)); + } + static inline AttributeSet getTombstoneKey() { + uintptr_t Val = static_cast<uintptr_t>(-2); + Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable; + return AttributeSet(reinterpret_cast<AttributeSetImpl*>(Val)); + } + static unsigned getHashValue(AttributeSet AS) { + return (unsigned((uintptr_t)AS.pImpl) >> 4) ^ + (unsigned((uintptr_t)AS.pImpl) >> 9); + } + static bool isEqual(AttributeSet LHS, AttributeSet RHS) { return LHS == RHS; } +}; + +//===----------------------------------------------------------------------===// +/// \class +/// \brief This class is used in conjunction with the Attribute::get method to +/// create an Attribute object. The object itself is uniquified. The Builder's +/// value, however, is not. So this can be used as a quick way to test for +/// equality, presence of attributes, etc. +class AttrBuilder { + std::bitset<Attribute::EndAttrKinds> Attrs; + std::map<std::string, std::string> TargetDepAttrs; + uint64_t Alignment; + uint64_t StackAlignment; + uint64_t DerefBytes; + uint64_t DerefOrNullBytes; + uint64_t AllocSizeArgs; + +public: + AttrBuilder() + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0), + DerefOrNullBytes(0), AllocSizeArgs(0) {} + explicit AttrBuilder(uint64_t Val) + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0), + DerefOrNullBytes(0), AllocSizeArgs(0) { + addRawValue(Val); + } + AttrBuilder(const Attribute &A) + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0), + DerefOrNullBytes(0), AllocSizeArgs(0) { + addAttribute(A); + } + AttrBuilder(AttributeSet AS, unsigned Idx); + + void clear(); + + /// \brief Add an attribute to the builder. + AttrBuilder &addAttribute(Attribute::AttrKind Val); + + /// \brief Add the Attribute object to the builder. + AttrBuilder &addAttribute(Attribute A); + + /// \brief Add the target-dependent attribute to the builder. + AttrBuilder &addAttribute(StringRef A, StringRef V = StringRef()); + + /// \brief Remove an attribute from the builder. + AttrBuilder &removeAttribute(Attribute::AttrKind Val); + + /// \brief Remove the attributes from the builder. + AttrBuilder &removeAttributes(AttributeSet A, uint64_t Index); + + /// \brief Remove the target-dependent attribute to the builder. + AttrBuilder &removeAttribute(StringRef A); + + /// \brief Add the attributes from the builder. + AttrBuilder &merge(const AttrBuilder &B); + + /// \brief Remove the attributes from the builder. + AttrBuilder &remove(const AttrBuilder &B); + + /// \brief Return true if the builder has any attribute that's in the + /// specified builder. + bool overlaps(const AttrBuilder &B) const; + + /// \brief Return true if the builder has the specified attribute. + bool contains(Attribute::AttrKind A) const { + assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!"); + return Attrs[A]; + } + + /// \brief Return true if the builder has the specified target-dependent + /// attribute. + bool contains(StringRef A) const; + + /// \brief Return true if the builder has IR-level attributes. + bool hasAttributes() const; + + /// \brief Return true if the builder has any attribute that's in the + /// specified attribute. + bool hasAttributes(AttributeSet A, uint64_t Index) const; + + /// \brief Return true if the builder has an alignment attribute. + bool hasAlignmentAttr() const; + + /// \brief Retrieve the alignment attribute, if it exists. + uint64_t getAlignment() const { return Alignment; } + + /// \brief Retrieve the stack alignment attribute, if it exists. + uint64_t getStackAlignment() const { return StackAlignment; } + + /// \brief Retrieve the number of dereferenceable bytes, if the + /// dereferenceable attribute exists (zero is returned otherwise). + uint64_t getDereferenceableBytes() const { return DerefBytes; } + + /// \brief Retrieve the number of dereferenceable_or_null bytes, if the + /// dereferenceable_or_null attribute exists (zero is returned otherwise). + uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; } + + /// Retrieve the allocsize args, if the allocsize attribute exists. If it + /// doesn't exist, pair(0, 0) is returned. + std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const; + + /// \brief This turns an int alignment (which must be a power of 2) into the + /// form used internally in Attribute. + AttrBuilder &addAlignmentAttr(unsigned Align); + + /// \brief This turns an int stack alignment (which must be a power of 2) into + /// the form used internally in Attribute. + AttrBuilder &addStackAlignmentAttr(unsigned Align); + + /// \brief This turns the number of dereferenceable bytes into the form used + /// internally in Attribute. + AttrBuilder &addDereferenceableAttr(uint64_t Bytes); + + /// \brief This turns the number of dereferenceable_or_null bytes into the + /// form used internally in Attribute. + AttrBuilder &addDereferenceableOrNullAttr(uint64_t Bytes); + + /// This turns one (or two) ints into the form used internally in Attribute. + AttrBuilder &addAllocSizeAttr(unsigned ElemSizeArg, + const Optional<unsigned> &NumElemsArg); + + /// Add an allocsize attribute, using the representation returned by + /// Attribute.getIntValue(). + AttrBuilder &addAllocSizeAttrFromRawRepr(uint64_t RawAllocSizeRepr); + + /// \brief Return true if the builder contains no target-independent + /// attributes. + bool empty() const { return Attrs.none(); } + + // Iterators for target-dependent attributes. + typedef std::pair<std::string, std::string> td_type; + typedef std::map<std::string, std::string>::iterator td_iterator; + typedef std::map<std::string, std::string>::const_iterator td_const_iterator; + typedef llvm::iterator_range<td_iterator> td_range; + typedef llvm::iterator_range<td_const_iterator> td_const_range; + + td_iterator td_begin() { return TargetDepAttrs.begin(); } + td_iterator td_end() { return TargetDepAttrs.end(); } + + td_const_iterator td_begin() const { return TargetDepAttrs.begin(); } + td_const_iterator td_end() const { return TargetDepAttrs.end(); } + + td_range td_attrs() { return td_range(td_begin(), td_end()); } + td_const_range td_attrs() const { + return td_const_range(td_begin(), td_end()); + } + + bool td_empty() const { return TargetDepAttrs.empty(); } + + bool operator==(const AttrBuilder &B); + bool operator!=(const AttrBuilder &B) { + return !(*this == B); + } + + // FIXME: Remove this in 4.0. + + /// \brief Add the raw value to the internal representation. + AttrBuilder &addRawValue(uint64_t Val); +}; + +namespace AttributeFuncs { + +/// \brief Which attributes cannot be applied to a type. +AttrBuilder typeIncompatible(Type *Ty); + +/// \returns Return true if the two functions have compatible target-independent +/// attributes for inlining purposes. +bool areInlineCompatible(const Function &Caller, const Function &Callee); + +/// \brief Merge caller's and callee's attributes. +void mergeAttributesForInlining(Function &Caller, const Function &Callee); + +} // end AttributeFuncs namespace + +} // end llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Attributes.inc b/third_party/llvm-subzero/include/llvm/IR/Attributes.inc new file mode 100644 index 0000000..57cc506 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/Attributes.inc
@@ -0,0 +1,458 @@ +#ifdef GET_ATTR_ENUM +#undef GET_ATTR_ENUM +Alignment, +AllocSize, +AlwaysInline, +ArgMemOnly, +Builtin, +ByVal, +Cold, +Convergent, +Dereferenceable, +DereferenceableOrNull, +InAlloca, +InReg, +InaccessibleMemOnly, +InaccessibleMemOrArgMemOnly, +InlineHint, +JumpTable, +MinSize, +Naked, +Nest, +NoAlias, +NoBuiltin, +NoCapture, +NoDuplicate, +NoImplicitFloat, +NoInline, +NoRecurse, +NoRedZone, +NoReturn, +NoUnwind, +NonLazyBind, +NonNull, +OptimizeForSize, +OptimizeNone, +ReadNone, +ReadOnly, +Returned, +ReturnsTwice, +SExt, +SafeStack, +SanitizeAddress, +SanitizeMemory, +SanitizeThread, +StackAlignment, +StackProtect, +StackProtectReq, +StackProtectStrong, +StructRet, +SwiftError, +SwiftSelf, +UWTable, +WriteOnly, +ZExt, +#endif +#ifdef GET_ATTR_KIND_FROM_NAME +#undef GET_ATTR_KIND_FROM_NAME +static Attribute::AttrKind getAttrKindFromName(StringRef AttrName) { + return StringSwitch<Attribute::AttrKind>(AttrName) + .Case("align", Attribute::Alignment) + .Case("allocsize", Attribute::AllocSize) + .Case("alwaysinline", Attribute::AlwaysInline) + .Case("argmemonly", Attribute::ArgMemOnly) + .Case("builtin", Attribute::Builtin) + .Case("byval", Attribute::ByVal) + .Case("cold", Attribute::Cold) + .Case("convergent", Attribute::Convergent) + .Case("dereferenceable", Attribute::Dereferenceable) + .Case("dereferenceable_or_null", Attribute::DereferenceableOrNull) + .Case("inalloca", Attribute::InAlloca) + .Case("inreg", Attribute::InReg) + .Case("inaccessiblememonly", Attribute::InaccessibleMemOnly) + .Case("inaccessiblemem_or_argmemonly", Attribute::InaccessibleMemOrArgMemOnly) + .Case("inlinehint", Attribute::InlineHint) + .Case("jumptable", Attribute::JumpTable) + .Case("minsize", Attribute::MinSize) + .Case("naked", Attribute::Naked) + .Case("nest", Attribute::Nest) + .Case("noalias", Attribute::NoAlias) + .Case("nobuiltin", Attribute::NoBuiltin) + .Case("nocapture", Attribute::NoCapture) + .Case("noduplicate", Attribute::NoDuplicate) + .Case("noimplicitfloat", Attribute::NoImplicitFloat) + .Case("noinline", Attribute::NoInline) + .Case("norecurse", Attribute::NoRecurse) + .Case("noredzone", Attribute::NoRedZone) + .Case("noreturn", Attribute::NoReturn) + .Case("nounwind", Attribute::NoUnwind) + .Case("nonlazybind", Attribute::NonLazyBind) + .Case("nonnull", Attribute::NonNull) + .Case("optsize", Attribute::OptimizeForSize) + .Case("optnone", Attribute::OptimizeNone) + .Case("readnone", Attribute::ReadNone) + .Case("readonly", Attribute::ReadOnly) + .Case("returned", Attribute::Returned) + .Case("returns_twice", Attribute::ReturnsTwice) + .Case("signext", Attribute::SExt) + .Case("safestack", Attribute::SafeStack) + .Case("sanitize_address", Attribute::SanitizeAddress) + .Case("sanitize_memory", Attribute::SanitizeMemory) + .Case("sanitize_thread", Attribute::SanitizeThread) + .Case("alignstack", Attribute::StackAlignment) + .Case("ssp", Attribute::StackProtect) + .Case("sspreq", Attribute::StackProtectReq) + .Case("sspstrong", Attribute::StackProtectStrong) + .Case("sret", Attribute::StructRet) + .Case("swifterror", Attribute::SwiftError) + .Case("swiftself", Attribute::SwiftSelf) + .Case("uwtable", Attribute::UWTable) + .Case("writeonly", Attribute::WriteOnly) + .Case("zeroext", Attribute::ZExt) + .Default(Attribute::None); +} + +#endif +#ifdef GET_ATTR_COMPAT_FUNC +#undef GET_ATTR_COMPAT_FUNC +struct EnumAttr { + static bool isSet(const Function &Fn, + Attribute::AttrKind Kind) { + return Fn.hasFnAttribute(Kind); + } + + static void set(Function &Fn, + Attribute::AttrKind Kind, bool Val) { + if (Val) + Fn.addFnAttr(Kind); + else + Fn.removeFnAttr(Kind); + } +}; + +struct StrBoolAttr { + static bool isSet(const Function &Fn, + StringRef Kind) { + auto A = Fn.getFnAttribute(Kind); + return A.getValueAsString().equals("true"); + } + + static void set(Function &Fn, + StringRef Kind, bool Val) { + Fn.addFnAttr(Kind, Val ? "true" : "false"); + } +}; + +// EnumAttr classes +struct AlignmentAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::Alignment; + } +}; +struct AllocSizeAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::AllocSize; + } +}; +struct AlwaysInlineAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::AlwaysInline; + } +}; +struct ArgMemOnlyAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::ArgMemOnly; + } +}; +struct BuiltinAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::Builtin; + } +}; +struct ByValAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::ByVal; + } +}; +struct ColdAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::Cold; + } +}; +struct ConvergentAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::Convergent; + } +}; +struct DereferenceableAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::Dereferenceable; + } +}; +struct DereferenceableOrNullAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::DereferenceableOrNull; + } +}; +struct InAllocaAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::InAlloca; + } +}; +struct InRegAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::InReg; + } +}; +struct InaccessibleMemOnlyAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::InaccessibleMemOnly; + } +}; +struct InaccessibleMemOrArgMemOnlyAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::InaccessibleMemOrArgMemOnly; + } +}; +struct InlineHintAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::InlineHint; + } +}; +struct JumpTableAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::JumpTable; + } +}; +struct MinSizeAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::MinSize; + } +}; +struct NakedAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::Naked; + } +}; +struct NestAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::Nest; + } +}; +struct NoAliasAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::NoAlias; + } +}; +struct NoBuiltinAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::NoBuiltin; + } +}; +struct NoCaptureAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::NoCapture; + } +}; +struct NoDuplicateAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::NoDuplicate; + } +}; +struct NoImplicitFloatAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::NoImplicitFloat; + } +}; +struct NoInlineAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::NoInline; + } +}; +struct NoRecurseAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::NoRecurse; + } +}; +struct NoRedZoneAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::NoRedZone; + } +}; +struct NoReturnAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::NoReturn; + } +}; +struct NoUnwindAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::NoUnwind; + } +}; +struct NonLazyBindAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::NonLazyBind; + } +}; +struct NonNullAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::NonNull; + } +}; +struct OptimizeForSizeAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::OptimizeForSize; + } +}; +struct OptimizeNoneAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::OptimizeNone; + } +}; +struct ReadNoneAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::ReadNone; + } +}; +struct ReadOnlyAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::ReadOnly; + } +}; +struct ReturnedAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::Returned; + } +}; +struct ReturnsTwiceAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::ReturnsTwice; + } +}; +struct SExtAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::SExt; + } +}; +struct SafeStackAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::SafeStack; + } +}; +struct SanitizeAddressAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::SanitizeAddress; + } +}; +struct SanitizeMemoryAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::SanitizeMemory; + } +}; +struct SanitizeThreadAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::SanitizeThread; + } +}; +struct StackAlignmentAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::StackAlignment; + } +}; +struct StackProtectAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::StackProtect; + } +}; +struct StackProtectReqAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::StackProtectReq; + } +}; +struct StackProtectStrongAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::StackProtectStrong; + } +}; +struct StructRetAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::StructRet; + } +}; +struct SwiftErrorAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::SwiftError; + } +}; +struct SwiftSelfAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::SwiftSelf; + } +}; +struct UWTableAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::UWTable; + } +}; +struct WriteOnlyAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::WriteOnly; + } +}; +struct ZExtAttr : EnumAttr { + static enum Attribute::AttrKind getKind() { + return llvm::Attribute::ZExt; + } +}; + +// StrBoolAttr classes +struct LessPreciseFPMADAttr : StrBoolAttr { + static const char *getKind() { + return "less-precise-fpmad"; + } +}; +struct NoInfsFPMathAttr : StrBoolAttr { + static const char *getKind() { + return "no-infs-fp-math"; + } +}; +struct NoJumpTablesAttr : StrBoolAttr { + static const char *getKind() { + return "no-jump-tables"; + } +}; +struct NoNansFPMathAttr : StrBoolAttr { + static const char *getKind() { + return "no-nans-fp-math"; + } +}; +struct UnsafeFPMathAttr : StrBoolAttr { + static const char *getKind() { + return "unsafe-fp-math"; + } +}; + +static inline bool hasCompatibleFnAttrs(const Function &Caller, + const Function &Callee) { + bool Ret = true; + + Ret &= isEqual<SanitizeAddressAttr>(Caller, Callee); + Ret &= isEqual<SanitizeThreadAttr>(Caller, Callee); + Ret &= isEqual<SanitizeMemoryAttr>(Caller, Callee); + Ret &= isEqual<SafeStackAttr>(Caller, Callee); + + return Ret; +} + +static inline void mergeFnAttrs(Function &Caller, + const Function &Callee) { + adjustCallerSSPLevel(Caller, Callee); + setAND<LessPreciseFPMADAttr>(Caller, Callee); + setAND<NoInfsFPMathAttr>(Caller, Callee); + setAND<NoNansFPMathAttr>(Caller, Callee); + setAND<UnsafeFPMathAttr>(Caller, Callee); + setOR<NoImplicitFloatAttr>(Caller, Callee); + setOR<NoJumpTablesAttr>(Caller, Callee); +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/BasicBlock.h b/third_party/llvm-subzero/include/llvm/IR/BasicBlock.h new file mode 100644 index 0000000..50eedec --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/BasicBlock.h
@@ -0,0 +1,345 @@ +//===-- llvm/BasicBlock.h - Represent a basic block in the VM ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the BasicBlock class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_BASICBLOCK_H +#define LLVM_IR_BASICBLOCK_H + +#include "llvm/ADT/Twine.h" +#include "llvm/ADT/ilist.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/SymbolTableListTraits.h" +#include "llvm/Support/CBindingWrapping.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class CallInst; +class LandingPadInst; +class TerminatorInst; +class LLVMContext; +class BlockAddress; +class Function; + +/// \brief LLVM Basic Block Representation +/// +/// This represents a single basic block in LLVM. A basic block is simply a +/// container of instructions that execute sequentially. Basic blocks are Values +/// because they are referenced by instructions such as branches and switch +/// tables. The type of a BasicBlock is "Type::LabelTy" because the basic block +/// represents a label to which a branch can jump. +/// +/// A well formed basic block is formed of a list of non-terminating +/// instructions followed by a single TerminatorInst instruction. +/// TerminatorInst's may not occur in the middle of basic blocks, and must +/// terminate the blocks. The BasicBlock class allows malformed basic blocks to +/// occur because it may be useful in the intermediate stage of constructing or +/// modifying a program. However, the verifier will ensure that basic blocks +/// are "well formed". +class BasicBlock : public Value, // Basic blocks are data objects also + public ilist_node_with_parent<BasicBlock, Function> { + friend class BlockAddress; +public: + typedef SymbolTableList<Instruction> InstListType; + +private: + InstListType InstList; + Function *Parent; + + void setParent(Function *parent); + friend class SymbolTableListTraits<BasicBlock>; + + BasicBlock(const BasicBlock &) = delete; + void operator=(const BasicBlock &) = delete; + + /// \brief Constructor. + /// + /// If the function parameter is specified, the basic block is automatically + /// inserted at either the end of the function (if InsertBefore is null), or + /// before the specified basic block. + explicit BasicBlock(LLVMContext &C, const Twine &Name = "", + Function *Parent = nullptr, + BasicBlock *InsertBefore = nullptr); +public: + /// \brief Get the context in which this basic block lives. + LLVMContext &getContext() const; + + /// Instruction iterators... + typedef InstListType::iterator iterator; + typedef InstListType::const_iterator const_iterator; + typedef InstListType::reverse_iterator reverse_iterator; + typedef InstListType::const_reverse_iterator const_reverse_iterator; + + /// \brief Creates a new BasicBlock. + /// + /// If the Parent parameter is specified, the basic block is automatically + /// inserted at either the end of the function (if InsertBefore is 0), or + /// before the specified basic block. + static BasicBlock *Create(LLVMContext &Context, const Twine &Name = "", + Function *Parent = nullptr, + BasicBlock *InsertBefore = nullptr) { + return new BasicBlock(Context, Name, Parent, InsertBefore); + } + ~BasicBlock() override; + + /// \brief Return the enclosing method, or null if none. + const Function *getParent() const { return Parent; } + Function *getParent() { return Parent; } + + /// \brief Return the module owning the function this basic block belongs to, + /// or nullptr it the function does not have a module. + /// + /// Note: this is undefined behavior if the block does not have a parent. + const Module *getModule() const; + Module *getModule(); + + /// \brief Returns the terminator instruction if the block is well formed or + /// null if the block is not well formed. + TerminatorInst *getTerminator(); + const TerminatorInst *getTerminator() const; + + /// \brief Returns the call instruction calling @llvm.experimental.deoptimize + /// prior to the terminating return instruction of this basic block, if such a + /// call is present. Otherwise, returns null. + CallInst *getTerminatingDeoptimizeCall(); + const CallInst *getTerminatingDeoptimizeCall() const { + return const_cast<BasicBlock *>(this)->getTerminatingDeoptimizeCall(); + } + + /// \brief Returns the call instruction marked 'musttail' prior to the + /// terminating return instruction of this basic block, if such a call is + /// present. Otherwise, returns null. + CallInst *getTerminatingMustTailCall(); + const CallInst *getTerminatingMustTailCall() const { + return const_cast<BasicBlock *>(this)->getTerminatingMustTailCall(); + } + + /// \brief Returns a pointer to the first instruction in this block that is + /// not a PHINode instruction. + /// + /// When adding instructions to the beginning of the basic block, they should + /// be added before the returned value, not before the first instruction, + /// which might be PHI. Returns 0 is there's no non-PHI instruction. + Instruction* getFirstNonPHI(); + const Instruction* getFirstNonPHI() const { + return const_cast<BasicBlock*>(this)->getFirstNonPHI(); + } + + /// \brief Returns a pointer to the first instruction in this block that is not + /// a PHINode or a debug intrinsic. + Instruction* getFirstNonPHIOrDbg(); + const Instruction* getFirstNonPHIOrDbg() const { + return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbg(); + } + + /// \brief Returns a pointer to the first instruction in this block that is not + /// a PHINode, a debug intrinsic, or a lifetime intrinsic. + Instruction* getFirstNonPHIOrDbgOrLifetime(); + const Instruction* getFirstNonPHIOrDbgOrLifetime() const { + return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbgOrLifetime(); + } + + /// \brief Returns an iterator to the first instruction in this block that is + /// suitable for inserting a non-PHI instruction. + /// + /// In particular, it skips all PHIs and LandingPad instructions. + iterator getFirstInsertionPt(); + const_iterator getFirstInsertionPt() const { + return const_cast<BasicBlock*>(this)->getFirstInsertionPt(); + } + + /// \brief Unlink 'this' from the containing function, but do not delete it. + void removeFromParent(); + + /// \brief Unlink 'this' from the containing function and delete it. + /// + // \returns an iterator pointing to the element after the erased one. + SymbolTableList<BasicBlock>::iterator eraseFromParent(); + + /// \brief Unlink this basic block from its current function and insert it + /// into the function that \p MovePos lives in, right before \p MovePos. + void moveBefore(BasicBlock *MovePos); + + /// \brief Unlink this basic block from its current function and insert it + /// right after \p MovePos in the function \p MovePos lives in. + void moveAfter(BasicBlock *MovePos); + + /// \brief Insert unlinked basic block into a function. + /// + /// Inserts an unlinked basic block into \c Parent. If \c InsertBefore is + /// provided, inserts before that basic block, otherwise inserts at the end. + /// + /// \pre \a getParent() is \c nullptr. + void insertInto(Function *Parent, BasicBlock *InsertBefore = nullptr); + + /// \brief Return the predecessor of this block if it has a single predecessor + /// block. Otherwise return a null pointer. + BasicBlock *getSinglePredecessor(); + const BasicBlock *getSinglePredecessor() const { + return const_cast<BasicBlock*>(this)->getSinglePredecessor(); + } + + /// \brief Return the predecessor of this block if it has a unique predecessor + /// block. Otherwise return a null pointer. + /// + /// Note that unique predecessor doesn't mean single edge, there can be + /// multiple edges from the unique predecessor to this block (for example a + /// switch statement with multiple cases having the same destination). + BasicBlock *getUniquePredecessor(); + const BasicBlock *getUniquePredecessor() const { + return const_cast<BasicBlock*>(this)->getUniquePredecessor(); + } + + /// \brief Return the successor of this block if it has a single successor. + /// Otherwise return a null pointer. + /// + /// This method is analogous to getSinglePredecessor above. + BasicBlock *getSingleSuccessor(); + const BasicBlock *getSingleSuccessor() const { + return const_cast<BasicBlock*>(this)->getSingleSuccessor(); + } + + /// \brief Return the successor of this block if it has a unique successor. + /// Otherwise return a null pointer. + /// + /// This method is analogous to getUniquePredecessor above. + BasicBlock *getUniqueSuccessor(); + const BasicBlock *getUniqueSuccessor() const { + return const_cast<BasicBlock*>(this)->getUniqueSuccessor(); + } + + //===--------------------------------------------------------------------===// + /// Instruction iterator methods + /// + inline iterator begin() { return InstList.begin(); } + inline const_iterator begin() const { return InstList.begin(); } + inline iterator end () { return InstList.end(); } + inline const_iterator end () const { return InstList.end(); } + + inline reverse_iterator rbegin() { return InstList.rbegin(); } + inline const_reverse_iterator rbegin() const { return InstList.rbegin(); } + inline reverse_iterator rend () { return InstList.rend(); } + inline const_reverse_iterator rend () const { return InstList.rend(); } + + inline size_t size() const { return InstList.size(); } + inline bool empty() const { return InstList.empty(); } + inline const Instruction &front() const { return InstList.front(); } + inline Instruction &front() { return InstList.front(); } + inline const Instruction &back() const { return InstList.back(); } + inline Instruction &back() { return InstList.back(); } + + /// \brief Return the underlying instruction list container. + /// + /// Currently you need to access the underlying instruction list container + /// directly if you want to modify it. + const InstListType &getInstList() const { return InstList; } + InstListType &getInstList() { return InstList; } + + /// \brief Returns a pointer to a member of the instruction list. + static InstListType BasicBlock::*getSublistAccess(Instruction*) { + return &BasicBlock::InstList; + } + + /// \brief Returns a pointer to the symbol table if one exists. + ValueSymbolTable *getValueSymbolTable(); + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Value *V) { + return V->getValueID() == Value::BasicBlockVal; + } + + /// \brief Cause all subinstructions to "let go" of all the references that + /// said subinstructions are maintaining. + /// + /// This allows one to 'delete' a whole class at a time, even though there may + /// be circular references... first all references are dropped, and all use + /// counts go to zero. Then everything is delete'd for real. Note that no + /// operations are valid on an object that has "dropped all references", + /// except operator delete. + void dropAllReferences(); + + /// \brief Notify the BasicBlock that the predecessor \p Pred is no longer + /// able to reach it. + /// + /// This is actually not used to update the Predecessor list, but is actually + /// used to update the PHI nodes that reside in the block. Note that this + /// should be called while the predecessor still refers to this block. + void removePredecessor(BasicBlock *Pred, bool DontDeleteUselessPHIs = false); + + bool canSplitPredecessors() const; + + /// \brief Split the basic block into two basic blocks at the specified + /// instruction. + /// + /// Note that all instructions BEFORE the specified iterator stay as part of + /// the original basic block, an unconditional branch is added to the original + /// BB, and the rest of the instructions in the BB are moved to the new BB, + /// including the old terminator. The newly formed BasicBlock is returned. + /// This function invalidates the specified iterator. + /// + /// Note that this only works on well formed basic blocks (must have a + /// terminator), and 'I' must not be the end of instruction list (which would + /// cause a degenerate basic block to be formed, having a terminator inside of + /// the basic block). + /// + /// Also note that this doesn't preserve any passes. To split blocks while + /// keeping loop information consistent, use the SplitBlock utility function. + BasicBlock *splitBasicBlock(iterator I, const Twine &BBName = ""); + BasicBlock *splitBasicBlock(Instruction *I, const Twine &BBName = "") { + return splitBasicBlock(I->getIterator(), BBName); + } + + /// \brief Returns true if there are any uses of this basic block other than + /// direct branches, switches, etc. to it. + bool hasAddressTaken() const { return getSubclassDataFromValue() != 0; } + + /// \brief Update all phi nodes in this basic block's successors to refer to + /// basic block \p New instead of to it. + void replaceSuccessorsPhiUsesWith(BasicBlock *New); + + /// \brief Return true if this basic block is an exception handling block. + bool isEHPad() const { return getFirstNonPHI()->isEHPad(); } + + /// \brief Return true if this basic block is a landing pad. + /// + /// Being a ``landing pad'' means that the basic block is the destination of + /// the 'unwind' edge of an invoke instruction. + bool isLandingPad() const; + + /// \brief Return the landingpad instruction associated with the landing pad. + LandingPadInst *getLandingPadInst(); + const LandingPadInst *getLandingPadInst() const; + +private: + /// \brief Increment the internal refcount of the number of BlockAddresses + /// referencing this BasicBlock by \p Amt. + /// + /// This is almost always 0, sometimes one possibly, but almost never 2, and + /// inconceivably 3 or more. + void AdjustBlockAddressRefCount(int Amt) { + setValueSubclassData(getSubclassDataFromValue()+Amt); + assert((int)(signed char)getSubclassDataFromValue() >= 0 && + "Refcount wrap-around"); + } + /// \brief Shadow Value::setValueSubclassData with a private forwarding method + /// so that any future subclasses cannot accidentally use it. + void setValueSubclassData(unsigned short D) { + Value::setValueSubclassData(D); + } +}; + +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef) + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/CallingConv.h b/third_party/llvm-subzero/include/llvm/IR/CallingConv.h new file mode 100644 index 0000000..4987b7e --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/CallingConv.h
@@ -0,0 +1,203 @@ +//===-- llvm/CallingConv.h - LLVM Calling Conventions -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines LLVM's set of calling conventions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_CALLINGCONV_H +#define LLVM_IR_CALLINGCONV_H + +namespace llvm { + +/// CallingConv Namespace - This namespace contains an enum with a value for +/// the well-known calling conventions. +/// +namespace CallingConv { + /// LLVM IR allows to use arbitrary numbers as calling convention identifiers. + typedef unsigned ID; + + /// A set of enums which specify the assigned numeric values for known llvm + /// calling conventions. + /// @brief LLVM Calling Convention Representation + enum { + /// C - The default llvm calling convention, compatible with C. This + /// convention is the only calling convention that supports varargs calls. + /// As with typical C calling conventions, the callee/caller have to + /// tolerate certain amounts of prototype mismatch. + C = 0, + + // Generic LLVM calling conventions. None of these calling conventions + // support varargs calls, and all assume that the caller and callee + // prototype exactly match. + + /// Fast - This calling convention attempts to make calls as fast as + /// possible (e.g. by passing things in registers). + Fast = 8, + + // Cold - This calling convention attempts to make code in the caller as + // efficient as possible under the assumption that the call is not commonly + // executed. As such, these calls often preserve all registers so that the + // call does not break any live ranges in the caller side. + Cold = 9, + + // GHC - Calling convention used by the Glasgow Haskell Compiler (GHC). + GHC = 10, + + // HiPE - Calling convention used by the High-Performance Erlang Compiler + // (HiPE). + HiPE = 11, + + // WebKit JS - Calling convention for stack based JavaScript calls + WebKit_JS = 12, + + // AnyReg - Calling convention for dynamic register based calls (e.g. + // stackmap and patchpoint intrinsics). + AnyReg = 13, + + // PreserveMost - Calling convention for runtime calls that preserves most + // registers. + PreserveMost = 14, + + // PreserveAll - Calling convention for runtime calls that preserves + // (almost) all registers. + PreserveAll = 15, + + // Swift - Calling convention for Swift. + Swift = 16, + + // CXX_FAST_TLS - Calling convention for access functions. + CXX_FAST_TLS = 17, + + // Target - This is the start of the target-specific calling conventions, + // e.g. fastcall and thiscall on X86. + FirstTargetCC = 64, + + /// X86_StdCall - stdcall is the calling conventions mostly used by the + /// Win32 API. It is basically the same as the C convention with the + /// difference in that the callee is responsible for popping the arguments + /// from the stack. + X86_StdCall = 64, + + /// X86_FastCall - 'fast' analog of X86_StdCall. Passes first two arguments + /// in ECX:EDX registers, others - via stack. Callee is responsible for + /// stack cleaning. + X86_FastCall = 65, + + /// ARM_APCS - ARM Procedure Calling Standard calling convention (obsolete, + /// but still used on some targets). + ARM_APCS = 66, + + /// ARM_AAPCS - ARM Architecture Procedure Calling Standard calling + /// convention (aka EABI). Soft float variant. + ARM_AAPCS = 67, + + /// ARM_AAPCS_VFP - Same as ARM_AAPCS, but uses hard floating point ABI. + ARM_AAPCS_VFP = 68, + + /// MSP430_INTR - Calling convention used for MSP430 interrupt routines. + MSP430_INTR = 69, + + /// X86_ThisCall - Similar to X86_StdCall. Passes first argument in ECX, + /// others via stack. Callee is responsible for stack cleaning. MSVC uses + /// this by default for methods in its ABI. + X86_ThisCall = 70, + + /// PTX_Kernel - Call to a PTX kernel. + /// Passes all arguments in parameter space. + PTX_Kernel = 71, + + /// PTX_Device - Call to a PTX device function. + /// Passes all arguments in register or parameter space. + PTX_Device = 72, + + /// SPIR_FUNC - Calling convention for SPIR non-kernel device functions. + /// No lowering or expansion of arguments. + /// Structures are passed as a pointer to a struct with the byval attribute. + /// Functions can only call SPIR_FUNC and SPIR_KERNEL functions. + /// Functions can only have zero or one return values. + /// Variable arguments are not allowed, except for printf. + /// How arguments/return values are lowered are not specified. + /// Functions are only visible to the devices. + SPIR_FUNC = 75, + + /// SPIR_KERNEL - Calling convention for SPIR kernel functions. + /// Inherits the restrictions of SPIR_FUNC, except + /// Cannot have non-void return values. + /// Cannot have variable arguments. + /// Can also be called by the host. + /// Is externally visible. + SPIR_KERNEL = 76, + + /// Intel_OCL_BI - Calling conventions for Intel OpenCL built-ins + Intel_OCL_BI = 77, + + /// \brief The C convention as specified in the x86-64 supplement to the + /// System V ABI, used on most non-Windows systems. + X86_64_SysV = 78, + + /// \brief The C convention as implemented on Windows/x86-64. This + /// convention differs from the more common \c X86_64_SysV convention + /// in a number of ways, most notably in that XMM registers used to pass + /// arguments are shadowed by GPRs, and vice versa. + X86_64_Win64 = 79, + + /// \brief MSVC calling convention that passes vectors and vector aggregates + /// in SSE registers. + X86_VectorCall = 80, + + /// \brief Calling convention used by HipHop Virtual Machine (HHVM) to + /// perform calls to and from translation cache, and for calling PHP + /// functions. + /// HHVM calling convention supports tail/sibling call elimination. + HHVM = 81, + + /// \brief HHVM calling convention for invoking C/C++ helpers. + HHVM_C = 82, + + /// X86_INTR - x86 hardware interrupt context. Callee may take one or two + /// parameters, where the 1st represents a pointer to hardware context frame + /// and the 2nd represents hardware error code, the presence of the later + /// depends on the interrupt vector taken. Valid for both 32- and 64-bit + /// subtargets. + X86_INTR = 83, + + /// Used for AVR interrupt routines. + AVR_INTR = 84, + + /// Calling convention used for AVR signal routines. + AVR_SIGNAL = 85, + + /// Calling convention used for special AVR rtlib functions + /// which have an "optimized" convention to preserve registers. + AVR_BUILTIN = 86, + + /// Calling convention used for Mesa vertex shaders. + AMDGPU_VS = 87, + + /// Calling convention used for Mesa geometry shaders. + AMDGPU_GS = 88, + + /// Calling convention used for Mesa pixel shaders. + AMDGPU_PS = 89, + + /// Calling convention used for Mesa compute shaders. + AMDGPU_CS = 90, + + /// Calling convention for AMDGPU code object kernels. + AMDGPU_KERNEL = 91, + + /// The highest possible calling convention ID. Must be some 2^k - 1. + MaxID = 1023 + }; +} // End CallingConv namespace + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Constant.h b/third_party/llvm-subzero/include/llvm/IR/Constant.h new file mode 100644 index 0000000..3c5fe55 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/Constant.h
@@ -0,0 +1,164 @@ +//===-- llvm/Constant.h - Constant class definition -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Constant class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_CONSTANT_H +#define LLVM_IR_CONSTANT_H + +#include "llvm/IR/User.h" + +namespace llvm { + class APInt; + + template<typename T> class SmallVectorImpl; + +/// This is an important base class in LLVM. It provides the common facilities +/// of all constant values in an LLVM program. A constant is a value that is +/// immutable at runtime. Functions are constants because their address is +/// immutable. Same with global variables. +/// +/// All constants share the capabilities provided in this class. All constants +/// can have a null value. They can have an operand list. Constants can be +/// simple (integer and floating point values), complex (arrays and structures), +/// or expression based (computations yielding a constant value composed of +/// only certain operators and other constant values). +/// +/// Note that Constants are immutable (once created they never change) +/// and are fully shared by structural equivalence. This means that two +/// structurally equivalent constants will always have the same address. +/// Constants are created on demand as needed and never deleted: thus clients +/// don't have to worry about the lifetime of the objects. +/// @brief LLVM Constant Representation +class Constant : public User { + void operator=(const Constant &) = delete; + Constant(const Constant &) = delete; + void anchor() override; + +protected: + Constant(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps) + : User(ty, vty, Ops, NumOps) {} + +public: + /// Return true if this is the value that would be returned by getNullValue. + bool isNullValue() const; + + /// Returns true if the value is one. + bool isOneValue() const; + + /// Return true if this is the value that would be returned by + /// getAllOnesValue. + bool isAllOnesValue() const; + + /// Return true if the value is what would be returned by + /// getZeroValueForNegation. + bool isNegativeZeroValue() const; + + /// Return true if the value is negative zero or null value. + bool isZeroValue() const; + + /// Return true if the value is not the smallest signed value. + bool isNotMinSignedValue() const; + + /// Return true if the value is the smallest signed value. + bool isMinSignedValue() const; + + /// Return true if evaluation of this constant could trap. This is true for + /// things like constant expressions that could divide by zero. + bool canTrap() const; + + /// Return true if the value can vary between threads. + bool isThreadDependent() const; + + /// Return true if the value is dependent on a dllimport variable. + bool isDLLImportDependent() const; + + /// Return true if the constant has users other than constant expressions and + /// other dangling things. + bool isConstantUsed() const; + + /// This method classifies the entry according to whether or not it may + /// generate a relocation entry. This must be conservative, so if it might + /// codegen to a relocatable entry, it should say so. + /// + /// FIXME: This really should not be in IR. + bool needsRelocation() const; + + /// For aggregates (struct/array/vector) return the constant that corresponds + /// to the specified element if possible, or null if not. This can return null + /// if the element index is a ConstantExpr, or if 'this' is a constant expr. + Constant *getAggregateElement(unsigned Elt) const; + Constant *getAggregateElement(Constant *Elt) const; + + /// If this is a splat vector constant, meaning that all of the elements have + /// the same value, return that value. Otherwise return 0. + Constant *getSplatValue() const; + + /// If C is a constant integer then return its value, otherwise C must be a + /// vector of constant integers, all equal, and the common value is returned. + const APInt &getUniqueInteger() const; + + /// Called if some element of this constant is no longer valid. + /// At this point only other constants may be on the use_list for this + /// constant. Any constants on our Use list must also be destroy'd. The + /// implementation must be sure to remove the constant from the list of + /// available cached constants. Implementations should implement + /// destroyConstantImpl to remove constants from any pools/maps they are + /// contained it. + void destroyConstant(); + + //// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return V->getValueID() >= ConstantFirstVal && + V->getValueID() <= ConstantLastVal; + } + + /// This method is a special form of User::replaceUsesOfWith + /// (which does not work on constants) that does work + /// on constants. Basically this method goes through the trouble of building + /// a new constant that is equivalent to the current one, with all uses of + /// From replaced with uses of To. After this construction is completed, all + /// of the users of 'this' are replaced to use the new constant, and then + /// 'this' is deleted. In general, you should not call this method, instead, + /// use Value::replaceAllUsesWith, which automatically dispatches to this + /// method as needed. + /// + void handleOperandChange(Value *, Value *); + + static Constant *getNullValue(Type* Ty); + + /// @returns the value for an integer or vector of integer constant of the + /// given type that has all its bits set to true. + /// @brief Get the all ones value + static Constant *getAllOnesValue(Type* Ty); + + /// Return the value for an integer or pointer constant, or a vector thereof, + /// with the given scalar value. + static Constant *getIntegerValue(Type *Ty, const APInt &V); + + /// If there are any dead constant users dangling off of this constant, remove + /// them. This method is useful for clients that want to check to see if a + /// global is unused, but don't want to deal with potentially dead constants + /// hanging off of the globals. + void removeDeadConstantUsers() const; + + Constant *stripPointerCasts() { + return cast<Constant>(Value::stripPointerCasts()); + } + + const Constant *stripPointerCasts() const { + return const_cast<Constant*>(this)->stripPointerCasts(); + } +}; + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/DebugLoc.h b/third_party/llvm-subzero/include/llvm/IR/DebugLoc.h new file mode 100644 index 0000000..8ea5875 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/DebugLoc.h
@@ -0,0 +1,126 @@ +//===- DebugLoc.h - Debug Location Information ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a number of light weight data structures used +// to describe and track debug location information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_DEBUGLOC_H +#define LLVM_IR_DEBUGLOC_H + +#include "llvm/IR/TrackingMDRef.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + + class LLVMContext; + class raw_ostream; + class DILocation; + + /// \brief A debug info location. + /// + /// This class is a wrapper around a tracking reference to an \a DILocation + /// pointer. + /// + /// To avoid extra includes, \a DebugLoc doubles the \a DILocation API with a + /// one based on relatively opaque \a MDNode pointers. + class DebugLoc { + TrackingMDNodeRef Loc; + + public: + DebugLoc() {} + DebugLoc(DebugLoc &&X) : Loc(std::move(X.Loc)) {} + DebugLoc(const DebugLoc &X) : Loc(X.Loc) {} + DebugLoc &operator=(DebugLoc &&X) { + Loc = std::move(X.Loc); + return *this; + } + DebugLoc &operator=(const DebugLoc &X) { + Loc = X.Loc; + return *this; + } + + /// \brief Construct from an \a DILocation. + DebugLoc(const DILocation *L); + + /// \brief Construct from an \a MDNode. + /// + /// Note: if \c N is not an \a DILocation, a verifier check will fail, and + /// accessors will crash. However, construction from other nodes is + /// supported in order to handle forward references when reading textual + /// IR. + explicit DebugLoc(const MDNode *N); + + /// \brief Get the underlying \a DILocation. + /// + /// \pre !*this or \c isa<DILocation>(getAsMDNode()). + /// @{ + DILocation *get() const; + operator DILocation *() const { return get(); } + DILocation *operator->() const { return get(); } + DILocation &operator*() const { return *get(); } + /// @} + + /// \brief Check for null. + /// + /// Check for null in a way that is safe with broken debug info. Unlike + /// the conversion to \c DILocation, this doesn't require that \c Loc is of + /// the right type. Important for cases like \a llvm::StripDebugInfo() and + /// \a Instruction::hasMetadata(). + explicit operator bool() const { return Loc; } + + /// \brief Check whether this has a trivial destructor. + bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); } + + /// \brief Create a new DebugLoc. + /// + /// Create a new DebugLoc at the specified line/col and scope/inline. This + /// forwards to \a DILocation::get(). + /// + /// If \c !Scope, returns a default-constructed \a DebugLoc. + /// + /// FIXME: Remove this. Users should use DILocation::get(). + static DebugLoc get(unsigned Line, unsigned Col, const MDNode *Scope, + const MDNode *InlinedAt = nullptr); + + unsigned getLine() const; + unsigned getCol() const; + MDNode *getScope() const; + DILocation *getInlinedAt() const; + + /// \brief Get the fully inlined-at scope for a DebugLoc. + /// + /// Gets the inlined-at scope for a DebugLoc. + MDNode *getInlinedAtScope() const; + + /// \brief Find the debug info location for the start of the function. + /// + /// Walk up the scope chain of given debug loc and find line number info + /// for the function. + /// + /// FIXME: Remove this. Users should use DILocation/DILocalScope API to + /// find the subprogram, and then DILocation::get(). + DebugLoc getFnDebugLoc() const; + + /// \brief Return \c this as a bar \a MDNode. + MDNode *getAsMDNode() const { return Loc; } + + bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; } + bool operator!=(const DebugLoc &DL) const { return Loc != DL.Loc; } + + void dump() const; + + /// \brief prints source location /path/to/file.exe:line:col @[inlined at] + void print(raw_ostream &OS) const; + }; + +} // end namespace llvm + +#endif /* LLVM_SUPPORT_DEBUGLOC_H */
diff --git a/third_party/llvm-subzero/include/llvm/IR/DerivedTypes.h b/third_party/llvm-subzero/include/llvm/IR/DerivedTypes.h new file mode 100644 index 0000000..efd0d07 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/DerivedTypes.h
@@ -0,0 +1,480 @@ +//===-- llvm/DerivedTypes.h - Classes for handling data types ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations of classes that represent "derived +// types". These are things like "arrays of x" or "structure of x, y, z" or +// "function returning x taking (y,z) as parameters", etc... +// +// The implementations of these classes live in the Type.cpp file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_DERIVEDTYPES_H +#define LLVM_IR_DERIVEDTYPES_H + +#include "llvm/IR/Type.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class Value; +class APInt; +class LLVMContext; +template<typename T> class ArrayRef; +class StringRef; + +/// Class to represent integer types. Note that this class is also used to +/// represent the built-in integer types: Int1Ty, Int8Ty, Int16Ty, Int32Ty and +/// Int64Ty. +/// @brief Integer representation type +class IntegerType : public Type { + friend class LLVMContextImpl; + +protected: + explicit IntegerType(LLVMContext &C, unsigned NumBits) : Type(C, IntegerTyID){ + setSubclassData(NumBits); + } + +public: + /// This enum is just used to hold constants we need for IntegerType. + enum { + MIN_INT_BITS = 1, ///< Minimum number of bits that can be specified + MAX_INT_BITS = (1<<23)-1 ///< Maximum number of bits that can be specified + ///< Note that bit width is stored in the Type classes SubclassData field + ///< which has 23 bits. This yields a maximum bit width of 8,388,607 bits. + }; + + /// This static method is the primary way of constructing an IntegerType. + /// If an IntegerType with the same NumBits value was previously instantiated, + /// that instance will be returned. Otherwise a new one will be created. Only + /// one instance with a given NumBits value is ever created. + /// @brief Get or create an IntegerType instance. + static IntegerType *get(LLVMContext &C, unsigned NumBits); + + /// @brief Get the number of bits in this IntegerType + unsigned getBitWidth() const { return getSubclassData(); } + + /// Return a bitmask with ones set for all of the bits that can be set by an + /// unsigned version of this type. This is 0xFF for i8, 0xFFFF for i16, etc. + uint64_t getBitMask() const { + return ~uint64_t(0UL) >> (64-getBitWidth()); + } + + /// Return a uint64_t with just the most significant bit set (the sign bit, if + /// the value is treated as a signed number). + uint64_t getSignBit() const { + return 1ULL << (getBitWidth()-1); + } + + /// For example, this is 0xFF for an 8 bit integer, 0xFFFF for i16, etc. + /// @returns a bit mask with ones set for all the bits of this type. + /// @brief Get a bit mask for this type. + APInt getMask() const; + + /// This method determines if the width of this IntegerType is a power-of-2 + /// in terms of 8 bit bytes. + /// @returns true if this is a power-of-2 byte width. + /// @brief Is this a power-of-2 byte-width IntegerType ? + bool isPowerOf2ByteWidth() const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Type *T) { + return T->getTypeID() == IntegerTyID; + } +}; + +unsigned Type::getIntegerBitWidth() const { + return cast<IntegerType>(this)->getBitWidth(); +} + +/// Class to represent function types +/// +class FunctionType : public Type { + FunctionType(const FunctionType &) = delete; + const FunctionType &operator=(const FunctionType &) = delete; + FunctionType(Type *Result, ArrayRef<Type*> Params, bool IsVarArgs); + +public: + /// This static method is the primary way of constructing a FunctionType. + static FunctionType *get(Type *Result, + ArrayRef<Type*> Params, bool isVarArg); + + /// Create a FunctionType taking no parameters. + static FunctionType *get(Type *Result, bool isVarArg); + + /// Return true if the specified type is valid as a return type. + static bool isValidReturnType(Type *RetTy); + + /// Return true if the specified type is valid as an argument type. + static bool isValidArgumentType(Type *ArgTy); + + bool isVarArg() const { return getSubclassData()!=0; } + Type *getReturnType() const { return ContainedTys[0]; } + + typedef Type::subtype_iterator param_iterator; + param_iterator param_begin() const { return ContainedTys + 1; } + param_iterator param_end() const { return &ContainedTys[NumContainedTys]; } + ArrayRef<Type *> params() const { + return makeArrayRef(param_begin(), param_end()); + } + + /// Parameter type accessors. + Type *getParamType(unsigned i) const { return ContainedTys[i+1]; } + + /// Return the number of fixed parameters this function type requires. + /// This does not consider varargs. + unsigned getNumParams() const { return NumContainedTys - 1; } + + /// Methods for support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Type *T) { + return T->getTypeID() == FunctionTyID; + } +}; +static_assert(AlignOf<FunctionType>::Alignment >= AlignOf<Type *>::Alignment, + "Alignment sufficient for objects appended to FunctionType"); + +bool Type::isFunctionVarArg() const { + return cast<FunctionType>(this)->isVarArg(); +} + +Type *Type::getFunctionParamType(unsigned i) const { + return cast<FunctionType>(this)->getParamType(i); +} + +unsigned Type::getFunctionNumParams() const { + return cast<FunctionType>(this)->getNumParams(); +} + +/// Common super class of ArrayType, StructType, PointerType and VectorType. +class CompositeType : public Type { +protected: + explicit CompositeType(LLVMContext &C, TypeID tid) : Type(C, tid) {} + +public: + /// Given an index value into the type, return the type of the element. + Type *getTypeAtIndex(const Value *V) const; + Type *getTypeAtIndex(unsigned Idx) const; + bool indexValid(const Value *V) const; + bool indexValid(unsigned Idx) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Type *T) { + return T->getTypeID() == ArrayTyID || + T->getTypeID() == StructTyID || + T->getTypeID() == PointerTyID || + T->getTypeID() == VectorTyID; + } +}; + +/// Class to represent struct types. There are two different kinds of struct +/// types: Literal structs and Identified structs. +/// +/// Literal struct types (e.g. { i32, i32 }) are uniqued structurally, and must +/// always have a body when created. You can get one of these by using one of +/// the StructType::get() forms. +/// +/// Identified structs (e.g. %foo or %42) may optionally have a name and are not +/// uniqued. The names for identified structs are managed at the LLVMContext +/// level, so there can only be a single identified struct with a given name in +/// a particular LLVMContext. Identified structs may also optionally be opaque +/// (have no body specified). You get one of these by using one of the +/// StructType::create() forms. +/// +/// Independent of what kind of struct you have, the body of a struct type are +/// laid out in memory consequtively with the elements directly one after the +/// other (if the struct is packed) or (if not packed) with padding between the +/// elements as defined by DataLayout (which is required to match what the code +/// generator for a target expects). +/// +class StructType : public CompositeType { + StructType(const StructType &) = delete; + const StructType &operator=(const StructType &) = delete; + StructType(LLVMContext &C) + : CompositeType(C, StructTyID), SymbolTableEntry(nullptr) {} + enum { + /// This is the contents of the SubClassData field. + SCDB_HasBody = 1, + SCDB_Packed = 2, + SCDB_IsLiteral = 4, + SCDB_IsSized = 8 + }; + + /// For a named struct that actually has a name, this is a pointer to the + /// symbol table entry (maintained by LLVMContext) for the struct. + /// This is null if the type is an literal struct or if it is a identified + /// type that has an empty name. + void *SymbolTableEntry; + +public: + /// This creates an identified struct. + static StructType *create(LLVMContext &Context, StringRef Name); + static StructType *create(LLVMContext &Context); + + static StructType *create(ArrayRef<Type *> Elements, StringRef Name, + bool isPacked = false); + static StructType *create(ArrayRef<Type *> Elements); + static StructType *create(LLVMContext &Context, ArrayRef<Type *> Elements, + StringRef Name, bool isPacked = false); + static StructType *create(LLVMContext &Context, ArrayRef<Type *> Elements); + static StructType *create(StringRef Name, Type *elt1, ...) LLVM_END_WITH_NULL; + + /// This static method is the primary way to create a literal StructType. + static StructType *get(LLVMContext &Context, ArrayRef<Type*> Elements, + bool isPacked = false); + + /// Create an empty structure type. + static StructType *get(LLVMContext &Context, bool isPacked = false); + + /// This static method is a convenience method for creating structure types by + /// specifying the elements as arguments. Note that this method always returns + /// a non-packed struct, and requires at least one element type. + static StructType *get(Type *elt1, ...) LLVM_END_WITH_NULL; + + bool isPacked() const { return (getSubclassData() & SCDB_Packed) != 0; } + + /// Return true if this type is uniqued by structural equivalence, false if it + /// is a struct definition. + bool isLiteral() const { return (getSubclassData() & SCDB_IsLiteral) != 0; } + + /// Return true if this is a type with an identity that has no body specified + /// yet. These prints as 'opaque' in .ll files. + bool isOpaque() const { return (getSubclassData() & SCDB_HasBody) == 0; } + + /// isSized - Return true if this is a sized type. + bool isSized(SmallPtrSetImpl<Type *> *Visited = nullptr) const; + + /// Return true if this is a named struct that has a non-empty name. + bool hasName() const { return SymbolTableEntry != nullptr; } + + /// Return the name for this struct type if it has an identity. + /// This may return an empty string for an unnamed struct type. Do not call + /// this on an literal type. + StringRef getName() const; + + /// Change the name of this type to the specified name, or to a name with a + /// suffix if there is a collision. Do not call this on an literal type. + void setName(StringRef Name); + + /// Specify a body for an opaque identified type. + void setBody(ArrayRef<Type*> Elements, bool isPacked = false); + void setBody(Type *elt1, ...) LLVM_END_WITH_NULL; + + /// Return true if the specified type is valid as a element type. + static bool isValidElementType(Type *ElemTy); + + // Iterator access to the elements. + typedef Type::subtype_iterator element_iterator; + element_iterator element_begin() const { return ContainedTys; } + element_iterator element_end() const { return &ContainedTys[NumContainedTys];} + ArrayRef<Type *> const elements() const { + return makeArrayRef(element_begin(), element_end()); + } + + /// Return true if this is layout identical to the specified struct. + bool isLayoutIdentical(StructType *Other) const; + + /// Random access to the elements + unsigned getNumElements() const { return NumContainedTys; } + Type *getElementType(unsigned N) const { + assert(N < NumContainedTys && "Element number out of range!"); + return ContainedTys[N]; + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Type *T) { + return T->getTypeID() == StructTyID; + } +}; + +StringRef Type::getStructName() const { + return cast<StructType>(this)->getName(); +} + +unsigned Type::getStructNumElements() const { + return cast<StructType>(this)->getNumElements(); +} + +Type *Type::getStructElementType(unsigned N) const { + return cast<StructType>(this)->getElementType(N); +} + +/// This is the superclass of the array, pointer and vector type classes. +/// All of these represent "arrays" in memory. The array type represents a +/// specifically sized array, pointer types are unsized/unknown size arrays, +/// vector types represent specifically sized arrays that allow for use of SIMD +/// instructions. SequentialType holds the common features of all, which stem +/// from the fact that all three lay their components out in memory identically. +class SequentialType : public CompositeType { + Type *ContainedType; ///< Storage for the single contained type. + SequentialType(const SequentialType &) = delete; + const SequentialType &operator=(const SequentialType &) = delete; + +protected: + SequentialType(TypeID TID, Type *ElType) + : CompositeType(ElType->getContext(), TID), ContainedType(ElType) { + ContainedTys = &ContainedType; + NumContainedTys = 1; + } + +public: + Type *getElementType() const { return getSequentialElementType(); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Type *T) { + return T->getTypeID() == ArrayTyID || + T->getTypeID() == PointerTyID || + T->getTypeID() == VectorTyID; + } +}; + +/// Class to represent array types. +class ArrayType : public SequentialType { + uint64_t NumElements; + + ArrayType(const ArrayType &) = delete; + const ArrayType &operator=(const ArrayType &) = delete; + ArrayType(Type *ElType, uint64_t NumEl); + +public: + /// This static method is the primary way to construct an ArrayType + static ArrayType *get(Type *ElementType, uint64_t NumElements); + + /// Return true if the specified type is valid as a element type. + static bool isValidElementType(Type *ElemTy); + + uint64_t getNumElements() const { return NumElements; } + + /// Methods for support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Type *T) { + return T->getTypeID() == ArrayTyID; + } +}; + +uint64_t Type::getArrayNumElements() const { + return cast<ArrayType>(this)->getNumElements(); +} + +/// Class to represent vector types. +class VectorType : public SequentialType { + unsigned NumElements; + + VectorType(const VectorType &) = delete; + const VectorType &operator=(const VectorType &) = delete; + VectorType(Type *ElType, unsigned NumEl); + +public: + /// This static method is the primary way to construct an VectorType. + static VectorType *get(Type *ElementType, unsigned NumElements); + + /// This static method gets a VectorType with the same number of elements as + /// the input type, and the element type is an integer type of the same width + /// as the input element type. + static VectorType *getInteger(VectorType *VTy) { + unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); + assert(EltBits && "Element size must be of a non-zero size"); + Type *EltTy = IntegerType::get(VTy->getContext(), EltBits); + return VectorType::get(EltTy, VTy->getNumElements()); + } + + /// This static method is like getInteger except that the element types are + /// twice as wide as the elements in the input type. + static VectorType *getExtendedElementVectorType(VectorType *VTy) { + unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); + Type *EltTy = IntegerType::get(VTy->getContext(), EltBits * 2); + return VectorType::get(EltTy, VTy->getNumElements()); + } + + /// This static method is like getInteger except that the element types are + /// half as wide as the elements in the input type. + static VectorType *getTruncatedElementVectorType(VectorType *VTy) { + unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); + assert((EltBits & 1) == 0 && + "Cannot truncate vector element with odd bit-width"); + Type *EltTy = IntegerType::get(VTy->getContext(), EltBits / 2); + return VectorType::get(EltTy, VTy->getNumElements()); + } + + /// This static method returns a VectorType with half as many elements as the + /// input type and the same element type. + static VectorType *getHalfElementsVectorType(VectorType *VTy) { + unsigned NumElts = VTy->getNumElements(); + assert ((NumElts & 1) == 0 && + "Cannot halve vector with odd number of elements."); + return VectorType::get(VTy->getElementType(), NumElts/2); + } + + /// This static method returns a VectorType with twice as many elements as the + /// input type and the same element type. + static VectorType *getDoubleElementsVectorType(VectorType *VTy) { + unsigned NumElts = VTy->getNumElements(); + return VectorType::get(VTy->getElementType(), NumElts*2); + } + + /// Return true if the specified type is valid as a element type. + static bool isValidElementType(Type *ElemTy); + + /// Return the number of elements in the Vector type. + unsigned getNumElements() const { return NumElements; } + + /// Return the number of bits in the Vector type. + /// Returns zero when the vector is a vector of pointers. + unsigned getBitWidth() const { + return NumElements * getElementType()->getPrimitiveSizeInBits(); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Type *T) { + return T->getTypeID() == VectorTyID; + } +}; + +unsigned Type::getVectorNumElements() const { + return cast<VectorType>(this)->getNumElements(); +} + +/// Class to represent pointers. +class PointerType : public SequentialType { + PointerType(const PointerType &) = delete; + const PointerType &operator=(const PointerType &) = delete; + explicit PointerType(Type *ElType, unsigned AddrSpace); + +public: + /// This constructs a pointer to an object of the specified type in a numbered + /// address space. + static PointerType *get(Type *ElementType, unsigned AddressSpace); + + /// This constructs a pointer to an object of the specified type in the + /// generic address space (address space zero). + static PointerType *getUnqual(Type *ElementType) { + return PointerType::get(ElementType, 0); + } + + /// Return true if the specified type is valid as a element type. + static bool isValidElementType(Type *ElemTy); + + /// Return true if we can load or store from a pointer to this type. + static bool isLoadableOrStorableType(Type *ElemTy); + + /// Return the address space of the Pointer type. + inline unsigned getAddressSpace() const { return getSubclassData(); } + + /// Implement support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const Type *T) { + return T->getTypeID() == PointerTyID; + } +}; + +unsigned Type::getPointerAddressSpace() const { + return cast<PointerType>(getScalarType())->getAddressSpace(); +} + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Function.h b/third_party/llvm-subzero/include/llvm/IR/Function.h new file mode 100644 index 0000000..ff55fcb --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/Function.h
@@ -0,0 +1,666 @@ +//===-- llvm/Function.h - Class to represent a single function --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Function class, which represents a +// single function/procedure in LLVM. +// +// A function basically consists of a list of basic blocks, a list of arguments, +// and a symbol table. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_FUNCTION_H +#define LLVM_IR_FUNCTION_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/Argument.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/GlobalObject.h" +#include "llvm/IR/OperandTraits.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +template <typename T> class Optional; +class FunctionType; +class LLVMContext; +class DISubprogram; + +class Function : public GlobalObject, public ilist_node<Function> { +public: + typedef SymbolTableList<Argument> ArgumentListType; + typedef SymbolTableList<BasicBlock> BasicBlockListType; + + // BasicBlock iterators... + typedef BasicBlockListType::iterator iterator; + typedef BasicBlockListType::const_iterator const_iterator; + + typedef ArgumentListType::iterator arg_iterator; + typedef ArgumentListType::const_iterator const_arg_iterator; + +private: + // Important things that make up a function! + BasicBlockListType BasicBlocks; ///< The basic blocks + mutable ArgumentListType ArgumentList; ///< The formal arguments + ValueSymbolTable *SymTab; ///< Symbol table of args/instructions + AttributeSet AttributeSets; ///< Parameter attributes + + /* + * Value::SubclassData + * + * bit 0 : HasLazyArguments + * bit 1 : HasPrefixData + * bit 2 : HasPrologueData + * bit 3 : HasPersonalityFn + * bits 4-13 : CallingConvention + * bits 14 : HasGC + * bits 15 : [reserved] + */ + + /// Bits from GlobalObject::GlobalObjectSubclassData. + enum { + /// Whether this function is materializable. + IsMaterializableBit = 0, + }; + + friend class SymbolTableListTraits<Function>; + + void setParent(Module *parent); + + /// hasLazyArguments/CheckLazyArguments - The argument list of a function is + /// built on demand, so that the list isn't allocated until the first client + /// needs it. The hasLazyArguments predicate returns true if the arg list + /// hasn't been set up yet. +public: + bool hasLazyArguments() const { + return getSubclassDataFromValue() & (1<<0); + } + +private: + void CheckLazyArguments() const { + if (hasLazyArguments()) + BuildLazyArguments(); + } + void BuildLazyArguments() const; + + Function(const Function&) = delete; + void operator=(const Function&) = delete; + + /// Function ctor - If the (optional) Module argument is specified, the + /// function is automatically inserted into the end of the function list for + /// the module. + /// + Function(FunctionType *Ty, LinkageTypes Linkage, + const Twine &N = "", Module *M = nullptr); + +public: + static Function *Create(FunctionType *Ty, LinkageTypes Linkage, + const Twine &N = "", Module *M = nullptr) { + return new Function(Ty, Linkage, N, M); + } + + ~Function() override; + + /// \brief Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + Type *getReturnType() const; // Return the type of the ret val + FunctionType *getFunctionType() const; // Return the FunctionType for me + + /// getContext - Return a reference to the LLVMContext associated with this + /// function. + LLVMContext &getContext() const; + + /// isVarArg - Return true if this function takes a variable number of + /// arguments. + bool isVarArg() const; + + bool isMaterializable() const; + void setIsMaterializable(bool V); + + /// getIntrinsicID - This method returns the ID number of the specified + /// function, or Intrinsic::not_intrinsic if the function is not an + /// intrinsic, or if the pointer is null. This value is always defined to be + /// zero to allow easy checking for whether a function is intrinsic or not. + /// The particular intrinsic functions which correspond to this value are + /// defined in llvm/Intrinsics.h. + Intrinsic::ID getIntrinsicID() const LLVM_READONLY { return IntID; } + bool isIntrinsic() const { return getName().startswith("llvm."); } + + static Intrinsic::ID lookupIntrinsicID(StringRef Name); + + /// \brief Recalculate the ID for this function if it is an Intrinsic defined + /// in llvm/Intrinsics.h. Sets the intrinsic ID to Intrinsic::not_intrinsic + /// if the name of this function does not match an intrinsic in that header. + /// Note, this method does not need to be called directly, as it is called + /// from Value::setName() whenever the name of this function changes. + void recalculateIntrinsicID(); + + /// getCallingConv()/setCallingConv(CC) - These method get and set the + /// calling convention of this function. The enum values for the known + /// calling conventions are defined in CallingConv.h. + CallingConv::ID getCallingConv() const { + return static_cast<CallingConv::ID>((getSubclassDataFromValue() >> 4) & + CallingConv::MaxID); + } + void setCallingConv(CallingConv::ID CC) { + auto ID = static_cast<unsigned>(CC); + assert(!(ID & ~CallingConv::MaxID) && "Unsupported calling convention"); + setValueSubclassData((getSubclassDataFromValue() & 0xc00f) | (ID << 4)); + } + + /// @brief Return the attribute list for this Function. + AttributeSet getAttributes() const { return AttributeSets; } + + /// @brief Set the attribute list for this Function. + void setAttributes(AttributeSet Attrs) { AttributeSets = Attrs; } + + /// @brief Add function attributes to this function. + void addFnAttr(Attribute::AttrKind N) { + setAttributes(AttributeSets.addAttribute(getContext(), + AttributeSet::FunctionIndex, N)); + } + + /// @brief Remove function attributes from this function. + void removeFnAttr(Attribute::AttrKind Kind) { + setAttributes(AttributeSets.removeAttribute( + getContext(), AttributeSet::FunctionIndex, Kind)); + } + + /// @brief Add function attributes to this function. + void addFnAttr(StringRef Kind) { + setAttributes( + AttributeSets.addAttribute(getContext(), + AttributeSet::FunctionIndex, Kind)); + } + void addFnAttr(StringRef Kind, StringRef Value) { + setAttributes( + AttributeSets.addAttribute(getContext(), + AttributeSet::FunctionIndex, Kind, Value)); + } + + /// @brief Remove function attribute from this function. + void removeFnAttr(StringRef Kind) { + setAttributes(AttributeSets.removeAttribute( + getContext(), AttributeSet::FunctionIndex, Kind)); + } + + /// Set the entry count for this function. + void setEntryCount(uint64_t Count); + + /// Get the entry count for this function. + Optional<uint64_t> getEntryCount() const; + + /// @brief Return true if the function has the attribute. + bool hasFnAttribute(Attribute::AttrKind Kind) const { + return AttributeSets.hasFnAttribute(Kind); + } + bool hasFnAttribute(StringRef Kind) const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); + } + + /// @brief Return the attribute for the given attribute kind. + Attribute getFnAttribute(Attribute::AttrKind Kind) const { + return getAttribute(AttributeSet::FunctionIndex, Kind); + } + Attribute getFnAttribute(StringRef Kind) const { + return getAttribute(AttributeSet::FunctionIndex, Kind); + } + + /// \brief Return the stack alignment for the function. + unsigned getFnStackAlignment() const { + if (!hasFnAttribute(Attribute::StackAlignment)) + return 0; + return AttributeSets.getStackAlignment(AttributeSet::FunctionIndex); + } + + /// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm + /// to use during code generation. + bool hasGC() const { + return getSubclassDataFromValue() & (1<<14); + } + const std::string &getGC() const; + void setGC(std::string Str); + void clearGC(); + + /// @brief adds the attribute to the list of attributes. + void addAttribute(unsigned i, Attribute::AttrKind Kind); + + /// @brief adds the attribute to the list of attributes. + void addAttribute(unsigned i, Attribute Attr); + + /// @brief adds the attributes to the list of attributes. + void addAttributes(unsigned i, AttributeSet Attrs); + + /// @brief removes the attribute from the list of attributes. + void removeAttribute(unsigned i, Attribute::AttrKind Kind); + + /// @brief removes the attribute from the list of attributes. + void removeAttribute(unsigned i, StringRef Kind); + + /// @brief removes the attributes from the list of attributes. + void removeAttributes(unsigned i, AttributeSet Attrs); + + /// @brief check if an attributes is in the list of attributes. + bool hasAttribute(unsigned i, Attribute::AttrKind Kind) const { + return getAttributes().hasAttribute(i, Kind); + } + + Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const { + return AttributeSets.getAttribute(i, Kind); + } + + Attribute getAttribute(unsigned i, StringRef Kind) const { + return AttributeSets.getAttribute(i, Kind); + } + + /// @brief adds the dereferenceable attribute to the list of attributes. + void addDereferenceableAttr(unsigned i, uint64_t Bytes); + + /// @brief adds the dereferenceable_or_null attribute to the list of + /// attributes. + void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); + + /// @brief Extract the alignment for a call or parameter (0=unknown). + unsigned getParamAlignment(unsigned i) const { + return AttributeSets.getParamAlignment(i); + } + + /// @brief Extract the number of dereferenceable bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableBytes(unsigned i) const { + return AttributeSets.getDereferenceableBytes(i); + } + + /// @brief Extract the number of dereferenceable_or_null bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableOrNullBytes(unsigned i) const { + return AttributeSets.getDereferenceableOrNullBytes(i); + } + + /// @brief Determine if the function does not access memory. + bool doesNotAccessMemory() const { + return hasFnAttribute(Attribute::ReadNone); + } + void setDoesNotAccessMemory() { + addFnAttr(Attribute::ReadNone); + } + + /// @brief Determine if the function does not access or only reads memory. + bool onlyReadsMemory() const { + return doesNotAccessMemory() || hasFnAttribute(Attribute::ReadOnly); + } + void setOnlyReadsMemory() { + addFnAttr(Attribute::ReadOnly); + } + + /// @brief Determine if the function does not access or only writes memory. + bool doesNotReadMemory() const { + return doesNotAccessMemory() || hasFnAttribute(Attribute::WriteOnly); + } + void setDoesNotReadMemory() { + addFnAttr(Attribute::WriteOnly); + } + + /// @brief Determine if the call can access memmory only using pointers based + /// on its arguments. + bool onlyAccessesArgMemory() const { + return hasFnAttribute(Attribute::ArgMemOnly); + } + void setOnlyAccessesArgMemory() { addFnAttr(Attribute::ArgMemOnly); } + + /// @brief Determine if the function may only access memory that is + /// inaccessible from the IR. + bool onlyAccessesInaccessibleMemory() const { + return hasFnAttribute(Attribute::InaccessibleMemOnly); + } + void setOnlyAccessesInaccessibleMemory() { + addFnAttr(Attribute::InaccessibleMemOnly); + } + + /// @brief Determine if the function may only access memory that is + // either inaccessible from the IR or pointed to by its arguments. + bool onlyAccessesInaccessibleMemOrArgMem() const { + return hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly); + } + void setOnlyAccessesInaccessibleMemOrArgMem() { + addFnAttr(Attribute::InaccessibleMemOrArgMemOnly); + } + + /// @brief Determine if the function cannot return. + bool doesNotReturn() const { + return hasFnAttribute(Attribute::NoReturn); + } + void setDoesNotReturn() { + addFnAttr(Attribute::NoReturn); + } + + /// @brief Determine if the function cannot unwind. + bool doesNotThrow() const { + return hasFnAttribute(Attribute::NoUnwind); + } + void setDoesNotThrow() { + addFnAttr(Attribute::NoUnwind); + } + + /// @brief Determine if the call cannot be duplicated. + bool cannotDuplicate() const { + return hasFnAttribute(Attribute::NoDuplicate); + } + void setCannotDuplicate() { + addFnAttr(Attribute::NoDuplicate); + } + + /// @brief Determine if the call is convergent. + bool isConvergent() const { + return hasFnAttribute(Attribute::Convergent); + } + void setConvergent() { + addFnAttr(Attribute::Convergent); + } + void setNotConvergent() { + removeFnAttr(Attribute::Convergent); + } + + /// Determine if the function is known not to recurse, directly or + /// indirectly. + bool doesNotRecurse() const { + return hasFnAttribute(Attribute::NoRecurse); + } + void setDoesNotRecurse() { + addFnAttr(Attribute::NoRecurse); + } + + /// @brief True if the ABI mandates (or the user requested) that this + /// function be in a unwind table. + bool hasUWTable() const { + return hasFnAttribute(Attribute::UWTable); + } + void setHasUWTable() { + addFnAttr(Attribute::UWTable); + } + + /// @brief True if this function needs an unwind table. + bool needsUnwindTableEntry() const { + return hasUWTable() || !doesNotThrow(); + } + + /// @brief Determine if the function returns a structure through first + /// pointer argument. + bool hasStructRetAttr() const { + return AttributeSets.hasAttribute(1, Attribute::StructRet) || + AttributeSets.hasAttribute(2, Attribute::StructRet); + } + + /// @brief Determine if the parameter or return value is marked with NoAlias + /// attribute. + /// @param n The parameter to check. 1 is the first parameter, 0 is the return + bool doesNotAlias(unsigned n) const { + return AttributeSets.hasAttribute(n, Attribute::NoAlias); + } + void setDoesNotAlias(unsigned n) { + addAttribute(n, Attribute::NoAlias); + } + + /// @brief Determine if the parameter can be captured. + /// @param n The parameter to check. 1 is the first parameter, 0 is the return + bool doesNotCapture(unsigned n) const { + return AttributeSets.hasAttribute(n, Attribute::NoCapture); + } + void setDoesNotCapture(unsigned n) { + addAttribute(n, Attribute::NoCapture); + } + + bool doesNotAccessMemory(unsigned n) const { + return AttributeSets.hasAttribute(n, Attribute::ReadNone); + } + void setDoesNotAccessMemory(unsigned n) { + addAttribute(n, Attribute::ReadNone); + } + + bool onlyReadsMemory(unsigned n) const { + return doesNotAccessMemory(n) || + AttributeSets.hasAttribute(n, Attribute::ReadOnly); + } + void setOnlyReadsMemory(unsigned n) { + addAttribute(n, Attribute::ReadOnly); + } + + /// Optimize this function for minimum size (-Oz). + bool optForMinSize() const { return hasFnAttribute(Attribute::MinSize); } + + /// Optimize this function for size (-Os) or minimum size (-Oz). + bool optForSize() const { + return hasFnAttribute(Attribute::OptimizeForSize) || optForMinSize(); + } + + /// copyAttributesFrom - copy all additional attributes (those not needed to + /// create a Function) from the Function Src to this one. + void copyAttributesFrom(const GlobalValue *Src) override; + + /// deleteBody - This method deletes the body of the function, and converts + /// the linkage to external. + /// + void deleteBody() { + dropAllReferences(); + setLinkage(ExternalLinkage); + } + + /// removeFromParent - This method unlinks 'this' from the containing module, + /// but does not delete it. + /// + void removeFromParent() override; + + /// eraseFromParent - This method unlinks 'this' from the containing module + /// and deletes it. + /// + void eraseFromParent() override; + + /// Steal arguments from another function. + /// + /// Drop this function's arguments and splice in the ones from \c Src. + /// Requires that this has no function body. + void stealArgumentListFrom(Function &Src); + + /// Get the underlying elements of the Function... the basic block list is + /// empty for external functions. + /// + const ArgumentListType &getArgumentList() const { + CheckLazyArguments(); + return ArgumentList; + } + ArgumentListType &getArgumentList() { + CheckLazyArguments(); + return ArgumentList; + } + static ArgumentListType Function::*getSublistAccess(Argument*) { + return &Function::ArgumentList; + } + + const BasicBlockListType &getBasicBlockList() const { return BasicBlocks; } + BasicBlockListType &getBasicBlockList() { return BasicBlocks; } + static BasicBlockListType Function::*getSublistAccess(BasicBlock*) { + return &Function::BasicBlocks; + } + + const BasicBlock &getEntryBlock() const { return front(); } + BasicBlock &getEntryBlock() { return front(); } + + //===--------------------------------------------------------------------===// + // Symbol Table Accessing functions... + + /// getSymbolTable() - Return the symbol table... + /// + inline ValueSymbolTable &getValueSymbolTable() { return *SymTab; } + inline const ValueSymbolTable &getValueSymbolTable() const { return *SymTab; } + + //===--------------------------------------------------------------------===// + // BasicBlock iterator forwarding functions + // + iterator begin() { return BasicBlocks.begin(); } + const_iterator begin() const { return BasicBlocks.begin(); } + iterator end () { return BasicBlocks.end(); } + const_iterator end () const { return BasicBlocks.end(); } + + size_t size() const { return BasicBlocks.size(); } + bool empty() const { return BasicBlocks.empty(); } + const BasicBlock &front() const { return BasicBlocks.front(); } + BasicBlock &front() { return BasicBlocks.front(); } + const BasicBlock &back() const { return BasicBlocks.back(); } + BasicBlock &back() { return BasicBlocks.back(); } + +/// @name Function Argument Iteration +/// @{ + + arg_iterator arg_begin() { + CheckLazyArguments(); + return ArgumentList.begin(); + } + const_arg_iterator arg_begin() const { + CheckLazyArguments(); + return ArgumentList.begin(); + } + arg_iterator arg_end() { + CheckLazyArguments(); + return ArgumentList.end(); + } + const_arg_iterator arg_end() const { + CheckLazyArguments(); + return ArgumentList.end(); + } + + iterator_range<arg_iterator> args() { + return make_range(arg_begin(), arg_end()); + } + + iterator_range<const_arg_iterator> args() const { + return make_range(arg_begin(), arg_end()); + } + +/// @} + + size_t arg_size() const; + bool arg_empty() const; + + /// \brief Check whether this function has a personality function. + bool hasPersonalityFn() const { + return getSubclassDataFromValue() & (1<<3); + } + + /// \brief Get the personality function associated with this function. + Constant *getPersonalityFn() const; + void setPersonalityFn(Constant *Fn); + + /// \brief Check whether this function has prefix data. + bool hasPrefixData() const { + return getSubclassDataFromValue() & (1<<1); + } + + /// \brief Get the prefix data associated with this function. + Constant *getPrefixData() const; + void setPrefixData(Constant *PrefixData); + + /// \brief Check whether this function has prologue data. + bool hasPrologueData() const { + return getSubclassDataFromValue() & (1<<2); + } + + /// \brief Get the prologue data associated with this function. + Constant *getPrologueData() const; + void setPrologueData(Constant *PrologueData); + + /// Print the function to an output stream with an optional + /// AssemblyAnnotationWriter. + void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW = nullptr, + bool ShouldPreserveUseListOrder = false, + bool IsForDebug = false) const; + + /// viewCFG - This function is meant for use from the debugger. You can just + /// say 'call F->viewCFG()' and a ghostview window should pop up from the + /// program, displaying the CFG of the current function with the code for each + /// basic block inside. This depends on there being a 'dot' and 'gv' program + /// in your path. + /// + void viewCFG() const; + + /// viewCFGOnly - This function is meant for use from the debugger. It works + /// just like viewCFG, but it does not include the contents of basic blocks + /// into the nodes, just the label. If you are only interested in the CFG + /// this can make the graph smaller. + /// + void viewCFGOnly() const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return V->getValueID() == Value::FunctionVal; + } + + /// dropAllReferences() - This method causes all the subinstructions to "let + /// go" of all references that they are maintaining. This allows one to + /// 'delete' a whole module at a time, even though there may be circular + /// references... first all references are dropped, and all use counts go to + /// zero. Then everything is deleted for real. Note that no operations are + /// valid on an object that has "dropped all references", except operator + /// delete. + /// + /// Since no other object in the module can have references into the body of a + /// function, dropping all references deletes the entire body of the function, + /// including any contained basic blocks. + /// + void dropAllReferences(); + + /// hasAddressTaken - returns true if there are any uses of this function + /// other than direct calls or invokes to it, or blockaddress expressions. + /// Optionally passes back an offending user for diagnostic purposes. + /// + bool hasAddressTaken(const User** = nullptr) const; + + /// isDefTriviallyDead - Return true if it is trivially safe to remove + /// this function definition from the module (because it isn't externally + /// visible, does not have its address taken, and has no callers). To make + /// this more accurate, call removeDeadConstantUsers first. + bool isDefTriviallyDead() const; + + /// callsFunctionThatReturnsTwice - Return true if the function has a call to + /// setjmp or other function that gcc recognizes as "returning twice". + bool callsFunctionThatReturnsTwice() const; + + /// \brief Set the attached subprogram. + /// + /// Calls \a setMetadata() with \a LLVMContext::MD_dbg. + void setSubprogram(DISubprogram *SP); + + /// \brief Get the attached subprogram. + /// + /// Calls \a getMetadata() with \a LLVMContext::MD_dbg and casts the result + /// to \a DISubprogram. + DISubprogram *getSubprogram() const; + +private: + void allocHungoffUselist(); + template<int Idx> void setHungoffOperand(Constant *C); + + // Shadow Value::setValueSubclassData with a private forwarding method so that + // subclasses cannot accidentally use it. + void setValueSubclassData(unsigned short D) { + Value::setValueSubclassData(D); + } + void setValueSubclassDataBit(unsigned Bit, bool On); +}; + +template <> +struct OperandTraits<Function> : public HungoffOperandTraits<3> {}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(Function, Value) + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/GlobalObject.h b/third_party/llvm-subzero/include/llvm/IR/GlobalObject.h new file mode 100644 index 0000000..04737a0 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/GlobalObject.h
@@ -0,0 +1,146 @@ +//===-- llvm/GlobalObject.h - Class to represent global objects -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This represents an independent object. That is, a function or a global +// variable, but not an alias. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_GLOBALOBJECT_H +#define LLVM_IR_GLOBALOBJECT_H + +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/GlobalValue.h" + +namespace llvm { +class Comdat; +class MDNode; +class Metadata; +class Module; + +class GlobalObject : public GlobalValue { + GlobalObject(const GlobalObject &) = delete; + +protected: + GlobalObject(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, + LinkageTypes Linkage, const Twine &Name, + unsigned AddressSpace = 0) + : GlobalValue(Ty, VTy, Ops, NumOps, Linkage, Name, AddressSpace), + ObjComdat(nullptr) { + setGlobalValueSubClassData(0); + } + + std::string Section; // Section to emit this into, empty means default + Comdat *ObjComdat; + enum { + LastAlignmentBit = 4, + HasMetadataHashEntryBit, + + GlobalObjectBits, + }; + static const unsigned GlobalObjectSubClassDataBits = + GlobalValueSubClassDataBits - GlobalObjectBits; + +private: + static const unsigned AlignmentBits = LastAlignmentBit + 1; + static const unsigned AlignmentMask = (1 << AlignmentBits) - 1; + static const unsigned GlobalObjectMask = (1 << GlobalObjectBits) - 1; + +public: + unsigned getAlignment() const { + unsigned Data = getGlobalValueSubClassData(); + unsigned AlignmentData = Data & AlignmentMask; + return (1u << AlignmentData) >> 1; + } + void setAlignment(unsigned Align); + + unsigned getGlobalObjectSubClassData() const; + void setGlobalObjectSubClassData(unsigned Val); + + bool hasSection() const { return !getSection().empty(); } + StringRef getSection() const { return Section; } + void setSection(StringRef S); + + bool hasComdat() const { return getComdat() != nullptr; } + const Comdat *getComdat() const { return ObjComdat; } + Comdat *getComdat() { return ObjComdat; } + void setComdat(Comdat *C) { ObjComdat = C; } + + /// Check if this has any metadata. + bool hasMetadata() const { return hasMetadataHashEntry(); } + + /// Get the current metadata attachments for the given kind, if any. + /// + /// These functions require that the function have at most a single attachment + /// of the given kind, and return \c nullptr if such an attachment is missing. + /// @{ + MDNode *getMetadata(unsigned KindID) const; + MDNode *getMetadata(StringRef Kind) const; + /// @} + + /// Appends all attachments with the given ID to \c MDs in insertion order. + /// If the global has no attachments with the given ID, or if ID is invalid, + /// leaves MDs unchanged. + /// @{ + void getMetadata(unsigned KindID, SmallVectorImpl<MDNode *> &MDs) const; + void getMetadata(StringRef Kind, SmallVectorImpl<MDNode *> &MDs) const; + /// @} + + /// Set a particular kind of metadata attachment. + /// + /// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or + /// replacing it if it already exists. + /// @{ + void setMetadata(unsigned KindID, MDNode *MD); + void setMetadata(StringRef Kind, MDNode *MD); + /// @} + + /// Add a metadata attachment. + /// @{ + void addMetadata(unsigned KindID, MDNode &MD); + void addMetadata(StringRef Kind, MDNode &MD); + /// @} + + /// Appends all attachments for the global to \c MDs, sorting by attachment + /// ID. Attachments with the same ID appear in insertion order. + void + getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const; + + /// Erase all metadata attachments with the given kind. + void eraseMetadata(unsigned KindID); + + /// Copy metadata from Src, adjusting offsets by Offset. + void copyMetadata(const GlobalObject *Src, unsigned Offset); + + void addTypeMetadata(unsigned Offset, Metadata *TypeID); + + void copyAttributesFrom(const GlobalValue *Src) override; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return V->getValueID() == Value::FunctionVal || + V->getValueID() == Value::GlobalVariableVal; + } + + void clearMetadata(); + +private: + bool hasMetadataHashEntry() const { + return getGlobalValueSubClassData() & (1 << HasMetadataHashEntryBit); + } + void setHasMetadataHashEntry(bool HasEntry) { + unsigned Mask = 1 << HasMetadataHashEntryBit; + setGlobalValueSubClassData((~Mask & getGlobalValueSubClassData()) | + (HasEntry ? Mask : 0u)); + } +}; + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/GlobalValue.h b/third_party/llvm-subzero/include/llvm/IR/GlobalValue.h new file mode 100644 index 0000000..09682f7 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/GlobalValue.h
@@ -0,0 +1,517 @@ +//===-- llvm/GlobalValue.h - Class to represent a global value --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a common base class of all globally definable objects. As such, +// it is subclassed by GlobalVariable, GlobalAlias and by Function. This is +// used because you can do certain things with these global objects that you +// can't do to anything else. For example, use the address of one as a +// constant. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_GLOBALVALUE_H +#define LLVM_IR_GLOBALVALUE_H + +#include "llvm/IR/Constant.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/Support/MD5.h" +#include <system_error> + +namespace llvm { + +class Comdat; +class PointerType; +class Module; + +namespace Intrinsic { + enum ID : unsigned; +} + +class GlobalValue : public Constant { + GlobalValue(const GlobalValue &) = delete; +public: + /// @brief An enumeration for the kinds of linkage for global values. + enum LinkageTypes { + ExternalLinkage = 0,///< Externally visible function + AvailableExternallyLinkage, ///< Available for inspection, not emission. + LinkOnceAnyLinkage, ///< Keep one copy of function when linking (inline) + LinkOnceODRLinkage, ///< Same, but only replaced by something equivalent. + WeakAnyLinkage, ///< Keep one copy of named function when linking (weak) + WeakODRLinkage, ///< Same, but only replaced by something equivalent. + AppendingLinkage, ///< Special purpose, only applies to global arrays + InternalLinkage, ///< Rename collisions when linking (static functions). + PrivateLinkage, ///< Like Internal, but omit from symbol table. + ExternalWeakLinkage,///< ExternalWeak linkage description. + CommonLinkage ///< Tentative definitions. + }; + + /// @brief An enumeration for the kinds of visibility of global values. + enum VisibilityTypes { + DefaultVisibility = 0, ///< The GV is visible + HiddenVisibility, ///< The GV is hidden + ProtectedVisibility ///< The GV is protected + }; + + /// @brief Storage classes of global values for PE targets. + enum DLLStorageClassTypes { + DefaultStorageClass = 0, + DLLImportStorageClass = 1, ///< Function to be imported from DLL + DLLExportStorageClass = 2 ///< Function to be accessible from DLL. + }; + +protected: + GlobalValue(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, + LinkageTypes Linkage, const Twine &Name, unsigned AddressSpace) + : Constant(PointerType::get(Ty, AddressSpace), VTy, Ops, NumOps), + ValueType(Ty), Linkage(Linkage), Visibility(DefaultVisibility), + UnnamedAddrVal(unsigned(UnnamedAddr::None)), + DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal), + IntID((Intrinsic::ID)0U), Parent(nullptr) { + setName(Name); + } + + Type *ValueType; + // All bitfields use unsigned as the underlying type so that MSVC will pack + // them. + unsigned Linkage : 4; // The linkage of this global + unsigned Visibility : 2; // The visibility style of this global + unsigned UnnamedAddrVal : 2; // This value's address is not significant + unsigned DllStorageClass : 2; // DLL storage class + + unsigned ThreadLocal : 3; // Is this symbol "Thread Local", if so, what is + // the desired model? + static const unsigned GlobalValueSubClassDataBits = 19; + +private: + // Give subclasses access to what otherwise would be wasted padding. + // (19 + 4 + 2 + 2 + 2 + 3) == 32. + unsigned SubClassData : GlobalValueSubClassDataBits; + + friend class Constant; + void destroyConstantImpl(); + Value *handleOperandChangeImpl(Value *From, Value *To); + + /// Returns true if the definition of this global may be replaced by a + /// differently optimized variant of the same source level function at link + /// time. + bool mayBeDerefined() const { + switch (getLinkage()) { + case WeakODRLinkage: + case LinkOnceODRLinkage: + case AvailableExternallyLinkage: + return true; + + case WeakAnyLinkage: + case LinkOnceAnyLinkage: + case CommonLinkage: + case ExternalWeakLinkage: + case ExternalLinkage: + case AppendingLinkage: + case InternalLinkage: + case PrivateLinkage: + return isInterposable(); + } + + llvm_unreachable("Fully covered switch above!"); + } + +protected: + /// \brief The intrinsic ID for this subclass (which must be a Function). + /// + /// This member is defined by this class, but not used for anything. + /// Subclasses can use it to store their intrinsic ID, if they have one. + /// + /// This is stored here to save space in Function on 64-bit hosts. + Intrinsic::ID IntID; + + unsigned getGlobalValueSubClassData() const { + return SubClassData; + } + void setGlobalValueSubClassData(unsigned V) { + assert(V < (1 << GlobalValueSubClassDataBits) && "It will not fit"); + SubClassData = V; + } + + Module *Parent; // The containing module. +public: + enum ThreadLocalMode { + NotThreadLocal = 0, + GeneralDynamicTLSModel, + LocalDynamicTLSModel, + InitialExecTLSModel, + LocalExecTLSModel + }; + + ~GlobalValue() override { + removeDeadConstantUsers(); // remove any dead constants using this. + } + + unsigned getAlignment() const; + + enum class UnnamedAddr { + None, + Local, + Global, + }; + + bool hasGlobalUnnamedAddr() const { + return getUnnamedAddr() == UnnamedAddr::Global; + } + + /// Returns true if this value's address is not significant in this module. + /// This attribute is intended to be used only by the code generator and LTO + /// to allow the linker to decide whether the global needs to be in the symbol + /// table. It should probably not be used in optimizations, as the value may + /// have uses outside the module; use hasGlobalUnnamedAddr() instead. + bool hasAtLeastLocalUnnamedAddr() const { + return getUnnamedAddr() != UnnamedAddr::None; + } + + UnnamedAddr getUnnamedAddr() const { + return UnnamedAddr(UnnamedAddrVal); + } + void setUnnamedAddr(UnnamedAddr Val) { UnnamedAddrVal = unsigned(Val); } + + static UnnamedAddr getMinUnnamedAddr(UnnamedAddr A, UnnamedAddr B) { + if (A == UnnamedAddr::None || B == UnnamedAddr::None) + return UnnamedAddr::None; + if (A == UnnamedAddr::Local || B == UnnamedAddr::Local) + return UnnamedAddr::Local; + return UnnamedAddr::Global; + } + + bool hasComdat() const { return getComdat() != nullptr; } + Comdat *getComdat(); + const Comdat *getComdat() const { + return const_cast<GlobalValue *>(this)->getComdat(); + } + + VisibilityTypes getVisibility() const { return VisibilityTypes(Visibility); } + bool hasDefaultVisibility() const { return Visibility == DefaultVisibility; } + bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; } + bool hasProtectedVisibility() const { + return Visibility == ProtectedVisibility; + } + void setVisibility(VisibilityTypes V) { + assert((!hasLocalLinkage() || V == DefaultVisibility) && + "local linkage requires default visibility"); + Visibility = V; + } + + /// If the value is "Thread Local", its value isn't shared by the threads. + bool isThreadLocal() const { return getThreadLocalMode() != NotThreadLocal; } + void setThreadLocal(bool Val) { + setThreadLocalMode(Val ? GeneralDynamicTLSModel : NotThreadLocal); + } + void setThreadLocalMode(ThreadLocalMode Val) { + assert(Val == NotThreadLocal || getValueID() != Value::FunctionVal); + ThreadLocal = Val; + } + ThreadLocalMode getThreadLocalMode() const { + return static_cast<ThreadLocalMode>(ThreadLocal); + } + + DLLStorageClassTypes getDLLStorageClass() const { + return DLLStorageClassTypes(DllStorageClass); + } + bool hasDLLImportStorageClass() const { + return DllStorageClass == DLLImportStorageClass; + } + bool hasDLLExportStorageClass() const { + return DllStorageClass == DLLExportStorageClass; + } + void setDLLStorageClass(DLLStorageClassTypes C) { DllStorageClass = C; } + + bool hasSection() const { return !getSection().empty(); } + StringRef getSection() const; + + /// Global values are always pointers. + PointerType *getType() const { return cast<PointerType>(User::getType()); } + + Type *getValueType() const { return ValueType; } + + static LinkageTypes getLinkOnceLinkage(bool ODR) { + return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage; + } + static LinkageTypes getWeakLinkage(bool ODR) { + return ODR ? WeakODRLinkage : WeakAnyLinkage; + } + + static bool isExternalLinkage(LinkageTypes Linkage) { + return Linkage == ExternalLinkage; + } + static bool isAvailableExternallyLinkage(LinkageTypes Linkage) { + return Linkage == AvailableExternallyLinkage; + } + static bool isLinkOnceODRLinkage(LinkageTypes Linkage) { + return Linkage == LinkOnceODRLinkage; + } + static bool isLinkOnceLinkage(LinkageTypes Linkage) { + return Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage; + } + static bool isWeakAnyLinkage(LinkageTypes Linkage) { + return Linkage == WeakAnyLinkage; + } + static bool isWeakODRLinkage(LinkageTypes Linkage) { + return Linkage == WeakODRLinkage; + } + static bool isWeakLinkage(LinkageTypes Linkage) { + return isWeakAnyLinkage(Linkage) || isWeakODRLinkage(Linkage); + } + static bool isAppendingLinkage(LinkageTypes Linkage) { + return Linkage == AppendingLinkage; + } + static bool isInternalLinkage(LinkageTypes Linkage) { + return Linkage == InternalLinkage; + } + static bool isPrivateLinkage(LinkageTypes Linkage) { + return Linkage == PrivateLinkage; + } + static bool isLocalLinkage(LinkageTypes Linkage) { + return isInternalLinkage(Linkage) || isPrivateLinkage(Linkage); + } + static bool isExternalWeakLinkage(LinkageTypes Linkage) { + return Linkage == ExternalWeakLinkage; + } + static bool isCommonLinkage(LinkageTypes Linkage) { + return Linkage == CommonLinkage; + } + static bool isValidDeclarationLinkage(LinkageTypes Linkage) { + return isExternalWeakLinkage(Linkage) || isExternalLinkage(Linkage); + } + + /// Whether the definition of this global may be replaced by something + /// non-equivalent at link time. For example, if a function has weak linkage + /// then the code defining it may be replaced by different code. + static bool isInterposableLinkage(LinkageTypes Linkage) { + switch (Linkage) { + case WeakAnyLinkage: + case LinkOnceAnyLinkage: + case CommonLinkage: + case ExternalWeakLinkage: + return true; + + case AvailableExternallyLinkage: + case LinkOnceODRLinkage: + case WeakODRLinkage: + // The above three cannot be overridden but can be de-refined. + + case ExternalLinkage: + case AppendingLinkage: + case InternalLinkage: + case PrivateLinkage: + return false; + } + llvm_unreachable("Fully covered switch above!"); + } + + /// Whether the definition of this global may be discarded if it is not used + /// in its compilation unit. + static bool isDiscardableIfUnused(LinkageTypes Linkage) { + return isLinkOnceLinkage(Linkage) || isLocalLinkage(Linkage) || + isAvailableExternallyLinkage(Linkage); + } + + /// Whether the definition of this global may be replaced at link time. NB: + /// Using this method outside of the code generators is almost always a + /// mistake: when working at the IR level use isInterposable instead as it + /// knows about ODR semantics. + static bool isWeakForLinker(LinkageTypes Linkage) { + return Linkage == WeakAnyLinkage || Linkage == WeakODRLinkage || + Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage || + Linkage == CommonLinkage || Linkage == ExternalWeakLinkage; + } + + /// Return true if the currently visible definition of this global (if any) is + /// exactly the definition we will see at runtime. + /// + /// Non-exact linkage types inhibits most non-inlining IPO, since a + /// differently optimized variant of the same function can have different + /// observable or undefined behavior than in the variant currently visible. + /// For instance, we could have started with + /// + /// void foo(int *v) { + /// int t = 5 / v[0]; + /// (void) t; + /// } + /// + /// and "refined" it to + /// + /// void foo(int *v) { } + /// + /// However, we cannot infer readnone for `foo`, since that would justify + /// DSE'ing a store to `v[0]` across a call to `foo`, which can cause + /// undefined behavior if the linker replaces the actual call destination with + /// the unoptimized `foo`. + /// + /// Inlining is okay across non-exact linkage types as long as they're not + /// interposable (see \c isInterposable), since in such cases the currently + /// visible variant is *a* correct implementation of the original source + /// function; it just isn't the *only* correct implementation. + bool isDefinitionExact() const { + return !mayBeDerefined(); + } + + /// Return true if this global has an exact defintion. + bool hasExactDefinition() const { + // While this computes exactly the same thing as + // isStrongDefinitionForLinker, the intended uses are different. This + // function is intended to help decide if specific inter-procedural + // transforms are correct, while isStrongDefinitionForLinker's intended use + // is in low level code generation. + return !isDeclaration() && isDefinitionExact(); + } + + /// Return true if this global's definition can be substituted with an + /// *arbitrary* definition at link time. We cannot do any IPO or inlinining + /// across interposable call edges, since the callee can be replaced with + /// something arbitrary at link time. + bool isInterposable() const { return isInterposableLinkage(getLinkage()); } + + bool hasExternalLinkage() const { return isExternalLinkage(getLinkage()); } + bool hasAvailableExternallyLinkage() const { + return isAvailableExternallyLinkage(getLinkage()); + } + bool hasLinkOnceLinkage() const { return isLinkOnceLinkage(getLinkage()); } + bool hasLinkOnceODRLinkage() const { + return isLinkOnceODRLinkage(getLinkage()); + } + bool hasWeakLinkage() const { return isWeakLinkage(getLinkage()); } + bool hasWeakAnyLinkage() const { return isWeakAnyLinkage(getLinkage()); } + bool hasWeakODRLinkage() const { return isWeakODRLinkage(getLinkage()); } + bool hasAppendingLinkage() const { return isAppendingLinkage(getLinkage()); } + bool hasInternalLinkage() const { return isInternalLinkage(getLinkage()); } + bool hasPrivateLinkage() const { return isPrivateLinkage(getLinkage()); } + bool hasLocalLinkage() const { return isLocalLinkage(getLinkage()); } + bool hasExternalWeakLinkage() const { + return isExternalWeakLinkage(getLinkage()); + } + bool hasCommonLinkage() const { return isCommonLinkage(getLinkage()); } + bool hasValidDeclarationLinkage() const { + return isValidDeclarationLinkage(getLinkage()); + } + + void setLinkage(LinkageTypes LT) { + if (isLocalLinkage(LT)) + Visibility = DefaultVisibility; + Linkage = LT; + } + LinkageTypes getLinkage() const { return LinkageTypes(Linkage); } + + bool isDiscardableIfUnused() const { + return isDiscardableIfUnused(getLinkage()); + } + + bool isWeakForLinker() const { return isWeakForLinker(getLinkage()); } + + /// Copy all additional attributes (those not needed to create a GlobalValue) + /// from the GlobalValue Src to this one. + virtual void copyAttributesFrom(const GlobalValue *Src); + + /// If special LLVM prefix that is used to inform the asm printer to not emit + /// usual symbol prefix before the symbol name is used then return linkage + /// name after skipping this special LLVM prefix. + static StringRef getRealLinkageName(StringRef Name) { + if (!Name.empty() && Name[0] == '\1') + return Name.substr(1); + return Name; + } + + /// Return the modified name for a global value suitable to be + /// used as the key for a global lookup (e.g. profile or ThinLTO). + /// The value's original name is \c Name and has linkage of type + /// \c Linkage. The value is defined in module \c FileName. + static std::string getGlobalIdentifier(StringRef Name, + GlobalValue::LinkageTypes Linkage, + StringRef FileName); + + /// Return the modified name for this global value suitable to be + /// used as the key for a global lookup (e.g. profile or ThinLTO). + std::string getGlobalIdentifier() const; + + /// Declare a type to represent a global unique identifier for a global value. + /// This is a 64 bits hash that is used by PGO and ThinLTO to have a compact + /// unique way to identify a symbol. + using GUID = uint64_t; + + /// Return a 64-bit global unique ID constructed from global value name + /// (i.e. returned by getGlobalIdentifier()). + static GUID getGUID(StringRef GlobalName) { return MD5Hash(GlobalName); } + + /// Return a 64-bit global unique ID constructed from global value name + /// (i.e. returned by getGlobalIdentifier()). + GUID getGUID() const { return getGUID(getGlobalIdentifier()); } + + /// @name Materialization + /// Materialization is used to construct functions only as they're needed. + /// This + /// is useful to reduce memory usage in LLVM or parsing work done by the + /// BitcodeReader to load the Module. + /// @{ + + /// If this function's Module is being lazily streamed in functions from disk + /// or some other source, this method can be used to check to see if the + /// function has been read in yet or not. + bool isMaterializable() const; + + /// Make sure this GlobalValue is fully read. If the module is corrupt, this + /// returns true and fills in the optional string with information about the + /// problem. If successful, this returns false. + std::error_code materialize(); + +/// @} + + /// Return true if the primary definition of this global value is outside of + /// the current translation unit. + bool isDeclaration() const; + + bool isDeclarationForLinker() const { + if (hasAvailableExternallyLinkage()) + return true; + + return isDeclaration(); + } + + /// Returns true if this global's definition will be the one chosen by the + /// linker. + /// + /// NB! Ideally this should not be used at the IR level at all. If you're + /// interested in optimization constraints implied by the linker's ability to + /// choose an implementation, prefer using \c hasExactDefinition. + bool isStrongDefinitionForLinker() const { + return !(isDeclarationForLinker() || isWeakForLinker()); + } + + // Returns true if the alignment of the value can be unilaterally + // increased. + bool canIncreaseAlignment() const; + + /// This method unlinks 'this' from the containing module, but does not delete + /// it. + virtual void removeFromParent() = 0; + + /// This method unlinks 'this' from the containing module and deletes it. + virtual void eraseFromParent() = 0; + + /// Get the module that this global value is contained inside of... + Module *getParent() { return Parent; } + const Module *getParent() const { return Parent; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Value *V) { + return V->getValueID() == Value::FunctionVal || + V->getValueID() == Value::GlobalVariableVal || + V->getValueID() == Value::GlobalAliasVal || + V->getValueID() == Value::GlobalIFuncVal; + } +}; + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Instruction.def b/third_party/llvm-subzero/include/llvm/IR/Instruction.def new file mode 100644 index 0000000..18711ab --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/Instruction.def
@@ -0,0 +1,225 @@ +//===-- llvm/Instruction.def - File that describes Instructions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains descriptions of the various LLVM instructions. This is +// used as a central place for enumerating the different instructions and +// should eventually be the place to put comments about the instructions. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +// Provide definitions of macros so that users of this file do not have to +// define everything to use it... +// +#ifndef FIRST_TERM_INST +#define FIRST_TERM_INST(num) +#endif +#ifndef HANDLE_TERM_INST +#ifndef HANDLE_INST +#define HANDLE_TERM_INST(num, opcode, Class) +#else +#define HANDLE_TERM_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_TERM_INST +#define LAST_TERM_INST(num) +#endif + +#ifndef FIRST_BINARY_INST +#define FIRST_BINARY_INST(num) +#endif +#ifndef HANDLE_BINARY_INST +#ifndef HANDLE_INST +#define HANDLE_BINARY_INST(num, opcode, instclass) +#else +#define HANDLE_BINARY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_BINARY_INST +#define LAST_BINARY_INST(num) +#endif + +#ifndef FIRST_MEMORY_INST +#define FIRST_MEMORY_INST(num) +#endif +#ifndef HANDLE_MEMORY_INST +#ifndef HANDLE_INST +#define HANDLE_MEMORY_INST(num, opcode, Class) +#else +#define HANDLE_MEMORY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_MEMORY_INST +#define LAST_MEMORY_INST(num) +#endif + +#ifndef FIRST_CAST_INST +#define FIRST_CAST_INST(num) +#endif +#ifndef HANDLE_CAST_INST +#ifndef HANDLE_INST +#define HANDLE_CAST_INST(num, opcode, Class) +#else +#define HANDLE_CAST_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_CAST_INST +#define LAST_CAST_INST(num) +#endif + +#ifndef FIRST_FUNCLETPAD_INST +#define FIRST_FUNCLETPAD_INST(num) +#endif +#ifndef HANDLE_FUNCLETPAD_INST +#ifndef HANDLE_INST +#define HANDLE_FUNCLETPAD_INST(num, opcode, Class) +#else +#define HANDLE_FUNCLETPAD_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_FUNCLETPAD_INST +#define LAST_FUNCLETPAD_INST(num) +#endif + +#ifndef FIRST_OTHER_INST +#define FIRST_OTHER_INST(num) +#endif +#ifndef HANDLE_OTHER_INST +#ifndef HANDLE_INST +#define HANDLE_OTHER_INST(num, opcode, Class) +#else +#define HANDLE_OTHER_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_OTHER_INST +#define LAST_OTHER_INST(num) +#endif + +// Terminator Instructions - These instructions are used to terminate a basic +// block of the program. Every basic block must end with one of these +// instructions for it to be a well formed basic block. +// + FIRST_TERM_INST ( 1) +HANDLE_TERM_INST ( 1, Ret , ReturnInst) +HANDLE_TERM_INST ( 2, Br , BranchInst) +HANDLE_TERM_INST ( 3, Switch , SwitchInst) +HANDLE_TERM_INST ( 4, IndirectBr , IndirectBrInst) +HANDLE_TERM_INST ( 5, Invoke , InvokeInst) +HANDLE_TERM_INST ( 6, Resume , ResumeInst) +HANDLE_TERM_INST ( 7, Unreachable , UnreachableInst) +HANDLE_TERM_INST ( 8, CleanupRet , CleanupReturnInst) +HANDLE_TERM_INST ( 9, CatchRet , CatchReturnInst) +HANDLE_TERM_INST (10, CatchSwitch , CatchSwitchInst) + LAST_TERM_INST (10) + +// Standard binary operators... + FIRST_BINARY_INST(11) +HANDLE_BINARY_INST(11, Add , BinaryOperator) +HANDLE_BINARY_INST(12, FAdd , BinaryOperator) +HANDLE_BINARY_INST(13, Sub , BinaryOperator) +HANDLE_BINARY_INST(14, FSub , BinaryOperator) +HANDLE_BINARY_INST(15, Mul , BinaryOperator) +HANDLE_BINARY_INST(16, FMul , BinaryOperator) +HANDLE_BINARY_INST(17, UDiv , BinaryOperator) +HANDLE_BINARY_INST(18, SDiv , BinaryOperator) +HANDLE_BINARY_INST(19, FDiv , BinaryOperator) +HANDLE_BINARY_INST(20, URem , BinaryOperator) +HANDLE_BINARY_INST(21, SRem , BinaryOperator) +HANDLE_BINARY_INST(22, FRem , BinaryOperator) + +// Logical operators (integer operands) +HANDLE_BINARY_INST(23, Shl , BinaryOperator) // Shift left (logical) +HANDLE_BINARY_INST(24, LShr , BinaryOperator) // Shift right (logical) +HANDLE_BINARY_INST(25, AShr , BinaryOperator) // Shift right (arithmetic) +HANDLE_BINARY_INST(26, And , BinaryOperator) +HANDLE_BINARY_INST(27, Or , BinaryOperator) +HANDLE_BINARY_INST(28, Xor , BinaryOperator) + LAST_BINARY_INST(28) + +// Memory operators... + FIRST_MEMORY_INST(29) +HANDLE_MEMORY_INST(29, Alloca, AllocaInst) // Stack management +HANDLE_MEMORY_INST(30, Load , LoadInst ) // Memory manipulation instrs +HANDLE_MEMORY_INST(31, Store , StoreInst ) +HANDLE_MEMORY_INST(32, GetElementPtr, GetElementPtrInst) +HANDLE_MEMORY_INST(33, Fence , FenceInst ) +HANDLE_MEMORY_INST(34, AtomicCmpXchg , AtomicCmpXchgInst ) +HANDLE_MEMORY_INST(35, AtomicRMW , AtomicRMWInst ) + LAST_MEMORY_INST(35) + +// Cast operators ... +// NOTE: The order matters here because CastInst::isEliminableCastPair +// NOTE: (see Instructions.cpp) encodes a table based on this ordering. + FIRST_CAST_INST(36) +HANDLE_CAST_INST(36, Trunc , TruncInst ) // Truncate integers +HANDLE_CAST_INST(37, ZExt , ZExtInst ) // Zero extend integers +HANDLE_CAST_INST(38, SExt , SExtInst ) // Sign extend integers +HANDLE_CAST_INST(39, FPToUI , FPToUIInst ) // floating point -> UInt +HANDLE_CAST_INST(40, FPToSI , FPToSIInst ) // floating point -> SInt +HANDLE_CAST_INST(41, UIToFP , UIToFPInst ) // UInt -> floating point +HANDLE_CAST_INST(42, SIToFP , SIToFPInst ) // SInt -> floating point +HANDLE_CAST_INST(43, FPTrunc , FPTruncInst ) // Truncate floating point +HANDLE_CAST_INST(44, FPExt , FPExtInst ) // Extend floating point +HANDLE_CAST_INST(45, PtrToInt, PtrToIntInst) // Pointer -> Integer +HANDLE_CAST_INST(46, IntToPtr, IntToPtrInst) // Integer -> Pointer +HANDLE_CAST_INST(47, BitCast , BitCastInst ) // Type cast +HANDLE_CAST_INST(48, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast + LAST_CAST_INST(48) + + FIRST_FUNCLETPAD_INST(49) +HANDLE_FUNCLETPAD_INST(49, CleanupPad, CleanupPadInst) +HANDLE_FUNCLETPAD_INST(50, CatchPad , CatchPadInst) + LAST_FUNCLETPAD_INST(50) + +// Other operators... + FIRST_OTHER_INST(51) +HANDLE_OTHER_INST(51, ICmp , ICmpInst ) // Integer comparison instruction +HANDLE_OTHER_INST(52, FCmp , FCmpInst ) // Floating point comparison instr. +HANDLE_OTHER_INST(53, PHI , PHINode ) // PHI node instruction +HANDLE_OTHER_INST(54, Call , CallInst ) // Call a function +HANDLE_OTHER_INST(55, Select , SelectInst ) // select instruction +HANDLE_OTHER_INST(56, UserOp1, Instruction) // May be used internally in a pass +HANDLE_OTHER_INST(57, UserOp2, Instruction) // Internal to passes only +HANDLE_OTHER_INST(58, VAArg , VAArgInst ) // vaarg instruction +HANDLE_OTHER_INST(59, ExtractElement, ExtractElementInst)// extract from vector +HANDLE_OTHER_INST(60, InsertElement, InsertElementInst) // insert into vector +HANDLE_OTHER_INST(61, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. +HANDLE_OTHER_INST(62, ExtractValue, ExtractValueInst)// extract from aggregate +HANDLE_OTHER_INST(63, InsertValue, InsertValueInst) // insert into aggregate +HANDLE_OTHER_INST(64, LandingPad, LandingPadInst) // Landing pad instruction. + LAST_OTHER_INST(64) + +#undef FIRST_TERM_INST +#undef HANDLE_TERM_INST +#undef LAST_TERM_INST + +#undef FIRST_BINARY_INST +#undef HANDLE_BINARY_INST +#undef LAST_BINARY_INST + +#undef FIRST_MEMORY_INST +#undef HANDLE_MEMORY_INST +#undef LAST_MEMORY_INST + +#undef FIRST_CAST_INST +#undef HANDLE_CAST_INST +#undef LAST_CAST_INST + +#undef FIRST_FUNCLETPAD_INST +#undef HANDLE_FUNCLETPAD_INST +#undef LAST_FUNCLETPAD_INST + +#undef FIRST_OTHER_INST +#undef HANDLE_OTHER_INST +#undef LAST_OTHER_INST + +#ifdef HANDLE_INST +#undef HANDLE_INST +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Instruction.h b/third_party/llvm-subzero/include/llvm/IR/Instruction.h new file mode 100644 index 0000000..027d9f3 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/Instruction.h
@@ -0,0 +1,599 @@ +//===-- llvm/Instruction.h - Instruction class definition -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Instruction class, which is the +// base class for all of the LLVM instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_INSTRUCTION_H +#define LLVM_IR_INSTRUCTION_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/IR/DebugLoc.h" +#include "llvm/IR/SymbolTableListTraits.h" +#include "llvm/IR/User.h" + +namespace llvm { + +class FastMathFlags; +class LLVMContext; +class MDNode; +class BasicBlock; +struct AAMDNodes; + +class Instruction : public User, + public ilist_node_with_parent<Instruction, BasicBlock> { + void operator=(const Instruction &) = delete; + Instruction(const Instruction &) = delete; + + BasicBlock *Parent; + DebugLoc DbgLoc; // 'dbg' Metadata cache. + + enum { + /// This is a bit stored in the SubClassData field which indicates whether + /// this instruction has metadata attached to it or not. + HasMetadataBit = 1 << 15 + }; +public: + // Out of line virtual method, so the vtable, etc has a home. + ~Instruction() override; + + /// Specialize the methods defined in Value, as we know that an instruction + /// can only be used by other instructions. + Instruction *user_back() { return cast<Instruction>(*user_begin());} + const Instruction *user_back() const { return cast<Instruction>(*user_begin());} + + inline const BasicBlock *getParent() const { return Parent; } + inline BasicBlock *getParent() { return Parent; } + + /// Return the module owning the function this instruction belongs to + /// or nullptr it the function does not have a module. + /// + /// Note: this is undefined behavior if the instruction does not have a + /// parent, or the parent basic block does not have a parent function. + const Module *getModule() const; + Module *getModule(); + + /// Return the function this instruction belongs to. + /// + /// Note: it is undefined behavior to call this on an instruction not + /// currently inserted into a function. + const Function *getFunction() const; + Function *getFunction(); + + /// This method unlinks 'this' from the containing basic block, but does not + /// delete it. + void removeFromParent(); + + /// This method unlinks 'this' from the containing basic block and deletes it. + /// + /// \returns an iterator pointing to the element after the erased one + SymbolTableList<Instruction>::iterator eraseFromParent(); + + /// Insert an unlinked instruction into a basic block immediately before + /// the specified instruction. + void insertBefore(Instruction *InsertPos); + + /// Insert an unlinked instruction into a basic block immediately after the + /// specified instruction. + void insertAfter(Instruction *InsertPos); + + /// Unlink this instruction from its current basic block and insert it into + /// the basic block that MovePos lives in, right before MovePos. + void moveBefore(Instruction *MovePos); + + /// Unlink this instruction and insert into BB before I. + /// + /// \pre I is a valid iterator into BB. + void moveBefore(BasicBlock &BB, SymbolTableList<Instruction>::iterator I); + + //===--------------------------------------------------------------------===// + // Subclass classification. + //===--------------------------------------------------------------------===// + + /// Returns a member of one of the enums like Instruction::Add. + unsigned getOpcode() const { return getValueID() - InstructionVal; } + + const char *getOpcodeName() const { return getOpcodeName(getOpcode()); } + bool isTerminator() const { return isTerminator(getOpcode()); } + bool isBinaryOp() const { return isBinaryOp(getOpcode()); } + bool isShift() { return isShift(getOpcode()); } + bool isCast() const { return isCast(getOpcode()); } + bool isFuncletPad() const { return isFuncletPad(getOpcode()); } + + static const char* getOpcodeName(unsigned OpCode); + + static inline bool isTerminator(unsigned OpCode) { + return OpCode >= TermOpsBegin && OpCode < TermOpsEnd; + } + + static inline bool isBinaryOp(unsigned Opcode) { + return Opcode >= BinaryOpsBegin && Opcode < BinaryOpsEnd; + } + + /// Determine if the Opcode is one of the shift instructions. + static inline bool isShift(unsigned Opcode) { + return Opcode >= Shl && Opcode <= AShr; + } + + /// Return true if this is a logical shift left or a logical shift right. + inline bool isLogicalShift() const { + return getOpcode() == Shl || getOpcode() == LShr; + } + + /// Return true if this is an arithmetic shift right. + inline bool isArithmeticShift() const { + return getOpcode() == AShr; + } + + /// Determine if the OpCode is one of the CastInst instructions. + static inline bool isCast(unsigned OpCode) { + return OpCode >= CastOpsBegin && OpCode < CastOpsEnd; + } + + /// Determine if the OpCode is one of the FuncletPadInst instructions. + static inline bool isFuncletPad(unsigned OpCode) { + return OpCode >= FuncletPadOpsBegin && OpCode < FuncletPadOpsEnd; + } + + //===--------------------------------------------------------------------===// + // Metadata manipulation. + //===--------------------------------------------------------------------===// + + /// Return true if this instruction has any metadata attached to it. + bool hasMetadata() const { return DbgLoc || hasMetadataHashEntry(); } + + /// Return true if this instruction has metadata attached to it other than a + /// debug location. + bool hasMetadataOtherThanDebugLoc() const { + return hasMetadataHashEntry(); + } + + /// Get the metadata of given kind attached to this Instruction. + /// If the metadata is not found then return null. + MDNode *getMetadata(unsigned KindID) const { + if (!hasMetadata()) return nullptr; + return getMetadataImpl(KindID); + } + + /// Get the metadata of given kind attached to this Instruction. + /// If the metadata is not found then return null. + MDNode *getMetadata(StringRef Kind) const { + if (!hasMetadata()) return nullptr; + return getMetadataImpl(Kind); + } + + /// Get all metadata attached to this Instruction. The first element of each + /// pair returned is the KindID, the second element is the metadata value. + /// This list is returned sorted by the KindID. + void + getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const { + if (hasMetadata()) + getAllMetadataImpl(MDs); + } + + /// This does the same thing as getAllMetadata, except that it filters out the + /// debug location. + void getAllMetadataOtherThanDebugLoc( + SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const { + if (hasMetadataOtherThanDebugLoc()) + getAllMetadataOtherThanDebugLocImpl(MDs); + } + + /// Fills the AAMDNodes structure with AA metadata from this instruction. + /// When Merge is true, the existing AA metadata is merged with that from this + /// instruction providing the most-general result. + void getAAMetadata(AAMDNodes &N, bool Merge = false) const; + + /// Set the metadata of the specified kind to the specified node. This updates + /// or replaces metadata if already present, or removes it if Node is null. + void setMetadata(unsigned KindID, MDNode *Node); + void setMetadata(StringRef Kind, MDNode *Node); + + /// Copy metadata from \p SrcInst to this instruction. \p WL, if not empty, + /// specifies the list of meta data that needs to be copied. If \p WL is + /// empty, all meta data will be copied. + void copyMetadata(const Instruction &SrcInst, + ArrayRef<unsigned> WL = ArrayRef<unsigned>()); + + /// If the instruction has "branch_weights" MD_prof metadata and the MDNode + /// has three operands (including name string), swap the order of the + /// metadata. + void swapProfMetadata(); + + /// Drop all unknown metadata except for debug locations. + /// @{ + /// Passes are required to drop metadata they don't understand. This is a + /// convenience method for passes to do so. + void dropUnknownNonDebugMetadata(ArrayRef<unsigned> KnownIDs); + void dropUnknownNonDebugMetadata() { + return dropUnknownNonDebugMetadata(None); + } + void dropUnknownNonDebugMetadata(unsigned ID1) { + return dropUnknownNonDebugMetadata(makeArrayRef(ID1)); + } + void dropUnknownNonDebugMetadata(unsigned ID1, unsigned ID2) { + unsigned IDs[] = {ID1, ID2}; + return dropUnknownNonDebugMetadata(IDs); + } + /// @} + + /// Sets the metadata on this instruction from the AAMDNodes structure. + void setAAMetadata(const AAMDNodes &N); + + /// Retrieve the raw weight values of a conditional branch or select. + /// Returns true on success with profile weights filled in. + /// Returns false if no metadata or invalid metadata was found. + bool extractProfMetadata(uint64_t &TrueVal, uint64_t &FalseVal); + + /// Retrieve total raw weight values of a branch. + /// Returns true on success with profile total weights filled in. + /// Returns false if no metadata was found. + bool extractProfTotalWeight(uint64_t &TotalVal); + + /// Set the debug location information for this instruction. + void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc); } + + /// Return the debug location for this node as a DebugLoc. + const DebugLoc &getDebugLoc() const { return DbgLoc; } + + /// Set or clear the nsw flag on this instruction, which must be an operator + /// which supports this flag. See LangRef.html for the meaning of this flag. + void setHasNoUnsignedWrap(bool b = true); + + /// Set or clear the nsw flag on this instruction, which must be an operator + /// which supports this flag. See LangRef.html for the meaning of this flag. + void setHasNoSignedWrap(bool b = true); + + /// Set or clear the exact flag on this instruction, which must be an operator + /// which supports this flag. See LangRef.html for the meaning of this flag. + void setIsExact(bool b = true); + + /// Determine whether the no unsigned wrap flag is set. + bool hasNoUnsignedWrap() const; + + /// Determine whether the no signed wrap flag is set. + bool hasNoSignedWrap() const; + + /// Determine whether the exact flag is set. + bool isExact() const; + + /// Set or clear the unsafe-algebra flag on this instruction, which must be an + /// operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasUnsafeAlgebra(bool B); + + /// Set or clear the no-nans flag on this instruction, which must be an + /// operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasNoNaNs(bool B); + + /// Set or clear the no-infs flag on this instruction, which must be an + /// operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasNoInfs(bool B); + + /// Set or clear the no-signed-zeros flag on this instruction, which must be + /// an operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasNoSignedZeros(bool B); + + /// Set or clear the allow-reciprocal flag on this instruction, which must be + /// an operator which supports this flag. See LangRef.html for the meaning of + /// this flag. + void setHasAllowReciprocal(bool B); + + /// Convenience function for setting multiple fast-math flags on this + /// instruction, which must be an operator which supports these flags. See + /// LangRef.html for the meaning of these flags. + void setFastMathFlags(FastMathFlags FMF); + + /// Convenience function for transferring all fast-math flag values to this + /// instruction, which must be an operator which supports these flags. See + /// LangRef.html for the meaning of these flags. + void copyFastMathFlags(FastMathFlags FMF); + + /// Determine whether the unsafe-algebra flag is set. + bool hasUnsafeAlgebra() const; + + /// Determine whether the no-NaNs flag is set. + bool hasNoNaNs() const; + + /// Determine whether the no-infs flag is set. + bool hasNoInfs() const; + + /// Determine whether the no-signed-zeros flag is set. + bool hasNoSignedZeros() const; + + /// Determine whether the allow-reciprocal flag is set. + bool hasAllowReciprocal() const; + + /// Convenience function for getting all the fast-math flags, which must be an + /// operator which supports these flags. See LangRef.html for the meaning of + /// these flags. + FastMathFlags getFastMathFlags() const; + + /// Copy I's fast-math flags + void copyFastMathFlags(const Instruction *I); + + /// Convenience method to copy supported wrapping, exact, and fast-math flags + /// from V to this instruction. + void copyIRFlags(const Value *V); + + /// Logical 'and' of any supported wrapping, exact, and fast-math flags of + /// V and this instruction. + void andIRFlags(const Value *V); + +private: + /// Return true if we have an entry in the on-the-side metadata hash. + bool hasMetadataHashEntry() const { + return (getSubclassDataFromValue() & HasMetadataBit) != 0; + } + + // These are all implemented in Metadata.cpp. + MDNode *getMetadataImpl(unsigned KindID) const; + MDNode *getMetadataImpl(StringRef Kind) const; + void + getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned, MDNode *>> &) const; + void getAllMetadataOtherThanDebugLocImpl( + SmallVectorImpl<std::pair<unsigned, MDNode *>> &) const; + /// Clear all hashtable-based metadata from this instruction. + void clearMetadataHashEntries(); +public: + //===--------------------------------------------------------------------===// + // Predicates and helper methods. + //===--------------------------------------------------------------------===// + + + /// Return true if the instruction is associative: + /// + /// Associative operators satisfy: x op (y op z) === (x op y) op z + /// + /// In LLVM, the Add, Mul, And, Or, and Xor operators are associative. + /// + bool isAssociative() const; + static bool isAssociative(unsigned op); + + /// Return true if the instruction is commutative: + /// + /// Commutative operators satisfy: (x op y) === (y op x) + /// + /// In LLVM, these are the associative operators, plus SetEQ and SetNE, when + /// applied to any type. + /// + bool isCommutative() const { return isCommutative(getOpcode()); } + static bool isCommutative(unsigned op); + + /// Return true if the instruction is idempotent: + /// + /// Idempotent operators satisfy: x op x === x + /// + /// In LLVM, the And and Or operators are idempotent. + /// + bool isIdempotent() const { return isIdempotent(getOpcode()); } + static bool isIdempotent(unsigned op); + + /// Return true if the instruction is nilpotent: + /// + /// Nilpotent operators satisfy: x op x === Id, + /// + /// where Id is the identity for the operator, i.e. a constant such that + /// x op Id === x and Id op x === x for all x. + /// + /// In LLVM, the Xor operator is nilpotent. + /// + bool isNilpotent() const { return isNilpotent(getOpcode()); } + static bool isNilpotent(unsigned op); + + /// Return true if this instruction may modify memory. + bool mayWriteToMemory() const; + + /// Return true if this instruction may read memory. + bool mayReadFromMemory() const; + + /// Return true if this instruction may read or write memory. + bool mayReadOrWriteMemory() const { + return mayReadFromMemory() || mayWriteToMemory(); + } + + /// Return true if this instruction has an AtomicOrdering of unordered or + /// higher. + bool isAtomic() const; + + /// Return true if this instruction may throw an exception. + bool mayThrow() const; + + /// Return true if this instruction behaves like a memory fence: it can load + /// or store to memory location without being given a memory location. + bool isFenceLike() const { + switch (getOpcode()) { + default: + return false; + // This list should be kept in sync with the list in mayWriteToMemory for + // all opcodes which don't have a memory location. + case Instruction::Fence: + case Instruction::CatchPad: + case Instruction::CatchRet: + case Instruction::Call: + case Instruction::Invoke: + return true; + } + } + + /// Return true if the instruction may have side effects. + /// + /// Note that this does not consider malloc and alloca to have side + /// effects because the newly allocated memory is completely invisible to + /// instructions which don't use the returned value. For cases where this + /// matters, isSafeToSpeculativelyExecute may be more appropriate. + bool mayHaveSideEffects() const { return mayWriteToMemory() || mayThrow(); } + + /// Return true if the instruction is a variety of EH-block. + bool isEHPad() const { + switch (getOpcode()) { + case Instruction::CatchSwitch: + case Instruction::CatchPad: + case Instruction::CleanupPad: + case Instruction::LandingPad: + return true; + default: + return false; + } + } + + /// Create a copy of 'this' instruction that is identical in all ways except + /// the following: + /// * The instruction has no parent + /// * The instruction has no name + /// + Instruction *clone() const; + + /// Return true if the specified instruction is exactly identical to the + /// current one. This means that all operands match and any extra information + /// (e.g. load is volatile) agree. + bool isIdenticalTo(const Instruction *I) const; + + /// This is like isIdenticalTo, except that it ignores the + /// SubclassOptionalData flags, which specify conditions under which the + /// instruction's result is undefined. + bool isIdenticalToWhenDefined(const Instruction *I) const; + + /// When checking for operation equivalence (using isSameOperationAs) it is + /// sometimes useful to ignore certain attributes. + enum OperationEquivalenceFlags { + /// Check for equivalence ignoring load/store alignment. + CompareIgnoringAlignment = 1<<0, + /// Check for equivalence treating a type and a vector of that type + /// as equivalent. + CompareUsingScalarTypes = 1<<1 + }; + + /// This function determines if the specified instruction executes the same + /// operation as the current one. This means that the opcodes, type, operand + /// types and any other factors affecting the operation must be the same. This + /// is similar to isIdenticalTo except the operands themselves don't have to + /// be identical. + /// @returns true if the specified instruction is the same operation as + /// the current one. + /// @brief Determine if one instruction is the same operation as another. + bool isSameOperationAs(const Instruction *I, unsigned flags = 0) const; + + /// Return true if there are any uses of this instruction in blocks other than + /// the specified block. Note that PHI nodes are considered to evaluate their + /// operands in the corresponding predecessor block. + bool isUsedOutsideOfBlock(const BasicBlock *BB) const; + + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return V->getValueID() >= Value::InstructionVal; + } + + //---------------------------------------------------------------------- + // Exported enumerations. + // + enum TermOps { // These terminate basic blocks +#define FIRST_TERM_INST(N) TermOpsBegin = N, +#define HANDLE_TERM_INST(N, OPC, CLASS) OPC = N, +#define LAST_TERM_INST(N) TermOpsEnd = N+1 +#include "llvm/IR/Instruction.def" + }; + + enum BinaryOps { +#define FIRST_BINARY_INST(N) BinaryOpsBegin = N, +#define HANDLE_BINARY_INST(N, OPC, CLASS) OPC = N, +#define LAST_BINARY_INST(N) BinaryOpsEnd = N+1 +#include "llvm/IR/Instruction.def" + }; + + enum MemoryOps { +#define FIRST_MEMORY_INST(N) MemoryOpsBegin = N, +#define HANDLE_MEMORY_INST(N, OPC, CLASS) OPC = N, +#define LAST_MEMORY_INST(N) MemoryOpsEnd = N+1 +#include "llvm/IR/Instruction.def" + }; + + enum CastOps { +#define FIRST_CAST_INST(N) CastOpsBegin = N, +#define HANDLE_CAST_INST(N, OPC, CLASS) OPC = N, +#define LAST_CAST_INST(N) CastOpsEnd = N+1 +#include "llvm/IR/Instruction.def" + }; + + enum FuncletPadOps { +#define FIRST_FUNCLETPAD_INST(N) FuncletPadOpsBegin = N, +#define HANDLE_FUNCLETPAD_INST(N, OPC, CLASS) OPC = N, +#define LAST_FUNCLETPAD_INST(N) FuncletPadOpsEnd = N+1 +#include "llvm/IR/Instruction.def" + }; + + enum OtherOps { +#define FIRST_OTHER_INST(N) OtherOpsBegin = N, +#define HANDLE_OTHER_INST(N, OPC, CLASS) OPC = N, +#define LAST_OTHER_INST(N) OtherOpsEnd = N+1 +#include "llvm/IR/Instruction.def" + }; +private: + // Shadow Value::setValueSubclassData with a private forwarding method so that + // subclasses cannot accidentally use it. + void setValueSubclassData(unsigned short D) { + Value::setValueSubclassData(D); + } + unsigned short getSubclassDataFromValue() const { + return Value::getSubclassDataFromValue(); + } + + void setHasMetadataHashEntry(bool V) { + setValueSubclassData((getSubclassDataFromValue() & ~HasMetadataBit) | + (V ? HasMetadataBit : 0)); + } + + friend class SymbolTableListTraits<Instruction>; + void setParent(BasicBlock *P); +protected: + // Instruction subclasses can stick up to 15 bits of stuff into the + // SubclassData field of instruction with these members. + + // Verify that only the low 15 bits are used. + void setInstructionSubclassData(unsigned short D) { + assert((D & HasMetadataBit) == 0 && "Out of range value put into field"); + setValueSubclassData((getSubclassDataFromValue() & HasMetadataBit) | D); + } + + unsigned getSubclassDataFromInstruction() const { + return getSubclassDataFromValue() & ~HasMetadataBit; + } + + Instruction(Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, + Instruction *InsertBefore = nullptr); + Instruction(Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, + BasicBlock *InsertAtEnd); + +private: + /// Create a copy of this instruction. + Instruction *cloneImpl() const; +}; + +// Instruction* is only 4-byte aligned. +template<> +class PointerLikeTypeTraits<Instruction*> { + typedef Instruction* PT; +public: + static inline void *getAsVoidPointer(PT P) { return P; } + static inline PT getFromVoidPointer(void *P) { + return static_cast<PT>(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/LLVMContext.h b/third_party/llvm-subzero/include/llvm/IR/LLVMContext.h new file mode 100644 index 0000000..dbf2b45 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/LLVMContext.h
@@ -0,0 +1,276 @@ +//===-- llvm/LLVMContext.h - Class for managing "global" state --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares LLVMContext, a container of "global" state in LLVM, such +// as the global type and constant uniquing tables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_LLVMCONTEXT_H +#define LLVM_IR_LLVMCONTEXT_H + +#include "llvm/Support/CBindingWrapping.h" +#include "llvm/Support/Options.h" + +namespace llvm { + +class LLVMContextImpl; +class StringRef; +class Twine; +class Instruction; +class Module; +class MDString; +class DICompositeType; +class SMDiagnostic; +class DiagnosticInfo; +enum DiagnosticSeverity : char; +template <typename T> class SmallVectorImpl; +class Function; +class DebugLoc; +class OptBisect; + +/// This is an important class for using LLVM in a threaded context. It +/// (opaquely) owns and manages the core "global" data of LLVM's core +/// infrastructure, including the type and constant uniquing tables. +/// LLVMContext itself provides no locking guarantees, so you should be careful +/// to have one context per thread. +class LLVMContext { +public: + LLVMContextImpl *const pImpl; + LLVMContext(); + ~LLVMContext(); + + // Pinned metadata names, which always have the same value. This is a + // compile-time performance optimization, not a correctness optimization. + enum { + MD_dbg = 0, // "dbg" + MD_tbaa = 1, // "tbaa" + MD_prof = 2, // "prof" + MD_fpmath = 3, // "fpmath" + MD_range = 4, // "range" + MD_tbaa_struct = 5, // "tbaa.struct" + MD_invariant_load = 6, // "invariant.load" + MD_alias_scope = 7, // "alias.scope" + MD_noalias = 8, // "noalias", + MD_nontemporal = 9, // "nontemporal" + MD_mem_parallel_loop_access = 10, // "llvm.mem.parallel_loop_access" + MD_nonnull = 11, // "nonnull" + MD_dereferenceable = 12, // "dereferenceable" + MD_dereferenceable_or_null = 13, // "dereferenceable_or_null" + MD_make_implicit = 14, // "make.implicit" + MD_unpredictable = 15, // "unpredictable" + MD_invariant_group = 16, // "invariant.group" + MD_align = 17, // "align" + MD_loop = 18, // "llvm.loop" + MD_type = 19, // "type" + }; + + /// Known operand bundle tag IDs, which always have the same value. All + /// operand bundle tags that LLVM has special knowledge of are listed here. + /// Additionally, this scheme allows LLVM to efficiently check for specific + /// operand bundle tags without comparing strings. + enum { + OB_deopt = 0, // "deopt" + OB_funclet = 1, // "funclet" + OB_gc_transition = 2, // "gc-transition" + }; + + /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. + /// This ID is uniqued across modules in the current LLVMContext. + unsigned getMDKindID(StringRef Name) const; + + /// getMDKindNames - Populate client supplied SmallVector with the name for + /// custom metadata IDs registered in this LLVMContext. + void getMDKindNames(SmallVectorImpl<StringRef> &Result) const; + + /// getOperandBundleTags - Populate client supplied SmallVector with the + /// bundle tags registered in this LLVMContext. The bundle tags are ordered + /// by increasing bundle IDs. + /// \see LLVMContext::getOperandBundleTagID + void getOperandBundleTags(SmallVectorImpl<StringRef> &Result) const; + + /// getOperandBundleTagID - Maps a bundle tag to an integer ID. Every bundle + /// tag registered with an LLVMContext has an unique ID. + uint32_t getOperandBundleTagID(StringRef Tag) const; + + /// Define the GC for a function + void setGC(const Function &Fn, std::string GCName); + + /// Return the GC for a function + const std::string &getGC(const Function &Fn); + + /// Remove the GC for a function + void deleteGC(const Function &Fn); + + /// Return true if the Context runtime configuration is set to discard all + /// value names. When true, only GlobalValue names will be available in the + /// IR. + bool shouldDiscardValueNames() const; + + /// Set the Context runtime configuration to discard all value name (but + /// GlobalValue). Clients can use this flag to save memory and runtime, + /// especially in release mode. + void setDiscardValueNames(bool Discard); + + /// Whether there is a string map for uniquing debug info + /// identifiers across the context. Off by default. + bool isODRUniquingDebugTypes() const; + void enableDebugTypeODRUniquing(); + void disableDebugTypeODRUniquing(); + + typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context, + unsigned LocCookie); + + /// Defines the type of a diagnostic handler. + /// \see LLVMContext::setDiagnosticHandler. + /// \see LLVMContext::diagnose. + typedef void (*DiagnosticHandlerTy)(const DiagnosticInfo &DI, void *Context); + + /// Defines the type of a yield callback. + /// \see LLVMContext::setYieldCallback. + typedef void (*YieldCallbackTy)(LLVMContext *Context, void *OpaqueHandle); + + /// setInlineAsmDiagnosticHandler - This method sets a handler that is invoked + /// when problems with inline asm are detected by the backend. The first + /// argument is a function pointer and the second is a context pointer that + /// gets passed into the DiagHandler. + /// + /// LLVMContext doesn't take ownership or interpret either of these + /// pointers. + void setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler, + void *DiagContext = nullptr); + + /// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by + /// setInlineAsmDiagnosticHandler. + InlineAsmDiagHandlerTy getInlineAsmDiagnosticHandler() const; + + /// getInlineAsmDiagnosticContext - Return the diagnostic context set by + /// setInlineAsmDiagnosticHandler. + void *getInlineAsmDiagnosticContext() const; + + /// setDiagnosticHandler - This method sets a handler that is invoked + /// when the backend needs to report anything to the user. The first + /// argument is a function pointer and the second is a context pointer that + /// gets passed into the DiagHandler. The third argument should be set to + /// true if the handler only expects enabled diagnostics. + /// + /// LLVMContext doesn't take ownership or interpret either of these + /// pointers. + void setDiagnosticHandler(DiagnosticHandlerTy DiagHandler, + void *DiagContext = nullptr, + bool RespectFilters = false); + + /// getDiagnosticHandler - Return the diagnostic handler set by + /// setDiagnosticHandler. + DiagnosticHandlerTy getDiagnosticHandler() const; + + /// getDiagnosticContext - Return the diagnostic context set by + /// setDiagnosticContext. + void *getDiagnosticContext() const; + + /// \brief Return if a code hotness metric should be included in optimization + /// diagnostics. + bool getDiagnosticHotnessRequested() const; + /// \brief Set if a code hotness metric should be included in optimization + /// diagnostics. + void setDiagnosticHotnessRequested(bool Requested); + + /// \brief Get the prefix that should be printed in front of a diagnostic of + /// the given \p Severity + static const char *getDiagnosticMessagePrefix(DiagnosticSeverity Severity); + + /// \brief Report a message to the currently installed diagnostic handler. + /// + /// This function returns, in particular in the case of error reporting + /// (DI.Severity == \a DS_Error), so the caller should leave the compilation + /// process in a self-consistent state, even though the generated code + /// need not be correct. + /// + /// The diagnostic message will be implicitly prefixed with a severity keyword + /// according to \p DI.getSeverity(), i.e., "error: " for \a DS_Error, + /// "warning: " for \a DS_Warning, and "note: " for \a DS_Note. + void diagnose(const DiagnosticInfo &DI); + + /// \brief Registers a yield callback with the given context. + /// + /// The yield callback function may be called by LLVM to transfer control back + /// to the client that invoked the LLVM compilation. This can be used to yield + /// control of the thread, or perform periodic work needed by the client. + /// There is no guaranteed frequency at which callbacks must occur; in fact, + /// the client is not guaranteed to ever receive this callback. It is at the + /// sole discretion of LLVM to do so and only if it can guarantee that + /// suspending the thread won't block any forward progress in other LLVM + /// contexts in the same process. + /// + /// At a suspend point, the state of the current LLVM context is intentionally + /// undefined. No assumptions about it can or should be made. Only LLVM + /// context API calls that explicitly state that they can be used during a + /// yield callback are allowed to be used. Any other API calls into the + /// context are not supported until the yield callback function returns + /// control to LLVM. Other LLVM contexts are unaffected by this restriction. + void setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle); + + /// \brief Calls the yield callback (if applicable). + /// + /// This transfers control of the current thread back to the client, which may + /// suspend the current thread. Only call this method when LLVM doesn't hold + /// any global mutex or cannot block the execution in another LLVM context. + void yield(); + + /// emitError - Emit an error message to the currently installed error handler + /// with optional location information. This function returns, so code should + /// be prepared to drop the erroneous construct on the floor and "not crash". + /// The generated code need not be correct. The error message will be + /// implicitly prefixed with "error: " and should not end with a ".". + void emitError(unsigned LocCookie, const Twine &ErrorStr); + void emitError(const Instruction *I, const Twine &ErrorStr); + void emitError(const Twine &ErrorStr); + + /// \brief Query for a debug option's value. + /// + /// This function returns typed data populated from command line parsing. + template <typename ValT, typename Base, ValT(Base::*Mem)> + ValT getOption() const { + return OptionRegistry::instance().template get<ValT, Base, Mem>(); + } + + /// \brief Access the object which manages optimization bisection for failure + /// analysis. + OptBisect &getOptBisect(); +private: + LLVMContext(LLVMContext&) = delete; + void operator=(LLVMContext&) = delete; + + /// addModule - Register a module as being instantiated in this context. If + /// the context is deleted, the module will be deleted as well. + void addModule(Module*); + + /// removeModule - Unregister a module from this context. + void removeModule(Module*); + + // Module needs access to the add/removeModule methods. + friend class Module; +}; + +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMContext, LLVMContextRef) + +/* Specialized opaque context conversions. + */ +inline LLVMContext **unwrap(LLVMContextRef* Tys) { + return reinterpret_cast<LLVMContext**>(Tys); +} + +inline LLVMContextRef *wrap(const LLVMContext **Tys) { + return reinterpret_cast<LLVMContextRef*>(const_cast<LLVMContext**>(Tys)); +} + +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Metadata.def b/third_party/llvm-subzero/include/llvm/IR/Metadata.def new file mode 100644 index 0000000..607f5ef --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/Metadata.def
@@ -0,0 +1,124 @@ +//===- llvm/IR/Metadata.def - Metadata definitions --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Macros for running through all types of metadata. +// +//===----------------------------------------------------------------------===// + +#if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF || \ + defined HANDLE_METADATA_BRANCH || defined HANDLE_MDNODE_LEAF || \ + defined HANDLE_MDNODE_LEAF_UNIQUABLE || defined HANDLE_MDNODE_BRANCH || \ + defined HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE || \ + defined HANDLE_SPECIALIZED_MDNODE_LEAF || \ + defined HANDLE_SPECIALIZED_MDNODE_BRANCH) +#error "Missing macro definition of HANDLE_METADATA*" +#endif + +// Handler for all types of metadata. +#ifndef HANDLE_METADATA +#define HANDLE_METADATA(CLASS) +#endif + +// Handler for leaf nodes in the class hierarchy. +#ifndef HANDLE_METADATA_LEAF +#define HANDLE_METADATA_LEAF(CLASS) HANDLE_METADATA(CLASS) +#endif + +// Handler for non-leaf nodes in the class hierarchy. +#ifndef HANDLE_METADATA_BRANCH +#define HANDLE_METADATA_BRANCH(CLASS) HANDLE_METADATA(CLASS) +#endif + +// Handler for specialized and uniquable leaf nodes under MDNode. Defers to +// HANDLE_MDNODE_LEAF_UNIQUABLE if it's defined, otherwise to +// HANDLE_SPECIALIZED_MDNODE_LEAF. +#ifndef HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE +#ifdef HANDLE_MDNODE_LEAF_UNIQUABLE +#define HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(CLASS) \ + HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) +#else +#define HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(CLASS) \ + HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) +#endif +#endif + +// Handler for leaf nodes under MDNode. +#ifndef HANDLE_MDNODE_LEAF_UNIQUABLE +#define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) HANDLE_MDNODE_LEAF(CLASS) +#endif + +// Handler for leaf nodes under MDNode. +#ifndef HANDLE_MDNODE_LEAF +#define HANDLE_MDNODE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS) +#endif + +// Handler for non-leaf nodes under MDNode. +#ifndef HANDLE_MDNODE_BRANCH +#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS) +#endif + +// Handler for specialized leaf nodes under MDNode. +#ifndef HANDLE_SPECIALIZED_MDNODE_LEAF +#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) HANDLE_MDNODE_LEAF(CLASS) +#endif + +// Handler for specialized non-leaf nodes under MDNode. +#ifndef HANDLE_SPECIALIZED_MDNODE_BRANCH +#define HANDLE_SPECIALIZED_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_BRANCH(CLASS) +#endif + +HANDLE_METADATA_LEAF(MDString) +HANDLE_METADATA_BRANCH(ValueAsMetadata) +HANDLE_METADATA_LEAF(ConstantAsMetadata) +HANDLE_METADATA_LEAF(LocalAsMetadata) +HANDLE_METADATA_LEAF(DistinctMDOperandPlaceholder) +HANDLE_MDNODE_BRANCH(MDNode) +HANDLE_MDNODE_LEAF_UNIQUABLE(MDTuple) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocation) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIExpression) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DINode) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(GenericDINode) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubrange) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIEnumerator) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DIScope) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DIType) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIBasicType) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIDerivedType) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICompositeType) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubroutineType) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIFile) +HANDLE_SPECIALIZED_MDNODE_LEAF(DICompileUnit) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DILocalScope) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubprogram) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DILexicalBlockBase) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILexicalBlock) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILexicalBlockFile) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DINamespace) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIModule) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DITemplateParameter) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DITemplateTypeParameter) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DITemplateValueParameter) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DIVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGlobalVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocalVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIObjCProperty) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIImportedEntity) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DIMacroNode) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacro) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacroFile) + +#undef HANDLE_METADATA +#undef HANDLE_METADATA_LEAF +#undef HANDLE_METADATA_BRANCH +#undef HANDLE_MDNODE_LEAF +#undef HANDLE_MDNODE_LEAF_UNIQUABLE +#undef HANDLE_MDNODE_BRANCH +#undef HANDLE_SPECIALIZED_MDNODE_LEAF +#undef HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE +#undef HANDLE_SPECIALIZED_MDNODE_BRANCH
diff --git a/third_party/llvm-subzero/include/llvm/IR/Metadata.h b/third_party/llvm-subzero/include/llvm/IR/Metadata.h new file mode 100644 index 0000000..0ce8882 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/Metadata.h
@@ -0,0 +1,1342 @@ +//===- llvm/IR/Metadata.h - Metadata definitions ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// This file contains the declarations for metadata subclasses. +/// They represent the different flavors of metadata that live in LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_METADATA_H +#define LLVM_IR_METADATA_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Value.h" +#include "llvm/Support/ErrorHandling.h" +#include <type_traits> + +namespace llvm { + +class LLVMContext; +class Module; +class ModuleSlotTracker; + +enum LLVMConstants : uint32_t { + DEBUG_METADATA_VERSION = 3 // Current debug info version number. +}; + +/// \brief Root of the metadata hierarchy. +/// +/// This is a root class for typeless data in the IR. +class Metadata { + friend class ReplaceableMetadataImpl; + + /// \brief RTTI. + const unsigned char SubclassID; + +protected: + /// \brief Active type of storage. + enum StorageType { Uniqued, Distinct, Temporary }; + + /// \brief Storage flag for non-uniqued, otherwise unowned, metadata. + unsigned char Storage; + // TODO: expose remaining bits to subclasses. + + unsigned short SubclassData16; + unsigned SubclassData32; + +public: + enum MetadataKind { +#define HANDLE_METADATA_LEAF(CLASS) CLASS##Kind, +#include "llvm/IR/Metadata.def" + }; + +protected: + Metadata(unsigned ID, StorageType Storage) + : SubclassID(ID), Storage(Storage), SubclassData16(0), SubclassData32(0) { + static_assert(sizeof(*this) == 8, "Metdata fields poorly packed"); + } + ~Metadata() = default; + + /// \brief Default handling of a changed operand, which asserts. + /// + /// If subclasses pass themselves in as owners to a tracking node reference, + /// they must provide an implementation of this method. + void handleChangedOperand(void *, Metadata *) { + llvm_unreachable("Unimplemented in Metadata subclass"); + } + +public: + unsigned getMetadataID() const { return SubclassID; } + + /// \brief User-friendly dump. + /// + /// If \c M is provided, metadata nodes will be numbered canonically; + /// otherwise, pointer addresses are substituted. + /// + /// Note: this uses an explicit overload instead of default arguments so that + /// the nullptr version is easy to call from a debugger. + /// + /// @{ + void dump() const; + void dump(const Module *M) const; + /// @} + + /// \brief Print. + /// + /// Prints definition of \c this. + /// + /// If \c M is provided, metadata nodes will be numbered canonically; + /// otherwise, pointer addresses are substituted. + /// @{ + void print(raw_ostream &OS, const Module *M = nullptr, + bool IsForDebug = false) const; + void print(raw_ostream &OS, ModuleSlotTracker &MST, const Module *M = nullptr, + bool IsForDebug = false) const; + /// @} + + /// \brief Print as operand. + /// + /// Prints reference of \c this. + /// + /// If \c M is provided, metadata nodes will be numbered canonically; + /// otherwise, pointer addresses are substituted. + /// @{ + void printAsOperand(raw_ostream &OS, const Module *M = nullptr) const; + void printAsOperand(raw_ostream &OS, ModuleSlotTracker &MST, + const Module *M = nullptr) const; + /// @} +}; + +#define HANDLE_METADATA(CLASS) class CLASS; +#include "llvm/IR/Metadata.def" + +// Provide specializations of isa so that we don't need definitions of +// subclasses to see if the metadata is a subclass. +#define HANDLE_METADATA_LEAF(CLASS) \ + template <> struct isa_impl<CLASS, Metadata> { \ + static inline bool doit(const Metadata &MD) { \ + return MD.getMetadataID() == Metadata::CLASS##Kind; \ + } \ + }; +#include "llvm/IR/Metadata.def" + +inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) { + MD.print(OS); + return OS; +} + +/// \brief Metadata wrapper in the Value hierarchy. +/// +/// A member of the \a Value hierarchy to represent a reference to metadata. +/// This allows, e.g., instrinsics to have metadata as operands. +/// +/// Notably, this is the only thing in either hierarchy that is allowed to +/// reference \a LocalAsMetadata. +class MetadataAsValue : public Value { + friend class ReplaceableMetadataImpl; + friend class LLVMContextImpl; + + Metadata *MD; + + MetadataAsValue(Type *Ty, Metadata *MD); + ~MetadataAsValue() override; + + /// \brief Drop use of metadata (during teardown). + void dropUse() { MD = nullptr; } + +public: + static MetadataAsValue *get(LLVMContext &Context, Metadata *MD); + static MetadataAsValue *getIfExists(LLVMContext &Context, Metadata *MD); + Metadata *getMetadata() const { return MD; } + + static bool classof(const Value *V) { + return V->getValueID() == MetadataAsValueVal; + } + +private: + void handleChangedMetadata(Metadata *MD); + void track(); + void untrack(); +}; + +/// \brief API for tracking metadata references through RAUW and deletion. +/// +/// Shared API for updating \a Metadata pointers in subclasses that support +/// RAUW. +/// +/// This API is not meant to be used directly. See \a TrackingMDRef for a +/// user-friendly tracking reference. +class MetadataTracking { +public: + /// \brief Track the reference to metadata. + /// + /// Register \c MD with \c *MD, if the subclass supports tracking. If \c *MD + /// gets RAUW'ed, \c MD will be updated to the new address. If \c *MD gets + /// deleted, \c MD will be set to \c nullptr. + /// + /// If tracking isn't supported, \c *MD will not change. + /// + /// \return true iff tracking is supported by \c MD. + static bool track(Metadata *&MD) { + return track(&MD, *MD, static_cast<Metadata *>(nullptr)); + } + + /// \brief Track the reference to metadata for \a Metadata. + /// + /// As \a track(Metadata*&), but with support for calling back to \c Owner to + /// tell it that its operand changed. This could trigger \c Owner being + /// re-uniqued. + static bool track(void *Ref, Metadata &MD, Metadata &Owner) { + return track(Ref, MD, &Owner); + } + + /// \brief Track the reference to metadata for \a MetadataAsValue. + /// + /// As \a track(Metadata*&), but with support for calling back to \c Owner to + /// tell it that its operand changed. This could trigger \c Owner being + /// re-uniqued. + static bool track(void *Ref, Metadata &MD, MetadataAsValue &Owner) { + return track(Ref, MD, &Owner); + } + + /// \brief Stop tracking a reference to metadata. + /// + /// Stops \c *MD from tracking \c MD. + static void untrack(Metadata *&MD) { untrack(&MD, *MD); } + static void untrack(void *Ref, Metadata &MD); + + /// \brief Move tracking from one reference to another. + /// + /// Semantically equivalent to \c untrack(MD) followed by \c track(New), + /// except that ownership callbacks are maintained. + /// + /// Note: it is an error if \c *MD does not equal \c New. + /// + /// \return true iff tracking is supported by \c MD. + static bool retrack(Metadata *&MD, Metadata *&New) { + return retrack(&MD, *MD, &New); + } + static bool retrack(void *Ref, Metadata &MD, void *New); + + /// \brief Check whether metadata is replaceable. + static bool isReplaceable(const Metadata &MD); + + typedef PointerUnion<MetadataAsValue *, Metadata *> OwnerTy; + +private: + /// \brief Track a reference to metadata for an owner. + /// + /// Generalized version of tracking. + static bool track(void *Ref, Metadata &MD, OwnerTy Owner); +}; + +/// \brief Shared implementation of use-lists for replaceable metadata. +/// +/// Most metadata cannot be RAUW'ed. This is a shared implementation of +/// use-lists and associated API for the two that support it (\a ValueAsMetadata +/// and \a TempMDNode). +class ReplaceableMetadataImpl { + friend class MetadataTracking; + +public: + typedef MetadataTracking::OwnerTy OwnerTy; + +private: + LLVMContext &Context; + uint64_t NextIndex; + SmallDenseMap<void *, std::pair<OwnerTy, uint64_t>, 4> UseMap; + +public: + ReplaceableMetadataImpl(LLVMContext &Context) + : Context(Context), NextIndex(0) {} + ~ReplaceableMetadataImpl() { + assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata"); + } + + LLVMContext &getContext() const { return Context; } + + /// \brief Replace all uses of this with MD. + /// + /// Replace all uses of this with \c MD, which is allowed to be null. + void replaceAllUsesWith(Metadata *MD); + + /// \brief Resolve all uses of this. + /// + /// Resolve all uses of this, turning off RAUW permanently. If \c + /// ResolveUsers, call \a MDNode::resolve() on any users whose last operand + /// is resolved. + void resolveAllUses(bool ResolveUsers = true); + +private: + void addRef(void *Ref, OwnerTy Owner); + void dropRef(void *Ref); + void moveRef(void *Ref, void *New, const Metadata &MD); + + /// Lazily construct RAUW support on MD. + /// + /// If this is an unresolved MDNode, RAUW support will be created on-demand. + /// ValueAsMetadata always has RAUW support. + static ReplaceableMetadataImpl *getOrCreate(Metadata &MD); + + /// Get RAUW support on MD, if it exists. + static ReplaceableMetadataImpl *getIfExists(Metadata &MD); + + /// Check whether this node will support RAUW. + /// + /// Returns \c true unless getOrCreate() would return null. + static bool isReplaceable(const Metadata &MD); +}; + +/// \brief Value wrapper in the Metadata hierarchy. +/// +/// This is a custom value handle that allows other metadata to refer to +/// classes in the Value hierarchy. +/// +/// Because of full uniquing support, each value is only wrapped by a single \a +/// ValueAsMetadata object, so the lookup maps are far more efficient than +/// those using ValueHandleBase. +class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl { + friend class ReplaceableMetadataImpl; + friend class LLVMContextImpl; + + Value *V; + + /// \brief Drop users without RAUW (during teardown). + void dropUsers() { + ReplaceableMetadataImpl::resolveAllUses(/* ResolveUsers */ false); + } + +protected: + ValueAsMetadata(unsigned ID, Value *V) + : Metadata(ID, Uniqued), ReplaceableMetadataImpl(V->getContext()), V(V) { + assert(V && "Expected valid value"); + } + ~ValueAsMetadata() = default; + +public: + static ValueAsMetadata *get(Value *V); + static ConstantAsMetadata *getConstant(Value *C) { + return cast<ConstantAsMetadata>(get(C)); + } + static LocalAsMetadata *getLocal(Value *Local) { + return cast<LocalAsMetadata>(get(Local)); + } + + static ValueAsMetadata *getIfExists(Value *V); + static ConstantAsMetadata *getConstantIfExists(Value *C) { + return cast_or_null<ConstantAsMetadata>(getIfExists(C)); + } + static LocalAsMetadata *getLocalIfExists(Value *Local) { + return cast_or_null<LocalAsMetadata>(getIfExists(Local)); + } + + Value *getValue() const { return V; } + Type *getType() const { return V->getType(); } + LLVMContext &getContext() const { return V->getContext(); } + + static void handleDeletion(Value *V); + static void handleRAUW(Value *From, Value *To); + +protected: + /// \brief Handle collisions after \a Value::replaceAllUsesWith(). + /// + /// RAUW isn't supported directly for \a ValueAsMetadata, but if the wrapped + /// \a Value gets RAUW'ed and the target already exists, this is used to + /// merge the two metadata nodes. + void replaceAllUsesWith(Metadata *MD) { + ReplaceableMetadataImpl::replaceAllUsesWith(MD); + } + +public: + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == LocalAsMetadataKind || + MD->getMetadataID() == ConstantAsMetadataKind; + } +}; + +class ConstantAsMetadata : public ValueAsMetadata { + friend class ValueAsMetadata; + + ConstantAsMetadata(Constant *C) + : ValueAsMetadata(ConstantAsMetadataKind, C) {} + +public: + static ConstantAsMetadata *get(Constant *C) { + return ValueAsMetadata::getConstant(C); + } + static ConstantAsMetadata *getIfExists(Constant *C) { + return ValueAsMetadata::getConstantIfExists(C); + } + + Constant *getValue() const { + return cast<Constant>(ValueAsMetadata::getValue()); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == ConstantAsMetadataKind; + } +}; + +class LocalAsMetadata : public ValueAsMetadata { + friend class ValueAsMetadata; + + LocalAsMetadata(Value *Local) + : ValueAsMetadata(LocalAsMetadataKind, Local) { + assert(!isa<Constant>(Local) && "Expected local value"); + } + +public: + static LocalAsMetadata *get(Value *Local) { + return ValueAsMetadata::getLocal(Local); + } + static LocalAsMetadata *getIfExists(Value *Local) { + return ValueAsMetadata::getLocalIfExists(Local); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == LocalAsMetadataKind; + } +}; + +/// \brief Transitional API for extracting constants from Metadata. +/// +/// This namespace contains transitional functions for metadata that points to +/// \a Constants. +/// +/// In prehistory -- when metadata was a subclass of \a Value -- \a MDNode +/// operands could refer to any \a Value. There's was a lot of code like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *CI = dyn_cast<ConstantInt>(N->getOperand(2)); +/// \endcode +/// +/// Now that \a Value and \a Metadata are in separate hierarchies, maintaining +/// the semantics for \a isa(), \a cast(), \a dyn_cast() (etc.) requires three +/// steps: cast in the \a Metadata hierarchy, extraction of the \a Value, and +/// cast in the \a Value hierarchy. Besides creating boiler-plate, this +/// requires subtle control flow changes. +/// +/// The end-goal is to create a new type of metadata, called (e.g.) \a MDInt, +/// so that metadata can refer to numbers without traversing a bridge to the \a +/// Value hierarchy. In this final state, the code above would look like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *MI = dyn_cast<MDInt>(N->getOperand(2)); +/// \endcode +/// +/// The API in this namespace supports the transition. \a MDInt doesn't exist +/// yet, and even once it does, changing each metadata schema to use it is its +/// own mini-project. In the meantime this API prevents us from introducing +/// complex and bug-prone control flow that will disappear in the end. In +/// particular, the above code looks like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *CI = mdconst::dyn_extract<ConstantInt>(N->getOperand(2)); +/// \endcode +/// +/// The full set of provided functions includes: +/// +/// mdconst::hasa <=> isa +/// mdconst::extract <=> cast +/// mdconst::extract_or_null <=> cast_or_null +/// mdconst::dyn_extract <=> dyn_cast +/// mdconst::dyn_extract_or_null <=> dyn_cast_or_null +/// +/// The target of the cast must be a subclass of \a Constant. +namespace mdconst { + +namespace detail { +template <class T> T &make(); +template <class T, class Result> struct HasDereference { + typedef char Yes[1]; + typedef char No[2]; + template <size_t N> struct SFINAE {}; + + template <class U, class V> + static Yes &hasDereference(SFINAE<sizeof(static_cast<V>(*make<U>()))> * = 0); + template <class U, class V> static No &hasDereference(...); + + static const bool value = + sizeof(hasDereference<T, Result>(nullptr)) == sizeof(Yes); +}; +template <class V, class M> struct IsValidPointer { + static const bool value = std::is_base_of<Constant, V>::value && + HasDereference<M, const Metadata &>::value; +}; +template <class V, class M> struct IsValidReference { + static const bool value = std::is_base_of<Constant, V>::value && + std::is_convertible<M, const Metadata &>::value; +}; +} // end namespace detail + +/// \brief Check whether Metadata has a Value. +/// +/// As an analogue to \a isa(), check whether \c MD has an \a Value inside of +/// type \c X. +template <class X, class Y> +inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, bool>::type +hasa(Y &&MD) { + assert(MD && "Null pointer sent into hasa"); + if (auto *V = dyn_cast<ConstantAsMetadata>(MD)) + return isa<X>(V->getValue()); + return false; +} +template <class X, class Y> +inline + typename std::enable_if<detail::IsValidReference<X, Y &>::value, bool>::type + hasa(Y &MD) { + return hasa(&MD); +} + +/// \brief Extract a Value from Metadata. +/// +/// As an analogue to \a cast(), extract the \a Value subclass \c X from \c MD. +template <class X, class Y> +inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type +extract(Y &&MD) { + return cast<X>(cast<ConstantAsMetadata>(MD)->getValue()); +} +template <class X, class Y> +inline + typename std::enable_if<detail::IsValidReference<X, Y &>::value, X *>::type + extract(Y &MD) { + return extract(&MD); +} + +/// \brief Extract a Value from Metadata, allowing null. +/// +/// As an analogue to \a cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, allowing \c MD to be null. +template <class X, class Y> +inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type +extract_or_null(Y &&MD) { + if (auto *V = cast_or_null<ConstantAsMetadata>(MD)) + return cast<X>(V->getValue()); + return nullptr; +} + +/// \brief Extract a Value from Metadata, if any. +/// +/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a +/// Value it does contain is of the wrong subclass. +template <class X, class Y> +inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type +dyn_extract(Y &&MD) { + if (auto *V = dyn_cast<ConstantAsMetadata>(MD)) + return dyn_cast<X>(V->getValue()); + return nullptr; +} + +/// \brief Extract a Value from Metadata, if any, allowing null. +/// +/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a +/// Value it does contain is of the wrong subclass, allowing \c MD to be null. +template <class X, class Y> +inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type +dyn_extract_or_null(Y &&MD) { + if (auto *V = dyn_cast_or_null<ConstantAsMetadata>(MD)) + return dyn_cast<X>(V->getValue()); + return nullptr; +} + +} // end namespace mdconst + +//===----------------------------------------------------------------------===// +/// \brief A single uniqued string. +/// +/// These are used to efficiently contain a byte sequence for metadata. +/// MDString is always unnamed. +class MDString : public Metadata { + friend class StringMapEntry<MDString>; + + MDString(const MDString &) = delete; + MDString &operator=(MDString &&) = delete; + MDString &operator=(const MDString &) = delete; + + StringMapEntry<MDString> *Entry; + MDString() : Metadata(MDStringKind, Uniqued), Entry(nullptr) {} + +public: + static MDString *get(LLVMContext &Context, StringRef Str); + static MDString *get(LLVMContext &Context, const char *Str) { + return get(Context, Str ? StringRef(Str) : StringRef()); + } + + StringRef getString() const; + + unsigned getLength() const { return (unsigned)getString().size(); } + + typedef StringRef::iterator iterator; + + /// \brief Pointer to the first byte of the string. + iterator begin() const { return getString().begin(); } + + /// \brief Pointer to one byte past the end of the string. + iterator end() const { return getString().end(); } + + const unsigned char *bytes_begin() const { return getString().bytes_begin(); } + const unsigned char *bytes_end() const { return getString().bytes_end(); } + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast. + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDStringKind; + } +}; + +/// \brief A collection of metadata nodes that might be associated with a +/// memory access used by the alias-analysis infrastructure. +struct AAMDNodes { + explicit AAMDNodes(MDNode *T = nullptr, MDNode *S = nullptr, + MDNode *N = nullptr) + : TBAA(T), Scope(S), NoAlias(N) {} + + bool operator==(const AAMDNodes &A) const { + return TBAA == A.TBAA && Scope == A.Scope && NoAlias == A.NoAlias; + } + + bool operator!=(const AAMDNodes &A) const { return !(*this == A); } + + explicit operator bool() const { return TBAA || Scope || NoAlias; } + + /// \brief The tag for type-based alias analysis. + MDNode *TBAA; + + /// \brief The tag for alias scope specification (used with noalias). + MDNode *Scope; + + /// \brief The tag specifying the noalias scope. + MDNode *NoAlias; +}; + +// Specialize DenseMapInfo for AAMDNodes. +template<> +struct DenseMapInfo<AAMDNodes> { + static inline AAMDNodes getEmptyKey() { + return AAMDNodes(DenseMapInfo<MDNode *>::getEmptyKey(), + nullptr, nullptr); + } + static inline AAMDNodes getTombstoneKey() { + return AAMDNodes(DenseMapInfo<MDNode *>::getTombstoneKey(), + nullptr, nullptr); + } + static unsigned getHashValue(const AAMDNodes &Val) { + return DenseMapInfo<MDNode *>::getHashValue(Val.TBAA) ^ + DenseMapInfo<MDNode *>::getHashValue(Val.Scope) ^ + DenseMapInfo<MDNode *>::getHashValue(Val.NoAlias); + } + static bool isEqual(const AAMDNodes &LHS, const AAMDNodes &RHS) { + return LHS == RHS; + } +}; + +/// \brief Tracking metadata reference owned by Metadata. +/// +/// Similar to \a TrackingMDRef, but it's expected to be owned by an instance +/// of \a Metadata, which has the option of registering itself for callbacks to +/// re-unique itself. +/// +/// In particular, this is used by \a MDNode. +class MDOperand { + MDOperand(MDOperand &&) = delete; + MDOperand(const MDOperand &) = delete; + MDOperand &operator=(MDOperand &&) = delete; + MDOperand &operator=(const MDOperand &) = delete; + + Metadata *MD; + +public: + MDOperand() : MD(nullptr) {} + ~MDOperand() { untrack(); } + + Metadata *get() const { return MD; } + operator Metadata *() const { return get(); } + Metadata *operator->() const { return get(); } + Metadata &operator*() const { return *get(); } + + void reset() { + untrack(); + MD = nullptr; + } + void reset(Metadata *MD, Metadata *Owner) { + untrack(); + this->MD = MD; + track(Owner); + } + +private: + void track(Metadata *Owner) { + if (MD) { + if (Owner) + MetadataTracking::track(this, *MD, *Owner); + else + MetadataTracking::track(MD); + } + } + void untrack() { + assert(static_cast<void *>(this) == &MD && "Expected same address"); + if (MD) + MetadataTracking::untrack(MD); + } +}; + +template <> struct simplify_type<MDOperand> { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(MDOperand &MD) { return MD.get(); } +}; + +template <> struct simplify_type<const MDOperand> { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); } +}; + +/// \brief Pointer to the context, with optional RAUW support. +/// +/// Either a raw (non-null) pointer to the \a LLVMContext, or an owned pointer +/// to \a ReplaceableMetadataImpl (which has a reference to \a LLVMContext). +class ContextAndReplaceableUses { + PointerUnion<LLVMContext *, ReplaceableMetadataImpl *> Ptr; + + ContextAndReplaceableUses() = delete; + ContextAndReplaceableUses(ContextAndReplaceableUses &&) = delete; + ContextAndReplaceableUses(const ContextAndReplaceableUses &) = delete; + ContextAndReplaceableUses &operator=(ContextAndReplaceableUses &&) = delete; + ContextAndReplaceableUses & + operator=(const ContextAndReplaceableUses &) = delete; + +public: + ContextAndReplaceableUses(LLVMContext &Context) : Ptr(&Context) {} + ContextAndReplaceableUses( + std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses) + : Ptr(ReplaceableUses.release()) { + assert(getReplaceableUses() && "Expected non-null replaceable uses"); + } + ~ContextAndReplaceableUses() { delete getReplaceableUses(); } + + operator LLVMContext &() { return getContext(); } + + /// \brief Whether this contains RAUW support. + bool hasReplaceableUses() const { + return Ptr.is<ReplaceableMetadataImpl *>(); + } + LLVMContext &getContext() const { + if (hasReplaceableUses()) + return getReplaceableUses()->getContext(); + return *Ptr.get<LLVMContext *>(); + } + ReplaceableMetadataImpl *getReplaceableUses() const { + if (hasReplaceableUses()) + return Ptr.get<ReplaceableMetadataImpl *>(); + return nullptr; + } + + /// Ensure that this has RAUW support, and then return it. + ReplaceableMetadataImpl *getOrCreateReplaceableUses() { + if (!hasReplaceableUses()) + makeReplaceable(llvm::make_unique<ReplaceableMetadataImpl>(getContext())); + return getReplaceableUses(); + } + + /// \brief Assign RAUW support to this. + /// + /// Make this replaceable, taking ownership of \c ReplaceableUses (which must + /// not be null). + void + makeReplaceable(std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses) { + assert(ReplaceableUses && "Expected non-null replaceable uses"); + assert(&ReplaceableUses->getContext() == &getContext() && + "Expected same context"); + delete getReplaceableUses(); + Ptr = ReplaceableUses.release(); + } + + /// \brief Drop RAUW support. + /// + /// Cede ownership of RAUW support, returning it. + std::unique_ptr<ReplaceableMetadataImpl> takeReplaceableUses() { + assert(hasReplaceableUses() && "Expected to own replaceable uses"); + std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses( + getReplaceableUses()); + Ptr = &ReplaceableUses->getContext(); + return ReplaceableUses; + } +}; + +struct TempMDNodeDeleter { + inline void operator()(MDNode *Node) const; +}; + +#define HANDLE_MDNODE_LEAF(CLASS) \ + typedef std::unique_ptr<CLASS, TempMDNodeDeleter> Temp##CLASS; +#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_LEAF(CLASS) +#include "llvm/IR/Metadata.def" + +/// \brief Metadata node. +/// +/// Metadata nodes can be uniqued, like constants, or distinct. Temporary +/// metadata nodes (with full support for RAUW) can be used to delay uniquing +/// until forward references are known. The basic metadata node is an \a +/// MDTuple. +/// +/// There is limited support for RAUW at construction time. At construction +/// time, if any operand is a temporary node (or an unresolved uniqued node, +/// which indicates a transitive temporary operand), the node itself will be +/// unresolved. As soon as all operands become resolved, it will drop RAUW +/// support permanently. +/// +/// If an unresolved node is part of a cycle, \a resolveCycles() needs +/// to be called on some member of the cycle once all temporary nodes have been +/// replaced. +class MDNode : public Metadata { + friend class ReplaceableMetadataImpl; + friend class LLVMContextImpl; + + MDNode(const MDNode &) = delete; + void operator=(const MDNode &) = delete; + void *operator new(size_t) = delete; + + unsigned NumOperands; + unsigned NumUnresolved; + + ContextAndReplaceableUses Context; + +protected: + void *operator new(size_t Size, unsigned NumOps); + void operator delete(void *Mem); + + /// \brief Required by std, but never called. + void operator delete(void *, unsigned) { + llvm_unreachable("Constructor throws?"); + } + + /// \brief Required by std, but never called. + void operator delete(void *, unsigned, bool) { + llvm_unreachable("Constructor throws?"); + } + + MDNode(LLVMContext &Context, unsigned ID, StorageType Storage, + ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None); + ~MDNode() = default; + + void dropAllReferences(); + + MDOperand *mutable_begin() { return mutable_end() - NumOperands; } + MDOperand *mutable_end() { return reinterpret_cast<MDOperand *>(this); } + + typedef iterator_range<MDOperand *> mutable_op_range; + mutable_op_range mutable_operands() { + return mutable_op_range(mutable_begin(), mutable_end()); + } + +public: + static inline MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs); + static inline MDTuple *getIfExists(LLVMContext &Context, + ArrayRef<Metadata *> MDs); + static inline MDTuple *getDistinct(LLVMContext &Context, + ArrayRef<Metadata *> MDs); + static inline TempMDTuple getTemporary(LLVMContext &Context, + ArrayRef<Metadata *> MDs); + + /// \brief Create a (temporary) clone of this. + TempMDNode clone() const; + + /// \brief Deallocate a node created by getTemporary. + /// + /// Calls \c replaceAllUsesWith(nullptr) before deleting, so any remaining + /// references will be reset. + static void deleteTemporary(MDNode *N); + + LLVMContext &getContext() const { return Context.getContext(); } + + /// \brief Replace a specific operand. + void replaceOperandWith(unsigned I, Metadata *New); + + /// \brief Check if node is fully resolved. + /// + /// If \a isTemporary(), this always returns \c false; if \a isDistinct(), + /// this always returns \c true. + /// + /// If \a isUniqued(), returns \c true if this has already dropped RAUW + /// support (because all operands are resolved). + /// + /// As forward declarations are resolved, their containers should get + /// resolved automatically. However, if this (or one of its operands) is + /// involved in a cycle, \a resolveCycles() needs to be called explicitly. + bool isResolved() const { return !isTemporary() && !NumUnresolved; } + + bool isUniqued() const { return Storage == Uniqued; } + bool isDistinct() const { return Storage == Distinct; } + bool isTemporary() const { return Storage == Temporary; } + + /// \brief RAUW a temporary. + /// + /// \pre \a isTemporary() must be \c true. + void replaceAllUsesWith(Metadata *MD) { + assert(isTemporary() && "Expected temporary node"); + if (Context.hasReplaceableUses()) + Context.getReplaceableUses()->replaceAllUsesWith(MD); + } + + /// \brief Resolve cycles. + /// + /// Once all forward declarations have been resolved, force cycles to be + /// resolved. + /// + /// \pre No operands (or operands' operands, etc.) have \a isTemporary(). + void resolveCycles(); + + /// \brief Replace a temporary node with a permanent one. + /// + /// Try to create a uniqued version of \c N -- in place, if possible -- and + /// return it. If \c N cannot be uniqued, return a distinct node instead. + template <class T> + static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type + replaceWithPermanent(std::unique_ptr<T, TempMDNodeDeleter> N) { + return cast<T>(N.release()->replaceWithPermanentImpl()); + } + + /// \brief Replace a temporary node with a uniqued one. + /// + /// Create a uniqued version of \c N -- in place, if possible -- and return + /// it. Takes ownership of the temporary node. + /// + /// \pre N does not self-reference. + template <class T> + static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type + replaceWithUniqued(std::unique_ptr<T, TempMDNodeDeleter> N) { + return cast<T>(N.release()->replaceWithUniquedImpl()); + } + + /// \brief Replace a temporary node with a distinct one. + /// + /// Create a distinct version of \c N -- in place, if possible -- and return + /// it. Takes ownership of the temporary node. + template <class T> + static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type + replaceWithDistinct(std::unique_ptr<T, TempMDNodeDeleter> N) { + return cast<T>(N.release()->replaceWithDistinctImpl()); + } + +private: + MDNode *replaceWithPermanentImpl(); + MDNode *replaceWithUniquedImpl(); + MDNode *replaceWithDistinctImpl(); + +protected: + /// \brief Set an operand. + /// + /// Sets the operand directly, without worrying about uniquing. + void setOperand(unsigned I, Metadata *New); + + void storeDistinctInContext(); + template <class T, class StoreT> + static T *storeImpl(T *N, StorageType Storage, StoreT &Store); + template <class T> static T *storeImpl(T *N, StorageType Storage); + +private: + void handleChangedOperand(void *Ref, Metadata *New); + + /// Resolve a unique, unresolved node. + void resolve(); + + /// Drop RAUW support, if any. + void dropReplaceableUses(); + + void resolveAfterOperandChange(Metadata *Old, Metadata *New); + void decrementUnresolvedOperandCount(); + void countUnresolvedOperands(); + + /// \brief Mutate this to be "uniqued". + /// + /// Mutate this so that \a isUniqued(). + /// \pre \a isTemporary(). + /// \pre already added to uniquing set. + void makeUniqued(); + + /// \brief Mutate this to be "distinct". + /// + /// Mutate this so that \a isDistinct(). + /// \pre \a isTemporary(). + void makeDistinct(); + + void deleteAsSubclass(); + MDNode *uniquify(); + void eraseFromStore(); + + template <class NodeTy> struct HasCachedHash; + template <class NodeTy> + static void dispatchRecalculateHash(NodeTy *N, std::true_type) { + N->recalculateHash(); + } + template <class NodeTy> + static void dispatchRecalculateHash(NodeTy *, std::false_type) {} + template <class NodeTy> + static void dispatchResetHash(NodeTy *N, std::true_type) { + N->setHash(0); + } + template <class NodeTy> + static void dispatchResetHash(NodeTy *, std::false_type) {} + +public: + typedef const MDOperand *op_iterator; + typedef iterator_range<op_iterator> op_range; + + op_iterator op_begin() const { + return const_cast<MDNode *>(this)->mutable_begin(); + } + op_iterator op_end() const { + return const_cast<MDNode *>(this)->mutable_end(); + } + op_range operands() const { return op_range(op_begin(), op_end()); } + + const MDOperand &getOperand(unsigned I) const { + assert(I < NumOperands && "Out of range"); + return op_begin()[I]; + } + + /// \brief Return number of MDNode operands. + unsigned getNumOperands() const { return NumOperands; } + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; +#define HANDLE_MDNODE_LEAF(CLASS) \ + case CLASS##Kind: \ + return true; +#include "llvm/IR/Metadata.def" + } + } + + /// \brief Check whether MDNode is a vtable access. + bool isTBAAVtableAccess() const; + + /// \brief Methods for metadata merging. + static MDNode *concatenate(MDNode *A, MDNode *B); + static MDNode *intersect(MDNode *A, MDNode *B); + static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B); + static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B); + static MDNode *getMostGenericRange(MDNode *A, MDNode *B); + static MDNode *getMostGenericAliasScope(MDNode *A, MDNode *B); + static MDNode *getMostGenericAlignmentOrDereferenceable(MDNode *A, MDNode *B); + +}; + +/// \brief Tuple of metadata. +/// +/// This is the simple \a MDNode arbitrary tuple. Nodes are uniqued by +/// default based on their operands. +class MDTuple : public MDNode { + friend class LLVMContextImpl; + friend class MDNode; + + MDTuple(LLVMContext &C, StorageType Storage, unsigned Hash, + ArrayRef<Metadata *> Vals) + : MDNode(C, MDTupleKind, Storage, Vals) { + setHash(Hash); + } + ~MDTuple() { dropAllReferences(); } + + void setHash(unsigned Hash) { SubclassData32 = Hash; } + void recalculateHash(); + + static MDTuple *getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs, + StorageType Storage, bool ShouldCreate = true); + + TempMDTuple cloneImpl() const { + return getTemporary(getContext(), + SmallVector<Metadata *, 4>(op_begin(), op_end())); + } + +public: + /// \brief Get the hash, if any. + unsigned getHash() const { return SubclassData32; } + + static MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) { + return getImpl(Context, MDs, Uniqued); + } + static MDTuple *getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) { + return getImpl(Context, MDs, Uniqued, /* ShouldCreate */ false); + } + + /// \brief Return a distinct node. + /// + /// Return a distinct node -- i.e., a node that is not uniqued. + static MDTuple *getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) { + return getImpl(Context, MDs, Distinct); + } + + /// \brief Return a temporary node. + /// + /// For use in constructing cyclic MDNode structures. A temporary MDNode is + /// not uniqued, may be RAUW'd, and must be manually deleted with + /// deleteTemporary. + static TempMDTuple getTemporary(LLVMContext &Context, + ArrayRef<Metadata *> MDs) { + return TempMDTuple(getImpl(Context, MDs, Temporary)); + } + + /// \brief Return a (temporary) clone of this. + TempMDTuple clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTupleKind; + } +}; + +MDTuple *MDNode::get(LLVMContext &Context, ArrayRef<Metadata *> MDs) { + return MDTuple::get(Context, MDs); +} +MDTuple *MDNode::getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) { + return MDTuple::getIfExists(Context, MDs); +} +MDTuple *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) { + return MDTuple::getDistinct(Context, MDs); +} +TempMDTuple MDNode::getTemporary(LLVMContext &Context, + ArrayRef<Metadata *> MDs) { + return MDTuple::getTemporary(Context, MDs); +} + +void TempMDNodeDeleter::operator()(MDNode *Node) const { + MDNode::deleteTemporary(Node); +} + +/// \brief Typed iterator through MDNode operands. +/// +/// An iterator that transforms an \a MDNode::iterator into an iterator over a +/// particular Metadata subclass. +template <class T> +class TypedMDOperandIterator + : std::iterator<std::input_iterator_tag, T *, std::ptrdiff_t, void, T *> { + MDNode::op_iterator I = nullptr; + +public: + TypedMDOperandIterator() = default; + explicit TypedMDOperandIterator(MDNode::op_iterator I) : I(I) {} + T *operator*() const { return cast_or_null<T>(*I); } + TypedMDOperandIterator &operator++() { + ++I; + return *this; + } + TypedMDOperandIterator operator++(int) { + TypedMDOperandIterator Temp(*this); + ++I; + return Temp; + } + bool operator==(const TypedMDOperandIterator &X) const { return I == X.I; } + bool operator!=(const TypedMDOperandIterator &X) const { return I != X.I; } +}; + +/// \brief Typed, array-like tuple of metadata. +/// +/// This is a wrapper for \a MDTuple that makes it act like an array holding a +/// particular type of metadata. +template <class T> class MDTupleTypedArrayWrapper { + const MDTuple *N = nullptr; + +public: + MDTupleTypedArrayWrapper() = default; + MDTupleTypedArrayWrapper(const MDTuple *N) : N(N) {} + + template <class U> + MDTupleTypedArrayWrapper( + const MDTupleTypedArrayWrapper<U> &Other, + typename std::enable_if<std::is_convertible<U *, T *>::value>::type * = + nullptr) + : N(Other.get()) {} + + template <class U> + explicit MDTupleTypedArrayWrapper( + const MDTupleTypedArrayWrapper<U> &Other, + typename std::enable_if<!std::is_convertible<U *, T *>::value>::type * = + nullptr) + : N(Other.get()) {} + + explicit operator bool() const { return get(); } + explicit operator MDTuple *() const { return get(); } + + MDTuple *get() const { return const_cast<MDTuple *>(N); } + MDTuple *operator->() const { return get(); } + MDTuple &operator*() const { return *get(); } + + // FIXME: Fix callers and remove condition on N. + unsigned size() const { return N ? N->getNumOperands() : 0u; } + T *operator[](unsigned I) const { return cast_or_null<T>(N->getOperand(I)); } + + // FIXME: Fix callers and remove condition on N. + typedef TypedMDOperandIterator<T> iterator; + iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } + iterator end() const { return N ? iterator(N->op_end()) : iterator(); } +}; + +#define HANDLE_METADATA(CLASS) \ + typedef MDTupleTypedArrayWrapper<CLASS> CLASS##Array; +#include "llvm/IR/Metadata.def" + +/// Placeholder metadata for operands of distinct MDNodes. +/// +/// This is a lightweight placeholder for an operand of a distinct node. It's +/// purpose is to help track forward references when creating a distinct node. +/// This allows distinct nodes involved in a cycle to be constructed before +/// their operands without requiring a heavyweight temporary node with +/// full-blown RAUW support. +/// +/// Each placeholder supports only a single MDNode user. Clients should pass +/// an ID, retrieved via \a getID(), to indicate the "real" operand that this +/// should be replaced with. +/// +/// While it would be possible to implement move operators, they would be +/// fairly expensive. Leave them unimplemented to discourage their use +/// (clients can use std::deque, std::list, BumpPtrAllocator, etc.). +class DistinctMDOperandPlaceholder : public Metadata { + friend class MetadataTracking; + + Metadata **Use = nullptr; + + DistinctMDOperandPlaceholder() = delete; + DistinctMDOperandPlaceholder(DistinctMDOperandPlaceholder &&) = delete; + DistinctMDOperandPlaceholder(const DistinctMDOperandPlaceholder &) = delete; + +public: + explicit DistinctMDOperandPlaceholder(unsigned ID) + : Metadata(DistinctMDOperandPlaceholderKind, Distinct) { + SubclassData32 = ID; + } + + ~DistinctMDOperandPlaceholder() { + if (Use) + *Use = nullptr; + } + + unsigned getID() const { return SubclassData32; } + + /// Replace the use of this with MD. + void replaceUseWith(Metadata *MD) { + if (!Use) + return; + *Use = MD; + Use = nullptr; + } +}; + +//===----------------------------------------------------------------------===// +/// \brief A tuple of MDNodes. +/// +/// Despite its name, a NamedMDNode isn't itself an MDNode. NamedMDNodes belong +/// to modules, have names, and contain lists of MDNodes. +/// +/// TODO: Inherit from Metadata. +class NamedMDNode : public ilist_node<NamedMDNode> { + friend class LLVMContextImpl; + friend class Module; + NamedMDNode(const NamedMDNode &) = delete; + + std::string Name; + Module *Parent; + void *Operands; // SmallVector<TrackingMDRef, 4> + + void setParent(Module *M) { Parent = M; } + + explicit NamedMDNode(const Twine &N); + + template<class T1, class T2> + class op_iterator_impl : + public std::iterator<std::bidirectional_iterator_tag, T2> { + const NamedMDNode *Node; + unsigned Idx; + op_iterator_impl(const NamedMDNode *N, unsigned i) : Node(N), Idx(i) { } + + friend class NamedMDNode; + + public: + op_iterator_impl() : Node(nullptr), Idx(0) { } + + bool operator==(const op_iterator_impl &o) const { return Idx == o.Idx; } + bool operator!=(const op_iterator_impl &o) const { return Idx != o.Idx; } + op_iterator_impl &operator++() { + ++Idx; + return *this; + } + op_iterator_impl operator++(int) { + op_iterator_impl tmp(*this); + operator++(); + return tmp; + } + op_iterator_impl &operator--() { + --Idx; + return *this; + } + op_iterator_impl operator--(int) { + op_iterator_impl tmp(*this); + operator--(); + return tmp; + } + + T1 operator*() const { return Node->getOperand(Idx); } + }; + +public: + /// \brief Drop all references and remove the node from parent module. + void eraseFromParent(); + + /// \brief Remove all uses and clear node vector. + void dropAllReferences(); + + ~NamedMDNode(); + + /// \brief Get the module that holds this named metadata collection. + inline Module *getParent() { return Parent; } + inline const Module *getParent() const { return Parent; } + + MDNode *getOperand(unsigned i) const; + unsigned getNumOperands() const; + void addOperand(MDNode *M); + void setOperand(unsigned I, MDNode *New); + StringRef getName() const; + void print(raw_ostream &ROS, bool IsForDebug = false) const; + void print(raw_ostream &ROS, ModuleSlotTracker &MST, + bool IsForDebug = false) const; + void dump() const; + + // --------------------------------------------------------------------------- + // Operand Iterator interface... + // + typedef op_iterator_impl<MDNode *, MDNode> op_iterator; + op_iterator op_begin() { return op_iterator(this, 0); } + op_iterator op_end() { return op_iterator(this, getNumOperands()); } + + typedef op_iterator_impl<const MDNode *, MDNode> const_op_iterator; + const_op_iterator op_begin() const { return const_op_iterator(this, 0); } + const_op_iterator op_end() const { return const_op_iterator(this, getNumOperands()); } + + inline iterator_range<op_iterator> operands() { + return make_range(op_begin(), op_end()); + } + inline iterator_range<const_op_iterator> operands() const { + return make_range(op_begin(), op_end()); + } +}; + +} // end llvm namespace + +#endif // LLVM_IR_METADATA_H
diff --git a/third_party/llvm-subzero/include/llvm/IR/OperandTraits.h b/third_party/llvm-subzero/include/llvm/IR/OperandTraits.h new file mode 100644 index 0000000..e97a800 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/OperandTraits.h
@@ -0,0 +1,160 @@ +//===-- llvm/OperandTraits.h - OperandTraits class definition ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the traits classes that are handy for enforcing the correct +// layout of various User subclasses. It also provides the means for accessing +// the operands in the most efficient manner. +// + +#ifndef LLVM_IR_OPERANDTRAITS_H +#define LLVM_IR_OPERANDTRAITS_H + +#include "llvm/IR/User.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// FixedNumOperand Trait Class +//===----------------------------------------------------------------------===// + +/// FixedNumOperandTraits - determine the allocation regime of the Use array +/// when it is a prefix to the User object, and the number of Use objects is +/// known at compile time. + +template <typename SubClass, unsigned ARITY> +struct FixedNumOperandTraits { + static Use *op_begin(SubClass* U) { + return reinterpret_cast<Use*>(U) - ARITY; + } + static Use *op_end(SubClass* U) { + return reinterpret_cast<Use*>(U); + } + static unsigned operands(const User*) { + return ARITY; + } +}; + +//===----------------------------------------------------------------------===// +// OptionalOperand Trait Class +//===----------------------------------------------------------------------===// + +/// OptionalOperandTraits - when the number of operands may change at runtime. +/// Naturally it may only decrease, because the allocations may not change. + +template <typename SubClass, unsigned ARITY = 1> +struct OptionalOperandTraits : public FixedNumOperandTraits<SubClass, ARITY> { + static unsigned operands(const User *U) { + return U->getNumOperands(); + } +}; + +//===----------------------------------------------------------------------===// +// VariadicOperand Trait Class +//===----------------------------------------------------------------------===// + +/// VariadicOperandTraits - determine the allocation regime of the Use array +/// when it is a prefix to the User object, and the number of Use objects is +/// only known at allocation time. + +template <typename SubClass, unsigned MINARITY = 0> +struct VariadicOperandTraits { + static Use *op_begin(SubClass* U) { + return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands(); + } + static Use *op_end(SubClass* U) { + return reinterpret_cast<Use*>(U); + } + static unsigned operands(const User *U) { + return U->getNumOperands(); + } +}; + +//===----------------------------------------------------------------------===// +// HungoffOperand Trait Class +//===----------------------------------------------------------------------===// + +/// HungoffOperandTraits - determine the allocation regime of the Use array +/// when it is not a prefix to the User object, but allocated at an unrelated +/// heap address. +/// Assumes that the User subclass that is determined by this traits class +/// has an OperandList member of type User::op_iterator. [Note: this is now +/// trivially satisfied, because User has that member for historic reasons.] +/// +/// This is the traits class that is needed when the Use array must be +/// resizable. + +template <unsigned MINARITY = 1> +struct HungoffOperandTraits { + static Use *op_begin(User* U) { + return U->getOperandList(); + } + static Use *op_end(User* U) { + return U->getOperandList() + U->getNumOperands(); + } + static unsigned operands(const User *U) { + return U->getNumOperands(); + } +}; + +/// Macro for generating in-class operand accessor declarations. +/// It should only be called in the public section of the interface. +/// +#define DECLARE_TRANSPARENT_OPERAND_ACCESSORS(VALUECLASS) \ + public: \ + inline VALUECLASS *getOperand(unsigned) const; \ + inline void setOperand(unsigned, VALUECLASS*); \ + inline op_iterator op_begin(); \ + inline const_op_iterator op_begin() const; \ + inline op_iterator op_end(); \ + inline const_op_iterator op_end() const; \ + protected: \ + template <int> inline Use &Op(); \ + template <int> inline const Use &Op() const; \ + public: \ + inline unsigned getNumOperands() const + +/// Macro for generating out-of-class operand accessor definitions +#define DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CLASS, VALUECLASS) \ +CLASS::op_iterator CLASS::op_begin() { \ + return OperandTraits<CLASS>::op_begin(this); \ +} \ +CLASS::const_op_iterator CLASS::op_begin() const { \ + return OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this)); \ +} \ +CLASS::op_iterator CLASS::op_end() { \ + return OperandTraits<CLASS>::op_end(this); \ +} \ +CLASS::const_op_iterator CLASS::op_end() const { \ + return OperandTraits<CLASS>::op_end(const_cast<CLASS*>(this)); \ +} \ +VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \ + assert(i_nocapture < OperandTraits<CLASS>::operands(this) \ + && "getOperand() out of range!"); \ + return cast_or_null<VALUECLASS>( \ + OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture].get()); \ +} \ +void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \ + assert(i_nocapture < OperandTraits<CLASS>::operands(this) \ + && "setOperand() out of range!"); \ + OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \ +} \ +unsigned CLASS::getNumOperands() const { \ + return OperandTraits<CLASS>::operands(this); \ +} \ +template <int Idx_nocapture> Use &CLASS::Op() { \ + return this->OpFrom<Idx_nocapture>(this); \ +} \ +template <int Idx_nocapture> const Use &CLASS::Op() const { \ + return this->OpFrom<Idx_nocapture>(this); \ +} + + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/SymbolTableListTraits.h b/third_party/llvm-subzero/include/llvm/IR/SymbolTableListTraits.h new file mode 100644 index 0000000..5c6d58a --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/SymbolTableListTraits.h
@@ -0,0 +1,114 @@ +//===-- llvm/SymbolTableListTraits.h - Traits for iplist --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a generic class that is used to implement the automatic +// symbol table manipulation that occurs when you put (for example) a named +// instruction into a basic block. +// +// The way that this is implemented is by using a special traits class with the +// intrusive list that makes up the list of instructions in a basic block. When +// a new element is added to the list of instructions, the traits class is +// notified, allowing the symbol table to be updated. +// +// This generic class implements the traits class. It must be generic so that +// it can work for all uses it, which include lists of instructions, basic +// blocks, arguments, functions, global variables, etc... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_SYMBOLTABLELISTTRAITS_H +#define LLVM_IR_SYMBOLTABLELISTTRAITS_H + +#include "llvm/ADT/ilist.h" + +namespace llvm { +class ValueSymbolTable; + +/// Template metafunction to get the parent type for a symbol table list. +/// +/// Implementations create a typedef called \c type so that we only need a +/// single template parameter for the list and traits. +template <typename NodeTy> struct SymbolTableListParentType {}; +class Argument; +class BasicBlock; +class Function; +class Instruction; +class GlobalVariable; +class GlobalAlias; +class GlobalIFunc; +class Module; +#define DEFINE_SYMBOL_TABLE_PARENT_TYPE(NODE, PARENT) \ + template <> struct SymbolTableListParentType<NODE> { typedef PARENT type; }; +DEFINE_SYMBOL_TABLE_PARENT_TYPE(Instruction, BasicBlock) +DEFINE_SYMBOL_TABLE_PARENT_TYPE(BasicBlock, Function) +DEFINE_SYMBOL_TABLE_PARENT_TYPE(Argument, Function) +DEFINE_SYMBOL_TABLE_PARENT_TYPE(Function, Module) +DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalVariable, Module) +DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalAlias, Module) +DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalIFunc, Module) +#undef DEFINE_SYMBOL_TABLE_PARENT_TYPE + +template <typename NodeTy> class SymbolTableList; + +// ValueSubClass - The type of objects that I hold, e.g. Instruction. +// ItemParentClass - The type of object that owns the list, e.g. BasicBlock. +// +template <typename ValueSubClass> +class SymbolTableListTraits : public ilist_alloc_traits<ValueSubClass> { + typedef SymbolTableList<ValueSubClass> ListTy; + typedef typename simple_ilist<ValueSubClass>::iterator iterator; + typedef + typename SymbolTableListParentType<ValueSubClass>::type ItemParentClass; + +public: + SymbolTableListTraits() {} + +private: + /// getListOwner - Return the object that owns this list. If this is a list + /// of instructions, it returns the BasicBlock that owns them. + ItemParentClass *getListOwner() { + size_t Offset(size_t(&((ItemParentClass*)nullptr->*ItemParentClass:: + getSublistAccess(static_cast<ValueSubClass*>(nullptr))))); + ListTy *Anchor(static_cast<ListTy *>(this)); + return reinterpret_cast<ItemParentClass*>(reinterpret_cast<char*>(Anchor)- + Offset); + } + + static ListTy &getList(ItemParentClass *Par) { + return Par->*(Par->getSublistAccess((ValueSubClass*)nullptr)); + } + + static ValueSymbolTable *getSymTab(ItemParentClass *Par) { + return Par ? toPtr(Par->getValueSymbolTable()) : nullptr; + } + +public: + void addNodeToList(ValueSubClass *V); + void removeNodeFromList(ValueSubClass *V); + void transferNodesFromList(SymbolTableListTraits &L2, iterator first, + iterator last); + // private: + template<typename TPtr> + void setSymTabObject(TPtr *, TPtr); + static ValueSymbolTable *toPtr(ValueSymbolTable *P) { return P; } + static ValueSymbolTable *toPtr(ValueSymbolTable &R) { return &R; } +}; + +/// List that automatically updates parent links and symbol tables. +/// +/// When nodes are inserted into and removed from this list, the associated +/// symbol table will be automatically updated. Similarly, parent links get +/// updated automatically. +template <class T> +class SymbolTableList + : public iplist_impl<simple_ilist<T>, SymbolTableListTraits<T>> {}; + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/TrackingMDRef.h b/third_party/llvm-subzero/include/llvm/IR/TrackingMDRef.h new file mode 100644 index 0000000..fe513a8 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/TrackingMDRef.h
@@ -0,0 +1,165 @@ +//===- llvm/IR/TrackingMDRef.h - Tracking Metadata references ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// References to metadata that track RAUW. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_TRACKINGMDREF_H +#define LLVM_IR_TRACKINGMDREF_H + +#include "llvm/IR/Metadata.h" + +namespace llvm { + +/// \brief Tracking metadata reference. +/// +/// This class behaves like \a TrackingVH, but for metadata. +class TrackingMDRef { + Metadata *MD; + +public: + TrackingMDRef() : MD(nullptr) {} + explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); } + + TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); } + TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); } + TrackingMDRef &operator=(TrackingMDRef &&X) { + if (&X == this) + return *this; + + untrack(); + MD = X.MD; + retrack(X); + return *this; + } + TrackingMDRef &operator=(const TrackingMDRef &X) { + if (&X == this) + return *this; + + untrack(); + MD = X.MD; + track(); + return *this; + } + ~TrackingMDRef() { untrack(); } + + Metadata *get() const { return MD; } + operator Metadata *() const { return get(); } + Metadata *operator->() const { return get(); } + Metadata &operator*() const { return *get(); } + + void reset() { + untrack(); + MD = nullptr; + } + void reset(Metadata *MD) { + untrack(); + this->MD = MD; + track(); + } + + /// \brief Check whether this has a trivial destructor. + /// + /// If \c MD isn't replaceable, the destructor will be a no-op. + bool hasTrivialDestructor() const { + return !MD || !MetadataTracking::isReplaceable(*MD); + } + + bool operator==(const TrackingMDRef &X) const { return MD == X.MD; } + bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; } + +private: + void track() { + if (MD) + MetadataTracking::track(MD); + } + void untrack() { + if (MD) + MetadataTracking::untrack(MD); + } + void retrack(TrackingMDRef &X) { + assert(MD == X.MD && "Expected values to match"); + if (X.MD) { + MetadataTracking::retrack(X.MD, MD); + X.MD = nullptr; + } + } +}; + +/// \brief Typed tracking ref. +/// +/// Track refererences of a particular type. It's useful to use this for \a +/// MDNode and \a ValueAsMetadata. +template <class T> class TypedTrackingMDRef { + TrackingMDRef Ref; + +public: + TypedTrackingMDRef() {} + explicit TypedTrackingMDRef(T *MD) : Ref(static_cast<Metadata *>(MD)) {} + + TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {} + TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {} + TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) { + Ref = std::move(X.Ref); + return *this; + } + TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) { + Ref = X.Ref; + return *this; + } + + T *get() const { return (T *)Ref.get(); } + operator T *() const { return get(); } + T *operator->() const { return get(); } + T &operator*() const { return *get(); } + + bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; } + bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; } + + void reset() { Ref.reset(); } + void reset(T *MD) { Ref.reset(static_cast<Metadata *>(MD)); } + + /// \brief Check whether this has a trivial destructor. + bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); } +}; + +typedef TypedTrackingMDRef<MDNode> TrackingMDNodeRef; +typedef TypedTrackingMDRef<ValueAsMetadata> TrackingValueAsMetadataRef; + +// Expose the underlying metadata to casting. +template <> struct simplify_type<TrackingMDRef> { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); } +}; + +template <> struct simplify_type<const TrackingMDRef> { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const TrackingMDRef &MD) { + return MD.get(); + } +}; + +template <class T> struct simplify_type<TypedTrackingMDRef<T>> { + typedef T *SimpleType; + static SimpleType getSimplifiedValue(TypedTrackingMDRef<T> &MD) { + return MD.get(); + } +}; + +template <class T> struct simplify_type<const TypedTrackingMDRef<T>> { + typedef T *SimpleType; + static SimpleType getSimplifiedValue(const TypedTrackingMDRef<T> &MD) { + return MD.get(); + } +}; + +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Type.h b/third_party/llvm-subzero/include/llvm/IR/Type.h new file mode 100644 index 0000000..9cf03d8 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/Type.h
@@ -0,0 +1,464 @@ +//===-- llvm/Type.h - Classes for handling data types -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Type class. For more "Type" +// stuff, look in DerivedTypes.h. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_TYPE_H +#define LLVM_IR_TYPE_H + +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/CBindingWrapping.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { + +class PointerType; +class IntegerType; +class raw_ostream; +class Module; +class LLVMContext; +class LLVMContextImpl; +class StringRef; +template<class GraphType> struct GraphTraits; + +/// The instances of the Type class are immutable: once they are created, +/// they are never changed. Also note that only one instance of a particular +/// type is ever created. Thus seeing if two types are equal is a matter of +/// doing a trivial pointer comparison. To enforce that no two equal instances +/// are created, Type instances can only be created via static factory methods +/// in class Type and in derived classes. Once allocated, Types are never +/// free'd. +/// +class Type { +public: + //===--------------------------------------------------------------------===// + /// Definitions of all of the base types for the Type system. Based on this + /// value, you can cast to a class defined in DerivedTypes.h. + /// Note: If you add an element to this, you need to add an element to the + /// Type::getPrimitiveType function, or else things will break! + /// Also update LLVMTypeKind and LLVMGetTypeKind () in the C binding. + /// + enum TypeID { + // PrimitiveTypes - make sure LastPrimitiveTyID stays up to date. + VoidTyID = 0, ///< 0: type with no size + HalfTyID, ///< 1: 16-bit floating point type + FloatTyID, ///< 2: 32-bit floating point type + DoubleTyID, ///< 3: 64-bit floating point type + X86_FP80TyID, ///< 4: 80-bit floating point type (X87) + FP128TyID, ///< 5: 128-bit floating point type (112-bit mantissa) + PPC_FP128TyID, ///< 6: 128-bit floating point type (two 64-bits, PowerPC) + LabelTyID, ///< 7: Labels + MetadataTyID, ///< 8: Metadata + X86_MMXTyID, ///< 9: MMX vectors (64 bits, X86 specific) + TokenTyID, ///< 10: Tokens + + // Derived types... see DerivedTypes.h file. + // Make sure FirstDerivedTyID stays up to date! + IntegerTyID, ///< 11: Arbitrary bit width integers + FunctionTyID, ///< 12: Functions + StructTyID, ///< 13: Structures + ArrayTyID, ///< 14: Arrays + PointerTyID, ///< 15: Pointers + VectorTyID ///< 16: SIMD 'packed' format, or other vector type + }; + +private: + /// This refers to the LLVMContext in which this type was uniqued. + LLVMContext &Context; + + TypeID ID : 8; // The current base type of this type. + unsigned SubclassData : 24; // Space for subclasses to store data. + +protected: + friend class LLVMContextImpl; + explicit Type(LLVMContext &C, TypeID tid) + : Context(C), ID(tid), SubclassData(0), + NumContainedTys(0), ContainedTys(nullptr) {} + ~Type() = default; + + unsigned getSubclassData() const { return SubclassData; } + + void setSubclassData(unsigned val) { + SubclassData = val; + // Ensure we don't have any accidental truncation. + assert(getSubclassData() == val && "Subclass data too large for field"); + } + + /// Keeps track of how many Type*'s there are in the ContainedTys list. + unsigned NumContainedTys; + + /// A pointer to the array of Types contained by this Type. For example, this + /// includes the arguments of a function type, the elements of a structure, + /// the pointee of a pointer, the element type of an array, etc. This pointer + /// may be 0 for types that don't contain other types (Integer, Double, + /// Float). + Type * const *ContainedTys; + + static bool isSequentialType(TypeID TyID) { + return TyID == ArrayTyID || TyID == PointerTyID || TyID == VectorTyID; + } + +public: + /// Print the current type. + /// Omit the type details if \p NoDetails == true. + /// E.g., let %st = type { i32, i16 } + /// When \p NoDetails is true, we only print %st. + /// Put differently, \p NoDetails prints the type as if + /// inlined with the operands when printing an instruction. + void print(raw_ostream &O, bool IsForDebug = false, + bool NoDetails = false) const; + void dump() const; + + /// Return the LLVMContext in which this type was uniqued. + LLVMContext &getContext() const { return Context; } + + //===--------------------------------------------------------------------===// + // Accessors for working with types. + // + + /// Return the type id for the type. This will return one of the TypeID enum + /// elements defined above. + TypeID getTypeID() const { return ID; } + + /// Return true if this is 'void'. + bool isVoidTy() const { return getTypeID() == VoidTyID; } + + /// Return true if this is 'half', a 16-bit IEEE fp type. + bool isHalfTy() const { return getTypeID() == HalfTyID; } + + /// Return true if this is 'float', a 32-bit IEEE fp type. + bool isFloatTy() const { return getTypeID() == FloatTyID; } + + /// Return true if this is 'double', a 64-bit IEEE fp type. + bool isDoubleTy() const { return getTypeID() == DoubleTyID; } + + /// Return true if this is x86 long double. + bool isX86_FP80Ty() const { return getTypeID() == X86_FP80TyID; } + + /// Return true if this is 'fp128'. + bool isFP128Ty() const { return getTypeID() == FP128TyID; } + + /// Return true if this is powerpc long double. + bool isPPC_FP128Ty() const { return getTypeID() == PPC_FP128TyID; } + + /// Return true if this is one of the six floating-point types + bool isFloatingPointTy() const { + return getTypeID() == HalfTyID || getTypeID() == FloatTyID || + getTypeID() == DoubleTyID || + getTypeID() == X86_FP80TyID || getTypeID() == FP128TyID || + getTypeID() == PPC_FP128TyID; + } + + const fltSemantics &getFltSemantics() const { + switch (getTypeID()) { + case HalfTyID: return APFloat::IEEEhalf; + case FloatTyID: return APFloat::IEEEsingle; + case DoubleTyID: return APFloat::IEEEdouble; + case X86_FP80TyID: return APFloat::x87DoubleExtended; + case FP128TyID: return APFloat::IEEEquad; + case PPC_FP128TyID: return APFloat::PPCDoubleDouble; + default: llvm_unreachable("Invalid floating type"); + } + } + + /// Return true if this is X86 MMX. + bool isX86_MMXTy() const { return getTypeID() == X86_MMXTyID; } + + /// Return true if this is a FP type or a vector of FP. + bool isFPOrFPVectorTy() const { return getScalarType()->isFloatingPointTy(); } + + /// Return true if this is 'label'. + bool isLabelTy() const { return getTypeID() == LabelTyID; } + + /// Return true if this is 'metadata'. + bool isMetadataTy() const { return getTypeID() == MetadataTyID; } + + /// Return true if this is 'token'. + bool isTokenTy() const { return getTypeID() == TokenTyID; } + + /// True if this is an instance of IntegerType. + bool isIntegerTy() const { return getTypeID() == IntegerTyID; } + + /// Return true if this is an IntegerType of the given width. + bool isIntegerTy(unsigned Bitwidth) const; + + /// Return true if this is an integer type or a vector of integer types. + bool isIntOrIntVectorTy() const { return getScalarType()->isIntegerTy(); } + + /// True if this is an instance of FunctionType. + bool isFunctionTy() const { return getTypeID() == FunctionTyID; } + + /// True if this is an instance of StructType. + bool isStructTy() const { return getTypeID() == StructTyID; } + + /// True if this is an instance of ArrayType. + bool isArrayTy() const { return getTypeID() == ArrayTyID; } + + /// True if this is an instance of PointerType. + bool isPointerTy() const { return getTypeID() == PointerTyID; } + + /// Return true if this is a pointer type or a vector of pointer types. + bool isPtrOrPtrVectorTy() const { return getScalarType()->isPointerTy(); } + + /// True if this is an instance of VectorType. + bool isVectorTy() const { return getTypeID() == VectorTyID; } + + /// Return true if this type could be converted with a lossless BitCast to + /// type 'Ty'. For example, i8* to i32*. BitCasts are valid for types of the + /// same size only where no re-interpretation of the bits is done. + /// @brief Determine if this type could be losslessly bitcast to Ty + bool canLosslesslyBitCastTo(Type *Ty) const; + + /// Return true if this type is empty, that is, it has no elements or all of + /// its elements are empty. + bool isEmptyTy() const; + + /// Return true if the type is "first class", meaning it is a valid type for a + /// Value. + bool isFirstClassType() const { + return getTypeID() != FunctionTyID && getTypeID() != VoidTyID; + } + + /// Return true if the type is a valid type for a register in codegen. This + /// includes all first-class types except struct and array types. + bool isSingleValueType() const { + return isFloatingPointTy() || isX86_MMXTy() || isIntegerTy() || + isPointerTy() || isVectorTy(); + } + + /// Return true if the type is an aggregate type. This means it is valid as + /// the first operand of an insertvalue or extractvalue instruction. This + /// includes struct and array types, but does not include vector types. + bool isAggregateType() const { + return getTypeID() == StructTyID || getTypeID() == ArrayTyID; + } + + /// Return true if it makes sense to take the size of this type. To get the + /// actual size for a particular target, it is reasonable to use the + /// DataLayout subsystem to do this. + bool isSized(SmallPtrSetImpl<Type*> *Visited = nullptr) const { + // If it's a primitive, it is always sized. + if (getTypeID() == IntegerTyID || isFloatingPointTy() || + getTypeID() == PointerTyID || + getTypeID() == X86_MMXTyID) + return true; + // If it is not something that can have a size (e.g. a function or label), + // it doesn't have a size. + if (getTypeID() != StructTyID && getTypeID() != ArrayTyID && + getTypeID() != VectorTyID) + return false; + // Otherwise we have to try harder to decide. + return isSizedDerivedType(Visited); + } + + /// Return the basic size of this type if it is a primitive type. These are + /// fixed by LLVM and are not target-dependent. + /// This will return zero if the type does not have a size or is not a + /// primitive type. + /// + /// Note that this may not reflect the size of memory allocated for an + /// instance of the type or the number of bytes that are written when an + /// instance of the type is stored to memory. The DataLayout class provides + /// additional query functions to provide this information. + /// + unsigned getPrimitiveSizeInBits() const LLVM_READONLY; + + /// If this is a vector type, return the getPrimitiveSizeInBits value for the + /// element type. Otherwise return the getPrimitiveSizeInBits value for this + /// type. + unsigned getScalarSizeInBits() const LLVM_READONLY; + + /// Return the width of the mantissa of this type. This is only valid on + /// floating-point types. If the FP type does not have a stable mantissa (e.g. + /// ppc long double), this method returns -1. + int getFPMantissaWidth() const; + + /// If this is a vector type, return the element type, otherwise return + /// 'this'. + Type *getScalarType() const LLVM_READONLY; + + //===--------------------------------------------------------------------===// + // Type Iteration support. + // + typedef Type * const *subtype_iterator; + subtype_iterator subtype_begin() const { return ContainedTys; } + subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];} + ArrayRef<Type*> subtypes() const { + return makeArrayRef(subtype_begin(), subtype_end()); + } + + typedef std::reverse_iterator<subtype_iterator> subtype_reverse_iterator; + subtype_reverse_iterator subtype_rbegin() const { + return subtype_reverse_iterator(subtype_end()); + } + subtype_reverse_iterator subtype_rend() const { + return subtype_reverse_iterator(subtype_begin()); + } + + /// This method is used to implement the type iterator (defined at the end of + /// the file). For derived types, this returns the types 'contained' in the + /// derived type. + Type *getContainedType(unsigned i) const { + assert(i < NumContainedTys && "Index out of range!"); + return ContainedTys[i]; + } + + /// Return the number of types in the derived type. + unsigned getNumContainedTypes() const { return NumContainedTys; } + + //===--------------------------------------------------------------------===// + // Helper methods corresponding to subclass methods. This forces a cast to + // the specified subclass and calls its accessor. "getVectorNumElements" (for + // example) is shorthand for cast<VectorType>(Ty)->getNumElements(). This is + // only intended to cover the core methods that are frequently used, helper + // methods should not be added here. + + inline unsigned getIntegerBitWidth() const; + + inline Type *getFunctionParamType(unsigned i) const; + inline unsigned getFunctionNumParams() const; + inline bool isFunctionVarArg() const; + + inline StringRef getStructName() const; + inline unsigned getStructNumElements() const; + inline Type *getStructElementType(unsigned N) const; + + inline Type *getSequentialElementType() const { + assert(isSequentialType(getTypeID()) && "Not a sequential type!"); + return ContainedTys[0]; + } + + inline uint64_t getArrayNumElements() const; + Type *getArrayElementType() const { return getSequentialElementType(); } + + inline unsigned getVectorNumElements() const; + Type *getVectorElementType() const { return getSequentialElementType(); } + + Type *getPointerElementType() const { return getSequentialElementType(); } + + /// Get the address space of this pointer or pointer vector type. + inline unsigned getPointerAddressSpace() const; + + //===--------------------------------------------------------------------===// + // Static members exported by the Type class itself. Useful for getting + // instances of Type. + // + + /// Return a type based on an identifier. + static Type *getPrimitiveType(LLVMContext &C, TypeID IDNumber); + + //===--------------------------------------------------------------------===// + // These are the builtin types that are always available. + // + static Type *getVoidTy(LLVMContext &C); + static Type *getLabelTy(LLVMContext &C); + static Type *getHalfTy(LLVMContext &C); + static Type *getFloatTy(LLVMContext &C); + static Type *getDoubleTy(LLVMContext &C); + static Type *getMetadataTy(LLVMContext &C); + static Type *getX86_FP80Ty(LLVMContext &C); + static Type *getFP128Ty(LLVMContext &C); + static Type *getPPC_FP128Ty(LLVMContext &C); + static Type *getX86_MMXTy(LLVMContext &C); + static Type *getTokenTy(LLVMContext &C); + static IntegerType *getIntNTy(LLVMContext &C, unsigned N); + static IntegerType *getInt1Ty(LLVMContext &C); + static IntegerType *getInt8Ty(LLVMContext &C); + static IntegerType *getInt16Ty(LLVMContext &C); + static IntegerType *getInt32Ty(LLVMContext &C); + static IntegerType *getInt64Ty(LLVMContext &C); + static IntegerType *getInt128Ty(LLVMContext &C); + + //===--------------------------------------------------------------------===// + // Convenience methods for getting pointer types with one of the above builtin + // types as pointee. + // + static PointerType *getHalfPtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getFloatPtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getDoublePtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getX86_FP80PtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getFP128PtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getPPC_FP128PtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getX86_MMXPtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getIntNPtrTy(LLVMContext &C, unsigned N, unsigned AS = 0); + static PointerType *getInt1PtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getInt8PtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getInt16PtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getInt32PtrTy(LLVMContext &C, unsigned AS = 0); + static PointerType *getInt64PtrTy(LLVMContext &C, unsigned AS = 0); + + /// Return a pointer to the current type. This is equivalent to + /// PointerType::get(Foo, AddrSpace). + PointerType *getPointerTo(unsigned AddrSpace = 0) const; + +private: + /// Derived types like structures and arrays are sized iff all of the members + /// of the type are sized as well. Since asking for their size is relatively + /// uncommon, move this operation out-of-line. + bool isSizedDerivedType(SmallPtrSetImpl<Type*> *Visited = nullptr) const; +}; + +// Printing of types. +static inline raw_ostream &operator<<(raw_ostream &OS, Type &T) { + T.print(OS); + return OS; +} + +// allow isa<PointerType>(x) to work without DerivedTypes.h included. +template <> struct isa_impl<PointerType, Type> { + static inline bool doit(const Type &Ty) { + return Ty.getTypeID() == Type::PointerTyID; + } +}; + +//===----------------------------------------------------------------------===// +// Provide specializations of GraphTraits to be able to treat a type as a +// graph of sub types. + +template <> struct GraphTraits<Type *> { + typedef Type *NodeRef; + typedef Type::subtype_iterator ChildIteratorType; + + static NodeRef getEntryNode(Type *T) { return T; } + static ChildIteratorType child_begin(NodeRef N) { return N->subtype_begin(); } + static ChildIteratorType child_end(NodeRef N) { return N->subtype_end(); } +}; + +template <> struct GraphTraits<const Type*> { + typedef const Type *NodeRef; + typedef Type::subtype_iterator ChildIteratorType; + + static NodeRef getEntryNode(NodeRef T) { return T; } + static ChildIteratorType child_begin(NodeRef N) { return N->subtype_begin(); } + static ChildIteratorType child_end(NodeRef N) { return N->subtype_end(); } +}; + +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_ISA_CONVERSION_FUNCTIONS(Type, LLVMTypeRef) + +/* Specialized opaque type conversions. + */ +inline Type **unwrap(LLVMTypeRef* Tys) { + return reinterpret_cast<Type**>(Tys); +} + +inline LLVMTypeRef *wrap(Type **Tys) { + return reinterpret_cast<LLVMTypeRef*>(const_cast<Type**>(Tys)); +} + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Use.h b/third_party/llvm-subzero/include/llvm/IR/Use.h new file mode 100644 index 0000000..e62eab5 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/Use.h
@@ -0,0 +1,164 @@ +//===-- llvm/Use.h - Definition of the Use class ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This defines the Use class. The Use class represents the operand of an +/// instruction or some other User instance which refers to a Value. The Use +/// class keeps the "use list" of the referenced value up to date. +/// +/// Pointer tagging is used to efficiently find the User corresponding to a Use +/// without having to store a User pointer in every Use. A User is preceded in +/// memory by all the Uses corresponding to its operands, and the low bits of +/// one of the fields (Prev) of the Use class are used to encode offsets to be +/// able to find that User given a pointer to any Use. For details, see: +/// +/// http://www.llvm.org/docs/ProgrammersManual.html#UserLayout +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_USE_H +#define LLVM_IR_USE_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/CBindingWrapping.h" +#include <cstddef> + +namespace llvm { + +class Value; +class User; +class Use; +template <typename> struct simplify_type; + +// Use** is only 4-byte aligned. +template <> class PointerLikeTypeTraits<Use **> { +public: + static inline void *getAsVoidPointer(Use **P) { return P; } + static inline Use **getFromVoidPointer(void *P) { + return static_cast<Use **>(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + +/// \brief A Use represents the edge between a Value definition and its users. +/// +/// This is notionally a two-dimensional linked list. It supports traversing +/// all of the uses for a particular value definition. It also supports jumping +/// directly to the used value when we arrive from the User's operands, and +/// jumping directly to the User when we arrive from the Value's uses. +/// +/// The pointer to the used Value is explicit, and the pointer to the User is +/// implicit. The implicit pointer is found via a waymarking algorithm +/// described in the programmer's manual: +/// +/// http://www.llvm.org/docs/ProgrammersManual.html#the-waymarking-algorithm +/// +/// This is essentially the single most memory intensive object in LLVM because +/// of the number of uses in the system. At the same time, the constant time +/// operations it allows are essential to many optimizations having reasonable +/// time complexity. +class Use { +public: + /// \brief Provide a fast substitute to std::swap<Use> + /// that also works with less standard-compliant compilers + void swap(Use &RHS); + + // A type for the word following an array of hung-off Uses in memory, which is + // a pointer back to their User with the bottom bit set. + typedef PointerIntPair<User *, 1, unsigned> UserRef; + +private: + Use(const Use &U) = delete; + + /// Destructor - Only for zap() + ~Use() { + if (Val) + removeFromList(); + } + + enum PrevPtrTag { zeroDigitTag, oneDigitTag, stopTag, fullStopTag }; + + /// Constructor + Use(PrevPtrTag tag) : Val(nullptr) { Prev.setInt(tag); } + +public: + operator Value *() const { return Val; } + Value *get() const { return Val; } + + /// \brief Returns the User that contains this Use. + /// + /// For an instruction operand, for example, this will return the + /// instruction. + User *getUser() const; + + inline void set(Value *Val); + + inline Value *operator=(Value *RHS); + inline const Use &operator=(const Use &RHS); + + Value *operator->() { return Val; } + const Value *operator->() const { return Val; } + + Use *getNext() const { return Next; } + + /// \brief Return the operand # of this use in its User. + unsigned getOperandNo() const; + + /// \brief Initializes the waymarking tags on an array of Uses. + /// + /// This sets up the array of Uses such that getUser() can find the User from + /// any of those Uses. + static Use *initTags(Use *Start, Use *Stop); + + /// \brief Destroys Use operands when the number of operands of + /// a User changes. + static void zap(Use *Start, const Use *Stop, bool del = false); + +private: + const Use *getImpliedUser() const; + + Value *Val; + Use *Next; + PointerIntPair<Use **, 2, PrevPtrTag> Prev; + + void setPrev(Use **NewPrev) { Prev.setPointer(NewPrev); } + void addToList(Use **List) { + Next = *List; + if (Next) + Next->setPrev(&Next); + setPrev(List); + *List = this; + } + void removeFromList() { + Use **StrippedPrev = Prev.getPointer(); + *StrippedPrev = Next; + if (Next) + Next->setPrev(StrippedPrev); + } + + friend class Value; +}; + +/// \brief Allow clients to treat uses just like values when using +/// casting operators. +template <> struct simplify_type<Use> { + typedef Value *SimpleType; + static SimpleType getSimplifiedValue(Use &Val) { return Val.get(); } +}; +template <> struct simplify_type<const Use> { + typedef /*const*/ Value *SimpleType; + static SimpleType getSimplifiedValue(const Use &Val) { return Val.get(); } +}; + +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Use, LLVMUseRef) + +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/User.h b/third_party/llvm-subzero/include/llvm/IR/User.h new file mode 100644 index 0000000..4d6b30c --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/User.h
@@ -0,0 +1,273 @@ +//===-- llvm/User.h - User class definition ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class defines the interface that one who uses a Value must implement. +// Each instance of the Value class keeps track of what User's have handles +// to it. +// +// * Instructions are the largest class of Users. +// * Constants may be users of other constants (think arrays and stuff) +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_USER_H +#define LLVM_IR_USER_H + +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/Value.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { + +template <typename T> class ArrayRef; +template <typename T> class MutableArrayRef; + +/// \brief Compile-time customization of User operands. +/// +/// Customizes operand-related allocators and accessors. +template <class> +struct OperandTraits; + +class User : public Value { + User(const User &) = delete; + template <unsigned> + friend struct HungoffOperandTraits; + virtual void anchor(); + + LLVM_ATTRIBUTE_ALWAYS_INLINE inline static void * + allocateFixedOperandUser(size_t, unsigned, unsigned); + +protected: + /// Allocate a User with an operand pointer co-allocated. + /// + /// This is used for subclasses which need to allocate a variable number + /// of operands, ie, 'hung off uses'. + void *operator new(size_t Size); + + /// Allocate a User with the operands co-allocated. + /// + /// This is used for subclasses which have a fixed number of operands. + void *operator new(size_t Size, unsigned Us); + + /// Allocate a User with the operands co-allocated. If DescBytes is non-zero + /// then allocate an additional DescBytes bytes before the operands. These + /// bytes can be accessed by calling getDescriptor. + /// + /// DescBytes needs to be divisible by sizeof(void *). The allocated + /// descriptor, if any, is aligned to sizeof(void *) bytes. + /// + /// This is used for subclasses which have a fixed number of operands. + void *operator new(size_t Size, unsigned Us, unsigned DescBytes); + + User(Type *ty, unsigned vty, Use *, unsigned NumOps) + : Value(ty, vty) { + assert(NumOps < (1u << NumUserOperandsBits) && "Too many operands"); + NumUserOperands = NumOps; + // If we have hung off uses, then the operand list should initially be + // null. + assert((!HasHungOffUses || !getOperandList()) && + "Error in initializing hung off uses for User"); + } + + /// \brief Allocate the array of Uses, followed by a pointer + /// (with bottom bit set) to the User. + /// \param IsPhi identifies callers which are phi nodes and which need + /// N BasicBlock* allocated along with N + void allocHungoffUses(unsigned N, bool IsPhi = false); + + /// \brief Grow the number of hung off uses. Note that allocHungoffUses + /// should be called if there are no uses. + void growHungoffUses(unsigned N, bool IsPhi = false); + +public: + ~User() override { + } + /// \brief Free memory allocated for User and Use objects. + void operator delete(void *Usr); + /// \brief Placement delete - required by std, but never called. + void operator delete(void*, unsigned) { + llvm_unreachable("Constructor throws?"); + } + /// \brief Placement delete - required by std, but never called. + void operator delete(void*, unsigned, bool) { + llvm_unreachable("Constructor throws?"); + } +protected: + template <int Idx, typename U> static Use &OpFrom(const U *that) { + return Idx < 0 + ? OperandTraits<U>::op_end(const_cast<U*>(that))[Idx] + : OperandTraits<U>::op_begin(const_cast<U*>(that))[Idx]; + } + template <int Idx> Use &Op() { + return OpFrom<Idx>(this); + } + template <int Idx> const Use &Op() const { + return OpFrom<Idx>(this); + } +private: + Use *&getHungOffOperands() { return *(reinterpret_cast<Use **>(this) - 1); } + + Use *getIntrusiveOperands() { + return reinterpret_cast<Use *>(this) - NumUserOperands; + } + + void setOperandList(Use *NewList) { + assert(HasHungOffUses && + "Setting operand list only required for hung off uses"); + getHungOffOperands() = NewList; + } +public: + Use *getOperandList() { + return HasHungOffUses ? getHungOffOperands() : getIntrusiveOperands(); + } + const Use *getOperandList() const { + return const_cast<User *>(this)->getOperandList(); + } + Value *getOperand(unsigned i) const { + assert(i < NumUserOperands && "getOperand() out of range!"); + return getOperandList()[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < NumUserOperands && "setOperand() out of range!"); + assert((!isa<Constant>((const Value*)this) || + isa<GlobalValue>((const Value*)this)) && + "Cannot mutate a constant with setOperand!"); + getOperandList()[i] = Val; + } + const Use &getOperandUse(unsigned i) const { + assert(i < NumUserOperands && "getOperandUse() out of range!"); + return getOperandList()[i]; + } + Use &getOperandUse(unsigned i) { + assert(i < NumUserOperands && "getOperandUse() out of range!"); + return getOperandList()[i]; + } + + unsigned getNumOperands() const { return NumUserOperands; } + + /// Returns the descriptor co-allocated with this User instance. + ArrayRef<const uint8_t> getDescriptor() const; + + /// Returns the descriptor co-allocated with this User instance. + MutableArrayRef<uint8_t> getDescriptor(); + + /// Set the number of operands on a GlobalVariable. + /// + /// GlobalVariable always allocates space for a single operands, but + /// doesn't always use it. + /// + /// FIXME: As that the number of operands is used to find the start of + /// the allocated memory in operator delete, we need to always think we have + /// 1 operand before delete. + void setGlobalVariableNumOperands(unsigned NumOps) { + assert(NumOps <= 1 && "GlobalVariable can only have 0 or 1 operands"); + NumUserOperands = NumOps; + } + + /// \brief Subclasses with hung off uses need to manage the operand count + /// themselves. In these instances, the operand count isn't used to find the + /// OperandList, so there's no issue in having the operand count change. + void setNumHungOffUseOperands(unsigned NumOps) { + assert(HasHungOffUses && "Must have hung off uses to use this method"); + assert(NumOps < (1u << NumUserOperandsBits) && "Too many operands"); + NumUserOperands = NumOps; + } + + // --------------------------------------------------------------------------- + // Operand Iterator interface... + // + typedef Use* op_iterator; + typedef const Use* const_op_iterator; + typedef iterator_range<op_iterator> op_range; + typedef iterator_range<const_op_iterator> const_op_range; + + op_iterator op_begin() { return getOperandList(); } + const_op_iterator op_begin() const { return getOperandList(); } + op_iterator op_end() { + return getOperandList() + NumUserOperands; + } + const_op_iterator op_end() const { + return getOperandList() + NumUserOperands; + } + op_range operands() { + return op_range(op_begin(), op_end()); + } + const_op_range operands() const { + return const_op_range(op_begin(), op_end()); + } + + /// \brief Iterator for directly iterating over the operand Values. + struct value_op_iterator + : iterator_adaptor_base<value_op_iterator, op_iterator, + std::random_access_iterator_tag, Value *, + ptrdiff_t, Value *, Value *> { + explicit value_op_iterator(Use *U = nullptr) : iterator_adaptor_base(U) {} + + Value *operator*() const { return *I; } + Value *operator->() const { return operator*(); } + }; + + value_op_iterator value_op_begin() { + return value_op_iterator(op_begin()); + } + value_op_iterator value_op_end() { + return value_op_iterator(op_end()); + } + iterator_range<value_op_iterator> operand_values() { + return make_range(value_op_begin(), value_op_end()); + } + + /// \brief Drop all references to operands. + /// + /// This function is in charge of "letting go" of all objects that this User + /// refers to. This allows one to 'delete' a whole class at a time, even + /// though there may be circular references... First all references are + /// dropped, and all use counts go to zero. Then everything is deleted for + /// real. Note that no operations are valid on an object that has "dropped + /// all references", except operator delete. + void dropAllReferences() { + for (Use &U : operands()) + U.set(nullptr); + } + + /// \brief Replace uses of one Value with another. + /// + /// Replaces all references to the "From" definition with references to the + /// "To" definition. + void replaceUsesOfWith(Value *From, Value *To); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return isa<Instruction>(V) || isa<Constant>(V); + } +}; +// Either Use objects, or a Use pointer can be prepended to User. +static_assert(AlignOf<Use>::Alignment >= AlignOf<User>::Alignment, + "Alignment is insufficient after objects prepended to User"); +static_assert(AlignOf<Use *>::Alignment >= AlignOf<User>::Alignment, + "Alignment is insufficient after objects prepended to User"); + +template<> struct simplify_type<User::op_iterator> { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(User::op_iterator &Val) { + return Val->get(); + } +}; +template<> struct simplify_type<User::const_op_iterator> { + typedef /*const*/ Value* SimpleType; + static SimpleType getSimplifiedValue(User::const_op_iterator &Val) { + return Val->get(); + } +}; + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IR/Value.def b/third_party/llvm-subzero/include/llvm/IR/Value.def new file mode 100644 index 0000000..48842d7 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/Value.def
@@ -0,0 +1,103 @@ +//===-------- llvm/IR/Value.def - File that describes Values ---v-*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains descriptions of the various LLVM values. This is +// used as a central place for enumerating the different values. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +// Provide definitions of macros so that users of this file do not have to +// define everything to use it... +// +#if !(defined HANDLE_GLOBAL_VALUE || defined HANDLE_CONSTANT || \ + defined HANDLE_INSTRUCTION || defined HANDLE_INLINE_ASM_VALUE || \ + defined HANDLE_METADATA_VALUE || defined HANDLE_VALUE || \ + defined HANDLE_CONSTANT_MARKER) +#error "Missing macro definition of HANDLE_VALUE*" +#endif + +#ifndef HANDLE_GLOBAL_VALUE +#define HANDLE_GLOBAL_VALUE(ValueName) HANDLE_CONSTANT(ValueName) +#endif + +#ifndef HANDLE_CONSTANT +#define HANDLE_CONSTANT(ValueName) HANDLE_VALUE(ValueName) +#endif + +#ifndef HANDLE_INSTRUCTION +#define HANDLE_INSTRUCTION(ValueName) HANDLE_VALUE(ValueName) +#endif + +#ifndef HANDLE_INLINE_ASM_VALUE +#define HANDLE_INLINE_ASM_VALUE(ValueName) HANDLE_VALUE(ValueName) +#endif + +#ifndef HANDLE_METADATA_VALUE +#define HANDLE_METADATA_VALUE(ValueName) HANDLE_VALUE(ValueName) +#endif + +#ifndef HANDLE_VALUE +#define HANDLE_VALUE(ValueName) +#endif + +#ifndef HANDLE_CONSTANT_MARKER +#define HANDLE_CONSTANT_MARKER(MarkerName, ValueName) +#endif + +HANDLE_VALUE(Argument) +HANDLE_VALUE(BasicBlock) +HANDLE_VALUE(MemoryUse) +HANDLE_VALUE(MemoryDef) +HANDLE_VALUE(MemoryPhi) + +HANDLE_GLOBAL_VALUE(Function) +HANDLE_GLOBAL_VALUE(GlobalAlias) +HANDLE_GLOBAL_VALUE(GlobalIFunc) +HANDLE_GLOBAL_VALUE(GlobalVariable) +HANDLE_CONSTANT(BlockAddress) +HANDLE_CONSTANT(ConstantExpr) + +// ConstantAggregate. +HANDLE_CONSTANT(ConstantArray) +HANDLE_CONSTANT(ConstantStruct) +HANDLE_CONSTANT(ConstantVector) + +// ConstantData. +HANDLE_CONSTANT(UndefValue) +HANDLE_CONSTANT(ConstantAggregateZero) +HANDLE_CONSTANT(ConstantDataArray) +HANDLE_CONSTANT(ConstantDataVector) +HANDLE_CONSTANT(ConstantInt) +HANDLE_CONSTANT(ConstantFP) +HANDLE_CONSTANT(ConstantPointerNull) +HANDLE_CONSTANT(ConstantTokenNone) + +HANDLE_METADATA_VALUE(MetadataAsValue) +HANDLE_INLINE_ASM_VALUE(InlineAsm) + +HANDLE_INSTRUCTION(Instruction) +// Enum values starting at InstructionVal are used for Instructions; +// don't add new values here! + +HANDLE_CONSTANT_MARKER(ConstantFirstVal, Function) +HANDLE_CONSTANT_MARKER(ConstantLastVal, ConstantTokenNone) +HANDLE_CONSTANT_MARKER(ConstantDataFirstVal, UndefValue) +HANDLE_CONSTANT_MARKER(ConstantDataLastVal, ConstantTokenNone) +HANDLE_CONSTANT_MARKER(ConstantAggregateFirstVal, ConstantArray) +HANDLE_CONSTANT_MARKER(ConstantAggregateLastVal, ConstantVector) + +#undef HANDLE_GLOBAL_VALUE +#undef HANDLE_CONSTANT +#undef HANDLE_INSTRUCTION +#undef HANDLE_METADATA_VALUE +#undef HANDLE_INLINE_ASM_VALUE +#undef HANDLE_VALUE +#undef HANDLE_CONSTANT_MARKER
diff --git a/third_party/llvm-subzero/include/llvm/IR/Value.h b/third_party/llvm-subzero/include/llvm/IR/Value.h new file mode 100644 index 0000000..b3d318c --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IR/Value.h
@@ -0,0 +1,817 @@ +//===-- llvm/Value.h - Definition of the Value class ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Value class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_VALUE_H +#define LLVM_IR_VALUE_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/Use.h" +#include "llvm/Support/CBindingWrapping.h" +#include "llvm/Support/Casting.h" + +namespace llvm { + +class APInt; +class Argument; +class AssemblyAnnotationWriter; +class BasicBlock; +class Constant; +class ConstantData; +class ConstantAggregate; +class DataLayout; +class Function; +class GlobalAlias; +class GlobalIFunc; +class GlobalIndirectSymbol; +class GlobalObject; +class GlobalValue; +class GlobalVariable; +class InlineAsm; +class Instruction; +class LLVMContext; +class Module; +class ModuleSlotTracker; +class StringRef; +class Twine; +class Type; +class ValueHandleBase; +class ValueSymbolTable; +class raw_ostream; + +template<typename ValueTy> class StringMapEntry; +typedef StringMapEntry<Value*> ValueName; + +//===----------------------------------------------------------------------===// +// Value Class +//===----------------------------------------------------------------------===// + +/// \brief LLVM Value Representation +/// +/// This is a very important LLVM class. It is the base class of all values +/// computed by a program that may be used as operands to other values. Value is +/// the super class of other important classes such as Instruction and Function. +/// All Values have a Type. Type is not a subclass of Value. Some values can +/// have a name and they belong to some Module. Setting the name on the Value +/// automatically updates the module's symbol table. +/// +/// Every value has a "use list" that keeps track of which other Values are +/// using this Value. A Value can also have an arbitrary number of ValueHandle +/// objects that watch it and listen to RAUW and Destroy events. See +/// llvm/IR/ValueHandle.h for details. +class Value { + Type *VTy; + Use *UseList; + + friend class ValueAsMetadata; // Allow access to IsUsedByMD. + friend class ValueHandleBase; + + const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast) + unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this? +protected: + /// \brief Hold subclass data that can be dropped. + /// + /// This member is similar to SubclassData, however it is for holding + /// information which may be used to aid optimization, but which may be + /// cleared to zero without affecting conservative interpretation. + unsigned char SubclassOptionalData : 7; + +private: + /// \brief Hold arbitrary subclass data. + /// + /// This member is defined by this class, but is not used for anything. + /// Subclasses can use it to hold whatever state they find useful. This + /// field is initialized to zero by the ctor. + unsigned short SubclassData; + +protected: + /// \brief The number of operands in the subclass. + /// + /// This member is defined by this class, but not used for anything. + /// Subclasses can use it to store their number of operands, if they have + /// any. + /// + /// This is stored here to save space in User on 64-bit hosts. Since most + /// instances of Value have operands, 32-bit hosts aren't significantly + /// affected. + /// + /// Note, this should *NOT* be used directly by any class other than User. + /// User uses this value to find the Use list. + enum : unsigned { NumUserOperandsBits = 28 }; + unsigned NumUserOperands : NumUserOperandsBits; + + // Use the same type as the bitfield above so that MSVC will pack them. + unsigned IsUsedByMD : 1; + unsigned HasName : 1; + unsigned HasHungOffUses : 1; + unsigned HasDescriptor : 1; + +private: + template <typename UseT> // UseT == 'Use' or 'const Use' + class use_iterator_impl + : public std::iterator<std::forward_iterator_tag, UseT *> { + UseT *U; + explicit use_iterator_impl(UseT *u) : U(u) {} + friend class Value; + + public: + use_iterator_impl() : U() {} + + bool operator==(const use_iterator_impl &x) const { return U == x.U; } + bool operator!=(const use_iterator_impl &x) const { return !operator==(x); } + + use_iterator_impl &operator++() { // Preincrement + assert(U && "Cannot increment end iterator!"); + U = U->getNext(); + return *this; + } + use_iterator_impl operator++(int) { // Postincrement + auto tmp = *this; + ++*this; + return tmp; + } + + UseT &operator*() const { + assert(U && "Cannot dereference end iterator!"); + return *U; + } + + UseT *operator->() const { return &operator*(); } + + operator use_iterator_impl<const UseT>() const { + return use_iterator_impl<const UseT>(U); + } + }; + + template <typename UserTy> // UserTy == 'User' or 'const User' + class user_iterator_impl + : public std::iterator<std::forward_iterator_tag, UserTy *> { + use_iterator_impl<Use> UI; + explicit user_iterator_impl(Use *U) : UI(U) {} + friend class Value; + + public: + user_iterator_impl() {} + + bool operator==(const user_iterator_impl &x) const { return UI == x.UI; } + bool operator!=(const user_iterator_impl &x) const { return !operator==(x); } + + /// \brief Returns true if this iterator is equal to user_end() on the value. + bool atEnd() const { return *this == user_iterator_impl(); } + + user_iterator_impl &operator++() { // Preincrement + ++UI; + return *this; + } + user_iterator_impl operator++(int) { // Postincrement + auto tmp = *this; + ++*this; + return tmp; + } + + // Retrieve a pointer to the current User. + UserTy *operator*() const { + return UI->getUser(); + } + + UserTy *operator->() const { return operator*(); } + + operator user_iterator_impl<const UserTy>() const { + return user_iterator_impl<const UserTy>(*UI); + } + + Use &getUse() const { return *UI; } + }; + + void operator=(const Value &) = delete; + Value(const Value &) = delete; + +protected: + Value(Type *Ty, unsigned scid); +public: + virtual ~Value(); + + /// \brief Support for debugging, callable in GDB: V->dump() + void dump() const; + + /// \brief Implement operator<< on Value. + /// @{ + void print(raw_ostream &O, bool IsForDebug = false) const; + void print(raw_ostream &O, ModuleSlotTracker &MST, + bool IsForDebug = false) const; + /// @} + + /// \brief Print the name of this Value out to the specified raw_ostream. + /// + /// This is useful when you just want to print 'int %reg126', not the + /// instruction that generated it. If you specify a Module for context, then + /// even constanst get pretty-printed; for example, the type of a null + /// pointer is printed symbolically. + /// @{ + void printAsOperand(raw_ostream &O, bool PrintType = true, + const Module *M = nullptr) const; + void printAsOperand(raw_ostream &O, bool PrintType, + ModuleSlotTracker &MST) const; + /// @} + + /// \brief All values are typed, get the type of this value. + Type *getType() const { return VTy; } + + /// \brief All values hold a context through their type. + LLVMContext &getContext() const; + + // \brief All values can potentially be named. + bool hasName() const { return HasName; } + ValueName *getValueName() const; + void setValueName(ValueName *VN); + +private: + void destroyValueName(); + void setNameImpl(const Twine &Name); + +public: + /// \brief Return a constant reference to the value's name. + /// + /// This is cheap and guaranteed to return the same reference as long as the + /// value is not modified. + StringRef getName() const; + + /// \brief Change the name of the value. + /// + /// Choose a new unique name if the provided name is taken. + /// + /// \param Name The new name; or "" if the value's name should be removed. + void setName(const Twine &Name); + + + /// \brief Transfer the name from V to this value. + /// + /// After taking V's name, sets V's name to empty. + /// + /// \note It is an error to call V->takeName(V). + void takeName(Value *V); + + /// \brief Change all uses of this to point to a new Value. + /// + /// Go through the uses list for this definition and make each use point to + /// "V" instead of "this". After this completes, 'this's use list is + /// guaranteed to be empty. + void replaceAllUsesWith(Value *V); + + /// replaceUsesOutsideBlock - Go through the uses list for this definition and + /// make each use point to "V" instead of "this" when the use is outside the + /// block. 'This's use list is expected to have at least one element. + /// Unlike replaceAllUsesWith this function does not support basic block + /// values or constant users. + void replaceUsesOutsideBlock(Value *V, BasicBlock *BB); + + //---------------------------------------------------------------------- + // Methods for handling the chain of uses of this Value. + // + // Materializing a function can introduce new uses, so these methods come in + // two variants: + // The methods that start with materialized_ check the uses that are + // currently known given which functions are materialized. Be very careful + // when using them since you might not get all uses. + // The methods that don't start with materialized_ assert that modules is + // fully materialized. + void assertModuleIsMaterialized() const; + + bool use_empty() const { + assertModuleIsMaterialized(); + return UseList == nullptr; + } + + typedef use_iterator_impl<Use> use_iterator; + typedef use_iterator_impl<const Use> const_use_iterator; + use_iterator materialized_use_begin() { return use_iterator(UseList); } + const_use_iterator materialized_use_begin() const { + return const_use_iterator(UseList); + } + use_iterator use_begin() { + assertModuleIsMaterialized(); + return materialized_use_begin(); + } + const_use_iterator use_begin() const { + assertModuleIsMaterialized(); + return materialized_use_begin(); + } + use_iterator use_end() { return use_iterator(); } + const_use_iterator use_end() const { return const_use_iterator(); } + iterator_range<use_iterator> materialized_uses() { + return make_range(materialized_use_begin(), use_end()); + } + iterator_range<const_use_iterator> materialized_uses() const { + return make_range(materialized_use_begin(), use_end()); + } + iterator_range<use_iterator> uses() { + assertModuleIsMaterialized(); + return materialized_uses(); + } + iterator_range<const_use_iterator> uses() const { + assertModuleIsMaterialized(); + return materialized_uses(); + } + + bool user_empty() const { + assertModuleIsMaterialized(); + return UseList == nullptr; + } + + typedef user_iterator_impl<User> user_iterator; + typedef user_iterator_impl<const User> const_user_iterator; + user_iterator materialized_user_begin() { return user_iterator(UseList); } + const_user_iterator materialized_user_begin() const { + return const_user_iterator(UseList); + } + user_iterator user_begin() { + assertModuleIsMaterialized(); + return materialized_user_begin(); + } + const_user_iterator user_begin() const { + assertModuleIsMaterialized(); + return materialized_user_begin(); + } + user_iterator user_end() { return user_iterator(); } + const_user_iterator user_end() const { return const_user_iterator(); } + User *user_back() { + assertModuleIsMaterialized(); + return *materialized_user_begin(); + } + const User *user_back() const { + assertModuleIsMaterialized(); + return *materialized_user_begin(); + } + iterator_range<user_iterator> materialized_users() { + return make_range(materialized_user_begin(), user_end()); + } + iterator_range<const_user_iterator> materialized_users() const { + return make_range(materialized_user_begin(), user_end()); + } + iterator_range<user_iterator> users() { + assertModuleIsMaterialized(); + return materialized_users(); + } + iterator_range<const_user_iterator> users() const { + assertModuleIsMaterialized(); + return materialized_users(); + } + + /// \brief Return true if there is exactly one user of this value. + /// + /// This is specialized because it is a common request and does not require + /// traversing the whole use list. + bool hasOneUse() const { + const_use_iterator I = use_begin(), E = use_end(); + if (I == E) return false; + return ++I == E; + } + + /// \brief Return true if this Value has exactly N users. + bool hasNUses(unsigned N) const; + + /// \brief Return true if this value has N users or more. + /// + /// This is logically equivalent to getNumUses() >= N. + bool hasNUsesOrMore(unsigned N) const; + + /// \brief Check if this value is used in the specified basic block. + bool isUsedInBasicBlock(const BasicBlock *BB) const; + + /// \brief This method computes the number of uses of this Value. + /// + /// This is a linear time operation. Use hasOneUse, hasNUses, or + /// hasNUsesOrMore to check for specific values. + unsigned getNumUses() const; + + /// \brief This method should only be used by the Use class. + void addUse(Use &U) { U.addToList(&UseList); } + + /// \brief Concrete subclass of this. + /// + /// An enumeration for keeping track of the concrete subclass of Value that + /// is actually instantiated. Values of this enumeration are kept in the + /// Value classes SubclassID field. They are used for concrete type + /// identification. + enum ValueTy { +#define HANDLE_VALUE(Name) Name##Val, +#include "llvm/IR/Value.def" + + // Markers: +#define HANDLE_CONSTANT_MARKER(Marker, Constant) Marker = Constant##Val, +#include "llvm/IR/Value.def" + }; + + /// \brief Return an ID for the concrete type of this object. + /// + /// This is used to implement the classof checks. This should not be used + /// for any other purpose, as the values may change as LLVM evolves. Also, + /// note that for instructions, the Instruction's opcode is added to + /// InstructionVal. So this means three things: + /// # there is no value with code InstructionVal (no opcode==0). + /// # there are more possible values for the value type than in ValueTy enum. + /// # the InstructionVal enumerator must be the highest valued enumerator in + /// the ValueTy enum. + unsigned getValueID() const { + return SubclassID; + } + + /// \brief Return the raw optional flags value contained in this value. + /// + /// This should only be used when testing two Values for equivalence. + unsigned getRawSubclassOptionalData() const { + return SubclassOptionalData; + } + + /// \brief Clear the optional flags contained in this value. + void clearSubclassOptionalData() { + SubclassOptionalData = 0; + } + + /// \brief Check the optional flags for equality. + bool hasSameSubclassOptionalData(const Value *V) const { + return SubclassOptionalData == V->SubclassOptionalData; + } + + /// \brief Return true if there is a value handle associated with this value. + bool hasValueHandle() const { return HasValueHandle; } + + /// \brief Return true if there is metadata referencing this value. + bool isUsedByMetadata() const { return IsUsedByMD; } + + /// \brief Strip off pointer casts, all-zero GEPs, and aliases. + /// + /// Returns the original uncasted value. If this is called on a non-pointer + /// value, it returns 'this'. + Value *stripPointerCasts(); + const Value *stripPointerCasts() const { + return const_cast<Value*>(this)->stripPointerCasts(); + } + + /// \brief Strip off pointer casts and all-zero GEPs. + /// + /// Returns the original uncasted value. If this is called on a non-pointer + /// value, it returns 'this'. + Value *stripPointerCastsNoFollowAliases(); + const Value *stripPointerCastsNoFollowAliases() const { + return const_cast<Value*>(this)->stripPointerCastsNoFollowAliases(); + } + + /// \brief Strip off pointer casts and all-constant inbounds GEPs. + /// + /// Returns the original pointer value. If this is called on a non-pointer + /// value, it returns 'this'. + Value *stripInBoundsConstantOffsets(); + const Value *stripInBoundsConstantOffsets() const { + return const_cast<Value*>(this)->stripInBoundsConstantOffsets(); + } + + /// \brief Accumulate offsets from \a stripInBoundsConstantOffsets(). + /// + /// Stores the resulting constant offset stripped into the APInt provided. + /// The provided APInt will be extended or truncated as needed to be the + /// correct bitwidth for an offset of this pointer type. + /// + /// If this is called on a non-pointer value, it returns 'this'. + Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, + APInt &Offset); + const Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, + APInt &Offset) const { + return const_cast<Value *>(this) + ->stripAndAccumulateInBoundsConstantOffsets(DL, Offset); + } + + /// \brief Strip off pointer casts and inbounds GEPs. + /// + /// Returns the original pointer value. If this is called on a non-pointer + /// value, it returns 'this'. + Value *stripInBoundsOffsets(); + const Value *stripInBoundsOffsets() const { + return const_cast<Value*>(this)->stripInBoundsOffsets(); + } + + /// \brief Returns the number of bytes known to be dereferenceable for the + /// pointer value. + /// + /// If CanBeNull is set by this function the pointer can either be null or be + /// dereferenceable up to the returned number of bytes. + unsigned getPointerDereferenceableBytes(const DataLayout &DL, + bool &CanBeNull) const; + + /// \brief Returns an alignment of the pointer value. + /// + /// Returns an alignment which is either specified explicitly, e.g. via + /// align attribute of a function argument, or guaranteed by DataLayout. + unsigned getPointerAlignment(const DataLayout &DL) const; + + /// \brief Translate PHI node to its predecessor from the given basic block. + /// + /// If this value is a PHI node with CurBB as its parent, return the value in + /// the PHI node corresponding to PredBB. If not, return ourself. This is + /// useful if you want to know the value something has in a predecessor + /// block. + Value *DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB); + + const Value *DoPHITranslation(const BasicBlock *CurBB, + const BasicBlock *PredBB) const{ + return const_cast<Value*>(this)->DoPHITranslation(CurBB, PredBB); + } + + /// \brief The maximum alignment for instructions. + /// + /// This is the greatest alignment value supported by load, store, and alloca + /// instructions, and global values. + static const unsigned MaxAlignmentExponent = 29; + static const unsigned MaximumAlignment = 1u << MaxAlignmentExponent; + + /// \brief Mutate the type of this Value to be of the specified type. + /// + /// Note that this is an extremely dangerous operation which can create + /// completely invalid IR very easily. It is strongly recommended that you + /// recreate IR objects with the right types instead of mutating them in + /// place. + void mutateType(Type *Ty) { + VTy = Ty; + } + + /// \brief Sort the use-list. + /// + /// Sorts the Value's use-list by Cmp using a stable mergesort. Cmp is + /// expected to compare two \a Use references. + template <class Compare> void sortUseList(Compare Cmp); + + /// \brief Reverse the use-list. + void reverseUseList(); + +private: + /// \brief Merge two lists together. + /// + /// Merges \c L and \c R using \c Cmp. To enable stable sorts, always pushes + /// "equal" items from L before items from R. + /// + /// \return the first element in the list. + /// + /// \note Completely ignores \a Use::Prev (doesn't read, doesn't update). + template <class Compare> + static Use *mergeUseLists(Use *L, Use *R, Compare Cmp) { + Use *Merged; + Use **Next = &Merged; + + for (;;) { + if (!L) { + *Next = R; + break; + } + if (!R) { + *Next = L; + break; + } + if (Cmp(*R, *L)) { + *Next = R; + Next = &R->Next; + R = R->Next; + } else { + *Next = L; + Next = &L->Next; + L = L->Next; + } + } + + return Merged; + } + + /// \brief Tail-recursive helper for \a mergeUseLists(). + /// + /// \param[out] Next the first element in the list. + template <class Compare> + static void mergeUseListsImpl(Use *L, Use *R, Use **Next, Compare Cmp); + +protected: + unsigned short getSubclassDataFromValue() const { return SubclassData; } + void setValueSubclassData(unsigned short D) { SubclassData = D; } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const Value &V) { + V.print(OS); + return OS; +} + +void Use::set(Value *V) { + if (Val) removeFromList(); + Val = V; + if (V) V->addUse(*this); +} + +Value *Use::operator=(Value *RHS) { + set(RHS); + return RHS; +} + +const Use &Use::operator=(const Use &RHS) { + set(RHS.Val); + return *this; +} + +template <class Compare> void Value::sortUseList(Compare Cmp) { + if (!UseList || !UseList->Next) + // No need to sort 0 or 1 uses. + return; + + // Note: this function completely ignores Prev pointers until the end when + // they're fixed en masse. + + // Create a binomial vector of sorted lists, visiting uses one at a time and + // merging lists as necessary. + const unsigned MaxSlots = 32; + Use *Slots[MaxSlots]; + + // Collect the first use, turning it into a single-item list. + Use *Next = UseList->Next; + UseList->Next = nullptr; + unsigned NumSlots = 1; + Slots[0] = UseList; + + // Collect all but the last use. + while (Next->Next) { + Use *Current = Next; + Next = Current->Next; + + // Turn Current into a single-item list. + Current->Next = nullptr; + + // Save Current in the first available slot, merging on collisions. + unsigned I; + for (I = 0; I < NumSlots; ++I) { + if (!Slots[I]) + break; + + // Merge two lists, doubling the size of Current and emptying slot I. + // + // Since the uses in Slots[I] originally preceded those in Current, send + // Slots[I] in as the left parameter to maintain a stable sort. + Current = mergeUseLists(Slots[I], Current, Cmp); + Slots[I] = nullptr; + } + // Check if this is a new slot. + if (I == NumSlots) { + ++NumSlots; + assert(NumSlots <= MaxSlots && "Use list bigger than 2^32"); + } + + // Found an open slot. + Slots[I] = Current; + } + + // Merge all the lists together. + assert(Next && "Expected one more Use"); + assert(!Next->Next && "Expected only one Use"); + UseList = Next; + for (unsigned I = 0; I < NumSlots; ++I) + if (Slots[I]) + // Since the uses in Slots[I] originally preceded those in UseList, send + // Slots[I] in as the left parameter to maintain a stable sort. + UseList = mergeUseLists(Slots[I], UseList, Cmp); + + // Fix the Prev pointers. + for (Use *I = UseList, **Prev = &UseList; I; I = I->Next) { + I->setPrev(Prev); + Prev = &I->Next; + } +} + +// isa - Provide some specializations of isa so that we don't have to include +// the subtype header files to test to see if the value is a subclass... +// +template <> struct isa_impl<Constant, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() >= Value::ConstantFirstVal && + Val.getValueID() <= Value::ConstantLastVal; + } +}; + +template <> struct isa_impl<ConstantData, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() >= Value::ConstantDataFirstVal && + Val.getValueID() <= Value::ConstantDataLastVal; + } +}; + +template <> struct isa_impl<ConstantAggregate, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() >= Value::ConstantAggregateFirstVal && + Val.getValueID() <= Value::ConstantAggregateLastVal; + } +}; + +template <> struct isa_impl<Argument, Value> { + static inline bool doit (const Value &Val) { + return Val.getValueID() == Value::ArgumentVal; + } +}; + +template <> struct isa_impl<InlineAsm, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::InlineAsmVal; + } +}; + +template <> struct isa_impl<Instruction, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() >= Value::InstructionVal; + } +}; + +template <> struct isa_impl<BasicBlock, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::BasicBlockVal; + } +}; + +template <> struct isa_impl<Function, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::FunctionVal; + } +}; + +template <> struct isa_impl<GlobalVariable, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::GlobalVariableVal; + } +}; + +template <> struct isa_impl<GlobalAlias, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::GlobalAliasVal; + } +}; + +template <> struct isa_impl<GlobalIFunc, Value> { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::GlobalIFuncVal; + } +}; + +template <> struct isa_impl<GlobalIndirectSymbol, Value> { + static inline bool doit(const Value &Val) { + return isa<GlobalAlias>(Val) || isa<GlobalIFunc>(Val); + } +}; + +template <> struct isa_impl<GlobalValue, Value> { + static inline bool doit(const Value &Val) { + return isa<GlobalObject>(Val) || isa<GlobalIndirectSymbol>(Val); + } +}; + +template <> struct isa_impl<GlobalObject, Value> { + static inline bool doit(const Value &Val) { + return isa<GlobalVariable>(Val) || isa<Function>(Val); + } +}; + +// Value* is only 4-byte aligned. +template<> +class PointerLikeTypeTraits<Value*> { + typedef Value* PT; +public: + static inline void *getAsVoidPointer(PT P) { return P; } + static inline PT getFromVoidPointer(void *P) { + return static_cast<PT>(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_ISA_CONVERSION_FUNCTIONS(Value, LLVMValueRef) + +// Specialized opaque value conversions. +inline Value **unwrap(LLVMValueRef *Vals) { + return reinterpret_cast<Value**>(Vals); +} + +template<typename T> +inline T **unwrap(LLVMValueRef *Vals, unsigned Length) { +#ifndef NDEBUG + for (LLVMValueRef *I = Vals, *E = Vals + Length; I != E; ++I) + unwrap<T>(*I); // For side effect of calling assert on invalid usage. +#endif + (void)Length; + return reinterpret_cast<T**>(Vals); +} + +inline LLVMValueRef *wrap(const Value **Vals) { + return reinterpret_cast<LLVMValueRef*>(const_cast<Value**>(Vals)); +} + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/IRReader/IRReader.h b/third_party/llvm-subzero/include/llvm/IRReader/IRReader.h new file mode 100644 index 0000000..7b24ec1 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/IRReader/IRReader.h
@@ -0,0 +1,50 @@ +//===---- llvm/IRReader/IRReader.h - Reader for LLVM IR files ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines functions for reading LLVM IR. They support both +// Bitcode and Assembly, automatically detecting the input format. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IRREADER_IRREADER_H +#define LLVM_IRREADER_IRREADER_H + +#include <memory> + +namespace llvm { + +class StringRef; +class MemoryBufferRef; +class Module; +class SMDiagnostic; +class LLVMContext; + +/// If the given file holds a bitcode image, return a Module +/// for it which does lazy deserialization of function bodies. Otherwise, +/// attempt to parse it as LLVM Assembly and return a fully populated +/// Module. The ShouldLazyLoadMetadata flag is passed down to the bitcode +/// reader to optionally enable lazy metadata loading. +std::unique_ptr<Module> +getLazyIRFileModule(StringRef Filename, SMDiagnostic &Err, LLVMContext &Context, + bool ShouldLazyLoadMetadata = false); + +/// If the given MemoryBuffer holds a bitcode image, return a Module +/// for it. Otherwise, attempt to parse it as LLVM Assembly and return +/// a Module for it. +std::unique_ptr<Module> parseIR(MemoryBufferRef Buffer, SMDiagnostic &Err, + LLVMContext &Context); + +/// If the given file holds a bitcode image, return a Module for it. +/// Otherwise, attempt to parse it as LLVM Assembly and return a Module +/// for it. +std::unique_ptr<Module> parseIRFile(StringRef Filename, SMDiagnostic &Err, + LLVMContext &Context); +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/AArch64TargetParser.def b/third_party/llvm-subzero/include/llvm/Support/AArch64TargetParser.def new file mode 100644 index 0000000..a2e30e7 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/AArch64TargetParser.def
@@ -0,0 +1,75 @@ +//===- AARCH64TargetParser.def - AARCH64 target parsing defines ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides defines to build up the AARCH64 target parser's logic. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +#ifndef AARCH64_ARCH +#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) +#endif +AARCH64_ARCH("invalid", AK_INVALID, nullptr, nullptr, + ARMBuildAttrs::CPUArch::v8_A, FK_NONE, AArch64::AEK_NONE) +AARCH64_ARCH("armv8-a", AK_ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8_A, + FK_CRYPTO_NEON_FP_ARMV8, + (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | + AArch64::AEK_SIMD)) +AARCH64_ARCH("armv8.1-a", AK_ARMV8_1A, "8.1-A", "v8.1a", + ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8, + (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | + AArch64::AEK_SIMD)) +AARCH64_ARCH("armv8.2-a", AK_ARMV8_2A, "8.2-A", "v8.2a", + ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8, + (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | + AArch64::AEK_SIMD | AArch64::AEK_RAS)) +#undef AARCH64_ARCH + +#ifndef AARCH64_ARCH_EXT_NAME +#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) +#endif +// FIXME: This would be nicer were it tablegen +AARCH64_ARCH_EXT_NAME("invalid", AArch64::AEK_INVALID, nullptr, nullptr) +AARCH64_ARCH_EXT_NAME("none", AArch64::AEK_NONE, nullptr, nullptr) +AARCH64_ARCH_EXT_NAME("crc", AArch64::AEK_CRC, "+crc", "-crc") +AARCH64_ARCH_EXT_NAME("crypto", AArch64::AEK_CRYPTO, "+crypto","-crypto") +AARCH64_ARCH_EXT_NAME("fp", AArch64::AEK_FP, "+fp-armv8", "-fp-armv8") +AARCH64_ARCH_EXT_NAME("simd", AArch64::AEK_SIMD, "+neon", "-neon") +AARCH64_ARCH_EXT_NAME("fp16", AArch64::AEK_FP16, "+fullfp16", "-fullfp16") +AARCH64_ARCH_EXT_NAME("profile", AArch64::AEK_PROFILE, "+spe", "-spe") +AARCH64_ARCH_EXT_NAME("ras", AArch64::AEK_RAS, "+ras", "-ras") +#undef AARCH64_ARCH_EXT_NAME + +#ifndef AARCH64_CPU_NAME +#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) +#endif +AARCH64_CPU_NAME("cortex-a35", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("cortex-a53", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true, + ( AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("cortex-a57", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("cortex-a72", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("cortex-a73", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("cyclone", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("exynos-m1", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("exynos-m2", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("kryo", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("vulcan", AK_ARMV8_1A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +// Invalid CPU +AARCH64_CPU_NAME("invalid", AK_INVALID, FK_INVALID, true, AArch64::AEK_INVALID) +#undef AARCH64_CPU_NAME
diff --git a/third_party/llvm-subzero/include/llvm/Support/ARMBuildAttributes.h b/third_party/llvm-subzero/include/llvm/Support/ARMBuildAttributes.h new file mode 100644 index 0000000..f447cd0 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ARMBuildAttributes.h
@@ -0,0 +1,233 @@ +//===-- ARMBuildAttributes.h - ARM Build Attributes -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains enumerations and support routines for ARM build attributes +// as defined in ARM ABI addenda document (ABI release 2.08). +// +// ELF for the ARM Architecture r2.09 - November 30, 2012 +// +// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/IHI0044E_aaelf.pdf +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ARMBUILDATTRIBUTES_H +#define LLVM_SUPPORT_ARMBUILDATTRIBUTES_H + +namespace llvm { +class StringRef; + +namespace ARMBuildAttrs { + +enum SpecialAttr { + // This is for the .cpu asm attr. It translates into one or more + // AttrType (below) entries in the .ARM.attributes section in the ELF. + SEL_CPU +}; + +enum AttrType { + // Rest correspond to ELF/.ARM.attributes + File = 1, + CPU_raw_name = 4, + CPU_name = 5, + CPU_arch = 6, + CPU_arch_profile = 7, + ARM_ISA_use = 8, + THUMB_ISA_use = 9, + FP_arch = 10, + WMMX_arch = 11, + Advanced_SIMD_arch = 12, + PCS_config = 13, + ABI_PCS_R9_use = 14, + ABI_PCS_RW_data = 15, + ABI_PCS_RO_data = 16, + ABI_PCS_GOT_use = 17, + ABI_PCS_wchar_t = 18, + ABI_FP_rounding = 19, + ABI_FP_denormal = 20, + ABI_FP_exceptions = 21, + ABI_FP_user_exceptions = 22, + ABI_FP_number_model = 23, + ABI_align_needed = 24, + ABI_align_preserved = 25, + ABI_enum_size = 26, + ABI_HardFP_use = 27, + ABI_VFP_args = 28, + ABI_WMMX_args = 29, + ABI_optimization_goals = 30, + ABI_FP_optimization_goals = 31, + compatibility = 32, + CPU_unaligned_access = 34, + FP_HP_extension = 36, + ABI_FP_16bit_format = 38, + MPextension_use = 42, // recoded from 70 (ABI r2.08) + DIV_use = 44, + DSP_extension = 46, + also_compatible_with = 65, + conformance = 67, + Virtualization_use = 68, + + /// Legacy Tags + Section = 2, // deprecated (ABI r2.09) + Symbol = 3, // deprecated (ABI r2.09) + ABI_align8_needed = 24, // renamed to ABI_align_needed (ABI r2.09) + ABI_align8_preserved = 25, // renamed to ABI_align_preserved (ABI r2.09) + nodefaults = 64, // deprecated (ABI r2.09) + T2EE_use = 66, // deprecated (ABI r2.09) + MPextension_use_old = 70 // recoded to MPextension_use (ABI r2.08) +}; + +StringRef AttrTypeAsString(unsigned Attr, bool HasTagPrefix = true); +StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix = true); +int AttrTypeFromString(StringRef Tag); + +// Magic numbers for .ARM.attributes +enum AttrMagic { + Format_Version = 0x41 +}; + +// Legal Values for CPU_arch, (=6), uleb128 +enum CPUArch { + Pre_v4 = 0, + v4 = 1, // e.g. SA110 + v4T = 2, // e.g. ARM7TDMI + v5T = 3, // e.g. ARM9TDMI + v5TE = 4, // e.g. ARM946E_S + v5TEJ = 5, // e.g. ARM926EJ_S + v6 = 6, // e.g. ARM1136J_S + v6KZ = 7, // e.g. ARM1176JZ_S + v6T2 = 8, // e.g. ARM1156T2_S + v6K = 9, // e.g. ARM1176JZ_S + v7 = 10, // e.g. Cortex A8, Cortex M3 + v6_M = 11, // e.g. Cortex M1 + v6S_M = 12, // v6_M with the System extensions + v7E_M = 13, // v7_M with DSP extensions + v8_A = 14, // v8_A AArch32 + v8_M_Base= 16, // v8_M_Base AArch32 + v8_M_Main= 17, // v8_M_Main AArch32 +}; + +enum CPUArchProfile { // (=7), uleb128 + Not_Applicable = 0, // pre v7, or cross-profile code + ApplicationProfile = (0x41), // 'A' (e.g. for Cortex A8) + RealTimeProfile = (0x52), // 'R' (e.g. for Cortex R4) + MicroControllerProfile = (0x4D), // 'M' (e.g. for Cortex M3) + SystemProfile = (0x53) // 'S' Application or real-time profile +}; + +// The following have a lot of common use cases +enum { + Not_Allowed = 0, + Allowed = 1, + + // Tag_ARM_ISA_use (=8), uleb128 + + // Tag_THUMB_ISA_use, (=9), uleb128 + AllowThumb32 = 2, // 32-bit Thumb (implies 16-bit instructions) + AllowThumbDerived = 3, // Thumb allowed, derived from arch/profile + + // Tag_FP_arch (=10), uleb128 (formerly Tag_VFP_arch = 10) + AllowFPv2 = 2, // v2 FP ISA permitted (implies use of the v1 FP ISA) + AllowFPv3A = 3, // v3 FP ISA permitted (implies use of the v2 FP ISA) + AllowFPv3B = 4, // v3 FP ISA permitted, but only D0-D15, S0-S31 + AllowFPv4A = 5, // v4 FP ISA permitted (implies use of v3 FP ISA) + AllowFPv4B = 6, // v4 FP ISA was permitted, but only D0-D15, S0-S31 + AllowFPARMv8A = 7, // Use of the ARM v8-A FP ISA was permitted + AllowFPARMv8B = 8, // Use of the ARM v8-A FP ISA was permitted, but only + // D0-D15, S0-S31 + + // Tag_WMMX_arch, (=11), uleb128 + AllowWMMXv1 = 1, // The user permitted this entity to use WMMX v1 + AllowWMMXv2 = 2, // The user permitted this entity to use WMMX v2 + + // Tag_Advanced_SIMD_arch, (=12), uleb128 + AllowNeon = 1, // SIMDv1 was permitted + AllowNeon2 = 2, // SIMDv2 was permitted (Half-precision FP, MAC operations) + AllowNeonARMv8 = 3, // ARM v8-A SIMD was permitted + AllowNeonARMv8_1a = 4,// ARM v8.1-A SIMD was permitted (RDMA) + + // Tag_ABI_PCS_R9_use, (=14), uleb128 + R9IsGPR = 0, // R9 used as v6 (just another callee-saved register) + R9IsSB = 1, // R9 used as a global static base rgister + R9IsTLSPointer = 2, // R9 used as a thread local storage pointer + R9Reserved = 3, // R9 not used by code associated with attributed entity + + // Tag_ABI_PCS_RW_data, (=15), uleb128 + AddressRWPCRel = 1, // Address RW static data PC-relative + AddressRWSBRel = 2, // Address RW static data SB-relative + AddressRWNone = 3, // No RW static data permitted + + // Tag_ABI_PCS_RO_data, (=14), uleb128 + AddressROPCRel = 1, // Address RO static data PC-relative + AddressRONone = 2, // No RO static data permitted + + // Tag_ABI_PCS_GOT_use, (=17), uleb128 + AddressDirect = 1, // Address imported data directly + AddressGOT = 2, // Address imported data indirectly (via GOT) + + // Tag_ABI_PCS_wchar_t, (=18), uleb128 + WCharProhibited = 0, // wchar_t is not used + WCharWidth2Bytes = 2, // sizeof(wchar_t) == 2 + WCharWidth4Bytes = 4, // sizeof(wchar_t) == 4 + + // Tag_ABI_FP_denormal, (=20), uleb128 + PositiveZero = 0, + IEEEDenormals = 1, + PreserveFPSign = 2, // sign when flushed-to-zero is preserved + + // Tag_ABI_FP_number_model, (=23), uleb128 + AllowRTABI = 2, // numbers, infinities, and one quiet NaN (see [RTABI]) + AllowIEE754 = 3, // this code to use all the IEEE 754-defined FP encodings + + // Tag_ABI_enum_size, (=26), uleb128 + EnumProhibited = 0, // The user prohibited the use of enums when building + // this entity. + EnumSmallest = 1, // Enum is smallest container big enough to hold all + // values. + Enum32Bit = 2, // Enum is at least 32 bits. + Enum32BitABI = 3, // Every enumeration visible across an ABI-complying + // interface contains a value needing 32 bits to encode + // it; other enums can be containerized. + + // Tag_ABI_HardFP_use, (=27), uleb128 + HardFPImplied = 0, // FP use should be implied by Tag_FP_arch + HardFPSinglePrecision = 1, // Single-precision only + + // Tag_ABI_VFP_args, (=28), uleb128 + BaseAAPCS = 0, + HardFPAAPCS = 1, + + // Tag_FP_HP_extension, (=36), uleb128 + AllowHPFP = 1, // Allow use of Half Precision FP + + // Tag_FP_16bit_format, (=38), uleb128 + FP16FormatIEEE = 1, + + // Tag_MPextension_use, (=42), uleb128 + AllowMP = 1, // Allow use of MP extensions + + // Tag_DIV_use, (=44), uleb128 + // Note: AllowDIVExt must be emitted if and only if the permission to use + // hardware divide cannot be conveyed using AllowDIVIfExists or DisallowDIV + AllowDIVIfExists = 0, // Allow hardware divide if available in arch, or no + // info exists. + DisallowDIV = 1, // Hardware divide explicitly disallowed. + AllowDIVExt = 2, // Allow hardware divide as optional architecture + // extension above the base arch specified by + // Tag_CPU_arch and Tag_CPU_arch_profile. + + // Tag_Virtualization_use, (=68), uleb128 + AllowTZ = 1, + AllowVirtualization = 2, + AllowTZVirtualization = 3 +}; + +} // namespace ARMBuildAttrs +} // namespace llvm + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/ARMTargetParser.def b/third_party/llvm-subzero/include/llvm/Support/ARMTargetParser.def new file mode 100644 index 0000000..49e6860 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ARMTargetParser.def
@@ -0,0 +1,243 @@ +//===- ARMTargetParser.def - ARM target parsing defines ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides defines to build up the ARM target parser's logic. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +#ifndef ARM_FPU +#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) +#endif +ARM_FPU("invalid", FK_INVALID, FV_NONE, NS_None, FR_None) +ARM_FPU("none", FK_NONE, FV_NONE, NS_None, FR_None) +ARM_FPU("vfp", FK_VFP, FV_VFPV2, NS_None, FR_None) +ARM_FPU("vfpv2", FK_VFPV2, FV_VFPV2, NS_None, FR_None) +ARM_FPU("vfpv3", FK_VFPV3, FV_VFPV3, NS_None, FR_None) +ARM_FPU("vfpv3-fp16", FK_VFPV3_FP16, FV_VFPV3_FP16, NS_None, FR_None) +ARM_FPU("vfpv3-d16", FK_VFPV3_D16, FV_VFPV3, NS_None, FR_D16) +ARM_FPU("vfpv3-d16-fp16", FK_VFPV3_D16_FP16, FV_VFPV3_FP16, NS_None, FR_D16) +ARM_FPU("vfpv3xd", FK_VFPV3XD, FV_VFPV3, NS_None, FR_SP_D16) +ARM_FPU("vfpv3xd-fp16", FK_VFPV3XD_FP16, FV_VFPV3_FP16, NS_None, FR_SP_D16) +ARM_FPU("vfpv4", FK_VFPV4, FV_VFPV4, NS_None, FR_None) +ARM_FPU("vfpv4-d16", FK_VFPV4_D16, FV_VFPV4, NS_None, FR_D16) +ARM_FPU("fpv4-sp-d16", FK_FPV4_SP_D16, FV_VFPV4, NS_None, FR_SP_D16) +ARM_FPU("fpv5-d16", FK_FPV5_D16, FV_VFPV5, NS_None, FR_D16) +ARM_FPU("fpv5-sp-d16", FK_FPV5_SP_D16, FV_VFPV5, NS_None, FR_SP_D16) +ARM_FPU("fp-armv8", FK_FP_ARMV8, FV_VFPV5, NS_None, FR_None) +ARM_FPU("neon", FK_NEON, FV_VFPV3, NS_Neon, FR_None) +ARM_FPU("neon-fp16", FK_NEON_FP16, FV_VFPV3_FP16, NS_Neon, FR_None) +ARM_FPU("neon-vfpv4", FK_NEON_VFPV4, FV_VFPV4, NS_Neon, FR_None) +ARM_FPU("neon-fp-armv8", FK_NEON_FP_ARMV8, FV_VFPV5, NS_Neon, FR_None) +ARM_FPU("crypto-neon-fp-armv8", FK_CRYPTO_NEON_FP_ARMV8, FV_VFPV5, NS_Crypto, + FR_None) +ARM_FPU("softvfp", FK_SOFTVFP, FV_NONE, NS_None, FR_None) +#undef ARM_FPU + +#ifndef ARM_ARCH +#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) +#endif +ARM_ARCH("invalid", AK_INVALID, nullptr, nullptr, + ARMBuildAttrs::CPUArch::Pre_v4, FK_NONE, ARM::AEK_NONE) +ARM_ARCH("armv2", AK_ARMV2, "2", "v2", ARMBuildAttrs::CPUArch::Pre_v4, + FK_NONE, ARM::AEK_NONE) +ARM_ARCH("armv2a", AK_ARMV2A, "2A", "v2a", ARMBuildAttrs::CPUArch::Pre_v4, + FK_NONE, ARM::AEK_NONE) +ARM_ARCH("armv3", AK_ARMV3, "3", "v3", ARMBuildAttrs::CPUArch::Pre_v4, + FK_NONE, ARM::AEK_NONE) +ARM_ARCH("armv3m", AK_ARMV3M, "3M", "v3m", ARMBuildAttrs::CPUArch::Pre_v4, + FK_NONE, ARM::AEK_NONE) +ARM_ARCH("armv4", AK_ARMV4, "4", "v4", ARMBuildAttrs::CPUArch::v4, + FK_NONE, ARM::AEK_NONE) +ARM_ARCH("armv4t", AK_ARMV4T, "4T", "v4t", ARMBuildAttrs::CPUArch::v4T, + FK_NONE, ARM::AEK_NONE) +ARM_ARCH("armv5t", AK_ARMV5T, "5T", "v5", ARMBuildAttrs::CPUArch::v5T, + FK_NONE, ARM::AEK_NONE) +ARM_ARCH("armv5te", AK_ARMV5TE, "5TE", "v5e", ARMBuildAttrs::CPUArch::v5TE, + FK_NONE, ARM::AEK_DSP) +ARM_ARCH("armv5tej", AK_ARMV5TEJ, "5TEJ", "v5e", ARMBuildAttrs::CPUArch::v5TEJ, + FK_NONE, ARM::AEK_DSP) +ARM_ARCH("armv6", AK_ARMV6, "6", "v6", ARMBuildAttrs::CPUArch::v6, + FK_VFPV2, ARM::AEK_DSP) +ARM_ARCH("armv6k", AK_ARMV6K, "6K", "v6k", ARMBuildAttrs::CPUArch::v6K, + FK_VFPV2, ARM::AEK_DSP) +ARM_ARCH("armv6t2", AK_ARMV6T2, "6T2", "v6t2", ARMBuildAttrs::CPUArch::v6T2, + FK_NONE, ARM::AEK_DSP) +ARM_ARCH("armv6kz", AK_ARMV6KZ, "6KZ", "v6kz", ARMBuildAttrs::CPUArch::v6KZ, + FK_VFPV2, (ARM::AEK_SEC | ARM::AEK_DSP)) +ARM_ARCH("armv6-m", AK_ARMV6M, "6-M", "v6m", ARMBuildAttrs::CPUArch::v6_M, + FK_NONE, ARM::AEK_NONE) +ARM_ARCH("armv7-a", AK_ARMV7A, "7-A", "v7", ARMBuildAttrs::CPUArch::v7, + FK_NEON, ARM::AEK_DSP) +ARM_ARCH("armv7-r", AK_ARMV7R, "7-R", "v7r", ARMBuildAttrs::CPUArch::v7, + FK_NONE, (ARM::AEK_HWDIV | ARM::AEK_DSP)) +ARM_ARCH("armv7-m", AK_ARMV7M, "7-M", "v7m", ARMBuildAttrs::CPUArch::v7, + FK_NONE, ARM::AEK_HWDIV) +ARM_ARCH("armv7e-m", AK_ARMV7EM, "7E-M", "v7em", ARMBuildAttrs::CPUArch::v7E_M, + FK_NONE, (ARM::AEK_HWDIV | ARM::AEK_DSP)) +ARM_ARCH("armv8-a", AK_ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8_A, + FK_CRYPTO_NEON_FP_ARMV8, + (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | + ARM::AEK_HWDIV | ARM::AEK_DSP | ARM::AEK_CRC)) +ARM_ARCH("armv8.1-a", AK_ARMV8_1A, "8.1-A", "v8.1a", + ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8, + (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | + ARM::AEK_HWDIV | ARM::AEK_DSP | ARM::AEK_CRC)) +ARM_ARCH("armv8.2-a", AK_ARMV8_2A, "8.2-A", "v8.2a", + ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8, + (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | + ARM::AEK_HWDIV | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS)) +ARM_ARCH("armv8-m.base", AK_ARMV8MBaseline, "8-M.Baseline", "v8m.base", + ARMBuildAttrs::CPUArch::v8_M_Base, FK_NONE, ARM::AEK_HWDIV) +ARM_ARCH("armv8-m.main", AK_ARMV8MMainline, "8-M.Mainline", "v8m.main", + ARMBuildAttrs::CPUArch::v8_M_Main, FK_FPV5_D16, ARM::AEK_HWDIV) +// Non-standard Arch names. +ARM_ARCH("iwmmxt", AK_IWMMXT, "iwmmxt", "", ARMBuildAttrs::CPUArch::v5TE, + FK_NONE, ARM::AEK_NONE) +ARM_ARCH("iwmmxt2", AK_IWMMXT2, "iwmmxt2", "", ARMBuildAttrs::CPUArch::v5TE, + FK_NONE, ARM::AEK_NONE) +ARM_ARCH("xscale", AK_XSCALE, "xscale", "v5e", ARMBuildAttrs::CPUArch::v5TE, + FK_NONE, ARM::AEK_NONE) +ARM_ARCH("armv7s", AK_ARMV7S, "7-S", "v7s", ARMBuildAttrs::CPUArch::v7, + FK_NEON_VFPV4, ARM::AEK_DSP) +ARM_ARCH("armv7k", AK_ARMV7K, "7-K", "v7k", ARMBuildAttrs::CPUArch::v7, + FK_NONE, ARM::AEK_DSP) +#undef ARM_ARCH + +#ifndef ARM_ARCH_EXT_NAME +#define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) +#endif +// FIXME: This would be nicer were it tablegen +ARM_ARCH_EXT_NAME("invalid", ARM::AEK_INVALID, nullptr, nullptr) +ARM_ARCH_EXT_NAME("none", ARM::AEK_NONE, nullptr, nullptr) +ARM_ARCH_EXT_NAME("crc", ARM::AEK_CRC, "+crc", "-crc") +ARM_ARCH_EXT_NAME("crypto", ARM::AEK_CRYPTO, "+crypto","-crypto") +ARM_ARCH_EXT_NAME("dsp", ARM::AEK_DSP, "+dsp", "-dsp") +ARM_ARCH_EXT_NAME("fp", ARM::AEK_FP, nullptr, nullptr) +ARM_ARCH_EXT_NAME("idiv", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV), nullptr, nullptr) +ARM_ARCH_EXT_NAME("mp", ARM::AEK_MP, nullptr, nullptr) +ARM_ARCH_EXT_NAME("simd", ARM::AEK_SIMD, nullptr, nullptr) +ARM_ARCH_EXT_NAME("sec", ARM::AEK_SEC, nullptr, nullptr) +ARM_ARCH_EXT_NAME("virt", ARM::AEK_VIRT, nullptr, nullptr) +ARM_ARCH_EXT_NAME("fp16", ARM::AEK_FP16, "+fullfp16", "-fullfp16") +ARM_ARCH_EXT_NAME("ras", ARM::AEK_RAS, "+ras", "-ras") +ARM_ARCH_EXT_NAME("os", ARM::AEK_OS, nullptr, nullptr) +ARM_ARCH_EXT_NAME("iwmmxt", ARM::AEK_IWMMXT, nullptr, nullptr) +ARM_ARCH_EXT_NAME("iwmmxt2", ARM::AEK_IWMMXT2, nullptr, nullptr) +ARM_ARCH_EXT_NAME("maverick", ARM::AEK_MAVERICK, nullptr, nullptr) +ARM_ARCH_EXT_NAME("xscale", ARM::AEK_XSCALE, nullptr, nullptr) +#undef ARM_ARCH_EXT_NAME + +#ifndef ARM_HW_DIV_NAME +#define ARM_HW_DIV_NAME(NAME, ID) +#endif +ARM_HW_DIV_NAME("invalid", ARM::AEK_INVALID) +ARM_HW_DIV_NAME("none", ARM::AEK_NONE) +ARM_HW_DIV_NAME("thumb", ARM::AEK_HWDIV) +ARM_HW_DIV_NAME("arm", ARM::AEK_HWDIVARM) +ARM_HW_DIV_NAME("arm,thumb", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV)) +#undef ARM_HW_DIV_NAME + +#ifndef ARM_CPU_NAME +#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) +#endif +ARM_CPU_NAME("arm2", AK_ARMV2, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm3", AK_ARMV2A, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm6", AK_ARMV3, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm7m", AK_ARMV3M, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm8", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm810", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("strongarm", AK_ARMV4, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("strongarm110", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("strongarm1100", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("strongarm1110", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm7tdmi", AK_ARMV4T, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm7tdmi-s", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm710t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm720t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm9", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm9tdmi", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm920", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm920t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm922t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm9312", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm940t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("ep9312", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm10tdmi", AK_ARMV5T, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm1020t", AK_ARMV5T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm9e", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm946e-s", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm966e-s", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm968e-s", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm10e", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm1020e", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm1022e", AK_ARMV5TE, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm926ej-s", AK_ARMV5TEJ, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm1136j-s", AK_ARMV6, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm1136jf-s", AK_ARMV6, FK_VFPV2, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm1136jz-s", AK_ARMV6, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm1176j-s", AK_ARMV6K, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm1176jz-s", AK_ARMV6KZ, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("mpcore", AK_ARMV6K, FK_VFPV2, false, ARM::AEK_NONE) +ARM_CPU_NAME("mpcorenovfp", AK_ARMV6K, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm1176jzf-s", AK_ARMV6KZ, FK_VFPV2, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm1156t2-s", AK_ARMV6T2, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm1156t2f-s", AK_ARMV6T2, FK_VFPV2, false, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-m0", AK_ARMV6M, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-m0plus", AK_ARMV6M, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-m1", AK_ARMV6M, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("sc000", AK_ARMV6M, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-a5", AK_ARMV7A, FK_NEON_VFPV4, false, + (ARM::AEK_SEC | ARM::AEK_MP)) +ARM_CPU_NAME("cortex-a7", AK_ARMV7A, FK_NEON_VFPV4, false, + (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | + ARM::AEK_HWDIV)) +ARM_CPU_NAME("cortex-a8", AK_ARMV7A, FK_NEON, true, ARM::AEK_SEC) +ARM_CPU_NAME("cortex-a9", AK_ARMV7A, FK_NEON_FP16, false, (ARM::AEK_SEC | ARM::AEK_MP)) +ARM_CPU_NAME("cortex-a12", AK_ARMV7A, FK_NEON_VFPV4, false, + (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | + ARM::AEK_HWDIV)) +ARM_CPU_NAME("cortex-a15", AK_ARMV7A, FK_NEON_VFPV4, false, + (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | + ARM::AEK_HWDIV)) +ARM_CPU_NAME("cortex-a17", AK_ARMV7A, FK_NEON_VFPV4, false, + (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | + ARM::AEK_HWDIV)) +ARM_CPU_NAME("krait", AK_ARMV7A, FK_NEON_VFPV4, false, + (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV)) +ARM_CPU_NAME("cortex-r4", AK_ARMV7R, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-r4f", AK_ARMV7R, FK_VFPV3_D16, false, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-r5", AK_ARMV7R, FK_VFPV3_D16, false, + (ARM::AEK_MP | ARM::AEK_HWDIVARM)) +ARM_CPU_NAME("cortex-r7", AK_ARMV7R, FK_VFPV3_D16_FP16, false, + (ARM::AEK_MP | ARM::AEK_HWDIVARM)) +ARM_CPU_NAME("cortex-r8", AK_ARMV7R, FK_VFPV3_D16_FP16, false, + (ARM::AEK_MP | ARM::AEK_HWDIVARM)) +ARM_CPU_NAME("sc300", AK_ARMV7M, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-m3", AK_ARMV7M, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-m4", AK_ARMV7EM, FK_FPV4_SP_D16, true, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-m7", AK_ARMV7EM, FK_FPV5_D16, false, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-a32", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) +ARM_CPU_NAME("cortex-a35", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) +ARM_CPU_NAME("cortex-a53", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true, ARM::AEK_CRC) +ARM_CPU_NAME("cortex-a57", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) +ARM_CPU_NAME("cortex-a72", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) +ARM_CPU_NAME("cortex-a73", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) +ARM_CPU_NAME("cyclone", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) +ARM_CPU_NAME("exynos-m1", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) +ARM_CPU_NAME("exynos-m2", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) +// Non-standard Arch names. +ARM_CPU_NAME("iwmmxt", AK_IWMMXT, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("xscale", AK_XSCALE, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("swift", AK_ARMV7S, FK_NEON_VFPV4, true, + (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV)) +// Invalid CPU +ARM_CPU_NAME("invalid", AK_INVALID, FK_INVALID, true, ARM::AEK_INVALID) +#undef ARM_CPU_NAME
diff --git a/third_party/llvm-subzero/include/llvm/Support/AlignOf.h b/third_party/llvm-subzero/include/llvm/Support/AlignOf.h new file mode 100644 index 0000000..333bf16 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/AlignOf.h
@@ -0,0 +1,259 @@ +//===--- AlignOf.h - Portable calculation of type alignment -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the AlignOf function that computes alignments for +// arbitrary types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ALIGNOF_H +#define LLVM_SUPPORT_ALIGNOF_H + +#include "llvm/Support/Compiler.h" +#include <cstddef> +#include <type_traits> + +namespace llvm { + +namespace detail { + +// For everything other than an abstract class we can calulate alignment by +// building a class with a single character and a member of the given type. +template <typename T, bool = std::is_abstract<T>::value> +struct AlignmentCalcImpl { + char x; +#if defined(_MSC_VER) +// Disables "structure was padded due to __declspec(align())" warnings that are +// generated by any class using AlignOf<T> with a manually specified alignment. +// Although the warning is disabled in the LLVM project we need this pragma +// as AlignOf.h is a published support header that's available for use +// out-of-tree, and we would like that to compile cleanly at /W4. +#pragma warning(suppress : 4324) +#endif + T t; +private: + AlignmentCalcImpl() = delete; +}; + +// Abstract base class helper, this will have the minimal alignment and size +// for any abstract class. We don't even define its destructor because this +// type should never be used in a way that requires it. +struct AlignmentCalcImplBase { + virtual ~AlignmentCalcImplBase() = 0; +}; + +// When we have an abstract class type, specialize the alignment computation +// engine to create another abstract class that derives from both an empty +// abstract base class and the provided type. This has the same effect as the +// above except that it handles the fact that we can't actually create a member +// of type T. +template <typename T> +struct AlignmentCalcImpl<T, true> : AlignmentCalcImplBase, T { + ~AlignmentCalcImpl() override = 0; +}; + +} // End detail namespace. + +/// AlignOf - A templated class that contains an enum value representing +/// the alignment of the template argument. For example, +/// AlignOf<int>::Alignment represents the alignment of type "int". The +/// alignment calculated is the minimum alignment, and not necessarily +/// the "desired" alignment returned by GCC's __alignof__ (for example). Note +/// that because the alignment is an enum value, it can be used as a +/// compile-time constant (e.g., for template instantiation). +template <typename T> +struct AlignOf { +#ifndef _MSC_VER + // Avoid warnings from GCC like: + // comparison between 'enum llvm::AlignOf<X>::<anonymous>' and 'enum + // llvm::AlignOf<Y>::<anonymous>' [-Wenum-compare] + // by using constexpr instead of enum. + // (except on MSVC, since it doesn't support constexpr yet). + static constexpr unsigned Alignment = static_cast<unsigned int>( + sizeof(detail::AlignmentCalcImpl<T>) - sizeof(T)); +#else + enum { + Alignment = static_cast<unsigned int>( + sizeof(::llvm::detail::AlignmentCalcImpl<T>) - sizeof(T)) + }; +#endif + enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 }; + enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 }; + enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 }; + enum { Alignment_GreaterEqual_16Bytes = Alignment >= 16 ? 1 : 0 }; + + enum { Alignment_LessEqual_2Bytes = Alignment <= 2 ? 1 : 0 }; + enum { Alignment_LessEqual_4Bytes = Alignment <= 4 ? 1 : 0 }; + enum { Alignment_LessEqual_8Bytes = Alignment <= 8 ? 1 : 0 }; + enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 }; +}; + +#ifndef _MSC_VER +template <typename T> constexpr unsigned AlignOf<T>::Alignment; +#endif + +/// alignOf - A templated function that returns the minimum alignment of +/// of a type. This provides no extra functionality beyond the AlignOf +/// class besides some cosmetic cleanliness. Example usage: +/// alignOf<int>() returns the alignment of an int. +template <typename T> +LLVM_CONSTEXPR inline unsigned alignOf() { return AlignOf<T>::Alignment; } + +/// \struct AlignedCharArray +/// \brief Helper for building an aligned character array type. +/// +/// This template is used to explicitly build up a collection of aligned +/// character array types. We have to build these up using a macro and explicit +/// specialization to cope with old versions of MSVC and GCC where only an +/// integer literal can be used to specify an alignment constraint. Once built +/// up here, we can then begin to indirect between these using normal C++ +/// template parameters. + +// MSVC requires special handling here. +#ifndef _MSC_VER + +#if __has_feature(cxx_alignas) +template<std::size_t Alignment, std::size_t Size> +struct AlignedCharArray { + alignas(Alignment) char buffer[Size]; +}; + +#elif defined(__GNUC__) || defined(__IBM_ATTRIBUTES) +/// \brief Create a type with an aligned char buffer. +template<std::size_t Alignment, std::size_t Size> +struct AlignedCharArray; + +#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ + template<std::size_t Size> \ + struct AlignedCharArray<x, Size> { \ + __attribute__((aligned(x))) char buffer[Size]; \ + }; + +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) + +#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT + +#else +# error No supported align as directive. +#endif + +#else // _MSC_VER + +/// \brief Create a type with an aligned char buffer. +template<std::size_t Alignment, std::size_t Size> +struct AlignedCharArray; + +// We provide special variations of this template for the most common +// alignments because __declspec(align(...)) doesn't actually work when it is +// a member of a by-value function argument in MSVC, even if the alignment +// request is something reasonably like 8-byte or 16-byte. Note that we can't +// even include the declspec with the union that forces the alignment because +// MSVC warns on the existence of the declspec despite the union member forcing +// proper alignment. + +template<std::size_t Size> +struct AlignedCharArray<1, Size> { + union { + char aligned; + char buffer[Size]; + }; +}; + +template<std::size_t Size> +struct AlignedCharArray<2, Size> { + union { + short aligned; + char buffer[Size]; + }; +}; + +template<std::size_t Size> +struct AlignedCharArray<4, Size> { + union { + int aligned; + char buffer[Size]; + }; +}; + +template<std::size_t Size> +struct AlignedCharArray<8, Size> { + union { + double aligned; + char buffer[Size]; + }; +}; + + +// The rest of these are provided with a __declspec(align(...)) and we simply +// can't pass them by-value as function arguments on MSVC. + +#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ + template<std::size_t Size> \ + struct AlignedCharArray<x, Size> { \ + __declspec(align(x)) char buffer[Size]; \ + }; + +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) + +#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT + +#endif // _MSC_VER + +namespace detail { +template <typename T1, + typename T2 = char, typename T3 = char, typename T4 = char, + typename T5 = char, typename T6 = char, typename T7 = char, + typename T8 = char, typename T9 = char, typename T10 = char> +class AlignerImpl { + T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8; T9 t9; T10 t10; + + AlignerImpl() = delete; +}; + +template <typename T1, + typename T2 = char, typename T3 = char, typename T4 = char, + typename T5 = char, typename T6 = char, typename T7 = char, + typename T8 = char, typename T9 = char, typename T10 = char> +union SizerImpl { + char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)], + arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)], arr8[sizeof(T8)], + arr9[sizeof(T9)], arr10[sizeof(T10)]; +}; +} // end namespace detail + +/// \brief This union template exposes a suitably aligned and sized character +/// array member which can hold elements of any of up to ten types. +/// +/// These types may be arrays, structs, or any other types. The goal is to +/// expose a char array buffer member which can be used as suitable storage for +/// a placement new of any of these types. Support for more than ten types can +/// be added at the cost of more boilerplate. +template <typename T1, + typename T2 = char, typename T3 = char, typename T4 = char, + typename T5 = char, typename T6 = char, typename T7 = char, + typename T8 = char, typename T9 = char, typename T10 = char> +struct AlignedCharArrayUnion : llvm::AlignedCharArray< + AlignOf<llvm::detail::AlignerImpl<T1, T2, T3, T4, T5, + T6, T7, T8, T9, T10> >::Alignment, + sizeof(::llvm::detail::SizerImpl<T1, T2, T3, T4, T5, + T6, T7, T8, T9, T10>)> { +}; +} // end namespace llvm + +#endif // LLVM_SUPPORT_ALIGNOF_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/Allocator.h b/third_party/llvm-subzero/include/llvm/Support/Allocator.h new file mode 100644 index 0000000..1c95086 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Allocator.h
@@ -0,0 +1,437 @@ +//===--- Allocator.h - Simple memory allocation abstraction -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file defines the MallocAllocator and BumpPtrAllocator interfaces. Both +/// of these conform to an LLVM "Allocator" concept which consists of an +/// Allocate method accepting a size and alignment, and a Deallocate accepting +/// a pointer and size. Further, the LLVM "Allocator" concept has overloads of +/// Allocate and Deallocate for setting size and alignment based on the final +/// type. These overloads are typically provided by a base class template \c +/// AllocatorBase. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ALLOCATOR_H +#define LLVM_SUPPORT_ALLOCATOR_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Memory.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdlib> + +namespace llvm { + +/// \brief CRTP base class providing obvious overloads for the core \c +/// Allocate() methods of LLVM-style allocators. +/// +/// This base class both documents the full public interface exposed by all +/// LLVM-style allocators, and redirects all of the overloads to a single core +/// set of methods which the derived class must define. +template <typename DerivedT> class AllocatorBase { +public: + /// \brief Allocate \a Size bytes of \a Alignment aligned memory. This method + /// must be implemented by \c DerivedT. + void *Allocate(size_t Size, size_t Alignment) { +#ifdef __clang__ + static_assert(static_cast<void *(AllocatorBase::*)(size_t, size_t)>( + &AllocatorBase::Allocate) != + static_cast<void *(DerivedT::*)(size_t, size_t)>( + &DerivedT::Allocate), + "Class derives from AllocatorBase without implementing the " + "core Allocate(size_t, size_t) overload!"); +#endif + return static_cast<DerivedT *>(this)->Allocate(Size, Alignment); + } + + /// \brief Deallocate \a Ptr to \a Size bytes of memory allocated by this + /// allocator. + void Deallocate(const void *Ptr, size_t Size) { +#ifdef __clang__ + static_assert(static_cast<void (AllocatorBase::*)(const void *, size_t)>( + &AllocatorBase::Deallocate) != + static_cast<void (DerivedT::*)(const void *, size_t)>( + &DerivedT::Deallocate), + "Class derives from AllocatorBase without implementing the " + "core Deallocate(void *) overload!"); +#endif + return static_cast<DerivedT *>(this)->Deallocate(Ptr, Size); + } + + // The rest of these methods are helpers that redirect to one of the above + // core methods. + + /// \brief Allocate space for a sequence of objects without constructing them. + template <typename T> T *Allocate(size_t Num = 1) { + return static_cast<T *>(Allocate(Num * sizeof(T), AlignOf<T>::Alignment)); + } + + /// \brief Deallocate space for a sequence of objects without constructing them. + template <typename T> + typename std::enable_if< + !std::is_same<typename std::remove_cv<T>::type, void>::value, void>::type + Deallocate(T *Ptr, size_t Num = 1) { + Deallocate(static_cast<const void *>(Ptr), Num * sizeof(T)); + } +}; + +class MallocAllocator : public AllocatorBase<MallocAllocator> { +public: + void Reset() {} + + LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, + size_t /*Alignment*/) { + return malloc(Size); + } + + // Pull in base class overloads. + using AllocatorBase<MallocAllocator>::Allocate; + + void Deallocate(const void *Ptr, size_t /*Size*/) { + free(const_cast<void *>(Ptr)); + } + + // Pull in base class overloads. + using AllocatorBase<MallocAllocator>::Deallocate; + + void PrintStats() const {} +}; + +namespace detail { + +// We call out to an external function to actually print the message as the +// printing code uses Allocator.h in its implementation. +void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated, + size_t TotalMemory); +} // End namespace detail. + +/// \brief Allocate memory in an ever growing pool, as if by bump-pointer. +/// +/// This isn't strictly a bump-pointer allocator as it uses backing slabs of +/// memory rather than relying on a boundless contiguous heap. However, it has +/// bump-pointer semantics in that it is a monotonically growing pool of memory +/// where every allocation is found by merely allocating the next N bytes in +/// the slab, or the next N bytes in the next slab. +/// +/// Note that this also has a threshold for forcing allocations above a certain +/// size into their own slab. +/// +/// The BumpPtrAllocatorImpl template defaults to using a MallocAllocator +/// object, which wraps malloc, to allocate memory, but it can be changed to +/// use a custom allocator. +template <typename AllocatorT = MallocAllocator, size_t SlabSize = 4096, + size_t SizeThreshold = SlabSize> +class BumpPtrAllocatorImpl + : public AllocatorBase< + BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold>> { +public: + static_assert(SizeThreshold <= SlabSize, + "The SizeThreshold must be at most the SlabSize to ensure " + "that objects larger than a slab go into their own memory " + "allocation."); + + BumpPtrAllocatorImpl() + : CurPtr(nullptr), End(nullptr), BytesAllocated(0), Allocator() {} + template <typename T> + BumpPtrAllocatorImpl(T &&Allocator) + : CurPtr(nullptr), End(nullptr), BytesAllocated(0), + Allocator(std::forward<T &&>(Allocator)) {} + + // Manually implement a move constructor as we must clear the old allocator's + // slabs as a matter of correctness. + BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old) + : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)), + CustomSizedSlabs(std::move(Old.CustomSizedSlabs)), + BytesAllocated(Old.BytesAllocated), + Allocator(std::move(Old.Allocator)) { + Old.CurPtr = Old.End = nullptr; + Old.BytesAllocated = 0; + Old.Slabs.clear(); + Old.CustomSizedSlabs.clear(); + } + + ~BumpPtrAllocatorImpl() { + DeallocateSlabs(Slabs.begin(), Slabs.end()); + DeallocateCustomSizedSlabs(); + } + + BumpPtrAllocatorImpl &operator=(BumpPtrAllocatorImpl &&RHS) { + DeallocateSlabs(Slabs.begin(), Slabs.end()); + DeallocateCustomSizedSlabs(); + + CurPtr = RHS.CurPtr; + End = RHS.End; + BytesAllocated = RHS.BytesAllocated; + Slabs = std::move(RHS.Slabs); + CustomSizedSlabs = std::move(RHS.CustomSizedSlabs); + Allocator = std::move(RHS.Allocator); + + RHS.CurPtr = RHS.End = nullptr; + RHS.BytesAllocated = 0; + RHS.Slabs.clear(); + RHS.CustomSizedSlabs.clear(); + return *this; + } + + /// \brief Deallocate all but the current slab and reset the current pointer + /// to the beginning of it, freeing all memory allocated so far. + void Reset() { + // Deallocate all but the first slab, and deallocate all custom-sized slabs. + DeallocateCustomSizedSlabs(); + CustomSizedSlabs.clear(); + + if (Slabs.empty()) + return; + + // Reset the state. + BytesAllocated = 0; + CurPtr = (char *)Slabs.front(); + End = CurPtr + SlabSize; + + __asan_poison_memory_region(*Slabs.begin(), computeSlabSize(0)); + DeallocateSlabs(std::next(Slabs.begin()), Slabs.end()); + Slabs.erase(std::next(Slabs.begin()), Slabs.end()); + } + + /// \brief Allocate space at the specified alignment. + LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void * + Allocate(size_t Size, size_t Alignment) { + assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead."); + + // Keep track of how many bytes we've allocated. + BytesAllocated += Size; + + size_t Adjustment = alignmentAdjustment(CurPtr, Alignment); + assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow"); + + // Check if we have enough space. + if (Adjustment + Size <= size_t(End - CurPtr)) { + char *AlignedPtr = CurPtr + Adjustment; + CurPtr = AlignedPtr + Size; + // Update the allocation point of this memory block in MemorySanitizer. + // Without this, MemorySanitizer messages for values originated from here + // will point to the allocation of the entire slab. + __msan_allocated_memory(AlignedPtr, Size); + // Similarly, tell ASan about this space. + __asan_unpoison_memory_region(AlignedPtr, Size); + return AlignedPtr; + } + + // If Size is really big, allocate a separate slab for it. + size_t PaddedSize = Size + Alignment - 1; + if (PaddedSize > SizeThreshold) { + void *NewSlab = Allocator.Allocate(PaddedSize, 0); + // We own the new slab and don't want anyone reading anyting other than + // pieces returned from this method. So poison the whole slab. + __asan_poison_memory_region(NewSlab, PaddedSize); + CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize)); + + uintptr_t AlignedAddr = alignAddr(NewSlab, Alignment); + assert(AlignedAddr + Size <= (uintptr_t)NewSlab + PaddedSize); + char *AlignedPtr = (char*)AlignedAddr; + __msan_allocated_memory(AlignedPtr, Size); + __asan_unpoison_memory_region(AlignedPtr, Size); + return AlignedPtr; + } + + // Otherwise, start a new slab and try again. + StartNewSlab(); + uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment); + assert(AlignedAddr + Size <= (uintptr_t)End && + "Unable to allocate memory!"); + char *AlignedPtr = (char*)AlignedAddr; + CurPtr = AlignedPtr + Size; + __msan_allocated_memory(AlignedPtr, Size); + __asan_unpoison_memory_region(AlignedPtr, Size); + return AlignedPtr; + } + + // Pull in base class overloads. + using AllocatorBase<BumpPtrAllocatorImpl>::Allocate; + + void Deallocate(const void *Ptr, size_t Size) { + __asan_poison_memory_region(Ptr, Size); + } + + // Pull in base class overloads. + using AllocatorBase<BumpPtrAllocatorImpl>::Deallocate; + + size_t GetNumSlabs() const { return Slabs.size() + CustomSizedSlabs.size(); } + + size_t getTotalMemory() const { + size_t TotalMemory = 0; + for (auto I = Slabs.begin(), E = Slabs.end(); I != E; ++I) + TotalMemory += computeSlabSize(std::distance(Slabs.begin(), I)); + for (auto &PtrAndSize : CustomSizedSlabs) + TotalMemory += PtrAndSize.second; + return TotalMemory; + } + + size_t getBytesAllocated() const { return BytesAllocated; } + + void PrintStats() const { + detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated, + getTotalMemory()); + } + +private: + /// \brief The current pointer into the current slab. + /// + /// This points to the next free byte in the slab. + char *CurPtr; + + /// \brief The end of the current slab. + char *End; + + /// \brief The slabs allocated so far. + SmallVector<void *, 4> Slabs; + + /// \brief Custom-sized slabs allocated for too-large allocation requests. + SmallVector<std::pair<void *, size_t>, 0> CustomSizedSlabs; + + /// \brief How many bytes we've allocated. + /// + /// Used so that we can compute how much space was wasted. + size_t BytesAllocated; + + /// \brief The allocator instance we use to get slabs of memory. + AllocatorT Allocator; + + static size_t computeSlabSize(unsigned SlabIdx) { + // Scale the actual allocated slab size based on the number of slabs + // allocated. Every 128 slabs allocated, we double the allocated size to + // reduce allocation frequency, but saturate at multiplying the slab size by + // 2^30. + return SlabSize * ((size_t)1 << std::min<size_t>(30, SlabIdx / 128)); + } + + /// \brief Allocate a new slab and move the bump pointers over into the new + /// slab, modifying CurPtr and End. + void StartNewSlab() { + size_t AllocatedSlabSize = computeSlabSize(Slabs.size()); + + void *NewSlab = Allocator.Allocate(AllocatedSlabSize, 0); + // We own the new slab and don't want anyone reading anything other than + // pieces returned from this method. So poison the whole slab. + __asan_poison_memory_region(NewSlab, AllocatedSlabSize); + + Slabs.push_back(NewSlab); + CurPtr = (char *)(NewSlab); + End = ((char *)NewSlab) + AllocatedSlabSize; + } + + /// \brief Deallocate a sequence of slabs. + void DeallocateSlabs(SmallVectorImpl<void *>::iterator I, + SmallVectorImpl<void *>::iterator E) { + for (; I != E; ++I) { + size_t AllocatedSlabSize = + computeSlabSize(std::distance(Slabs.begin(), I)); + Allocator.Deallocate(*I, AllocatedSlabSize); + } + } + + /// \brief Deallocate all memory for custom sized slabs. + void DeallocateCustomSizedSlabs() { + for (auto &PtrAndSize : CustomSizedSlabs) { + void *Ptr = PtrAndSize.first; + size_t Size = PtrAndSize.second; + Allocator.Deallocate(Ptr, Size); + } + } + + template <typename T> friend class SpecificBumpPtrAllocator; +}; + +/// \brief The standard BumpPtrAllocator which just uses the default template +/// paramaters. +typedef BumpPtrAllocatorImpl<> BumpPtrAllocator; + +/// \brief A BumpPtrAllocator that allows only elements of a specific type to be +/// allocated. +/// +/// This allows calling the destructor in DestroyAll() and when the allocator is +/// destroyed. +template <typename T> class SpecificBumpPtrAllocator { + BumpPtrAllocator Allocator; + +public: + SpecificBumpPtrAllocator() : Allocator() {} + SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old) + : Allocator(std::move(Old.Allocator)) {} + ~SpecificBumpPtrAllocator() { DestroyAll(); } + + SpecificBumpPtrAllocator &operator=(SpecificBumpPtrAllocator &&RHS) { + Allocator = std::move(RHS.Allocator); + return *this; + } + + /// Call the destructor of each allocated object and deallocate all but the + /// current slab and reset the current pointer to the beginning of it, freeing + /// all memory allocated so far. + void DestroyAll() { + auto DestroyElements = [](char *Begin, char *End) { + assert(Begin == (char*)alignAddr(Begin, alignOf<T>())); + for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T)) + reinterpret_cast<T *>(Ptr)->~T(); + }; + + for (auto I = Allocator.Slabs.begin(), E = Allocator.Slabs.end(); I != E; + ++I) { + size_t AllocatedSlabSize = BumpPtrAllocator::computeSlabSize( + std::distance(Allocator.Slabs.begin(), I)); + char *Begin = (char*)alignAddr(*I, alignOf<T>()); + char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr + : (char *)*I + AllocatedSlabSize; + + DestroyElements(Begin, End); + } + + for (auto &PtrAndSize : Allocator.CustomSizedSlabs) { + void *Ptr = PtrAndSize.first; + size_t Size = PtrAndSize.second; + DestroyElements((char*)alignAddr(Ptr, alignOf<T>()), (char *)Ptr + Size); + } + + Allocator.Reset(); + } + + /// \brief Allocate space for an array of objects without constructing them. + T *Allocate(size_t num = 1) { return Allocator.Allocate<T>(num); } +}; + +} // end namespace llvm + +template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold> +void *operator new(size_t Size, + llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, + SizeThreshold> &Allocator) { + struct S { + char c; + union { + double D; + long double LD; + long long L; + void *P; + } x; + }; + return Allocator.Allocate( + Size, std::min((size_t)llvm::NextPowerOf2(Size), offsetof(S, x))); +} + +template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold> +void operator delete( + void *, llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold> &) { +} + +#endif // LLVM_SUPPORT_ALLOCATOR_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/Atomic.h b/third_party/llvm-subzero/include/llvm/Support/Atomic.h new file mode 100644 index 0000000..d03714b --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Atomic.h
@@ -0,0 +1,38 @@ +//===- llvm/Support/Atomic.h - Atomic Operations -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys atomic operations. +// +// DO NOT USE IN NEW CODE! +// +// New code should always rely on the std::atomic facilities in C++11. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ATOMIC_H +#define LLVM_SUPPORT_ATOMIC_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + namespace sys { + void MemoryFence(); + +#ifdef _MSC_VER + typedef long cas_flag; +#else + typedef uint32_t cas_flag; +#endif + cas_flag CompareAndSwap(volatile cas_flag* ptr, + cas_flag new_value, + cas_flag old_value); + } +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/CBindingWrapping.h b/third_party/llvm-subzero/include/llvm/Support/CBindingWrapping.h new file mode 100644 index 0000000..d4633aa --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/CBindingWrapping.h
@@ -0,0 +1,47 @@ +//===- llvm/Support/CBindingWrapph.h - C Interface Wrapping -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the wrapping macros for the C interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CBINDINGWRAPPING_H +#define LLVM_SUPPORT_CBINDINGWRAPPING_H + +#include "llvm/Support/Casting.h" +#include "llvm-c/Types.h" + +#define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ + inline ty *unwrap(ref P) { \ + return reinterpret_cast<ty*>(P); \ + } \ + \ + inline ref wrap(const ty *P) { \ + return reinterpret_cast<ref>(const_cast<ty*>(P)); \ + } + +#define DEFINE_ISA_CONVERSION_FUNCTIONS(ty, ref) \ + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ + \ + template<typename T> \ + inline T *unwrap(ref P) { \ + return cast<T>(unwrap(P)); \ + } + +#define DEFINE_STDCXX_CONVERSION_FUNCTIONS(ty, ref) \ + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ + \ + template<typename T> \ + inline T *unwrap(ref P) { \ + T *Q = (T*)unwrap(P); \ + assert(Q && "Invalid cast!"); \ + return Q; \ + } + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/COFF.h b/third_party/llvm-subzero/include/llvm/Support/COFF.h new file mode 100644 index 0000000..7dad3e8 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/COFF.h
@@ -0,0 +1,675 @@ +//===-- llvm/Support/COFF.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains an definitions used in Windows COFF Files. +// +// Structures and enums defined within this file where created using +// information from Microsoft's publicly available PE/COFF format document: +// +// Microsoft Portable Executable and Common Object File Format Specification +// Revision 8.1 - February 15, 2008 +// +// As of 5/2/2010, hosted by Microsoft at: +// http://www.microsoft.com/whdc/system/platform/firmware/pecoff.mspx +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_COFF_H +#define LLVM_SUPPORT_COFF_H + +#include "llvm/Support/DataTypes.h" +#include <cassert> +#include <cstring> + +namespace llvm { +namespace COFF { + + // The maximum number of sections that a COFF object can have (inclusive). + const int32_t MaxNumberOfSections16 = 65279; + + // The PE signature bytes that follows the DOS stub header. + static const char PEMagic[] = { 'P', 'E', '\0', '\0' }; + + static const char BigObjMagic[] = { + '\xc7', '\xa1', '\xba', '\xd1', '\xee', '\xba', '\xa9', '\x4b', + '\xaf', '\x20', '\xfa', '\xf6', '\x6a', '\xa4', '\xdc', '\xb8', + }; + + // Sizes in bytes of various things in the COFF format. + enum { + Header16Size = 20, + Header32Size = 56, + NameSize = 8, + Symbol16Size = 18, + Symbol32Size = 20, + SectionSize = 40, + RelocationSize = 10 + }; + + struct header { + uint16_t Machine; + int32_t NumberOfSections; + uint32_t TimeDateStamp; + uint32_t PointerToSymbolTable; + uint32_t NumberOfSymbols; + uint16_t SizeOfOptionalHeader; + uint16_t Characteristics; + }; + + struct BigObjHeader { + enum : uint16_t { MinBigObjectVersion = 2 }; + + uint16_t Sig1; ///< Must be IMAGE_FILE_MACHINE_UNKNOWN (0). + uint16_t Sig2; ///< Must be 0xFFFF. + uint16_t Version; + uint16_t Machine; + uint32_t TimeDateStamp; + uint8_t UUID[16]; + uint32_t unused1; + uint32_t unused2; + uint32_t unused3; + uint32_t unused4; + uint32_t NumberOfSections; + uint32_t PointerToSymbolTable; + uint32_t NumberOfSymbols; + }; + + enum MachineTypes { + MT_Invalid = 0xffff, + + IMAGE_FILE_MACHINE_UNKNOWN = 0x0, + IMAGE_FILE_MACHINE_AM33 = 0x13, + IMAGE_FILE_MACHINE_AMD64 = 0x8664, + IMAGE_FILE_MACHINE_ARM = 0x1C0, + IMAGE_FILE_MACHINE_ARMNT = 0x1C4, + IMAGE_FILE_MACHINE_ARM64 = 0xAA64, + IMAGE_FILE_MACHINE_EBC = 0xEBC, + IMAGE_FILE_MACHINE_I386 = 0x14C, + IMAGE_FILE_MACHINE_IA64 = 0x200, + IMAGE_FILE_MACHINE_M32R = 0x9041, + IMAGE_FILE_MACHINE_MIPS16 = 0x266, + IMAGE_FILE_MACHINE_MIPSFPU = 0x366, + IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466, + IMAGE_FILE_MACHINE_POWERPC = 0x1F0, + IMAGE_FILE_MACHINE_POWERPCFP = 0x1F1, + IMAGE_FILE_MACHINE_R4000 = 0x166, + IMAGE_FILE_MACHINE_SH3 = 0x1A2, + IMAGE_FILE_MACHINE_SH3DSP = 0x1A3, + IMAGE_FILE_MACHINE_SH4 = 0x1A6, + IMAGE_FILE_MACHINE_SH5 = 0x1A8, + IMAGE_FILE_MACHINE_THUMB = 0x1C2, + IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169 + }; + + enum Characteristics { + C_Invalid = 0, + + /// The file does not contain base relocations and must be loaded at its + /// preferred base. If this cannot be done, the loader will error. + IMAGE_FILE_RELOCS_STRIPPED = 0x0001, + /// The file is valid and can be run. + IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002, + /// COFF line numbers have been stripped. This is deprecated and should be + /// 0. + IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004, + /// COFF symbol table entries for local symbols have been removed. This is + /// deprecated and should be 0. + IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008, + /// Aggressively trim working set. This is deprecated and must be 0. + IMAGE_FILE_AGGRESSIVE_WS_TRIM = 0x0010, + /// Image can handle > 2GiB addresses. + IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020, + /// Little endian: the LSB precedes the MSB in memory. This is deprecated + /// and should be 0. + IMAGE_FILE_BYTES_REVERSED_LO = 0x0080, + /// Machine is based on a 32bit word architecture. + IMAGE_FILE_32BIT_MACHINE = 0x0100, + /// Debugging info has been removed. + IMAGE_FILE_DEBUG_STRIPPED = 0x0200, + /// If the image is on removable media, fully load it and copy it to swap. + IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400, + /// If the image is on network media, fully load it and copy it to swap. + IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800, + /// The image file is a system file, not a user program. + IMAGE_FILE_SYSTEM = 0x1000, + /// The image file is a DLL. + IMAGE_FILE_DLL = 0x2000, + /// This file should only be run on a uniprocessor machine. + IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000, + /// Big endian: the MSB precedes the LSB in memory. This is deprecated + /// and should be 0. + IMAGE_FILE_BYTES_REVERSED_HI = 0x8000 + }; + + struct symbol { + char Name[NameSize]; + uint32_t Value; + int32_t SectionNumber; + uint16_t Type; + uint8_t StorageClass; + uint8_t NumberOfAuxSymbols; + }; + + enum SymbolSectionNumber : int32_t { + IMAGE_SYM_DEBUG = -2, + IMAGE_SYM_ABSOLUTE = -1, + IMAGE_SYM_UNDEFINED = 0 + }; + + /// Storage class tells where and what the symbol represents + enum SymbolStorageClass { + SSC_Invalid = 0xff, + + IMAGE_SYM_CLASS_END_OF_FUNCTION = -1, ///< Physical end of function + IMAGE_SYM_CLASS_NULL = 0, ///< No symbol + IMAGE_SYM_CLASS_AUTOMATIC = 1, ///< Stack variable + IMAGE_SYM_CLASS_EXTERNAL = 2, ///< External symbol + IMAGE_SYM_CLASS_STATIC = 3, ///< Static + IMAGE_SYM_CLASS_REGISTER = 4, ///< Register variable + IMAGE_SYM_CLASS_EXTERNAL_DEF = 5, ///< External definition + IMAGE_SYM_CLASS_LABEL = 6, ///< Label + IMAGE_SYM_CLASS_UNDEFINED_LABEL = 7, ///< Undefined label + IMAGE_SYM_CLASS_MEMBER_OF_STRUCT = 8, ///< Member of structure + IMAGE_SYM_CLASS_ARGUMENT = 9, ///< Function argument + IMAGE_SYM_CLASS_STRUCT_TAG = 10, ///< Structure tag + IMAGE_SYM_CLASS_MEMBER_OF_UNION = 11, ///< Member of union + IMAGE_SYM_CLASS_UNION_TAG = 12, ///< Union tag + IMAGE_SYM_CLASS_TYPE_DEFINITION = 13, ///< Type definition + IMAGE_SYM_CLASS_UNDEFINED_STATIC = 14, ///< Undefined static + IMAGE_SYM_CLASS_ENUM_TAG = 15, ///< Enumeration tag + IMAGE_SYM_CLASS_MEMBER_OF_ENUM = 16, ///< Member of enumeration + IMAGE_SYM_CLASS_REGISTER_PARAM = 17, ///< Register parameter + IMAGE_SYM_CLASS_BIT_FIELD = 18, ///< Bit field + /// ".bb" or ".eb" - beginning or end of block + IMAGE_SYM_CLASS_BLOCK = 100, + /// ".bf" or ".ef" - beginning or end of function + IMAGE_SYM_CLASS_FUNCTION = 101, + IMAGE_SYM_CLASS_END_OF_STRUCT = 102, ///< End of structure + IMAGE_SYM_CLASS_FILE = 103, ///< File name + /// Line number, reformatted as symbol + IMAGE_SYM_CLASS_SECTION = 104, + IMAGE_SYM_CLASS_WEAK_EXTERNAL = 105, ///< Duplicate tag + /// External symbol in dmert public lib + IMAGE_SYM_CLASS_CLR_TOKEN = 107 + }; + + enum SymbolBaseType { + IMAGE_SYM_TYPE_NULL = 0, ///< No type information or unknown base type. + IMAGE_SYM_TYPE_VOID = 1, ///< Used with void pointers and functions. + IMAGE_SYM_TYPE_CHAR = 2, ///< A character (signed byte). + IMAGE_SYM_TYPE_SHORT = 3, ///< A 2-byte signed integer. + IMAGE_SYM_TYPE_INT = 4, ///< A natural integer type on the target. + IMAGE_SYM_TYPE_LONG = 5, ///< A 4-byte signed integer. + IMAGE_SYM_TYPE_FLOAT = 6, ///< A 4-byte floating-point number. + IMAGE_SYM_TYPE_DOUBLE = 7, ///< An 8-byte floating-point number. + IMAGE_SYM_TYPE_STRUCT = 8, ///< A structure. + IMAGE_SYM_TYPE_UNION = 9, ///< An union. + IMAGE_SYM_TYPE_ENUM = 10, ///< An enumerated type. + IMAGE_SYM_TYPE_MOE = 11, ///< A member of enumeration (a specific value). + IMAGE_SYM_TYPE_BYTE = 12, ///< A byte; unsigned 1-byte integer. + IMAGE_SYM_TYPE_WORD = 13, ///< A word; unsigned 2-byte integer. + IMAGE_SYM_TYPE_UINT = 14, ///< An unsigned integer of natural size. + IMAGE_SYM_TYPE_DWORD = 15 ///< An unsigned 4-byte integer. + }; + + enum SymbolComplexType { + IMAGE_SYM_DTYPE_NULL = 0, ///< No complex type; simple scalar variable. + IMAGE_SYM_DTYPE_POINTER = 1, ///< A pointer to base type. + IMAGE_SYM_DTYPE_FUNCTION = 2, ///< A function that returns a base type. + IMAGE_SYM_DTYPE_ARRAY = 3, ///< An array of base type. + + /// Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT)) + SCT_COMPLEX_TYPE_SHIFT = 4 + }; + + enum AuxSymbolType { + IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF = 1 + }; + + struct section { + char Name[NameSize]; + uint32_t VirtualSize; + uint32_t VirtualAddress; + uint32_t SizeOfRawData; + uint32_t PointerToRawData; + uint32_t PointerToRelocations; + uint32_t PointerToLineNumbers; + uint16_t NumberOfRelocations; + uint16_t NumberOfLineNumbers; + uint32_t Characteristics; + }; + + enum SectionCharacteristics : uint32_t { + SC_Invalid = 0xffffffff, + + IMAGE_SCN_TYPE_NOLOAD = 0x00000002, + IMAGE_SCN_TYPE_NO_PAD = 0x00000008, + IMAGE_SCN_CNT_CODE = 0x00000020, + IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040, + IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080, + IMAGE_SCN_LNK_OTHER = 0x00000100, + IMAGE_SCN_LNK_INFO = 0x00000200, + IMAGE_SCN_LNK_REMOVE = 0x00000800, + IMAGE_SCN_LNK_COMDAT = 0x00001000, + IMAGE_SCN_GPREL = 0x00008000, + IMAGE_SCN_MEM_PURGEABLE = 0x00020000, + IMAGE_SCN_MEM_16BIT = 0x00020000, + IMAGE_SCN_MEM_LOCKED = 0x00040000, + IMAGE_SCN_MEM_PRELOAD = 0x00080000, + IMAGE_SCN_ALIGN_1BYTES = 0x00100000, + IMAGE_SCN_ALIGN_2BYTES = 0x00200000, + IMAGE_SCN_ALIGN_4BYTES = 0x00300000, + IMAGE_SCN_ALIGN_8BYTES = 0x00400000, + IMAGE_SCN_ALIGN_16BYTES = 0x00500000, + IMAGE_SCN_ALIGN_32BYTES = 0x00600000, + IMAGE_SCN_ALIGN_64BYTES = 0x00700000, + IMAGE_SCN_ALIGN_128BYTES = 0x00800000, + IMAGE_SCN_ALIGN_256BYTES = 0x00900000, + IMAGE_SCN_ALIGN_512BYTES = 0x00A00000, + IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000, + IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000, + IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000, + IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000, + IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000, + IMAGE_SCN_MEM_DISCARDABLE = 0x02000000, + IMAGE_SCN_MEM_NOT_CACHED = 0x04000000, + IMAGE_SCN_MEM_NOT_PAGED = 0x08000000, + IMAGE_SCN_MEM_SHARED = 0x10000000, + IMAGE_SCN_MEM_EXECUTE = 0x20000000, + IMAGE_SCN_MEM_READ = 0x40000000, + IMAGE_SCN_MEM_WRITE = 0x80000000 + }; + + struct relocation { + uint32_t VirtualAddress; + uint32_t SymbolTableIndex; + uint16_t Type; + }; + + enum RelocationTypeI386 { + IMAGE_REL_I386_ABSOLUTE = 0x0000, + IMAGE_REL_I386_DIR16 = 0x0001, + IMAGE_REL_I386_REL16 = 0x0002, + IMAGE_REL_I386_DIR32 = 0x0006, + IMAGE_REL_I386_DIR32NB = 0x0007, + IMAGE_REL_I386_SEG12 = 0x0009, + IMAGE_REL_I386_SECTION = 0x000A, + IMAGE_REL_I386_SECREL = 0x000B, + IMAGE_REL_I386_TOKEN = 0x000C, + IMAGE_REL_I386_SECREL7 = 0x000D, + IMAGE_REL_I386_REL32 = 0x0014 + }; + + enum RelocationTypeAMD64 { + IMAGE_REL_AMD64_ABSOLUTE = 0x0000, + IMAGE_REL_AMD64_ADDR64 = 0x0001, + IMAGE_REL_AMD64_ADDR32 = 0x0002, + IMAGE_REL_AMD64_ADDR32NB = 0x0003, + IMAGE_REL_AMD64_REL32 = 0x0004, + IMAGE_REL_AMD64_REL32_1 = 0x0005, + IMAGE_REL_AMD64_REL32_2 = 0x0006, + IMAGE_REL_AMD64_REL32_3 = 0x0007, + IMAGE_REL_AMD64_REL32_4 = 0x0008, + IMAGE_REL_AMD64_REL32_5 = 0x0009, + IMAGE_REL_AMD64_SECTION = 0x000A, + IMAGE_REL_AMD64_SECREL = 0x000B, + IMAGE_REL_AMD64_SECREL7 = 0x000C, + IMAGE_REL_AMD64_TOKEN = 0x000D, + IMAGE_REL_AMD64_SREL32 = 0x000E, + IMAGE_REL_AMD64_PAIR = 0x000F, + IMAGE_REL_AMD64_SSPAN32 = 0x0010 + }; + + enum RelocationTypesARM { + IMAGE_REL_ARM_ABSOLUTE = 0x0000, + IMAGE_REL_ARM_ADDR32 = 0x0001, + IMAGE_REL_ARM_ADDR32NB = 0x0002, + IMAGE_REL_ARM_BRANCH24 = 0x0003, + IMAGE_REL_ARM_BRANCH11 = 0x0004, + IMAGE_REL_ARM_TOKEN = 0x0005, + IMAGE_REL_ARM_BLX24 = 0x0008, + IMAGE_REL_ARM_BLX11 = 0x0009, + IMAGE_REL_ARM_SECTION = 0x000E, + IMAGE_REL_ARM_SECREL = 0x000F, + IMAGE_REL_ARM_MOV32A = 0x0010, + IMAGE_REL_ARM_MOV32T = 0x0011, + IMAGE_REL_ARM_BRANCH20T = 0x0012, + IMAGE_REL_ARM_BRANCH24T = 0x0014, + IMAGE_REL_ARM_BLX23T = 0x0015 + }; + + enum COMDATType { + IMAGE_COMDAT_SELECT_NODUPLICATES = 1, + IMAGE_COMDAT_SELECT_ANY, + IMAGE_COMDAT_SELECT_SAME_SIZE, + IMAGE_COMDAT_SELECT_EXACT_MATCH, + IMAGE_COMDAT_SELECT_ASSOCIATIVE, + IMAGE_COMDAT_SELECT_LARGEST, + IMAGE_COMDAT_SELECT_NEWEST + }; + + // Auxiliary Symbol Formats + struct AuxiliaryFunctionDefinition { + uint32_t TagIndex; + uint32_t TotalSize; + uint32_t PointerToLinenumber; + uint32_t PointerToNextFunction; + char unused[2]; + }; + + struct AuxiliarybfAndefSymbol { + uint8_t unused1[4]; + uint16_t Linenumber; + uint8_t unused2[6]; + uint32_t PointerToNextFunction; + uint8_t unused3[2]; + }; + + struct AuxiliaryWeakExternal { + uint32_t TagIndex; + uint32_t Characteristics; + uint8_t unused[10]; + }; + + enum WeakExternalCharacteristics { + IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY = 1, + IMAGE_WEAK_EXTERN_SEARCH_LIBRARY = 2, + IMAGE_WEAK_EXTERN_SEARCH_ALIAS = 3 + }; + + struct AuxiliarySectionDefinition { + uint32_t Length; + uint16_t NumberOfRelocations; + uint16_t NumberOfLinenumbers; + uint32_t CheckSum; + uint32_t Number; + uint8_t Selection; + char unused; + }; + + struct AuxiliaryCLRToken { + uint8_t AuxType; + uint8_t unused1; + uint32_t SymbolTableIndex; + char unused2[12]; + }; + + union Auxiliary { + AuxiliaryFunctionDefinition FunctionDefinition; + AuxiliarybfAndefSymbol bfAndefSymbol; + AuxiliaryWeakExternal WeakExternal; + AuxiliarySectionDefinition SectionDefinition; + }; + + /// @brief The Import Directory Table. + /// + /// There is a single array of these and one entry per imported DLL. + struct ImportDirectoryTableEntry { + uint32_t ImportLookupTableRVA; + uint32_t TimeDateStamp; + uint32_t ForwarderChain; + uint32_t NameRVA; + uint32_t ImportAddressTableRVA; + }; + + /// @brief The PE32 Import Lookup Table. + /// + /// There is an array of these for each imported DLL. It represents either + /// the ordinal to import from the target DLL, or a name to lookup and import + /// from the target DLL. + /// + /// This also happens to be the same format used by the Import Address Table + /// when it is initially written out to the image. + struct ImportLookupTableEntry32 { + uint32_t data; + + /// @brief Is this entry specified by ordinal, or name? + bool isOrdinal() const { return data & 0x80000000; } + + /// @brief Get the ordinal value of this entry. isOrdinal must be true. + uint16_t getOrdinal() const { + assert(isOrdinal() && "ILT entry is not an ordinal!"); + return data & 0xFFFF; + } + + /// @brief Set the ordinal value and set isOrdinal to true. + void setOrdinal(uint16_t o) { + data = o; + data |= 0x80000000; + } + + /// @brief Get the Hint/Name entry RVA. isOrdinal must be false. + uint32_t getHintNameRVA() const { + assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); + return data; + } + + /// @brief Set the Hint/Name entry RVA and set isOrdinal to false. + void setHintNameRVA(uint32_t rva) { data = rva; } + }; + + /// @brief The DOS compatible header at the front of all PEs. + struct DOSHeader { + uint16_t Magic; + uint16_t UsedBytesInTheLastPage; + uint16_t FileSizeInPages; + uint16_t NumberOfRelocationItems; + uint16_t HeaderSizeInParagraphs; + uint16_t MinimumExtraParagraphs; + uint16_t MaximumExtraParagraphs; + uint16_t InitialRelativeSS; + uint16_t InitialSP; + uint16_t Checksum; + uint16_t InitialIP; + uint16_t InitialRelativeCS; + uint16_t AddressOfRelocationTable; + uint16_t OverlayNumber; + uint16_t Reserved[4]; + uint16_t OEMid; + uint16_t OEMinfo; + uint16_t Reserved2[10]; + uint32_t AddressOfNewExeHeader; + }; + + struct PE32Header { + enum { + PE32 = 0x10b, + PE32_PLUS = 0x20b + }; + + uint16_t Magic; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; + uint32_t SizeOfCode; + uint32_t SizeOfInitializedData; + uint32_t SizeOfUninitializedData; + uint32_t AddressOfEntryPoint; // RVA + uint32_t BaseOfCode; // RVA + uint32_t BaseOfData; // RVA + uint32_t ImageBase; + uint32_t SectionAlignment; + uint32_t FileAlignment; + uint16_t MajorOperatingSystemVersion; + uint16_t MinorOperatingSystemVersion; + uint16_t MajorImageVersion; + uint16_t MinorImageVersion; + uint16_t MajorSubsystemVersion; + uint16_t MinorSubsystemVersion; + uint32_t Win32VersionValue; + uint32_t SizeOfImage; + uint32_t SizeOfHeaders; + uint32_t CheckSum; + uint16_t Subsystem; + // FIXME: This should be DllCharacteristics to match the COFF spec. + uint16_t DLLCharacteristics; + uint32_t SizeOfStackReserve; + uint32_t SizeOfStackCommit; + uint32_t SizeOfHeapReserve; + uint32_t SizeOfHeapCommit; + uint32_t LoaderFlags; + // FIXME: This should be NumberOfRvaAndSizes to match the COFF spec. + uint32_t NumberOfRvaAndSize; + }; + + struct DataDirectory { + uint32_t RelativeVirtualAddress; + uint32_t Size; + }; + + enum DataDirectoryIndex { + EXPORT_TABLE = 0, + IMPORT_TABLE, + RESOURCE_TABLE, + EXCEPTION_TABLE, + CERTIFICATE_TABLE, + BASE_RELOCATION_TABLE, + DEBUG_DIRECTORY, + ARCHITECTURE, + GLOBAL_PTR, + TLS_TABLE, + LOAD_CONFIG_TABLE, + BOUND_IMPORT, + IAT, + DELAY_IMPORT_DESCRIPTOR, + CLR_RUNTIME_HEADER, + + NUM_DATA_DIRECTORIES + }; + + enum WindowsSubsystem { + IMAGE_SUBSYSTEM_UNKNOWN = 0, ///< An unknown subsystem. + IMAGE_SUBSYSTEM_NATIVE = 1, ///< Device drivers and native Windows processes + IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, ///< The Windows GUI subsystem. + IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, ///< The Windows character subsystem. + IMAGE_SUBSYSTEM_OS2_CUI = 5, ///< The OS/2 character subsytem. + IMAGE_SUBSYSTEM_POSIX_CUI = 7, ///< The POSIX character subsystem. + IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8, ///< Native Windows 9x driver. + IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9, ///< Windows CE. + IMAGE_SUBSYSTEM_EFI_APPLICATION = 10, ///< An EFI application. + IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11, ///< An EFI driver with boot + /// services. + IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12, ///< An EFI driver with run-time + /// services. + IMAGE_SUBSYSTEM_EFI_ROM = 13, ///< An EFI ROM image. + IMAGE_SUBSYSTEM_XBOX = 14, ///< XBOX. + IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16 ///< A BCD application. + }; + + enum DLLCharacteristics { + /// ASLR with 64 bit address space. + IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020, + /// DLL can be relocated at load time. + IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040, + /// Code integrity checks are enforced. + IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080, + ///< Image is NX compatible. + IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100, + /// Isolation aware, but do not isolate the image. + IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION = 0x0200, + /// Does not use structured exception handling (SEH). No SEH handler may be + /// called in this image. + IMAGE_DLL_CHARACTERISTICS_NO_SEH = 0x0400, + /// Do not bind the image. + IMAGE_DLL_CHARACTERISTICS_NO_BIND = 0x0800, + ///< Image should execute in an AppContainer. + IMAGE_DLL_CHARACTERISTICS_APPCONTAINER = 0x1000, + ///< A WDM driver. + IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER = 0x2000, + ///< Image supports Control Flow Guard. + IMAGE_DLL_CHARACTERISTICS_GUARD_CF = 0x4000, + /// Terminal Server aware. + IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000 + }; + + enum DebugType { + IMAGE_DEBUG_TYPE_UNKNOWN = 0, + IMAGE_DEBUG_TYPE_COFF = 1, + IMAGE_DEBUG_TYPE_CODEVIEW = 2, + IMAGE_DEBUG_TYPE_FPO = 3, + IMAGE_DEBUG_TYPE_MISC = 4, + IMAGE_DEBUG_TYPE_EXCEPTION = 5, + IMAGE_DEBUG_TYPE_FIXUP = 6, + IMAGE_DEBUG_TYPE_OMAP_TO_SRC = 7, + IMAGE_DEBUG_TYPE_OMAP_FROM_SRC = 8, + IMAGE_DEBUG_TYPE_BORLAND = 9, + IMAGE_DEBUG_TYPE_RESERVED10 = 10, + IMAGE_DEBUG_TYPE_CLSID = 11, + IMAGE_DEBUG_TYPE_VC_FEATURE = 12, + IMAGE_DEBUG_TYPE_POGO = 13, + IMAGE_DEBUG_TYPE_ILTCG = 14, + IMAGE_DEBUG_TYPE_MPX = 15, + IMAGE_DEBUG_TYPE_REPRO = 16, + }; + + enum BaseRelocationType { + IMAGE_REL_BASED_ABSOLUTE = 0, + IMAGE_REL_BASED_HIGH = 1, + IMAGE_REL_BASED_LOW = 2, + IMAGE_REL_BASED_HIGHLOW = 3, + IMAGE_REL_BASED_HIGHADJ = 4, + IMAGE_REL_BASED_MIPS_JMPADDR = 5, + IMAGE_REL_BASED_ARM_MOV32A = 5, + IMAGE_REL_BASED_ARM_MOV32T = 7, + IMAGE_REL_BASED_MIPS_JMPADDR16 = 9, + IMAGE_REL_BASED_DIR64 = 10 + }; + + enum ImportType { + IMPORT_CODE = 0, + IMPORT_DATA = 1, + IMPORT_CONST = 2 + }; + + enum ImportNameType { + /// Import is by ordinal. This indicates that the value in the Ordinal/Hint + /// field of the import header is the import's ordinal. If this constant is + /// not specified, then the Ordinal/Hint field should always be interpreted + /// as the import's hint. + IMPORT_ORDINAL = 0, + /// The import name is identical to the public symbol name + IMPORT_NAME = 1, + /// The import name is the public symbol name, but skipping the leading ?, + /// @, or optionally _. + IMPORT_NAME_NOPREFIX = 2, + /// The import name is the public symbol name, but skipping the leading ?, + /// @, or optionally _, and truncating at the first @. + IMPORT_NAME_UNDECORATE = 3 + }; + + struct ImportHeader { + uint16_t Sig1; ///< Must be IMAGE_FILE_MACHINE_UNKNOWN (0). + uint16_t Sig2; ///< Must be 0xFFFF. + uint16_t Version; + uint16_t Machine; + uint32_t TimeDateStamp; + uint32_t SizeOfData; + uint16_t OrdinalHint; + uint16_t TypeInfo; + + ImportType getType() const { + return static_cast<ImportType>(TypeInfo & 0x3); + } + + ImportNameType getNameType() const { + return static_cast<ImportNameType>((TypeInfo & 0x1C) >> 3); + } + }; + + enum CodeViewIdentifiers { + DEBUG_SECTION_MAGIC = 0x4, + }; + + inline bool isReservedSectionNumber(int32_t SectionNumber) { + return SectionNumber <= 0; + } + +} // End namespace COFF. +} // End namespace llvm. + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Casting.h b/third_party/llvm-subzero/include/llvm/Support/Casting.h new file mode 100644 index 0000000..6ba5efa --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Casting.h
@@ -0,0 +1,326 @@ +//===-- llvm/Support/Casting.h - Allow flexible, checked, casts -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the isa<X>(), cast<X>(), dyn_cast<X>(), cast_or_null<X>(), +// and dyn_cast_or_null<X>() templates. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CASTING_H +#define LLVM_SUPPORT_CASTING_H + +#include "llvm/Support/Compiler.h" +#include "llvm/Support/type_traits.h" +#include <cassert> + +namespace llvm { + +//===----------------------------------------------------------------------===// +// isa<x> Support Templates +//===----------------------------------------------------------------------===// + +// Define a template that can be specialized by smart pointers to reflect the +// fact that they are automatically dereferenced, and are not involved with the +// template selection process... the default implementation is a noop. +// +template<typename From> struct simplify_type { + typedef From SimpleType; // The real type this represents... + + // An accessor to get the real value... + static SimpleType &getSimplifiedValue(From &Val) { return Val; } +}; + +template<typename From> struct simplify_type<const From> { + typedef typename simplify_type<From>::SimpleType NonConstSimpleType; + typedef typename add_const_past_pointer<NonConstSimpleType>::type + SimpleType; + typedef typename add_lvalue_reference_if_not_pointer<SimpleType>::type + RetType; + static RetType getSimplifiedValue(const From& Val) { + return simplify_type<From>::getSimplifiedValue(const_cast<From&>(Val)); + } +}; + +// The core of the implementation of isa<X> is here; To and From should be +// the names of classes. This template can be specialized to customize the +// implementation of isa<> without rewriting it from scratch. +template <typename To, typename From, typename Enabler = void> +struct isa_impl { + static inline bool doit(const From &Val) { + return To::classof(&Val); + } +}; + +/// \brief Always allow upcasts, and perform no dynamic check for them. +template <typename To, typename From> +struct isa_impl< + To, From, typename std::enable_if<std::is_base_of<To, From>::value>::type> { + static inline bool doit(const From &) { return true; } +}; + +template <typename To, typename From> struct isa_impl_cl { + static inline bool doit(const From &Val) { + return isa_impl<To, From>::doit(Val); + } +}; + +template <typename To, typename From> struct isa_impl_cl<To, const From> { + static inline bool doit(const From &Val) { + return isa_impl<To, From>::doit(Val); + } +}; + +template <typename To, typename From> struct isa_impl_cl<To, From*> { + static inline bool doit(const From *Val) { + assert(Val && "isa<> used on a null pointer"); + return isa_impl<To, From>::doit(*Val); + } +}; + +template <typename To, typename From> struct isa_impl_cl<To, From*const> { + static inline bool doit(const From *Val) { + assert(Val && "isa<> used on a null pointer"); + return isa_impl<To, From>::doit(*Val); + } +}; + +template <typename To, typename From> struct isa_impl_cl<To, const From*> { + static inline bool doit(const From *Val) { + assert(Val && "isa<> used on a null pointer"); + return isa_impl<To, From>::doit(*Val); + } +}; + +template <typename To, typename From> struct isa_impl_cl<To, const From*const> { + static inline bool doit(const From *Val) { + assert(Val && "isa<> used on a null pointer"); + return isa_impl<To, From>::doit(*Val); + } +}; + +template<typename To, typename From, typename SimpleFrom> +struct isa_impl_wrap { + // When From != SimplifiedType, we can simplify the type some more by using + // the simplify_type template. + static bool doit(const From &Val) { + return isa_impl_wrap<To, SimpleFrom, + typename simplify_type<SimpleFrom>::SimpleType>::doit( + simplify_type<const From>::getSimplifiedValue(Val)); + } +}; + +template<typename To, typename FromTy> +struct isa_impl_wrap<To, FromTy, FromTy> { + // When From == SimpleType, we are as simple as we are going to get. + static bool doit(const FromTy &Val) { + return isa_impl_cl<To,FromTy>::doit(Val); + } +}; + +// isa<X> - Return true if the parameter to the template is an instance of the +// template type argument. Used like this: +// +// if (isa<Type>(myVal)) { ... } +// +template <class X, class Y> +LLVM_ATTRIBUTE_UNUSED_RESULT inline bool isa(const Y &Val) { + return isa_impl_wrap<X, const Y, + typename simplify_type<const Y>::SimpleType>::doit(Val); +} + +//===----------------------------------------------------------------------===// +// cast<x> Support Templates +//===----------------------------------------------------------------------===// + +template<class To, class From> struct cast_retty; + + +// Calculate what type the 'cast' function should return, based on a requested +// type of To and a source type of From. +template<class To, class From> struct cast_retty_impl { + typedef To& ret_type; // Normal case, return Ty& +}; +template<class To, class From> struct cast_retty_impl<To, const From> { + typedef const To &ret_type; // Normal case, return Ty& +}; + +template<class To, class From> struct cast_retty_impl<To, From*> { + typedef To* ret_type; // Pointer arg case, return Ty* +}; + +template<class To, class From> struct cast_retty_impl<To, const From*> { + typedef const To* ret_type; // Constant pointer arg case, return const Ty* +}; + +template<class To, class From> struct cast_retty_impl<To, const From*const> { + typedef const To* ret_type; // Constant pointer arg case, return const Ty* +}; + + +template<class To, class From, class SimpleFrom> +struct cast_retty_wrap { + // When the simplified type and the from type are not the same, use the type + // simplifier to reduce the type, then reuse cast_retty_impl to get the + // resultant type. + typedef typename cast_retty<To, SimpleFrom>::ret_type ret_type; +}; + +template<class To, class FromTy> +struct cast_retty_wrap<To, FromTy, FromTy> { + // When the simplified type is equal to the from type, use it directly. + typedef typename cast_retty_impl<To,FromTy>::ret_type ret_type; +}; + +template<class To, class From> +struct cast_retty { + typedef typename cast_retty_wrap<To, From, + typename simplify_type<From>::SimpleType>::ret_type ret_type; +}; + +// Ensure the non-simple values are converted using the simplify_type template +// that may be specialized by smart pointers... +// +template<class To, class From, class SimpleFrom> struct cast_convert_val { + // This is not a simple type, use the template to simplify it... + static typename cast_retty<To, From>::ret_type doit(From &Val) { + return cast_convert_val<To, SimpleFrom, + typename simplify_type<SimpleFrom>::SimpleType>::doit( + simplify_type<From>::getSimplifiedValue(Val)); + } +}; + +template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> { + // This _is_ a simple type, just cast it. + static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) { + typename cast_retty<To, FromTy>::ret_type Res2 + = (typename cast_retty<To, FromTy>::ret_type)const_cast<FromTy&>(Val); + return Res2; + } +}; + +template <class X> struct is_simple_type { + static const bool value = + std::is_same<X, typename simplify_type<X>::SimpleType>::value; +}; + +// cast<X> - Return the argument parameter cast to the specified type. This +// casting operator asserts that the type is correct, so it does not return null +// on failure. It does not allow a null argument (use cast_or_null for that). +// It is typically used like this: +// +// cast<Instruction>(myVal)->getParent() +// +template <class X, class Y> +inline typename std::enable_if<!is_simple_type<Y>::value, + typename cast_retty<X, const Y>::ret_type>::type +cast(const Y &Val) { + assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); + return cast_convert_val< + X, const Y, typename simplify_type<const Y>::SimpleType>::doit(Val); +} + +template <class X, class Y> +inline typename cast_retty<X, Y>::ret_type cast(Y &Val) { + assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); + return cast_convert_val<X, Y, + typename simplify_type<Y>::SimpleType>::doit(Val); +} + +template <class X, class Y> +inline typename cast_retty<X, Y *>::ret_type cast(Y *Val) { + assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); + return cast_convert_val<X, Y*, + typename simplify_type<Y*>::SimpleType>::doit(Val); +} + +// cast_or_null<X> - Functionally identical to cast, except that a null value is +// accepted. +// +template <class X, class Y> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type +cast_or_null(const Y &Val) { + if (!Val) + return nullptr; + assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); + return cast<X>(Val); +} + +template <class X, class Y> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type +cast_or_null(Y &Val) { + if (!Val) + return nullptr; + assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); + return cast<X>(Val); +} + +template <class X, class Y> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type +cast_or_null(Y *Val) { + if (!Val) return nullptr; + assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); + return cast<X>(Val); +} + + +// dyn_cast<X> - Return the argument parameter cast to the specified type. This +// casting operator returns null if the argument is of the wrong type, so it can +// be used to test for a type as well as cast if successful. This should be +// used in the context of an if statement like this: +// +// if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... } +// + +template <class X, class Y> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type +dyn_cast(const Y &Val) { + return isa<X>(Val) ? cast<X>(Val) : nullptr; +} + +template <class X, class Y> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y>::ret_type +dyn_cast(Y &Val) { + return isa<X>(Val) ? cast<X>(Val) : nullptr; +} + +template <class X, class Y> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type +dyn_cast(Y *Val) { + return isa<X>(Val) ? cast<X>(Val) : nullptr; +} + +// dyn_cast_or_null<X> - Functionally identical to dyn_cast, except that a null +// value is accepted. +// +template <class X, class Y> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type +dyn_cast_or_null(const Y &Val) { + return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; +} + +template <class X, class Y> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type +dyn_cast_or_null(Y &Val) { + return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; +} + +template <class X, class Y> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type +dyn_cast_or_null(Y *Val) { + return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; +} + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/CommandLine.h b/third_party/llvm-subzero/include/llvm/Support/CommandLine.h new file mode 100644 index 0000000..a0ec262 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/CommandLine.h
@@ -0,0 +1,1833 @@ +//===- llvm/Support/CommandLine.h - Command line handler --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements a command line argument processor that is useful when +// creating a tool. It provides a simple, minimalistic interface that is easily +// extensible and supports nonlocal (library) command line options. +// +// Note that rather than trying to figure out what this code does, you should +// read the library documentation located in docs/CommandLine.html or looks at +// the many example usages in tools/*/*.cpp +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_COMMANDLINE_H +#define LLVM_SUPPORT_COMMANDLINE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ManagedStatic.h" +#include <cassert> +#include <climits> +#include <cstdarg> +#include <utility> +#include <vector> + +namespace llvm { + +class StringSaver; + +/// cl Namespace - This namespace contains all of the command line option +/// processing machinery. It is intentionally a short name to make qualified +/// usage concise. +namespace cl { + +//===----------------------------------------------------------------------===// +// ParseCommandLineOptions - Command line option processing entry point. +// +bool ParseCommandLineOptions(int argc, const char *const *argv, + const char *Overview = nullptr, + bool IgnoreErrors = false); + +//===----------------------------------------------------------------------===// +// ParseEnvironmentOptions - Environment variable option processing alternate +// entry point. +// +void ParseEnvironmentOptions(const char *progName, const char *envvar, + const char *Overview = nullptr); + +///===---------------------------------------------------------------------===// +/// SetVersionPrinter - Override the default (LLVM specific) version printer +/// used to print out the version when --version is given +/// on the command line. This allows other systems using the +/// CommandLine utilities to print their own version string. +void SetVersionPrinter(void (*func)()); + +///===---------------------------------------------------------------------===// +/// AddExtraVersionPrinter - Add an extra printer to use in addition to the +/// default one. This can be called multiple times, +/// and each time it adds a new function to the list +/// which will be called after the basic LLVM version +/// printing is complete. Each can then add additional +/// information specific to the tool. +void AddExtraVersionPrinter(void (*func)()); + +// PrintOptionValues - Print option values. +// With -print-options print the difference between option values and defaults. +// With -print-all-options print all option values. +// (Currently not perfect, but best-effort.) +void PrintOptionValues(); + +// Forward declaration - AddLiteralOption needs to be up here to make gcc happy. +class Option; + +/// \brief Adds a new option for parsing and provides the option it refers to. +/// +/// \param O pointer to the option +/// \param Name the string name for the option to handle during parsing +/// +/// Literal options are used by some parsers to register special option values. +/// This is how the PassNameParser registers pass names for opt. +void AddLiteralOption(Option &O, const char *Name); + +//===----------------------------------------------------------------------===// +// Flags permitted to be passed to command line arguments +// + +enum NumOccurrencesFlag { // Flags for the number of occurrences allowed + Optional = 0x00, // Zero or One occurrence + ZeroOrMore = 0x01, // Zero or more occurrences allowed + Required = 0x02, // One occurrence required + OneOrMore = 0x03, // One or more occurrences required + + // ConsumeAfter - Indicates that this option is fed anything that follows the + // last positional argument required by the application (it is an error if + // there are zero positional arguments, and a ConsumeAfter option is used). + // Thus, for example, all arguments to LLI are processed until a filename is + // found. Once a filename is found, all of the succeeding arguments are + // passed, unprocessed, to the ConsumeAfter option. + // + ConsumeAfter = 0x04 +}; + +enum ValueExpected { // Is a value required for the option? + // zero reserved for the unspecified value + ValueOptional = 0x01, // The value can appear... or not + ValueRequired = 0x02, // The value is required to appear! + ValueDisallowed = 0x03 // A value may not be specified (for flags) +}; + +enum OptionHidden { // Control whether -help shows this option + NotHidden = 0x00, // Option included in -help & -help-hidden + Hidden = 0x01, // -help doesn't, but -help-hidden does + ReallyHidden = 0x02 // Neither -help nor -help-hidden show this arg +}; + +// Formatting flags - This controls special features that the option might have +// that cause it to be parsed differently... +// +// Prefix - This option allows arguments that are otherwise unrecognized to be +// matched by options that are a prefix of the actual value. This is useful for +// cases like a linker, where options are typically of the form '-lfoo' or +// '-L../../include' where -l or -L are the actual flags. When prefix is +// enabled, and used, the value for the flag comes from the suffix of the +// argument. +// +// Grouping - With this option enabled, multiple letter options are allowed to +// bunch together with only a single hyphen for the whole group. This allows +// emulation of the behavior that ls uses for example: ls -la === ls -l -a +// + +enum FormattingFlags { + NormalFormatting = 0x00, // Nothing special + Positional = 0x01, // Is a positional argument, no '-' required + Prefix = 0x02, // Can this option directly prefix its value? + Grouping = 0x03 // Can this option group with other options? +}; + +enum MiscFlags { // Miscellaneous flags to adjust argument + CommaSeparated = 0x01, // Should this cl::list split between commas? + PositionalEatsArgs = 0x02, // Should this positional cl::list eat -args? + Sink = 0x04 // Should this cl::list eat all unknown options? +}; + +//===----------------------------------------------------------------------===// +// Option Category class +// +class OptionCategory { +private: + const char *const Name; + const char *const Description; + void registerCategory(); + +public: + OptionCategory(const char *const Name, + const char *const Description = nullptr) + : Name(Name), Description(Description) { + registerCategory(); + } + const char *getName() const { return Name; } + const char *getDescription() const { return Description; } +}; + +// The general Option Category (used as default category). +extern OptionCategory GeneralCategory; + +//===----------------------------------------------------------------------===// +// SubCommand class +// +class SubCommand { +private: + const char *const Name = nullptr; + const char *const Description = nullptr; + +protected: + void registerSubCommand(); + void unregisterSubCommand(); + +public: + SubCommand(const char *const Name, const char *const Description = nullptr) + : Name(Name), Description(Description) { + registerSubCommand(); + } + SubCommand() {} + + void reset(); + + operator bool() const; + + const char *getName() const { return Name; } + const char *getDescription() const { return Description; } + + SmallVector<Option *, 4> PositionalOpts; + SmallVector<Option *, 4> SinkOpts; + StringMap<Option *> OptionsMap; + + Option *ConsumeAfterOpt = nullptr; // The ConsumeAfter option if it exists. +}; + +// A special subcommand representing no subcommand +extern ManagedStatic<SubCommand> TopLevelSubCommand; + +// A special subcommand that can be used to put an option into all subcommands. +extern ManagedStatic<SubCommand> AllSubCommands; + +//===----------------------------------------------------------------------===// +// Option Base class +// +class alias; +class Option { + friend class alias; + + // handleOccurrences - Overriden by subclasses to handle the value passed into + // an argument. Should return true if there was an error processing the + // argument and the program should exit. + // + virtual bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) = 0; + + virtual enum ValueExpected getValueExpectedFlagDefault() const { + return ValueOptional; + } + + // Out of line virtual function to provide home for the class. + virtual void anchor(); + + int NumOccurrences; // The number of times specified + // Occurrences, HiddenFlag, and Formatting are all enum types but to avoid + // problems with signed enums in bitfields. + unsigned Occurrences : 3; // enum NumOccurrencesFlag + // not using the enum type for 'Value' because zero is an implementation + // detail representing the non-value + unsigned Value : 2; + unsigned HiddenFlag : 2; // enum OptionHidden + unsigned Formatting : 2; // enum FormattingFlags + unsigned Misc : 3; + unsigned Position; // Position of last occurrence of the option + unsigned AdditionalVals; // Greater than 0 for multi-valued option. + +public: + StringRef ArgStr; // The argument string itself (ex: "help", "o") + StringRef HelpStr; // The descriptive text message for -help + StringRef ValueStr; // String describing what the value of this option is + OptionCategory *Category; // The Category this option belongs to + SmallPtrSet<SubCommand *, 4> Subs; // The subcommands this option belongs to. + bool FullyInitialized; // Has addArguemnt been called? + + inline enum NumOccurrencesFlag getNumOccurrencesFlag() const { + return (enum NumOccurrencesFlag)Occurrences; + } + inline enum ValueExpected getValueExpectedFlag() const { + return Value ? ((enum ValueExpected)Value) : getValueExpectedFlagDefault(); + } + inline enum OptionHidden getOptionHiddenFlag() const { + return (enum OptionHidden)HiddenFlag; + } + inline enum FormattingFlags getFormattingFlag() const { + return (enum FormattingFlags)Formatting; + } + inline unsigned getMiscFlags() const { return Misc; } + inline unsigned getPosition() const { return Position; } + inline unsigned getNumAdditionalVals() const { return AdditionalVals; } + + // hasArgStr - Return true if the argstr != "" + bool hasArgStr() const { return !ArgStr.empty(); } + bool isPositional() const { return getFormattingFlag() == cl::Positional; } + bool isSink() const { return getMiscFlags() & cl::Sink; } + bool isConsumeAfter() const { + return getNumOccurrencesFlag() == cl::ConsumeAfter; + } + bool isInAllSubCommands() const { + return any_of(Subs, [](const SubCommand *SC) { + return SC == &*AllSubCommands; + }); + } + + //-------------------------------------------------------------------------=== + // Accessor functions set by OptionModifiers + // + void setArgStr(StringRef S); + void setDescription(StringRef S) { HelpStr = S; } + void setValueStr(StringRef S) { ValueStr = S; } + void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { Occurrences = Val; } + void setValueExpectedFlag(enum ValueExpected Val) { Value = Val; } + void setHiddenFlag(enum OptionHidden Val) { HiddenFlag = Val; } + void setFormattingFlag(enum FormattingFlags V) { Formatting = V; } + void setMiscFlag(enum MiscFlags M) { Misc |= M; } + void setPosition(unsigned pos) { Position = pos; } + void setCategory(OptionCategory &C) { Category = &C; } + void addSubCommand(SubCommand &S) { Subs.insert(&S); } + +protected: + explicit Option(enum NumOccurrencesFlag OccurrencesFlag, + enum OptionHidden Hidden) + : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), + HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), Position(0), + AdditionalVals(0), ArgStr(""), HelpStr(""), ValueStr(""), + Category(&GeneralCategory), FullyInitialized(false) {} + + inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; } + +public: + // addArgument - Register this argument with the commandline system. + // + void addArgument(); + + /// Unregisters this option from the CommandLine system. + /// + /// This option must have been the last option registered. + /// For testing purposes only. + void removeArgument(); + + // Return the width of the option tag for printing... + virtual size_t getOptionWidth() const = 0; + + // printOptionInfo - Print out information about this option. The + // to-be-maintained width is specified. + // + virtual void printOptionInfo(size_t GlobalWidth) const = 0; + + virtual void printOptionValue(size_t GlobalWidth, bool Force) const = 0; + + virtual void getExtraOptionNames(SmallVectorImpl<StringRef> &) {} + + // addOccurrence - Wrapper around handleOccurrence that enforces Flags. + // + virtual bool addOccurrence(unsigned pos, StringRef ArgName, StringRef Value, + bool MultiArg = false); + + // Prints option name followed by message. Always returns true. + bool error(const Twine &Message, StringRef ArgName = StringRef()); + +public: + inline int getNumOccurrences() const { return NumOccurrences; } + inline void reset() { NumOccurrences = 0; } + virtual ~Option() {} +}; + +//===----------------------------------------------------------------------===// +// Command line option modifiers that can be used to modify the behavior of +// command line option parsers... +// + +// desc - Modifier to set the description shown in the -help output... +struct desc { + const char *Desc; + desc(const char *Str) : Desc(Str) {} + void apply(Option &O) const { O.setDescription(Desc); } +}; + +// value_desc - Modifier to set the value description shown in the -help +// output... +struct value_desc { + const char *Desc; + value_desc(const char *Str) : Desc(Str) {} + void apply(Option &O) const { O.setValueStr(Desc); } +}; + +// init - Specify a default (initial) value for the command line argument, if +// the default constructor for the argument type does not give you what you +// want. This is only valid on "opt" arguments, not on "list" arguments. +// +template <class Ty> struct initializer { + const Ty &Init; + initializer(const Ty &Val) : Init(Val) {} + + template <class Opt> void apply(Opt &O) const { O.setInitialValue(Init); } +}; + +template <class Ty> initializer<Ty> init(const Ty &Val) { + return initializer<Ty>(Val); +} + +// location - Allow the user to specify which external variable they want to +// store the results of the command line argument processing into, if they don't +// want to store it in the option itself. +// +template <class Ty> struct LocationClass { + Ty &Loc; + LocationClass(Ty &L) : Loc(L) {} + + template <class Opt> void apply(Opt &O) const { O.setLocation(O, Loc); } +}; + +template <class Ty> LocationClass<Ty> location(Ty &L) { + return LocationClass<Ty>(L); +} + +// cat - Specifiy the Option category for the command line argument to belong +// to. +struct cat { + OptionCategory &Category; + cat(OptionCategory &c) : Category(c) {} + + template <class Opt> void apply(Opt &O) const { O.setCategory(Category); } +}; + +// sub - Specify the subcommand that this option belongs to. +struct sub { + SubCommand ⋐ + sub(SubCommand &S) : Sub(S) {} + + template <class Opt> void apply(Opt &O) const { O.addSubCommand(Sub); } +}; + +//===----------------------------------------------------------------------===// +// OptionValue class + +// Support value comparison outside the template. +struct GenericOptionValue { + virtual bool compare(const GenericOptionValue &V) const = 0; + +protected: + ~GenericOptionValue() = default; + GenericOptionValue() = default; + GenericOptionValue(const GenericOptionValue&) = default; + GenericOptionValue &operator=(const GenericOptionValue &) = default; + +private: + virtual void anchor(); +}; + +template <class DataType> struct OptionValue; + +// The default value safely does nothing. Option value printing is only +// best-effort. +template <class DataType, bool isClass> +struct OptionValueBase : public GenericOptionValue { + // Temporary storage for argument passing. + typedef OptionValue<DataType> WrapperType; + + bool hasValue() const { return false; } + + const DataType &getValue() const { llvm_unreachable("no default value"); } + + // Some options may take their value from a different data type. + template <class DT> void setValue(const DT & /*V*/) {} + + bool compare(const DataType & /*V*/) const { return false; } + + bool compare(const GenericOptionValue & /*V*/) const override { + return false; + } + +protected: + ~OptionValueBase() = default; +}; + +// Simple copy of the option value. +template <class DataType> class OptionValueCopy : public GenericOptionValue { + DataType Value; + bool Valid; + +protected: + ~OptionValueCopy() = default; + OptionValueCopy(const OptionValueCopy&) = default; + OptionValueCopy &operator=(const OptionValueCopy&) = default; + +public: + OptionValueCopy() : Valid(false) {} + + bool hasValue() const { return Valid; } + + const DataType &getValue() const { + assert(Valid && "invalid option value"); + return Value; + } + + void setValue(const DataType &V) { + Valid = true; + Value = V; + } + + bool compare(const DataType &V) const { return Valid && (Value != V); } + + bool compare(const GenericOptionValue &V) const override { + const OptionValueCopy<DataType> &VC = + static_cast<const OptionValueCopy<DataType> &>(V); + if (!VC.hasValue()) + return false; + return compare(VC.getValue()); + } +}; + +// Non-class option values. +template <class DataType> +struct OptionValueBase<DataType, false> : OptionValueCopy<DataType> { + typedef DataType WrapperType; + +protected: + ~OptionValueBase() = default; + OptionValueBase() = default; + OptionValueBase(const OptionValueBase&) = default; + OptionValueBase &operator=(const OptionValueBase&) = default; +}; + +// Top-level option class. +template <class DataType> +struct OptionValue final + : OptionValueBase<DataType, std::is_class<DataType>::value> { + OptionValue() = default; + + OptionValue(const DataType &V) { this->setValue(V); } + // Some options may take their value from a different data type. + template <class DT> OptionValue<DataType> &operator=(const DT &V) { + this->setValue(V); + return *this; + } +}; + +// Other safe-to-copy-by-value common option types. +enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE }; +template <> +struct OptionValue<cl::boolOrDefault> final + : OptionValueCopy<cl::boolOrDefault> { + typedef cl::boolOrDefault WrapperType; + + OptionValue() {} + + OptionValue(const cl::boolOrDefault &V) { this->setValue(V); } + OptionValue<cl::boolOrDefault> &operator=(const cl::boolOrDefault &V) { + setValue(V); + return *this; + } + +private: + void anchor() override; +}; + +template <> +struct OptionValue<std::string> final : OptionValueCopy<std::string> { + typedef StringRef WrapperType; + + OptionValue() {} + + OptionValue(const std::string &V) { this->setValue(V); } + OptionValue<std::string> &operator=(const std::string &V) { + setValue(V); + return *this; + } + +private: + void anchor() override; +}; + +//===----------------------------------------------------------------------===// +// Enum valued command line option +// +#define clEnumVal(ENUMVAL, DESC) #ENUMVAL, int(ENUMVAL), DESC +#define clEnumValN(ENUMVAL, FLAGNAME, DESC) FLAGNAME, int(ENUMVAL), DESC +#define clEnumValEnd (reinterpret_cast<void *>(0)) + +// values - For custom data types, allow specifying a group of values together +// as the values that go into the mapping that the option handler uses. Note +// that the values list must always have a 0 at the end of the list to indicate +// that the list has ended. +// +template <class DataType> class ValuesClass { + // Use a vector instead of a map, because the lists should be short, + // the overhead is less, and most importantly, it keeps them in the order + // inserted so we can print our option out nicely. + SmallVector<std::pair<const char *, std::pair<int, const char *>>, 4> Values; + void processValues(va_list Vals); + +public: + ValuesClass(const char *EnumName, DataType Val, const char *Desc, + va_list ValueArgs) { + // Insert the first value, which is required. + Values.push_back(std::make_pair(EnumName, std::make_pair(Val, Desc))); + + // Process the varargs portion of the values... + while (const char *enumName = va_arg(ValueArgs, const char *)) { + DataType EnumVal = static_cast<DataType>(va_arg(ValueArgs, int)); + const char *EnumDesc = va_arg(ValueArgs, const char *); + Values.push_back(std::make_pair(enumName, // Add value to value map + std::make_pair(EnumVal, EnumDesc))); + } + } + + template <class Opt> void apply(Opt &O) const { + for (size_t i = 0, e = Values.size(); i != e; ++i) + O.getParser().addLiteralOption(Values[i].first, Values[i].second.first, + Values[i].second.second); + } +}; + +template <class DataType> +ValuesClass<DataType> LLVM_END_WITH_NULL +values(const char *Arg, DataType Val, const char *Desc, ...) { + va_list ValueArgs; + va_start(ValueArgs, Desc); + ValuesClass<DataType> Vals(Arg, Val, Desc, ValueArgs); + va_end(ValueArgs); + return Vals; +} + +//===----------------------------------------------------------------------===// +// parser class - Parameterizable parser for different data types. By default, +// known data types (string, int, bool) have specialized parsers, that do what +// you would expect. The default parser, used for data types that are not +// built-in, uses a mapping table to map specific options to values, which is +// used, among other things, to handle enum types. + +//-------------------------------------------------- +// generic_parser_base - This class holds all the non-generic code that we do +// not need replicated for every instance of the generic parser. This also +// allows us to put stuff into CommandLine.cpp +// +class generic_parser_base { +protected: + class GenericOptionInfo { + public: + GenericOptionInfo(const char *name, const char *helpStr) + : Name(name), HelpStr(helpStr) {} + const char *Name; + const char *HelpStr; + }; + +public: + generic_parser_base(Option &O) : Owner(O) {} + + virtual ~generic_parser_base() {} // Base class should have virtual-dtor + + // getNumOptions - Virtual function implemented by generic subclass to + // indicate how many entries are in Values. + // + virtual unsigned getNumOptions() const = 0; + + // getOption - Return option name N. + virtual const char *getOption(unsigned N) const = 0; + + // getDescription - Return description N + virtual const char *getDescription(unsigned N) const = 0; + + // Return the width of the option tag for printing... + virtual size_t getOptionWidth(const Option &O) const; + + virtual const GenericOptionValue &getOptionValue(unsigned N) const = 0; + + // printOptionInfo - Print out information about this option. The + // to-be-maintained width is specified. + // + virtual void printOptionInfo(const Option &O, size_t GlobalWidth) const; + + void printGenericOptionDiff(const Option &O, const GenericOptionValue &V, + const GenericOptionValue &Default, + size_t GlobalWidth) const; + + // printOptionDiff - print the value of an option and it's default. + // + // Template definition ensures that the option and default have the same + // DataType (via the same AnyOptionValue). + template <class AnyOptionValue> + void printOptionDiff(const Option &O, const AnyOptionValue &V, + const AnyOptionValue &Default, + size_t GlobalWidth) const { + printGenericOptionDiff(O, V, Default, GlobalWidth); + } + + void initialize() {} + + void getExtraOptionNames(SmallVectorImpl<StringRef> &OptionNames) { + // If there has been no argstr specified, that means that we need to add an + // argument for every possible option. This ensures that our options are + // vectored to us. + if (!Owner.hasArgStr()) + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) + OptionNames.push_back(getOption(i)); + } + + enum ValueExpected getValueExpectedFlagDefault() const { + // If there is an ArgStr specified, then we are of the form: + // + // -opt=O2 or -opt O2 or -optO2 + // + // In which case, the value is required. Otherwise if an arg str has not + // been specified, we are of the form: + // + // -O2 or O2 or -la (where -l and -a are separate options) + // + // If this is the case, we cannot allow a value. + // + if (Owner.hasArgStr()) + return ValueRequired; + else + return ValueDisallowed; + } + + // findOption - Return the option number corresponding to the specified + // argument string. If the option is not found, getNumOptions() is returned. + // + unsigned findOption(const char *Name); + +protected: + Option &Owner; +}; + +// Default parser implementation - This implementation depends on having a +// mapping of recognized options to values of some sort. In addition to this, +// each entry in the mapping also tracks a help message that is printed with the +// command line option for -help. Because this is a simple mapping parser, the +// data type can be any unsupported type. +// +template <class DataType> class parser : public generic_parser_base { +protected: + class OptionInfo : public GenericOptionInfo { + public: + OptionInfo(const char *name, DataType v, const char *helpStr) + : GenericOptionInfo(name, helpStr), V(v) {} + OptionValue<DataType> V; + }; + SmallVector<OptionInfo, 8> Values; + +public: + parser(Option &O) : generic_parser_base(O) {} + typedef DataType parser_data_type; + + // Implement virtual functions needed by generic_parser_base + unsigned getNumOptions() const override { return unsigned(Values.size()); } + const char *getOption(unsigned N) const override { return Values[N].Name; } + const char *getDescription(unsigned N) const override { + return Values[N].HelpStr; + } + + // getOptionValue - Return the value of option name N. + const GenericOptionValue &getOptionValue(unsigned N) const override { + return Values[N].V; + } + + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, DataType &V) { + StringRef ArgVal; + if (Owner.hasArgStr()) + ArgVal = Arg; + else + ArgVal = ArgName; + + for (size_t i = 0, e = Values.size(); i != e; ++i) + if (Values[i].Name == ArgVal) { + V = Values[i].V.getValue(); + return false; + } + + return O.error("Cannot find option named '" + ArgVal + "'!"); + } + + /// addLiteralOption - Add an entry to the mapping table. + /// + template <class DT> + void addLiteralOption(const char *Name, const DT &V, const char *HelpStr) { + assert(findOption(Name) == Values.size() && "Option already exists!"); + OptionInfo X(Name, static_cast<DataType>(V), HelpStr); + Values.push_back(X); + AddLiteralOption(Owner, Name); + } + + /// removeLiteralOption - Remove the specified option. + /// + void removeLiteralOption(const char *Name) { + unsigned N = findOption(Name); + assert(N != Values.size() && "Option not found!"); + Values.erase(Values.begin() + N); + } +}; + +//-------------------------------------------------- +// basic_parser - Super class of parsers to provide boilerplate code +// +class basic_parser_impl { // non-template implementation of basic_parser<t> +public: + basic_parser_impl(Option &) {} + + + enum ValueExpected getValueExpectedFlagDefault() const { + return ValueRequired; + } + + void getExtraOptionNames(SmallVectorImpl<StringRef> &) {} + + void initialize() {} + + // Return the width of the option tag for printing... + size_t getOptionWidth(const Option &O) const; + + // printOptionInfo - Print out information about this option. The + // to-be-maintained width is specified. + // + void printOptionInfo(const Option &O, size_t GlobalWidth) const; + + // printOptionNoValue - Print a placeholder for options that don't yet support + // printOptionDiff(). + void printOptionNoValue(const Option &O, size_t GlobalWidth) const; + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "value"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); + +protected: + ~basic_parser_impl() = default; + // A helper for basic_parser::printOptionDiff. + void printOptionName(const Option &O, size_t GlobalWidth) const; +}; + +// basic_parser - The real basic parser is just a template wrapper that provides +// a typedef for the provided data type. +// +template <class DataType> class basic_parser : public basic_parser_impl { +public: + basic_parser(Option &O) : basic_parser_impl(O) {} + typedef DataType parser_data_type; + typedef OptionValue<DataType> OptVal; + +protected: + // Workaround Clang PR22793 + ~basic_parser() {} +}; + +//-------------------------------------------------- +// parser<bool> +// +template <> class parser<bool> final : public basic_parser<bool> { +public: + parser(Option &O) : basic_parser(O) {} + + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, bool &Val); + + void initialize() {} + + enum ValueExpected getValueExpectedFlagDefault() const { + return ValueOptional; + } + + // getValueName - Do not print =<value> at all. + const char *getValueName() const override { return nullptr; } + + void printOptionDiff(const Option &O, bool V, OptVal Default, + size_t GlobalWidth) const; + + // An out-of-line virtual method to provide a 'home' for this class. + void anchor() override; +}; + +extern template class basic_parser<bool>; + +//-------------------------------------------------- +// parser<boolOrDefault> +template <> +class parser<boolOrDefault> final : public basic_parser<boolOrDefault> { +public: + parser(Option &O) : basic_parser(O) {} + + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, boolOrDefault &Val); + + enum ValueExpected getValueExpectedFlagDefault() const { + return ValueOptional; + } + + // getValueName - Do not print =<value> at all. + const char *getValueName() const override { return nullptr; } + + void printOptionDiff(const Option &O, boolOrDefault V, OptVal Default, + size_t GlobalWidth) const; + + // An out-of-line virtual method to provide a 'home' for this class. + void anchor() override; +}; + +extern template class basic_parser<boolOrDefault>; + +//-------------------------------------------------- +// parser<int> +// +template <> class parser<int> final : public basic_parser<int> { +public: + parser(Option &O) : basic_parser(O) {} + + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, int &Val); + + // getValueName - Overload in subclass to provide a better default value. + const char *getValueName() const override { return "int"; } + + void printOptionDiff(const Option &O, int V, OptVal Default, + size_t GlobalWidth) const; + + // An out-of-line virtual method to provide a 'home' for this class. + void anchor() override; +}; + +extern template class basic_parser<int>; + +//-------------------------------------------------- +// parser<unsigned> +// +template <> class parser<unsigned> final : public basic_parser<unsigned> { +public: + parser(Option &O) : basic_parser(O) {} + + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned &Val); + + // getValueName - Overload in subclass to provide a better default value. + const char *getValueName() const override { return "uint"; } + + void printOptionDiff(const Option &O, unsigned V, OptVal Default, + size_t GlobalWidth) const; + + // An out-of-line virtual method to provide a 'home' for this class. + void anchor() override; +}; + +extern template class basic_parser<unsigned>; + +//-------------------------------------------------- +// parser<unsigned long long> +// +template <> +class parser<unsigned long long> final + : public basic_parser<unsigned long long> { +public: + parser(Option &O) : basic_parser(O) {} + + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, + unsigned long long &Val); + + // getValueName - Overload in subclass to provide a better default value. + const char *getValueName() const override { return "uint"; } + + void printOptionDiff(const Option &O, unsigned long long V, OptVal Default, + size_t GlobalWidth) const; + + // An out-of-line virtual method to provide a 'home' for this class. + void anchor() override; +}; + +extern template class basic_parser<unsigned long long>; + +//-------------------------------------------------- +// parser<double> +// +template <> class parser<double> final : public basic_parser<double> { +public: + parser(Option &O) : basic_parser(O) {} + + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, double &Val); + + // getValueName - Overload in subclass to provide a better default value. + const char *getValueName() const override { return "number"; } + + void printOptionDiff(const Option &O, double V, OptVal Default, + size_t GlobalWidth) const; + + // An out-of-line virtual method to provide a 'home' for this class. + void anchor() override; +}; + +extern template class basic_parser<double>; + +//-------------------------------------------------- +// parser<float> +// +template <> class parser<float> final : public basic_parser<float> { +public: + parser(Option &O) : basic_parser(O) {} + + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, float &Val); + + // getValueName - Overload in subclass to provide a better default value. + const char *getValueName() const override { return "number"; } + + void printOptionDiff(const Option &O, float V, OptVal Default, + size_t GlobalWidth) const; + + // An out-of-line virtual method to provide a 'home' for this class. + void anchor() override; +}; + +extern template class basic_parser<float>; + +//-------------------------------------------------- +// parser<std::string> +// +template <> class parser<std::string> final : public basic_parser<std::string> { +public: + parser(Option &O) : basic_parser(O) {} + + // parse - Return true on error. + bool parse(Option &, StringRef, StringRef Arg, std::string &Value) { + Value = Arg.str(); + return false; + } + + // getValueName - Overload in subclass to provide a better default value. + const char *getValueName() const override { return "string"; } + + void printOptionDiff(const Option &O, StringRef V, const OptVal &Default, + size_t GlobalWidth) const; + + // An out-of-line virtual method to provide a 'home' for this class. + void anchor() override; +}; + +extern template class basic_parser<std::string>; + +//-------------------------------------------------- +// parser<char> +// +template <> class parser<char> final : public basic_parser<char> { +public: + parser(Option &O) : basic_parser(O) {} + + // parse - Return true on error. + bool parse(Option &, StringRef, StringRef Arg, char &Value) { + Value = Arg[0]; + return false; + } + + // getValueName - Overload in subclass to provide a better default value. + const char *getValueName() const override { return "char"; } + + void printOptionDiff(const Option &O, char V, OptVal Default, + size_t GlobalWidth) const; + + // An out-of-line virtual method to provide a 'home' for this class. + void anchor() override; +}; + +extern template class basic_parser<char>; + +//-------------------------------------------------- +// PrintOptionDiff +// +// This collection of wrappers is the intermediary between class opt and class +// parser to handle all the template nastiness. + +// This overloaded function is selected by the generic parser. +template <class ParserClass, class DT> +void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V, + const OptionValue<DT> &Default, size_t GlobalWidth) { + OptionValue<DT> OV = V; + P.printOptionDiff(O, OV, Default, GlobalWidth); +} + +// This is instantiated for basic parsers when the parsed value has a different +// type than the option value. e.g. HelpPrinter. +template <class ParserDT, class ValDT> struct OptionDiffPrinter { + void print(const Option &O, const parser<ParserDT> &P, const ValDT & /*V*/, + const OptionValue<ValDT> & /*Default*/, size_t GlobalWidth) { + P.printOptionNoValue(O, GlobalWidth); + } +}; + +// This is instantiated for basic parsers when the parsed value has the same +// type as the option value. +template <class DT> struct OptionDiffPrinter<DT, DT> { + void print(const Option &O, const parser<DT> &P, const DT &V, + const OptionValue<DT> &Default, size_t GlobalWidth) { + P.printOptionDiff(O, V, Default, GlobalWidth); + } +}; + +// This overloaded function is selected by the basic parser, which may parse a +// different type than the option type. +template <class ParserClass, class ValDT> +void printOptionDiff( + const Option &O, + const basic_parser<typename ParserClass::parser_data_type> &P, + const ValDT &V, const OptionValue<ValDT> &Default, size_t GlobalWidth) { + + OptionDiffPrinter<typename ParserClass::parser_data_type, ValDT> printer; + printer.print(O, static_cast<const ParserClass &>(P), V, Default, + GlobalWidth); +} + +//===----------------------------------------------------------------------===// +// applicator class - This class is used because we must use partial +// specialization to handle literal string arguments specially (const char* does +// not correctly respond to the apply method). Because the syntax to use this +// is a pain, we have the 'apply' method below to handle the nastiness... +// +template <class Mod> struct applicator { + template <class Opt> static void opt(const Mod &M, Opt &O) { M.apply(O); } +}; + +// Handle const char* as a special case... +template <unsigned n> struct applicator<char[n]> { + template <class Opt> static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } +}; +template <unsigned n> struct applicator<const char[n]> { + template <class Opt> static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } +}; +template <> struct applicator<const char *> { + template <class Opt> static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } +}; + +template <> struct applicator<NumOccurrencesFlag> { + static void opt(NumOccurrencesFlag N, Option &O) { + O.setNumOccurrencesFlag(N); + } +}; +template <> struct applicator<ValueExpected> { + static void opt(ValueExpected VE, Option &O) { O.setValueExpectedFlag(VE); } +}; +template <> struct applicator<OptionHidden> { + static void opt(OptionHidden OH, Option &O) { O.setHiddenFlag(OH); } +}; +template <> struct applicator<FormattingFlags> { + static void opt(FormattingFlags FF, Option &O) { O.setFormattingFlag(FF); } +}; +template <> struct applicator<MiscFlags> { + static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); } +}; + +// apply method - Apply modifiers to an option in a type safe way. +template <class Opt, class Mod, class... Mods> +void apply(Opt *O, const Mod &M, const Mods &... Ms) { + applicator<Mod>::opt(M, *O); + apply(O, Ms...); +} + +template <class Opt, class Mod> void apply(Opt *O, const Mod &M) { + applicator<Mod>::opt(M, *O); +} + +//===----------------------------------------------------------------------===// +// opt_storage class + +// Default storage class definition: external storage. This implementation +// assumes the user will specify a variable to store the data into with the +// cl::location(x) modifier. +// +template <class DataType, bool ExternalStorage, bool isClass> +class opt_storage { + DataType *Location; // Where to store the object... + OptionValue<DataType> Default; + + void check_location() const { + assert(Location && "cl::location(...) not specified for a command " + "line option with external storage, " + "or cl::init specified before cl::location()!!"); + } + +public: + opt_storage() : Location(nullptr) {} + + bool setLocation(Option &O, DataType &L) { + if (Location) + return O.error("cl::location(x) specified more than once!"); + Location = &L; + Default = L; + return false; + } + + template <class T> void setValue(const T &V, bool initial = false) { + check_location(); + *Location = V; + if (initial) + Default = V; + } + + DataType &getValue() { + check_location(); + return *Location; + } + const DataType &getValue() const { + check_location(); + return *Location; + } + + operator DataType() const { return this->getValue(); } + + const OptionValue<DataType> &getDefault() const { return Default; } +}; + +// Define how to hold a class type object, such as a string. Since we can +// inherit from a class, we do so. This makes us exactly compatible with the +// object in all cases that it is used. +// +template <class DataType> +class opt_storage<DataType, false, true> : public DataType { +public: + OptionValue<DataType> Default; + + template <class T> void setValue(const T &V, bool initial = false) { + DataType::operator=(V); + if (initial) + Default = V; + } + + DataType &getValue() { return *this; } + const DataType &getValue() const { return *this; } + + const OptionValue<DataType> &getDefault() const { return Default; } +}; + +// Define a partial specialization to handle things we cannot inherit from. In +// this case, we store an instance through containment, and overload operators +// to get at the value. +// +template <class DataType> class opt_storage<DataType, false, false> { +public: + DataType Value; + OptionValue<DataType> Default; + + // Make sure we initialize the value with the default constructor for the + // type. + opt_storage() : Value(DataType()), Default(DataType()) {} + + template <class T> void setValue(const T &V, bool initial = false) { + Value = V; + if (initial) + Default = V; + } + DataType &getValue() { return Value; } + DataType getValue() const { return Value; } + + const OptionValue<DataType> &getDefault() const { return Default; } + + operator DataType() const { return getValue(); } + + // If the datatype is a pointer, support -> on it. + DataType operator->() const { return Value; } +}; + +//===----------------------------------------------------------------------===// +// opt - A scalar command line option. +// +template <class DataType, bool ExternalStorage = false, + class ParserClass = parser<DataType>> +class opt : public Option, + public opt_storage<DataType, ExternalStorage, + std::is_class<DataType>::value> { + ParserClass Parser; + + bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) override { + typename ParserClass::parser_data_type Val = + typename ParserClass::parser_data_type(); + if (Parser.parse(*this, ArgName, Arg, Val)) + return true; // Parse error! + this->setValue(Val); + this->setPosition(pos); + return false; + } + + enum ValueExpected getValueExpectedFlagDefault() const override { + return Parser.getValueExpectedFlagDefault(); + } + void getExtraOptionNames(SmallVectorImpl<StringRef> &OptionNames) override { + return Parser.getExtraOptionNames(OptionNames); + } + + // Forward printing stuff to the parser... + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } + void printOptionInfo(size_t GlobalWidth) const override { + Parser.printOptionInfo(*this, GlobalWidth); + } + + void printOptionValue(size_t GlobalWidth, bool Force) const override { + if (Force || this->getDefault().compare(this->getValue())) { + cl::printOptionDiff<ParserClass>(*this, Parser, this->getValue(), + this->getDefault(), GlobalWidth); + } + } + + void done() { + addArgument(); + Parser.initialize(); + } + + // Command line options should not be copyable + opt(const opt &) = delete; + opt &operator=(const opt &) = delete; + +public: + // setInitialValue - Used by the cl::init modifier... + void setInitialValue(const DataType &V) { this->setValue(V, true); } + + ParserClass &getParser() { return Parser; } + + template <class T> DataType &operator=(const T &Val) { + this->setValue(Val); + return this->getValue(); + } + + template <class... Mods> + explicit opt(const Mods &... Ms) + : Option(Optional, NotHidden), Parser(*this) { + apply(this, Ms...); + done(); + } +}; + +extern template class opt<unsigned>; +extern template class opt<int>; +extern template class opt<std::string>; +extern template class opt<char>; +extern template class opt<bool>; + +//===----------------------------------------------------------------------===// +// list_storage class + +// Default storage class definition: external storage. This implementation +// assumes the user will specify a variable to store the data into with the +// cl::location(x) modifier. +// +template <class DataType, class StorageClass> class list_storage { + StorageClass *Location; // Where to store the object... + +public: + list_storage() : Location(0) {} + + bool setLocation(Option &O, StorageClass &L) { + if (Location) + return O.error("cl::location(x) specified more than once!"); + Location = &L; + return false; + } + + template <class T> void addValue(const T &V) { + assert(Location != 0 && "cl::location(...) not specified for a command " + "line option with external storage!"); + Location->push_back(V); + } +}; + +// Define how to hold a class type object, such as a string. +// Originally this code inherited from std::vector. In transitioning to a new +// API for command line options we should change this. The new implementation +// of this list_storage specialization implements the minimum subset of the +// std::vector API required for all the current clients. +// +// FIXME: Reduce this API to a more narrow subset of std::vector +// +template <class DataType> class list_storage<DataType, bool> { + std::vector<DataType> Storage; + +public: + typedef typename std::vector<DataType>::iterator iterator; + + iterator begin() { return Storage.begin(); } + iterator end() { return Storage.end(); } + + typedef typename std::vector<DataType>::const_iterator const_iterator; + const_iterator begin() const { return Storage.begin(); } + const_iterator end() const { return Storage.end(); } + + typedef typename std::vector<DataType>::size_type size_type; + size_type size() const { return Storage.size(); } + + bool empty() const { return Storage.empty(); } + + void push_back(const DataType &value) { Storage.push_back(value); } + void push_back(DataType &&value) { Storage.push_back(value); } + + typedef typename std::vector<DataType>::reference reference; + typedef typename std::vector<DataType>::const_reference const_reference; + reference operator[](size_type pos) { return Storage[pos]; } + const_reference operator[](size_type pos) const { return Storage[pos]; } + + iterator erase(const_iterator pos) { return Storage.erase(pos); } + iterator erase(const_iterator first, const_iterator last) { + return Storage.erase(first, last); + } + + iterator erase(iterator pos) { return Storage.erase(pos); } + iterator erase(iterator first, iterator last) { + return Storage.erase(first, last); + } + + iterator insert(const_iterator pos, const DataType &value) { + return Storage.insert(pos, value); + } + iterator insert(const_iterator pos, DataType &&value) { + return Storage.insert(pos, value); + } + + iterator insert(iterator pos, const DataType &value) { + return Storage.insert(pos, value); + } + iterator insert(iterator pos, DataType &&value) { + return Storage.insert(pos, value); + } + + reference front() { return Storage.front(); } + const_reference front() const { return Storage.front(); } + + operator std::vector<DataType>&() { return Storage; } + operator ArrayRef<DataType>() { return Storage; } + std::vector<DataType> *operator&() { return &Storage; } + const std::vector<DataType> *operator&() const { return &Storage; } + + template <class T> void addValue(const T &V) { Storage.push_back(V); } +}; + +//===----------------------------------------------------------------------===// +// list - A list of command line options. +// +template <class DataType, class StorageClass = bool, + class ParserClass = parser<DataType>> +class list : public Option, public list_storage<DataType, StorageClass> { + std::vector<unsigned> Positions; + ParserClass Parser; + + enum ValueExpected getValueExpectedFlagDefault() const override { + return Parser.getValueExpectedFlagDefault(); + } + void getExtraOptionNames(SmallVectorImpl<StringRef> &OptionNames) override { + return Parser.getExtraOptionNames(OptionNames); + } + + bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) override { + typename ParserClass::parser_data_type Val = + typename ParserClass::parser_data_type(); + if (Parser.parse(*this, ArgName, Arg, Val)) + return true; // Parse Error! + list_storage<DataType, StorageClass>::addValue(Val); + setPosition(pos); + Positions.push_back(pos); + return false; + } + + // Forward printing stuff to the parser... + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } + void printOptionInfo(size_t GlobalWidth) const override { + Parser.printOptionInfo(*this, GlobalWidth); + } + + // Unimplemented: list options don't currently store their default value. + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } + + void done() { + addArgument(); + Parser.initialize(); + } + + // Command line options should not be copyable + list(const list &) = delete; + list &operator=(const list &) = delete; + +public: + ParserClass &getParser() { return Parser; } + + unsigned getPosition(unsigned optnum) const { + assert(optnum < this->size() && "Invalid option index"); + return Positions[optnum]; + } + + void setNumAdditionalVals(unsigned n) { Option::setNumAdditionalVals(n); } + + template <class... Mods> + explicit list(const Mods &... Ms) + : Option(ZeroOrMore, NotHidden), Parser(*this) { + apply(this, Ms...); + done(); + } +}; + +// multi_val - Modifier to set the number of additional values. +struct multi_val { + unsigned AdditionalVals; + explicit multi_val(unsigned N) : AdditionalVals(N) {} + + template <typename D, typename S, typename P> + void apply(list<D, S, P> &L) const { + L.setNumAdditionalVals(AdditionalVals); + } +}; + +//===----------------------------------------------------------------------===// +// bits_storage class + +// Default storage class definition: external storage. This implementation +// assumes the user will specify a variable to store the data into with the +// cl::location(x) modifier. +// +template <class DataType, class StorageClass> class bits_storage { + unsigned *Location; // Where to store the bits... + + template <class T> static unsigned Bit(const T &V) { + unsigned BitPos = reinterpret_cast<unsigned>(V); + assert(BitPos < sizeof(unsigned) * CHAR_BIT && + "enum exceeds width of bit vector!"); + return 1 << BitPos; + } + +public: + bits_storage() : Location(nullptr) {} + + bool setLocation(Option &O, unsigned &L) { + if (Location) + return O.error("cl::location(x) specified more than once!"); + Location = &L; + return false; + } + + template <class T> void addValue(const T &V) { + assert(Location != 0 && "cl::location(...) not specified for a command " + "line option with external storage!"); + *Location |= Bit(V); + } + + unsigned getBits() { return *Location; } + + template <class T> bool isSet(const T &V) { + return (*Location & Bit(V)) != 0; + } +}; + +// Define how to hold bits. Since we can inherit from a class, we do so. +// This makes us exactly compatible with the bits in all cases that it is used. +// +template <class DataType> class bits_storage<DataType, bool> { + unsigned Bits; // Where to store the bits... + + template <class T> static unsigned Bit(const T &V) { + unsigned BitPos = (unsigned)V; + assert(BitPos < sizeof(unsigned) * CHAR_BIT && + "enum exceeds width of bit vector!"); + return 1 << BitPos; + } + +public: + template <class T> void addValue(const T &V) { Bits |= Bit(V); } + + unsigned getBits() { return Bits; } + + template <class T> bool isSet(const T &V) { return (Bits & Bit(V)) != 0; } +}; + +//===----------------------------------------------------------------------===// +// bits - A bit vector of command options. +// +template <class DataType, class Storage = bool, + class ParserClass = parser<DataType>> +class bits : public Option, public bits_storage<DataType, Storage> { + std::vector<unsigned> Positions; + ParserClass Parser; + + enum ValueExpected getValueExpectedFlagDefault() const override { + return Parser.getValueExpectedFlagDefault(); + } + void getExtraOptionNames(SmallVectorImpl<StringRef> &OptionNames) override { + return Parser.getExtraOptionNames(OptionNames); + } + + bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) override { + typename ParserClass::parser_data_type Val = + typename ParserClass::parser_data_type(); + if (Parser.parse(*this, ArgName, Arg, Val)) + return true; // Parse Error! + this->addValue(Val); + setPosition(pos); + Positions.push_back(pos); + return false; + } + + // Forward printing stuff to the parser... + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } + void printOptionInfo(size_t GlobalWidth) const override { + Parser.printOptionInfo(*this, GlobalWidth); + } + + // Unimplemented: bits options don't currently store their default values. + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } + + void done() { + addArgument(); + Parser.initialize(); + } + + // Command line options should not be copyable + bits(const bits &) = delete; + bits &operator=(const bits &) = delete; + +public: + ParserClass &getParser() { return Parser; } + + unsigned getPosition(unsigned optnum) const { + assert(optnum < this->size() && "Invalid option index"); + return Positions[optnum]; + } + + template <class... Mods> + explicit bits(const Mods &... Ms) + : Option(ZeroOrMore, NotHidden), Parser(*this) { + apply(this, Ms...); + done(); + } +}; + +//===----------------------------------------------------------------------===// +// Aliased command line option (alias this name to a preexisting name) +// + +class alias : public Option { + Option *AliasFor; + bool handleOccurrence(unsigned pos, StringRef /*ArgName*/, + StringRef Arg) override { + return AliasFor->handleOccurrence(pos, AliasFor->ArgStr, Arg); + } + bool addOccurrence(unsigned pos, StringRef /*ArgName*/, StringRef Value, + bool MultiArg = false) override { + return AliasFor->addOccurrence(pos, AliasFor->ArgStr, Value, MultiArg); + } + // Handle printing stuff... + size_t getOptionWidth() const override; + void printOptionInfo(size_t GlobalWidth) const override; + + // Aliases do not need to print their values. + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } + + ValueExpected getValueExpectedFlagDefault() const override { + return AliasFor->getValueExpectedFlag(); + } + + void done() { + if (!hasArgStr()) + error("cl::alias must have argument name specified!"); + if (!AliasFor) + error("cl::alias must have an cl::aliasopt(option) specified!"); + Subs = AliasFor->Subs; + addArgument(); + } + + // Command line options should not be copyable + alias(const alias &) = delete; + alias &operator=(const alias &) = delete; + +public: + void setAliasFor(Option &O) { + if (AliasFor) + error("cl::alias must only have one cl::aliasopt(...) specified!"); + AliasFor = &O; + } + + template <class... Mods> + explicit alias(const Mods &... Ms) + : Option(Optional, Hidden), AliasFor(nullptr) { + apply(this, Ms...); + done(); + } +}; + +// aliasfor - Modifier to set the option an alias aliases. +struct aliasopt { + Option &Opt; + explicit aliasopt(Option &O) : Opt(O) {} + void apply(alias &A) const { A.setAliasFor(Opt); } +}; + +// extrahelp - provide additional help at the end of the normal help +// output. All occurrences of cl::extrahelp will be accumulated and +// printed to stderr at the end of the regular help, just before +// exit is called. +struct extrahelp { + const char *morehelp; + explicit extrahelp(const char *help); +}; + +void PrintVersionMessage(); + +/// This function just prints the help message, exactly the same way as if the +/// -help or -help-hidden option had been given on the command line. +/// +/// NOTE: THIS FUNCTION TERMINATES THE PROGRAM! +/// +/// \param Hidden if true will print hidden options +/// \param Categorized if true print options in categories +void PrintHelpMessage(bool Hidden = false, bool Categorized = false); + +//===----------------------------------------------------------------------===// +// Public interface for accessing registered options. +// + +/// \brief Use this to get a StringMap to all registered named options +/// (e.g. -help). Note \p Map Should be an empty StringMap. +/// +/// \return A reference to the StringMap used by the cl APIs to parse options. +/// +/// Access to unnamed arguments (i.e. positional) are not provided because +/// it is expected that the client already has access to these. +/// +/// Typical usage: +/// \code +/// main(int argc,char* argv[]) { +/// StringMap<llvm::cl::Option*> &opts = llvm::cl::getRegisteredOptions(); +/// assert(opts.count("help") == 1) +/// opts["help"]->setDescription("Show alphabetical help information") +/// // More code +/// llvm::cl::ParseCommandLineOptions(argc,argv); +/// //More code +/// } +/// \endcode +/// +/// This interface is useful for modifying options in libraries that are out of +/// the control of the client. The options should be modified before calling +/// llvm::cl::ParseCommandLineOptions(). +/// +/// Hopefully this API can be depricated soon. Any situation where options need +/// to be modified by tools or libraries should be handled by sane APIs rather +/// than just handing around a global list. +StringMap<Option *> &getRegisteredOptions(SubCommand &Sub = *TopLevelSubCommand); + +//===----------------------------------------------------------------------===// +// Standalone command line processing utilities. +// + +/// \brief Tokenizes a command line that can contain escapes and quotes. +// +/// The quoting rules match those used by GCC and other tools that use +/// libiberty's buildargv() or expandargv() utilities, and do not match bash. +/// They differ from buildargv() on treatment of backslashes that do not escape +/// a special character to make it possible to accept most Windows file paths. +/// +/// \param [in] Source The string to be split on whitespace with quotes. +/// \param [in] Saver Delegates back to the caller for saving parsed strings. +/// \param [in] MarkEOLs true if tokenizing a response file and you want end of +/// lines and end of the response file to be marked with a nullptr string. +/// \param [out] NewArgv All parsed strings are appended to NewArgv. +void TokenizeGNUCommandLine(StringRef Source, StringSaver &Saver, + SmallVectorImpl<const char *> &NewArgv, + bool MarkEOLs = false); + +/// \brief Tokenizes a Windows command line which may contain quotes and escaped +/// quotes. +/// +/// See MSDN docs for CommandLineToArgvW for information on the quoting rules. +/// http://msdn.microsoft.com/en-us/library/windows/desktop/17w5ykft(v=vs.85).aspx +/// +/// \param [in] Source The string to be split on whitespace with quotes. +/// \param [in] Saver Delegates back to the caller for saving parsed strings. +/// \param [in] MarkEOLs true if tokenizing a response file and you want end of +/// lines and end of the response file to be marked with a nullptr string. +/// \param [out] NewArgv All parsed strings are appended to NewArgv. +void TokenizeWindowsCommandLine(StringRef Source, StringSaver &Saver, + SmallVectorImpl<const char *> &NewArgv, + bool MarkEOLs = false); + +/// \brief String tokenization function type. Should be compatible with either +/// Windows or Unix command line tokenizers. +typedef void (*TokenizerCallback)(StringRef Source, StringSaver &Saver, + SmallVectorImpl<const char *> &NewArgv, + bool MarkEOLs); + +/// \brief Expand response files on a command line recursively using the given +/// StringSaver and tokenization strategy. Argv should contain the command line +/// before expansion and will be modified in place. If requested, Argv will +/// also be populated with nullptrs indicating where each response file line +/// ends, which is useful for the "/link" argument that needs to consume all +/// remaining arguments only until the next end of line, when in a response +/// file. +/// +/// \param [in] Saver Delegates back to the caller for saving parsed strings. +/// \param [in] Tokenizer Tokenization strategy. Typically Unix or Windows. +/// \param [in,out] Argv Command line into which to expand response files. +/// \param [in] MarkEOLs Mark end of lines and the end of the response file +/// with nullptrs in the Argv vector. +/// \return true if all @files were expanded successfully or there were none. +bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, + SmallVectorImpl<const char *> &Argv, + bool MarkEOLs = false); + +/// \brief Mark all options not part of this category as cl::ReallyHidden. +/// +/// \param Category the category of options to keep displaying +/// +/// Some tools (like clang-format) like to be able to hide all options that are +/// not specific to the tool. This function allows a tool to specify a single +/// option category to display in the -help output. +void HideUnrelatedOptions(cl::OptionCategory &Category, + SubCommand &Sub = *TopLevelSubCommand); + +/// \brief Mark all options not part of the categories as cl::ReallyHidden. +/// +/// \param Categories the categories of options to keep displaying. +/// +/// Some tools (like clang-format) like to be able to hide all options that are +/// not specific to the tool. This function allows a tool to specify a single +/// option category to display in the -help output. +void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories, + SubCommand &Sub = *TopLevelSubCommand); + +/// \brief Reset all command line options to a state that looks as if they have +/// never appeared on the command line. This is useful for being able to parse +/// a command line multiple times (especially useful for writing tests). +void ResetAllOptionOccurrences(); + +/// \brief Reset the command line parser back to its initial state. This +/// removes +/// all options, categories, and subcommands and returns the parser to a state +/// where no options are supported. +void ResetCommandLineParser(); + +} // End namespace cl + +} // End namespace llvm + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Compiler.h b/third_party/llvm-subzero/include/llvm/Support/Compiler.h new file mode 100644 index 0000000..3cf9910 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Compiler.h
@@ -0,0 +1,515 @@ +//===-- llvm/Support/Compiler.h - Compiler abstraction support --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines several macros, based on the current compiler. This allows +// use of compiler-specific features in a way that remains portable. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_COMPILER_H +#define LLVM_SUPPORT_COMPILER_H + +#include "llvm/Config/llvm-config.h" + +#if defined(_MSC_VER) +#include <sal.h> +#endif + +#ifndef __has_feature +# define __has_feature(x) 0 +#endif + +#ifndef __has_extension +# define __has_extension(x) 0 +#endif + +#ifndef __has_attribute +# define __has_attribute(x) 0 +#endif + +#ifndef __has_cpp_attribute +# define __has_cpp_attribute(x) 0 +#endif + +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + +/// \macro LLVM_GNUC_PREREQ +/// \brief Extend the default __GNUC_PREREQ even if glibc's features.h isn't +/// available. +#ifndef LLVM_GNUC_PREREQ +# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LLVM_GNUC_PREREQ(maj, min, patch) \ + ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \ + ((maj) << 20) + ((min) << 10) + (patch)) +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) +# define LLVM_GNUC_PREREQ(maj, min, patch) \ + ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) +# else +# define LLVM_GNUC_PREREQ(maj, min, patch) 0 +# endif +#endif + +/// \macro LLVM_MSC_PREREQ +/// \brief Is the compiler MSVC of at least the specified version? +/// The common \param version values to check for are: +/// * 1800: Microsoft Visual Studio 2013 / 12.0 +/// * 1900: Microsoft Visual Studio 2015 / 14.0 +#ifdef _MSC_VER +#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version)) + +// We require at least MSVC 2013. +#if !LLVM_MSC_PREREQ(1800) +#error LLVM requires at least MSVC 2013. +#endif + +#else +#define LLVM_MSC_PREREQ(version) 0 +#endif + +#if !defined(_MSC_VER) || defined(__clang__) || LLVM_MSC_PREREQ(1900) +#define LLVM_NOEXCEPT noexcept +#else +#define LLVM_NOEXCEPT throw() +#endif + +/// \brief Does the compiler support ref-qualifiers for *this? +/// +/// Sadly, this is separate from just rvalue reference support because GCC +/// and MSVC implemented this later than everything else. +#if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1) +#define LLVM_HAS_RVALUE_REFERENCE_THIS 1 +#else +#define LLVM_HAS_RVALUE_REFERENCE_THIS 0 +#endif + +/// Expands to '&' if ref-qualifiers for *this are supported. +/// +/// This can be used to provide lvalue/rvalue overrides of member functions. +/// The rvalue override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS +#if LLVM_HAS_RVALUE_REFERENCE_THIS +#define LLVM_LVALUE_FUNCTION & +#else +#define LLVM_LVALUE_FUNCTION +#endif + +#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) || LLVM_MSC_PREREQ(1900) +# define LLVM_CONSTEXPR constexpr +#else +# define LLVM_CONSTEXPR +#endif + +/// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked +/// into a shared library, then the class should be private to the library and +/// not accessible from outside it. Can also be used to mark variables and +/// functions, making them private to any shared library they are linked into. +/// On PE/COFF targets, library visibility is the default, so this isn't needed. +#if (__has_attribute(visibility) || LLVM_GNUC_PREREQ(4, 0, 0)) && \ + !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32) +#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden"))) +#else +#define LLVM_LIBRARY_VISIBILITY +#endif + +#if __has_attribute(sentinel) || LLVM_GNUC_PREREQ(3, 0, 0) +#define LLVM_END_WITH_NULL __attribute__((sentinel)) +#else +#define LLVM_END_WITH_NULL +#endif + +#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0) +#define LLVM_ATTRIBUTE_USED __attribute__((__used__)) +#else +#define LLVM_ATTRIBUTE_USED +#endif + +#if __has_attribute(warn_unused_result) || LLVM_GNUC_PREREQ(3, 4, 0) +#define LLVM_ATTRIBUTE_UNUSED_RESULT __attribute__((__warn_unused_result__)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_UNUSED_RESULT _Check_return_ +#else +#define LLVM_ATTRIBUTE_UNUSED_RESULT +#endif + +// Some compilers warn about unused functions. When a function is sometimes +// used or not depending on build settings (e.g. a function only called from +// within "assert"), this attribute can be used to suppress such warnings. +// +// However, it shouldn't be used for unused *variables*, as those have a much +// more portable solution: +// (void)unused_var_name; +// Prefer cast-to-void wherever it is sufficient. +#if __has_attribute(unused) || LLVM_GNUC_PREREQ(3, 1, 0) +#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__)) +#else +#define LLVM_ATTRIBUTE_UNUSED +#endif + +// FIXME: Provide this for PE/COFF targets. +#if (__has_attribute(weak) || LLVM_GNUC_PREREQ(4, 0, 0)) && \ + (!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32)) +#define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__)) +#else +#define LLVM_ATTRIBUTE_WEAK +#endif + +// Prior to clang 3.2, clang did not accept any spelling of +// __has_attribute(const), so assume it is supported. +#if defined(__clang__) || defined(__GNUC__) +// aka 'CONST' but following LLVM Conventions. +#define LLVM_READNONE __attribute__((__const__)) +#else +#define LLVM_READNONE +#endif + +#if __has_attribute(pure) || defined(__GNUC__) +// aka 'PURE' but following LLVM Conventions. +#define LLVM_READONLY __attribute__((__pure__)) +#else +#define LLVM_READONLY +#endif + +#if __has_builtin(__builtin_expect) || LLVM_GNUC_PREREQ(4, 0, 0) +#define LLVM_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true) +#define LLVM_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false) +#else +#define LLVM_LIKELY(EXPR) (EXPR) +#define LLVM_UNLIKELY(EXPR) (EXPR) +#endif + +/// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, +/// mark a method "not for inlining". +#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0) +#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline) +#else +#define LLVM_ATTRIBUTE_NOINLINE +#endif + +/// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do +/// so, mark a method "always inline" because it is performance sensitive. GCC +/// 3.4 supported this but is buggy in various cases and produces unimplemented +/// errors, just use it in GCC 4.0 and later. +#if __has_attribute(always_inline) || LLVM_GNUC_PREREQ(4, 0, 0) +#define LLVM_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline +#else +#define LLVM_ATTRIBUTE_ALWAYS_INLINE +#endif + +#ifdef __GNUC__ +#define LLVM_ATTRIBUTE_NORETURN __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_NORETURN __declspec(noreturn) +#else +#define LLVM_ATTRIBUTE_NORETURN +#endif + +#if __has_attribute(returns_nonnull) || LLVM_GNUC_PREREQ(4, 9, 0) +#define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_RETURNS_NONNULL _Ret_notnull_ +#else +#define LLVM_ATTRIBUTE_RETURNS_NONNULL +#endif + +/// \macro LLVM_ATTRIBUTE_RETURNS_NOALIAS Used to mark a function as returning a +/// pointer that does not alias any other valid pointer. +#ifdef __GNUC__ +#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict) +#else +#define LLVM_ATTRIBUTE_RETURNS_NOALIAS +#endif + +/// LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements. +#if __cplusplus > 201402L && __has_cpp_attribute(fallthrough) +#define LLVM_FALLTHROUGH [[fallthrough]] +#elif !__cplusplus +// Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious +// error when __has_cpp_attribute is given a scoped attribute in C mode. +#define LLVM_FALLTHROUGH +#elif __has_cpp_attribute(clang::fallthrough) +#define LLVM_FALLTHROUGH [[clang::fallthrough]] +#else +#define LLVM_FALLTHROUGH +#endif + +/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress +/// pedantic diagnostics. +#ifdef __GNUC__ +#define LLVM_EXTENSION __extension__ +#else +#define LLVM_EXTENSION +#endif + +// LLVM_ATTRIBUTE_DEPRECATED(decl, "message") +#if __has_feature(attribute_deprecated_with_message) +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + decl __attribute__((deprecated(message))) +#elif defined(__GNUC__) +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + decl __attribute__((deprecated)) +#elif defined(_MSC_VER) +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + __declspec(deprecated(message)) decl +#else +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + decl +#endif + +/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands +/// to an expression which states that it is undefined behavior for the +/// compiler to reach this point. Otherwise is not defined. +#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0) +# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable() +#elif defined(_MSC_VER) +# define LLVM_BUILTIN_UNREACHABLE __assume(false) +#endif + +/// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression +/// which causes the program to exit abnormally. +#if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0) +# define LLVM_BUILTIN_TRAP __builtin_trap() +#elif defined(_MSC_VER) +// The __debugbreak intrinsic is supported by MSVC, does not require forward +// declarations involving platform-specific typedefs (unlike RaiseException), +// results in a call to vectored exception handlers, and encodes to a short +// instruction that still causes the trapping behavior we want. +# define LLVM_BUILTIN_TRAP __debugbreak() +#else +# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0 +#endif + +/// LLVM_BUILTIN_DEBUGTRAP - On compilers which support it, expands to +/// an expression which causes the program to break while running +/// under a debugger. +#if __has_builtin(__builtin_debugtrap) +# define LLVM_BUILTIN_DEBUGTRAP __builtin_debugtrap() +#elif defined(_MSC_VER) +// The __debugbreak intrinsic is supported by MSVC and breaks while +// running under the debugger, and also supports invoking a debugger +// when the OS is configured appropriately. +# define LLVM_BUILTIN_DEBUGTRAP __debugbreak() +#else +// Just continue execution when built with compilers that have no +// support. This is a debugging aid and not intended to force the +// program to abort if encountered. +# define LLVM_BUILTIN_DEBUGTRAP +#endif + +/// \macro LLVM_ASSUME_ALIGNED +/// \brief Returns a pointer with an assumed alignment. +#if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0) +# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a) +#elif defined(LLVM_BUILTIN_UNREACHABLE) +// As of today, clang does not support __builtin_assume_aligned. +# define LLVM_ASSUME_ALIGNED(p, a) \ + (((uintptr_t(p) % (a)) == 0) ? (p) : (LLVM_BUILTIN_UNREACHABLE, (p))) +#else +# define LLVM_ASSUME_ALIGNED(p, a) (p) +#endif + +/// \macro LLVM_ALIGNAS +/// \brief Used to specify a minimum alignment for a structure or variable. The +/// alignment must be a constant integer. Use LLVM_PTR_SIZE to compute +/// alignments in terms of the size of a pointer. +/// +/// Note that __declspec(align) has special quirks, it's not legal to pass a +/// structure with __declspec(align) as a formal parameter. +#ifdef _MSC_VER +# define LLVM_ALIGNAS(x) __declspec(align(x)) +#elif __GNUC__ && !__has_feature(cxx_alignas) && !LLVM_GNUC_PREREQ(4, 8, 0) +# define LLVM_ALIGNAS(x) __attribute__((aligned(x))) +#else +# define LLVM_ALIGNAS(x) alignas(x) +#endif + +/// \macro LLVM_PACKED +/// \brief Used to specify a packed structure. +/// LLVM_PACKED( +/// struct A { +/// int i; +/// int j; +/// int k; +/// long long l; +/// }); +/// +/// LLVM_PACKED_START +/// struct B { +/// int i; +/// int j; +/// int k; +/// long long l; +/// }; +/// LLVM_PACKED_END +#ifdef _MSC_VER +# define LLVM_PACKED(d) __pragma(pack(push, 1)) d __pragma(pack(pop)) +# define LLVM_PACKED_START __pragma(pack(push, 1)) +# define LLVM_PACKED_END __pragma(pack(pop)) +#else +# define LLVM_PACKED(d) d __attribute__((packed)) +# define LLVM_PACKED_START _Pragma("pack(push, 1)") +# define LLVM_PACKED_END _Pragma("pack(pop)") +#endif + +/// \macro LLVM_PTR_SIZE +/// \brief A constant integer equivalent to the value of sizeof(void*). +/// Generally used in combination with LLVM_ALIGNAS or when doing computation in +/// the preprocessor. +#ifdef __SIZEOF_POINTER__ +# define LLVM_PTR_SIZE __SIZEOF_POINTER__ +#elif defined(_WIN64) +# define LLVM_PTR_SIZE 8 +#elif defined(_WIN32) +# define LLVM_PTR_SIZE 4 +#elif defined(_MSC_VER) +# error "could not determine LLVM_PTR_SIZE as a constant int for MSVC" +#else +# define LLVM_PTR_SIZE sizeof(void *) +#endif + +/// \macro LLVM_FUNCTION_NAME +/// \brief Expands to __func__ on compilers which support it. Otherwise, +/// expands to a compiler-dependent replacement. +#if defined(_MSC_VER) +# define LLVM_FUNCTION_NAME __FUNCTION__ +#else +# define LLVM_FUNCTION_NAME __func__ +#endif + +/// \macro LLVM_MEMORY_SANITIZER_BUILD +/// \brief Whether LLVM itself is built with MemorySanitizer instrumentation. +#if __has_feature(memory_sanitizer) +# define LLVM_MEMORY_SANITIZER_BUILD 1 +# include <sanitizer/msan_interface.h> +#else +# define LLVM_MEMORY_SANITIZER_BUILD 0 +# define __msan_allocated_memory(p, size) +# define __msan_unpoison(p, size) +#endif + +/// \macro LLVM_ADDRESS_SANITIZER_BUILD +/// \brief Whether LLVM itself is built with AddressSanitizer instrumentation. +#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) +# define LLVM_ADDRESS_SANITIZER_BUILD 1 +# include <sanitizer/asan_interface.h> +#else +# define LLVM_ADDRESS_SANITIZER_BUILD 0 +# define __asan_poison_memory_region(p, size) +# define __asan_unpoison_memory_region(p, size) +#endif + +/// \macro LLVM_THREAD_SANITIZER_BUILD +/// \brief Whether LLVM itself is built with ThreadSanitizer instrumentation. +#if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__) +# define LLVM_THREAD_SANITIZER_BUILD 1 +#else +# define LLVM_THREAD_SANITIZER_BUILD 0 +#endif + +#if LLVM_THREAD_SANITIZER_BUILD +// Thread Sanitizer is a tool that finds races in code. +// See http://code.google.com/p/data-race-test/wiki/DynamicAnnotations . +// tsan detects these exact functions by name. +#ifdef __cplusplus +extern "C" { +#endif +void AnnotateHappensAfter(const char *file, int line, const volatile void *cv); +void AnnotateHappensBefore(const char *file, int line, const volatile void *cv); +void AnnotateIgnoreWritesBegin(const char *file, int line); +void AnnotateIgnoreWritesEnd(const char *file, int line); +#ifdef __cplusplus +} +#endif + +// This marker is used to define a happens-before arc. The race detector will +// infer an arc from the begin to the end when they share the same pointer +// argument. +# define TsanHappensBefore(cv) AnnotateHappensBefore(__FILE__, __LINE__, cv) + +// This marker defines the destination of a happens-before arc. +# define TsanHappensAfter(cv) AnnotateHappensAfter(__FILE__, __LINE__, cv) + +// Ignore any races on writes between here and the next TsanIgnoreWritesEnd. +# define TsanIgnoreWritesBegin() AnnotateIgnoreWritesBegin(__FILE__, __LINE__) + +// Resume checking for racy writes. +# define TsanIgnoreWritesEnd() AnnotateIgnoreWritesEnd(__FILE__, __LINE__) +#else +# define TsanHappensBefore(cv) +# define TsanHappensAfter(cv) +# define TsanIgnoreWritesBegin() +# define TsanIgnoreWritesEnd() +#endif + +/// \macro LLVM_NO_SANITIZE +/// \brief Disable a particular sanitizer for a function. +#if __has_attribute(no_sanitize) +#define LLVM_NO_SANITIZE(KIND) __attribute__((no_sanitize(KIND))) +#else +#define LLVM_NO_SANITIZE(KIND) +#endif + +/// \brief Mark debug helper function definitions like dump() that should not be +/// stripped from debug builds. +// FIXME: Move this to a private config.h as it's not usable in public headers. +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED +#else +#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE +#endif + +/// \macro LLVM_PRETTY_FUNCTION +/// \brief Gets a user-friendly looking function signature for the current scope +/// using the best available method on each platform. The exact format of the +/// resulting string is implementation specific and non-portable, so this should +/// only be used, for example, for logging or diagnostics. +#if defined(_MSC_VER) +#define LLVM_PRETTY_FUNCTION __FUNCSIG__ +#elif defined(__GNUC__) || defined(__clang__) +#define LLVM_PRETTY_FUNCTION __PRETTY_FUNCTION__ +#else +#define LLVM_PRETTY_FUNCTION __func__ +#endif + +/// \macro LLVM_THREAD_LOCAL +/// \brief A thread-local storage specifier which can be used with globals, +/// extern globals, and static globals. +/// +/// This is essentially an extremely restricted analog to C++11's thread_local +/// support, and uses that when available. However, it falls back on +/// platform-specific or vendor-provided extensions when necessary. These +/// extensions don't support many of the C++11 thread_local's features. You +/// should only use this for PODs that you can statically initialize to +/// some constant value. In almost all circumstances this is most appropriate +/// for use with a pointer, integer, or small aggregation of pointers and +/// integers. +#if LLVM_ENABLE_THREADS +#if __has_feature(cxx_thread_local) +#define LLVM_THREAD_LOCAL thread_local +#elif defined(_MSC_VER) +// MSVC supports this with a __declspec. +#define LLVM_THREAD_LOCAL __declspec(thread) +#else +// Clang, GCC, and other compatible compilers used __thread prior to C++11 and +// we only need the restricted functionality that provides. +#define LLVM_THREAD_LOCAL __thread +#endif +#else // !LLVM_ENABLE_THREADS +// If threading is disabled entirely, this compiles to nothing and you get +// a normal global variable. +#define LLVM_THREAD_LOCAL +#endif + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/ConvertUTF.h b/third_party/llvm-subzero/include/llvm/Support/ConvertUTF.h new file mode 100644 index 0000000..5de5774 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ConvertUTF.h
@@ -0,0 +1,299 @@ +/*===--- ConvertUTF.h - Universal Character Names conversions ---------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *==------------------------------------------------------------------------==*/ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Header file. + + Several funtions are included here, forming a complete set of + conversions between the three formats. UTF-7 is not included + here, but is handled in a separate source file. + + Each of these routines takes pointers to input buffers and output + buffers. The input buffers are const. + + Each routine converts the text between *sourceStart and sourceEnd, + putting the result into the buffer between *targetStart and + targetEnd. Note: the end pointers are *after* the last item: e.g. + *(sourceEnd - 1) is the last item. + + The return result indicates whether the conversion was successful, + and if not, whether the problem was in the source or target buffers. + (Only the first encountered problem is indicated.) + + After the conversion, *sourceStart and *targetStart are both + updated to point to the end of last text successfully converted in + the respective buffers. + + Input parameters: + sourceStart - pointer to a pointer to the source buffer. + The contents of this are modified on return so that + it points at the next thing to be converted. + targetStart - similarly, pointer to pointer to the target buffer. + sourceEnd, targetEnd - respectively pointers to the ends of the + two buffers, for overflow checking only. + + These conversion functions take a ConversionFlags argument. When this + flag is set to strict, both irregular sequences and isolated surrogates + will cause an error. When the flag is set to lenient, both irregular + sequences and isolated surrogates are converted. + + Whether the flag is strict or lenient, all illegal sequences will cause + an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>, + or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code + must check for illegal sequences. + + When the flag is set to lenient, characters over 0x10FFFF are converted + to the replacement character; otherwise (when the flag is set to strict) + they constitute an error. + + Output parameters: + The value "sourceIllegal" is returned from some routines if the input + sequence is malformed. When "sourceIllegal" is returned, the source + value will point to the illegal value that caused the problem. E.g., + in UTF-8 when a sequence is malformed, it points to the start of the + malformed sequence. + + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Fixes & updates, Sept 2001. + +------------------------------------------------------------------------ */ + +#ifndef LLVM_SUPPORT_CONVERTUTF_H +#define LLVM_SUPPORT_CONVERTUTF_H + +/* --------------------------------------------------------------------- + The following 4 definitions are compiler-specific. + The C standard does not guarantee that wchar_t has at least + 16 bits, so wchar_t is no less portable than unsigned short! + All should be unsigned values to avoid sign extension during + bit mask & shift operations. +------------------------------------------------------------------------ */ + +typedef unsigned int UTF32; /* at least 32 bits */ +typedef unsigned short UTF16; /* at least 16 bits */ +typedef unsigned char UTF8; /* typically 8 bits */ +typedef unsigned char Boolean; /* 0 or 1 */ + +/* Some fundamental constants */ +#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD +#define UNI_MAX_BMP (UTF32)0x0000FFFF +#define UNI_MAX_UTF16 (UTF32)0x0010FFFF +#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF +#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF + +#define UNI_MAX_UTF8_BYTES_PER_CODE_POINT 4 + +#define UNI_UTF16_BYTE_ORDER_MARK_NATIVE 0xFEFF +#define UNI_UTF16_BYTE_ORDER_MARK_SWAPPED 0xFFFE + +typedef enum { + conversionOK, /* conversion successful */ + sourceExhausted, /* partial character in source, but hit end */ + targetExhausted, /* insuff. room in target for conversion */ + sourceIllegal /* source sequence is illegal/malformed */ +} ConversionResult; + +typedef enum { + strictConversion = 0, + lenientConversion +} ConversionFlags; + +/* This is for C++ and does no harm in C */ +#ifdef __cplusplus +extern "C" { +#endif + +ConversionResult ConvertUTF8toUTF16 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +/** + * Convert a partial UTF8 sequence to UTF32. If the sequence ends in an + * incomplete code unit sequence, returns \c sourceExhausted. + */ +ConversionResult ConvertUTF8toUTF32Partial( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +/** + * Convert a partial UTF8 sequence to UTF32. If the sequence ends in an + * incomplete code unit sequence, returns \c sourceIllegal. + */ +ConversionResult ConvertUTF8toUTF32( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF8 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF8 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF32 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF16 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); + +Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd); + +unsigned getNumBytesForUTF8(UTF8 firstByte); + +#ifdef __cplusplus +} + +/*************************************************************************/ +/* Below are LLVM-specific wrappers of the functions above. */ + +#include <string> +#include <cstddef> + +namespace llvm { +template <typename T> class ArrayRef; +template <typename T> class SmallVectorImpl; +class StringRef; + +/** + * Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on + * WideCharWidth. The converted data is written to ResultPtr, which needs to + * point to at least WideCharWidth * (Source.Size() + 1) bytes. On success, + * ResultPtr will point one after the end of the copied string. On failure, + * ResultPtr will not be changed, and ErrorPtr will be set to the location of + * the first character which could not be converted. + * \return true on success. + */ +bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source, + char *&ResultPtr, const UTF8 *&ErrorPtr); + +/** +* Converts a UTF-8 StringRef to a std::wstring. +* \return true on success. +*/ +bool ConvertUTF8toWide(llvm::StringRef Source, std::wstring &Result); + +/** +* Converts a UTF-8 C-string to a std::wstring. +* \return true on success. +*/ +bool ConvertUTF8toWide(const char *Source, std::wstring &Result); + +/** +* Converts a std::wstring to a UTF-8 encoded std::string. +* \return true on success. +*/ +bool convertWideToUTF8(const std::wstring &Source, std::string &Result); + + +/** + * Convert an Unicode code point to UTF8 sequence. + * + * \param Source a Unicode code point. + * \param [in,out] ResultPtr pointer to the output buffer, needs to be at least + * \c UNI_MAX_UTF8_BYTES_PER_CODE_POINT bytes. On success \c ResultPtr is + * updated one past end of the converted sequence. + * + * \returns true on success. + */ +bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr); + +/** + * Convert the first UTF8 sequence in the given source buffer to a UTF32 + * code point. + * + * \param [in,out] source A pointer to the source buffer. If the conversion + * succeeds, this pointer will be updated to point to the byte just past the + * end of the converted sequence. + * \param sourceEnd A pointer just past the end of the source buffer. + * \param [out] target The converted code + * \param flags Whether the conversion is strict or lenient. + * + * \returns conversionOK on success + * + * \sa ConvertUTF8toUTF32 + */ +static inline ConversionResult convertUTF8Sequence(const UTF8 **source, + const UTF8 *sourceEnd, + UTF32 *target, + ConversionFlags flags) { + if (*source == sourceEnd) + return sourceExhausted; + unsigned size = getNumBytesForUTF8(**source); + if ((ptrdiff_t)size > sourceEnd - *source) + return sourceExhausted; + return ConvertUTF8toUTF32(source, *source + size, &target, target + 1, flags); +} + +/** + * Returns true if a blob of text starts with a UTF-16 big or little endian byte + * order mark. + */ +bool hasUTF16ByteOrderMark(ArrayRef<char> SrcBytes); + +/** + * Converts a stream of raw bytes assumed to be UTF16 into a UTF8 std::string. + * + * \param [in] SrcBytes A buffer of what is assumed to be UTF-16 encoded text. + * \param [out] Out Converted UTF-8 is stored here on success. + * \returns true on success + */ +bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out); + +/** +* Converts a UTF16 string into a UTF8 std::string. +* +* \param [in] Src A buffer of UTF-16 encoded text. +* \param [out] Out Converted UTF-8 is stored here on success. +* \returns true on success +*/ +bool convertUTF16ToUTF8String(ArrayRef<UTF16> Src, std::string &Out); + +/** + * Converts a UTF-8 string into a UTF-16 string with native endianness. + * + * \returns true on success + */ +bool convertUTF8ToUTF16String(StringRef SrcUTF8, + SmallVectorImpl<UTF16> &DstUTF16); + +} /* end namespace llvm */ + +#endif + +/* --------------------------------------------------------------------- */ + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/DataStream.h b/third_party/llvm-subzero/include/llvm/Support/DataStream.h new file mode 100644 index 0000000..a544316 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/DataStream.h
@@ -0,0 +1,38 @@ +//===---- llvm/Support/DataStream.h - Lazy bitcode streaming ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines DataStreamer, which fetches bytes of data from +// a stream source. It provides support for streaming (lazy reading) of +// data, e.g. bitcode +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_SUPPORT_DATASTREAM_H +#define LLVM_SUPPORT_DATASTREAM_H + +#include <memory> +#include <string> + +namespace llvm { + +class DataStreamer { +public: + /// Fetch bytes [start-end) from the stream, and write them to the + /// buffer pointed to by buf. Returns the number of bytes actually written. + virtual size_t GetBytes(unsigned char *buf, size_t len) = 0; + + virtual ~DataStreamer(); +}; + +std::unique_ptr<DataStreamer> getDataFileStreamer(const std::string &Filename, + std::string *Err); +} + +#endif // LLVM_SUPPORT_DATASTREAM_H_
diff --git a/third_party/llvm-subzero/include/llvm/Support/DataTypes.h b/third_party/llvm-subzero/include/llvm/Support/DataTypes.h new file mode 100644 index 0000000..329c819 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/DataTypes.h
@@ -0,0 +1,213 @@ +/*===-- include/Support/DataTypes.h - Define fixed size types -----*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file contains definitions to figure out the size of _HOST_ data types.*| +|* This file is important because different host OS's define different macros,*| +|* which makes portability tough. This file exports the following *| +|* definitions: *| +|* *| +|* [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types*| +|* [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values. *| +|* *| +|* No library is required when using these functions. *| +|* *| +|*===----------------------------------------------------------------------===*/ + +/* Please leave this file C-compatible. */ + +/* Please keep this file in sync with DataTypes.h.in */ + +#ifndef SUPPORT_DATATYPES_H +#define SUPPORT_DATATYPES_H + +#define HAVE_SYS_TYPES_H 1 +/* #undef HAVE_INTTYPES_H */ +#define HAVE_STDINT_H 1 +#define HAVE_UINT64_T 1 +/* #undef HAVE_U_INT64_T */ + +#ifdef __cplusplus +#include <cmath> +#else +#include <math.h> +#endif + +#ifndef _MSC_VER + +/* Note that this header's correct operation depends on __STDC_LIMIT_MACROS + being defined. We would define it here, but in order to prevent Bad Things + happening when system headers or C++ STL headers include stdint.h before we + define it here, we define it on the g++ command line (in Makefile.rules). */ +#if !defined(__STDC_LIMIT_MACROS) +#error "Must #define __STDC_LIMIT_MACROS before #including Support/DataTypes.h" +#endif + +#if !defined(__STDC_CONSTANT_MACROS) +#error "Must #define __STDC_CONSTANT_MACROS before " \ + "#including Support/DataTypes.h" +#endif + +/* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */ +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif + +#ifdef _AIX +#include "llvm/Support/AIXDataTypesFix.h" +#endif + +/* Handle incorrect definition of uint64_t as u_int64_t */ +#ifndef HAVE_UINT64_T +#ifdef HAVE_U_INT64_T +typedef u_int64_t uint64_t; +#else +#error "Don't have a definition for uint64_t on this platform" +#endif +#endif + +#ifdef _OpenBSD_ +#define INT8_MAX 127 +#define INT8_MIN -128 +#define UINT8_MAX 255 +#define INT16_MAX 32767 +#define INT16_MIN -32768 +#define UINT16_MAX 65535 +#define INT32_MAX 2147483647 +#define INT32_MIN -2147483648 +#define UINT32_MAX 4294967295U +#endif + +#else /* _MSC_VER */ +/* Visual C++ doesn't provide standard integer headers, but it does provide + built-in data types. */ +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <sys/types.h> +#ifdef __cplusplus +#include <cmath> +#else +#include <math.h> +#endif +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed int ssize_t; +#ifndef INT8_MAX +#define INT8_MAX 127 +#endif +#ifndef INT8_MIN +#define INT8_MIN -128 +#endif +#ifndef UINT8_MAX +#define UINT8_MAX 255 +#endif +#ifndef INT16_MAX +#define INT16_MAX 32767 +#endif +#ifndef INT16_MIN +#define INT16_MIN -32768 +#endif +#ifndef UINT16_MAX +#define UINT16_MAX 65535 +#endif +#ifndef INT32_MAX +#define INT32_MAX 2147483647 +#endif +#ifndef INT32_MIN +/* MSC treats -2147483648 as -(2147483648U). */ +#define INT32_MIN (-INT32_MAX - 1) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX 4294967295U +#endif +/* Certain compatibility updates to VC++ introduce the `cstdint' + * header, which defines the INT*_C macros. On default installs they + * are absent. */ +#ifndef INT8_C +#define INT8_C(C) C##i8 +#endif +#ifndef UINT8_C +#define UINT8_C(C) C##ui8 +#endif +#ifndef INT16_C +#define INT16_C(C) C##i16 +#endif +#ifndef UINT16_C +#define UINT16_C(C) C##ui16 +#endif +#ifndef INT32_C +#define INT32_C(C) C##i32 +#endif +#ifndef UINT32_C +#define UINT32_C(C) C##ui32 +#endif +#ifndef INT64_C +#define INT64_C(C) C##i64 +#endif +#ifndef UINT64_C +#define UINT64_C(C) C##ui64 +#endif + +#ifndef PRId64 +# define PRId64 "I64d" +#endif +#ifndef PRIi64 +# define PRIu64 "I64i" +#endif +#ifndef PRIo64 +# define PRIx64 "I64o" +#endif +#ifndef PRIu64 +# define PRIu64 "I64u" +#endif +#ifndef PRIx64 +# define PRIx64 "I64x" +#endif +#ifndef PRIX64 +# define PRIX64 "I64X" +#endif + +#endif /* _MSC_VER */ + +/* Set defaults for constants which we cannot find. */ +#if !defined(INT64_MAX) +#define INT64_MAX 9223372036854775807LL +#endif +#if !defined(INT64_MIN) +#define INT64_MIN ((-INT64_MAX) - 1) +#endif +#if !defined(UINT64_MAX) +#define UINT64_MAX 0xffffffffffffffffULL +#endif + +#if __GNUC__ > 3 +#define END_WITH_NULL __attribute__((sentinel)) +#else +#define END_WITH_NULL +#endif + +#ifndef HUGE_VALF +#define HUGE_VALF (float)HUGE_VAL +#endif + +#endif /* SUPPORT_DATATYPES_H */
diff --git a/third_party/llvm-subzero/include/llvm/Support/Debug.h b/third_party/llvm-subzero/include/llvm/Support/Debug.h new file mode 100644 index 0000000..dc42379 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Debug.h
@@ -0,0 +1,97 @@ +//===- llvm/Support/Debug.h - Easy way to add debug output ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a handy way of adding debugging information to your +// code, without it being enabled all of the time, and without having to add +// command line options to enable it. +// +// In particular, just wrap your code with the DEBUG() macro, and it will be +// enabled automatically if you specify '-debug' on the command-line. +// DEBUG() requires the DEBUG_TYPE macro to be defined. Set it to "foo" specify +// that your debug code belongs to class "foo". Be careful that you only do +// this after including Debug.h and not around any #include of headers. Headers +// should define and undef the macro acround the code that needs to use the +// DEBUG() macro. Then, on the command line, you can specify '-debug-only=foo' +// to enable JUST the debug information for the foo class. +// +// When compiling without assertions, the -debug-* options and all code in +// DEBUG() statements disappears, so it does not affect the runtime of the code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DEBUG_H +#define LLVM_SUPPORT_DEBUG_H + +namespace llvm { + +class raw_ostream; + +#ifndef NDEBUG +/// DebugFlag - This boolean is set to true if the '-debug' command line option +/// is specified. This should probably not be referenced directly, instead, use +/// the DEBUG macro below. +/// +extern bool DebugFlag; + +/// isCurrentDebugType - Return true if the specified string is the debug type +/// specified on the command line, or if none was specified on the command line +/// with the -debug-only=X option. +/// +bool isCurrentDebugType(const char *Type); + +/// setCurrentDebugType - Set the current debug type, as if the -debug-only=X +/// option were specified. Note that DebugFlag also needs to be set to true for +/// debug output to be produced. +/// +void setCurrentDebugType(const char *Type); + +/// DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug +/// information. In the '-debug' option is specified on the commandline, and if +/// this is a debug build, then the code specified as the option to the macro +/// will be executed. Otherwise it will not be. Example: +/// +/// DEBUG_WITH_TYPE("bitset", dbgs() << "Bitset contains: " << Bitset << "\n"); +/// +/// This will emit the debug information if -debug is present, and -debug-only +/// is not specified, or is specified as "bitset". +#define DEBUG_WITH_TYPE(TYPE, X) \ + do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType(TYPE)) { X; } \ + } while (false) + +#else +#define isCurrentDebugType(X) (false) +#define setCurrentDebugType(X) +#define DEBUG_WITH_TYPE(TYPE, X) do { } while (false) +#endif + +/// EnableDebugBuffering - This defaults to false. If true, the debug +/// stream will install signal handlers to dump any buffered debug +/// output. It allows clients to selectively allow the debug stream +/// to install signal handlers if they are certain there will be no +/// conflict. +/// +extern bool EnableDebugBuffering; + +/// dbgs() - This returns a reference to a raw_ostream for debugging +/// messages. If debugging is disabled it returns errs(). Use it +/// like: dbgs() << "foo" << "bar"; +raw_ostream &dbgs(); + +// DEBUG macro - This macro should be used by passes to emit debug information. +// In the '-debug' option is specified on the commandline, and if this is a +// debug build, then the code specified as the option to the macro will be +// executed. Otherwise it will not be. Example: +// +// DEBUG(dbgs() << "Bitset contains: " << Bitset << "\n"); +// +#define DEBUG(X) DEBUG_WITH_TYPE(DEBUG_TYPE, X) + +} // end namespace llvm + +#endif // LLVM_SUPPORT_DEBUG_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELF.h b/third_party/llvm-subzero/include/llvm/Support/ELF.h new file mode 100644 index 0000000..826c0de --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ELF.h
@@ -0,0 +1,1370 @@ +//===-- llvm/Support/ELF.h - ELF constants and data structures --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header contains common, non-processor-specific data structures and +// constants for the ELF file format. +// +// The details of the ELF32 bits in this file are largely based on the Tool +// Interface Standard (TIS) Executable and Linking Format (ELF) Specification +// Version 1.2, May 1995. The ELF64 stuff is based on ELF-64 Object File Format +// Version 1.5, Draft 2, May 1998 as well as OpenBSD header files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ELF_H +#define LLVM_SUPPORT_ELF_H + +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" +#include <cstring> + +namespace llvm { + +namespace ELF { + +typedef uint32_t Elf32_Addr; // Program address +typedef uint32_t Elf32_Off; // File offset +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; + +typedef uint64_t Elf64_Addr; +typedef uint64_t Elf64_Off; +typedef uint16_t Elf64_Half; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +// Object file magic string. +static const char ElfMagic[] = { 0x7f, 'E', 'L', 'F', '\0' }; + +// e_ident size and indices. +enum { + EI_MAG0 = 0, // File identification index. + EI_MAG1 = 1, // File identification index. + EI_MAG2 = 2, // File identification index. + EI_MAG3 = 3, // File identification index. + EI_CLASS = 4, // File class. + EI_DATA = 5, // Data encoding. + EI_VERSION = 6, // File version. + EI_OSABI = 7, // OS/ABI identification. + EI_ABIVERSION = 8, // ABI version. + EI_PAD = 9, // Start of padding bytes. + EI_NIDENT = 16 // Number of bytes in e_ident. +}; + +struct Elf32_Ehdr { + unsigned char e_ident[EI_NIDENT]; // ELF Identification bytes + Elf32_Half e_type; // Type of file (see ET_* below) + Elf32_Half e_machine; // Required architecture for this file (see EM_*) + Elf32_Word e_version; // Must be equal to 1 + Elf32_Addr e_entry; // Address to jump to in order to start program + Elf32_Off e_phoff; // Program header table's file offset, in bytes + Elf32_Off e_shoff; // Section header table's file offset, in bytes + Elf32_Word e_flags; // Processor-specific flags + Elf32_Half e_ehsize; // Size of ELF header, in bytes + Elf32_Half e_phentsize; // Size of an entry in the program header table + Elf32_Half e_phnum; // Number of entries in the program header table + Elf32_Half e_shentsize; // Size of an entry in the section header table + Elf32_Half e_shnum; // Number of entries in the section header table + Elf32_Half e_shstrndx; // Sect hdr table index of sect name string table + bool checkMagic() const { + return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0; + } + unsigned char getFileClass() const { return e_ident[EI_CLASS]; } + unsigned char getDataEncoding() const { return e_ident[EI_DATA]; } +}; + +// 64-bit ELF header. Fields are the same as for ELF32, but with different +// types (see above). +struct Elf64_Ehdr { + unsigned char e_ident[EI_NIDENT]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; + bool checkMagic() const { + return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0; + } + unsigned char getFileClass() const { return e_ident[EI_CLASS]; } + unsigned char getDataEncoding() const { return e_ident[EI_DATA]; } +}; + +// File types +enum { + ET_NONE = 0, // No file type + ET_REL = 1, // Relocatable file + ET_EXEC = 2, // Executable file + ET_DYN = 3, // Shared object file + ET_CORE = 4, // Core file + ET_LOPROC = 0xff00, // Beginning of processor-specific codes + ET_HIPROC = 0xffff // Processor-specific +}; + +// Versioning +enum { + EV_NONE = 0, + EV_CURRENT = 1 +}; + +// Machine architectures +// See current registered ELF machine architectures at: +// http://www.uxsglobal.com/developers/gabi/latest/ch4.eheader.html +enum { + EM_NONE = 0, // No machine + EM_M32 = 1, // AT&T WE 32100 + EM_SPARC = 2, // SPARC + EM_386 = 3, // Intel 386 + EM_68K = 4, // Motorola 68000 + EM_88K = 5, // Motorola 88000 + EM_IAMCU = 6, // Intel MCU + EM_860 = 7, // Intel 80860 + EM_MIPS = 8, // MIPS R3000 + EM_S370 = 9, // IBM System/370 + EM_MIPS_RS3_LE = 10, // MIPS RS3000 Little-endian + EM_PARISC = 15, // Hewlett-Packard PA-RISC + EM_VPP500 = 17, // Fujitsu VPP500 + EM_SPARC32PLUS = 18, // Enhanced instruction set SPARC + EM_960 = 19, // Intel 80960 + EM_PPC = 20, // PowerPC + EM_PPC64 = 21, // PowerPC64 + EM_S390 = 22, // IBM System/390 + EM_SPU = 23, // IBM SPU/SPC + EM_V800 = 36, // NEC V800 + EM_FR20 = 37, // Fujitsu FR20 + EM_RH32 = 38, // TRW RH-32 + EM_RCE = 39, // Motorola RCE + EM_ARM = 40, // ARM + EM_ALPHA = 41, // DEC Alpha + EM_SH = 42, // Hitachi SH + EM_SPARCV9 = 43, // SPARC V9 + EM_TRICORE = 44, // Siemens TriCore + EM_ARC = 45, // Argonaut RISC Core + EM_H8_300 = 46, // Hitachi H8/300 + EM_H8_300H = 47, // Hitachi H8/300H + EM_H8S = 48, // Hitachi H8S + EM_H8_500 = 49, // Hitachi H8/500 + EM_IA_64 = 50, // Intel IA-64 processor architecture + EM_MIPS_X = 51, // Stanford MIPS-X + EM_COLDFIRE = 52, // Motorola ColdFire + EM_68HC12 = 53, // Motorola M68HC12 + EM_MMA = 54, // Fujitsu MMA Multimedia Accelerator + EM_PCP = 55, // Siemens PCP + EM_NCPU = 56, // Sony nCPU embedded RISC processor + EM_NDR1 = 57, // Denso NDR1 microprocessor + EM_STARCORE = 58, // Motorola Star*Core processor + EM_ME16 = 59, // Toyota ME16 processor + EM_ST100 = 60, // STMicroelectronics ST100 processor + EM_TINYJ = 61, // Advanced Logic Corp. TinyJ embedded processor family + EM_X86_64 = 62, // AMD x86-64 architecture + EM_PDSP = 63, // Sony DSP Processor + EM_PDP10 = 64, // Digital Equipment Corp. PDP-10 + EM_PDP11 = 65, // Digital Equipment Corp. PDP-11 + EM_FX66 = 66, // Siemens FX66 microcontroller + EM_ST9PLUS = 67, // STMicroelectronics ST9+ 8/16 bit microcontroller + EM_ST7 = 68, // STMicroelectronics ST7 8-bit microcontroller + EM_68HC16 = 69, // Motorola MC68HC16 Microcontroller + EM_68HC11 = 70, // Motorola MC68HC11 Microcontroller + EM_68HC08 = 71, // Motorola MC68HC08 Microcontroller + EM_68HC05 = 72, // Motorola MC68HC05 Microcontroller + EM_SVX = 73, // Silicon Graphics SVx + EM_ST19 = 74, // STMicroelectronics ST19 8-bit microcontroller + EM_VAX = 75, // Digital VAX + EM_CRIS = 76, // Axis Communications 32-bit embedded processor + EM_JAVELIN = 77, // Infineon Technologies 32-bit embedded processor + EM_FIREPATH = 78, // Element 14 64-bit DSP Processor + EM_ZSP = 79, // LSI Logic 16-bit DSP Processor + EM_MMIX = 80, // Donald Knuth's educational 64-bit processor + EM_HUANY = 81, // Harvard University machine-independent object files + EM_PRISM = 82, // SiTera Prism + EM_AVR = 83, // Atmel AVR 8-bit microcontroller + EM_FR30 = 84, // Fujitsu FR30 + EM_D10V = 85, // Mitsubishi D10V + EM_D30V = 86, // Mitsubishi D30V + EM_V850 = 87, // NEC v850 + EM_M32R = 88, // Mitsubishi M32R + EM_MN10300 = 89, // Matsushita MN10300 + EM_MN10200 = 90, // Matsushita MN10200 + EM_PJ = 91, // picoJava + EM_OPENRISC = 92, // OpenRISC 32-bit embedded processor + EM_ARC_COMPACT = 93, // ARC International ARCompact processor (old + // spelling/synonym: EM_ARC_A5) + EM_XTENSA = 94, // Tensilica Xtensa Architecture + EM_VIDEOCORE = 95, // Alphamosaic VideoCore processor + EM_TMM_GPP = 96, // Thompson Multimedia General Purpose Processor + EM_NS32K = 97, // National Semiconductor 32000 series + EM_TPC = 98, // Tenor Network TPC processor + EM_SNP1K = 99, // Trebia SNP 1000 processor + EM_ST200 = 100, // STMicroelectronics (www.st.com) ST200 + EM_IP2K = 101, // Ubicom IP2xxx microcontroller family + EM_MAX = 102, // MAX Processor + EM_CR = 103, // National Semiconductor CompactRISC microprocessor + EM_F2MC16 = 104, // Fujitsu F2MC16 + EM_MSP430 = 105, // Texas Instruments embedded microcontroller msp430 + EM_BLACKFIN = 106, // Analog Devices Blackfin (DSP) processor + EM_SE_C33 = 107, // S1C33 Family of Seiko Epson processors + EM_SEP = 108, // Sharp embedded microprocessor + EM_ARCA = 109, // Arca RISC Microprocessor + EM_UNICORE = 110, // Microprocessor series from PKU-Unity Ltd. and MPRC + // of Peking University + EM_EXCESS = 111, // eXcess: 16/32/64-bit configurable embedded CPU + EM_DXP = 112, // Icera Semiconductor Inc. Deep Execution Processor + EM_ALTERA_NIOS2 = 113, // Altera Nios II soft-core processor + EM_CRX = 114, // National Semiconductor CompactRISC CRX + EM_XGATE = 115, // Motorola XGATE embedded processor + EM_C166 = 116, // Infineon C16x/XC16x processor + EM_M16C = 117, // Renesas M16C series microprocessors + EM_DSPIC30F = 118, // Microchip Technology dsPIC30F Digital Signal + // Controller + EM_CE = 119, // Freescale Communication Engine RISC core + EM_M32C = 120, // Renesas M32C series microprocessors + EM_TSK3000 = 131, // Altium TSK3000 core + EM_RS08 = 132, // Freescale RS08 embedded processor + EM_SHARC = 133, // Analog Devices SHARC family of 32-bit DSP + // processors + EM_ECOG2 = 134, // Cyan Technology eCOG2 microprocessor + EM_SCORE7 = 135, // Sunplus S+core7 RISC processor + EM_DSP24 = 136, // New Japan Radio (NJR) 24-bit DSP Processor + EM_VIDEOCORE3 = 137, // Broadcom VideoCore III processor + EM_LATTICEMICO32 = 138, // RISC processor for Lattice FPGA architecture + EM_SE_C17 = 139, // Seiko Epson C17 family + EM_TI_C6000 = 140, // The Texas Instruments TMS320C6000 DSP family + EM_TI_C2000 = 141, // The Texas Instruments TMS320C2000 DSP family + EM_TI_C5500 = 142, // The Texas Instruments TMS320C55x DSP family + EM_MMDSP_PLUS = 160, // STMicroelectronics 64bit VLIW Data Signal Processor + EM_CYPRESS_M8C = 161, // Cypress M8C microprocessor + EM_R32C = 162, // Renesas R32C series microprocessors + EM_TRIMEDIA = 163, // NXP Semiconductors TriMedia architecture family + EM_HEXAGON = 164, // Qualcomm Hexagon processor + EM_8051 = 165, // Intel 8051 and variants + EM_STXP7X = 166, // STMicroelectronics STxP7x family of configurable + // and extensible RISC processors + EM_NDS32 = 167, // Andes Technology compact code size embedded RISC + // processor family + EM_ECOG1 = 168, // Cyan Technology eCOG1X family + EM_ECOG1X = 168, // Cyan Technology eCOG1X family + EM_MAXQ30 = 169, // Dallas Semiconductor MAXQ30 Core Micro-controllers + EM_XIMO16 = 170, // New Japan Radio (NJR) 16-bit DSP Processor + EM_MANIK = 171, // M2000 Reconfigurable RISC Microprocessor + EM_CRAYNV2 = 172, // Cray Inc. NV2 vector architecture + EM_RX = 173, // Renesas RX family + EM_METAG = 174, // Imagination Technologies META processor + // architecture + EM_MCST_ELBRUS = 175, // MCST Elbrus general purpose hardware architecture + EM_ECOG16 = 176, // Cyan Technology eCOG16 family + EM_CR16 = 177, // National Semiconductor CompactRISC CR16 16-bit + // microprocessor + EM_ETPU = 178, // Freescale Extended Time Processing Unit + EM_SLE9X = 179, // Infineon Technologies SLE9X core + EM_L10M = 180, // Intel L10M + EM_K10M = 181, // Intel K10M + EM_AARCH64 = 183, // ARM AArch64 + EM_AVR32 = 185, // Atmel Corporation 32-bit microprocessor family + EM_STM8 = 186, // STMicroeletronics STM8 8-bit microcontroller + EM_TILE64 = 187, // Tilera TILE64 multicore architecture family + EM_TILEPRO = 188, // Tilera TILEPro multicore architecture family + EM_CUDA = 190, // NVIDIA CUDA architecture + EM_TILEGX = 191, // Tilera TILE-Gx multicore architecture family + EM_CLOUDSHIELD = 192, // CloudShield architecture family + EM_COREA_1ST = 193, // KIPO-KAIST Core-A 1st generation processor family + EM_COREA_2ND = 194, // KIPO-KAIST Core-A 2nd generation processor family + EM_ARC_COMPACT2 = 195, // Synopsys ARCompact V2 + EM_OPEN8 = 196, // Open8 8-bit RISC soft processor core + EM_RL78 = 197, // Renesas RL78 family + EM_VIDEOCORE5 = 198, // Broadcom VideoCore V processor + EM_78KOR = 199, // Renesas 78KOR family + EM_56800EX = 200, // Freescale 56800EX Digital Signal Controller (DSC) + EM_BA1 = 201, // Beyond BA1 CPU architecture + EM_BA2 = 202, // Beyond BA2 CPU architecture + EM_XCORE = 203, // XMOS xCORE processor family + EM_MCHP_PIC = 204, // Microchip 8-bit PIC(r) family + EM_INTEL205 = 205, // Reserved by Intel + EM_INTEL206 = 206, // Reserved by Intel + EM_INTEL207 = 207, // Reserved by Intel + EM_INTEL208 = 208, // Reserved by Intel + EM_INTEL209 = 209, // Reserved by Intel + EM_KM32 = 210, // KM211 KM32 32-bit processor + EM_KMX32 = 211, // KM211 KMX32 32-bit processor + EM_KMX16 = 212, // KM211 KMX16 16-bit processor + EM_KMX8 = 213, // KM211 KMX8 8-bit processor + EM_KVARC = 214, // KM211 KVARC processor + EM_CDP = 215, // Paneve CDP architecture family + EM_COGE = 216, // Cognitive Smart Memory Processor + EM_COOL = 217, // iCelero CoolEngine + EM_NORC = 218, // Nanoradio Optimized RISC + EM_CSR_KALIMBA = 219, // CSR Kalimba architecture family + EM_AMDGPU = 224, // AMD GPU architecture + EM_LANAI = 244, // Lanai 32-bit processor + EM_BPF = 247, // Linux kernel bpf virtual machine + + // A request has been made to the maintainer of the official registry for + // such numbers for an official value for WebAssembly. As soon as one is + // allocated, this enum will be updated to use it. + EM_WEBASSEMBLY = 0x4157, // WebAssembly architecture +}; + +// Object file classes. +enum { + ELFCLASSNONE = 0, + ELFCLASS32 = 1, // 32-bit object file + ELFCLASS64 = 2 // 64-bit object file +}; + +// Object file byte orderings. +enum { + ELFDATANONE = 0, // Invalid data encoding. + ELFDATA2LSB = 1, // Little-endian object file + ELFDATA2MSB = 2 // Big-endian object file +}; + +// OS ABI identification. +enum { + ELFOSABI_NONE = 0, // UNIX System V ABI + ELFOSABI_HPUX = 1, // HP-UX operating system + ELFOSABI_NETBSD = 2, // NetBSD + ELFOSABI_GNU = 3, // GNU/Linux + ELFOSABI_LINUX = 3, // Historical alias for ELFOSABI_GNU. + ELFOSABI_HURD = 4, // GNU/Hurd + ELFOSABI_SOLARIS = 6, // Solaris + ELFOSABI_AIX = 7, // AIX + ELFOSABI_IRIX = 8, // IRIX + ELFOSABI_FREEBSD = 9, // FreeBSD + ELFOSABI_TRU64 = 10, // TRU64 UNIX + ELFOSABI_MODESTO = 11, // Novell Modesto + ELFOSABI_OPENBSD = 12, // OpenBSD + ELFOSABI_OPENVMS = 13, // OpenVMS + ELFOSABI_NSK = 14, // Hewlett-Packard Non-Stop Kernel + ELFOSABI_AROS = 15, // AROS + ELFOSABI_FENIXOS = 16, // FenixOS + ELFOSABI_CLOUDABI = 17, // Nuxi CloudABI + ELFOSABI_C6000_ELFABI = 64, // Bare-metal TMS320C6000 + ELFOSABI_AMDGPU_HSA = 64, // AMD HSA runtime + ELFOSABI_C6000_LINUX = 65, // Linux TMS320C6000 + ELFOSABI_ARM = 97, // ARM + ELFOSABI_STANDALONE = 255 // Standalone (embedded) application +}; + +#define ELF_RELOC(name, value) name = value, + +// X86_64 relocations. +enum { +#include "ELFRelocs/x86_64.def" +}; + +// i386 relocations. +enum { +#include "ELFRelocs/i386.def" +}; + +// ELF Relocation types for PPC32 +enum { +#include "ELFRelocs/PowerPC.def" +}; + +// Specific e_flags for PPC64 +enum { + // e_flags bits specifying ABI: + // 1 for original ABI using function descriptors, + // 2 for revised ABI without function descriptors, + // 0 for unspecified or not using any features affected by the differences. + EF_PPC64_ABI = 3 +}; + +// Special values for the st_other field in the symbol table entry for PPC64. +enum { + STO_PPC64_LOCAL_BIT = 5, + STO_PPC64_LOCAL_MASK = (7 << STO_PPC64_LOCAL_BIT) +}; +static inline int64_t +decodePPC64LocalEntryOffset(unsigned Other) { + unsigned Val = (Other & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT; + return ((1 << Val) >> 2) << 2; +} +static inline unsigned +encodePPC64LocalEntryOffset(int64_t Offset) { + unsigned Val = (Offset >= 4 * 4 + ? (Offset >= 8 * 4 + ? (Offset >= 16 * 4 ? 6 : 5) + : 4) + : (Offset >= 2 * 4 + ? 3 + : (Offset >= 1 * 4 ? 2 : 0))); + return Val << STO_PPC64_LOCAL_BIT; +} + +// ELF Relocation types for PPC64 +enum { +#include "ELFRelocs/PowerPC64.def" +}; + +// ELF Relocation types for AArch64 +enum { +#include "ELFRelocs/AArch64.def" +}; + +// ARM Specific e_flags +enum : unsigned { + EF_ARM_SOFT_FLOAT = 0x00000200U, + EF_ARM_VFP_FLOAT = 0x00000400U, + EF_ARM_EABI_UNKNOWN = 0x00000000U, + EF_ARM_EABI_VER1 = 0x01000000U, + EF_ARM_EABI_VER2 = 0x02000000U, + EF_ARM_EABI_VER3 = 0x03000000U, + EF_ARM_EABI_VER4 = 0x04000000U, + EF_ARM_EABI_VER5 = 0x05000000U, + EF_ARM_EABIMASK = 0xFF000000U +}; + +// ELF Relocation types for ARM +enum { +#include "ELFRelocs/ARM.def" +}; + +// AVR specific e_flags +enum : unsigned { + EF_AVR_ARCH_AVR1 = 1, + EF_AVR_ARCH_AVR2 = 2, + EF_AVR_ARCH_AVR25 = 25, + EF_AVR_ARCH_AVR3 = 3, + EF_AVR_ARCH_AVR31 = 31, + EF_AVR_ARCH_AVR35 = 35, + EF_AVR_ARCH_AVR4 = 4, + EF_AVR_ARCH_AVR5 = 5, + EF_AVR_ARCH_AVR51 = 51, + EF_AVR_ARCH_AVR6 = 6, + EF_AVR_ARCH_AVRTINY = 100, + EF_AVR_ARCH_XMEGA1 = 101, + EF_AVR_ARCH_XMEGA2 = 102, + EF_AVR_ARCH_XMEGA3 = 103, + EF_AVR_ARCH_XMEGA4 = 104, + EF_AVR_ARCH_XMEGA5 = 105, + EF_AVR_ARCH_XMEGA6 = 106, + EF_AVR_ARCH_XMEGA7 = 107 +}; + +// ELF Relocation types for AVR +enum { +#include "ELFRelocs/AVR.def" +}; + +// Mips Specific e_flags +enum : unsigned { + EF_MIPS_NOREORDER = 0x00000001, // Don't reorder instructions + EF_MIPS_PIC = 0x00000002, // Position independent code + EF_MIPS_CPIC = 0x00000004, // Call object with Position independent code + EF_MIPS_ABI2 = 0x00000020, // File uses N32 ABI + EF_MIPS_32BITMODE = 0x00000100, // Code compiled for a 64-bit machine + // in 32-bit mode + EF_MIPS_FP64 = 0x00000200, // Code compiled for a 32-bit machine + // but uses 64-bit FP registers + EF_MIPS_NAN2008 = 0x00000400, // Uses IEE 754-2008 NaN encoding + + // ABI flags + EF_MIPS_ABI_O32 = 0x00001000, // This file follows the first MIPS 32 bit ABI + EF_MIPS_ABI_O64 = 0x00002000, // O32 ABI extended for 64-bit architecture. + EF_MIPS_ABI_EABI32 = 0x00003000, // EABI in 32 bit mode. + EF_MIPS_ABI_EABI64 = 0x00004000, // EABI in 64 bit mode. + EF_MIPS_ABI = 0x0000f000, // Mask for selecting EF_MIPS_ABI_ variant. + + // MIPS machine variant + EF_MIPS_MACH_NONE = 0x00000000, // A standard MIPS implementation. + EF_MIPS_MACH_3900 = 0x00810000, // Toshiba R3900 + EF_MIPS_MACH_4010 = 0x00820000, // LSI R4010 + EF_MIPS_MACH_4100 = 0x00830000, // NEC VR4100 + EF_MIPS_MACH_4650 = 0x00850000, // MIPS R4650 + EF_MIPS_MACH_4120 = 0x00870000, // NEC VR4120 + EF_MIPS_MACH_4111 = 0x00880000, // NEC VR4111/VR4181 + EF_MIPS_MACH_SB1 = 0x008a0000, // Broadcom SB-1 + EF_MIPS_MACH_OCTEON = 0x008b0000, // Cavium Networks Octeon + EF_MIPS_MACH_XLR = 0x008c0000, // RMI Xlr + EF_MIPS_MACH_OCTEON2 = 0x008d0000, // Cavium Networks Octeon2 + EF_MIPS_MACH_OCTEON3 = 0x008e0000, // Cavium Networks Octeon3 + EF_MIPS_MACH_5400 = 0x00910000, // NEC VR5400 + EF_MIPS_MACH_5900 = 0x00920000, // MIPS R5900 + EF_MIPS_MACH_5500 = 0x00980000, // NEC VR5500 + EF_MIPS_MACH_9000 = 0x00990000, // Unknown + EF_MIPS_MACH_LS2E = 0x00a00000, // ST Microelectronics Loongson 2E + EF_MIPS_MACH_LS2F = 0x00a10000, // ST Microelectronics Loongson 2F + EF_MIPS_MACH_LS3A = 0x00a20000, // Loongson 3A + EF_MIPS_MACH = 0x00ff0000, // EF_MIPS_MACH_xxx selection mask + + // ARCH_ASE + EF_MIPS_MICROMIPS = 0x02000000, // microMIPS + EF_MIPS_ARCH_ASE_M16 = + 0x04000000, // Has Mips-16 ISA extensions + EF_MIPS_ARCH_ASE_MDMX = + 0x08000000, // Has MDMX multimedia extensions + EF_MIPS_ARCH_ASE = 0x0f000000, // Mask for EF_MIPS_ARCH_ASE_xxx flags + + // ARCH + EF_MIPS_ARCH_1 = 0x00000000, // MIPS1 instruction set + EF_MIPS_ARCH_2 = 0x10000000, // MIPS2 instruction set + EF_MIPS_ARCH_3 = 0x20000000, // MIPS3 instruction set + EF_MIPS_ARCH_4 = 0x30000000, // MIPS4 instruction set + EF_MIPS_ARCH_5 = 0x40000000, // MIPS5 instruction set + EF_MIPS_ARCH_32 = 0x50000000, // MIPS32 instruction set per linux not elf.h + EF_MIPS_ARCH_64 = 0x60000000, // MIPS64 instruction set per linux not elf.h + EF_MIPS_ARCH_32R2 = 0x70000000, // mips32r2, mips32r3, mips32r5 + EF_MIPS_ARCH_64R2 = 0x80000000, // mips64r2, mips64r3, mips64r5 + EF_MIPS_ARCH_32R6 = 0x90000000, // mips32r6 + EF_MIPS_ARCH_64R6 = 0xa0000000, // mips64r6 + EF_MIPS_ARCH = 0xf0000000 // Mask for applying EF_MIPS_ARCH_ variant +}; + +// ELF Relocation types for Mips +enum { +#include "ELFRelocs/Mips.def" +}; + +// Special values for the st_other field in the symbol table entry for MIPS. +enum { + STO_MIPS_OPTIONAL = 0x04, // Symbol whose definition is optional + STO_MIPS_PLT = 0x08, // PLT entry related dynamic table record + STO_MIPS_PIC = 0x20, // PIC func in an object mixes PIC/non-PIC + STO_MIPS_MICROMIPS = 0x80, // MIPS Specific ISA for MicroMips + STO_MIPS_MIPS16 = 0xf0 // MIPS Specific ISA for Mips16 +}; + +// .MIPS.options section descriptor kinds +enum { + ODK_NULL = 0, // Undefined + ODK_REGINFO = 1, // Register usage information + ODK_EXCEPTIONS = 2, // Exception processing options + ODK_PAD = 3, // Section padding options + ODK_HWPATCH = 4, // Hardware patches applied + ODK_FILL = 5, // Linker fill value + ODK_TAGS = 6, // Space for tool identification + ODK_HWAND = 7, // Hardware AND patches applied + ODK_HWOR = 8, // Hardware OR patches applied + ODK_GP_GROUP = 9, // GP group to use for text/data sections + ODK_IDENT = 10, // ID information + ODK_PAGESIZE = 11 // Page size information +}; + +// Hexagon-specific e_flags +enum { + // Object processor version flags, bits[11:0] + EF_HEXAGON_MACH_V2 = 0x00000001, // Hexagon V2 + EF_HEXAGON_MACH_V3 = 0x00000002, // Hexagon V3 + EF_HEXAGON_MACH_V4 = 0x00000003, // Hexagon V4 + EF_HEXAGON_MACH_V5 = 0x00000004, // Hexagon V5 + EF_HEXAGON_MACH_V55 = 0x00000005, // Hexagon V55 + EF_HEXAGON_MACH_V60 = 0x00000060, // Hexagon V60 + + // Highest ISA version flags + EF_HEXAGON_ISA_MACH = 0x00000000, // Same as specified in bits[11:0] + // of e_flags + EF_HEXAGON_ISA_V2 = 0x00000010, // Hexagon V2 ISA + EF_HEXAGON_ISA_V3 = 0x00000020, // Hexagon V3 ISA + EF_HEXAGON_ISA_V4 = 0x00000030, // Hexagon V4 ISA + EF_HEXAGON_ISA_V5 = 0x00000040, // Hexagon V5 ISA + EF_HEXAGON_ISA_V55 = 0x00000050, // Hexagon V55 ISA + EF_HEXAGON_ISA_V60 = 0x00000060, // Hexagon V60 ISA +}; + +// Hexagon-specific section indexes for common small data +enum { + SHN_HEXAGON_SCOMMON = 0xff00, // Other access sizes + SHN_HEXAGON_SCOMMON_1 = 0xff01, // Byte-sized access + SHN_HEXAGON_SCOMMON_2 = 0xff02, // Half-word-sized access + SHN_HEXAGON_SCOMMON_4 = 0xff03, // Word-sized access + SHN_HEXAGON_SCOMMON_8 = 0xff04 // Double-word-size access +}; + +// ELF Relocation types for Hexagon +enum { +#include "ELFRelocs/Hexagon.def" +}; + +// ELF Relocation type for Lanai. +enum { +#include "ELFRelocs/Lanai.def" +}; + +// ELF Relocation types for S390/zSeries +enum { +#include "ELFRelocs/SystemZ.def" +}; + +// ELF Relocation type for Sparc. +enum { +#include "ELFRelocs/Sparc.def" +}; + +// ELF Relocation types for WebAssembly +enum { +#include "ELFRelocs/WebAssembly.def" +}; + +// ELF Relocation types for AMDGPU +enum { +#include "ELFRelocs/AMDGPU.def" +}; + +// ELF Relocation types for BPF +enum { +#include "ELFRelocs/BPF.def" +}; + +#undef ELF_RELOC + +// Section header. +struct Elf32_Shdr { + Elf32_Word sh_name; // Section name (index into string table) + Elf32_Word sh_type; // Section type (SHT_*) + Elf32_Word sh_flags; // Section flags (SHF_*) + Elf32_Addr sh_addr; // Address where section is to be loaded + Elf32_Off sh_offset; // File offset of section data, in bytes + Elf32_Word sh_size; // Size of section, in bytes + Elf32_Word sh_link; // Section type-specific header table index link + Elf32_Word sh_info; // Section type-specific extra information + Elf32_Word sh_addralign; // Section address alignment + Elf32_Word sh_entsize; // Size of records contained within the section +}; + +// Section header for ELF64 - same fields as ELF32, different types. +struct Elf64_Shdr { + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +}; + +// Special section indices. +enum { + SHN_UNDEF = 0, // Undefined, missing, irrelevant, or meaningless + SHN_LORESERVE = 0xff00, // Lowest reserved index + SHN_LOPROC = 0xff00, // Lowest processor-specific index + SHN_HIPROC = 0xff1f, // Highest processor-specific index + SHN_LOOS = 0xff20, // Lowest operating system-specific index + SHN_HIOS = 0xff3f, // Highest operating system-specific index + SHN_ABS = 0xfff1, // Symbol has absolute value; does not need relocation + SHN_COMMON = 0xfff2, // FORTRAN COMMON or C external global variables + SHN_XINDEX = 0xffff, // Mark that the index is >= SHN_LORESERVE + SHN_HIRESERVE = 0xffff // Highest reserved index +}; + +// Section types. +enum : unsigned { + SHT_NULL = 0, // No associated section (inactive entry). + SHT_PROGBITS = 1, // Program-defined contents. + SHT_SYMTAB = 2, // Symbol table. + SHT_STRTAB = 3, // String table. + SHT_RELA = 4, // Relocation entries; explicit addends. + SHT_HASH = 5, // Symbol hash table. + SHT_DYNAMIC = 6, // Information for dynamic linking. + SHT_NOTE = 7, // Information about the file. + SHT_NOBITS = 8, // Data occupies no space in the file. + SHT_REL = 9, // Relocation entries; no explicit addends. + SHT_SHLIB = 10, // Reserved. + SHT_DYNSYM = 11, // Symbol table. + SHT_INIT_ARRAY = 14, // Pointers to initialization functions. + SHT_FINI_ARRAY = 15, // Pointers to termination functions. + SHT_PREINIT_ARRAY = 16, // Pointers to pre-init functions. + SHT_GROUP = 17, // Section group. + SHT_SYMTAB_SHNDX = 18, // Indices for SHN_XINDEX entries. + SHT_LOOS = 0x60000000, // Lowest operating system-specific type. + SHT_GNU_ATTRIBUTES= 0x6ffffff5, // Object attributes. + SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table. + SHT_GNU_verdef = 0x6ffffffd, // GNU version definitions. + SHT_GNU_verneed = 0x6ffffffe, // GNU version references. + SHT_GNU_versym = 0x6fffffff, // GNU symbol versions table. + SHT_HIOS = 0x6fffffff, // Highest operating system-specific type. + SHT_LOPROC = 0x70000000, // Lowest processor arch-specific type. + // Fixme: All this is duplicated in MCSectionELF. Why?? + // Exception Index table + SHT_ARM_EXIDX = 0x70000001U, + // BPABI DLL dynamic linking pre-emption map + SHT_ARM_PREEMPTMAP = 0x70000002U, + // Object file compatibility attributes + SHT_ARM_ATTRIBUTES = 0x70000003U, + SHT_ARM_DEBUGOVERLAY = 0x70000004U, + SHT_ARM_OVERLAYSECTION = 0x70000005U, + SHT_HEX_ORDERED = 0x70000000, // Link editor is to sort the entries in + // this section based on their sizes + SHT_X86_64_UNWIND = 0x70000001, // Unwind information + + SHT_MIPS_REGINFO = 0x70000006, // Register usage information + SHT_MIPS_OPTIONS = 0x7000000d, // General options + SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information. + + SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. + SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. + SHT_HIUSER = 0xffffffff // Highest type reserved for applications. +}; + +// Section flags. +enum : unsigned { + // Section data should be writable during execution. + SHF_WRITE = 0x1, + + // Section occupies memory during program execution. + SHF_ALLOC = 0x2, + + // Section contains executable machine instructions. + SHF_EXECINSTR = 0x4, + + // The data in this section may be merged. + SHF_MERGE = 0x10, + + // The data in this section is null-terminated strings. + SHF_STRINGS = 0x20, + + // A field in this section holds a section header table index. + SHF_INFO_LINK = 0x40U, + + // Adds special ordering requirements for link editors. + SHF_LINK_ORDER = 0x80U, + + // This section requires special OS-specific processing to avoid incorrect + // behavior. + SHF_OS_NONCONFORMING = 0x100U, + + // This section is a member of a section group. + SHF_GROUP = 0x200U, + + // This section holds Thread-Local Storage. + SHF_TLS = 0x400U, + + // Identifies a section containing compressed data. + SHF_COMPRESSED = 0x800U, + + // This section is excluded from the final executable or shared library. + SHF_EXCLUDE = 0x80000000U, + + // Start of target-specific flags. + + /// XCORE_SHF_CP_SECTION - All sections with the "c" flag are grouped + /// together by the linker to form the constant pool and the cp register is + /// set to the start of the constant pool by the boot code. + XCORE_SHF_CP_SECTION = 0x800U, + + /// XCORE_SHF_DP_SECTION - All sections with the "d" flag are grouped + /// together by the linker to form the data section and the dp register is + /// set to the start of the section by the boot code. + XCORE_SHF_DP_SECTION = 0x1000U, + + SHF_MASKOS = 0x0ff00000, + + // Bits indicating processor-specific flags. + SHF_MASKPROC = 0xf0000000, + + // If an object file section does not have this flag set, then it may not hold + // more than 2GB and can be freely referred to in objects using smaller code + // models. Otherwise, only objects using larger code models can refer to them. + // For example, a medium code model object can refer to data in a section that + // sets this flag besides being able to refer to data in a section that does + // not set it; likewise, a small code model object can refer only to code in a + // section that does not set this flag. + SHF_X86_64_LARGE = 0x10000000, + + // All sections with the GPREL flag are grouped into a global data area + // for faster accesses + SHF_HEX_GPREL = 0x10000000, + + // Section contains text/data which may be replicated in other sections. + // Linker must retain only one copy. + SHF_MIPS_NODUPES = 0x01000000, + + // Linker must generate implicit hidden weak names. + SHF_MIPS_NAMES = 0x02000000, + + // Section data local to process. + SHF_MIPS_LOCAL = 0x04000000, + + // Do not strip this section. + SHF_MIPS_NOSTRIP = 0x08000000, + + // Section must be part of global data area. + SHF_MIPS_GPREL = 0x10000000, + + // This section should be merged. + SHF_MIPS_MERGE = 0x20000000, + + // Address size to be inferred from section entry size. + SHF_MIPS_ADDR = 0x40000000, + + // Section data is string data by default. + SHF_MIPS_STRING = 0x80000000, + + SHF_AMDGPU_HSA_GLOBAL = 0x00100000, + SHF_AMDGPU_HSA_READONLY = 0x00200000, + SHF_AMDGPU_HSA_CODE = 0x00400000, + SHF_AMDGPU_HSA_AGENT = 0x00800000 +}; + +// Section Group Flags +enum : unsigned { + GRP_COMDAT = 0x1, + GRP_MASKOS = 0x0ff00000, + GRP_MASKPROC = 0xf0000000 +}; + +// Symbol table entries for ELF32. +struct Elf32_Sym { + Elf32_Word st_name; // Symbol name (index into string table) + Elf32_Addr st_value; // Value or address associated with the symbol + Elf32_Word st_size; // Size of the symbol + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf32_Half st_shndx; // Which section (header table index) it's defined in + + // These accessors and mutators correspond to the ELF32_ST_BIND, + // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: + unsigned char getBinding() const { return st_info >> 4; } + unsigned char getType() const { return st_info & 0x0f; } + void setBinding(unsigned char b) { setBindingAndType(b, getType()); } + void setType(unsigned char t) { setBindingAndType(getBinding(), t); } + void setBindingAndType(unsigned char b, unsigned char t) { + st_info = (b << 4) + (t & 0x0f); + } +}; + +// Symbol table entries for ELF64. +struct Elf64_Sym { + Elf64_Word st_name; // Symbol name (index into string table) + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf64_Half st_shndx; // Which section (header tbl index) it's defined in + Elf64_Addr st_value; // Value or address associated with the symbol + Elf64_Xword st_size; // Size of the symbol + + // These accessors and mutators are identical to those defined for ELF32 + // symbol table entries. + unsigned char getBinding() const { return st_info >> 4; } + unsigned char getType() const { return st_info & 0x0f; } + void setBinding(unsigned char b) { setBindingAndType(b, getType()); } + void setType(unsigned char t) { setBindingAndType(getBinding(), t); } + void setBindingAndType(unsigned char b, unsigned char t) { + st_info = (b << 4) + (t & 0x0f); + } +}; + +// The size (in bytes) of symbol table entries. +enum { + SYMENTRY_SIZE32 = 16, // 32-bit symbol entry size + SYMENTRY_SIZE64 = 24 // 64-bit symbol entry size. +}; + +// Symbol bindings. +enum { + STB_LOCAL = 0, // Local symbol, not visible outside obj file containing def + STB_GLOBAL = 1, // Global symbol, visible to all object files being combined + STB_WEAK = 2, // Weak symbol, like global but lower-precedence + STB_GNU_UNIQUE = 10, + STB_LOOS = 10, // Lowest operating system-specific binding type + STB_HIOS = 12, // Highest operating system-specific binding type + STB_LOPROC = 13, // Lowest processor-specific binding type + STB_HIPROC = 15 // Highest processor-specific binding type +}; + +// Symbol types. +enum { + STT_NOTYPE = 0, // Symbol's type is not specified + STT_OBJECT = 1, // Symbol is a data object (variable, array, etc.) + STT_FUNC = 2, // Symbol is executable code (function, etc.) + STT_SECTION = 3, // Symbol refers to a section + STT_FILE = 4, // Local, absolute symbol that refers to a file + STT_COMMON = 5, // An uninitialized common block + STT_TLS = 6, // Thread local data object + STT_GNU_IFUNC = 10, // GNU indirect function + STT_LOOS = 10, // Lowest operating system-specific symbol type + STT_HIOS = 12, // Highest operating system-specific symbol type + STT_LOPROC = 13, // Lowest processor-specific symbol type + STT_HIPROC = 15, // Highest processor-specific symbol type + + // AMDGPU symbol types + STT_AMDGPU_HSA_KERNEL = 10, + STT_AMDGPU_HSA_INDIRECT_FUNCTION = 11, + STT_AMDGPU_HSA_METADATA = 12 +}; + +enum { + STV_DEFAULT = 0, // Visibility is specified by binding type + STV_INTERNAL = 1, // Defined by processor supplements + STV_HIDDEN = 2, // Not visible to other components + STV_PROTECTED = 3 // Visible in other components but not preemptable +}; + +// Symbol number. +enum { + STN_UNDEF = 0 +}; + +// Special relocation symbols used in the MIPS64 ELF relocation entries +enum { + RSS_UNDEF = 0, // None + RSS_GP = 1, // Value of gp + RSS_GP0 = 2, // Value of gp used to create object being relocated + RSS_LOC = 3 // Address of location being relocated +}; + +// Relocation entry, without explicit addend. +struct Elf32_Rel { + Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf32_Word r_info; // Symbol table index and type of relocation to apply + + // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, + // and ELF32_R_INFO macros defined in the ELF specification: + Elf32_Word getSymbol() const { return (r_info >> 8); } + unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } + void setSymbol(Elf32_Word s) { setSymbolAndType(s, getType()); } + void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(Elf32_Word s, unsigned char t) { + r_info = (s << 8) + t; + } +}; + +// Relocation entry with explicit addend. +struct Elf32_Rela { + Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf32_Word r_info; // Symbol table index and type of relocation to apply + Elf32_Sword r_addend; // Compute value for relocatable field by adding this + + // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, + // and ELF32_R_INFO macros defined in the ELF specification: + Elf32_Word getSymbol() const { return (r_info >> 8); } + unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } + void setSymbol(Elf32_Word s) { setSymbolAndType(s, getType()); } + void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(Elf32_Word s, unsigned char t) { + r_info = (s << 8) + t; + } +}; + +// Relocation entry, without explicit addend. +struct Elf64_Rel { + Elf64_Addr r_offset; // Location (file byte offset, or program virtual addr). + Elf64_Xword r_info; // Symbol table index and type of relocation to apply. + + // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, + // and ELF64_R_INFO macros defined in the ELF specification: + Elf64_Word getSymbol() const { return (r_info >> 32); } + Elf64_Word getType() const { + return (Elf64_Word) (r_info & 0xffffffffL); + } + void setSymbol(Elf64_Word s) { setSymbolAndType(s, getType()); } + void setType(Elf64_Word t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(Elf64_Word s, Elf64_Word t) { + r_info = ((Elf64_Xword)s << 32) + (t&0xffffffffL); + } +}; + +// Relocation entry with explicit addend. +struct Elf64_Rela { + Elf64_Addr r_offset; // Location (file byte offset, or program virtual addr). + Elf64_Xword r_info; // Symbol table index and type of relocation to apply. + Elf64_Sxword r_addend; // Compute value for relocatable field by adding this. + + // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, + // and ELF64_R_INFO macros defined in the ELF specification: + Elf64_Word getSymbol() const { return (r_info >> 32); } + Elf64_Word getType() const { + return (Elf64_Word) (r_info & 0xffffffffL); + } + void setSymbol(Elf64_Word s) { setSymbolAndType(s, getType()); } + void setType(Elf64_Word t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(Elf64_Word s, Elf64_Word t) { + r_info = ((Elf64_Xword)s << 32) + (t&0xffffffffL); + } +}; + +// Program header for ELF32. +struct Elf32_Phdr { + Elf32_Word p_type; // Type of segment + Elf32_Off p_offset; // File offset where segment is located, in bytes + Elf32_Addr p_vaddr; // Virtual address of beginning of segment + Elf32_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf32_Word p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf32_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf32_Word p_flags; // Segment flags + Elf32_Word p_align; // Segment alignment constraint +}; + +// Program header for ELF64. +struct Elf64_Phdr { + Elf64_Word p_type; // Type of segment + Elf64_Word p_flags; // Segment flags + Elf64_Off p_offset; // File offset where segment is located, in bytes + Elf64_Addr p_vaddr; // Virtual address of beginning of segment + Elf64_Addr p_paddr; // Physical addr of beginning of segment (OS-specific) + Elf64_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf64_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf64_Xword p_align; // Segment alignment constraint +}; + +// Segment types. +enum { + PT_NULL = 0, // Unused segment. + PT_LOAD = 1, // Loadable segment. + PT_DYNAMIC = 2, // Dynamic linking information. + PT_INTERP = 3, // Interpreter pathname. + PT_NOTE = 4, // Auxiliary information. + PT_SHLIB = 5, // Reserved. + PT_PHDR = 6, // The program header table itself. + PT_TLS = 7, // The thread-local storage template. + PT_LOOS = 0x60000000, // Lowest operating system-specific pt entry type. + PT_HIOS = 0x6fffffff, // Highest operating system-specific pt entry type. + PT_LOPROC = 0x70000000, // Lowest processor-specific program hdr entry type. + PT_HIPROC = 0x7fffffff, // Highest processor-specific program hdr entry type. + + // x86-64 program header types. + // These all contain stack unwind tables. + PT_GNU_EH_FRAME = 0x6474e550, + PT_SUNW_EH_FRAME = 0x6474e550, + PT_SUNW_UNWIND = 0x6464e550, + + PT_GNU_STACK = 0x6474e551, // Indicates stack executability. + PT_GNU_RELRO = 0x6474e552, // Read-only after relocation. + + // ARM program header types. + PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility info + // These all contain stack unwind tables. + PT_ARM_EXIDX = 0x70000001, + PT_ARM_UNWIND = 0x70000001, + + // MIPS program header types. + PT_MIPS_REGINFO = 0x70000000, // Register usage information. + PT_MIPS_RTPROC = 0x70000001, // Runtime procedure table. + PT_MIPS_OPTIONS = 0x70000002, // Options segment. + PT_MIPS_ABIFLAGS = 0x70000003, // Abiflags segment. + + // AMDGPU program header types. + PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM = 0x60000000, + PT_AMDGPU_HSA_LOAD_GLOBAL_AGENT = 0x60000001, + PT_AMDGPU_HSA_LOAD_READONLY_AGENT = 0x60000002, + PT_AMDGPU_HSA_LOAD_CODE_AGENT = 0x60000003, + + // WebAssembly program header types. + PT_WEBASSEMBLY_FUNCTIONS = PT_LOPROC + 0, // Function definitions. +}; + +// Segment flag bits. +enum : unsigned { + PF_X = 1, // Execute + PF_W = 2, // Write + PF_R = 4, // Read + PF_MASKOS = 0x0ff00000,// Bits for operating system-specific semantics. + PF_MASKPROC = 0xf0000000 // Bits for processor-specific semantics. +}; + +// Dynamic table entry for ELF32. +struct Elf32_Dyn +{ + Elf32_Sword d_tag; // Type of dynamic table entry. + union + { + Elf32_Word d_val; // Integer value of entry. + Elf32_Addr d_ptr; // Pointer value of entry. + } d_un; +}; + +// Dynamic table entry for ELF64. +struct Elf64_Dyn +{ + Elf64_Sxword d_tag; // Type of dynamic table entry. + union + { + Elf64_Xword d_val; // Integer value of entry. + Elf64_Addr d_ptr; // Pointer value of entry. + } d_un; +}; + +// Dynamic table entry tags. +enum { + DT_NULL = 0, // Marks end of dynamic array. + DT_NEEDED = 1, // String table offset of needed library. + DT_PLTRELSZ = 2, // Size of relocation entries in PLT. + DT_PLTGOT = 3, // Address associated with linkage table. + DT_HASH = 4, // Address of symbolic hash table. + DT_STRTAB = 5, // Address of dynamic string table. + DT_SYMTAB = 6, // Address of dynamic symbol table. + DT_RELA = 7, // Address of relocation table (Rela entries). + DT_RELASZ = 8, // Size of Rela relocation table. + DT_RELAENT = 9, // Size of a Rela relocation entry. + DT_STRSZ = 10, // Total size of the string table. + DT_SYMENT = 11, // Size of a symbol table entry. + DT_INIT = 12, // Address of initialization function. + DT_FINI = 13, // Address of termination function. + DT_SONAME = 14, // String table offset of a shared objects name. + DT_RPATH = 15, // String table offset of library search path. + DT_SYMBOLIC = 16, // Changes symbol resolution algorithm. + DT_REL = 17, // Address of relocation table (Rel entries). + DT_RELSZ = 18, // Size of Rel relocation table. + DT_RELENT = 19, // Size of a Rel relocation entry. + DT_PLTREL = 20, // Type of relocation entry used for linking. + DT_DEBUG = 21, // Reserved for debugger. + DT_TEXTREL = 22, // Relocations exist for non-writable segments. + DT_JMPREL = 23, // Address of relocations associated with PLT. + DT_BIND_NOW = 24, // Process all relocations before execution. + DT_INIT_ARRAY = 25, // Pointer to array of initialization functions. + DT_FINI_ARRAY = 26, // Pointer to array of termination functions. + DT_INIT_ARRAYSZ = 27, // Size of DT_INIT_ARRAY. + DT_FINI_ARRAYSZ = 28, // Size of DT_FINI_ARRAY. + DT_RUNPATH = 29, // String table offset of lib search path. + DT_FLAGS = 30, // Flags. + DT_ENCODING = 32, // Values from here to DT_LOOS follow the rules + // for the interpretation of the d_un union. + + DT_PREINIT_ARRAY = 32, // Pointer to array of preinit functions. + DT_PREINIT_ARRAYSZ = 33, // Size of the DT_PREINIT_ARRAY array. + + DT_LOOS = 0x60000000, // Start of environment specific tags. + DT_HIOS = 0x6FFFFFFF, // End of environment specific tags. + DT_LOPROC = 0x70000000, // Start of processor specific tags. + DT_HIPROC = 0x7FFFFFFF, // End of processor specific tags. + + DT_GNU_HASH = 0x6FFFFEF5, // Reference to the GNU hash table. + DT_TLSDESC_PLT = 0x6FFFFEF6, // Location of PLT entry for TLS descriptor resolver calls. + DT_TLSDESC_GOT = 0x6FFFFEF7, // Location of GOT entry used by TLS descriptor resolver PLT entry. + DT_RELACOUNT = 0x6FFFFFF9, // ELF32_Rela count. + DT_RELCOUNT = 0x6FFFFFFA, // ELF32_Rel count. + + DT_FLAGS_1 = 0X6FFFFFFB, // Flags_1. + DT_VERSYM = 0x6FFFFFF0, // The address of .gnu.version section. + DT_VERDEF = 0X6FFFFFFC, // The address of the version definition table. + DT_VERDEFNUM = 0X6FFFFFFD, // The number of entries in DT_VERDEF. + DT_VERNEED = 0X6FFFFFFE, // The address of the version Dependency table. + DT_VERNEEDNUM = 0X6FFFFFFF, // The number of entries in DT_VERNEED. + + // Mips specific dynamic table entry tags. + DT_MIPS_RLD_VERSION = 0x70000001, // 32 bit version number for runtime + // linker interface. + DT_MIPS_TIME_STAMP = 0x70000002, // Time stamp. + DT_MIPS_ICHECKSUM = 0x70000003, // Checksum of external strings + // and common sizes. + DT_MIPS_IVERSION = 0x70000004, // Index of version string + // in string table. + DT_MIPS_FLAGS = 0x70000005, // 32 bits of flags. + DT_MIPS_BASE_ADDRESS = 0x70000006, // Base address of the segment. + DT_MIPS_MSYM = 0x70000007, // Address of .msym section. + DT_MIPS_CONFLICT = 0x70000008, // Address of .conflict section. + DT_MIPS_LIBLIST = 0x70000009, // Address of .liblist section. + DT_MIPS_LOCAL_GOTNO = 0x7000000a, // Number of local global offset + // table entries. + DT_MIPS_CONFLICTNO = 0x7000000b, // Number of entries + // in the .conflict section. + DT_MIPS_LIBLISTNO = 0x70000010, // Number of entries + // in the .liblist section. + DT_MIPS_SYMTABNO = 0x70000011, // Number of entries + // in the .dynsym section. + DT_MIPS_UNREFEXTNO = 0x70000012, // Index of first external dynamic symbol + // not referenced locally. + DT_MIPS_GOTSYM = 0x70000013, // Index of first dynamic symbol + // in global offset table. + DT_MIPS_HIPAGENO = 0x70000014, // Number of page table entries + // in global offset table. + DT_MIPS_RLD_MAP = 0x70000016, // Address of run time loader map, + // used for debugging. + DT_MIPS_DELTA_CLASS = 0x70000017, // Delta C++ class definition. + DT_MIPS_DELTA_CLASS_NO = 0x70000018, // Number of entries + // in DT_MIPS_DELTA_CLASS. + DT_MIPS_DELTA_INSTANCE = 0x70000019, // Delta C++ class instances. + DT_MIPS_DELTA_INSTANCE_NO = 0x7000001A, // Number of entries + // in DT_MIPS_DELTA_INSTANCE. + DT_MIPS_DELTA_RELOC = 0x7000001B, // Delta relocations. + DT_MIPS_DELTA_RELOC_NO = 0x7000001C, // Number of entries + // in DT_MIPS_DELTA_RELOC. + DT_MIPS_DELTA_SYM = 0x7000001D, // Delta symbols that Delta + // relocations refer to. + DT_MIPS_DELTA_SYM_NO = 0x7000001E, // Number of entries + // in DT_MIPS_DELTA_SYM. + DT_MIPS_DELTA_CLASSSYM = 0x70000020, // Delta symbols that hold + // class declarations. + DT_MIPS_DELTA_CLASSSYM_NO = 0x70000021, // Number of entries + // in DT_MIPS_DELTA_CLASSSYM. + DT_MIPS_CXX_FLAGS = 0x70000022, // Flags indicating information + // about C++ flavor. + DT_MIPS_PIXIE_INIT = 0x70000023, // Pixie information. + DT_MIPS_SYMBOL_LIB = 0x70000024, // Address of .MIPS.symlib + DT_MIPS_LOCALPAGE_GOTIDX = 0x70000025, // The GOT index of the first PTE + // for a segment + DT_MIPS_LOCAL_GOTIDX = 0x70000026, // The GOT index of the first PTE + // for a local symbol + DT_MIPS_HIDDEN_GOTIDX = 0x70000027, // The GOT index of the first PTE + // for a hidden symbol + DT_MIPS_PROTECTED_GOTIDX = 0x70000028, // The GOT index of the first PTE + // for a protected symbol + DT_MIPS_OPTIONS = 0x70000029, // Address of `.MIPS.options'. + DT_MIPS_INTERFACE = 0x7000002A, // Address of `.interface'. + DT_MIPS_DYNSTR_ALIGN = 0x7000002B, // Unknown. + DT_MIPS_INTERFACE_SIZE = 0x7000002C, // Size of the .interface section. + DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 0x7000002D, // Size of rld_text_resolve + // function stored in the GOT. + DT_MIPS_PERF_SUFFIX = 0x7000002E, // Default suffix of DSO to be added + // by rld on dlopen() calls. + DT_MIPS_COMPACT_SIZE = 0x7000002F, // Size of compact relocation + // section (O32). + DT_MIPS_GP_VALUE = 0x70000030, // GP value for auxiliary GOTs. + DT_MIPS_AUX_DYNAMIC = 0x70000031, // Address of auxiliary .dynamic. + DT_MIPS_PLTGOT = 0x70000032, // Address of the base of the PLTGOT. + DT_MIPS_RWPLT = 0x70000034, // Points to the base + // of a writable PLT. + DT_MIPS_RLD_MAP_REL = 0x70000035, // Relative offset of run time loader + // map, used for debugging. + + // Sun machine-independent extensions. + DT_AUXILIARY = 0x7FFFFFFD, // Shared object to load before self + DT_FILTER = 0x7FFFFFFF // Shared object to get values from +}; + +// DT_FLAGS values. +enum { + DF_ORIGIN = 0x01, // The object may reference $ORIGIN. + DF_SYMBOLIC = 0x02, // Search the shared lib before searching the exe. + DF_TEXTREL = 0x04, // Relocations may modify a non-writable segment. + DF_BIND_NOW = 0x08, // Process all relocations on load. + DF_STATIC_TLS = 0x10 // Reject attempts to load dynamically. +}; + +// State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 entry. +enum { + DF_1_NOW = 0x00000001, // Set RTLD_NOW for this object. + DF_1_GLOBAL = 0x00000002, // Set RTLD_GLOBAL for this object. + DF_1_GROUP = 0x00000004, // Set RTLD_GROUP for this object. + DF_1_NODELETE = 0x00000008, // Set RTLD_NODELETE for this object. + DF_1_LOADFLTR = 0x00000010, // Trigger filtee loading at runtime. + DF_1_INITFIRST = 0x00000020, // Set RTLD_INITFIRST for this object. + DF_1_NOOPEN = 0x00000040, // Set RTLD_NOOPEN for this object. + DF_1_ORIGIN = 0x00000080, // $ORIGIN must be handled. + DF_1_DIRECT = 0x00000100, // Direct binding enabled. + DF_1_TRANS = 0x00000200, + DF_1_INTERPOSE = 0x00000400, // Object is used to interpose. + DF_1_NODEFLIB = 0x00000800, // Ignore default lib search path. + DF_1_NODUMP = 0x00001000, // Object can't be dldump'ed. + DF_1_CONFALT = 0x00002000, // Configuration alternative created. + DF_1_ENDFILTEE = 0x00004000, // Filtee terminates filters search. + DF_1_DISPRELDNE = 0x00008000, // Disp reloc applied at build time. + DF_1_DISPRELPND = 0x00010000, // Disp reloc applied at run-time. + DF_1_NODIRECT = 0x00020000, // Object has no-direct binding. + DF_1_IGNMULDEF = 0x00040000, + DF_1_NOKSYMS = 0x00080000, + DF_1_NOHDR = 0x00100000, + DF_1_EDITED = 0x00200000, // Object is modified after built. + DF_1_NORELOC = 0x00400000, + DF_1_SYMINTPOSE = 0x00800000, // Object has individual interposers. + DF_1_GLOBAUDIT = 0x01000000, // Global auditing required. + DF_1_SINGLETON = 0x02000000 // Singleton symbols are used. +}; + +// DT_MIPS_FLAGS values. +enum { + RHF_NONE = 0x00000000, // No flags. + RHF_QUICKSTART = 0x00000001, // Uses shortcut pointers. + RHF_NOTPOT = 0x00000002, // Hash size is not a power of two. + RHS_NO_LIBRARY_REPLACEMENT = 0x00000004, // Ignore LD_LIBRARY_PATH. + RHF_NO_MOVE = 0x00000008, // DSO address may not be relocated. + RHF_SGI_ONLY = 0x00000010, // SGI specific features. + RHF_GUARANTEE_INIT = 0x00000020, // Guarantee that .init will finish + // executing before any non-init + // code in DSO is called. + RHF_DELTA_C_PLUS_PLUS = 0x00000040, // Contains Delta C++ code. + RHF_GUARANTEE_START_INIT = 0x00000080, // Guarantee that .init will start + // executing before any non-init + // code in DSO is called. + RHF_PIXIE = 0x00000100, // Generated by pixie. + RHF_DEFAULT_DELAY_LOAD = 0x00000200, // Delay-load DSO by default. + RHF_REQUICKSTART = 0x00000400, // Object may be requickstarted + RHF_REQUICKSTARTED = 0x00000800, // Object has been requickstarted + RHF_CORD = 0x00001000, // Generated by cord. + RHF_NO_UNRES_UNDEF = 0x00002000, // Object contains no unresolved + // undef symbols. + RHF_RLD_ORDER_SAFE = 0x00004000 // Symbol table is in a safe order. +}; + +// ElfXX_VerDef structure version (GNU versioning) +enum { + VER_DEF_NONE = 0, + VER_DEF_CURRENT = 1 +}; + +// VerDef Flags (ElfXX_VerDef::vd_flags) +enum { + VER_FLG_BASE = 0x1, + VER_FLG_WEAK = 0x2, + VER_FLG_INFO = 0x4 +}; + +// Special constants for the version table. (SHT_GNU_versym/.gnu.version) +enum { + VER_NDX_LOCAL = 0, // Unversioned local symbol + VER_NDX_GLOBAL = 1, // Unversioned global symbol + VERSYM_VERSION = 0x7fff, // Version Index mask + VERSYM_HIDDEN = 0x8000 // Hidden bit (non-default version) +}; + +// ElfXX_VerNeed structure version (GNU versioning) +enum { + VER_NEED_NONE = 0, + VER_NEED_CURRENT = 1 +}; + +// SHT_NOTE section types +enum { + NT_GNU_ABI_TAG = 1, + NT_GNU_HWCAP = 2, + NT_GNU_BUILD_ID = 3, + NT_GNU_GOLD_VERSION = 4, +}; + +enum { + GNU_ABI_TAG_LINUX = 0, + GNU_ABI_TAG_HURD = 1, + GNU_ABI_TAG_SOLARIS = 2, + GNU_ABI_TAG_FREEBSD = 3, + GNU_ABI_TAG_NETBSD = 4, + GNU_ABI_TAG_SYLLABLE = 5, + GNU_ABI_TAG_NACL = 6, +}; + +// Compressed section header for ELF32. +struct Elf32_Chdr { + Elf32_Word ch_type; + Elf32_Word ch_size; + Elf32_Word ch_addralign; +}; + +// Compressed section header for ELF64. +struct Elf64_Chdr { + Elf64_Word ch_type; + Elf64_Word ch_reserved; + Elf64_Xword ch_size; + Elf64_Xword ch_addralign; +}; + +// Legal values for ch_type field of compressed section header. +enum { + ELFCOMPRESS_ZLIB = 1, // ZLIB/DEFLATE algorithm. + ELFCOMPRESS_LOOS = 0x60000000, // Start of OS-specific. + ELFCOMPRESS_HIOS = 0x6fffffff, // End of OS-specific. + ELFCOMPRESS_LOPROC = 0x70000000, // Start of processor-specific. + ELFCOMPRESS_HIPROC = 0x7fffffff // End of processor-specific. +}; + +} // end namespace ELF + +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AArch64.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AArch64.def new file mode 100644 index 0000000..aa0c560 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AArch64.def
@@ -0,0 +1,147 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +// ABI release 1.0 +ELF_RELOC(R_AARCH64_NONE, 0) + +ELF_RELOC(R_AARCH64_ABS64, 0x101) +ELF_RELOC(R_AARCH64_ABS32, 0x102) +ELF_RELOC(R_AARCH64_ABS16, 0x103) +ELF_RELOC(R_AARCH64_PREL64, 0x104) +ELF_RELOC(R_AARCH64_PREL32, 0x105) +ELF_RELOC(R_AARCH64_PREL16, 0x106) + +ELF_RELOC(R_AARCH64_MOVW_UABS_G0, 0x107) +ELF_RELOC(R_AARCH64_MOVW_UABS_G0_NC, 0x108) +ELF_RELOC(R_AARCH64_MOVW_UABS_G1, 0x109) +ELF_RELOC(R_AARCH64_MOVW_UABS_G1_NC, 0x10a) +ELF_RELOC(R_AARCH64_MOVW_UABS_G2, 0x10b) +ELF_RELOC(R_AARCH64_MOVW_UABS_G2_NC, 0x10c) +ELF_RELOC(R_AARCH64_MOVW_UABS_G3, 0x10d) +ELF_RELOC(R_AARCH64_MOVW_SABS_G0, 0x10e) +ELF_RELOC(R_AARCH64_MOVW_SABS_G1, 0x10f) +ELF_RELOC(R_AARCH64_MOVW_SABS_G2, 0x110) + +ELF_RELOC(R_AARCH64_LD_PREL_LO19, 0x111) +ELF_RELOC(R_AARCH64_ADR_PREL_LO21, 0x112) +ELF_RELOC(R_AARCH64_ADR_PREL_PG_HI21, 0x113) +ELF_RELOC(R_AARCH64_ADR_PREL_PG_HI21_NC, 0x114) +ELF_RELOC(R_AARCH64_ADD_ABS_LO12_NC, 0x115) +ELF_RELOC(R_AARCH64_LDST8_ABS_LO12_NC, 0x116) + +ELF_RELOC(R_AARCH64_TSTBR14, 0x117) +ELF_RELOC(R_AARCH64_CONDBR19, 0x118) +ELF_RELOC(R_AARCH64_JUMP26, 0x11a) +ELF_RELOC(R_AARCH64_CALL26, 0x11b) + +ELF_RELOC(R_AARCH64_LDST16_ABS_LO12_NC, 0x11c) +ELF_RELOC(R_AARCH64_LDST32_ABS_LO12_NC, 0x11d) +ELF_RELOC(R_AARCH64_LDST64_ABS_LO12_NC, 0x11e) + +ELF_RELOC(R_AARCH64_MOVW_PREL_G0, 0x11f) +ELF_RELOC(R_AARCH64_MOVW_PREL_G0_NC, 0x120) +ELF_RELOC(R_AARCH64_MOVW_PREL_G1, 0x121) +ELF_RELOC(R_AARCH64_MOVW_PREL_G1_NC, 0x122) +ELF_RELOC(R_AARCH64_MOVW_PREL_G2, 0x123) +ELF_RELOC(R_AARCH64_MOVW_PREL_G2_NC, 0x124) +ELF_RELOC(R_AARCH64_MOVW_PREL_G3, 0x125) + +ELF_RELOC(R_AARCH64_LDST128_ABS_LO12_NC, 0x12b) + +ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G0, 0x12c) +ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G0_NC, 0x12d) +ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G1, 0x12e) +ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G1_NC, 0x12f) +ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G2, 0x130) +ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G2_NC, 0x131) +ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G3, 0x132) + +ELF_RELOC(R_AARCH64_GOTREL64, 0x133) +ELF_RELOC(R_AARCH64_GOTREL32, 0x134) + +ELF_RELOC(R_AARCH64_GOT_LD_PREL19, 0x135) +ELF_RELOC(R_AARCH64_LD64_GOTOFF_LO15, 0x136) +ELF_RELOC(R_AARCH64_ADR_GOT_PAGE, 0x137) +ELF_RELOC(R_AARCH64_LD64_GOT_LO12_NC, 0x138) +ELF_RELOC(R_AARCH64_LD64_GOTPAGE_LO15, 0x139) + +ELF_RELOC(R_AARCH64_TLSGD_ADR_PREL21, 0x200) +ELF_RELOC(R_AARCH64_TLSGD_ADR_PAGE21, 0x201) +ELF_RELOC(R_AARCH64_TLSGD_ADD_LO12_NC, 0x202) +ELF_RELOC(R_AARCH64_TLSGD_MOVW_G1, 0x203) +ELF_RELOC(R_AARCH64_TLSGD_MOVW_G0_NC, 0x204) + +ELF_RELOC(R_AARCH64_TLSLD_ADR_PREL21, 0x205) +ELF_RELOC(R_AARCH64_TLSLD_ADR_PAGE21, 0x206) +ELF_RELOC(R_AARCH64_TLSLD_ADD_LO12_NC, 0x207) +ELF_RELOC(R_AARCH64_TLSLD_MOVW_G1, 0x208) +ELF_RELOC(R_AARCH64_TLSLD_MOVW_G0_NC, 0x209) +ELF_RELOC(R_AARCH64_TLSLD_LD_PREL19, 0x20a) +ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G2, 0x20b) +ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1, 0x20c) +ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC, 0x20d) +ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0, 0x20e) +ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC, 0x20f) +ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_HI12, 0x210) +ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_LO12, 0x211) +ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC, 0x212) +ELF_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12, 0x213) +ELF_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC, 0x214) +ELF_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12, 0x215) +ELF_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC, 0x216) +ELF_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12, 0x217) +ELF_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC, 0x218) +ELF_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12, 0x219) +ELF_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC, 0x21a) + +ELF_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1, 0x21b) +ELF_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC, 0x21c) +ELF_RELOC(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, 0x21d) +ELF_RELOC(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, 0x21e) +ELF_RELOC(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19, 0x21f) + +ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G2, 0x220) +ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1, 0x221) +ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC, 0x222) +ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0, 0x223) +ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC, 0x224) +ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_HI12, 0x225) +ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12, 0x226) +ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC, 0x227) +ELF_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12, 0x228) +ELF_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC, 0x229) +ELF_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12, 0x22a) +ELF_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC, 0x22b) +ELF_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12, 0x22c) +ELF_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC, 0x22d) +ELF_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12, 0x22e) +ELF_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC, 0x22f) + +ELF_RELOC(R_AARCH64_TLSDESC_LD_PREL19, 0x230) +ELF_RELOC(R_AARCH64_TLSDESC_ADR_PREL21, 0x231) +ELF_RELOC(R_AARCH64_TLSDESC_ADR_PAGE21, 0x232) +ELF_RELOC(R_AARCH64_TLSDESC_LD64_LO12_NC, 0x233) +ELF_RELOC(R_AARCH64_TLSDESC_ADD_LO12_NC, 0x234) +ELF_RELOC(R_AARCH64_TLSDESC_OFF_G1, 0x235) +ELF_RELOC(R_AARCH64_TLSDESC_OFF_G0_NC, 0x236) +ELF_RELOC(R_AARCH64_TLSDESC_LDR, 0x237) +ELF_RELOC(R_AARCH64_TLSDESC_ADD, 0x238) +ELF_RELOC(R_AARCH64_TLSDESC_CALL, 0x239) + +ELF_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12, 0x23a) +ELF_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC, 0x23b) + +ELF_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12, 0x23c) +ELF_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC, 0x23d) + +ELF_RELOC(R_AARCH64_COPY, 0x400) +ELF_RELOC(R_AARCH64_GLOB_DAT, 0x401) +ELF_RELOC(R_AARCH64_JUMP_SLOT, 0x402) +ELF_RELOC(R_AARCH64_RELATIVE, 0x403) +ELF_RELOC(R_AARCH64_TLS_DTPREL64, 0x404) +ELF_RELOC(R_AARCH64_TLS_DTPMOD64, 0x405) +ELF_RELOC(R_AARCH64_TLS_TPREL64, 0x406) +ELF_RELOC(R_AARCH64_TLSDESC, 0x407) +ELF_RELOC(R_AARCH64_IRELATIVE, 0x408)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AMDGPU.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AMDGPU.def new file mode 100644 index 0000000..c1e6797 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AMDGPU.def
@@ -0,0 +1,12 @@ +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_AMDGPU_NONE, 0) +ELF_RELOC(R_AMDGPU_ABS32_LO, 1) +ELF_RELOC(R_AMDGPU_ABS32_HI, 2) +ELF_RELOC(R_AMDGPU_ABS64, 3) +ELF_RELOC(R_AMDGPU_REL32, 4) +ELF_RELOC(R_AMDGPU_REL64, 5) +ELF_RELOC(R_AMDGPU_ABS32, 6) +ELF_RELOC(R_AMDGPU_GOTPCREL, 7)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/ARM.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/ARM.def new file mode 100644 index 0000000..730fc5b --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/ARM.def
@@ -0,0 +1,138 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +// Meets 2.09 ABI Specs. +ELF_RELOC(R_ARM_NONE, 0x00) +ELF_RELOC(R_ARM_PC24, 0x01) +ELF_RELOC(R_ARM_ABS32, 0x02) +ELF_RELOC(R_ARM_REL32, 0x03) +ELF_RELOC(R_ARM_LDR_PC_G0, 0x04) +ELF_RELOC(R_ARM_ABS16, 0x05) +ELF_RELOC(R_ARM_ABS12, 0x06) +ELF_RELOC(R_ARM_THM_ABS5, 0x07) +ELF_RELOC(R_ARM_ABS8, 0x08) +ELF_RELOC(R_ARM_SBREL32, 0x09) +ELF_RELOC(R_ARM_THM_CALL, 0x0a) +ELF_RELOC(R_ARM_THM_PC8, 0x0b) +ELF_RELOC(R_ARM_BREL_ADJ, 0x0c) +ELF_RELOC(R_ARM_TLS_DESC, 0x0d) +ELF_RELOC(R_ARM_THM_SWI8, 0x0e) +ELF_RELOC(R_ARM_XPC25, 0x0f) +ELF_RELOC(R_ARM_THM_XPC22, 0x10) +ELF_RELOC(R_ARM_TLS_DTPMOD32, 0x11) +ELF_RELOC(R_ARM_TLS_DTPOFF32, 0x12) +ELF_RELOC(R_ARM_TLS_TPOFF32, 0x13) +ELF_RELOC(R_ARM_COPY, 0x14) +ELF_RELOC(R_ARM_GLOB_DAT, 0x15) +ELF_RELOC(R_ARM_JUMP_SLOT, 0x16) +ELF_RELOC(R_ARM_RELATIVE, 0x17) +ELF_RELOC(R_ARM_GOTOFF32, 0x18) +ELF_RELOC(R_ARM_BASE_PREL, 0x19) +ELF_RELOC(R_ARM_GOT_BREL, 0x1a) +ELF_RELOC(R_ARM_PLT32, 0x1b) +ELF_RELOC(R_ARM_CALL, 0x1c) +ELF_RELOC(R_ARM_JUMP24, 0x1d) +ELF_RELOC(R_ARM_THM_JUMP24, 0x1e) +ELF_RELOC(R_ARM_BASE_ABS, 0x1f) +ELF_RELOC(R_ARM_ALU_PCREL_7_0, 0x20) +ELF_RELOC(R_ARM_ALU_PCREL_15_8, 0x21) +ELF_RELOC(R_ARM_ALU_PCREL_23_15, 0x22) +ELF_RELOC(R_ARM_LDR_SBREL_11_0_NC, 0x23) +ELF_RELOC(R_ARM_ALU_SBREL_19_12_NC, 0x24) +ELF_RELOC(R_ARM_ALU_SBREL_27_20_CK, 0x25) +ELF_RELOC(R_ARM_TARGET1, 0x26) +ELF_RELOC(R_ARM_SBREL31, 0x27) +ELF_RELOC(R_ARM_V4BX, 0x28) +ELF_RELOC(R_ARM_TARGET2, 0x29) +ELF_RELOC(R_ARM_PREL31, 0x2a) +ELF_RELOC(R_ARM_MOVW_ABS_NC, 0x2b) +ELF_RELOC(R_ARM_MOVT_ABS, 0x2c) +ELF_RELOC(R_ARM_MOVW_PREL_NC, 0x2d) +ELF_RELOC(R_ARM_MOVT_PREL, 0x2e) +ELF_RELOC(R_ARM_THM_MOVW_ABS_NC, 0x2f) +ELF_RELOC(R_ARM_THM_MOVT_ABS, 0x30) +ELF_RELOC(R_ARM_THM_MOVW_PREL_NC, 0x31) +ELF_RELOC(R_ARM_THM_MOVT_PREL, 0x32) +ELF_RELOC(R_ARM_THM_JUMP19, 0x33) +ELF_RELOC(R_ARM_THM_JUMP6, 0x34) +ELF_RELOC(R_ARM_THM_ALU_PREL_11_0, 0x35) +ELF_RELOC(R_ARM_THM_PC12, 0x36) +ELF_RELOC(R_ARM_ABS32_NOI, 0x37) +ELF_RELOC(R_ARM_REL32_NOI, 0x38) +ELF_RELOC(R_ARM_ALU_PC_G0_NC, 0x39) +ELF_RELOC(R_ARM_ALU_PC_G0, 0x3a) +ELF_RELOC(R_ARM_ALU_PC_G1_NC, 0x3b) +ELF_RELOC(R_ARM_ALU_PC_G1, 0x3c) +ELF_RELOC(R_ARM_ALU_PC_G2, 0x3d) +ELF_RELOC(R_ARM_LDR_PC_G1, 0x3e) +ELF_RELOC(R_ARM_LDR_PC_G2, 0x3f) +ELF_RELOC(R_ARM_LDRS_PC_G0, 0x40) +ELF_RELOC(R_ARM_LDRS_PC_G1, 0x41) +ELF_RELOC(R_ARM_LDRS_PC_G2, 0x42) +ELF_RELOC(R_ARM_LDC_PC_G0, 0x43) +ELF_RELOC(R_ARM_LDC_PC_G1, 0x44) +ELF_RELOC(R_ARM_LDC_PC_G2, 0x45) +ELF_RELOC(R_ARM_ALU_SB_G0_NC, 0x46) +ELF_RELOC(R_ARM_ALU_SB_G0, 0x47) +ELF_RELOC(R_ARM_ALU_SB_G1_NC, 0x48) +ELF_RELOC(R_ARM_ALU_SB_G1, 0x49) +ELF_RELOC(R_ARM_ALU_SB_G2, 0x4a) +ELF_RELOC(R_ARM_LDR_SB_G0, 0x4b) +ELF_RELOC(R_ARM_LDR_SB_G1, 0x4c) +ELF_RELOC(R_ARM_LDR_SB_G2, 0x4d) +ELF_RELOC(R_ARM_LDRS_SB_G0, 0x4e) +ELF_RELOC(R_ARM_LDRS_SB_G1, 0x4f) +ELF_RELOC(R_ARM_LDRS_SB_G2, 0x50) +ELF_RELOC(R_ARM_LDC_SB_G0, 0x51) +ELF_RELOC(R_ARM_LDC_SB_G1, 0x52) +ELF_RELOC(R_ARM_LDC_SB_G2, 0x53) +ELF_RELOC(R_ARM_MOVW_BREL_NC, 0x54) +ELF_RELOC(R_ARM_MOVT_BREL, 0x55) +ELF_RELOC(R_ARM_MOVW_BREL, 0x56) +ELF_RELOC(R_ARM_THM_MOVW_BREL_NC, 0x57) +ELF_RELOC(R_ARM_THM_MOVT_BREL, 0x58) +ELF_RELOC(R_ARM_THM_MOVW_BREL, 0x59) +ELF_RELOC(R_ARM_TLS_GOTDESC, 0x5a) +ELF_RELOC(R_ARM_TLS_CALL, 0x5b) +ELF_RELOC(R_ARM_TLS_DESCSEQ, 0x5c) +ELF_RELOC(R_ARM_THM_TLS_CALL, 0x5d) +ELF_RELOC(R_ARM_PLT32_ABS, 0x5e) +ELF_RELOC(R_ARM_GOT_ABS, 0x5f) +ELF_RELOC(R_ARM_GOT_PREL, 0x60) +ELF_RELOC(R_ARM_GOT_BREL12, 0x61) +ELF_RELOC(R_ARM_GOTOFF12, 0x62) +ELF_RELOC(R_ARM_GOTRELAX, 0x63) +ELF_RELOC(R_ARM_GNU_VTENTRY, 0x64) +ELF_RELOC(R_ARM_GNU_VTINHERIT, 0x65) +ELF_RELOC(R_ARM_THM_JUMP11, 0x66) +ELF_RELOC(R_ARM_THM_JUMP8, 0x67) +ELF_RELOC(R_ARM_TLS_GD32, 0x68) +ELF_RELOC(R_ARM_TLS_LDM32, 0x69) +ELF_RELOC(R_ARM_TLS_LDO32, 0x6a) +ELF_RELOC(R_ARM_TLS_IE32, 0x6b) +ELF_RELOC(R_ARM_TLS_LE32, 0x6c) +ELF_RELOC(R_ARM_TLS_LDO12, 0x6d) +ELF_RELOC(R_ARM_TLS_LE12, 0x6e) +ELF_RELOC(R_ARM_TLS_IE12GP, 0x6f) +ELF_RELOC(R_ARM_PRIVATE_0, 0x70) +ELF_RELOC(R_ARM_PRIVATE_1, 0x71) +ELF_RELOC(R_ARM_PRIVATE_2, 0x72) +ELF_RELOC(R_ARM_PRIVATE_3, 0x73) +ELF_RELOC(R_ARM_PRIVATE_4, 0x74) +ELF_RELOC(R_ARM_PRIVATE_5, 0x75) +ELF_RELOC(R_ARM_PRIVATE_6, 0x76) +ELF_RELOC(R_ARM_PRIVATE_7, 0x77) +ELF_RELOC(R_ARM_PRIVATE_8, 0x78) +ELF_RELOC(R_ARM_PRIVATE_9, 0x79) +ELF_RELOC(R_ARM_PRIVATE_10, 0x7a) +ELF_RELOC(R_ARM_PRIVATE_11, 0x7b) +ELF_RELOC(R_ARM_PRIVATE_12, 0x7c) +ELF_RELOC(R_ARM_PRIVATE_13, 0x7d) +ELF_RELOC(R_ARM_PRIVATE_14, 0x7e) +ELF_RELOC(R_ARM_PRIVATE_15, 0x7f) +ELF_RELOC(R_ARM_ME_TOO, 0x80) +ELF_RELOC(R_ARM_THM_TLS_DESCSEQ16, 0x81) +ELF_RELOC(R_ARM_THM_TLS_DESCSEQ32, 0x82) +ELF_RELOC(R_ARM_IRELATIVE, 0xa0)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AVR.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AVR.def new file mode 100644 index 0000000..5692d6c --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/AVR.def
@@ -0,0 +1,40 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_AVR_NONE, 0) +ELF_RELOC(R_AVR_32, 1) +ELF_RELOC(R_AVR_7_PCREL, 2) +ELF_RELOC(R_AVR_13_PCREL, 3) +ELF_RELOC(R_AVR_16, 4) +ELF_RELOC(R_AVR_16_PM, 5) +ELF_RELOC(R_AVR_LO8_LDI, 6) +ELF_RELOC(R_AVR_HI8_LDI, 7) +ELF_RELOC(R_AVR_HH8_LDI, 8) +ELF_RELOC(R_AVR_LO8_LDI_NEG, 9) +ELF_RELOC(R_AVR_HI8_LDI_NEG, 10) +ELF_RELOC(R_AVR_HH8_LDI_NEG, 11) +ELF_RELOC(R_AVR_LO8_LDI_PM, 12) +ELF_RELOC(R_AVR_HI8_LDI_PM, 13) +ELF_RELOC(R_AVR_HH8_LDI_PM, 14) +ELF_RELOC(R_AVR_LO8_LDI_PM_NEG, 15) +ELF_RELOC(R_AVR_HI8_LDI_PM_NEG, 16) +ELF_RELOC(R_AVR_HH8_LDI_PM_NEG, 17) +ELF_RELOC(R_AVR_CALL, 18) +ELF_RELOC(R_AVR_LDI, 19) +ELF_RELOC(R_AVR_6, 20) +ELF_RELOC(R_AVR_6_ADIW, 21) +ELF_RELOC(R_AVR_MS8_LDI, 22) +ELF_RELOC(R_AVR_MS8_LDI_NEG, 23) +ELF_RELOC(R_AVR_LO8_LDI_GS, 24) +ELF_RELOC(R_AVR_HI8_LDI_GS, 25) +ELF_RELOC(R_AVR_8, 26) +ELF_RELOC(R_AVR_8_LO8, 27) +ELF_RELOC(R_AVR_8_HI8, 28) +ELF_RELOC(R_AVR_8_HLO8, 29) +ELF_RELOC(R_AVR_SYM_DIFF, 30) +ELF_RELOC(R_AVR_16_LDST, 31) +ELF_RELOC(R_AVR_LDS_STS_16, 33) +ELF_RELOC(R_AVR_PORT6, 34) +ELF_RELOC(R_AVR_PORT5, 35)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/BPF.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/BPF.def new file mode 100644 index 0000000..868974d --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/BPF.def
@@ -0,0 +1,9 @@ +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +// No relocation +ELF_RELOC(R_BPF_NONE, 0) +// Map index in "maps" section to file descriptor +// within ld_64 instruction. +ELF_RELOC(R_BPF_MAP_FD, 1)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Hexagon.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Hexagon.def new file mode 100644 index 0000000..74e1d40 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Hexagon.def
@@ -0,0 +1,101 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +// Release 5 ABI +ELF_RELOC(R_HEX_NONE, 0) +ELF_RELOC(R_HEX_B22_PCREL, 1) +ELF_RELOC(R_HEX_B15_PCREL, 2) +ELF_RELOC(R_HEX_B7_PCREL, 3) +ELF_RELOC(R_HEX_LO16, 4) +ELF_RELOC(R_HEX_HI16, 5) +ELF_RELOC(R_HEX_32, 6) +ELF_RELOC(R_HEX_16, 7) +ELF_RELOC(R_HEX_8, 8) +ELF_RELOC(R_HEX_GPREL16_0, 9) +ELF_RELOC(R_HEX_GPREL16_1, 10) +ELF_RELOC(R_HEX_GPREL16_2, 11) +ELF_RELOC(R_HEX_GPREL16_3, 12) +ELF_RELOC(R_HEX_HL16, 13) +ELF_RELOC(R_HEX_B13_PCREL, 14) +ELF_RELOC(R_HEX_B9_PCREL, 15) +ELF_RELOC(R_HEX_B32_PCREL_X, 16) +ELF_RELOC(R_HEX_32_6_X, 17) +ELF_RELOC(R_HEX_B22_PCREL_X, 18) +ELF_RELOC(R_HEX_B15_PCREL_X, 19) +ELF_RELOC(R_HEX_B13_PCREL_X, 20) +ELF_RELOC(R_HEX_B9_PCREL_X, 21) +ELF_RELOC(R_HEX_B7_PCREL_X, 22) +ELF_RELOC(R_HEX_16_X, 23) +ELF_RELOC(R_HEX_12_X, 24) +ELF_RELOC(R_HEX_11_X, 25) +ELF_RELOC(R_HEX_10_X, 26) +ELF_RELOC(R_HEX_9_X, 27) +ELF_RELOC(R_HEX_8_X, 28) +ELF_RELOC(R_HEX_7_X, 29) +ELF_RELOC(R_HEX_6_X, 30) +ELF_RELOC(R_HEX_32_PCREL, 31) +ELF_RELOC(R_HEX_COPY, 32) +ELF_RELOC(R_HEX_GLOB_DAT, 33) +ELF_RELOC(R_HEX_JMP_SLOT, 34) +ELF_RELOC(R_HEX_RELATIVE, 35) +ELF_RELOC(R_HEX_PLT_B22_PCREL, 36) +ELF_RELOC(R_HEX_GOTREL_LO16, 37) +ELF_RELOC(R_HEX_GOTREL_HI16, 38) +ELF_RELOC(R_HEX_GOTREL_32, 39) +ELF_RELOC(R_HEX_GOT_LO16, 40) +ELF_RELOC(R_HEX_GOT_HI16, 41) +ELF_RELOC(R_HEX_GOT_32, 42) +ELF_RELOC(R_HEX_GOT_16, 43) +ELF_RELOC(R_HEX_DTPMOD_32, 44) +ELF_RELOC(R_HEX_DTPREL_LO16, 45) +ELF_RELOC(R_HEX_DTPREL_HI16, 46) +ELF_RELOC(R_HEX_DTPREL_32, 47) +ELF_RELOC(R_HEX_DTPREL_16, 48) +ELF_RELOC(R_HEX_GD_PLT_B22_PCREL, 49) +ELF_RELOC(R_HEX_GD_GOT_LO16, 50) +ELF_RELOC(R_HEX_GD_GOT_HI16, 51) +ELF_RELOC(R_HEX_GD_GOT_32, 52) +ELF_RELOC(R_HEX_GD_GOT_16, 53) +ELF_RELOC(R_HEX_IE_LO16, 54) +ELF_RELOC(R_HEX_IE_HI16, 55) +ELF_RELOC(R_HEX_IE_32, 56) +ELF_RELOC(R_HEX_IE_GOT_LO16, 57) +ELF_RELOC(R_HEX_IE_GOT_HI16, 58) +ELF_RELOC(R_HEX_IE_GOT_32, 59) +ELF_RELOC(R_HEX_IE_GOT_16, 60) +ELF_RELOC(R_HEX_TPREL_LO16, 61) +ELF_RELOC(R_HEX_TPREL_HI16, 62) +ELF_RELOC(R_HEX_TPREL_32, 63) +ELF_RELOC(R_HEX_TPREL_16, 64) +ELF_RELOC(R_HEX_6_PCREL_X, 65) +ELF_RELOC(R_HEX_GOTREL_32_6_X, 66) +ELF_RELOC(R_HEX_GOTREL_16_X, 67) +ELF_RELOC(R_HEX_GOTREL_11_X, 68) +ELF_RELOC(R_HEX_GOT_32_6_X, 69) +ELF_RELOC(R_HEX_GOT_16_X, 70) +ELF_RELOC(R_HEX_GOT_11_X, 71) +ELF_RELOC(R_HEX_DTPREL_32_6_X, 72) +ELF_RELOC(R_HEX_DTPREL_16_X, 73) +ELF_RELOC(R_HEX_DTPREL_11_X, 74) +ELF_RELOC(R_HEX_GD_GOT_32_6_X, 75) +ELF_RELOC(R_HEX_GD_GOT_16_X, 76) +ELF_RELOC(R_HEX_GD_GOT_11_X, 77) +ELF_RELOC(R_HEX_IE_32_6_X, 78) +ELF_RELOC(R_HEX_IE_16_X, 79) +ELF_RELOC(R_HEX_IE_GOT_32_6_X, 80) +ELF_RELOC(R_HEX_IE_GOT_16_X, 81) +ELF_RELOC(R_HEX_IE_GOT_11_X, 82) +ELF_RELOC(R_HEX_TPREL_32_6_X, 83) +ELF_RELOC(R_HEX_TPREL_16_X, 84) +ELF_RELOC(R_HEX_TPREL_11_X, 85) +ELF_RELOC(R_HEX_LD_PLT_B22_PCREL, 86) +ELF_RELOC(R_HEX_LD_GOT_LO16, 87) +ELF_RELOC(R_HEX_LD_GOT_HI16, 88) +ELF_RELOC(R_HEX_LD_GOT_32, 89) +ELF_RELOC(R_HEX_LD_GOT_16, 90) +ELF_RELOC(R_HEX_LD_GOT_32_6_X, 91) +ELF_RELOC(R_HEX_LD_GOT_16_X, 92) +ELF_RELOC(R_HEX_LD_GOT_11_X, 93) +ELF_RELOC(R_HEX_23_REG, 94)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Lanai.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Lanai.def new file mode 100644 index 0000000..77ecb04 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Lanai.def
@@ -0,0 +1,19 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +// No relocation +ELF_RELOC(R_LANAI_NONE, 0) +// 21-bit symbol relocation +ELF_RELOC(R_LANAI_21, 1) +// 21-bit symbol relocation with last two bits masked to 0 +ELF_RELOC(R_LANAI_21_F, 2) +// 25-bit branch targets +ELF_RELOC(R_LANAI_25, 3) +// General 32-bit relocation +ELF_RELOC(R_LANAI_32, 4) +// Upper 16-bits of a symbolic relocation +ELF_RELOC(R_LANAI_HI16, 5) +// Lower 16-bits of a symbolic relocation +ELF_RELOC(R_LANAI_LO16, 6)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Mips.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Mips.def new file mode 100644 index 0000000..bc0088d --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Mips.def
@@ -0,0 +1,117 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_MIPS_NONE, 0) +ELF_RELOC(R_MIPS_16, 1) +ELF_RELOC(R_MIPS_32, 2) +ELF_RELOC(R_MIPS_REL32, 3) +ELF_RELOC(R_MIPS_26, 4) +ELF_RELOC(R_MIPS_HI16, 5) +ELF_RELOC(R_MIPS_LO16, 6) +ELF_RELOC(R_MIPS_GPREL16, 7) +ELF_RELOC(R_MIPS_LITERAL, 8) +ELF_RELOC(R_MIPS_GOT16, 9) +ELF_RELOC(R_MIPS_PC16, 10) +ELF_RELOC(R_MIPS_CALL16, 11) +ELF_RELOC(R_MIPS_GPREL32, 12) +ELF_RELOC(R_MIPS_UNUSED1, 13) +ELF_RELOC(R_MIPS_UNUSED2, 14) +ELF_RELOC(R_MIPS_UNUSED3, 15) +ELF_RELOC(R_MIPS_SHIFT5, 16) +ELF_RELOC(R_MIPS_SHIFT6, 17) +ELF_RELOC(R_MIPS_64, 18) +ELF_RELOC(R_MIPS_GOT_DISP, 19) +ELF_RELOC(R_MIPS_GOT_PAGE, 20) +ELF_RELOC(R_MIPS_GOT_OFST, 21) +ELF_RELOC(R_MIPS_GOT_HI16, 22) +ELF_RELOC(R_MIPS_GOT_LO16, 23) +ELF_RELOC(R_MIPS_SUB, 24) +ELF_RELOC(R_MIPS_INSERT_A, 25) +ELF_RELOC(R_MIPS_INSERT_B, 26) +ELF_RELOC(R_MIPS_DELETE, 27) +ELF_RELOC(R_MIPS_HIGHER, 28) +ELF_RELOC(R_MIPS_HIGHEST, 29) +ELF_RELOC(R_MIPS_CALL_HI16, 30) +ELF_RELOC(R_MIPS_CALL_LO16, 31) +ELF_RELOC(R_MIPS_SCN_DISP, 32) +ELF_RELOC(R_MIPS_REL16, 33) +ELF_RELOC(R_MIPS_ADD_IMMEDIATE, 34) +ELF_RELOC(R_MIPS_PJUMP, 35) +ELF_RELOC(R_MIPS_RELGOT, 36) +ELF_RELOC(R_MIPS_JALR, 37) +ELF_RELOC(R_MIPS_TLS_DTPMOD32, 38) +ELF_RELOC(R_MIPS_TLS_DTPREL32, 39) +ELF_RELOC(R_MIPS_TLS_DTPMOD64, 40) +ELF_RELOC(R_MIPS_TLS_DTPREL64, 41) +ELF_RELOC(R_MIPS_TLS_GD, 42) +ELF_RELOC(R_MIPS_TLS_LDM, 43) +ELF_RELOC(R_MIPS_TLS_DTPREL_HI16, 44) +ELF_RELOC(R_MIPS_TLS_DTPREL_LO16, 45) +ELF_RELOC(R_MIPS_TLS_GOTTPREL, 46) +ELF_RELOC(R_MIPS_TLS_TPREL32, 47) +ELF_RELOC(R_MIPS_TLS_TPREL64, 48) +ELF_RELOC(R_MIPS_TLS_TPREL_HI16, 49) +ELF_RELOC(R_MIPS_TLS_TPREL_LO16, 50) +ELF_RELOC(R_MIPS_GLOB_DAT, 51) +ELF_RELOC(R_MIPS_PC21_S2, 60) +ELF_RELOC(R_MIPS_PC26_S2, 61) +ELF_RELOC(R_MIPS_PC18_S3, 62) +ELF_RELOC(R_MIPS_PC19_S2, 63) +ELF_RELOC(R_MIPS_PCHI16, 64) +ELF_RELOC(R_MIPS_PCLO16, 65) +ELF_RELOC(R_MIPS16_26, 100) +ELF_RELOC(R_MIPS16_GPREL, 101) +ELF_RELOC(R_MIPS16_GOT16, 102) +ELF_RELOC(R_MIPS16_CALL16, 103) +ELF_RELOC(R_MIPS16_HI16, 104) +ELF_RELOC(R_MIPS16_LO16, 105) +ELF_RELOC(R_MIPS16_TLS_GD, 106) +ELF_RELOC(R_MIPS16_TLS_LDM, 107) +ELF_RELOC(R_MIPS16_TLS_DTPREL_HI16, 108) +ELF_RELOC(R_MIPS16_TLS_DTPREL_LO16, 109) +ELF_RELOC(R_MIPS16_TLS_GOTTPREL, 110) +ELF_RELOC(R_MIPS16_TLS_TPREL_HI16, 111) +ELF_RELOC(R_MIPS16_TLS_TPREL_LO16, 112) +ELF_RELOC(R_MIPS_COPY, 126) +ELF_RELOC(R_MIPS_JUMP_SLOT, 127) +ELF_RELOC(R_MICROMIPS_26_S1, 133) +ELF_RELOC(R_MICROMIPS_HI16, 134) +ELF_RELOC(R_MICROMIPS_LO16, 135) +ELF_RELOC(R_MICROMIPS_GPREL16, 136) +ELF_RELOC(R_MICROMIPS_LITERAL, 137) +ELF_RELOC(R_MICROMIPS_GOT16, 138) +ELF_RELOC(R_MICROMIPS_PC7_S1, 139) +ELF_RELOC(R_MICROMIPS_PC10_S1, 140) +ELF_RELOC(R_MICROMIPS_PC16_S1, 141) +ELF_RELOC(R_MICROMIPS_CALL16, 142) +ELF_RELOC(R_MICROMIPS_GOT_DISP, 145) +ELF_RELOC(R_MICROMIPS_GOT_PAGE, 146) +ELF_RELOC(R_MICROMIPS_GOT_OFST, 147) +ELF_RELOC(R_MICROMIPS_GOT_HI16, 148) +ELF_RELOC(R_MICROMIPS_GOT_LO16, 149) +ELF_RELOC(R_MICROMIPS_SUB, 150) +ELF_RELOC(R_MICROMIPS_HIGHER, 151) +ELF_RELOC(R_MICROMIPS_HIGHEST, 152) +ELF_RELOC(R_MICROMIPS_CALL_HI16, 153) +ELF_RELOC(R_MICROMIPS_CALL_LO16, 154) +ELF_RELOC(R_MICROMIPS_SCN_DISP, 155) +ELF_RELOC(R_MICROMIPS_JALR, 156) +ELF_RELOC(R_MICROMIPS_HI0_LO16, 157) +ELF_RELOC(R_MICROMIPS_TLS_GD, 162) +ELF_RELOC(R_MICROMIPS_TLS_LDM, 163) +ELF_RELOC(R_MICROMIPS_TLS_DTPREL_HI16, 164) +ELF_RELOC(R_MICROMIPS_TLS_DTPREL_LO16, 165) +ELF_RELOC(R_MICROMIPS_TLS_GOTTPREL, 166) +ELF_RELOC(R_MICROMIPS_TLS_TPREL_HI16, 169) +ELF_RELOC(R_MICROMIPS_TLS_TPREL_LO16, 170) +ELF_RELOC(R_MICROMIPS_GPREL7_S2, 172) +ELF_RELOC(R_MICROMIPS_PC23_S2, 173) +ELF_RELOC(R_MICROMIPS_PC21_S1, 174) +ELF_RELOC(R_MICROMIPS_PC26_S1, 175) +ELF_RELOC(R_MICROMIPS_PC18_S3, 176) +ELF_RELOC(R_MICROMIPS_PC19_S2, 177) +ELF_RELOC(R_MIPS_NUM, 218) +ELF_RELOC(R_MIPS_PC32, 248) +ELF_RELOC(R_MIPS_EH, 249)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/PowerPC.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/PowerPC.def new file mode 100644 index 0000000..e4f8ee0 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/PowerPC.def
@@ -0,0 +1,123 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +// glibc's PowerPC asm/sigcontext.h, when compiling for PPC64, has the +// unfortunate behavior of including asm/elf.h, which defines R_PPC_NONE, etc. +// to their corresponding integer values. As a result, we need to undef them +// here before continuing. + +#undef R_PPC_NONE +#undef R_PPC_ADDR32 +#undef R_PPC_ADDR24 +#undef R_PPC_ADDR16 +#undef R_PPC_ADDR16_LO +#undef R_PPC_ADDR16_HI +#undef R_PPC_ADDR16_HA +#undef R_PPC_ADDR14 +#undef R_PPC_ADDR14_BRTAKEN +#undef R_PPC_ADDR14_BRNTAKEN +#undef R_PPC_REL24 +#undef R_PPC_REL14 +#undef R_PPC_REL14_BRTAKEN +#undef R_PPC_REL14_BRNTAKEN +#undef R_PPC_GOT16 +#undef R_PPC_GOT16_LO +#undef R_PPC_GOT16_HI +#undef R_PPC_GOT16_HA +#undef R_PPC_PLTREL24 +#undef R_PPC_JMP_SLOT +#undef R_PPC_LOCAL24PC +#undef R_PPC_REL32 +#undef R_PPC_TLS +#undef R_PPC_DTPMOD32 +#undef R_PPC_TPREL16 +#undef R_PPC_TPREL16_LO +#undef R_PPC_TPREL16_HI +#undef R_PPC_TPREL16_HA +#undef R_PPC_TPREL32 +#undef R_PPC_DTPREL16 +#undef R_PPC_DTPREL16_LO +#undef R_PPC_DTPREL16_HI +#undef R_PPC_DTPREL16_HA +#undef R_PPC_DTPREL32 +#undef R_PPC_GOT_TLSGD16 +#undef R_PPC_GOT_TLSGD16_LO +#undef R_PPC_GOT_TLSGD16_HI +#undef R_PPC_GOT_TLSGD16_HA +#undef R_PPC_GOT_TLSLD16 +#undef R_PPC_GOT_TLSLD16_LO +#undef R_PPC_GOT_TLSLD16_HI +#undef R_PPC_GOT_TLSLD16_HA +#undef R_PPC_GOT_TPREL16 +#undef R_PPC_GOT_TPREL16_LO +#undef R_PPC_GOT_TPREL16_HI +#undef R_PPC_GOT_TPREL16_HA +#undef R_PPC_GOT_DTPREL16 +#undef R_PPC_GOT_DTPREL16_LO +#undef R_PPC_GOT_DTPREL16_HI +#undef R_PPC_GOT_DTPREL16_HA +#undef R_PPC_TLSGD +#undef R_PPC_TLSLD +#undef R_PPC_REL16 +#undef R_PPC_REL16_LO +#undef R_PPC_REL16_HI +#undef R_PPC_REL16_HA + +ELF_RELOC(R_PPC_NONE, 0) /* No relocation. */ +ELF_RELOC(R_PPC_ADDR32, 1) +ELF_RELOC(R_PPC_ADDR24, 2) +ELF_RELOC(R_PPC_ADDR16, 3) +ELF_RELOC(R_PPC_ADDR16_LO, 4) +ELF_RELOC(R_PPC_ADDR16_HI, 5) +ELF_RELOC(R_PPC_ADDR16_HA, 6) +ELF_RELOC(R_PPC_ADDR14, 7) +ELF_RELOC(R_PPC_ADDR14_BRTAKEN, 8) +ELF_RELOC(R_PPC_ADDR14_BRNTAKEN, 9) +ELF_RELOC(R_PPC_REL24, 10) +ELF_RELOC(R_PPC_REL14, 11) +ELF_RELOC(R_PPC_REL14_BRTAKEN, 12) +ELF_RELOC(R_PPC_REL14_BRNTAKEN, 13) +ELF_RELOC(R_PPC_GOT16, 14) +ELF_RELOC(R_PPC_GOT16_LO, 15) +ELF_RELOC(R_PPC_GOT16_HI, 16) +ELF_RELOC(R_PPC_GOT16_HA, 17) +ELF_RELOC(R_PPC_PLTREL24, 18) +ELF_RELOC(R_PPC_JMP_SLOT, 21) +ELF_RELOC(R_PPC_LOCAL24PC, 23) +ELF_RELOC(R_PPC_REL32, 26) +ELF_RELOC(R_PPC_TLS, 67) +ELF_RELOC(R_PPC_DTPMOD32, 68) +ELF_RELOC(R_PPC_TPREL16, 69) +ELF_RELOC(R_PPC_TPREL16_LO, 70) +ELF_RELOC(R_PPC_TPREL16_HI, 71) +ELF_RELOC(R_PPC_TPREL16_HA, 72) +ELF_RELOC(R_PPC_TPREL32, 73) +ELF_RELOC(R_PPC_DTPREL16, 74) +ELF_RELOC(R_PPC_DTPREL16_LO, 75) +ELF_RELOC(R_PPC_DTPREL16_HI, 76) +ELF_RELOC(R_PPC_DTPREL16_HA, 77) +ELF_RELOC(R_PPC_DTPREL32, 78) +ELF_RELOC(R_PPC_GOT_TLSGD16, 79) +ELF_RELOC(R_PPC_GOT_TLSGD16_LO, 80) +ELF_RELOC(R_PPC_GOT_TLSGD16_HI, 81) +ELF_RELOC(R_PPC_GOT_TLSGD16_HA, 82) +ELF_RELOC(R_PPC_GOT_TLSLD16, 83) +ELF_RELOC(R_PPC_GOT_TLSLD16_LO, 84) +ELF_RELOC(R_PPC_GOT_TLSLD16_HI, 85) +ELF_RELOC(R_PPC_GOT_TLSLD16_HA, 86) +ELF_RELOC(R_PPC_GOT_TPREL16, 87) +ELF_RELOC(R_PPC_GOT_TPREL16_LO, 88) +ELF_RELOC(R_PPC_GOT_TPREL16_HI, 89) +ELF_RELOC(R_PPC_GOT_TPREL16_HA, 90) +ELF_RELOC(R_PPC_GOT_DTPREL16, 91) +ELF_RELOC(R_PPC_GOT_DTPREL16_LO, 92) +ELF_RELOC(R_PPC_GOT_DTPREL16_HI, 93) +ELF_RELOC(R_PPC_GOT_DTPREL16_HA, 94) +ELF_RELOC(R_PPC_TLSGD, 95) +ELF_RELOC(R_PPC_TLSLD, 96) +ELF_RELOC(R_PPC_REL16, 249) +ELF_RELOC(R_PPC_REL16_LO, 250) +ELF_RELOC(R_PPC_REL16_HI, 251) +ELF_RELOC(R_PPC_REL16_HA, 252)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/PowerPC64.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/PowerPC64.def new file mode 100644 index 0000000..3a47c5a --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/PowerPC64.def
@@ -0,0 +1,181 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +// glibc's PowerPC asm/sigcontext.h, when compiling for PPC64, has the +// unfortunate behavior of including asm/elf.h, which defines R_PPC_NONE, etc. +// to their corresponding integer values. As a result, we need to undef them +// here before continuing. + +#undef R_PPC64_NONE +#undef R_PPC64_ADDR32 +#undef R_PPC64_ADDR24 +#undef R_PPC64_ADDR16 +#undef R_PPC64_ADDR16_LO +#undef R_PPC64_ADDR16_HI +#undef R_PPC64_ADDR16_HA +#undef R_PPC64_ADDR14 +#undef R_PPC64_ADDR14_BRTAKEN +#undef R_PPC64_ADDR14_BRNTAKEN +#undef R_PPC64_REL24 +#undef R_PPC64_REL14 +#undef R_PPC64_REL14_BRTAKEN +#undef R_PPC64_REL14_BRNTAKEN +#undef R_PPC64_GOT16 +#undef R_PPC64_GOT16_LO +#undef R_PPC64_GOT16_HI +#undef R_PPC64_GOT16_HA +#undef R_PPC64_GLOB_DAT +#undef R_PPC64_JMP_SLOT +#undef R_PPC64_RELATIVE +#undef R_PPC64_REL32 +#undef R_PPC64_ADDR64 +#undef R_PPC64_ADDR16_HIGHER +#undef R_PPC64_ADDR16_HIGHERA +#undef R_PPC64_ADDR16_HIGHEST +#undef R_PPC64_ADDR16_HIGHESTA +#undef R_PPC64_REL64 +#undef R_PPC64_TOC16 +#undef R_PPC64_TOC16_LO +#undef R_PPC64_TOC16_HI +#undef R_PPC64_TOC16_HA +#undef R_PPC64_TOC +#undef R_PPC64_ADDR16_DS +#undef R_PPC64_ADDR16_LO_DS +#undef R_PPC64_GOT16_DS +#undef R_PPC64_GOT16_LO_DS +#undef R_PPC64_TOC16_DS +#undef R_PPC64_TOC16_LO_DS +#undef R_PPC64_TLS +#undef R_PPC64_DTPMOD64 +#undef R_PPC64_TPREL16 +#undef R_PPC64_TPREL16_LO +#undef R_PPC64_TPREL16_HI +#undef R_PPC64_TPREL16_HA +#undef R_PPC64_TPREL64 +#undef R_PPC64_DTPREL16 +#undef R_PPC64_DTPREL16_LO +#undef R_PPC64_DTPREL16_HI +#undef R_PPC64_DTPREL16_HA +#undef R_PPC64_DTPREL64 +#undef R_PPC64_GOT_TLSGD16 +#undef R_PPC64_GOT_TLSGD16_LO +#undef R_PPC64_GOT_TLSGD16_HI +#undef R_PPC64_GOT_TLSGD16_HA +#undef R_PPC64_GOT_TLSLD16 +#undef R_PPC64_GOT_TLSLD16_LO +#undef R_PPC64_GOT_TLSLD16_HI +#undef R_PPC64_GOT_TLSLD16_HA +#undef R_PPC64_GOT_TPREL16_DS +#undef R_PPC64_GOT_TPREL16_LO_DS +#undef R_PPC64_GOT_TPREL16_HI +#undef R_PPC64_GOT_TPREL16_HA +#undef R_PPC64_GOT_DTPREL16_DS +#undef R_PPC64_GOT_DTPREL16_LO_DS +#undef R_PPC64_GOT_DTPREL16_HI +#undef R_PPC64_GOT_DTPREL16_HA +#undef R_PPC64_TPREL16_DS +#undef R_PPC64_TPREL16_LO_DS +#undef R_PPC64_TPREL16_HIGHER +#undef R_PPC64_TPREL16_HIGHERA +#undef R_PPC64_TPREL16_HIGHEST +#undef R_PPC64_TPREL16_HIGHESTA +#undef R_PPC64_DTPREL16_DS +#undef R_PPC64_DTPREL16_LO_DS +#undef R_PPC64_DTPREL16_HIGHER +#undef R_PPC64_DTPREL16_HIGHERA +#undef R_PPC64_DTPREL16_HIGHEST +#undef R_PPC64_DTPREL16_HIGHESTA +#undef R_PPC64_TLSGD +#undef R_PPC64_TLSLD +#undef R_PPC64_REL16 +#undef R_PPC64_REL16_LO +#undef R_PPC64_REL16_HI +#undef R_PPC64_REL16_HA + +ELF_RELOC(R_PPC64_NONE, 0) +ELF_RELOC(R_PPC64_ADDR32, 1) +ELF_RELOC(R_PPC64_ADDR24, 2) +ELF_RELOC(R_PPC64_ADDR16, 3) +ELF_RELOC(R_PPC64_ADDR16_LO, 4) +ELF_RELOC(R_PPC64_ADDR16_HI, 5) +ELF_RELOC(R_PPC64_ADDR16_HA, 6) +ELF_RELOC(R_PPC64_ADDR14, 7) +ELF_RELOC(R_PPC64_ADDR14_BRTAKEN, 8) +ELF_RELOC(R_PPC64_ADDR14_BRNTAKEN, 9) +ELF_RELOC(R_PPC64_REL24, 10) +ELF_RELOC(R_PPC64_REL14, 11) +ELF_RELOC(R_PPC64_REL14_BRTAKEN, 12) +ELF_RELOC(R_PPC64_REL14_BRNTAKEN, 13) +ELF_RELOC(R_PPC64_GOT16, 14) +ELF_RELOC(R_PPC64_GOT16_LO, 15) +ELF_RELOC(R_PPC64_GOT16_HI, 16) +ELF_RELOC(R_PPC64_GOT16_HA, 17) +ELF_RELOC(R_PPC64_GLOB_DAT, 20) +ELF_RELOC(R_PPC64_JMP_SLOT, 21) +ELF_RELOC(R_PPC64_RELATIVE, 22) +ELF_RELOC(R_PPC64_REL32, 26) +ELF_RELOC(R_PPC64_ADDR64, 38) +ELF_RELOC(R_PPC64_ADDR16_HIGHER, 39) +ELF_RELOC(R_PPC64_ADDR16_HIGHERA, 40) +ELF_RELOC(R_PPC64_ADDR16_HIGHEST, 41) +ELF_RELOC(R_PPC64_ADDR16_HIGHESTA, 42) +ELF_RELOC(R_PPC64_REL64, 44) +ELF_RELOC(R_PPC64_TOC16, 47) +ELF_RELOC(R_PPC64_TOC16_LO, 48) +ELF_RELOC(R_PPC64_TOC16_HI, 49) +ELF_RELOC(R_PPC64_TOC16_HA, 50) +ELF_RELOC(R_PPC64_TOC, 51) +ELF_RELOC(R_PPC64_ADDR16_DS, 56) +ELF_RELOC(R_PPC64_ADDR16_LO_DS, 57) +ELF_RELOC(R_PPC64_GOT16_DS, 58) +ELF_RELOC(R_PPC64_GOT16_LO_DS, 59) +ELF_RELOC(R_PPC64_TOC16_DS, 63) +ELF_RELOC(R_PPC64_TOC16_LO_DS, 64) +ELF_RELOC(R_PPC64_TLS, 67) +ELF_RELOC(R_PPC64_DTPMOD64, 68) +ELF_RELOC(R_PPC64_TPREL16, 69) +ELF_RELOC(R_PPC64_TPREL16_LO, 70) +ELF_RELOC(R_PPC64_TPREL16_HI, 71) +ELF_RELOC(R_PPC64_TPREL16_HA, 72) +ELF_RELOC(R_PPC64_TPREL64, 73) +ELF_RELOC(R_PPC64_DTPREL16, 74) +ELF_RELOC(R_PPC64_DTPREL16_LO, 75) +ELF_RELOC(R_PPC64_DTPREL16_HI, 76) +ELF_RELOC(R_PPC64_DTPREL16_HA, 77) +ELF_RELOC(R_PPC64_DTPREL64, 78) +ELF_RELOC(R_PPC64_GOT_TLSGD16, 79) +ELF_RELOC(R_PPC64_GOT_TLSGD16_LO, 80) +ELF_RELOC(R_PPC64_GOT_TLSGD16_HI, 81) +ELF_RELOC(R_PPC64_GOT_TLSGD16_HA, 82) +ELF_RELOC(R_PPC64_GOT_TLSLD16, 83) +ELF_RELOC(R_PPC64_GOT_TLSLD16_LO, 84) +ELF_RELOC(R_PPC64_GOT_TLSLD16_HI, 85) +ELF_RELOC(R_PPC64_GOT_TLSLD16_HA, 86) +ELF_RELOC(R_PPC64_GOT_TPREL16_DS, 87) +ELF_RELOC(R_PPC64_GOT_TPREL16_LO_DS, 88) +ELF_RELOC(R_PPC64_GOT_TPREL16_HI, 89) +ELF_RELOC(R_PPC64_GOT_TPREL16_HA, 90) +ELF_RELOC(R_PPC64_GOT_DTPREL16_DS, 91) +ELF_RELOC(R_PPC64_GOT_DTPREL16_LO_DS, 92) +ELF_RELOC(R_PPC64_GOT_DTPREL16_HI, 93) +ELF_RELOC(R_PPC64_GOT_DTPREL16_HA, 94) +ELF_RELOC(R_PPC64_TPREL16_DS, 95) +ELF_RELOC(R_PPC64_TPREL16_LO_DS, 96) +ELF_RELOC(R_PPC64_TPREL16_HIGHER, 97) +ELF_RELOC(R_PPC64_TPREL16_HIGHERA, 98) +ELF_RELOC(R_PPC64_TPREL16_HIGHEST, 99) +ELF_RELOC(R_PPC64_TPREL16_HIGHESTA, 100) +ELF_RELOC(R_PPC64_DTPREL16_DS, 101) +ELF_RELOC(R_PPC64_DTPREL16_LO_DS, 102) +ELF_RELOC(R_PPC64_DTPREL16_HIGHER, 103) +ELF_RELOC(R_PPC64_DTPREL16_HIGHERA, 104) +ELF_RELOC(R_PPC64_DTPREL16_HIGHEST, 105) +ELF_RELOC(R_PPC64_DTPREL16_HIGHESTA, 106) +ELF_RELOC(R_PPC64_TLSGD, 107) +ELF_RELOC(R_PPC64_TLSLD, 108) +ELF_RELOC(R_PPC64_REL16, 249) +ELF_RELOC(R_PPC64_REL16_LO, 250) +ELF_RELOC(R_PPC64_REL16_HI, 251) +ELF_RELOC(R_PPC64_REL16_HA, 252)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Sparc.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Sparc.def new file mode 100644 index 0000000..7e01a4a --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/Sparc.def
@@ -0,0 +1,89 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_SPARC_NONE, 0) +ELF_RELOC(R_SPARC_8, 1) +ELF_RELOC(R_SPARC_16, 2) +ELF_RELOC(R_SPARC_32, 3) +ELF_RELOC(R_SPARC_DISP8, 4) +ELF_RELOC(R_SPARC_DISP16, 5) +ELF_RELOC(R_SPARC_DISP32, 6) +ELF_RELOC(R_SPARC_WDISP30, 7) +ELF_RELOC(R_SPARC_WDISP22, 8) +ELF_RELOC(R_SPARC_HI22, 9) +ELF_RELOC(R_SPARC_22, 10) +ELF_RELOC(R_SPARC_13, 11) +ELF_RELOC(R_SPARC_LO10, 12) +ELF_RELOC(R_SPARC_GOT10, 13) +ELF_RELOC(R_SPARC_GOT13, 14) +ELF_RELOC(R_SPARC_GOT22, 15) +ELF_RELOC(R_SPARC_PC10, 16) +ELF_RELOC(R_SPARC_PC22, 17) +ELF_RELOC(R_SPARC_WPLT30, 18) +ELF_RELOC(R_SPARC_COPY, 19) +ELF_RELOC(R_SPARC_GLOB_DAT, 20) +ELF_RELOC(R_SPARC_JMP_SLOT, 21) +ELF_RELOC(R_SPARC_RELATIVE, 22) +ELF_RELOC(R_SPARC_UA32, 23) +ELF_RELOC(R_SPARC_PLT32, 24) +ELF_RELOC(R_SPARC_HIPLT22, 25) +ELF_RELOC(R_SPARC_LOPLT10, 26) +ELF_RELOC(R_SPARC_PCPLT32, 27) +ELF_RELOC(R_SPARC_PCPLT22, 28) +ELF_RELOC(R_SPARC_PCPLT10, 29) +ELF_RELOC(R_SPARC_10, 30) +ELF_RELOC(R_SPARC_11, 31) +ELF_RELOC(R_SPARC_64, 32) +ELF_RELOC(R_SPARC_OLO10, 33) +ELF_RELOC(R_SPARC_HH22, 34) +ELF_RELOC(R_SPARC_HM10, 35) +ELF_RELOC(R_SPARC_LM22, 36) +ELF_RELOC(R_SPARC_PC_HH22, 37) +ELF_RELOC(R_SPARC_PC_HM10, 38) +ELF_RELOC(R_SPARC_PC_LM22, 39) +ELF_RELOC(R_SPARC_WDISP16, 40) +ELF_RELOC(R_SPARC_WDISP19, 41) +ELF_RELOC(R_SPARC_7, 43) +ELF_RELOC(R_SPARC_5, 44) +ELF_RELOC(R_SPARC_6, 45) +ELF_RELOC(R_SPARC_DISP64, 46) +ELF_RELOC(R_SPARC_PLT64, 47) +ELF_RELOC(R_SPARC_HIX22, 48) +ELF_RELOC(R_SPARC_LOX10, 49) +ELF_RELOC(R_SPARC_H44, 50) +ELF_RELOC(R_SPARC_M44, 51) +ELF_RELOC(R_SPARC_L44, 52) +ELF_RELOC(R_SPARC_REGISTER, 53) +ELF_RELOC(R_SPARC_UA64, 54) +ELF_RELOC(R_SPARC_UA16, 55) +ELF_RELOC(R_SPARC_TLS_GD_HI22, 56) +ELF_RELOC(R_SPARC_TLS_GD_LO10, 57) +ELF_RELOC(R_SPARC_TLS_GD_ADD, 58) +ELF_RELOC(R_SPARC_TLS_GD_CALL, 59) +ELF_RELOC(R_SPARC_TLS_LDM_HI22, 60) +ELF_RELOC(R_SPARC_TLS_LDM_LO10, 61) +ELF_RELOC(R_SPARC_TLS_LDM_ADD, 62) +ELF_RELOC(R_SPARC_TLS_LDM_CALL, 63) +ELF_RELOC(R_SPARC_TLS_LDO_HIX22, 64) +ELF_RELOC(R_SPARC_TLS_LDO_LOX10, 65) +ELF_RELOC(R_SPARC_TLS_LDO_ADD, 66) +ELF_RELOC(R_SPARC_TLS_IE_HI22, 67) +ELF_RELOC(R_SPARC_TLS_IE_LO10, 68) +ELF_RELOC(R_SPARC_TLS_IE_LD, 69) +ELF_RELOC(R_SPARC_TLS_IE_LDX, 70) +ELF_RELOC(R_SPARC_TLS_IE_ADD, 71) +ELF_RELOC(R_SPARC_TLS_LE_HIX22, 72) +ELF_RELOC(R_SPARC_TLS_LE_LOX10, 73) +ELF_RELOC(R_SPARC_TLS_DTPMOD32, 74) +ELF_RELOC(R_SPARC_TLS_DTPMOD64, 75) +ELF_RELOC(R_SPARC_TLS_DTPOFF32, 76) +ELF_RELOC(R_SPARC_TLS_DTPOFF64, 77) +ELF_RELOC(R_SPARC_TLS_TPOFF32, 78) +ELF_RELOC(R_SPARC_TLS_TPOFF64, 79) +ELF_RELOC(R_SPARC_GOTDATA_HIX22, 80) +ELF_RELOC(R_SPARC_GOTDATA_LOX10, 81) +ELF_RELOC(R_SPARC_GOTDATA_OP_HIX22, 82) +ELF_RELOC(R_SPARC_GOTDATA_OP_LOX10, 83) +ELF_RELOC(R_SPARC_GOTDATA_OP, 84)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/SystemZ.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/SystemZ.def new file mode 100644 index 0000000..711f940 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/SystemZ.def
@@ -0,0 +1,67 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_390_NONE, 0) +ELF_RELOC(R_390_8, 1) +ELF_RELOC(R_390_12, 2) +ELF_RELOC(R_390_16, 3) +ELF_RELOC(R_390_32, 4) +ELF_RELOC(R_390_PC32, 5) +ELF_RELOC(R_390_GOT12, 6) +ELF_RELOC(R_390_GOT32, 7) +ELF_RELOC(R_390_PLT32, 8) +ELF_RELOC(R_390_COPY, 9) +ELF_RELOC(R_390_GLOB_DAT, 10) +ELF_RELOC(R_390_JMP_SLOT, 11) +ELF_RELOC(R_390_RELATIVE, 12) +ELF_RELOC(R_390_GOTOFF, 13) +ELF_RELOC(R_390_GOTPC, 14) +ELF_RELOC(R_390_GOT16, 15) +ELF_RELOC(R_390_PC16, 16) +ELF_RELOC(R_390_PC16DBL, 17) +ELF_RELOC(R_390_PLT16DBL, 18) +ELF_RELOC(R_390_PC32DBL, 19) +ELF_RELOC(R_390_PLT32DBL, 20) +ELF_RELOC(R_390_GOTPCDBL, 21) +ELF_RELOC(R_390_64, 22) +ELF_RELOC(R_390_PC64, 23) +ELF_RELOC(R_390_GOT64, 24) +ELF_RELOC(R_390_PLT64, 25) +ELF_RELOC(R_390_GOTENT, 26) +ELF_RELOC(R_390_GOTOFF16, 27) +ELF_RELOC(R_390_GOTOFF64, 28) +ELF_RELOC(R_390_GOTPLT12, 29) +ELF_RELOC(R_390_GOTPLT16, 30) +ELF_RELOC(R_390_GOTPLT32, 31) +ELF_RELOC(R_390_GOTPLT64, 32) +ELF_RELOC(R_390_GOTPLTENT, 33) +ELF_RELOC(R_390_PLTOFF16, 34) +ELF_RELOC(R_390_PLTOFF32, 35) +ELF_RELOC(R_390_PLTOFF64, 36) +ELF_RELOC(R_390_TLS_LOAD, 37) +ELF_RELOC(R_390_TLS_GDCALL, 38) +ELF_RELOC(R_390_TLS_LDCALL, 39) +ELF_RELOC(R_390_TLS_GD32, 40) +ELF_RELOC(R_390_TLS_GD64, 41) +ELF_RELOC(R_390_TLS_GOTIE12, 42) +ELF_RELOC(R_390_TLS_GOTIE32, 43) +ELF_RELOC(R_390_TLS_GOTIE64, 44) +ELF_RELOC(R_390_TLS_LDM32, 45) +ELF_RELOC(R_390_TLS_LDM64, 46) +ELF_RELOC(R_390_TLS_IE32, 47) +ELF_RELOC(R_390_TLS_IE64, 48) +ELF_RELOC(R_390_TLS_IEENT, 49) +ELF_RELOC(R_390_TLS_LE32, 50) +ELF_RELOC(R_390_TLS_LE64, 51) +ELF_RELOC(R_390_TLS_LDO32, 52) +ELF_RELOC(R_390_TLS_LDO64, 53) +ELF_RELOC(R_390_TLS_DTPMOD, 54) +ELF_RELOC(R_390_TLS_DTPOFF, 55) +ELF_RELOC(R_390_TLS_TPOFF, 56) +ELF_RELOC(R_390_20, 57) +ELF_RELOC(R_390_GOT20, 58) +ELF_RELOC(R_390_GOTPLT20, 59) +ELF_RELOC(R_390_TLS_GOTIE20, 60) +ELF_RELOC(R_390_IRELATIVE, 61)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/WebAssembly.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/WebAssembly.def new file mode 100644 index 0000000..9a34349 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/WebAssembly.def
@@ -0,0 +1,8 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_WEBASSEMBLY_NONE, 0) +ELF_RELOC(R_WEBASSEMBLY_DATA, 1) +ELF_RELOC(R_WEBASSEMBLY_FUNCTION, 2)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/i386.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/i386.def new file mode 100644 index 0000000..1d28cf5 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/i386.def
@@ -0,0 +1,47 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +// TODO: this is just a subset +ELF_RELOC(R_386_NONE, 0) +ELF_RELOC(R_386_32, 1) +ELF_RELOC(R_386_PC32, 2) +ELF_RELOC(R_386_GOT32, 3) +ELF_RELOC(R_386_PLT32, 4) +ELF_RELOC(R_386_COPY, 5) +ELF_RELOC(R_386_GLOB_DAT, 6) +ELF_RELOC(R_386_JUMP_SLOT, 7) +ELF_RELOC(R_386_RELATIVE, 8) +ELF_RELOC(R_386_GOTOFF, 9) +ELF_RELOC(R_386_GOTPC, 10) +ELF_RELOC(R_386_32PLT, 11) +ELF_RELOC(R_386_TLS_TPOFF, 14) +ELF_RELOC(R_386_TLS_IE, 15) +ELF_RELOC(R_386_TLS_GOTIE, 16) +ELF_RELOC(R_386_TLS_LE, 17) +ELF_RELOC(R_386_TLS_GD, 18) +ELF_RELOC(R_386_TLS_LDM, 19) +ELF_RELOC(R_386_16, 20) +ELF_RELOC(R_386_PC16, 21) +ELF_RELOC(R_386_8, 22) +ELF_RELOC(R_386_PC8, 23) +ELF_RELOC(R_386_TLS_GD_32, 24) +ELF_RELOC(R_386_TLS_GD_PUSH, 25) +ELF_RELOC(R_386_TLS_GD_CALL, 26) +ELF_RELOC(R_386_TLS_GD_POP, 27) +ELF_RELOC(R_386_TLS_LDM_32, 28) +ELF_RELOC(R_386_TLS_LDM_PUSH, 29) +ELF_RELOC(R_386_TLS_LDM_CALL, 30) +ELF_RELOC(R_386_TLS_LDM_POP, 31) +ELF_RELOC(R_386_TLS_LDO_32, 32) +ELF_RELOC(R_386_TLS_IE_32, 33) +ELF_RELOC(R_386_TLS_LE_32, 34) +ELF_RELOC(R_386_TLS_DTPMOD32, 35) +ELF_RELOC(R_386_TLS_DTPOFF32, 36) +ELF_RELOC(R_386_TLS_TPOFF32, 37) +ELF_RELOC(R_386_TLS_GOTDESC, 39) +ELF_RELOC(R_386_TLS_DESC_CALL, 40) +ELF_RELOC(R_386_TLS_DESC, 41) +ELF_RELOC(R_386_IRELATIVE, 42) +ELF_RELOC(R_386_GOT32X, 43)
diff --git a/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/x86_64.def b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/x86_64.def new file mode 100644 index 0000000..18fdcf9 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ELFRelocs/x86_64.def
@@ -0,0 +1,45 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_X86_64_NONE, 0) +ELF_RELOC(R_X86_64_64, 1) +ELF_RELOC(R_X86_64_PC32, 2) +ELF_RELOC(R_X86_64_GOT32, 3) +ELF_RELOC(R_X86_64_PLT32, 4) +ELF_RELOC(R_X86_64_COPY, 5) +ELF_RELOC(R_X86_64_GLOB_DAT, 6) +ELF_RELOC(R_X86_64_JUMP_SLOT, 7) +ELF_RELOC(R_X86_64_RELATIVE, 8) +ELF_RELOC(R_X86_64_GOTPCREL, 9) +ELF_RELOC(R_X86_64_32, 10) +ELF_RELOC(R_X86_64_32S, 11) +ELF_RELOC(R_X86_64_16, 12) +ELF_RELOC(R_X86_64_PC16, 13) +ELF_RELOC(R_X86_64_8, 14) +ELF_RELOC(R_X86_64_PC8, 15) +ELF_RELOC(R_X86_64_DTPMOD64, 16) +ELF_RELOC(R_X86_64_DTPOFF64, 17) +ELF_RELOC(R_X86_64_TPOFF64, 18) +ELF_RELOC(R_X86_64_TLSGD, 19) +ELF_RELOC(R_X86_64_TLSLD, 20) +ELF_RELOC(R_X86_64_DTPOFF32, 21) +ELF_RELOC(R_X86_64_GOTTPOFF, 22) +ELF_RELOC(R_X86_64_TPOFF32, 23) +ELF_RELOC(R_X86_64_PC64, 24) +ELF_RELOC(R_X86_64_GOTOFF64, 25) +ELF_RELOC(R_X86_64_GOTPC32, 26) +ELF_RELOC(R_X86_64_GOT64, 27) +ELF_RELOC(R_X86_64_GOTPCREL64, 28) +ELF_RELOC(R_X86_64_GOTPC64, 29) +ELF_RELOC(R_X86_64_GOTPLT64, 30) +ELF_RELOC(R_X86_64_PLTOFF64, 31) +ELF_RELOC(R_X86_64_SIZE32, 32) +ELF_RELOC(R_X86_64_SIZE64, 33) +ELF_RELOC(R_X86_64_GOTPC32_TLSDESC, 34) +ELF_RELOC(R_X86_64_TLSDESC_CALL, 35) +ELF_RELOC(R_X86_64_TLSDESC, 36) +ELF_RELOC(R_X86_64_IRELATIVE, 37) +ELF_RELOC(R_X86_64_GOTPCRELX, 41) +ELF_RELOC(R_X86_64_REX_GOTPCRELX, 42)
diff --git a/third_party/llvm-subzero/include/llvm/Support/Endian.h b/third_party/llvm-subzero/include/llvm/Support/Endian.h new file mode 100644 index 0000000..cb5cd8e --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Endian.h
@@ -0,0 +1,349 @@ +//===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares generic functions to read and write endian specific data. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ENDIAN_H +#define LLVM_SUPPORT_ENDIAN_H + +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/SwapByteOrder.h" + +namespace llvm { +namespace support { +enum endianness {big, little, native}; + +// These are named values for common alignments. +enum {aligned = 0, unaligned = 1}; + +namespace detail { + /// \brief ::value is either alignment, or alignof(T) if alignment is 0. + template<class T, int alignment> + struct PickAlignment { + enum {value = alignment == 0 ? AlignOf<T>::Alignment : alignment}; + }; +} // end namespace detail + +namespace endian { +/// Swap the bytes of value to match the given endianness. +template<typename value_type, endianness endian> +inline value_type byte_swap(value_type value) { + if (endian != native && sys::IsBigEndianHost != (endian == big)) + sys::swapByteOrder(value); + return value; +} + +/// Read a value of a particular endianness from memory. +template<typename value_type, + endianness endian, + std::size_t alignment> +inline value_type read(const void *memory) { + value_type ret; + + memcpy(&ret, + LLVM_ASSUME_ALIGNED(memory, + (detail::PickAlignment<value_type, alignment>::value)), + sizeof(value_type)); + return byte_swap<value_type, endian>(ret); +} + +/// Read a value of a particular endianness from a buffer, and increment the +/// buffer past that value. +template<typename value_type, endianness endian, std::size_t alignment, + typename CharT> +inline value_type readNext(const CharT *&memory) { + value_type ret = read<value_type, endian, alignment>(memory); + memory += sizeof(value_type); + return ret; +} + +/// Write a value to memory with a particular endianness. +template<typename value_type, + endianness endian, + std::size_t alignment> +inline void write(void *memory, value_type value) { + value = byte_swap<value_type, endian>(value); + memcpy(LLVM_ASSUME_ALIGNED(memory, + (detail::PickAlignment<value_type, alignment>::value)), + &value, + sizeof(value_type)); +} + +template <typename value_type> +using make_unsigned_t = typename std::make_unsigned<value_type>::type; + +/// Read a value of a particular endianness from memory, for a location +/// that starts at the given bit offset within the first byte. +template <typename value_type, endianness endian, std::size_t alignment> +inline value_type readAtBitAlignment(const void *memory, uint64_t startBit) { + assert(startBit < 8); + if (startBit == 0) + return read<value_type, endian, alignment>(memory); + else { + // Read two values and compose the result from them. + value_type val[2]; + memcpy(&val[0], + LLVM_ASSUME_ALIGNED( + memory, (detail::PickAlignment<value_type, alignment>::value)), + sizeof(value_type) * 2); + val[0] = byte_swap<value_type, endian>(val[0]); + val[1] = byte_swap<value_type, endian>(val[1]); + + // Shift bits from the lower value into place. + make_unsigned_t<value_type> lowerVal = val[0] >> startBit; + // Mask off upper bits after right shift in case of signed type. + make_unsigned_t<value_type> numBitsFirstVal = + (sizeof(value_type) * 8) - startBit; + lowerVal &= ((make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1; + + // Get the bits from the upper value. + make_unsigned_t<value_type> upperVal = + val[1] & (((make_unsigned_t<value_type>)1 << startBit) - 1); + // Shift them in to place. + upperVal <<= numBitsFirstVal; + + return lowerVal | upperVal; + } +} + +/// Write a value to memory with a particular endianness, for a location +/// that starts at the given bit offset within the first byte. +template <typename value_type, endianness endian, std::size_t alignment> +inline void writeAtBitAlignment(void *memory, value_type value, + uint64_t startBit) { + assert(startBit < 8); + if (startBit == 0) + write<value_type, endian, alignment>(memory, value); + else { + // Read two values and shift the result into them. + value_type val[2]; + memcpy(&val[0], + LLVM_ASSUME_ALIGNED( + memory, (detail::PickAlignment<value_type, alignment>::value)), + sizeof(value_type) * 2); + val[0] = byte_swap<value_type, endian>(val[0]); + val[1] = byte_swap<value_type, endian>(val[1]); + + // Mask off any existing bits in the upper part of the lower value that + // we want to replace. + val[0] &= ((make_unsigned_t<value_type>)1 << startBit) - 1; + make_unsigned_t<value_type> numBitsFirstVal = + (sizeof(value_type) * 8) - startBit; + make_unsigned_t<value_type> lowerVal = value; + if (startBit > 0) { + // Mask off the upper bits in the new value that are not going to go into + // the lower value. This avoids a left shift of a negative value, which + // is undefined behavior. + lowerVal &= (((make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1); + // Now shift the new bits into place + lowerVal <<= startBit; + } + val[0] |= lowerVal; + + // Mask off any existing bits in the lower part of the upper value that + // we want to replace. + val[1] &= ~(((make_unsigned_t<value_type>)1 << startBit) - 1); + // Next shift the bits that go into the upper value into position. + make_unsigned_t<value_type> upperVal = value >> numBitsFirstVal; + // Mask off upper bits after right shift in case of signed type. + upperVal &= ((make_unsigned_t<value_type>)1 << startBit) - 1; + val[1] |= upperVal; + + // Finally, rewrite values. + val[0] = byte_swap<value_type, endian>(val[0]); + val[1] = byte_swap<value_type, endian>(val[1]); + memcpy(LLVM_ASSUME_ALIGNED( + memory, (detail::PickAlignment<value_type, alignment>::value)), + &val[0], sizeof(value_type) * 2); + } +} +} // end namespace endian + +namespace detail { +template<typename value_type, + endianness endian, + std::size_t alignment> +struct packed_endian_specific_integral { + packed_endian_specific_integral() = default; + + explicit packed_endian_specific_integral(value_type val) { *this = val; } + + operator value_type() const { + return endian::read<value_type, endian, alignment>( + (const void*)Value.buffer); + } + + void operator=(value_type newValue) { + endian::write<value_type, endian, alignment>( + (void*)Value.buffer, newValue); + } + + packed_endian_specific_integral &operator+=(value_type newValue) { + *this = *this + newValue; + return *this; + } + + packed_endian_specific_integral &operator-=(value_type newValue) { + *this = *this - newValue; + return *this; + } + + packed_endian_specific_integral &operator|=(value_type newValue) { + *this = *this | newValue; + return *this; + } + + packed_endian_specific_integral &operator&=(value_type newValue) { + *this = *this & newValue; + return *this; + } + +private: + AlignedCharArray<PickAlignment<value_type, alignment>::value, + sizeof(value_type)> Value; + +public: + struct ref { + explicit ref(void *Ptr) : Ptr(Ptr) {} + + operator value_type() const { + return endian::read<value_type, endian, alignment>(Ptr); + } + + void operator=(value_type NewValue) { + endian::write<value_type, endian, alignment>(Ptr, NewValue); + } + + private: + void *Ptr; + }; +}; + +} // end namespace detail + +typedef detail::packed_endian_specific_integral + <uint16_t, little, unaligned> ulittle16_t; +typedef detail::packed_endian_specific_integral + <uint32_t, little, unaligned> ulittle32_t; +typedef detail::packed_endian_specific_integral + <uint64_t, little, unaligned> ulittle64_t; + +typedef detail::packed_endian_specific_integral + <int16_t, little, unaligned> little16_t; +typedef detail::packed_endian_specific_integral + <int32_t, little, unaligned> little32_t; +typedef detail::packed_endian_specific_integral + <int64_t, little, unaligned> little64_t; + +typedef detail::packed_endian_specific_integral + <uint16_t, little, aligned> aligned_ulittle16_t; +typedef detail::packed_endian_specific_integral + <uint32_t, little, aligned> aligned_ulittle32_t; +typedef detail::packed_endian_specific_integral + <uint64_t, little, aligned> aligned_ulittle64_t; + +typedef detail::packed_endian_specific_integral + <int16_t, little, aligned> aligned_little16_t; +typedef detail::packed_endian_specific_integral + <int32_t, little, aligned> aligned_little32_t; +typedef detail::packed_endian_specific_integral + <int64_t, little, aligned> aligned_little64_t; + +typedef detail::packed_endian_specific_integral + <uint16_t, big, unaligned> ubig16_t; +typedef detail::packed_endian_specific_integral + <uint32_t, big, unaligned> ubig32_t; +typedef detail::packed_endian_specific_integral + <uint64_t, big, unaligned> ubig64_t; + +typedef detail::packed_endian_specific_integral + <int16_t, big, unaligned> big16_t; +typedef detail::packed_endian_specific_integral + <int32_t, big, unaligned> big32_t; +typedef detail::packed_endian_specific_integral + <int64_t, big, unaligned> big64_t; + +typedef detail::packed_endian_specific_integral + <uint16_t, big, aligned> aligned_ubig16_t; +typedef detail::packed_endian_specific_integral + <uint32_t, big, aligned> aligned_ubig32_t; +typedef detail::packed_endian_specific_integral + <uint64_t, big, aligned> aligned_ubig64_t; + +typedef detail::packed_endian_specific_integral + <int16_t, big, aligned> aligned_big16_t; +typedef detail::packed_endian_specific_integral + <int32_t, big, aligned> aligned_big32_t; +typedef detail::packed_endian_specific_integral + <int64_t, big, aligned> aligned_big64_t; + +typedef detail::packed_endian_specific_integral + <uint16_t, native, unaligned> unaligned_uint16_t; +typedef detail::packed_endian_specific_integral + <uint32_t, native, unaligned> unaligned_uint32_t; +typedef detail::packed_endian_specific_integral + <uint64_t, native, unaligned> unaligned_uint64_t; + +typedef detail::packed_endian_specific_integral + <int16_t, native, unaligned> unaligned_int16_t; +typedef detail::packed_endian_specific_integral + <int32_t, native, unaligned> unaligned_int32_t; +typedef detail::packed_endian_specific_integral + <int64_t, native, unaligned> unaligned_int64_t; + +namespace endian { +template <typename T, endianness E> inline T read(const void *P) { + return *(const detail::packed_endian_specific_integral<T, E, unaligned> *)P; +} + +template <endianness E> inline uint16_t read16(const void *P) { + return read<uint16_t, E>(P); +} +template <endianness E> inline uint32_t read32(const void *P) { + return read<uint32_t, E>(P); +} +template <endianness E> inline uint64_t read64(const void *P) { + return read<uint64_t, E>(P); +} + +inline uint16_t read16le(const void *P) { return read16<little>(P); } +inline uint32_t read32le(const void *P) { return read32<little>(P); } +inline uint64_t read64le(const void *P) { return read64<little>(P); } +inline uint16_t read16be(const void *P) { return read16<big>(P); } +inline uint32_t read32be(const void *P) { return read32<big>(P); } +inline uint64_t read64be(const void *P) { return read64<big>(P); } + +template <typename T, endianness E> inline void write(void *P, T V) { + *(detail::packed_endian_specific_integral<T, E, unaligned> *)P = V; +} + +template <endianness E> inline void write16(void *P, uint16_t V) { + write<uint16_t, E>(P, V); +} +template <endianness E> inline void write32(void *P, uint32_t V) { + write<uint32_t, E>(P, V); +} +template <endianness E> inline void write64(void *P, uint64_t V) { + write<uint64_t, E>(P, V); +} + +inline void write16le(void *P, uint16_t V) { write16<little>(P, V); } +inline void write32le(void *P, uint32_t V) { write32<little>(P, V); } +inline void write64le(void *P, uint64_t V) { write64<little>(P, V); } +inline void write16be(void *P, uint16_t V) { write16<big>(P, V); } +inline void write32be(void *P, uint32_t V) { write32<big>(P, V); } +inline void write64be(void *P, uint64_t V) { write64<big>(P, V); } +} // end namespace endian +} // end namespace support +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Errc.h b/third_party/llvm-subzero/include/llvm/Support/Errc.h new file mode 100644 index 0000000..80bfe2a --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Errc.h
@@ -0,0 +1,86 @@ +//===- llvm/Support/Errc.h - Defines the llvm::errc enum --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// While std::error_code works OK on all platforms we use, there are some +// some problems with std::errc that can be avoided by using our own +// enumeration: +// +// * std::errc is a namespace in some implementations. That meas that ADL +// doesn't work and it is sometimes necessary to write std::make_error_code +// or in templates: +// using std::make_error_code; +// make_error_code(...); +// +// with this enum it is safe to always just use make_error_code. +// +// * Some implementations define fewer names than others. This header has +// the intersection of all the ones we support. +// +// * std::errc is just marked with is_error_condition_enum. This means that +// common patters like AnErrorCode == errc::no_such_file_or_directory take +// 4 virtual calls instead of two comparisons. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ERRC_H +#define LLVM_SUPPORT_ERRC_H + +#include <system_error> + +namespace llvm { +enum class errc { + argument_list_too_long = int(std::errc::argument_list_too_long), + argument_out_of_domain = int(std::errc::argument_out_of_domain), + bad_address = int(std::errc::bad_address), + bad_file_descriptor = int(std::errc::bad_file_descriptor), + broken_pipe = int(std::errc::broken_pipe), + device_or_resource_busy = int(std::errc::device_or_resource_busy), + directory_not_empty = int(std::errc::directory_not_empty), + executable_format_error = int(std::errc::executable_format_error), + file_exists = int(std::errc::file_exists), + file_too_large = int(std::errc::file_too_large), + filename_too_long = int(std::errc::filename_too_long), + function_not_supported = int(std::errc::function_not_supported), + illegal_byte_sequence = int(std::errc::illegal_byte_sequence), + inappropriate_io_control_operation = + int(std::errc::inappropriate_io_control_operation), + interrupted = int(std::errc::interrupted), + invalid_argument = int(std::errc::invalid_argument), + invalid_seek = int(std::errc::invalid_seek), + io_error = int(std::errc::io_error), + is_a_directory = int(std::errc::is_a_directory), + no_child_process = int(std::errc::no_child_process), + no_lock_available = int(std::errc::no_lock_available), + no_space_on_device = int(std::errc::no_space_on_device), + no_such_device_or_address = int(std::errc::no_such_device_or_address), + no_such_device = int(std::errc::no_such_device), + no_such_file_or_directory = int(std::errc::no_such_file_or_directory), + no_such_process = int(std::errc::no_such_process), + not_a_directory = int(std::errc::not_a_directory), + not_enough_memory = int(std::errc::not_enough_memory), + operation_not_permitted = int(std::errc::operation_not_permitted), + permission_denied = int(std::errc::permission_denied), + read_only_file_system = int(std::errc::read_only_file_system), + resource_deadlock_would_occur = int(std::errc::resource_deadlock_would_occur), + resource_unavailable_try_again = + int(std::errc::resource_unavailable_try_again), + result_out_of_range = int(std::errc::result_out_of_range), + too_many_files_open_in_system = int(std::errc::too_many_files_open_in_system), + too_many_files_open = int(std::errc::too_many_files_open), + too_many_links = int(std::errc::too_many_links) +}; + +inline std::error_code make_error_code(errc E) { + return std::error_code(static_cast<int>(E), std::generic_category()); +} +} + +namespace std { +template <> struct is_error_code_enum<llvm::errc> : std::true_type {}; +} +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Errno.h b/third_party/llvm-subzero/include/llvm/Support/Errno.h new file mode 100644 index 0000000..8e145c7 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Errno.h
@@ -0,0 +1,34 @@ +//===- llvm/Support/Errno.h - Portable+convenient errno handling -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares some portable and convenient functions to deal with errno. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ERRNO_H +#define LLVM_SUPPORT_ERRNO_H + +#include <string> + +namespace llvm { +namespace sys { + +/// Returns a string representation of the errno value, using whatever +/// thread-safe variant of strerror() is available. Be sure to call this +/// immediately after the function that set errno, or errno may have been +/// overwritten by an intervening call. +std::string StrError(); + +/// Like the no-argument version above, but uses \p errnum instead of errno. +std::string StrError(int errnum); + +} // namespace sys +} // namespace llvm + +#endif // LLVM_SYSTEM_ERRNO_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/Error.h b/third_party/llvm-subzero/include/llvm/Support/Error.h new file mode 100644 index 0000000..afd2660 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Error.h
@@ -0,0 +1,964 @@ +//===----- llvm/Support/Error.h - Recoverable error handling ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an API used to report recoverable errors. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ERROR_H +#define LLVM_SUPPORT_ERROR_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/raw_ostream.h" +#include <vector> + +namespace llvm { + +class Error; +class ErrorList; + +/// Base class for error info classes. Do not extend this directly: Extend +/// the ErrorInfo template subclass instead. +class ErrorInfoBase { +public: + virtual ~ErrorInfoBase() {} + + /// Print an error message to an output stream. + virtual void log(raw_ostream &OS) const = 0; + + /// Return the error message as a string. + virtual std::string message() const { + std::string Msg; + raw_string_ostream OS(Msg); + log(OS); + return OS.str(); + } + + /// Convert this error to a std::error_code. + /// + /// This is a temporary crutch to enable interaction with code still + /// using std::error_code. It will be removed in the future. + virtual std::error_code convertToErrorCode() const = 0; + + // Check whether this instance is a subclass of the class identified by + // ClassID. + virtual bool isA(const void *const ClassID) const { + return ClassID == classID(); + } + + // Check whether this instance is a subclass of ErrorInfoT. + template <typename ErrorInfoT> bool isA() const { + return isA(ErrorInfoT::classID()); + } + + // Returns the class ID for this type. + static const void *classID() { return &ID; } + +private: + virtual void anchor(); + static char ID; +}; + +/// Lightweight error class with error context and mandatory checking. +/// +/// Instances of this class wrap a ErrorInfoBase pointer. Failure states +/// are represented by setting the pointer to a ErrorInfoBase subclass +/// instance containing information describing the failure. Success is +/// represented by a null pointer value. +/// +/// Instances of Error also contains a 'Checked' flag, which must be set +/// before the destructor is called, otherwise the destructor will trigger a +/// runtime error. This enforces at runtime the requirement that all Error +/// instances be checked or returned to the caller. +/// +/// There are two ways to set the checked flag, depending on what state the +/// Error instance is in. For Error instances indicating success, it +/// is sufficient to invoke the boolean conversion operator. E.g.: +/// +/// @code{.cpp} +/// Error foo(<...>); +/// +/// if (auto E = foo(<...>)) +/// return E; // <- Return E if it is in the error state. +/// // We have verified that E was in the success state. It can now be safely +/// // destroyed. +/// @endcode +/// +/// A success value *can not* be dropped. For example, just calling 'foo(<...>)' +/// without testing the return value will raise a runtime error, even if foo +/// returns success. +/// +/// For Error instances representing failure, you must use either the +/// handleErrors or handleAllErrors function with a typed handler. E.g.: +/// +/// @code{.cpp} +/// class MyErrorInfo : public ErrorInfo<MyErrorInfo> { +/// // Custom error info. +/// }; +/// +/// Error foo(<...>) { return make_error<MyErrorInfo>(...); } +/// +/// auto E = foo(<...>); // <- foo returns failure with MyErrorInfo. +/// auto NewE = +/// handleErrors(E, +/// [](const MyErrorInfo &M) { +/// // Deal with the error. +/// }, +/// [](std::unique_ptr<OtherError> M) -> Error { +/// if (canHandle(*M)) { +/// // handle error. +/// return Error::success(); +/// } +/// // Couldn't handle this error instance. Pass it up the stack. +/// return Error(std::move(M)); +/// ); +/// // Note - we must check or return NewE in case any of the handlers +/// // returned a new error. +/// @endcode +/// +/// The handleAllErrors function is identical to handleErrors, except +/// that it has a void return type, and requires all errors to be handled and +/// no new errors be returned. It prevents errors (assuming they can all be +/// handled) from having to be bubbled all the way to the top-level. +/// +/// *All* Error instances must be checked before destruction, even if +/// they're moved-assigned or constructed from Success values that have already +/// been checked. This enforces checking through all levels of the call stack. +class Error { + + // ErrorList needs to be able to yank ErrorInfoBase pointers out of this + // class to add to the error list. + friend class ErrorList; + + // handleErrors needs to be able to set the Checked flag. + template <typename... HandlerTs> + friend Error handleErrors(Error E, HandlerTs &&... Handlers); + + // Expected<T> needs to be able to steal the payload when constructed from an + // error. + template <typename T> class Expected; + +public: + /// Create a success value. Prefer using 'Error::success()' for readability + /// where possible. + Error() { + setPtr(nullptr); + setChecked(false); + } + + /// Create a success value. This is equivalent to calling the default + /// constructor, but should be preferred for readability where possible. + static Error success() { return Error(); } + + // Errors are not copy-constructable. + Error(const Error &Other) = delete; + + /// Move-construct an error value. The newly constructed error is considered + /// unchecked, even if the source error had been checked. The original error + /// becomes a checked Success value, regardless of its original state. + Error(Error &&Other) { + setChecked(true); + *this = std::move(Other); + } + + /// Create an error value. Prefer using the 'make_error' function, but + /// this constructor can be useful when "re-throwing" errors from handlers. + Error(std::unique_ptr<ErrorInfoBase> Payload) { + setPtr(Payload.release()); + setChecked(false); + } + + // Errors are not copy-assignable. + Error &operator=(const Error &Other) = delete; + + /// Move-assign an error value. The current error must represent success, you + /// you cannot overwrite an unhandled error. The current error is then + /// considered unchecked. The source error becomes a checked success value, + /// regardless of its original state. + Error &operator=(Error &&Other) { + // Don't allow overwriting of unchecked values. + assertIsChecked(); + setPtr(Other.getPtr()); + + // This Error is unchecked, even if the source error was checked. + setChecked(false); + + // Null out Other's payload and set its checked bit. + Other.setPtr(nullptr); + Other.setChecked(true); + + return *this; + } + + /// Destroy a Error. Fails with a call to abort() if the error is + /// unchecked. + ~Error() { + assertIsChecked(); + delete getPtr(); + } + + /// Bool conversion. Returns true if this Error is in a failure state, + /// and false if it is in an accept state. If the error is in a Success state + /// it will be considered checked. + explicit operator bool() { + setChecked(getPtr() == nullptr); + return getPtr() != nullptr; + } + + /// Check whether one error is a subclass of another. + template <typename ErrT> bool isA() const { + return getPtr() && getPtr()->isA(ErrT::classID()); + } + +private: + void assertIsChecked() { +#ifndef NDEBUG + if (!getChecked() || getPtr()) { + dbgs() << "Program aborted due to an unhandled Error:\n"; + if (getPtr()) + getPtr()->log(dbgs()); + else + dbgs() + << "Error value was Success. (Note: Success values must still be " + "checked prior to being destroyed).\n"; + abort(); + } +#endif + } + + ErrorInfoBase *getPtr() const { +#ifndef NDEBUG + return PayloadAndCheckedBit.getPointer(); +#else + return Payload; +#endif + } + + void setPtr(ErrorInfoBase *EI) { +#ifndef NDEBUG + PayloadAndCheckedBit.setPointer(EI); +#else + Payload = EI; +#endif + } + + bool getChecked() const { +#ifndef NDEBUG + return PayloadAndCheckedBit.getInt(); +#else + return true; +#endif + } + + void setChecked(bool V) { +#ifndef NDEBUG + PayloadAndCheckedBit.setInt(V); +#endif + } + + std::unique_ptr<ErrorInfoBase> takePayload() { + std::unique_ptr<ErrorInfoBase> Tmp(getPtr()); + setPtr(nullptr); + setChecked(true); + return Tmp; + } + +#ifndef NDEBUG + PointerIntPair<ErrorInfoBase *, 1> PayloadAndCheckedBit; +#else + ErrorInfoBase *Payload; +#endif +}; + +/// Make a Error instance representing failure using the given error info +/// type. +template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) { + return Error(llvm::make_unique<ErrT>(std::forward<ArgTs>(Args)...)); +} + +/// Base class for user error types. Users should declare their error types +/// like: +/// +/// class MyError : public ErrorInfo<MyError> { +/// .... +/// }; +/// +/// This class provides an implementation of the ErrorInfoBase::kind +/// method, which is used by the Error RTTI system. +template <typename ThisErrT, typename ParentErrT = ErrorInfoBase> +class ErrorInfo : public ParentErrT { +public: + bool isA(const void *const ClassID) const override { + return ClassID == classID() || ParentErrT::isA(ClassID); + } + + static const void *classID() { return &ThisErrT::ID; } +}; + +/// Special ErrorInfo subclass representing a list of ErrorInfos. +/// Instances of this class are constructed by joinError. +class ErrorList final : public ErrorInfo<ErrorList> { + + // handleErrors needs to be able to iterate the payload list of an + // ErrorList. + template <typename... HandlerTs> + friend Error handleErrors(Error E, HandlerTs &&... Handlers); + + // joinErrors is implemented in terms of join. + friend Error joinErrors(Error, Error); + +public: + void log(raw_ostream &OS) const override { + OS << "Multiple errors:\n"; + for (auto &ErrPayload : Payloads) { + ErrPayload->log(OS); + OS << "\n"; + } + } + + std::error_code convertToErrorCode() const override; + + // Used by ErrorInfo::classID. + static char ID; + +private: + ErrorList(std::unique_ptr<ErrorInfoBase> Payload1, + std::unique_ptr<ErrorInfoBase> Payload2) { + assert(!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && + "ErrorList constructor payloads should be singleton errors"); + Payloads.push_back(std::move(Payload1)); + Payloads.push_back(std::move(Payload2)); + } + + static Error join(Error E1, Error E2) { + if (!E1) + return E2; + if (!E2) + return E1; + if (E1.isA<ErrorList>()) { + auto &E1List = static_cast<ErrorList &>(*E1.getPtr()); + if (E2.isA<ErrorList>()) { + auto E2Payload = E2.takePayload(); + auto &E2List = static_cast<ErrorList &>(*E2Payload); + for (auto &Payload : E2List.Payloads) + E1List.Payloads.push_back(std::move(Payload)); + } else + E1List.Payloads.push_back(E2.takePayload()); + + return E1; + } + if (E2.isA<ErrorList>()) { + auto &E2List = static_cast<ErrorList &>(*E2.getPtr()); + E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload()); + return E2; + } + return Error(std::unique_ptr<ErrorList>( + new ErrorList(E1.takePayload(), E2.takePayload()))); + } + + std::vector<std::unique_ptr<ErrorInfoBase>> Payloads; +}; + +/// Concatenate errors. The resulting Error is unchecked, and contains the +/// ErrorInfo(s), if any, contained in E1, followed by the +/// ErrorInfo(s), if any, contained in E2. +inline Error joinErrors(Error E1, Error E2) { + return ErrorList::join(std::move(E1), std::move(E2)); +} + +/// Helper for testing applicability of, and applying, handlers for +/// ErrorInfo types. +template <typename HandlerT> +class ErrorHandlerTraits + : public ErrorHandlerTraits<decltype( + &std::remove_reference<HandlerT>::type::operator())> {}; + +// Specialization functions of the form 'Error (const ErrT&)'. +template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> { +public: + static bool appliesTo(const ErrorInfoBase &E) { + return E.template isA<ErrT>(); + } + + template <typename HandlerT> + static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { + assert(appliesTo(*E) && "Applying incorrect handler"); + return H(static_cast<ErrT &>(*E)); + } +}; + +// Specialization functions of the form 'void (const ErrT&)'. +template <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> { +public: + static bool appliesTo(const ErrorInfoBase &E) { + return E.template isA<ErrT>(); + } + + template <typename HandlerT> + static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { + assert(appliesTo(*E) && "Applying incorrect handler"); + H(static_cast<ErrT &>(*E)); + return Error::success(); + } +}; + +/// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'. +template <typename ErrT> +class ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> { +public: + static bool appliesTo(const ErrorInfoBase &E) { + return E.template isA<ErrT>(); + } + + template <typename HandlerT> + static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { + assert(appliesTo(*E) && "Applying incorrect handler"); + std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); + return H(std::move(SubE)); + } +}; + +/// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'. +template <typename ErrT> +class ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> { +public: + static bool appliesTo(const ErrorInfoBase &E) { + return E.template isA<ErrT>(); + } + + template <typename HandlerT> + static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { + assert(appliesTo(*E) && "Applying incorrect handler"); + std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); + H(std::move(SubE)); + return Error::success(); + } +}; + +// Specialization for member functions of the form 'RetT (const ErrT&)'. +template <typename C, typename RetT, typename ErrT> +class ErrorHandlerTraits<RetT (C::*)(ErrT &)> + : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; + +// Specialization for member functions of the form 'RetT (const ErrT&) const'. +template <typename C, typename RetT, typename ErrT> +class ErrorHandlerTraits<RetT (C::*)(ErrT &) const> + : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; + +// Specialization for member functions of the form 'RetT (const ErrT&)'. +template <typename C, typename RetT, typename ErrT> +class ErrorHandlerTraits<RetT (C::*)(const ErrT &)> + : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; + +// Specialization for member functions of the form 'RetT (const ErrT&) const'. +template <typename C, typename RetT, typename ErrT> +class ErrorHandlerTraits<RetT (C::*)(const ErrT &) const> + : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; + +/// Specialization for member functions of the form +/// 'RetT (std::unique_ptr<ErrT>) const'. +template <typename C, typename RetT, typename ErrT> +class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>)> + : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; + +/// Specialization for member functions of the form +/// 'RetT (std::unique_ptr<ErrT>) const'. +template <typename C, typename RetT, typename ErrT> +class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const> + : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; + +inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) { + return Error(std::move(Payload)); +} + +template <typename HandlerT, typename... HandlerTs> +Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload, + HandlerT &&Handler, HandlerTs &&... Handlers) { + if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload)) + return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler), + std::move(Payload)); + return handleErrorImpl(std::move(Payload), + std::forward<HandlerTs>(Handlers)...); +} + +/// Pass the ErrorInfo(s) contained in E to their respective handlers. Any +/// unhandled errors (or Errors returned by handlers) are re-concatenated and +/// returned. +/// Because this function returns an error, its result must also be checked +/// or returned. If you intend to handle all errors use handleAllErrors +/// (which returns void, and will abort() on unhandled errors) instead. +template <typename... HandlerTs> +Error handleErrors(Error E, HandlerTs &&... Hs) { + if (!E) + return Error::success(); + + std::unique_ptr<ErrorInfoBase> Payload = E.takePayload(); + + if (Payload->isA<ErrorList>()) { + ErrorList &List = static_cast<ErrorList &>(*Payload); + Error R; + for (auto &P : List.Payloads) + R = ErrorList::join( + std::move(R), + handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...)); + return R; + } + + return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...); +} + +/// Behaves the same as handleErrors, except that it requires that all +/// errors be handled by the given handlers. If any unhandled error remains +/// after the handlers have run, abort() will be called. +template <typename... HandlerTs> +void handleAllErrors(Error E, HandlerTs &&... Handlers) { + auto F = handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...); + // Cast 'F' to bool to set the 'Checked' flag if it's a success value: + (void)!F; +} + +/// Check that E is a non-error, then drop it. +inline void handleAllErrors(Error E) { + // Cast 'E' to a bool to set the 'Checked' flag if it's a success value: + (void)!E; +} + +/// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner +/// will be printed before the first one is logged. A newline will be printed +/// after each error. +/// +/// This is useful in the base level of your program to allow clean termination +/// (allowing clean deallocation of resources, etc.), while reporting error +/// information to the user. +void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner); + +/// Write all error messages (if any) in E to a string. The newline character +/// is used to separate error messages. +inline std::string toString(Error E) { + SmallVector<std::string, 2> Errors; + handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) { + Errors.push_back(EI.message()); + }); + return join(Errors.begin(), Errors.end(), "\n"); +} + +/// Consume a Error without doing anything. This method should be used +/// only where an error can be considered a reasonable and expected return +/// value. +/// +/// Uses of this method are potentially indicative of design problems: If it's +/// legitimate to do nothing while processing an "error", the error-producer +/// might be more clearly refactored to return an Optional<T>. +inline void consumeError(Error Err) { + handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {}); +} + +/// Helper for Errors used as out-parameters. +/// +/// This helper is for use with the Error-as-out-parameter idiom, where an error +/// is passed to a function or method by reference, rather than being returned. +/// In such cases it is helpful to set the checked bit on entry to the function +/// so that the error can be written to (unchecked Errors abort on assignment) +/// and clear the checked bit on exit so that clients cannot accidentally forget +/// to check the result. This helper performs these actions automatically using +/// RAII: +/// +/// @code{.cpp} +/// Result foo(Error &Err) { +/// ErrorAsOutParameter ErrAsOutParam(&Err); // 'Checked' flag set +/// // <body of foo> +/// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed. +/// } +/// @endcode +/// +/// ErrorAsOutParameter takes an Error* rather than Error& so that it can be +/// used with optional Errors (Error pointers that are allowed to be null). If +/// ErrorAsOutParameter took an Error reference, an instance would have to be +/// created inside every condition that verified that Error was non-null. By +/// taking an Error pointer we can just create one instance at the top of the +/// function. +class ErrorAsOutParameter { +public: + ErrorAsOutParameter(Error *Err) : Err(Err) { + // Raise the checked bit if Err is success. + if (Err) + (void)!!*Err; + } + ~ErrorAsOutParameter() { + // Clear the checked bit. + if (Err && !*Err) + *Err = Error::success(); + } + +private: + Error *Err; +}; + +/// Tagged union holding either a T or a Error. +/// +/// This class parallels ErrorOr, but replaces error_code with Error. Since +/// Error cannot be copied, this class replaces getError() with +/// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the +/// error class type. +template <class T> class Expected { + template <class OtherT> friend class Expected; + static const bool isRef = std::is_reference<T>::value; + typedef ReferenceStorage<typename std::remove_reference<T>::type> wrap; + + typedef std::unique_ptr<ErrorInfoBase> error_type; + +public: + typedef typename std::conditional<isRef, wrap, T>::type storage_type; + typedef T value_type; + +private: + typedef typename std::remove_reference<T>::type &reference; + typedef const typename std::remove_reference<T>::type &const_reference; + typedef typename std::remove_reference<T>::type *pointer; + typedef const typename std::remove_reference<T>::type *const_pointer; + +public: + /// Create an Expected<T> error value from the given Error. + Expected(Error Err) + : HasError(true) +#ifndef NDEBUG + , + Checked(false) +#endif + { + assert(Err && "Cannot create Expected<T> from Error success value."); + new (getErrorStorage()) Error(std::move(Err)); + } + + /// Create an Expected<T> success value from the given OtherT value, which + /// must be convertible to T. + template <typename OtherT> + Expected(OtherT &&Val, + typename std::enable_if<std::is_convertible<OtherT, T>::value>::type + * = nullptr) + : HasError(false) +#ifndef NDEBUG + , + Checked(false) +#endif + { + new (getStorage()) storage_type(std::forward<OtherT>(Val)); + } + + /// Move construct an Expected<T> value. + Expected(Expected &&Other) { moveConstruct(std::move(Other)); } + + /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT + /// must be convertible to T. + template <class OtherT> + Expected(Expected<OtherT> &&Other, + typename std::enable_if<std::is_convertible<OtherT, T>::value>::type + * = nullptr) { + moveConstruct(std::move(Other)); + } + + /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT + /// isn't convertible to T. + template <class OtherT> + explicit Expected( + Expected<OtherT> &&Other, + typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * = + nullptr) { + moveConstruct(std::move(Other)); + } + + /// Move-assign from another Expected<T>. + Expected &operator=(Expected &&Other) { + moveAssign(std::move(Other)); + return *this; + } + + /// Destroy an Expected<T>. + ~Expected() { + assertIsChecked(); + if (!HasError) + getStorage()->~storage_type(); + else + getErrorStorage()->~error_type(); + } + + /// \brief Return false if there is an error. + explicit operator bool() { +#ifndef NDEBUG + Checked = !HasError; +#endif + return !HasError; + } + + /// \brief Returns a reference to the stored T value. + reference get() { + assertIsChecked(); + return *getStorage(); + } + + /// \brief Returns a const reference to the stored T value. + const_reference get() const { + assertIsChecked(); + return const_cast<Expected<T> *>(this)->get(); + } + + /// \brief Check that this Expected<T> is an error of type ErrT. + template <typename ErrT> bool errorIsA() const { + return HasError && getErrorStorage()->template isA<ErrT>(); + } + + /// \brief Take ownership of the stored error. + /// After calling this the Expected<T> is in an indeterminate state that can + /// only be safely destructed. No further calls (beside the destructor) should + /// be made on the Expected<T> vaule. + Error takeError() { +#ifndef NDEBUG + Checked = true; +#endif + return HasError ? Error(std::move(*getErrorStorage())) : Error::success(); + } + + /// \brief Returns a pointer to the stored T value. + pointer operator->() { + assertIsChecked(); + return toPointer(getStorage()); + } + + /// \brief Returns a const pointer to the stored T value. + const_pointer operator->() const { + assertIsChecked(); + return toPointer(getStorage()); + } + + /// \brief Returns a reference to the stored T value. + reference operator*() { + assertIsChecked(); + return *getStorage(); + } + + /// \brief Returns a const reference to the stored T value. + const_reference operator*() const { + assertIsChecked(); + return *getStorage(); + } + +private: + template <class T1> + static bool compareThisIfSameType(const T1 &a, const T1 &b) { + return &a == &b; + } + + template <class T1, class T2> + static bool compareThisIfSameType(const T1 &a, const T2 &b) { + return false; + } + + template <class OtherT> void moveConstruct(Expected<OtherT> &&Other) { + HasError = Other.HasError; + +#ifndef NDEBUG + Checked = false; + Other.Checked = true; +#endif + + if (!HasError) + new (getStorage()) storage_type(std::move(*Other.getStorage())); + else + new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage())); + } + + template <class OtherT> void moveAssign(Expected<OtherT> &&Other) { + assertIsChecked(); + + if (compareThisIfSameType(*this, Other)) + return; + + this->~Expected(); + new (this) Expected(std::move(Other)); + } + + pointer toPointer(pointer Val) { return Val; } + + const_pointer toPointer(const_pointer Val) const { return Val; } + + pointer toPointer(wrap *Val) { return &Val->get(); } + + const_pointer toPointer(const wrap *Val) const { return &Val->get(); } + + storage_type *getStorage() { + assert(!HasError && "Cannot get value when an error exists!"); + return reinterpret_cast<storage_type *>(TStorage.buffer); + } + + const storage_type *getStorage() const { + assert(!HasError && "Cannot get value when an error exists!"); + return reinterpret_cast<const storage_type *>(TStorage.buffer); + } + + error_type *getErrorStorage() { + assert(HasError && "Cannot get error when a value exists!"); + return reinterpret_cast<error_type *>(ErrorStorage.buffer); + } + + void assertIsChecked() { +#ifndef NDEBUG + if (!Checked) { + dbgs() << "Expected<T> must be checked before access or destruction.\n"; + if (HasError) { + dbgs() << "Unchecked Expected<T> contained error:\n"; + (*getErrorStorage())->log(dbgs()); + } else + dbgs() << "Expected<T> value was in success state. (Note: Expected<T> " + "values in success mode must still be checked prior to being " + "destroyed).\n"; + abort(); + } +#endif + } + + union { + AlignedCharArrayUnion<storage_type> TStorage; + AlignedCharArrayUnion<error_type> ErrorStorage; + }; + bool HasError : 1; +#ifndef NDEBUG + bool Checked : 1; +#endif +}; + +/// This class wraps a std::error_code in a Error. +/// +/// This is useful if you're writing an interface that returns a Error +/// (or Expected) and you want to call code that still returns +/// std::error_codes. +class ECError : public ErrorInfo<ECError> { + friend Error errorCodeToError(std::error_code); +public: + void setErrorCode(std::error_code EC) { this->EC = EC; } + std::error_code convertToErrorCode() const override { return EC; } + void log(raw_ostream &OS) const override { OS << EC.message(); } + + // Used by ErrorInfo::classID. + static char ID; + +protected: + ECError() = default; + ECError(std::error_code EC) : EC(EC) {} + std::error_code EC; +}; + +/// The value returned by this function can be returned from convertToErrorCode +/// for Error values where no sensible translation to std::error_code exists. +/// It should only be used in this situation, and should never be used where a +/// sensible conversion to std::error_code is available, as attempts to convert +/// to/from this error will result in a fatal error. (i.e. it is a programmatic +///error to try to convert such a value). +std::error_code inconvertibleErrorCode(); + +/// Helper for converting an std::error_code to a Error. +Error errorCodeToError(std::error_code EC); + +/// Helper for converting an ECError to a std::error_code. +/// +/// This method requires that Err be Error() or an ECError, otherwise it +/// will trigger a call to abort(). +std::error_code errorToErrorCode(Error Err); + +/// Convert an ErrorOr<T> to an Expected<T>. +template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) { + if (auto EC = EO.getError()) + return errorCodeToError(EC); + return std::move(*EO); +} + +/// Convert an Expected<T> to an ErrorOr<T>. +template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) { + if (auto Err = E.takeError()) + return errorToErrorCode(std::move(Err)); + return std::move(*E); +} + +/// This class wraps a string in an Error. +/// +/// StringError is useful in cases where the client is not expected to be able +/// to consume the specific error message programmatically (for example, if the +/// error message is to be presented to the user). +class StringError : public ErrorInfo<StringError> { +public: + static char ID; + StringError(const Twine &S, std::error_code EC); + void log(raw_ostream &OS) const override; + std::error_code convertToErrorCode() const override; +private: + std::string Msg; + std::error_code EC; +}; + +/// Helper for check-and-exit error handling. +/// +/// For tool use only. NOT FOR USE IN LIBRARY CODE. +/// +class ExitOnError { +public: + /// Create an error on exit helper. + ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1) + : Banner(std::move(Banner)), + GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {} + + /// Set the banner string for any errors caught by operator(). + void setBanner(std::string Banner) { this->Banner = std::move(Banner); } + + /// Set the exit-code mapper function. + void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) { + this->GetExitCode = std::move(GetExitCode); + } + + /// Check Err. If it's in a failure state log the error(s) and exit. + void operator()(Error Err) const { checkError(std::move(Err)); } + + /// Check E. If it's in a success state then return the contained value. If + /// it's in a failure state log the error(s) and exit. + template <typename T> T operator()(Expected<T> &&E) const { + checkError(E.takeError()); + return std::move(*E); + } + + /// Check E. If it's in a success state then return the contained reference. If + /// it's in a failure state log the error(s) and exit. + template <typename T> T& operator()(Expected<T&> &&E) const { + checkError(E.takeError()); + return *E; + } + +private: + void checkError(Error Err) const { + if (Err) { + int ExitCode = GetExitCode(Err); + logAllUnhandledErrors(std::move(Err), errs(), Banner); + exit(ExitCode); + } + } + + std::string Banner; + std::function<int(const Error &)> GetExitCode; +}; + +/// Report a serious error, calling any installed error handler. See +/// ErrorHandling.h. +LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, + bool gen_crash_diag = true); + +} // namespace llvm + +#endif // LLVM_SUPPORT_ERROR_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/ErrorHandling.h b/third_party/llvm-subzero/include/llvm/Support/ErrorHandling.h new file mode 100644 index 0000000..7c1edd8 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ErrorHandling.h
@@ -0,0 +1,106 @@ +//===- llvm/Support/ErrorHandling.h - Fatal error handling ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an API used to indicate fatal error conditions. Non-fatal +// errors (most of them) should be handled through LLVMContext. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ERRORHANDLING_H +#define LLVM_SUPPORT_ERRORHANDLING_H + +#include "llvm/Support/Compiler.h" +#include <string> + +namespace llvm { +class StringRef; + class Twine; + + /// An error handler callback. + typedef void (*fatal_error_handler_t)(void *user_data, + const std::string& reason, + bool gen_crash_diag); + + /// install_fatal_error_handler - Installs a new error handler to be used + /// whenever a serious (non-recoverable) error is encountered by LLVM. + /// + /// If no error handler is installed the default is to print the error message + /// to stderr, and call exit(1). If an error handler is installed then it is + /// the handler's responsibility to log the message, it will no longer be + /// printed to stderr. If the error handler returns, then exit(1) will be + /// called. + /// + /// It is dangerous to naively use an error handler which throws an exception. + /// Even though some applications desire to gracefully recover from arbitrary + /// faults, blindly throwing exceptions through unfamiliar code isn't a way to + /// achieve this. + /// + /// \param user_data - An argument which will be passed to the install error + /// handler. + void install_fatal_error_handler(fatal_error_handler_t handler, + void *user_data = nullptr); + + /// Restores default error handling behaviour. + void remove_fatal_error_handler(); + + /// ScopedFatalErrorHandler - This is a simple helper class which just + /// calls install_fatal_error_handler in its constructor and + /// remove_fatal_error_handler in its destructor. + struct ScopedFatalErrorHandler { + explicit ScopedFatalErrorHandler(fatal_error_handler_t handler, + void *user_data = nullptr) { + install_fatal_error_handler(handler, user_data); + } + + ~ScopedFatalErrorHandler() { remove_fatal_error_handler(); } + }; + +/// Reports a serious error, calling any installed error handler. These +/// functions are intended to be used for error conditions which are outside +/// the control of the compiler (I/O errors, invalid user input, etc.) +/// +/// If no error handler is installed the default is to print the message to +/// standard error, followed by a newline. +/// After the error handler is called this function will call exit(1), it +/// does not return. +LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, + bool gen_crash_diag = true); +LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason, + bool gen_crash_diag = true); +LLVM_ATTRIBUTE_NORETURN void report_fatal_error(StringRef reason, + bool gen_crash_diag = true); +LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const Twine &reason, + bool gen_crash_diag = true); + + /// This function calls abort(), and prints the optional message to stderr. + /// Use the llvm_unreachable macro (that adds location info), instead of + /// calling this function directly. + LLVM_ATTRIBUTE_NORETURN void + llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr, + unsigned line=0); +} + +/// Marks that the current location is not supposed to be reachable. +/// In !NDEBUG builds, prints the message and location info to stderr. +/// In NDEBUG builds, becomes an optimizer hint that the current location +/// is not supposed to be reachable. On compilers that don't support +/// such hints, prints a reduced message instead. +/// +/// Use this instead of assert(0). It conveys intent more clearly and +/// allows compilers to omit some unnecessary code. +#ifndef NDEBUG +#define llvm_unreachable(msg) \ + ::llvm::llvm_unreachable_internal(msg, __FILE__, __LINE__) +#elif defined(LLVM_BUILTIN_UNREACHABLE) +#define llvm_unreachable(msg) LLVM_BUILTIN_UNREACHABLE +#else +#define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal() +#endif + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/ErrorOr.h b/third_party/llvm-subzero/include/llvm/Support/ErrorOr.h new file mode 100644 index 0000000..877f406 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ErrorOr.h
@@ -0,0 +1,287 @@ +//===- llvm/Support/ErrorOr.h - Error Smart Pointer -------------*- C++ -*-===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// +/// Provides ErrorOr<T> smart pointer. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ERROROR_H +#define LLVM_SUPPORT_ERROROR_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/AlignOf.h" +#include <cassert> +#include <system_error> +#include <type_traits> + +namespace llvm { +/// \brief Stores a reference that can be changed. +template <typename T> +class ReferenceStorage { + T *Storage; + +public: + ReferenceStorage(T &Ref) : Storage(&Ref) {} + + operator T &() const { return *Storage; } + T &get() const { return *Storage; } +}; + +/// \brief Represents either an error or a value T. +/// +/// ErrorOr<T> is a pointer-like class that represents the result of an +/// operation. The result is either an error, or a value of type T. This is +/// designed to emulate the usage of returning a pointer where nullptr indicates +/// failure. However instead of just knowing that the operation failed, we also +/// have an error_code and optional user data that describes why it failed. +/// +/// It is used like the following. +/// \code +/// ErrorOr<Buffer> getBuffer(); +/// +/// auto buffer = getBuffer(); +/// if (error_code ec = buffer.getError()) +/// return ec; +/// buffer->write("adena"); +/// \endcode +/// +/// +/// Implicit conversion to bool returns true if there is a usable value. The +/// unary * and -> operators provide pointer like access to the value. Accessing +/// the value when there is an error has undefined behavior. +/// +/// When T is a reference type the behavior is slightly different. The reference +/// is held in a std::reference_wrapper<std::remove_reference<T>::type>, and +/// there is special handling to make operator -> work as if T was not a +/// reference. +/// +/// T cannot be a rvalue reference. +template<class T> +class ErrorOr { + template <class OtherT> friend class ErrorOr; + static const bool isRef = std::is_reference<T>::value; + typedef ReferenceStorage<typename std::remove_reference<T>::type> wrap; + +public: + typedef typename std::conditional<isRef, wrap, T>::type storage_type; + +private: + typedef typename std::remove_reference<T>::type &reference; + typedef const typename std::remove_reference<T>::type &const_reference; + typedef typename std::remove_reference<T>::type *pointer; + typedef const typename std::remove_reference<T>::type *const_pointer; + +public: + template <class E> + ErrorOr(E ErrorCode, + typename std::enable_if<std::is_error_code_enum<E>::value || + std::is_error_condition_enum<E>::value, + void *>::type = nullptr) + : HasError(true) { + new (getErrorStorage()) std::error_code(make_error_code(ErrorCode)); + } + + ErrorOr(std::error_code EC) : HasError(true) { + new (getErrorStorage()) std::error_code(EC); + } + + template <class OtherT> + ErrorOr(OtherT &&Val, + typename std::enable_if<std::is_convertible<OtherT, T>::value>::type + * = nullptr) + : HasError(false) { + new (getStorage()) storage_type(std::forward<OtherT>(Val)); + } + + ErrorOr(const ErrorOr &Other) { + copyConstruct(Other); + } + + template <class OtherT> + ErrorOr( + const ErrorOr<OtherT> &Other, + typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * = + nullptr) { + copyConstruct(Other); + } + + template <class OtherT> + explicit ErrorOr( + const ErrorOr<OtherT> &Other, + typename std::enable_if< + !std::is_convertible<OtherT, const T &>::value>::type * = nullptr) { + copyConstruct(Other); + } + + ErrorOr(ErrorOr &&Other) { + moveConstruct(std::move(Other)); + } + + template <class OtherT> + ErrorOr( + ErrorOr<OtherT> &&Other, + typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * = + nullptr) { + moveConstruct(std::move(Other)); + } + + // This might eventually need SFINAE but it's more complex than is_convertible + // & I'm too lazy to write it right now. + template <class OtherT> + explicit ErrorOr( + ErrorOr<OtherT> &&Other, + typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * = + nullptr) { + moveConstruct(std::move(Other)); + } + + ErrorOr &operator=(const ErrorOr &Other) { + copyAssign(Other); + return *this; + } + + ErrorOr &operator=(ErrorOr &&Other) { + moveAssign(std::move(Other)); + return *this; + } + + ~ErrorOr() { + if (!HasError) + getStorage()->~storage_type(); + } + + /// \brief Return false if there is an error. + explicit operator bool() const { + return !HasError; + } + + reference get() { return *getStorage(); } + const_reference get() const { return const_cast<ErrorOr<T> *>(this)->get(); } + + std::error_code getError() const { + return HasError ? *getErrorStorage() : std::error_code(); + } + + pointer operator ->() { + return toPointer(getStorage()); + } + + const_pointer operator->() const { return toPointer(getStorage()); } + + reference operator *() { + return *getStorage(); + } + + const_reference operator*() const { return *getStorage(); } + +private: + template <class OtherT> + void copyConstruct(const ErrorOr<OtherT> &Other) { + if (!Other.HasError) { + // Get the other value. + HasError = false; + new (getStorage()) storage_type(*Other.getStorage()); + } else { + // Get other's error. + HasError = true; + new (getErrorStorage()) std::error_code(Other.getError()); + } + } + + template <class T1> + static bool compareThisIfSameType(const T1 &a, const T1 &b) { + return &a == &b; + } + + template <class T1, class T2> + static bool compareThisIfSameType(const T1 &a, const T2 &b) { + return false; + } + + template <class OtherT> + void copyAssign(const ErrorOr<OtherT> &Other) { + if (compareThisIfSameType(*this, Other)) + return; + + this->~ErrorOr(); + new (this) ErrorOr(Other); + } + + template <class OtherT> + void moveConstruct(ErrorOr<OtherT> &&Other) { + if (!Other.HasError) { + // Get the other value. + HasError = false; + new (getStorage()) storage_type(std::move(*Other.getStorage())); + } else { + // Get other's error. + HasError = true; + new (getErrorStorage()) std::error_code(Other.getError()); + } + } + + template <class OtherT> + void moveAssign(ErrorOr<OtherT> &&Other) { + if (compareThisIfSameType(*this, Other)) + return; + + this->~ErrorOr(); + new (this) ErrorOr(std::move(Other)); + } + + pointer toPointer(pointer Val) { + return Val; + } + + const_pointer toPointer(const_pointer Val) const { return Val; } + + pointer toPointer(wrap *Val) { + return &Val->get(); + } + + const_pointer toPointer(const wrap *Val) const { return &Val->get(); } + + storage_type *getStorage() { + assert(!HasError && "Cannot get value when an error exists!"); + return reinterpret_cast<storage_type*>(TStorage.buffer); + } + + const storage_type *getStorage() const { + assert(!HasError && "Cannot get value when an error exists!"); + return reinterpret_cast<const storage_type*>(TStorage.buffer); + } + + std::error_code *getErrorStorage() { + assert(HasError && "Cannot get error when a value exists!"); + return reinterpret_cast<std::error_code *>(ErrorStorage.buffer); + } + + const std::error_code *getErrorStorage() const { + return const_cast<ErrorOr<T> *>(this)->getErrorStorage(); + } + + union { + AlignedCharArrayUnion<storage_type> TStorage; + AlignedCharArrayUnion<std::error_code> ErrorStorage; + }; + bool HasError : 1; +}; + +template <class T, class E> +typename std::enable_if<std::is_error_code_enum<E>::value || + std::is_error_condition_enum<E>::value, + bool>::type +operator==(const ErrorOr<T> &Err, E Code) { + return Err.getError() == Code; +} +} // end namespace llvm + +#endif // LLVM_SUPPORT_ERROROR_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/FileSystem.h b/third_party/llvm-subzero/include/llvm/Support/FileSystem.h new file mode 100644 index 0000000..42a6180 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/FileSystem.h
@@ -0,0 +1,935 @@ +//===- llvm/Support/FileSystem.h - File System OS Concept -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::fs namespace. It is designed after +// TR2/boost filesystem (v3), but modified to remove exception handling and the +// path class. +// +// All functions return an error_code and their actual work via the last out +// argument. The out argument is defined if and only if errc::success is +// returned. A function may return any error code in the generic or system +// category. However, they shall be equivalent to any error conditions listed +// in each functions respective documentation if the condition applies. [ note: +// this does not guarantee that error_code will be in the set of explicitly +// listed codes, but it does guarantee that if any of the explicitly listed +// errors occur, the correct error_code will be used ]. All functions may +// return errc::not_enough_memory if there is not enough memory to complete the +// operation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FILESYSTEM_H +#define LLVM_SUPPORT_FILESYSTEM_H + +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/TimeValue.h" +#include <cassert> +#include <cstdint> +#include <ctime> +#include <stack> +#include <string> +#include <system_error> +#include <tuple> +#include <vector> + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +namespace llvm { +namespace sys { +namespace fs { + +/// An enumeration for the file system's view of the type. +enum class file_type { + status_error, + file_not_found, + regular_file, + directory_file, + symlink_file, + block_file, + character_file, + fifo_file, + socket_file, + type_unknown +}; + +/// space_info - Self explanatory. +struct space_info { + uint64_t capacity; + uint64_t free; + uint64_t available; +}; + +enum perms { + no_perms = 0, + owner_read = 0400, + owner_write = 0200, + owner_exe = 0100, + owner_all = owner_read | owner_write | owner_exe, + group_read = 040, + group_write = 020, + group_exe = 010, + group_all = group_read | group_write | group_exe, + others_read = 04, + others_write = 02, + others_exe = 01, + others_all = others_read | others_write | others_exe, + all_read = owner_read | group_read | others_read, + all_write = owner_write | group_write | others_write, + all_exe = owner_exe | group_exe | others_exe, + all_all = owner_all | group_all | others_all, + set_uid_on_exe = 04000, + set_gid_on_exe = 02000, + sticky_bit = 01000, + perms_not_known = 0xFFFF +}; + +// Helper functions so that you can use & and | to manipulate perms bits: +inline perms operator|(perms l, perms r) { + return static_cast<perms>(static_cast<unsigned short>(l) | + static_cast<unsigned short>(r)); +} +inline perms operator&(perms l, perms r) { + return static_cast<perms>(static_cast<unsigned short>(l) & + static_cast<unsigned short>(r)); +} +inline perms &operator|=(perms &l, perms r) { + l = l | r; + return l; +} +inline perms &operator&=(perms &l, perms r) { + l = l & r; + return l; +} +inline perms operator~(perms x) { + return static_cast<perms>(~static_cast<unsigned short>(x)); +} + +class UniqueID { + uint64_t Device; + uint64_t File; + +public: + UniqueID() = default; + UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {} + bool operator==(const UniqueID &Other) const { + return Device == Other.Device && File == Other.File; + } + bool operator!=(const UniqueID &Other) const { return !(*this == Other); } + bool operator<(const UniqueID &Other) const { + return std::tie(Device, File) < std::tie(Other.Device, Other.File); + } + uint64_t getDevice() const { return Device; } + uint64_t getFile() const { return File; } +}; + +/// file_status - Represents the result of a call to stat and friends. It has +/// a platform-specific member to store the result. +class file_status +{ + #if defined(LLVM_ON_UNIX) + dev_t fs_st_dev; + ino_t fs_st_ino; + time_t fs_st_atime; + time_t fs_st_mtime; + uid_t fs_st_uid; + gid_t fs_st_gid; + off_t fs_st_size; + #elif defined (LLVM_ON_WIN32) + uint32_t LastAccessedTimeHigh; + uint32_t LastAccessedTimeLow; + uint32_t LastWriteTimeHigh; + uint32_t LastWriteTimeLow; + uint32_t VolumeSerialNumber; + uint32_t FileSizeHigh; + uint32_t FileSizeLow; + uint32_t FileIndexHigh; + uint32_t FileIndexLow; + #endif + friend bool equivalent(file_status A, file_status B); + file_type Type; + perms Perms; + +public: + #if defined(LLVM_ON_UNIX) + file_status() + : fs_st_dev(0), fs_st_ino(0), fs_st_atime(0), fs_st_mtime(0), + fs_st_uid(0), fs_st_gid(0), fs_st_size(0), + Type(file_type::status_error), Perms(perms_not_known) {} + + file_status(file_type Type) + : fs_st_dev(0), fs_st_ino(0), fs_st_atime(0), fs_st_mtime(0), + fs_st_uid(0), fs_st_gid(0), fs_st_size(0), Type(Type), + Perms(perms_not_known) {} + + file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t ATime, + time_t MTime, uid_t UID, gid_t GID, off_t Size) + : fs_st_dev(Dev), fs_st_ino(Ino), fs_st_atime(ATime), fs_st_mtime(MTime), + fs_st_uid(UID), fs_st_gid(GID), fs_st_size(Size), Type(Type), + Perms(Perms) {} + #elif defined(LLVM_ON_WIN32) + file_status() + : LastAccessedTimeHigh(0), LastAccessedTimeLow(0), LastWriteTimeHigh(0), + LastWriteTimeLow(0), VolumeSerialNumber(0), FileSizeHigh(0), + FileSizeLow(0), FileIndexHigh(0), FileIndexLow(0), + Type(file_type::status_error), Perms(perms_not_known) {} + + file_status(file_type Type) + : LastAccessedTimeHigh(0), LastAccessedTimeLow(0), LastWriteTimeHigh(0), + LastWriteTimeLow(0), VolumeSerialNumber(0), FileSizeHigh(0), + FileSizeLow(0), FileIndexHigh(0), FileIndexLow(0), Type(Type), + Perms(perms_not_known) {} + + file_status(file_type Type, uint32_t LastAccessTimeHigh, + uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh, + uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber, + uint32_t FileSizeHigh, uint32_t FileSizeLow, + uint32_t FileIndexHigh, uint32_t FileIndexLow) + : LastAccessedTimeHigh(LastAccessTimeHigh), LastAccessedTimeLow(LastAccessTimeLow), + LastWriteTimeHigh(LastWriteTimeHigh), + LastWriteTimeLow(LastWriteTimeLow), + VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh), + FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh), + FileIndexLow(FileIndexLow), Type(Type), Perms(perms_not_known) {} + #endif + + // getters + file_type type() const { return Type; } + perms permissions() const { return Perms; } + TimeValue getLastAccessedTime() const; + TimeValue getLastModificationTime() const; + UniqueID getUniqueID() const; + + #if defined(LLVM_ON_UNIX) + uint32_t getUser() const { return fs_st_uid; } + uint32_t getGroup() const { return fs_st_gid; } + uint64_t getSize() const { return fs_st_size; } + #elif defined (LLVM_ON_WIN32) + uint32_t getUser() const { + return 9999; // Not applicable to Windows, so... + } + uint32_t getGroup() const { + return 9999; // Not applicable to Windows, so... + } + uint64_t getSize() const { + return (uint64_t(FileSizeHigh) << 32) + FileSizeLow; + } + #endif + + // setters + void type(file_type v) { Type = v; } + void permissions(perms p) { Perms = p; } +}; + +/// file_magic - An "enum class" enumeration of file types based on magic (the first +/// N bytes of the file). +struct file_magic { + enum Impl { + unknown = 0, ///< Unrecognized file + bitcode, ///< Bitcode file + archive, ///< ar style archive file + elf, ///< ELF Unknown type + elf_relocatable, ///< ELF Relocatable object file + elf_executable, ///< ELF Executable image + elf_shared_object, ///< ELF dynamically linked shared lib + elf_core, ///< ELF core image + macho_object, ///< Mach-O Object file + macho_executable, ///< Mach-O Executable + macho_fixed_virtual_memory_shared_lib, ///< Mach-O Shared Lib, FVM + macho_core, ///< Mach-O Core File + macho_preload_executable, ///< Mach-O Preloaded Executable + macho_dynamically_linked_shared_lib, ///< Mach-O dynlinked shared lib + macho_dynamic_linker, ///< The Mach-O dynamic linker + macho_bundle, ///< Mach-O Bundle file + macho_dynamically_linked_shared_lib_stub, ///< Mach-O Shared lib stub + macho_dsym_companion, ///< Mach-O dSYM companion file + macho_kext_bundle, ///< Mach-O kext bundle file + macho_universal_binary, ///< Mach-O universal binary + coff_object, ///< COFF object file + coff_import_library, ///< COFF import library + pecoff_executable, ///< PECOFF executable file + windows_resource ///< Windows compiled resource file (.rc) + }; + + bool is_object() const { + return V != unknown; + } + + file_magic() : V(unknown) {} + file_magic(Impl V) : V(V) {} + operator Impl() const { return V; } + +private: + Impl V; +}; + +/// @} +/// @name Physical Operators +/// @{ + +/// @brief Make \a path an absolute path. +/// +/// Makes \a path absolute using the \a current_directory if it is not already. +/// An empty \a path will result in the \a current_directory. +/// +/// /absolute/path => /absolute/path +/// relative/../path => <current-directory>/relative/../path +/// +/// @param path A path that is modified to be an absolute path. +/// @returns errc::success if \a path has been made absolute, otherwise a +/// platform-specific error_code. +std::error_code make_absolute(const Twine ¤t_directory, + SmallVectorImpl<char> &path); + +/// @brief Make \a path an absolute path. +/// +/// Makes \a path absolute using the current directory if it is not already. An +/// empty \a path will result in the current directory. +/// +/// /absolute/path => /absolute/path +/// relative/../path => <current-directory>/relative/../path +/// +/// @param path A path that is modified to be an absolute path. +/// @returns errc::success if \a path has been made absolute, otherwise a +/// platform-specific error_code. +std::error_code make_absolute(SmallVectorImpl<char> &path); + +/// @brief Create all the non-existent directories in path. +/// +/// @param path Directories to create. +/// @returns errc::success if is_directory(path), otherwise a platform +/// specific error_code. If IgnoreExisting is false, also returns +/// error if the directory already existed. +std::error_code create_directories(const Twine &path, + bool IgnoreExisting = true, + perms Perms = owner_all | group_all); + +/// @brief Create the directory in path. +/// +/// @param path Directory to create. +/// @returns errc::success if is_directory(path), otherwise a platform +/// specific error_code. If IgnoreExisting is false, also returns +/// error if the directory already existed. +std::error_code create_directory(const Twine &path, bool IgnoreExisting = true, + perms Perms = owner_all | group_all); + +/// @brief Create a link from \a from to \a to. +/// +/// The link may be a soft or a hard link, depending on the platform. The caller +/// may not assume which one. Currently on windows it creates a hard link since +/// soft links require extra privileges. On unix, it creates a soft link since +/// hard links don't work on SMB file systems. +/// +/// @param to The path to hard link to. +/// @param from The path to hard link from. This is created. +/// @returns errc::success if the link was created, otherwise a platform +/// specific error_code. +std::error_code create_link(const Twine &to, const Twine &from); + +/// @brief Get the current path. +/// +/// @param result Holds the current path on return. +/// @returns errc::success if the current path has been stored in result, +/// otherwise a platform-specific error_code. +std::error_code current_path(SmallVectorImpl<char> &result); + +/// @brief Remove path. Equivalent to POSIX remove(). +/// +/// @param path Input path. +/// @returns errc::success if path has been removed or didn't exist, otherwise a +/// platform-specific error code. If IgnoreNonExisting is false, also +/// returns error if the file didn't exist. +std::error_code remove(const Twine &path, bool IgnoreNonExisting = true); + +/// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). +/// +/// @param from The path to rename from. +/// @param to The path to rename to. This is created. +std::error_code rename(const Twine &from, const Twine &to); + +/// @brief Copy the contents of \a From to \a To. +/// +/// @param From The path to copy from. +/// @param To The path to copy to. This is created. +std::error_code copy_file(const Twine &From, const Twine &To); + +/// @brief Resize path to size. File is resized as if by POSIX truncate(). +/// +/// @param FD Input file descriptor. +/// @param Size Size to resize to. +/// @returns errc::success if \a path has been resized to \a size, otherwise a +/// platform-specific error_code. +std::error_code resize_file(int FD, uint64_t Size); + +/// @} +/// @name Physical Observers +/// @{ + +/// @brief Does file exist? +/// +/// @param status A file_status previously returned from stat. +/// @returns True if the file represented by status exists, false if it does +/// not. +bool exists(file_status status); + +enum class AccessMode { Exist, Write, Execute }; + +/// @brief Can the file be accessed? +/// +/// @param Path Input path. +/// @returns errc::success if the path can be accessed, otherwise a +/// platform-specific error_code. +std::error_code access(const Twine &Path, AccessMode Mode); + +/// @brief Does file exist? +/// +/// @param Path Input path. +/// @returns True if it exists, false otherwise. +inline bool exists(const Twine &Path) { + return !access(Path, AccessMode::Exist); +} + +/// @brief Can we execute this file? +/// +/// @param Path Input path. +/// @returns True if we can execute it, false otherwise. +bool can_execute(const Twine &Path); + +/// @brief Can we write this file? +/// +/// @param Path Input path. +/// @returns True if we can write to it, false otherwise. +inline bool can_write(const Twine &Path) { + return !access(Path, AccessMode::Write); +} + +/// @brief Do file_status's represent the same thing? +/// +/// @param A Input file_status. +/// @param B Input file_status. +/// +/// assert(status_known(A) || status_known(B)); +/// +/// @returns True if A and B both represent the same file system entity, false +/// otherwise. +bool equivalent(file_status A, file_status B); + +/// @brief Do paths represent the same thing? +/// +/// assert(status_known(A) || status_known(B)); +/// +/// @param A Input path A. +/// @param B Input path B. +/// @param result Set to true if stat(A) and stat(B) have the same device and +/// inode (or equivalent). +/// @returns errc::success if result has been successfully set, otherwise a +/// platform-specific error_code. +std::error_code equivalent(const Twine &A, const Twine &B, bool &result); + +/// @brief Simpler version of equivalent for clients that don't need to +/// differentiate between an error and false. +inline bool equivalent(const Twine &A, const Twine &B) { + bool result; + return !equivalent(A, B, result) && result; +} + +/// @brief Does status represent a directory? +/// +/// @param status A file_status previously returned from status. +/// @returns status.type() == file_type::directory_file. +bool is_directory(file_status status); + +/// @brief Is path a directory? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a directory, false if it is not. +/// Undefined otherwise. +/// @returns errc::success if result has been successfully set, otherwise a +/// platform-specific error_code. +std::error_code is_directory(const Twine &path, bool &result); + +/// @brief Simpler version of is_directory for clients that don't need to +/// differentiate between an error and false. +inline bool is_directory(const Twine &Path) { + bool Result; + return !is_directory(Path, Result) && Result; +} + +/// @brief Does status represent a regular file? +/// +/// @param status A file_status previously returned from status. +/// @returns status_known(status) && status.type() == file_type::regular_file. +bool is_regular_file(file_status status); + +/// @brief Is path a regular file? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a regular file, false if it is not. +/// Undefined otherwise. +/// @returns errc::success if result has been successfully set, otherwise a +/// platform-specific error_code. +std::error_code is_regular_file(const Twine &path, bool &result); + +/// @brief Simpler version of is_regular_file for clients that don't need to +/// differentiate between an error and false. +inline bool is_regular_file(const Twine &Path) { + bool Result; + if (is_regular_file(Path, Result)) + return false; + return Result; +} + +/// @brief Does this status represent something that exists but is not a +/// directory, regular file, or symlink? +/// +/// @param status A file_status previously returned from status. +/// @returns exists(s) && !is_regular_file(s) && !is_directory(s) +bool is_other(file_status status); + +/// @brief Is path something that exists but is not a directory, +/// regular file, or symlink? +/// +/// @param path Input path. +/// @param result Set to true if \a path exists, but is not a directory, regular +/// file, or a symlink, false if it does not. Undefined otherwise. +/// @returns errc::success if result has been successfully set, otherwise a +/// platform-specific error_code. +std::error_code is_other(const Twine &path, bool &result); + +/// @brief Get file status as if by POSIX stat(). +/// +/// @param path Input path. +/// @param result Set to the file status. +/// @returns errc::success if result has been successfully set, otherwise a +/// platform-specific error_code. +std::error_code status(const Twine &path, file_status &result); + +/// @brief A version for when a file descriptor is already available. +std::error_code status(int FD, file_status &Result); + +/// @brief Get file size. +/// +/// @param Path Input path. +/// @param Result Set to the size of the file in \a Path. +/// @returns errc::success if result has been successfully set, otherwise a +/// platform-specific error_code. +inline std::error_code file_size(const Twine &Path, uint64_t &Result) { + file_status Status; + std::error_code EC = status(Path, Status); + if (EC) + return EC; + Result = Status.getSize(); + return std::error_code(); +} + +/// @brief Set the file modification and access time. +/// +/// @returns errc::success if the file times were successfully set, otherwise a +/// platform-specific error_code or errc::function_not_supported on +/// platforms where the functionality isn't available. +std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time); + +/// @brief Is status available? +/// +/// @param s Input file status. +/// @returns True if status() != status_error. +bool status_known(file_status s); + +/// @brief Is status available? +/// +/// @param path Input path. +/// @param result Set to true if status() != status_error. +/// @returns errc::success if result has been successfully set, otherwise a +/// platform-specific error_code. +std::error_code status_known(const Twine &path, bool &result); + +/// @brief Create a uniquely named file. +/// +/// Generates a unique path suitable for a temporary file and then opens it as a +/// file. The name is based on \a model with '%' replaced by a random char in +/// [0-9a-f]. If \a model is not an absolute path, the temporary file will be +/// created in the current directory. +/// +/// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s +/// +/// This is an atomic operation. Either the file is created and opened, or the +/// file system is left untouched. +/// +/// The intended use is for files that are to be kept, possibly after +/// renaming them. For example, when running 'clang -c foo.o', the file can +/// be first created as foo-abc123.o and then renamed. +/// +/// @param Model Name to base unique path off of. +/// @param ResultFD Set to the opened file's file descriptor. +/// @param ResultPath Set to the opened file's absolute path. +/// @returns errc::success if Result{FD,Path} have been successfully set, +/// otherwise a platform-specific error_code. +std::error_code createUniqueFile(const Twine &Model, int &ResultFD, + SmallVectorImpl<char> &ResultPath, + unsigned Mode = all_read | all_write); + +/// @brief Simpler version for clients that don't want an open file. +std::error_code createUniqueFile(const Twine &Model, + SmallVectorImpl<char> &ResultPath); + +/// @brief Create a file in the system temporary directory. +/// +/// The filename is of the form prefix-random_chars.suffix. Since the directory +/// is not know to the caller, Prefix and Suffix cannot have path separators. +/// The files are created with mode 0600. +/// +/// This should be used for things like a temporary .s that is removed after +/// running the assembler. +std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, + int &ResultFD, + SmallVectorImpl<char> &ResultPath); + +/// @brief Simpler version for clients that don't want an open file. +std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, + SmallVectorImpl<char> &ResultPath); + +std::error_code createUniqueDirectory(const Twine &Prefix, + SmallVectorImpl<char> &ResultPath); + +/// @brief Fetch a path to an open file, as specified by a file descriptor +/// +/// @param FD File descriptor to a currently open file +/// @param ResultPath The buffer into which to write the path +std::error_code getPathFromOpenFD(int FD, SmallVectorImpl<char> &ResultPath); + +enum OpenFlags : unsigned { + F_None = 0, + + /// F_Excl - When opening a file, this flag makes raw_fd_ostream + /// report an error if the file already exists. + F_Excl = 1, + + /// F_Append - When opening a file, if it already exists append to the + /// existing file instead of returning an error. This may not be specified + /// with F_Excl. + F_Append = 2, + + /// The file should be opened in text mode on platforms that make this + /// distinction. + F_Text = 4, + + /// Open the file for read and write. + F_RW = 8 +}; + +inline OpenFlags operator|(OpenFlags A, OpenFlags B) { + return OpenFlags(unsigned(A) | unsigned(B)); +} + +inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) { + A = A | B; + return A; +} + +std::error_code openFileForWrite(const Twine &Name, int &ResultFD, + OpenFlags Flags, unsigned Mode = 0666); + +std::error_code openFileForRead(const Twine &Name, int &ResultFD, + SmallVectorImpl<char> *RealPath = nullptr); + +/// @brief Identify the type of a binary file based on how magical it is. +file_magic identify_magic(StringRef magic); + +/// @brief Get and identify \a path's type based on its content. +/// +/// @param path Input path. +/// @param result Set to the type of file, or file_magic::unknown. +/// @returns errc::success if result has been successfully set, otherwise a +/// platform-specific error_code. +std::error_code identify_magic(const Twine &path, file_magic &result); + +std::error_code getUniqueID(const Twine Path, UniqueID &Result); + +/// @brief Get disk space usage information. +/// +/// Note: Users must be careful about "Time Of Check, Time Of Use" kind of bug. +/// Note: Windows reports results according to the quota allocated to the user. +/// +/// @param Path Input path. +/// @returns a space_info structure filled with the capacity, free, and +/// available space on the device \a Path is on. A platform specific error_code +/// is returned on error. +ErrorOr<space_info> disk_space(const Twine &Path); + +/// This class represents a memory mapped file. It is based on +/// boost::iostreams::mapped_file. +class mapped_file_region { + mapped_file_region() = delete; + mapped_file_region(mapped_file_region&) = delete; + mapped_file_region &operator =(mapped_file_region&) = delete; + +public: + enum mapmode { + readonly, ///< May only access map via const_data as read only. + readwrite, ///< May access map via data and modify it. Written to path. + priv ///< May modify via data, but changes are lost on destruction. + }; + +private: + /// Platform-specific mapping state. + uint64_t Size; + void *Mapping; + + std::error_code init(int FD, uint64_t Offset, mapmode Mode); + +public: + /// \param fd An open file descriptor to map. mapped_file_region takes + /// ownership if closefd is true. It must have been opended in the correct + /// mode. + mapped_file_region(int fd, mapmode mode, uint64_t length, uint64_t offset, + std::error_code &ec); + + ~mapped_file_region(); + + uint64_t size() const; + char *data() const; + + /// Get a const view of the data. Modifying this memory has undefined + /// behavior. + const char *const_data() const; + + /// \returns The minimum alignment offset must be. + static int alignment(); +}; + +/// Return the path to the main executable, given the value of argv[0] from +/// program startup and the address of main itself. In extremis, this function +/// may fail and return an empty path. +std::string getMainExecutable(const char *argv0, void *MainExecAddr); + +/// @} +/// @name Iterators +/// @{ + +/// directory_entry - A single entry in a directory. Caches the status either +/// from the result of the iteration syscall, or the first time status is +/// called. +class directory_entry { + std::string Path; + mutable file_status Status; + +public: + explicit directory_entry(const Twine &path, file_status st = file_status()) + : Path(path.str()) + , Status(st) {} + + directory_entry() {} + + void assign(const Twine &path, file_status st = file_status()) { + Path = path.str(); + Status = st; + } + + void replace_filename(const Twine &filename, file_status st = file_status()); + + const std::string &path() const { return Path; } + std::error_code status(file_status &result) const; + + bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; } + bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); } + bool operator< (const directory_entry& rhs) const; + bool operator<=(const directory_entry& rhs) const; + bool operator> (const directory_entry& rhs) const; + bool operator>=(const directory_entry& rhs) const; +}; + +namespace detail { + struct DirIterState; + + std::error_code directory_iterator_construct(DirIterState &, StringRef); + std::error_code directory_iterator_increment(DirIterState &); + std::error_code directory_iterator_destruct(DirIterState &); + + /// DirIterState - Keeps state for the directory_iterator. It is reference + /// counted in order to preserve InputIterator semantics on copy. + struct DirIterState : public RefCountedBase<DirIterState> { + DirIterState() + : IterationHandle(0) {} + + ~DirIterState() { + directory_iterator_destruct(*this); + } + + intptr_t IterationHandle; + directory_entry CurrentEntry; + }; +} // end namespace detail + +/// directory_iterator - Iterates through the entries in path. There is no +/// operator++ because we need an error_code. If it's really needed we can make +/// it call report_fatal_error on error. +class directory_iterator { + IntrusiveRefCntPtr<detail::DirIterState> State; + +public: + explicit directory_iterator(const Twine &path, std::error_code &ec) { + State = new detail::DirIterState; + SmallString<128> path_storage; + ec = detail::directory_iterator_construct(*State, + path.toStringRef(path_storage)); + } + + explicit directory_iterator(const directory_entry &de, std::error_code &ec) { + State = new detail::DirIterState; + ec = detail::directory_iterator_construct(*State, de.path()); + } + + /// Construct end iterator. + directory_iterator() : State(nullptr) {} + + // No operator++ because we need error_code. + directory_iterator &increment(std::error_code &ec) { + ec = directory_iterator_increment(*State); + return *this; + } + + const directory_entry &operator*() const { return State->CurrentEntry; } + const directory_entry *operator->() const { return &State->CurrentEntry; } + + bool operator==(const directory_iterator &RHS) const { + if (State == RHS.State) + return true; + if (!RHS.State) + return State->CurrentEntry == directory_entry(); + if (!State) + return RHS.State->CurrentEntry == directory_entry(); + return State->CurrentEntry == RHS.State->CurrentEntry; + } + + bool operator!=(const directory_iterator &RHS) const { + return !(*this == RHS); + } + // Other members as required by + // C++ Std, 24.1.1 Input iterators [input.iterators] +}; + +namespace detail { + /// RecDirIterState - Keeps state for the recursive_directory_iterator. It is + /// reference counted in order to preserve InputIterator semantics on copy. + struct RecDirIterState : public RefCountedBase<RecDirIterState> { + RecDirIterState() + : Level(0) + , HasNoPushRequest(false) {} + + std::stack<directory_iterator, std::vector<directory_iterator> > Stack; + uint16_t Level; + bool HasNoPushRequest; + }; +} // end namespace detail + +/// recursive_directory_iterator - Same as directory_iterator except for it +/// recurses down into child directories. +class recursive_directory_iterator { + IntrusiveRefCntPtr<detail::RecDirIterState> State; + +public: + recursive_directory_iterator() {} + explicit recursive_directory_iterator(const Twine &path, std::error_code &ec) + : State(new detail::RecDirIterState) { + State->Stack.push(directory_iterator(path, ec)); + if (State->Stack.top() == directory_iterator()) + State.reset(); + } + // No operator++ because we need error_code. + recursive_directory_iterator &increment(std::error_code &ec) { + const directory_iterator end_itr; + + if (State->HasNoPushRequest) + State->HasNoPushRequest = false; + else { + file_status st; + if ((ec = State->Stack.top()->status(st))) return *this; + if (is_directory(st)) { + State->Stack.push(directory_iterator(*State->Stack.top(), ec)); + if (ec) return *this; + if (State->Stack.top() != end_itr) { + ++State->Level; + return *this; + } + State->Stack.pop(); + } + } + + while (!State->Stack.empty() + && State->Stack.top().increment(ec) == end_itr) { + State->Stack.pop(); + --State->Level; + } + + // Check if we are done. If so, create an end iterator. + if (State->Stack.empty()) + State.reset(); + + return *this; + } + + const directory_entry &operator*() const { return *State->Stack.top(); } + const directory_entry *operator->() const { return &*State->Stack.top(); } + + // observers + /// Gets the current level. Starting path is at level 0. + int level() const { return State->Level; } + + /// Returns true if no_push has been called for this directory_entry. + bool no_push_request() const { return State->HasNoPushRequest; } + + // modifiers + /// Goes up one level if Level > 0. + void pop() { + assert(State && "Cannot pop an end iterator!"); + assert(State->Level > 0 && "Cannot pop an iterator with level < 1"); + + const directory_iterator end_itr; + std::error_code ec; + do { + if (ec) + report_fatal_error("Error incrementing directory iterator."); + State->Stack.pop(); + --State->Level; + } while (!State->Stack.empty() + && State->Stack.top().increment(ec) == end_itr); + + // Check if we are done. If so, create an end iterator. + if (State->Stack.empty()) + State.reset(); + } + + /// Does not go down into the current directory_entry. + void no_push() { State->HasNoPushRequest = true; } + + bool operator==(const recursive_directory_iterator &RHS) const { + return State == RHS.State; + } + + bool operator!=(const recursive_directory_iterator &RHS) const { + return !(*this == RHS); + } + // Other members as required by + // C++ Std, 24.1.1 Input iterators [input.iterators] +}; + +/// @} + +} // end namespace fs +} // end namespace sys +} // end namespace llvm + +#endif // LLVM_SUPPORT_FILESYSTEM_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/FileUtilities.h b/third_party/llvm-subzero/include/llvm/Support/FileUtilities.h new file mode 100644 index 0000000..2ee2c60 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/FileUtilities.h
@@ -0,0 +1,78 @@ +//===- llvm/Support/FileUtilities.h - File System Utilities -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a family of utility functions which are useful for doing +// various things with files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FILEUTILITIES_H +#define LLVM_SUPPORT_FILEUTILITIES_H + +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" + +namespace llvm { + + /// DiffFilesWithTolerance - Compare the two files specified, returning 0 if + /// the files match, 1 if they are different, and 2 if there is a file error. + /// This function allows you to specify an absolute and relative FP error that + /// is allowed to exist. If you specify a string to fill in for the error + /// option, it will set the string to an error message if an error occurs, or + /// if the files are different. + /// + int DiffFilesWithTolerance(StringRef FileA, + StringRef FileB, + double AbsTol, double RelTol, + std::string *Error = nullptr); + + + /// FileRemover - This class is a simple object meant to be stack allocated. + /// If an exception is thrown from a region, the object removes the filename + /// specified (if deleteIt is true). + /// + class FileRemover { + SmallString<128> Filename; + bool DeleteIt; + public: + FileRemover() : DeleteIt(false) {} + + explicit FileRemover(const Twine& filename, bool deleteIt = true) + : DeleteIt(deleteIt) { + filename.toVector(Filename); + } + + ~FileRemover() { + if (DeleteIt) { + // Ignore problems deleting the file. + sys::fs::remove(Filename); + } + } + + /// setFile - Give ownership of the file to the FileRemover so it will + /// be removed when the object is destroyed. If the FileRemover already + /// had ownership of a file, remove it first. + void setFile(const Twine& filename, bool deleteIt = true) { + if (DeleteIt) { + // Ignore problems deleting the file. + sys::fs::remove(Filename); + } + + Filename.clear(); + filename.toVector(Filename); + DeleteIt = deleteIt; + } + + /// releaseFile - Take ownership of the file away from the FileRemover so it + /// will not be removed when the object is destroyed. + void releaseFile() { DeleteIt = false; } + }; +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Format.h b/third_party/llvm-subzero/include/llvm/Support/Format.h new file mode 100644 index 0000000..d5c301c --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Format.h
@@ -0,0 +1,195 @@ +//===- Format.h - Efficient printf-style formatting for streams -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the format() function, which can be used with other +// LLVM subsystems to provide printf-style formatting. This gives all the power +// and risk of printf. This can be used like this (with raw_ostreams as an +// example): +// +// OS << "mynumber: " << format("%4.5f", 1234.412) << '\n'; +// +// Or if you prefer: +// +// OS << format("mynumber: %4.5f\n", 1234.412); +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FORMAT_H +#define LLVM_SUPPORT_FORMAT_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include <cassert> +#include <cstdio> +#include <tuple> + +namespace llvm { + +/// This is a helper class used for handling formatted output. It is the +/// abstract base class of a templated derived class. +class format_object_base { +protected: + const char *Fmt; + ~format_object_base() = default; // Disallow polymorphic deletion. + format_object_base(const format_object_base &) = default; + virtual void home(); // Out of line virtual method. + + /// Call snprintf() for this object, on the given buffer and size. + virtual int snprint(char *Buffer, unsigned BufferSize) const = 0; + +public: + format_object_base(const char *fmt) : Fmt(fmt) {} + + /// Format the object into the specified buffer. On success, this returns + /// the length of the formatted string. If the buffer is too small, this + /// returns a length to retry with, which will be larger than BufferSize. + unsigned print(char *Buffer, unsigned BufferSize) const { + assert(BufferSize && "Invalid buffer size!"); + + // Print the string, leaving room for the terminating null. + int N = snprint(Buffer, BufferSize); + + // VC++ and old GlibC return negative on overflow, just double the size. + if (N < 0) + return BufferSize * 2; + + // Other implementations yield number of bytes needed, not including the + // final '\0'. + if (unsigned(N) >= BufferSize) + return N + 1; + + // Otherwise N is the length of output (not including the final '\0'). + return N; + } +}; + +/// These are templated helper classes used by the format function that +/// capture the object to be formated and the format string. When actually +/// printed, this synthesizes the string into a temporary buffer provided and +/// returns whether or not it is big enough. + +template <typename... Ts> +class format_object final : public format_object_base { + std::tuple<Ts...> Vals; + + template <std::size_t... Is> + int snprint_tuple(char *Buffer, unsigned BufferSize, + index_sequence<Is...>) const { +#ifdef _MSC_VER + return _snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...); +#else + return snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...); +#endif + } + +public: + format_object(const char *fmt, const Ts &... vals) + : format_object_base(fmt), Vals(vals...) {} + + int snprint(char *Buffer, unsigned BufferSize) const override { + return snprint_tuple(Buffer, BufferSize, index_sequence_for<Ts...>()); + } +}; + +/// These are helper functions used to produce formatted output. They use +/// template type deduction to construct the appropriate instance of the +/// format_object class to simplify their construction. +/// +/// This is typically used like: +/// \code +/// OS << format("%0.4f", myfloat) << '\n'; +/// \endcode + +template <typename... Ts> +inline format_object<Ts...> format(const char *Fmt, const Ts &... Vals) { + return format_object<Ts...>(Fmt, Vals...); +} + +/// This is a helper class used for left_justify() and right_justify(). +class FormattedString { + StringRef Str; + unsigned Width; + bool RightJustify; + friend class raw_ostream; + +public: + FormattedString(StringRef S, unsigned W, bool R) + : Str(S), Width(W), RightJustify(R) { } +}; + +/// left_justify - append spaces after string so total output is +/// \p Width characters. If \p Str is larger that \p Width, full string +/// is written with no padding. +inline FormattedString left_justify(StringRef Str, unsigned Width) { + return FormattedString(Str, Width, false); +} + +/// right_justify - add spaces before string so total output is +/// \p Width characters. If \p Str is larger that \p Width, full string +/// is written with no padding. +inline FormattedString right_justify(StringRef Str, unsigned Width) { + return FormattedString(Str, Width, true); +} + +/// This is a helper class used for format_hex() and format_decimal(). +class FormattedNumber { + uint64_t HexValue; + int64_t DecValue; + unsigned Width; + bool Hex; + bool Upper; + bool HexPrefix; + friend class raw_ostream; + +public: + FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U, + bool Prefix) + : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U), + HexPrefix(Prefix) {} +}; + +/// format_hex - Output \p N as a fixed width hexadecimal. If number will not +/// fit in width, full number is still printed. Examples: +/// OS << format_hex(255, 4) => 0xff +/// OS << format_hex(255, 4, true) => 0xFF +/// OS << format_hex(255, 6) => 0x00ff +/// OS << format_hex(255, 2) => 0xff +inline FormattedNumber format_hex(uint64_t N, unsigned Width, + bool Upper = false) { + assert(Width <= 18 && "hex width must be <= 18"); + return FormattedNumber(N, 0, Width, true, Upper, true); +} + +/// format_hex_no_prefix - Output \p N as a fixed width hexadecimal. Does not +/// prepend '0x' to the outputted string. If number will not fit in width, +/// full number is still printed. Examples: +/// OS << format_hex_no_prefix(255, 2) => ff +/// OS << format_hex_no_prefix(255, 2, true) => FF +/// OS << format_hex_no_prefix(255, 4) => 00ff +/// OS << format_hex_no_prefix(255, 1) => ff +inline FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, + bool Upper = false) { + assert(Width <= 16 && "hex width must be <= 16"); + return FormattedNumber(N, 0, Width, true, Upper, false); +} + +/// format_decimal - Output \p N as a right justified, fixed-width decimal. If +/// number will not fit in width, full number is still printed. Examples: +/// OS << format_decimal(0, 5) => " 0" +/// OS << format_decimal(255, 5) => " 255" +/// OS << format_decimal(-1, 3) => " -1" +/// OS << format_decimal(12345, 3) => "12345" +inline FormattedNumber format_decimal(int64_t N, unsigned Width) { + return FormattedNumber(0, N, Width, false, false, false); +} + +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Host.h b/third_party/llvm-subzero/include/llvm/Support/Host.h new file mode 100644 index 0000000..9e59a94 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Host.h
@@ -0,0 +1,76 @@ +//===- llvm/Support/Host.h - Host machine characteristics --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Methods for querying the nature of the host machine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_HOST_H +#define LLVM_SUPPORT_HOST_H + +#include "llvm/ADT/StringMap.h" + +#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) +#include <endian.h> +#elif defined(_AIX) +#include <sys/machine.h> +#else +#if !defined(BYTE_ORDER) && !defined(LLVM_ON_WIN32) +#include <machine/endian.h> +#endif +#endif + +#include <string> + +namespace llvm { +namespace sys { + +#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN + static const bool IsBigEndianHost = true; +#else + static const bool IsBigEndianHost = false; +#endif + + static const bool IsLittleEndianHost = !IsBigEndianHost; + + /// getDefaultTargetTriple() - Return the default target triple the compiler + /// has been configured to produce code for. + /// + /// The target triple is a string in the format of: + /// CPU_TYPE-VENDOR-OPERATING_SYSTEM + /// or + /// CPU_TYPE-VENDOR-KERNEL-OPERATING_SYSTEM + std::string getDefaultTargetTriple(); + + /// getProcessTriple() - Return an appropriate target triple for generating + /// code to be loaded into the current process, e.g. when using the JIT. + std::string getProcessTriple(); + + /// getHostCPUName - Get the LLVM name for the host CPU. The particular format + /// of the name is target dependent, and suitable for passing as -mcpu to the + /// target which matches the host. + /// + /// \return - The host CPU name, or empty if the CPU could not be determined. + StringRef getHostCPUName(); + + /// getHostCPUFeatures - Get the LLVM names for the host CPU features. + /// The particular format of the names are target dependent, and suitable for + /// passing as -mattr to the target which matches the host. + /// + /// \param Features - A string mapping feature names to either + /// true (if enabled) or false (if disabled). This routine makes no guarantees + /// about exactly which features may appear in this map, except that they are + /// all valid LLVM feature names. + /// + /// \return - True on success. + bool getHostCPUFeatures(StringMap<bool> &Features); +} +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/MD5.h b/third_party/llvm-subzero/include/llvm/Support/MD5.h new file mode 100644 index 0000000..42d8ca8 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/MD5.h
@@ -0,0 +1,83 @@ +/* + * This code is derived from (original license follows): + * + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer <solar at openwall.com> + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * See md5.c for more information. + */ + +#ifndef LLVM_SUPPORT_MD5_H +#define LLVM_SUPPORT_MD5_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +template <typename T> class ArrayRef; + +class MD5 { + // Any 32-bit or wider unsigned integer data type will do. + typedef uint32_t MD5_u32plus; + + MD5_u32plus a, b, c, d; + MD5_u32plus hi, lo; + uint8_t buffer[64]; + MD5_u32plus block[16]; + +public: + typedef uint8_t MD5Result[16]; + + MD5(); + + /// \brief Updates the hash for the byte stream provided. + void update(ArrayRef<uint8_t> Data); + + /// \brief Updates the hash for the StringRef provided. + void update(StringRef Str); + + /// \brief Finishes off the hash and puts the result in result. + void final(MD5Result &Result); + + /// \brief Translates the bytes in \p Res to a hex string that is + /// deposited into \p Str. The result will be of length 32. + static void stringifyResult(MD5Result &Result, SmallString<32> &Str); + +private: + const uint8_t *body(ArrayRef<uint8_t> Data); +}; + +/// Helper to compute and return lower 64 bits of the given string's MD5 hash. +inline uint64_t MD5Hash(StringRef Str) { + MD5 Hash; + Hash.update(Str); + llvm::MD5::MD5Result Result; + Hash.final(Result); + // Return the least significant 8 bytes. Our MD5 implementation returns the + // result in little endian, so we may need to swap bytes. + using namespace llvm::support; + return endian::read<uint64_t, little, unaligned>(Result); +} + +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/MachO.def b/third_party/llvm-subzero/include/llvm/Support/MachO.def new file mode 100644 index 0000000..9ca6440 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/MachO.def
@@ -0,0 +1,106 @@ +//,,,-- llvm/Support/MachO.def - The MachO file definitions -----*- C++ -*-,,,// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//,,,----------------------------------------------------------------------,,,// +// +// Definitions for MachO files +// +//,,,----------------------------------------------------------------------,,,// + +#ifdef HANDLE_LOAD_COMMAND + +HANDLE_LOAD_COMMAND(LC_SEGMENT, 0x00000001u, segment_command) +HANDLE_LOAD_COMMAND(LC_SYMTAB, 0x00000002u, symtab_command) +HANDLE_LOAD_COMMAND(LC_SYMSEG, 0x00000003u, symseg_command) +HANDLE_LOAD_COMMAND(LC_THREAD, 0x00000004u, thread_command) +HANDLE_LOAD_COMMAND(LC_UNIXTHREAD, 0x00000005u, thread_command) +HANDLE_LOAD_COMMAND(LC_LOADFVMLIB, 0x00000006u, fvmlib_command) +HANDLE_LOAD_COMMAND(LC_IDFVMLIB, 0x00000007u, fvmlib_command) +HANDLE_LOAD_COMMAND(LC_IDENT, 0x00000008u, ident_command) +HANDLE_LOAD_COMMAND(LC_FVMFILE, 0x00000009u, fvmfile_command) +HANDLE_LOAD_COMMAND(LC_PREPAGE, 0x0000000Au, load_command) +HANDLE_LOAD_COMMAND(LC_DYSYMTAB, 0x0000000Bu, dysymtab_command) +HANDLE_LOAD_COMMAND(LC_LOAD_DYLIB, 0x0000000Cu, dylib_command) +HANDLE_LOAD_COMMAND(LC_ID_DYLIB, 0x0000000Du, dylib_command) +HANDLE_LOAD_COMMAND(LC_LOAD_DYLINKER, 0x0000000Eu, dylinker_command) +HANDLE_LOAD_COMMAND(LC_ID_DYLINKER, 0x0000000Fu, dylinker_command) +HANDLE_LOAD_COMMAND(LC_PREBOUND_DYLIB, 0x00000010u, prebound_dylib_command) +HANDLE_LOAD_COMMAND(LC_ROUTINES, 0x00000011u, routines_command) +HANDLE_LOAD_COMMAND(LC_SUB_FRAMEWORK, 0x00000012u, sub_framework_command) +HANDLE_LOAD_COMMAND(LC_SUB_UMBRELLA, 0x00000013u, sub_umbrella_command) +HANDLE_LOAD_COMMAND(LC_SUB_CLIENT, 0x00000014u, sub_client_command) +HANDLE_LOAD_COMMAND(LC_SUB_LIBRARY, 0x00000015u, sub_library_command) +HANDLE_LOAD_COMMAND(LC_TWOLEVEL_HINTS, 0x00000016u, twolevel_hints_command) +HANDLE_LOAD_COMMAND(LC_PREBIND_CKSUM, 0x00000017u, prebind_cksum_command) +HANDLE_LOAD_COMMAND(LC_LOAD_WEAK_DYLIB, 0x80000018u, dylib_command) +HANDLE_LOAD_COMMAND(LC_SEGMENT_64, 0x00000019u, segment_command_64) +HANDLE_LOAD_COMMAND(LC_ROUTINES_64, 0x0000001Au, routines_command_64) +HANDLE_LOAD_COMMAND(LC_UUID, 0x0000001Bu, uuid_command) +HANDLE_LOAD_COMMAND(LC_RPATH, 0x8000001Cu, rpath_command) +HANDLE_LOAD_COMMAND(LC_CODE_SIGNATURE, 0x0000001Du, linkedit_data_command) +HANDLE_LOAD_COMMAND(LC_SEGMENT_SPLIT_INFO, 0x0000001Eu, linkedit_data_command) +HANDLE_LOAD_COMMAND(LC_REEXPORT_DYLIB, 0x8000001Fu, dylib_command) +HANDLE_LOAD_COMMAND(LC_LAZY_LOAD_DYLIB, 0x00000020u, dylib_command) +HANDLE_LOAD_COMMAND(LC_ENCRYPTION_INFO, 0x00000021u, encryption_info_command) +HANDLE_LOAD_COMMAND(LC_DYLD_INFO, 0x00000022u, dyld_info_command) +HANDLE_LOAD_COMMAND(LC_DYLD_INFO_ONLY, 0x80000022u, dyld_info_command) +HANDLE_LOAD_COMMAND(LC_LOAD_UPWARD_DYLIB, 0x80000023u, dylib_command) +HANDLE_LOAD_COMMAND(LC_VERSION_MIN_MACOSX, 0x00000024u, version_min_command) +HANDLE_LOAD_COMMAND(LC_VERSION_MIN_IPHONEOS, 0x00000025u, version_min_command) +HANDLE_LOAD_COMMAND(LC_FUNCTION_STARTS, 0x00000026u, linkedit_data_command) +HANDLE_LOAD_COMMAND(LC_DYLD_ENVIRONMENT, 0x00000027u, dylinker_command) +HANDLE_LOAD_COMMAND(LC_MAIN, 0x80000028u, entry_point_command) +HANDLE_LOAD_COMMAND(LC_DATA_IN_CODE, 0x00000029u, linkedit_data_command) +HANDLE_LOAD_COMMAND(LC_SOURCE_VERSION, 0x0000002Au, source_version_command) +HANDLE_LOAD_COMMAND(LC_DYLIB_CODE_SIGN_DRS, 0x0000002Bu, linkedit_data_command) +HANDLE_LOAD_COMMAND(LC_ENCRYPTION_INFO_64, 0x0000002Cu, + encryption_info_command_64) +HANDLE_LOAD_COMMAND(LC_LINKER_OPTION, 0x0000002Du, linker_option_command) +HANDLE_LOAD_COMMAND(LC_LINKER_OPTIMIZATION_HINT, 0x0000002Eu, linkedit_data_command) +HANDLE_LOAD_COMMAND(LC_VERSION_MIN_TVOS, 0x0000002Fu, version_min_command) +HANDLE_LOAD_COMMAND(LC_VERSION_MIN_WATCHOS, 0x00000030u, version_min_command) + +#endif + +#ifdef LOAD_COMMAND_STRUCT + +LOAD_COMMAND_STRUCT(dyld_info_command) +LOAD_COMMAND_STRUCT(dylib_command) +LOAD_COMMAND_STRUCT(dylinker_command) +LOAD_COMMAND_STRUCT(dysymtab_command) +LOAD_COMMAND_STRUCT(encryption_info_command) +LOAD_COMMAND_STRUCT(encryption_info_command_64) +LOAD_COMMAND_STRUCT(entry_point_command) +LOAD_COMMAND_STRUCT(fvmfile_command) +LOAD_COMMAND_STRUCT(fvmlib_command) +LOAD_COMMAND_STRUCT(ident_command) +LOAD_COMMAND_STRUCT(linkedit_data_command) +LOAD_COMMAND_STRUCT(linker_option_command) +LOAD_COMMAND_STRUCT(load_command) +LOAD_COMMAND_STRUCT(prebind_cksum_command) +LOAD_COMMAND_STRUCT(prebound_dylib_command) +LOAD_COMMAND_STRUCT(routines_command) +LOAD_COMMAND_STRUCT(routines_command_64) +LOAD_COMMAND_STRUCT(rpath_command) +LOAD_COMMAND_STRUCT(segment_command) +LOAD_COMMAND_STRUCT(segment_command_64) +LOAD_COMMAND_STRUCT(source_version_command) +LOAD_COMMAND_STRUCT(sub_client_command) +LOAD_COMMAND_STRUCT(sub_framework_command) +LOAD_COMMAND_STRUCT(sub_library_command) +LOAD_COMMAND_STRUCT(sub_umbrella_command) +LOAD_COMMAND_STRUCT(symseg_command) +LOAD_COMMAND_STRUCT(symtab_command) +LOAD_COMMAND_STRUCT(thread_command) +LOAD_COMMAND_STRUCT(twolevel_hints_command) +LOAD_COMMAND_STRUCT(uuid_command) +LOAD_COMMAND_STRUCT(version_min_command) + +#endif + +#undef HANDLE_LOAD_COMMAND +#undef LOAD_COMMAND_STRUCT
diff --git a/third_party/llvm-subzero/include/llvm/Support/MachO.h b/third_party/llvm-subzero/include/llvm/Support/MachO.h new file mode 100644 index 0000000..ebaaa7e --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/MachO.h
@@ -0,0 +1,1723 @@ +//===-- llvm/Support/MachO.h - The MachO file format ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines manifest constants for the MachO object file format. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MACHO_H +#define LLVM_SUPPORT_MACHO_H + +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Host.h" + +namespace llvm { + namespace MachO { + // Enums from <mach-o/loader.h> + enum : uint32_t { + // Constants for the "magic" field in llvm::MachO::mach_header and + // llvm::MachO::mach_header_64 + MH_MAGIC = 0xFEEDFACEu, + MH_CIGAM = 0xCEFAEDFEu, + MH_MAGIC_64 = 0xFEEDFACFu, + MH_CIGAM_64 = 0xCFFAEDFEu, + FAT_MAGIC = 0xCAFEBABEu, + FAT_CIGAM = 0xBEBAFECAu, + FAT_MAGIC_64 = 0xCAFEBABFu, + FAT_CIGAM_64 = 0xBFBAFECAu + }; + + enum HeaderFileType { + // Constants for the "filetype" field in llvm::MachO::mach_header and + // llvm::MachO::mach_header_64 + MH_OBJECT = 0x1u, + MH_EXECUTE = 0x2u, + MH_FVMLIB = 0x3u, + MH_CORE = 0x4u, + MH_PRELOAD = 0x5u, + MH_DYLIB = 0x6u, + MH_DYLINKER = 0x7u, + MH_BUNDLE = 0x8u, + MH_DYLIB_STUB = 0x9u, + MH_DSYM = 0xAu, + MH_KEXT_BUNDLE = 0xBu + }; + + enum { + // Constant bits for the "flags" field in llvm::MachO::mach_header and + // llvm::MachO::mach_header_64 + MH_NOUNDEFS = 0x00000001u, + MH_INCRLINK = 0x00000002u, + MH_DYLDLINK = 0x00000004u, + MH_BINDATLOAD = 0x00000008u, + MH_PREBOUND = 0x00000010u, + MH_SPLIT_SEGS = 0x00000020u, + MH_LAZY_INIT = 0x00000040u, + MH_TWOLEVEL = 0x00000080u, + MH_FORCE_FLAT = 0x00000100u, + MH_NOMULTIDEFS = 0x00000200u, + MH_NOFIXPREBINDING = 0x00000400u, + MH_PREBINDABLE = 0x00000800u, + MH_ALLMODSBOUND = 0x00001000u, + MH_SUBSECTIONS_VIA_SYMBOLS = 0x00002000u, + MH_CANONICAL = 0x00004000u, + MH_WEAK_DEFINES = 0x00008000u, + MH_BINDS_TO_WEAK = 0x00010000u, + MH_ALLOW_STACK_EXECUTION = 0x00020000u, + MH_ROOT_SAFE = 0x00040000u, + MH_SETUID_SAFE = 0x00080000u, + MH_NO_REEXPORTED_DYLIBS = 0x00100000u, + MH_PIE = 0x00200000u, + MH_DEAD_STRIPPABLE_DYLIB = 0x00400000u, + MH_HAS_TLV_DESCRIPTORS = 0x00800000u, + MH_NO_HEAP_EXECUTION = 0x01000000u, + MH_APP_EXTENSION_SAFE = 0x02000000u + }; + + enum : uint32_t { + // Flags for the "cmd" field in llvm::MachO::load_command + LC_REQ_DYLD = 0x80000000u + }; + +#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \ + LCName = LCValue, + + enum LoadCommandType : uint32_t { + #include "llvm/Support/MachO.def" + }; + +#undef HANDLE_LOAD_COMMAND + + enum : uint32_t { + // Constant bits for the "flags" field in llvm::MachO::segment_command + SG_HIGHVM = 0x1u, + SG_FVMLIB = 0x2u, + SG_NORELOC = 0x4u, + SG_PROTECTED_VERSION_1 = 0x8u, + + // Constant masks for the "flags" field in llvm::MachO::section and + // llvm::MachO::section_64 + SECTION_TYPE = 0x000000ffu, // SECTION_TYPE + SECTION_ATTRIBUTES = 0xffffff00u, // SECTION_ATTRIBUTES + SECTION_ATTRIBUTES_USR = 0xff000000u, // SECTION_ATTRIBUTES_USR + SECTION_ATTRIBUTES_SYS = 0x00ffff00u // SECTION_ATTRIBUTES_SYS + }; + + /// These are the section type and attributes fields. A MachO section can + /// have only one Type, but can have any of the attributes specified. + enum SectionType : uint32_t { + // Constant masks for the "flags[7:0]" field in llvm::MachO::section and + // llvm::MachO::section_64 (mask "flags" with SECTION_TYPE) + + /// S_REGULAR - Regular section. + S_REGULAR = 0x00u, + /// S_ZEROFILL - Zero fill on demand section. + S_ZEROFILL = 0x01u, + /// S_CSTRING_LITERALS - Section with literal C strings. + S_CSTRING_LITERALS = 0x02u, + /// S_4BYTE_LITERALS - Section with 4 byte literals. + S_4BYTE_LITERALS = 0x03u, + /// S_8BYTE_LITERALS - Section with 8 byte literals. + S_8BYTE_LITERALS = 0x04u, + /// S_LITERAL_POINTERS - Section with pointers to literals. + S_LITERAL_POINTERS = 0x05u, + /// S_NON_LAZY_SYMBOL_POINTERS - Section with non-lazy symbol pointers. + S_NON_LAZY_SYMBOL_POINTERS = 0x06u, + /// S_LAZY_SYMBOL_POINTERS - Section with lazy symbol pointers. + S_LAZY_SYMBOL_POINTERS = 0x07u, + /// S_SYMBOL_STUBS - Section with symbol stubs, byte size of stub in + /// the Reserved2 field. + S_SYMBOL_STUBS = 0x08u, + /// S_MOD_INIT_FUNC_POINTERS - Section with only function pointers for + /// initialization. + S_MOD_INIT_FUNC_POINTERS = 0x09u, + /// S_MOD_TERM_FUNC_POINTERS - Section with only function pointers for + /// termination. + S_MOD_TERM_FUNC_POINTERS = 0x0au, + /// S_COALESCED - Section contains symbols that are to be coalesced. + S_COALESCED = 0x0bu, + /// S_GB_ZEROFILL - Zero fill on demand section (that can be larger than 4 + /// gigabytes). + S_GB_ZEROFILL = 0x0cu, + /// S_INTERPOSING - Section with only pairs of function pointers for + /// interposing. + S_INTERPOSING = 0x0du, + /// S_16BYTE_LITERALS - Section with only 16 byte literals. + S_16BYTE_LITERALS = 0x0eu, + /// S_DTRACE_DOF - Section contains DTrace Object Format. + S_DTRACE_DOF = 0x0fu, + /// S_LAZY_DYLIB_SYMBOL_POINTERS - Section with lazy symbol pointers to + /// lazy loaded dylibs. + S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10u, + /// S_THREAD_LOCAL_REGULAR - Thread local data section. + S_THREAD_LOCAL_REGULAR = 0x11u, + /// S_THREAD_LOCAL_ZEROFILL - Thread local zerofill section. + S_THREAD_LOCAL_ZEROFILL = 0x12u, + /// S_THREAD_LOCAL_VARIABLES - Section with thread local variable + /// structure data. + S_THREAD_LOCAL_VARIABLES = 0x13u, + /// S_THREAD_LOCAL_VARIABLE_POINTERS - Section with pointers to thread + /// local structures. + S_THREAD_LOCAL_VARIABLE_POINTERS = 0x14u, + /// S_THREAD_LOCAL_INIT_FUNCTION_POINTERS - Section with thread local + /// variable initialization pointers to functions. + S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15u, + + LAST_KNOWN_SECTION_TYPE = S_THREAD_LOCAL_INIT_FUNCTION_POINTERS + }; + + enum : uint32_t { + // Constant masks for the "flags[31:24]" field in llvm::MachO::section and + // llvm::MachO::section_64 (mask "flags" with SECTION_ATTRIBUTES_USR) + + /// S_ATTR_PURE_INSTRUCTIONS - Section contains only true machine + /// instructions. + S_ATTR_PURE_INSTRUCTIONS = 0x80000000u, + /// S_ATTR_NO_TOC - Section contains coalesced symbols that are not to be + /// in a ranlib table of contents. + S_ATTR_NO_TOC = 0x40000000u, + /// S_ATTR_STRIP_STATIC_SYMS - Ok to strip static symbols in this section + /// in files with the MY_DYLDLINK flag. + S_ATTR_STRIP_STATIC_SYMS = 0x20000000u, + /// S_ATTR_NO_DEAD_STRIP - No dead stripping. + S_ATTR_NO_DEAD_STRIP = 0x10000000u, + /// S_ATTR_LIVE_SUPPORT - Blocks are live if they reference live blocks. + S_ATTR_LIVE_SUPPORT = 0x08000000u, + /// S_ATTR_SELF_MODIFYING_CODE - Used with i386 code stubs written on by + /// dyld. + S_ATTR_SELF_MODIFYING_CODE = 0x04000000u, + /// S_ATTR_DEBUG - A debug section. + S_ATTR_DEBUG = 0x02000000u, + + // Constant masks for the "flags[23:8]" field in llvm::MachO::section and + // llvm::MachO::section_64 (mask "flags" with SECTION_ATTRIBUTES_SYS) + + /// S_ATTR_SOME_INSTRUCTIONS - Section contains some machine instructions. + S_ATTR_SOME_INSTRUCTIONS = 0x00000400u, + /// S_ATTR_EXT_RELOC - Section has external relocation entries. + S_ATTR_EXT_RELOC = 0x00000200u, + /// S_ATTR_LOC_RELOC - Section has local relocation entries. + S_ATTR_LOC_RELOC = 0x00000100u, + + // Constant masks for the value of an indirect symbol in an indirect + // symbol table + INDIRECT_SYMBOL_LOCAL = 0x80000000u, + INDIRECT_SYMBOL_ABS = 0x40000000u + }; + + enum DataRegionType { + // Constants for the "kind" field in a data_in_code_entry structure + DICE_KIND_DATA = 1u, + DICE_KIND_JUMP_TABLE8 = 2u, + DICE_KIND_JUMP_TABLE16 = 3u, + DICE_KIND_JUMP_TABLE32 = 4u, + DICE_KIND_ABS_JUMP_TABLE32 = 5u + }; + + enum RebaseType { + REBASE_TYPE_POINTER = 1u, + REBASE_TYPE_TEXT_ABSOLUTE32 = 2u, + REBASE_TYPE_TEXT_PCREL32 = 3u + }; + + enum { + REBASE_OPCODE_MASK = 0xF0u, + REBASE_IMMEDIATE_MASK = 0x0Fu + }; + + enum RebaseOpcode { + REBASE_OPCODE_DONE = 0x00u, + REBASE_OPCODE_SET_TYPE_IMM = 0x10u, + REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x20u, + REBASE_OPCODE_ADD_ADDR_ULEB = 0x30u, + REBASE_OPCODE_ADD_ADDR_IMM_SCALED = 0x40u, + REBASE_OPCODE_DO_REBASE_IMM_TIMES = 0x50u, + REBASE_OPCODE_DO_REBASE_ULEB_TIMES = 0x60u, + REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB = 0x70u, + REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB = 0x80u + }; + + enum BindType { + BIND_TYPE_POINTER = 1u, + BIND_TYPE_TEXT_ABSOLUTE32 = 2u, + BIND_TYPE_TEXT_PCREL32 = 3u + }; + + enum BindSpecialDylib { + BIND_SPECIAL_DYLIB_SELF = 0, + BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE = -1, + BIND_SPECIAL_DYLIB_FLAT_LOOKUP = -2 + }; + + enum { + BIND_SYMBOL_FLAGS_WEAK_IMPORT = 0x1u, + BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION = 0x8u, + + BIND_OPCODE_MASK = 0xF0u, + BIND_IMMEDIATE_MASK = 0x0Fu + }; + + enum BindOpcode { + BIND_OPCODE_DONE = 0x00u, + BIND_OPCODE_SET_DYLIB_ORDINAL_IMM = 0x10u, + BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB = 0x20u, + BIND_OPCODE_SET_DYLIB_SPECIAL_IMM = 0x30u, + BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM = 0x40u, + BIND_OPCODE_SET_TYPE_IMM = 0x50u, + BIND_OPCODE_SET_ADDEND_SLEB = 0x60u, + BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x70u, + BIND_OPCODE_ADD_ADDR_ULEB = 0x80u, + BIND_OPCODE_DO_BIND = 0x90u, + BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB = 0xA0u, + BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED = 0xB0u, + BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB = 0xC0u + }; + + enum { + EXPORT_SYMBOL_FLAGS_KIND_MASK = 0x03u, + EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION = 0x04u, + EXPORT_SYMBOL_FLAGS_REEXPORT = 0x08u, + EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER = 0x10u + }; + + enum ExportSymbolKind { + EXPORT_SYMBOL_FLAGS_KIND_REGULAR = 0x00u, + EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL = 0x01u, + EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE = 0x02u + }; + + enum { + // Constant masks for the "n_type" field in llvm::MachO::nlist and + // llvm::MachO::nlist_64 + N_STAB = 0xe0, + N_PEXT = 0x10, + N_TYPE = 0x0e, + N_EXT = 0x01 + }; + + enum NListType : uint8_t { + // Constants for the "n_type & N_TYPE" llvm::MachO::nlist and + // llvm::MachO::nlist_64 + N_UNDF = 0x0u, + N_ABS = 0x2u, + N_SECT = 0xeu, + N_PBUD = 0xcu, + N_INDR = 0xau + }; + + enum SectionOrdinal { + // Constants for the "n_sect" field in llvm::MachO::nlist and + // llvm::MachO::nlist_64 + NO_SECT = 0u, + MAX_SECT = 0xffu + }; + + enum { + // Constant masks for the "n_desc" field in llvm::MachO::nlist and + // llvm::MachO::nlist_64 + // The low 3 bits are the for the REFERENCE_TYPE. + REFERENCE_TYPE = 0x7, + REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0, + REFERENCE_FLAG_UNDEFINED_LAZY = 1, + REFERENCE_FLAG_DEFINED = 2, + REFERENCE_FLAG_PRIVATE_DEFINED = 3, + REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4, + REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5, + // Flag bits (some overlap with the library ordinal bits). + N_ARM_THUMB_DEF = 0x0008u, + REFERENCED_DYNAMICALLY = 0x0010u, + N_NO_DEAD_STRIP = 0x0020u, + N_WEAK_REF = 0x0040u, + N_WEAK_DEF = 0x0080u, + N_SYMBOL_RESOLVER = 0x0100u, + N_ALT_ENTRY = 0x0200u, + // For undefined symbols coming from libraries, see GET_LIBRARY_ORDINAL() + // as these are in the top 8 bits. + SELF_LIBRARY_ORDINAL = 0x0, + MAX_LIBRARY_ORDINAL = 0xfd, + DYNAMIC_LOOKUP_ORDINAL = 0xfe, + EXECUTABLE_ORDINAL = 0xff + }; + + enum StabType { + // Constant values for the "n_type" field in llvm::MachO::nlist and + // llvm::MachO::nlist_64 when "(n_type & N_STAB) != 0" + N_GSYM = 0x20u, + N_FNAME = 0x22u, + N_FUN = 0x24u, + N_STSYM = 0x26u, + N_LCSYM = 0x28u, + N_BNSYM = 0x2Eu, + N_PC = 0x30u, + N_AST = 0x32u, + N_OPT = 0x3Cu, + N_RSYM = 0x40u, + N_SLINE = 0x44u, + N_ENSYM = 0x4Eu, + N_SSYM = 0x60u, + N_SO = 0x64u, + N_OSO = 0x66u, + N_LSYM = 0x80u, + N_BINCL = 0x82u, + N_SOL = 0x84u, + N_PARAMS = 0x86u, + N_VERSION = 0x88u, + N_OLEVEL = 0x8Au, + N_PSYM = 0xA0u, + N_EINCL = 0xA2u, + N_ENTRY = 0xA4u, + N_LBRAC = 0xC0u, + N_EXCL = 0xC2u, + N_RBRAC = 0xE0u, + N_BCOMM = 0xE2u, + N_ECOMM = 0xE4u, + N_ECOML = 0xE8u, + N_LENG = 0xFEu + }; + + enum : uint32_t { + // Constant values for the r_symbolnum field in an + // llvm::MachO::relocation_info structure when r_extern is 0. + R_ABS = 0, + + // Constant bits for the r_address field in an + // llvm::MachO::relocation_info structure. + R_SCATTERED = 0x80000000 + }; + + enum RelocationInfoType { + // Constant values for the r_type field in an + // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info + // structure. + GENERIC_RELOC_VANILLA = 0, + GENERIC_RELOC_PAIR = 1, + GENERIC_RELOC_SECTDIFF = 2, + GENERIC_RELOC_PB_LA_PTR = 3, + GENERIC_RELOC_LOCAL_SECTDIFF = 4, + GENERIC_RELOC_TLV = 5, + + // Constant values for the r_type field in a PowerPC architecture + // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info + // structure. + PPC_RELOC_VANILLA = GENERIC_RELOC_VANILLA, + PPC_RELOC_PAIR = GENERIC_RELOC_PAIR, + PPC_RELOC_BR14 = 2, + PPC_RELOC_BR24 = 3, + PPC_RELOC_HI16 = 4, + PPC_RELOC_LO16 = 5, + PPC_RELOC_HA16 = 6, + PPC_RELOC_LO14 = 7, + PPC_RELOC_SECTDIFF = 8, + PPC_RELOC_PB_LA_PTR = 9, + PPC_RELOC_HI16_SECTDIFF = 10, + PPC_RELOC_LO16_SECTDIFF = 11, + PPC_RELOC_HA16_SECTDIFF = 12, + PPC_RELOC_JBSR = 13, + PPC_RELOC_LO14_SECTDIFF = 14, + PPC_RELOC_LOCAL_SECTDIFF = 15, + + // Constant values for the r_type field in an ARM architecture + // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info + // structure. + ARM_RELOC_VANILLA = GENERIC_RELOC_VANILLA, + ARM_RELOC_PAIR = GENERIC_RELOC_PAIR, + ARM_RELOC_SECTDIFF = GENERIC_RELOC_SECTDIFF, + ARM_RELOC_LOCAL_SECTDIFF = 3, + ARM_RELOC_PB_LA_PTR = 4, + ARM_RELOC_BR24 = 5, + ARM_THUMB_RELOC_BR22 = 6, + ARM_THUMB_32BIT_BRANCH = 7, // obsolete + ARM_RELOC_HALF = 8, + ARM_RELOC_HALF_SECTDIFF = 9, + + // Constant values for the r_type field in an ARM64 architecture + // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info + // structure. + + // For pointers. + ARM64_RELOC_UNSIGNED = 0, + // Must be followed by an ARM64_RELOC_UNSIGNED + ARM64_RELOC_SUBTRACTOR = 1, + // A B/BL instruction with 26-bit displacement. + ARM64_RELOC_BRANCH26 = 2, + // PC-rel distance to page of target. + ARM64_RELOC_PAGE21 = 3, + // Offset within page, scaled by r_length. + ARM64_RELOC_PAGEOFF12 = 4, + // PC-rel distance to page of GOT slot. + ARM64_RELOC_GOT_LOAD_PAGE21 = 5, + // Offset within page of GOT slot, scaled by r_length. + ARM64_RELOC_GOT_LOAD_PAGEOFF12 = 6, + // For pointers to GOT slots. + ARM64_RELOC_POINTER_TO_GOT = 7, + // PC-rel distance to page of TLVP slot. + ARM64_RELOC_TLVP_LOAD_PAGE21 = 8, + // Offset within page of TLVP slot, scaled by r_length. + ARM64_RELOC_TLVP_LOAD_PAGEOFF12 = 9, + // Must be followed by ARM64_RELOC_PAGE21 or ARM64_RELOC_PAGEOFF12. + ARM64_RELOC_ADDEND = 10, + + // Constant values for the r_type field in an x86_64 architecture + // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info + // structure + X86_64_RELOC_UNSIGNED = 0, + X86_64_RELOC_SIGNED = 1, + X86_64_RELOC_BRANCH = 2, + X86_64_RELOC_GOT_LOAD = 3, + X86_64_RELOC_GOT = 4, + X86_64_RELOC_SUBTRACTOR = 5, + X86_64_RELOC_SIGNED_1 = 6, + X86_64_RELOC_SIGNED_2 = 7, + X86_64_RELOC_SIGNED_4 = 8, + X86_64_RELOC_TLV = 9 + }; + + // Values for segment_command.initprot. + // From <mach/vm_prot.h> + enum { + VM_PROT_READ = 0x1, + VM_PROT_WRITE = 0x2, + VM_PROT_EXECUTE = 0x4 + }; + + // Structs from <mach-o/loader.h> + + struct mach_header { + uint32_t magic; + uint32_t cputype; + uint32_t cpusubtype; + uint32_t filetype; + uint32_t ncmds; + uint32_t sizeofcmds; + uint32_t flags; + }; + + struct mach_header_64 { + uint32_t magic; + uint32_t cputype; + uint32_t cpusubtype; + uint32_t filetype; + uint32_t ncmds; + uint32_t sizeofcmds; + uint32_t flags; + uint32_t reserved; + }; + + struct load_command { + uint32_t cmd; + uint32_t cmdsize; + }; + + struct segment_command { + uint32_t cmd; + uint32_t cmdsize; + char segname[16]; + uint32_t vmaddr; + uint32_t vmsize; + uint32_t fileoff; + uint32_t filesize; + uint32_t maxprot; + uint32_t initprot; + uint32_t nsects; + uint32_t flags; + }; + + struct segment_command_64 { + uint32_t cmd; + uint32_t cmdsize; + char segname[16]; + uint64_t vmaddr; + uint64_t vmsize; + uint64_t fileoff; + uint64_t filesize; + uint32_t maxprot; + uint32_t initprot; + uint32_t nsects; + uint32_t flags; + }; + + struct section { + char sectname[16]; + char segname[16]; + uint32_t addr; + uint32_t size; + uint32_t offset; + uint32_t align; + uint32_t reloff; + uint32_t nreloc; + uint32_t flags; + uint32_t reserved1; + uint32_t reserved2; + }; + + struct section_64 { + char sectname[16]; + char segname[16]; + uint64_t addr; + uint64_t size; + uint32_t offset; + uint32_t align; + uint32_t reloff; + uint32_t nreloc; + uint32_t flags; + uint32_t reserved1; + uint32_t reserved2; + uint32_t reserved3; + }; + + struct fvmlib { + uint32_t name; + uint32_t minor_version; + uint32_t header_addr; + }; + + struct fvmlib_command { + uint32_t cmd; + uint32_t cmdsize; + struct fvmlib fvmlib; + }; + + struct dylib { + uint32_t name; + uint32_t timestamp; + uint32_t current_version; + uint32_t compatibility_version; + }; + + struct dylib_command { + uint32_t cmd; + uint32_t cmdsize; + struct dylib dylib; + }; + + struct sub_framework_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t umbrella; + }; + + struct sub_client_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t client; + }; + + struct sub_umbrella_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t sub_umbrella; + }; + + struct sub_library_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t sub_library; + }; + + struct prebound_dylib_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t name; + uint32_t nmodules; + uint32_t linked_modules; + }; + + struct dylinker_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t name; + }; + + struct thread_command { + uint32_t cmd; + uint32_t cmdsize; + }; + + struct routines_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t init_address; + uint32_t init_module; + uint32_t reserved1; + uint32_t reserved2; + uint32_t reserved3; + uint32_t reserved4; + uint32_t reserved5; + uint32_t reserved6; + }; + + struct routines_command_64 { + uint32_t cmd; + uint32_t cmdsize; + uint64_t init_address; + uint64_t init_module; + uint64_t reserved1; + uint64_t reserved2; + uint64_t reserved3; + uint64_t reserved4; + uint64_t reserved5; + uint64_t reserved6; + }; + + struct symtab_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t symoff; + uint32_t nsyms; + uint32_t stroff; + uint32_t strsize; + }; + + struct dysymtab_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t ilocalsym; + uint32_t nlocalsym; + uint32_t iextdefsym; + uint32_t nextdefsym; + uint32_t iundefsym; + uint32_t nundefsym; + uint32_t tocoff; + uint32_t ntoc; + uint32_t modtaboff; + uint32_t nmodtab; + uint32_t extrefsymoff; + uint32_t nextrefsyms; + uint32_t indirectsymoff; + uint32_t nindirectsyms; + uint32_t extreloff; + uint32_t nextrel; + uint32_t locreloff; + uint32_t nlocrel; + }; + + struct dylib_table_of_contents { + uint32_t symbol_index; + uint32_t module_index; + }; + + struct dylib_module { + uint32_t module_name; + uint32_t iextdefsym; + uint32_t nextdefsym; + uint32_t irefsym; + uint32_t nrefsym; + uint32_t ilocalsym; + uint32_t nlocalsym; + uint32_t iextrel; + uint32_t nextrel; + uint32_t iinit_iterm; + uint32_t ninit_nterm; + uint32_t objc_module_info_addr; + uint32_t objc_module_info_size; + }; + + struct dylib_module_64 { + uint32_t module_name; + uint32_t iextdefsym; + uint32_t nextdefsym; + uint32_t irefsym; + uint32_t nrefsym; + uint32_t ilocalsym; + uint32_t nlocalsym; + uint32_t iextrel; + uint32_t nextrel; + uint32_t iinit_iterm; + uint32_t ninit_nterm; + uint32_t objc_module_info_size; + uint64_t objc_module_info_addr; + }; + + struct dylib_reference { + uint32_t isym:24, + flags:8; + }; + + struct twolevel_hints_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t offset; + uint32_t nhints; + }; + + struct twolevel_hint { + uint32_t isub_image:8, + itoc:24; + }; + + struct prebind_cksum_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t cksum; + }; + + struct uuid_command { + uint32_t cmd; + uint32_t cmdsize; + uint8_t uuid[16]; + }; + + struct rpath_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t path; + }; + + struct linkedit_data_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t dataoff; + uint32_t datasize; + }; + + struct data_in_code_entry { + uint32_t offset; + uint16_t length; + uint16_t kind; + }; + + struct source_version_command { + uint32_t cmd; + uint32_t cmdsize; + uint64_t version; + }; + + struct encryption_info_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t cryptoff; + uint32_t cryptsize; + uint32_t cryptid; + }; + + struct encryption_info_command_64 { + uint32_t cmd; + uint32_t cmdsize; + uint32_t cryptoff; + uint32_t cryptsize; + uint32_t cryptid; + uint32_t pad; + }; + + struct version_min_command { + uint32_t cmd; // LC_VERSION_MIN_MACOSX or + // LC_VERSION_MIN_IPHONEOS + uint32_t cmdsize; // sizeof(struct version_min_command) + uint32_t version; // X.Y.Z is encoded in nibbles xxxx.yy.zz + uint32_t sdk; // X.Y.Z is encoded in nibbles xxxx.yy.zz + }; + + struct dyld_info_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t rebase_off; + uint32_t rebase_size; + uint32_t bind_off; + uint32_t bind_size; + uint32_t weak_bind_off; + uint32_t weak_bind_size; + uint32_t lazy_bind_off; + uint32_t lazy_bind_size; + uint32_t export_off; + uint32_t export_size; + }; + + struct linker_option_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t count; + }; + + struct symseg_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t offset; + uint32_t size; + }; + + struct ident_command { + uint32_t cmd; + uint32_t cmdsize; + }; + + struct fvmfile_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t name; + uint32_t header_addr; + }; + + struct tlv_descriptor_32 { + uint32_t thunk; + uint32_t key; + uint32_t offset; + }; + + struct tlv_descriptor_64 { + uint64_t thunk; + uint64_t key; + uint64_t offset; + }; + + struct tlv_descriptor { + uintptr_t thunk; + uintptr_t key; + uintptr_t offset; + }; + + struct entry_point_command { + uint32_t cmd; + uint32_t cmdsize; + uint64_t entryoff; + uint64_t stacksize; + }; + + // Structs from <mach-o/fat.h> + struct fat_header { + uint32_t magic; + uint32_t nfat_arch; + }; + + struct fat_arch { + uint32_t cputype; + uint32_t cpusubtype; + uint32_t offset; + uint32_t size; + uint32_t align; + }; + + struct fat_arch_64 { + uint32_t cputype; + uint32_t cpusubtype; + uint64_t offset; + uint64_t size; + uint32_t align; + uint32_t reserved; + }; + + // Structs from <mach-o/reloc.h> + struct relocation_info { + int32_t r_address; + uint32_t r_symbolnum:24, + r_pcrel:1, + r_length:2, + r_extern:1, + r_type:4; + }; + + struct scattered_relocation_info { +#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && (BYTE_ORDER == BIG_ENDIAN) + uint32_t r_scattered:1, + r_pcrel:1, + r_length:2, + r_type:4, + r_address:24; +#else + uint32_t r_address:24, + r_type:4, + r_length:2, + r_pcrel:1, + r_scattered:1; +#endif + int32_t r_value; + }; + + // Structs NOT from <mach-o/reloc.h>, but that make LLVM's life easier + struct any_relocation_info { + uint32_t r_word0, r_word1; + }; + + // Structs from <mach-o/nlist.h> + struct nlist_base { + uint32_t n_strx; + uint8_t n_type; + uint8_t n_sect; + uint16_t n_desc; + }; + + struct nlist { + uint32_t n_strx; + uint8_t n_type; + uint8_t n_sect; + int16_t n_desc; + uint32_t n_value; + }; + + struct nlist_64 { + uint32_t n_strx; + uint8_t n_type; + uint8_t n_sect; + uint16_t n_desc; + uint64_t n_value; + }; + + // Byte order swapping functions for MachO structs + + inline void swapStruct(fat_header &mh) { + sys::swapByteOrder(mh.magic); + sys::swapByteOrder(mh.nfat_arch); + } + + inline void swapStruct(fat_arch &mh) { + sys::swapByteOrder(mh.cputype); + sys::swapByteOrder(mh.cpusubtype); + sys::swapByteOrder(mh.offset); + sys::swapByteOrder(mh.size); + sys::swapByteOrder(mh.align); + } + + inline void swapStruct(fat_arch_64 &mh) { + sys::swapByteOrder(mh.cputype); + sys::swapByteOrder(mh.cpusubtype); + sys::swapByteOrder(mh.offset); + sys::swapByteOrder(mh.size); + sys::swapByteOrder(mh.align); + sys::swapByteOrder(mh.reserved); + } + + inline void swapStruct(mach_header &mh) { + sys::swapByteOrder(mh.magic); + sys::swapByteOrder(mh.cputype); + sys::swapByteOrder(mh.cpusubtype); + sys::swapByteOrder(mh.filetype); + sys::swapByteOrder(mh.ncmds); + sys::swapByteOrder(mh.sizeofcmds); + sys::swapByteOrder(mh.flags); + } + + inline void swapStruct(mach_header_64 &H) { + sys::swapByteOrder(H.magic); + sys::swapByteOrder(H.cputype); + sys::swapByteOrder(H.cpusubtype); + sys::swapByteOrder(H.filetype); + sys::swapByteOrder(H.ncmds); + sys::swapByteOrder(H.sizeofcmds); + sys::swapByteOrder(H.flags); + sys::swapByteOrder(H.reserved); + } + + inline void swapStruct(load_command &lc) { + sys::swapByteOrder(lc.cmd); + sys::swapByteOrder(lc.cmdsize); + } + + inline void swapStruct(symtab_command &lc) { + sys::swapByteOrder(lc.cmd); + sys::swapByteOrder(lc.cmdsize); + sys::swapByteOrder(lc.symoff); + sys::swapByteOrder(lc.nsyms); + sys::swapByteOrder(lc.stroff); + sys::swapByteOrder(lc.strsize); + } + + inline void swapStruct(segment_command_64 &seg) { + sys::swapByteOrder(seg.cmd); + sys::swapByteOrder(seg.cmdsize); + sys::swapByteOrder(seg.vmaddr); + sys::swapByteOrder(seg.vmsize); + sys::swapByteOrder(seg.fileoff); + sys::swapByteOrder(seg.filesize); + sys::swapByteOrder(seg.maxprot); + sys::swapByteOrder(seg.initprot); + sys::swapByteOrder(seg.nsects); + sys::swapByteOrder(seg.flags); + } + + inline void swapStruct(segment_command &seg) { + sys::swapByteOrder(seg.cmd); + sys::swapByteOrder(seg.cmdsize); + sys::swapByteOrder(seg.vmaddr); + sys::swapByteOrder(seg.vmsize); + sys::swapByteOrder(seg.fileoff); + sys::swapByteOrder(seg.filesize); + sys::swapByteOrder(seg.maxprot); + sys::swapByteOrder(seg.initprot); + sys::swapByteOrder(seg.nsects); + sys::swapByteOrder(seg.flags); + } + + inline void swapStruct(section_64 §) { + sys::swapByteOrder(sect.addr); + sys::swapByteOrder(sect.size); + sys::swapByteOrder(sect.offset); + sys::swapByteOrder(sect.align); + sys::swapByteOrder(sect.reloff); + sys::swapByteOrder(sect.nreloc); + sys::swapByteOrder(sect.flags); + sys::swapByteOrder(sect.reserved1); + sys::swapByteOrder(sect.reserved2); + } + + inline void swapStruct(section §) { + sys::swapByteOrder(sect.addr); + sys::swapByteOrder(sect.size); + sys::swapByteOrder(sect.offset); + sys::swapByteOrder(sect.align); + sys::swapByteOrder(sect.reloff); + sys::swapByteOrder(sect.nreloc); + sys::swapByteOrder(sect.flags); + sys::swapByteOrder(sect.reserved1); + sys::swapByteOrder(sect.reserved2); + } + + inline void swapStruct(dyld_info_command &info) { + sys::swapByteOrder(info.cmd); + sys::swapByteOrder(info.cmdsize); + sys::swapByteOrder(info.rebase_off); + sys::swapByteOrder(info.rebase_size); + sys::swapByteOrder(info.bind_off); + sys::swapByteOrder(info.bind_size); + sys::swapByteOrder(info.weak_bind_off); + sys::swapByteOrder(info.weak_bind_size); + sys::swapByteOrder(info.lazy_bind_off); + sys::swapByteOrder(info.lazy_bind_size); + sys::swapByteOrder(info.export_off); + sys::swapByteOrder(info.export_size); + } + + inline void swapStruct(dylib_command &d) { + sys::swapByteOrder(d.cmd); + sys::swapByteOrder(d.cmdsize); + sys::swapByteOrder(d.dylib.name); + sys::swapByteOrder(d.dylib.timestamp); + sys::swapByteOrder(d.dylib.current_version); + sys::swapByteOrder(d.dylib.compatibility_version); + } + + inline void swapStruct(sub_framework_command &s) { + sys::swapByteOrder(s.cmd); + sys::swapByteOrder(s.cmdsize); + sys::swapByteOrder(s.umbrella); + } + + inline void swapStruct(sub_umbrella_command &s) { + sys::swapByteOrder(s.cmd); + sys::swapByteOrder(s.cmdsize); + sys::swapByteOrder(s.sub_umbrella); + } + + inline void swapStruct(sub_library_command &s) { + sys::swapByteOrder(s.cmd); + sys::swapByteOrder(s.cmdsize); + sys::swapByteOrder(s.sub_library); + } + + inline void swapStruct(sub_client_command &s) { + sys::swapByteOrder(s.cmd); + sys::swapByteOrder(s.cmdsize); + sys::swapByteOrder(s.client); + } + + inline void swapStruct(routines_command &r) { + sys::swapByteOrder(r.cmd); + sys::swapByteOrder(r.cmdsize); + sys::swapByteOrder(r.init_address); + sys::swapByteOrder(r.init_module); + sys::swapByteOrder(r.reserved1); + sys::swapByteOrder(r.reserved2); + sys::swapByteOrder(r.reserved3); + sys::swapByteOrder(r.reserved4); + sys::swapByteOrder(r.reserved5); + sys::swapByteOrder(r.reserved6); + } + + inline void swapStruct(routines_command_64 &r) { + sys::swapByteOrder(r.cmd); + sys::swapByteOrder(r.cmdsize); + sys::swapByteOrder(r.init_address); + sys::swapByteOrder(r.init_module); + sys::swapByteOrder(r.reserved1); + sys::swapByteOrder(r.reserved2); + sys::swapByteOrder(r.reserved3); + sys::swapByteOrder(r.reserved4); + sys::swapByteOrder(r.reserved5); + sys::swapByteOrder(r.reserved6); + } + + inline void swapStruct(thread_command &t) { + sys::swapByteOrder(t.cmd); + sys::swapByteOrder(t.cmdsize); + } + + inline void swapStruct(dylinker_command &d) { + sys::swapByteOrder(d.cmd); + sys::swapByteOrder(d.cmdsize); + sys::swapByteOrder(d.name); + } + + inline void swapStruct(uuid_command &u) { + sys::swapByteOrder(u.cmd); + sys::swapByteOrder(u.cmdsize); + } + + inline void swapStruct(rpath_command &r) { + sys::swapByteOrder(r.cmd); + sys::swapByteOrder(r.cmdsize); + sys::swapByteOrder(r.path); + } + + inline void swapStruct(source_version_command &s) { + sys::swapByteOrder(s.cmd); + sys::swapByteOrder(s.cmdsize); + sys::swapByteOrder(s.version); + } + + inline void swapStruct(entry_point_command &e) { + sys::swapByteOrder(e.cmd); + sys::swapByteOrder(e.cmdsize); + sys::swapByteOrder(e.entryoff); + sys::swapByteOrder(e.stacksize); + } + + inline void swapStruct(encryption_info_command &e) { + sys::swapByteOrder(e.cmd); + sys::swapByteOrder(e.cmdsize); + sys::swapByteOrder(e.cryptoff); + sys::swapByteOrder(e.cryptsize); + sys::swapByteOrder(e.cryptid); + } + + inline void swapStruct(encryption_info_command_64 &e) { + sys::swapByteOrder(e.cmd); + sys::swapByteOrder(e.cmdsize); + sys::swapByteOrder(e.cryptoff); + sys::swapByteOrder(e.cryptsize); + sys::swapByteOrder(e.cryptid); + sys::swapByteOrder(e.pad); + } + + inline void swapStruct(dysymtab_command &dst) { + sys::swapByteOrder(dst.cmd); + sys::swapByteOrder(dst.cmdsize); + sys::swapByteOrder(dst.ilocalsym); + sys::swapByteOrder(dst.nlocalsym); + sys::swapByteOrder(dst.iextdefsym); + sys::swapByteOrder(dst.nextdefsym); + sys::swapByteOrder(dst.iundefsym); + sys::swapByteOrder(dst.nundefsym); + sys::swapByteOrder(dst.tocoff); + sys::swapByteOrder(dst.ntoc); + sys::swapByteOrder(dst.modtaboff); + sys::swapByteOrder(dst.nmodtab); + sys::swapByteOrder(dst.extrefsymoff); + sys::swapByteOrder(dst.nextrefsyms); + sys::swapByteOrder(dst.indirectsymoff); + sys::swapByteOrder(dst.nindirectsyms); + sys::swapByteOrder(dst.extreloff); + sys::swapByteOrder(dst.nextrel); + sys::swapByteOrder(dst.locreloff); + sys::swapByteOrder(dst.nlocrel); + } + + inline void swapStruct(any_relocation_info &reloc) { + sys::swapByteOrder(reloc.r_word0); + sys::swapByteOrder(reloc.r_word1); + } + + inline void swapStruct(nlist_base &S) { + sys::swapByteOrder(S.n_strx); + sys::swapByteOrder(S.n_desc); + } + + inline void swapStruct(nlist &sym) { + sys::swapByteOrder(sym.n_strx); + sys::swapByteOrder(sym.n_desc); + sys::swapByteOrder(sym.n_value); + } + + inline void swapStruct(nlist_64 &sym) { + sys::swapByteOrder(sym.n_strx); + sys::swapByteOrder(sym.n_desc); + sys::swapByteOrder(sym.n_value); + } + + inline void swapStruct(linkedit_data_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.dataoff); + sys::swapByteOrder(C.datasize); + } + + inline void swapStruct(linker_option_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.count); + } + + inline void swapStruct(version_min_command&C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.version); + sys::swapByteOrder(C.sdk); + } + + inline void swapStruct(data_in_code_entry &C) { + sys::swapByteOrder(C.offset); + sys::swapByteOrder(C.length); + sys::swapByteOrder(C.kind); + } + + inline void swapStruct(uint32_t &C) { + sys::swapByteOrder(C); + } + + inline void swapStruct(prebind_cksum_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.cksum); + } + + inline void swapStruct(twolevel_hints_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.offset); + sys::swapByteOrder(C.nhints); + } + + inline void swapStruct(prebound_dylib_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.name); + sys::swapByteOrder(C.nmodules); + sys::swapByteOrder(C.linked_modules); + } + + inline void swapStruct(fvmfile_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.name); + sys::swapByteOrder(C.header_addr); + } + + inline void swapStruct(symseg_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.offset); + sys::swapByteOrder(C.size); + } + + inline void swapStruct(ident_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + } + + inline void swapStruct(fvmlib &C) { + sys::swapByteOrder(C.name); + sys::swapByteOrder(C.minor_version); + sys::swapByteOrder(C.header_addr); + } + + inline void swapStruct(fvmlib_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + swapStruct(C.fvmlib); + } + + // Get/Set functions from <mach-o/nlist.h> + + static inline uint16_t GET_LIBRARY_ORDINAL(uint16_t n_desc) { + return (((n_desc) >> 8u) & 0xffu); + } + + static inline void SET_LIBRARY_ORDINAL(uint16_t &n_desc, uint8_t ordinal) { + n_desc = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8)); + } + + static inline uint8_t GET_COMM_ALIGN (uint16_t n_desc) { + return (n_desc >> 8u) & 0x0fu; + } + + static inline void SET_COMM_ALIGN (uint16_t &n_desc, uint8_t align) { + n_desc = ((n_desc & 0xf0ffu) | ((align & 0x0fu) << 8u)); + } + + // Enums from <mach/machine.h> + enum : uint32_t { + // Capability bits used in the definition of cpu_type. + CPU_ARCH_MASK = 0xff000000, // Mask for architecture bits + CPU_ARCH_ABI64 = 0x01000000 // 64 bit ABI + }; + + // Constants for the cputype field. + enum CPUType { + CPU_TYPE_ANY = -1, + CPU_TYPE_X86 = 7, + CPU_TYPE_I386 = CPU_TYPE_X86, + CPU_TYPE_X86_64 = CPU_TYPE_X86 | CPU_ARCH_ABI64, + /* CPU_TYPE_MIPS = 8, */ + CPU_TYPE_MC98000 = 10, // Old Motorola PowerPC + CPU_TYPE_ARM = 12, + CPU_TYPE_ARM64 = CPU_TYPE_ARM | CPU_ARCH_ABI64, + CPU_TYPE_SPARC = 14, + CPU_TYPE_POWERPC = 18, + CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC | CPU_ARCH_ABI64 + }; + + enum : uint32_t { + // Capability bits used in the definition of cpusubtype. + CPU_SUBTYPE_MASK = 0xff000000, // Mask for architecture bits + CPU_SUBTYPE_LIB64 = 0x80000000, // 64 bit libraries + + // Special CPU subtype constants. + CPU_SUBTYPE_MULTIPLE = ~0u + }; + + // Constants for the cpusubtype field. + enum CPUSubTypeX86 { + CPU_SUBTYPE_I386_ALL = 3, + CPU_SUBTYPE_386 = 3, + CPU_SUBTYPE_486 = 4, + CPU_SUBTYPE_486SX = 0x84, + CPU_SUBTYPE_586 = 5, + CPU_SUBTYPE_PENT = CPU_SUBTYPE_586, + CPU_SUBTYPE_PENTPRO = 0x16, + CPU_SUBTYPE_PENTII_M3 = 0x36, + CPU_SUBTYPE_PENTII_M5 = 0x56, + CPU_SUBTYPE_CELERON = 0x67, + CPU_SUBTYPE_CELERON_MOBILE = 0x77, + CPU_SUBTYPE_PENTIUM_3 = 0x08, + CPU_SUBTYPE_PENTIUM_3_M = 0x18, + CPU_SUBTYPE_PENTIUM_3_XEON = 0x28, + CPU_SUBTYPE_PENTIUM_M = 0x09, + CPU_SUBTYPE_PENTIUM_4 = 0x0a, + CPU_SUBTYPE_PENTIUM_4_M = 0x1a, + CPU_SUBTYPE_ITANIUM = 0x0b, + CPU_SUBTYPE_ITANIUM_2 = 0x1b, + CPU_SUBTYPE_XEON = 0x0c, + CPU_SUBTYPE_XEON_MP = 0x1c, + + CPU_SUBTYPE_X86_ALL = 3, + CPU_SUBTYPE_X86_64_ALL = 3, + CPU_SUBTYPE_X86_ARCH1 = 4, + CPU_SUBTYPE_X86_64_H = 8 + }; + static inline int CPU_SUBTYPE_INTEL(int Family, int Model) { + return Family | (Model << 4); + } + static inline int CPU_SUBTYPE_INTEL_FAMILY(CPUSubTypeX86 ST) { + return ((int)ST) & 0x0f; + } + static inline int CPU_SUBTYPE_INTEL_MODEL(CPUSubTypeX86 ST) { + return ((int)ST) >> 4; + } + enum { + CPU_SUBTYPE_INTEL_FAMILY_MAX = 15, + CPU_SUBTYPE_INTEL_MODEL_ALL = 0 + }; + + enum CPUSubTypeARM { + CPU_SUBTYPE_ARM_ALL = 0, + CPU_SUBTYPE_ARM_V4T = 5, + CPU_SUBTYPE_ARM_V6 = 6, + CPU_SUBTYPE_ARM_V5 = 7, + CPU_SUBTYPE_ARM_V5TEJ = 7, + CPU_SUBTYPE_ARM_XSCALE = 8, + CPU_SUBTYPE_ARM_V7 = 9, + // unused ARM_V7F = 10, + CPU_SUBTYPE_ARM_V7S = 11, + CPU_SUBTYPE_ARM_V7K = 12, + CPU_SUBTYPE_ARM_V6M = 14, + CPU_SUBTYPE_ARM_V7M = 15, + CPU_SUBTYPE_ARM_V7EM = 16 + }; + + enum CPUSubTypeARM64 { + CPU_SUBTYPE_ARM64_ALL = 0 + }; + + enum CPUSubTypeSPARC { + CPU_SUBTYPE_SPARC_ALL = 0 + }; + + enum CPUSubTypePowerPC { + CPU_SUBTYPE_POWERPC_ALL = 0, + CPU_SUBTYPE_POWERPC_601 = 1, + CPU_SUBTYPE_POWERPC_602 = 2, + CPU_SUBTYPE_POWERPC_603 = 3, + CPU_SUBTYPE_POWERPC_603e = 4, + CPU_SUBTYPE_POWERPC_603ev = 5, + CPU_SUBTYPE_POWERPC_604 = 6, + CPU_SUBTYPE_POWERPC_604e = 7, + CPU_SUBTYPE_POWERPC_620 = 8, + CPU_SUBTYPE_POWERPC_750 = 9, + CPU_SUBTYPE_POWERPC_7400 = 10, + CPU_SUBTYPE_POWERPC_7450 = 11, + CPU_SUBTYPE_POWERPC_970 = 100, + + CPU_SUBTYPE_MC980000_ALL = CPU_SUBTYPE_POWERPC_ALL, + CPU_SUBTYPE_MC98601 = CPU_SUBTYPE_POWERPC_601 + }; + + struct x86_thread_state64_t { + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; + uint64_t rdi; + uint64_t rsi; + uint64_t rbp; + uint64_t rsp; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t rip; + uint64_t rflags; + uint64_t cs; + uint64_t fs; + uint64_t gs; + }; + + enum x86_fp_control_precis { + x86_FP_PREC_24B = 0, + x86_FP_PREC_53B = 2, + x86_FP_PREC_64B = 3 + }; + + enum x86_fp_control_rc { + x86_FP_RND_NEAR = 0, + x86_FP_RND_DOWN = 1, + x86_FP_RND_UP = 2, + x86_FP_CHOP = 3 + }; + + struct fp_control_t { + unsigned short + invalid :1, + denorm :1, + zdiv :1, + ovrfl :1, + undfl :1, + precis :1, + :2, + pc :2, + rc :2, + :1, + :3; + }; + + struct fp_status_t { + unsigned short + invalid :1, + denorm :1, + zdiv :1, + ovrfl :1, + undfl :1, + precis :1, + stkflt :1, + errsumm :1, + c0 :1, + c1 :1, + c2 :1, + tos :3, + c3 :1, + busy :1; + }; + + struct mmst_reg_t { + char mmst_reg[10]; + char mmst_rsrv[6]; + }; + + struct xmm_reg_t { + char xmm_reg[16]; + }; + + struct x86_float_state64_t { + int32_t fpu_reserved[2]; + fp_control_t fpu_fcw; + fp_status_t fpu_fsw; + uint8_t fpu_ftw; + uint8_t fpu_rsrv1; + uint16_t fpu_fop; + uint32_t fpu_ip; + uint16_t fpu_cs; + uint16_t fpu_rsrv2; + uint32_t fpu_dp; + uint16_t fpu_ds; + uint16_t fpu_rsrv3; + uint32_t fpu_mxcsr; + uint32_t fpu_mxcsrmask; + mmst_reg_t fpu_stmm0; + mmst_reg_t fpu_stmm1; + mmst_reg_t fpu_stmm2; + mmst_reg_t fpu_stmm3; + mmst_reg_t fpu_stmm4; + mmst_reg_t fpu_stmm5; + mmst_reg_t fpu_stmm6; + mmst_reg_t fpu_stmm7; + xmm_reg_t fpu_xmm0; + xmm_reg_t fpu_xmm1; + xmm_reg_t fpu_xmm2; + xmm_reg_t fpu_xmm3; + xmm_reg_t fpu_xmm4; + xmm_reg_t fpu_xmm5; + xmm_reg_t fpu_xmm6; + xmm_reg_t fpu_xmm7; + xmm_reg_t fpu_xmm8; + xmm_reg_t fpu_xmm9; + xmm_reg_t fpu_xmm10; + xmm_reg_t fpu_xmm11; + xmm_reg_t fpu_xmm12; + xmm_reg_t fpu_xmm13; + xmm_reg_t fpu_xmm14; + xmm_reg_t fpu_xmm15; + char fpu_rsrv4[6*16]; + uint32_t fpu_reserved1; + }; + + struct x86_exception_state64_t { + uint16_t trapno; + uint16_t cpu; + uint32_t err; + uint64_t faultvaddr; + }; + + inline void swapStruct(x86_thread_state64_t &x) { + sys::swapByteOrder(x.rax); + sys::swapByteOrder(x.rbx); + sys::swapByteOrder(x.rcx); + sys::swapByteOrder(x.rdx); + sys::swapByteOrder(x.rdi); + sys::swapByteOrder(x.rsi); + sys::swapByteOrder(x.rbp); + sys::swapByteOrder(x.rsp); + sys::swapByteOrder(x.r8); + sys::swapByteOrder(x.r9); + sys::swapByteOrder(x.r10); + sys::swapByteOrder(x.r11); + sys::swapByteOrder(x.r12); + sys::swapByteOrder(x.r13); + sys::swapByteOrder(x.r14); + sys::swapByteOrder(x.r15); + sys::swapByteOrder(x.rip); + sys::swapByteOrder(x.rflags); + sys::swapByteOrder(x.cs); + sys::swapByteOrder(x.fs); + sys::swapByteOrder(x.gs); + } + + inline void swapStruct(x86_float_state64_t &x) { + sys::swapByteOrder(x.fpu_reserved[0]); + sys::swapByteOrder(x.fpu_reserved[1]); + // TODO swap: fp_control_t fpu_fcw; + // TODO swap: fp_status_t fpu_fsw; + sys::swapByteOrder(x.fpu_fop); + sys::swapByteOrder(x.fpu_ip); + sys::swapByteOrder(x.fpu_cs); + sys::swapByteOrder(x.fpu_rsrv2); + sys::swapByteOrder(x.fpu_dp); + sys::swapByteOrder(x.fpu_ds); + sys::swapByteOrder(x.fpu_rsrv3); + sys::swapByteOrder(x.fpu_mxcsr); + sys::swapByteOrder(x.fpu_mxcsrmask); + sys::swapByteOrder(x.fpu_reserved1); + } + + inline void swapStruct(x86_exception_state64_t &x) { + sys::swapByteOrder(x.trapno); + sys::swapByteOrder(x.cpu); + sys::swapByteOrder(x.err); + sys::swapByteOrder(x.faultvaddr); + } + + struct x86_state_hdr_t { + uint32_t flavor; + uint32_t count; + }; + + struct x86_thread_state_t { + x86_state_hdr_t tsh; + union { + x86_thread_state64_t ts64; + } uts; + }; + + struct x86_float_state_t { + x86_state_hdr_t fsh; + union { + x86_float_state64_t fs64; + } ufs; + }; + + struct x86_exception_state_t { + x86_state_hdr_t esh; + union { + x86_exception_state64_t es64; + } ues; + }; + + inline void swapStruct(x86_state_hdr_t &x) { + sys::swapByteOrder(x.flavor); + sys::swapByteOrder(x.count); + } + + enum X86ThreadFlavors { + x86_THREAD_STATE32 = 1, + x86_FLOAT_STATE32 = 2, + x86_EXCEPTION_STATE32 = 3, + x86_THREAD_STATE64 = 4, + x86_FLOAT_STATE64 = 5, + x86_EXCEPTION_STATE64 = 6, + x86_THREAD_STATE = 7, + x86_FLOAT_STATE = 8, + x86_EXCEPTION_STATE = 9, + x86_DEBUG_STATE32 = 10, + x86_DEBUG_STATE64 = 11, + x86_DEBUG_STATE = 12 + }; + + inline void swapStruct(x86_thread_state_t &x) { + swapStruct(x.tsh); + if (x.tsh.flavor == x86_THREAD_STATE64) + swapStruct(x.uts.ts64); + } + + inline void swapStruct(x86_float_state_t &x) { + swapStruct(x.fsh); + if (x.fsh.flavor == x86_FLOAT_STATE64) + swapStruct(x.ufs.fs64); + } + + inline void swapStruct(x86_exception_state_t &x) { + swapStruct(x.esh); + if (x.esh.flavor == x86_EXCEPTION_STATE64) + swapStruct(x.ues.es64); + } + + const uint32_t x86_THREAD_STATE64_COUNT = + sizeof(x86_thread_state64_t) / sizeof(uint32_t); + const uint32_t x86_FLOAT_STATE64_COUNT = + sizeof(x86_float_state64_t) / sizeof(uint32_t); + const uint32_t x86_EXCEPTION_STATE64_COUNT = + sizeof(x86_exception_state64_t) / sizeof(uint32_t); + + const uint32_t x86_THREAD_STATE_COUNT = + sizeof(x86_thread_state_t) / sizeof(uint32_t); + const uint32_t x86_FLOAT_STATE_COUNT = + sizeof(x86_float_state_t) / sizeof(uint32_t); + const uint32_t x86_EXCEPTION_STATE_COUNT = + sizeof(x86_exception_state_t) / sizeof(uint32_t); + + // Define a union of all load command structs + #define LOAD_COMMAND_STRUCT(LCStruct) LCStruct LCStruct##_data; + + union macho_load_command { + #include "llvm/Support/MachO.def" + }; + + } // end namespace MachO +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/ManagedStatic.h b/third_party/llvm-subzero/include/llvm/Support/ManagedStatic.h new file mode 100644 index 0000000..ec8154b --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/ManagedStatic.h
@@ -0,0 +1,98 @@ +//===-- llvm/Support/ManagedStatic.h - Static Global wrapper ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ManagedStatic class and the llvm_shutdown() function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MANAGEDSTATIC_H +#define LLVM_SUPPORT_MANAGEDSTATIC_H + +#include "llvm/Support/Compiler.h" +#include <atomic> +#include <cstddef> + +namespace llvm { + +/// object_creator - Helper method for ManagedStatic. +template<class C> +LLVM_LIBRARY_VISIBILITY void* object_creator() { + return new C(); +} + +/// object_deleter - Helper method for ManagedStatic. +/// +template <typename T> struct LLVM_LIBRARY_VISIBILITY object_deleter { + static void call(void *Ptr) { delete (T *)Ptr; } +}; +template <typename T, size_t N> +struct LLVM_LIBRARY_VISIBILITY object_deleter<T[N]> { + static void call(void *Ptr) { delete[](T *)Ptr; } +}; + +/// ManagedStaticBase - Common base class for ManagedStatic instances. +class ManagedStaticBase { +protected: + // This should only be used as a static variable, which guarantees that this + // will be zero initialized. + mutable std::atomic<void *> Ptr; + mutable void (*DeleterFn)(void*); + mutable const ManagedStaticBase *Next; + + void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const; +public: + /// isConstructed - Return true if this object has not been created yet. + bool isConstructed() const { return Ptr != nullptr; } + + void destroy() const; +}; + +/// ManagedStatic - This transparently changes the behavior of global statics to +/// be lazily constructed on demand (good for reducing startup times of dynamic +/// libraries that link in LLVM components) and for making destruction be +/// explicit through the llvm_shutdown() function call. +/// +template<class C> +class ManagedStatic : public ManagedStaticBase { +public: + // Accessors. + C &operator*() { + void *Tmp = Ptr.load(std::memory_order_acquire); + if (!Tmp) + RegisterManagedStatic(object_creator<C>, object_deleter<C>::call); + + return *static_cast<C *>(Ptr.load(std::memory_order_relaxed)); + } + + C *operator->() { return &**this; } + + const C &operator*() const { + void *Tmp = Ptr.load(std::memory_order_acquire); + if (!Tmp) + RegisterManagedStatic(object_creator<C>, object_deleter<C>::call); + + return *static_cast<C *>(Ptr.load(std::memory_order_relaxed)); + } + + const C *operator->() const { return &**this; } +}; + +/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. +void llvm_shutdown(); + +/// llvm_shutdown_obj - This is a simple helper class that calls +/// llvm_shutdown() when it is destroyed. +struct llvm_shutdown_obj { + llvm_shutdown_obj() { } + ~llvm_shutdown_obj() { llvm_shutdown(); } +}; + +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/MathExtras.h b/third_party/llvm-subzero/include/llvm/Support/MathExtras.h new file mode 100644 index 0000000..fdf7f27 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/MathExtras.h
@@ -0,0 +1,836 @@ +//===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some functions that are useful for math stuff. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MATHEXTRAS_H +#define LLVM_SUPPORT_MATHEXTRAS_H + +#include "llvm/Support/Compiler.h" +#include "llvm/Support/SwapByteOrder.h" +#include <algorithm> +#include <cassert> +#include <cstring> +#include <type_traits> +#include <limits> + +#ifdef _MSC_VER +#include <intrin.h> +#endif + +#ifdef __ANDROID_NDK__ +#include <android/api-level.h> +#endif + +namespace llvm { +/// \brief The behavior an operation has on an input of 0. +enum ZeroBehavior { + /// \brief The returned value is undefined. + ZB_Undefined, + /// \brief The returned value is numeric_limits<T>::max() + ZB_Max, + /// \brief The returned value is numeric_limits<T>::digits + ZB_Width +}; + +namespace detail { +template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter { + static std::size_t count(T Val, ZeroBehavior) { + if (!Val) + return std::numeric_limits<T>::digits; + if (Val & 0x1) + return 0; + + // Bisection method. + std::size_t ZeroBits = 0; + T Shift = std::numeric_limits<T>::digits >> 1; + T Mask = std::numeric_limits<T>::max() >> Shift; + while (Shift) { + if ((Val & Mask) == 0) { + Val >>= Shift; + ZeroBits |= Shift; + } + Shift >>= 1; + Mask >>= Shift; + } + return ZeroBits; + } +}; + +#if __GNUC__ >= 4 || defined(_MSC_VER) +template <typename T> struct TrailingZerosCounter<T, 4> { + static std::size_t count(T Val, ZeroBehavior ZB) { + if (ZB != ZB_Undefined && Val == 0) + return 32; + +#if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0) + return __builtin_ctz(Val); +#elif defined(_MSC_VER) + unsigned long Index; + _BitScanForward(&Index, Val); + return Index; +#endif + } +}; + +#if !defined(_MSC_VER) || defined(_M_X64) +template <typename T> struct TrailingZerosCounter<T, 8> { + static std::size_t count(T Val, ZeroBehavior ZB) { + if (ZB != ZB_Undefined && Val == 0) + return 64; + +#if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0) + return __builtin_ctzll(Val); +#elif defined(_MSC_VER) + unsigned long Index; + _BitScanForward64(&Index, Val); + return Index; +#endif + } +}; +#endif +#endif +} // namespace detail + +/// \brief Count number of 0's from the least significant bit to the most +/// stopping at the first 1. +/// +/// Only unsigned integral types are allowed. +/// +/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are +/// valid arguments. +template <typename T> +std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { + static_assert(std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + "Only unsigned integral types are allowed."); + return detail::TrailingZerosCounter<T, sizeof(T)>::count(Val, ZB); +} + +namespace detail { +template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter { + static std::size_t count(T Val, ZeroBehavior) { + if (!Val) + return std::numeric_limits<T>::digits; + + // Bisection method. + std::size_t ZeroBits = 0; + for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) { + T Tmp = Val >> Shift; + if (Tmp) + Val = Tmp; + else + ZeroBits |= Shift; + } + return ZeroBits; + } +}; + +#if __GNUC__ >= 4 || defined(_MSC_VER) +template <typename T> struct LeadingZerosCounter<T, 4> { + static std::size_t count(T Val, ZeroBehavior ZB) { + if (ZB != ZB_Undefined && Val == 0) + return 32; + +#if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0) + return __builtin_clz(Val); +#elif defined(_MSC_VER) + unsigned long Index; + _BitScanReverse(&Index, Val); + return Index ^ 31; +#endif + } +}; + +#if !defined(_MSC_VER) || defined(_M_X64) +template <typename T> struct LeadingZerosCounter<T, 8> { + static std::size_t count(T Val, ZeroBehavior ZB) { + if (ZB != ZB_Undefined && Val == 0) + return 64; + +#if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0) + return __builtin_clzll(Val); +#elif defined(_MSC_VER) + unsigned long Index; + _BitScanReverse64(&Index, Val); + return Index ^ 63; +#endif + } +}; +#endif +#endif +} // namespace detail + +/// \brief Count number of 0's from the most significant bit to the least +/// stopping at the first 1. +/// +/// Only unsigned integral types are allowed. +/// +/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are +/// valid arguments. +template <typename T> +std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { + static_assert(std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + "Only unsigned integral types are allowed."); + return detail::LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB); +} + +/// \brief Get the index of the first set bit starting from the least +/// significant bit. +/// +/// Only unsigned integral types are allowed. +/// +/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are +/// valid arguments. +template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { + if (ZB == ZB_Max && Val == 0) + return std::numeric_limits<T>::max(); + + return countTrailingZeros(Val, ZB_Undefined); +} + +/// \brief Get the index of the last set bit starting from the least +/// significant bit. +/// +/// Only unsigned integral types are allowed. +/// +/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are +/// valid arguments. +template <typename T> T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { + if (ZB == ZB_Max && Val == 0) + return std::numeric_limits<T>::max(); + + // Use ^ instead of - because both gcc and llvm can remove the associated ^ + // in the __builtin_clz intrinsic on x86. + return countLeadingZeros(Val, ZB_Undefined) ^ + (std::numeric_limits<T>::digits - 1); +} + +/// \brief Macro compressed bit reversal table for 256 bits. +/// +/// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable +static const unsigned char BitReverseTable256[256] = { +#define R2(n) n, n + 2 * 64, n + 1 * 64, n + 3 * 64 +#define R4(n) R2(n), R2(n + 2 * 16), R2(n + 1 * 16), R2(n + 3 * 16) +#define R6(n) R4(n), R4(n + 2 * 4), R4(n + 1 * 4), R4(n + 3 * 4) + R6(0), R6(2), R6(1), R6(3) +#undef R2 +#undef R4 +#undef R6 +}; + +/// \brief Reverse the bits in \p Val. +template <typename T> +T reverseBits(T Val) { + unsigned char in[sizeof(Val)]; + unsigned char out[sizeof(Val)]; + std::memcpy(in, &Val, sizeof(Val)); + for (unsigned i = 0; i < sizeof(Val); ++i) + out[(sizeof(Val) - i) - 1] = BitReverseTable256[in[i]]; + std::memcpy(&Val, out, sizeof(Val)); + return Val; +} + +// NOTE: The following support functions use the _32/_64 extensions instead of +// type overloading so that signed and unsigned integers can be used without +// ambiguity. + +/// Hi_32 - This function returns the high 32 bits of a 64 bit value. +LLVM_CONSTEXPR inline uint32_t Hi_32(uint64_t Value) { + return static_cast<uint32_t>(Value >> 32); +} + +/// Lo_32 - This function returns the low 32 bits of a 64 bit value. +LLVM_CONSTEXPR inline uint32_t Lo_32(uint64_t Value) { + return static_cast<uint32_t>(Value); +} + +/// Make_64 - This functions makes a 64-bit integer from a high / low pair of +/// 32-bit integers. +LLVM_CONSTEXPR inline uint64_t Make_64(uint32_t High, uint32_t Low) { + return ((uint64_t)High << 32) | (uint64_t)Low; +} + +/// isInt - Checks if an integer fits into the given bit width. +template<unsigned N> +LLVM_CONSTEXPR inline bool isInt(int64_t x) { + return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); +} +// Template specializations to get better code for common cases. +template<> +LLVM_CONSTEXPR inline bool isInt<8>(int64_t x) { + return static_cast<int8_t>(x) == x; +} +template<> +LLVM_CONSTEXPR inline bool isInt<16>(int64_t x) { + return static_cast<int16_t>(x) == x; +} +template<> +LLVM_CONSTEXPR inline bool isInt<32>(int64_t x) { + return static_cast<int32_t>(x) == x; +} + +/// isShiftedInt<N,S> - Checks if a signed integer is an N bit number shifted +/// left by S. +template<unsigned N, unsigned S> +LLVM_CONSTEXPR inline bool isShiftedInt(int64_t x) { + static_assert( + N > 0, "isShiftedInt<0> doesn't make sense (refers to a 0-bit number."); + static_assert(N + S <= 64, "isShiftedInt<N, S> with N + S > 64 is too wide."); + return isInt<N + S>(x) && (x % (UINT64_C(1) << S) == 0); +} + +/// isUInt - Checks if an unsigned integer fits into the given bit width. +/// +/// This is written as two functions rather than as simply +/// +/// return N >= 64 || X < (UINT64_C(1) << N); +/// +/// to keep MSVC from (incorrectly) warning on isUInt<64> that we're shifting +/// left too many places. +template <unsigned N> +LLVM_CONSTEXPR inline typename std::enable_if<(N < 64), bool>::type +isUInt(uint64_t X) { + static_assert(N > 0, "isUInt<0> doesn't make sense"); + return X < (UINT64_C(1) << (N)); +} +template <unsigned N> +LLVM_CONSTEXPR inline typename std::enable_if<N >= 64, bool>::type +isUInt(uint64_t X) { + return true; +} + +// Template specializations to get better code for common cases. +template<> +LLVM_CONSTEXPR inline bool isUInt<8>(uint64_t x) { + return static_cast<uint8_t>(x) == x; +} +template<> +LLVM_CONSTEXPR inline bool isUInt<16>(uint64_t x) { + return static_cast<uint16_t>(x) == x; +} +template<> +LLVM_CONSTEXPR inline bool isUInt<32>(uint64_t x) { + return static_cast<uint32_t>(x) == x; +} + +/// Checks if a unsigned integer is an N bit number shifted left by S. +template<unsigned N, unsigned S> +LLVM_CONSTEXPR inline bool isShiftedUInt(uint64_t x) { + static_assert( + N > 0, "isShiftedUInt<0> doesn't make sense (refers to a 0-bit number)"); + static_assert(N + S <= 64, + "isShiftedUInt<N, S> with N + S > 64 is too wide."); + // Per the two static_asserts above, S must be strictly less than 64. So + // 1 << S is not undefined behavior. + return isUInt<N + S>(x) && (x % (UINT64_C(1) << S) == 0); +} + +/// Gets the maximum value for a N-bit unsigned integer. +inline uint64_t maxUIntN(uint64_t N) { + assert(N > 0 && N <= 64 && "integer width out of range"); + + // uint64_t(1) << 64 is undefined behavior, so we can't do + // (uint64_t(1) << N) - 1 + // without checking first that N != 64. But this works and doesn't have a + // branch. + return UINT64_MAX >> (64 - N); +} + +/// Gets the minimum value for a N-bit signed integer. +inline int64_t minIntN(int64_t N) { + assert(N > 0 && N <= 64 && "integer width out of range"); + + return -(UINT64_C(1)<<(N-1)); +} + +/// Gets the maximum value for a N-bit signed integer. +inline int64_t maxIntN(int64_t N) { + assert(N > 0 && N <= 64 && "integer width out of range"); + + // This relies on two's complement wraparound when N == 64, so we convert to + // int64_t only at the very end to avoid UB. + return (UINT64_C(1) << (N - 1)) - 1; +} + +/// isUIntN - Checks if an unsigned integer fits into the given (dynamic) +/// bit width. +inline bool isUIntN(unsigned N, uint64_t x) { + return N >= 64 || x <= maxUIntN(N); +} + +/// isIntN - Checks if an signed integer fits into the given (dynamic) +/// bit width. +inline bool isIntN(unsigned N, int64_t x) { + return N >= 64 || (minIntN(N) <= x && x <= maxIntN(N)); +} + +/// isMask_32 - This function returns true if the argument is a non-empty +/// sequence of ones starting at the least significant bit with the remainder +/// zero (32 bit version). Ex. isMask_32(0x0000FFFFU) == true. +LLVM_CONSTEXPR inline bool isMask_32(uint32_t Value) { + return Value && ((Value + 1) & Value) == 0; +} + +/// isMask_64 - This function returns true if the argument is a non-empty +/// sequence of ones starting at the least significant bit with the remainder +/// zero (64 bit version). +LLVM_CONSTEXPR inline bool isMask_64(uint64_t Value) { + return Value && ((Value + 1) & Value) == 0; +} + +/// isShiftedMask_32 - This function returns true if the argument contains a +/// non-empty sequence of ones with the remainder zero (32 bit version.) +/// Ex. isShiftedMask_32(0x0000FF00U) == true. +LLVM_CONSTEXPR inline bool isShiftedMask_32(uint32_t Value) { + return Value && isMask_32((Value - 1) | Value); +} + +/// isShiftedMask_64 - This function returns true if the argument contains a +/// non-empty sequence of ones with the remainder zero (64 bit version.) +LLVM_CONSTEXPR inline bool isShiftedMask_64(uint64_t Value) { + return Value && isMask_64((Value - 1) | Value); +} + +/// isPowerOf2_32 - This function returns true if the argument is a power of +/// two > 0. Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.) +LLVM_CONSTEXPR inline bool isPowerOf2_32(uint32_t Value) { + return Value && !(Value & (Value - 1)); +} + +/// isPowerOf2_64 - This function returns true if the argument is a power of two +/// > 0 (64 bit edition.) +LLVM_CONSTEXPR inline bool isPowerOf2_64(uint64_t Value) { + return Value && !(Value & (Value - int64_t(1L))); +} + +/// ByteSwap_16 - This function returns a byte-swapped representation of the +/// 16-bit argument, Value. +inline uint16_t ByteSwap_16(uint16_t Value) { + return sys::SwapByteOrder_16(Value); +} + +/// ByteSwap_32 - This function returns a byte-swapped representation of the +/// 32-bit argument, Value. +inline uint32_t ByteSwap_32(uint32_t Value) { + return sys::SwapByteOrder_32(Value); +} + +/// ByteSwap_64 - This function returns a byte-swapped representation of the +/// 64-bit argument, Value. +inline uint64_t ByteSwap_64(uint64_t Value) { + return sys::SwapByteOrder_64(Value); +} + +/// \brief Count the number of ones from the most significant bit to the first +/// zero bit. +/// +/// Ex. CountLeadingOnes(0xFF0FFF00) == 8. +/// Only unsigned integral types are allowed. +/// +/// \param ZB the behavior on an input of all ones. Only ZB_Width and +/// ZB_Undefined are valid arguments. +template <typename T> +std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) { + static_assert(std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + "Only unsigned integral types are allowed."); + return countLeadingZeros(~Value, ZB); +} + +/// \brief Count the number of ones from the least significant bit to the first +/// zero bit. +/// +/// Ex. countTrailingOnes(0x00FF00FF) == 8. +/// Only unsigned integral types are allowed. +/// +/// \param ZB the behavior on an input of all ones. Only ZB_Width and +/// ZB_Undefined are valid arguments. +template <typename T> +std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) { + static_assert(std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + "Only unsigned integral types are allowed."); + return countTrailingZeros(~Value, ZB); +} + +namespace detail { +template <typename T, std::size_t SizeOfT> struct PopulationCounter { + static unsigned count(T Value) { + // Generic version, forward to 32 bits. + static_assert(SizeOfT <= 4, "Not implemented!"); +#if __GNUC__ >= 4 + return __builtin_popcount(Value); +#else + uint32_t v = Value; + v = v - ((v >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; +#endif + } +}; + +template <typename T> struct PopulationCounter<T, 8> { + static unsigned count(T Value) { +#if __GNUC__ >= 4 + return __builtin_popcountll(Value); +#else + uint64_t v = Value; + v = v - ((v >> 1) & 0x5555555555555555ULL); + v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); + v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; + return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); +#endif + } +}; +} // namespace detail + +/// \brief Count the number of set bits in a value. +/// Ex. countPopulation(0xF000F000) = 8 +/// Returns 0 if the word is zero. +template <typename T> +inline unsigned countPopulation(T Value) { + static_assert(std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + "Only unsigned integral types are allowed."); + return detail::PopulationCounter<T, sizeof(T)>::count(Value); +} + +/// Log2 - This function returns the log base 2 of the specified value +inline double Log2(double Value) { +#if defined(__ANDROID_API__) && __ANDROID_API__ < 18 + return __builtin_log(Value) / __builtin_log(2.0); +#else + return log2(Value); +#endif +} + +/// Log2_32 - This function returns the floor log base 2 of the specified value, +/// -1 if the value is zero. (32 bit edition.) +/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2 +inline unsigned Log2_32(uint32_t Value) { + return 31 - countLeadingZeros(Value); +} + +/// Log2_64 - This function returns the floor log base 2 of the specified value, +/// -1 if the value is zero. (64 bit edition.) +inline unsigned Log2_64(uint64_t Value) { + return 63 - countLeadingZeros(Value); +} + +/// Log2_32_Ceil - This function returns the ceil log base 2 of the specified +/// value, 32 if the value is zero. (32 bit edition). +/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3 +inline unsigned Log2_32_Ceil(uint32_t Value) { + return 32 - countLeadingZeros(Value - 1); +} + +/// Log2_64_Ceil - This function returns the ceil log base 2 of the specified +/// value, 64 if the value is zero. (64 bit edition.) +inline unsigned Log2_64_Ceil(uint64_t Value) { + return 64 - countLeadingZeros(Value - 1); +} + +/// GreatestCommonDivisor64 - Return the greatest common divisor of the two +/// values using Euclid's algorithm. +inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) { + while (B) { + uint64_t T = B; + B = A % B; + A = T; + } + return A; +} + +/// BitsToDouble - This function takes a 64-bit integer and returns the bit +/// equivalent double. +inline double BitsToDouble(uint64_t Bits) { + union { + uint64_t L; + double D; + } T; + T.L = Bits; + return T.D; +} + +/// BitsToFloat - This function takes a 32-bit integer and returns the bit +/// equivalent float. +inline float BitsToFloat(uint32_t Bits) { + union { + uint32_t I; + float F; + } T; + T.I = Bits; + return T.F; +} + +/// DoubleToBits - This function takes a double and returns the bit +/// equivalent 64-bit integer. Note that copying doubles around +/// changes the bits of NaNs on some hosts, notably x86, so this +/// routine cannot be used if these bits are needed. +inline uint64_t DoubleToBits(double Double) { + union { + uint64_t L; + double D; + } T; + T.D = Double; + return T.L; +} + +/// FloatToBits - This function takes a float and returns the bit +/// equivalent 32-bit integer. Note that copying floats around +/// changes the bits of NaNs on some hosts, notably x86, so this +/// routine cannot be used if these bits are needed. +inline uint32_t FloatToBits(float Float) { + union { + uint32_t I; + float F; + } T; + T.F = Float; + return T.I; +} + +/// MinAlign - A and B are either alignments or offsets. Return the minimum +/// alignment that may be assumed after adding the two together. +LLVM_CONSTEXPR inline uint64_t MinAlign(uint64_t A, uint64_t B) { + // The largest power of 2 that divides both A and B. + // + // Replace "-Value" by "1+~Value" in the following commented code to avoid + // MSVC warning C4146 + // return (A | B) & -(A | B); + return (A | B) & (1 + ~(A | B)); +} + +/// \brief Aligns \c Addr to \c Alignment bytes, rounding up. +/// +/// Alignment should be a power of two. This method rounds up, so +/// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8. +inline uintptr_t alignAddr(const void *Addr, size_t Alignment) { + assert(Alignment && isPowerOf2_64((uint64_t)Alignment) && + "Alignment is not a power of two!"); + + assert((uintptr_t)Addr + Alignment - 1 >= (uintptr_t)Addr); + + return (((uintptr_t)Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1)); +} + +/// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment +/// bytes, rounding up. +inline size_t alignmentAdjustment(const void *Ptr, size_t Alignment) { + return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr; +} + +/// NextPowerOf2 - Returns the next power of two (in 64-bits) +/// that is strictly greater than A. Returns zero on overflow. +inline uint64_t NextPowerOf2(uint64_t A) { + A |= (A >> 1); + A |= (A >> 2); + A |= (A >> 4); + A |= (A >> 8); + A |= (A >> 16); + A |= (A >> 32); + return A + 1; +} + +/// Returns the power of two which is less than or equal to the given value. +/// Essentially, it is a floor operation across the domain of powers of two. +inline uint64_t PowerOf2Floor(uint64_t A) { + if (!A) return 0; + return 1ull << (63 - countLeadingZeros(A, ZB_Undefined)); +} + +/// Returns the next integer (mod 2**64) that is greater than or equal to +/// \p Value and is a multiple of \p Align. \p Align must be non-zero. +/// +/// If non-zero \p Skew is specified, the return value will be a minimal +/// integer that is greater than or equal to \p Value and equal to +/// \p Align * N + \p Skew for some integer N. If \p Skew is larger than +/// \p Align, its value is adjusted to '\p Skew mod \p Align'. +/// +/// Examples: +/// \code +/// alignTo(5, 8) = 8 +/// alignTo(17, 8) = 24 +/// alignTo(~0LL, 8) = 0 +/// alignTo(321, 255) = 510 +/// +/// alignTo(5, 8, 7) = 7 +/// alignTo(17, 8, 1) = 17 +/// alignTo(~0LL, 8, 3) = 3 +/// alignTo(321, 255, 42) = 552 +/// \endcode +inline uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew = 0) { + assert(Align != 0u && "Align can't be 0."); + Skew %= Align; + return (Value + Align - 1 - Skew) / Align * Align + Skew; +} + +/// Returns the next integer (mod 2**64) that is greater than or equal to +/// \p Value and is a multiple of \c Align. \c Align must be non-zero. +template <uint64_t Align> +LLVM_CONSTEXPR inline uint64_t alignTo(uint64_t Value) { + static_assert(Align != 0u, "Align must be non-zero"); + return (Value + Align - 1) / Align * Align; +} + +/// \c alignTo for contexts where a constant expression is required. +/// \sa alignTo +/// +/// \todo FIXME: remove when \c LLVM_CONSTEXPR becomes really \c constexpr +template <uint64_t Align> +struct AlignTo { + static_assert(Align != 0u, "Align must be non-zero"); + template <uint64_t Value> + struct from_value { + static const uint64_t value = (Value + Align - 1) / Align * Align; + }; +}; + +/// Returns the largest uint64_t less than or equal to \p Value and is +/// \p Skew mod \p Align. \p Align must be non-zero +inline uint64_t alignDown(uint64_t Value, uint64_t Align, uint64_t Skew = 0) { + assert(Align != 0u && "Align can't be 0."); + Skew %= Align; + return (Value - Skew) / Align * Align + Skew; +} + +/// Returns the offset to the next integer (mod 2**64) that is greater than +/// or equal to \p Value and is a multiple of \p Align. \p Align must be +/// non-zero. +inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) { + return alignTo(Value, Align) - Value; +} + +/// Sign-extend the number in the bottom B bits of X to a 32-bit integer. +/// Requires 0 < B <= 32. +template <unsigned B> LLVM_CONSTEXPR inline int32_t SignExtend32(uint32_t X) { + static_assert(B > 0, "Bit width can't be 0."); + static_assert(B <= 32, "Bit width out of range."); + return int32_t(X << (32 - B)) >> (32 - B); +} + +/// Sign-extend the number in the bottom B bits of X to a 32-bit integer. +/// Requires 0 < B < 32. +inline int32_t SignExtend32(uint32_t X, unsigned B) { + assert(B > 0 && "Bit width can't be 0."); + assert(B <= 32 && "Bit width out of range."); + return int32_t(X << (32 - B)) >> (32 - B); +} + +/// Sign-extend the number in the bottom B bits of X to a 64-bit integer. +/// Requires 0 < B < 64. +template <unsigned B> LLVM_CONSTEXPR inline int64_t SignExtend64(uint64_t x) { + static_assert(B > 0, "Bit width can't be 0."); + static_assert(B <= 64, "Bit width out of range."); + return int64_t(x << (64 - B)) >> (64 - B); +} + +/// Sign-extend the number in the bottom B bits of X to a 64-bit integer. +/// Requires 0 < B < 64. +inline int64_t SignExtend64(uint64_t X, unsigned B) { + assert(B > 0 && "Bit width can't be 0."); + assert(B <= 64 && "Bit width out of range."); + return int64_t(X << (64 - B)) >> (64 - B); +} + +/// Subtract two unsigned integers, X and Y, of type T and return the absolute +/// value of the result. +template <typename T> +typename std::enable_if<std::is_unsigned<T>::value, T>::type +AbsoluteDifference(T X, T Y) { + return std::max(X, Y) - std::min(X, Y); +} + +/// Add two unsigned integers, X and Y, of type T. Clamp the result to the +/// maximum representable value of T on overflow. ResultOverflowed indicates if +/// the result is larger than the maximum representable value of type T. +template <typename T> +typename std::enable_if<std::is_unsigned<T>::value, T>::type +SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) { + bool Dummy; + bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy; + // Hacker's Delight, p. 29 + T Z = X + Y; + Overflowed = (Z < X || Z < Y); + if (Overflowed) + return std::numeric_limits<T>::max(); + else + return Z; +} + +/// Multiply two unsigned integers, X and Y, of type T. Clamp the result to the +/// maximum representable value of T on overflow. ResultOverflowed indicates if +/// the result is larger than the maximum representable value of type T. +template <typename T> +typename std::enable_if<std::is_unsigned<T>::value, T>::type +SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) { + bool Dummy; + bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy; + + // Hacker's Delight, p. 30 has a different algorithm, but we don't use that + // because it fails for uint16_t (where multiplication can have undefined + // behavior due to promotion to int), and requires a division in addition + // to the multiplication. + + Overflowed = false; + + // Log2(Z) would be either Log2Z or Log2Z + 1. + // Special case: if X or Y is 0, Log2_64 gives -1, and Log2Z + // will necessarily be less than Log2Max as desired. + int Log2Z = Log2_64(X) + Log2_64(Y); + const T Max = std::numeric_limits<T>::max(); + int Log2Max = Log2_64(Max); + if (Log2Z < Log2Max) { + return X * Y; + } + if (Log2Z > Log2Max) { + Overflowed = true; + return Max; + } + + // We're going to use the top bit, and maybe overflow one + // bit past it. Multiply all but the bottom bit then add + // that on at the end. + T Z = (X >> 1) * Y; + if (Z & ~(Max >> 1)) { + Overflowed = true; + return Max; + } + Z <<= 1; + if (X & 1) + return SaturatingAdd(Z, Y, ResultOverflowed); + + return Z; +} + +/// Multiply two unsigned integers, X and Y, and add the unsigned integer, A to +/// the product. Clamp the result to the maximum representable value of T on +/// overflow. ResultOverflowed indicates if the result is larger than the +/// maximum representable value of type T. +template <typename T> +typename std::enable_if<std::is_unsigned<T>::value, T>::type +SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) { + bool Dummy; + bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy; + + T Product = SaturatingMultiply(X, Y, &Overflowed); + if (Overflowed) + return Product; + + return SaturatingAdd(A, Product, &Overflowed); +} + +/// Use this rather than HUGE_VALF; the latter causes warnings on MSVC. +extern const float huge_valf; +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Memory.h b/third_party/llvm-subzero/include/llvm/Support/Memory.h new file mode 100644 index 0000000..8103aea --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Memory.h
@@ -0,0 +1,186 @@ +//===- llvm/Support/Memory.h - Memory Support -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::Memory class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MEMORY_H +#define LLVM_SUPPORT_MEMORY_H + +#include "llvm/Support/DataTypes.h" +#include <string> +#include <system_error> + +namespace llvm { +namespace sys { + + /// This class encapsulates the notion of a memory block which has an address + /// and a size. It is used by the Memory class (a friend) as the result of + /// various memory allocation operations. + /// @see Memory + /// @brief Memory block abstraction. + class MemoryBlock { + public: + MemoryBlock() : Address(nullptr), Size(0) { } + MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { } + void *base() const { return Address; } + size_t size() const { return Size; } + + private: + void *Address; ///< Address of first byte of memory area + size_t Size; ///< Size, in bytes of the memory area + friend class Memory; + }; + + /// This class provides various memory handling functions that manipulate + /// MemoryBlock instances. + /// @since 1.4 + /// @brief An abstraction for memory operations. + class Memory { + public: + enum ProtectionFlags { + MF_READ = 0x1000000, + MF_WRITE = 0x2000000, + MF_EXEC = 0x4000000 + }; + + /// This method allocates a block of memory that is suitable for loading + /// dynamically generated code (e.g. JIT). An attempt to allocate + /// \p NumBytes bytes of virtual memory is made. + /// \p NearBlock may point to an existing allocation in which case + /// an attempt is made to allocate more memory near the existing block. + /// The actual allocated address is not guaranteed to be near the requested + /// address. + /// \p Flags is used to set the initial protection flags for the block + /// of the memory. + /// \p EC [out] returns an object describing any error that occurs. + /// + /// This method may allocate more than the number of bytes requested. The + /// actual number of bytes allocated is indicated in the returned + /// MemoryBlock. + /// + /// The start of the allocated block must be aligned with the + /// system allocation granularity (64K on Windows, page size on Linux). + /// If the address following \p NearBlock is not so aligned, it will be + /// rounded up to the next allocation granularity boundary. + /// + /// \r a non-null MemoryBlock if the function was successful, + /// otherwise a null MemoryBlock is with \p EC describing the error. + /// + /// @brief Allocate mapped memory. + static MemoryBlock allocateMappedMemory(size_t NumBytes, + const MemoryBlock *const NearBlock, + unsigned Flags, + std::error_code &EC); + + /// This method releases a block of memory that was allocated with the + /// allocateMappedMemory method. It should not be used to release any + /// memory block allocated any other way. + /// \p Block describes the memory to be released. + /// + /// \r error_success if the function was successful, or an error_code + /// describing the failure if an error occurred. + /// + /// @brief Release mapped memory. + static std::error_code releaseMappedMemory(MemoryBlock &Block); + + /// This method sets the protection flags for a block of memory to the + /// state specified by /p Flags. The behavior is not specified if the + /// memory was not allocated using the allocateMappedMemory method. + /// \p Block describes the memory block to be protected. + /// \p Flags specifies the new protection state to be assigned to the block. + /// \p ErrMsg [out] returns a string describing any error that occurred. + /// + /// If \p Flags is MF_WRITE, the actual behavior varies + /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and the + /// target architecture (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386). + /// + /// \r error_success if the function was successful, or an error_code + /// describing the failure if an error occurred. + /// + /// @brief Set memory protection state. + static std::error_code protectMappedMemory(const MemoryBlock &Block, + unsigned Flags); + + /// This method allocates a block of Read/Write/Execute memory that is + /// suitable for executing dynamically generated code (e.g. JIT). An + /// attempt to allocate \p NumBytes bytes of virtual memory is made. + /// \p NearBlock may point to an existing allocation in which case + /// an attempt is made to allocate more memory near the existing block. + /// + /// On success, this returns a non-null memory block, otherwise it returns + /// a null memory block and fills in *ErrMsg. + /// + /// @brief Allocate Read/Write/Execute memory. + static MemoryBlock AllocateRWX(size_t NumBytes, + const MemoryBlock *NearBlock, + std::string *ErrMsg = nullptr); + + /// This method releases a block of Read/Write/Execute memory that was + /// allocated with the AllocateRWX method. It should not be used to + /// release any memory block allocated any other way. + /// + /// On success, this returns false, otherwise it returns true and fills + /// in *ErrMsg. + /// @brief Release Read/Write/Execute memory. + static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = nullptr); + + /// InvalidateInstructionCache - Before the JIT can run a block of code + /// that has been emitted it must invalidate the instruction cache on some + /// platforms. + static void InvalidateInstructionCache(const void *Addr, size_t Len); + + /// setExecutable - Before the JIT can run a block of code, it has to be + /// given read and executable privilege. Return true if it is already r-x + /// or the system is able to change its previlege. + static bool setExecutable(MemoryBlock &M, std::string *ErrMsg = nullptr); + + /// setWritable - When adding to a block of code, the JIT may need + /// to mark a block of code as RW since the protections are on page + /// boundaries, and the JIT internal allocations are not page aligned. + static bool setWritable(MemoryBlock &M, std::string *ErrMsg = nullptr); + + /// setRangeExecutable - Mark the page containing a range of addresses + /// as executable. + static bool setRangeExecutable(const void *Addr, size_t Size); + + /// setRangeWritable - Mark the page containing a range of addresses + /// as writable. + static bool setRangeWritable(const void *Addr, size_t Size); + }; + + /// Owning version of MemoryBlock. + class OwningMemoryBlock { + public: + OwningMemoryBlock() = default; + explicit OwningMemoryBlock(MemoryBlock M) : M(M) {} + OwningMemoryBlock(OwningMemoryBlock &&Other) { + M = Other.M; + Other.M = MemoryBlock(); + } + OwningMemoryBlock& operator=(OwningMemoryBlock &&Other) { + M = Other.M; + Other.M = MemoryBlock(); + return *this; + } + ~OwningMemoryBlock() { + Memory::releaseMappedMemory(M); + } + void *base() const { return M.base(); } + size_t size() const { return M.size(); } + MemoryBlock getMemoryBlock() const { return M; } + private: + MemoryBlock M; + }; + +} +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/MemoryBuffer.h b/third_party/llvm-subzero/include/llvm/Support/MemoryBuffer.h new file mode 100644 index 0000000..73d6435 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/MemoryBuffer.h
@@ -0,0 +1,173 @@ +//===--- MemoryBuffer.h - Memory Buffer Interface ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the MemoryBuffer interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MEMORYBUFFER_H +#define LLVM_SUPPORT_MEMORYBUFFER_H + +#include "llvm/ADT/Twine.h" +#include "llvm/Support/CBindingWrapping.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorOr.h" +#include <memory> + +namespace llvm { +class MemoryBufferRef; + +/// This interface provides simple read-only access to a block of memory, and +/// provides simple methods for reading files and standard input into a memory +/// buffer. In addition to basic access to the characters in the file, this +/// interface guarantees you can read one character past the end of the file, +/// and that this character will read as '\0'. +/// +/// The '\0' guarantee is needed to support an optimization -- it's intended to +/// be more efficient for clients which are reading all the data to stop +/// reading when they encounter a '\0' than to continually check the file +/// position to see if it has reached the end of the file. +class MemoryBuffer { + const char *BufferStart; // Start of the buffer. + const char *BufferEnd; // End of the buffer. + + MemoryBuffer(const MemoryBuffer &) = delete; + MemoryBuffer &operator=(const MemoryBuffer &) = delete; +protected: + MemoryBuffer() {} + void init(const char *BufStart, const char *BufEnd, + bool RequiresNullTerminator); +public: + virtual ~MemoryBuffer(); + + const char *getBufferStart() const { return BufferStart; } + const char *getBufferEnd() const { return BufferEnd; } + size_t getBufferSize() const { return BufferEnd-BufferStart; } + + StringRef getBuffer() const { + return StringRef(BufferStart, getBufferSize()); + } + + /// Return an identifier for this buffer, typically the filename it was read + /// from. + virtual const char *getBufferIdentifier() const { + return "Unknown buffer"; + } + + /// Open the specified file as a MemoryBuffer, returning a new MemoryBuffer + /// if successful, otherwise returning null. If FileSize is specified, this + /// means that the client knows that the file exists and that it has the + /// specified size. + /// + /// \param IsVolatileSize Set to true to indicate that the file size may be + /// changing, e.g. when libclang tries to parse while the user is + /// editing/updating the file. + static ErrorOr<std::unique_ptr<MemoryBuffer>> + getFile(const Twine &Filename, int64_t FileSize = -1, + bool RequiresNullTerminator = true, bool IsVolatileSize = false); + + /// Given an already-open file descriptor, map some slice of it into a + /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize. + /// Since this is in the middle of a file, the buffer is not null terminated. + static ErrorOr<std::unique_ptr<MemoryBuffer>> + getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize, + int64_t Offset); + + /// Given an already-open file descriptor, read the file and return a + /// MemoryBuffer. + /// + /// \param IsVolatileSize Set to true to indicate that the file size may be + /// changing, e.g. when libclang tries to parse while the user is + /// editing/updating the file. + static ErrorOr<std::unique_ptr<MemoryBuffer>> + getOpenFile(int FD, const Twine &Filename, uint64_t FileSize, + bool RequiresNullTerminator = true, bool IsVolatileSize = false); + + /// Open the specified memory range as a MemoryBuffer. Note that InputData + /// must be null terminated if RequiresNullTerminator is true. + static std::unique_ptr<MemoryBuffer> + getMemBuffer(StringRef InputData, StringRef BufferName = "", + bool RequiresNullTerminator = true); + + static std::unique_ptr<MemoryBuffer> + getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator = true); + + /// Open the specified memory range as a MemoryBuffer, copying the contents + /// and taking ownership of it. InputData does not have to be null terminated. + static std::unique_ptr<MemoryBuffer> + getMemBufferCopy(StringRef InputData, const Twine &BufferName = ""); + + /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note + /// that the caller need not initialize the memory allocated by this method. + /// The memory is owned by the MemoryBuffer object. + static std::unique_ptr<MemoryBuffer> + getNewMemBuffer(size_t Size, StringRef BufferName = ""); + + /// Allocate a new MemoryBuffer of the specified size that is not initialized. + /// Note that the caller should initialize the memory allocated by this + /// method. The memory is owned by the MemoryBuffer object. + static std::unique_ptr<MemoryBuffer> + getNewUninitMemBuffer(size_t Size, const Twine &BufferName = ""); + + /// Read all of stdin into a file buffer, and return it. + static ErrorOr<std::unique_ptr<MemoryBuffer>> getSTDIN(); + + /// Open the specified file as a MemoryBuffer, or open stdin if the Filename + /// is "-". + static ErrorOr<std::unique_ptr<MemoryBuffer>> + getFileOrSTDIN(const Twine &Filename, int64_t FileSize = -1, + bool RequiresNullTerminator = true); + + /// Map a subrange of the specified file as a MemoryBuffer. + static ErrorOr<std::unique_ptr<MemoryBuffer>> + getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset); + + //===--------------------------------------------------------------------===// + // Provided for performance analysis. + //===--------------------------------------------------------------------===// + + /// The kind of memory backing used to support the MemoryBuffer. + enum BufferKind { + MemoryBuffer_Malloc, + MemoryBuffer_MMap + }; + + /// Return information on the memory mechanism used to support the + /// MemoryBuffer. + virtual BufferKind getBufferKind() const = 0; + + MemoryBufferRef getMemBufferRef() const; +}; + +class MemoryBufferRef { + StringRef Buffer; + StringRef Identifier; + +public: + MemoryBufferRef() {} + MemoryBufferRef(MemoryBuffer& Buffer) + : Buffer(Buffer.getBuffer()), Identifier(Buffer.getBufferIdentifier()) {} + MemoryBufferRef(StringRef Buffer, StringRef Identifier) + : Buffer(Buffer), Identifier(Identifier) {} + + StringRef getBuffer() const { return Buffer; } + + StringRef getBufferIdentifier() const { return Identifier; } + + const char *getBufferStart() const { return Buffer.begin(); } + const char *getBufferEnd() const { return Buffer.end(); } + size_t getBufferSize() const { return Buffer.size(); } +}; + +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef) + +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/MemoryObject.h b/third_party/llvm-subzero/include/llvm/Support/MemoryObject.h new file mode 100644 index 0000000..e0c8749 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/MemoryObject.h
@@ -0,0 +1,68 @@ +//===- MemoryObject.h - Abstract memory interface ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MEMORYOBJECT_H +#define LLVM_SUPPORT_MEMORYOBJECT_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +/// Interface to data which might be streamed. Streamability has 2 important +/// implications/restrictions. First, the data might not yet exist in memory +/// when the request is made. This just means that readByte/readBytes might have +/// to block or do some work to get it. More significantly, the exact size of +/// the object might not be known until it has all been fetched. This means that +/// to return the right result, getExtent must also wait for all the data to +/// arrive; therefore it should not be called on objects which are actually +/// streamed (this would defeat the purpose of streaming). Instead, +/// isValidAddress can be used to test addresses without knowing the exact size +/// of the stream. Finally, getPointer can be used instead of readBytes to avoid +/// extra copying. +class MemoryObject { +public: + virtual ~MemoryObject(); + + /// Returns the size of the region in bytes. (The region is contiguous, so + /// the highest valid address of the region is getExtent() - 1). + /// + /// @result - The size of the region. + virtual uint64_t getExtent() const = 0; + + /// Tries to read a contiguous range of bytes from the region, up to the end + /// of the region. + /// + /// @param Buf - A pointer to a buffer to be filled in. Must be non-NULL + /// and large enough to hold size bytes. + /// @param Size - The number of bytes to copy. + /// @param Address - The address of the first byte, in the same space as + /// getBase(). + /// @result - The number of bytes read. + virtual uint64_t readBytes(uint8_t *Buf, uint64_t Size, + uint64_t Address) const = 0; + + /// Ensures that the requested data is in memory, and returns a pointer to it. + /// More efficient than using readBytes if the data is already in memory. May + /// block until (address - base + size) bytes have been read + /// @param address - address of the byte, in the same space as getBase() + /// @param size - amount of data that must be available on return + /// @result - valid pointer to the requested data + virtual const uint8_t *getPointer(uint64_t address, uint64_t size) const = 0; + + /// Returns true if the address is within the object (i.e. between base and + /// base + extent - 1 inclusive). May block until (address - base) bytes have + /// been read + /// @param address - address of the byte, in the same space as getBase() + /// @result - true if the address may be read with readByte() + virtual bool isValidAddress(uint64_t address) const = 0; +}; + +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Mutex.h b/third_party/llvm-subzero/include/llvm/Support/Mutex.h new file mode 100644 index 0000000..0f4e61a --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Mutex.h
@@ -0,0 +1,158 @@ +//===- llvm/Support/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::Mutex class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MUTEX_H +#define LLVM_SUPPORT_MUTEX_H + +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Threading.h" +#include <cassert> + +namespace llvm +{ + namespace sys + { + /// @brief Platform agnostic Mutex class. + class MutexImpl + { + /// @name Constructors + /// @{ + public: + + /// Initializes the lock but doesn't acquire it. if \p recursive is set + /// to false, the lock will not be recursive which makes it cheaper but + /// also more likely to deadlock (same thread can't acquire more than + /// once). + /// @brief Default Constructor. + explicit MutexImpl(bool recursive = true); + + /// Releases and removes the lock + /// @brief Destructor + ~MutexImpl(); + + /// @} + /// @name Methods + /// @{ + public: + + /// Attempts to unconditionally acquire the lock. If the lock is held by + /// another thread, this method will wait until it can acquire the lock. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally acquire the lock. + bool acquire(); + + /// Attempts to release the lock. If the lock is held by the current + /// thread, the lock is released allowing other threads to acquire the + /// lock. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally release the lock. + bool release(); + + /// Attempts to acquire the lock without blocking. If the lock is not + /// available, this function returns false quickly (without blocking). If + /// the lock is available, it is acquired. + /// @returns false if any kind of error occurs or the lock is not + /// available, true otherwise. + /// @brief Try to acquire the lock. + bool tryacquire(); + + //@} + /// @name Platform Dependent Data + /// @{ + private: +#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0 + void* data_; ///< We don't know what the data will be +#endif + + /// @} + /// @name Do Not Implement + /// @{ + private: + MutexImpl(const MutexImpl &) = delete; + void operator=(const MutexImpl &) = delete; + /// @} + }; + + + /// SmartMutex - A mutex with a compile time constant parameter that + /// indicates whether this mutex should become a no-op when we're not + /// running in multithreaded mode. + template<bool mt_only> + class SmartMutex { + MutexImpl impl; + unsigned acquired; + bool recursive; + public: + explicit SmartMutex(bool rec = true) : + impl(rec), acquired(0), recursive(rec) { } + + bool lock() { + if (!mt_only || llvm_is_multithreaded()) { + return impl.acquire(); + } else { + // Single-threaded debugging code. This would be racy in + // multithreaded mode, but provides not sanity checks in single + // threaded mode. + assert((recursive || acquired == 0) && "Lock already acquired!!"); + ++acquired; + return true; + } + } + + bool unlock() { + if (!mt_only || llvm_is_multithreaded()) { + return impl.release(); + } else { + // Single-threaded debugging code. This would be racy in + // multithreaded mode, but provides not sanity checks in single + // threaded mode. + assert(((recursive && acquired) || (acquired == 1)) && + "Lock not acquired before release!"); + --acquired; + return true; + } + } + + bool try_lock() { + if (!mt_only || llvm_is_multithreaded()) + return impl.tryacquire(); + else return true; + } + + private: + SmartMutex(const SmartMutex<mt_only> & original); + void operator=(const SmartMutex<mt_only> &); + }; + + /// Mutex - A standard, always enforced mutex. + typedef SmartMutex<false> Mutex; + + template<bool mt_only> + class SmartScopedLock { + SmartMutex<mt_only>& mtx; + + public: + SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) { + mtx.lock(); + } + + ~SmartScopedLock() { + mtx.unlock(); + } + }; + + typedef SmartScopedLock<false> ScopedLock; + } +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/MutexGuard.h b/third_party/llvm-subzero/include/llvm/Support/MutexGuard.h new file mode 100644 index 0000000..07b64b6 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/MutexGuard.h
@@ -0,0 +1,41 @@ +//===-- Support/MutexGuard.h - Acquire/Release Mutex In Scope ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a guard for a block of code that ensures a Mutex is locked +// upon construction and released upon destruction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MUTEXGUARD_H +#define LLVM_SUPPORT_MUTEXGUARD_H + +#include "llvm/Support/Mutex.h" + +namespace llvm { + /// Instances of this class acquire a given Mutex Lock when constructed and + /// hold that lock until destruction. The intention is to instantiate one of + /// these on the stack at the top of some scope to be assured that C++ + /// destruction of the object will always release the Mutex and thus avoid + /// a host of nasty multi-threading problems in the face of exceptions, etc. + /// @brief Guard a section of code with a Mutex. + class MutexGuard { + sys::Mutex &M; + MutexGuard(const MutexGuard &) = delete; + void operator=(const MutexGuard &) = delete; + public: + MutexGuard(sys::Mutex &m) : M(m) { M.lock(); } + ~MutexGuard() { M.unlock(); } + /// holds - Returns true if this locker instance holds the specified lock. + /// This is mostly used in assertions to validate that the correct mutex + /// is held. + bool holds(const sys::Mutex& lock) const { return &M == &lock; } + }; +} + +#endif // LLVM_SUPPORT_MUTEXGUARD_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/Options.h b/third_party/llvm-subzero/include/llvm/Support/Options.h new file mode 100644 index 0000000..7b61b23 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Options.h
@@ -0,0 +1,120 @@ +//===- llvm/Support/Options.h - Debug options support -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file declares helper objects for defining debug options that can be +/// configured via the command line. The new API currently builds on the cl::opt +/// API, but does not require the use of static globals. +/// +/// With this API options are registered during initialization. For passes, this +/// happens during pass initialization. Passes with options will call a static +/// registerOptions method during initialization that registers options with the +/// OptionRegistry. An example implementation of registerOptions is: +/// +/// static void registerOptions() { +/// OptionRegistry::registerOption<bool, Scalarizer, +/// &Scalarizer::ScalarizeLoadStore>( +/// "scalarize-load-store", +/// "Allow the scalarizer pass to scalarize loads and store", false); +/// } +/// +/// When reading data for options the interface is via the LLVMContext. Option +/// data for passes should be read from the context during doInitialization. An +/// example of reading the above option would be: +/// +/// ScalarizeLoadStore = +/// M.getContext().getOption<bool, +/// Scalarizer, +/// &Scalarizer::ScalarizeLoadStore>(); +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_OPTIONS_H +#define LLVM_SUPPORT_OPTIONS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/CommandLine.h" + +namespace llvm { + +namespace detail { + +// Options are keyed of the unique address of a static character synthesized +// based on template arguments. +template <typename ValT, typename Base, ValT(Base::*Mem)> class OptionKey { +public: + static char ID; +}; + +template <typename ValT, typename Base, ValT(Base::*Mem)> +char OptionKey<ValT, Base, Mem>::ID = 0; + +} // namespace detail + +/// \brief Singleton class used to register debug options. +/// +/// The OptionRegistry is responsible for managing lifetimes of the options and +/// provides interfaces for option registration and reading values from options. +/// This object is a singleton, only one instance should ever exist so that all +/// options are registered in the same place. +class OptionRegistry { +private: + DenseMap<void *, cl::Option *> Options; + + /// \brief Adds a cl::Option to the registry. + /// + /// \param Key unique key for option + /// \param O option to map to \p Key + /// + /// Allocated cl::Options are owned by the OptionRegistry and are deallocated + /// on destruction or removal + void addOption(void *Key, cl::Option *O); + +public: + ~OptionRegistry(); + OptionRegistry() {} + + /// \brief Returns a reference to the singleton instance. + static OptionRegistry &instance(); + + /// \brief Registers an option with the OptionRegistry singleton. + /// + /// \tparam ValT type of the option's data + /// \tparam Base class used to key the option + /// \tparam Mem member of \p Base used for keying the option + /// + /// Options are keyed off the template parameters to generate unique static + /// characters. The template parameters are (1) the type of the data the + /// option stores (\p ValT), the class that will read the option (\p Base), + /// and the member that the class will store the data into (\p Mem). + template <typename ValT, typename Base, ValT(Base::*Mem)> + static void registerOption(const char *ArgStr, const char *Desc, + const ValT &InitValue) { + cl::opt<ValT> *Option = new cl::opt<ValT>(ArgStr, cl::desc(Desc), + cl::Hidden, cl::init(InitValue)); + instance().addOption(&detail::OptionKey<ValT, Base, Mem>::ID, Option); + } + + /// \brief Returns the value of the option. + /// + /// \tparam ValT type of the option's data + /// \tparam Base class used to key the option + /// \tparam Mem member of \p Base used for keying the option + /// + /// Reads option values based on the key generated by the template parameters. + /// Keying for get() is the same as keying for registerOption. + template <typename ValT, typename Base, ValT(Base::*Mem)> ValT get() const { + auto It = Options.find(&detail::OptionKey<ValT, Base, Mem>::ID); + assert(It != Options.end() && "Option not in OptionRegistry"); + return *(cl::opt<ValT> *)It->second; + } +}; + +} // namespace llvm + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Path.h b/third_party/llvm-subzero/include/llvm/Support/Path.h new file mode 100644 index 0000000..853f099 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Path.h
@@ -0,0 +1,456 @@ +//===- llvm/Support/Path.h - Path Operating System Concept ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::path namespace. It is designed after +// TR2/boost filesystem (v3), but modified to remove exception handling and the +// path class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PATH_H +#define LLVM_SUPPORT_PATH_H + +#include "llvm/ADT/Twine.h" +#include "llvm/Support/DataTypes.h" +#include <iterator> + +namespace llvm { +namespace sys { +namespace path { + +/// @name Lexical Component Iterator +/// @{ + +/// @brief Path iterator. +/// +/// This is an input iterator that iterates over the individual components in +/// \a path. The traversal order is as follows: +/// * The root-name element, if present. +/// * The root-directory element, if present. +/// * Each successive filename element, if present. +/// * Dot, if one or more trailing non-root slash characters are present. +/// Traversing backwards is possible with \a reverse_iterator +/// +/// Iteration examples. Each component is separated by ',': +/// @code +/// / => / +/// /foo => /,foo +/// foo/ => foo,. +/// /foo/bar => /,foo,bar +/// ../ => ..,. +/// C:\foo\bar => C:,/,foo,bar +/// @endcode +class const_iterator + : public std::iterator<std::input_iterator_tag, const StringRef> { + StringRef Path; ///< The entire path. + StringRef Component; ///< The current component. Not necessarily in Path. + size_t Position; ///< The iterators current position within Path. + + // An end iterator has Position = Path.size() + 1. + friend const_iterator begin(StringRef path); + friend const_iterator end(StringRef path); + +public: + reference operator*() const { return Component; } + pointer operator->() const { return &Component; } + const_iterator &operator++(); // preincrement + bool operator==(const const_iterator &RHS) const; + bool operator!=(const const_iterator &RHS) const { return !(*this == RHS); } + + /// @brief Difference in bytes between this and RHS. + ptrdiff_t operator-(const const_iterator &RHS) const; +}; + +/// @brief Reverse path iterator. +/// +/// This is an input iterator that iterates over the individual components in +/// \a path in reverse order. The traversal order is exactly reversed from that +/// of \a const_iterator +class reverse_iterator + : public std::iterator<std::input_iterator_tag, const StringRef> { + StringRef Path; ///< The entire path. + StringRef Component; ///< The current component. Not necessarily in Path. + size_t Position; ///< The iterators current position within Path. + + friend reverse_iterator rbegin(StringRef path); + friend reverse_iterator rend(StringRef path); + +public: + reference operator*() const { return Component; } + pointer operator->() const { return &Component; } + reverse_iterator &operator++(); // preincrement + bool operator==(const reverse_iterator &RHS) const; + bool operator!=(const reverse_iterator &RHS) const { return !(*this == RHS); } + + /// @brief Difference in bytes between this and RHS. + ptrdiff_t operator-(const reverse_iterator &RHS) const; +}; + +/// @brief Get begin iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized with the first component of \a path. +const_iterator begin(StringRef path); + +/// @brief Get end iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized to the end of \a path. +const_iterator end(StringRef path); + +/// @brief Get reverse begin iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized with the first reverse component of \a path. +reverse_iterator rbegin(StringRef path); + +/// @brief Get reverse end iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized to the reverse end of \a path. +reverse_iterator rend(StringRef path); + +/// @} +/// @name Lexical Modifiers +/// @{ + +/// @brief Remove the last component from \a path unless it is the root dir. +/// +/// @code +/// directory/filename.cpp => directory/ +/// directory/ => directory +/// filename.cpp => <empty> +/// / => / +/// @endcode +/// +/// @param path A path that is modified to not have a file component. +void remove_filename(SmallVectorImpl<char> &path); + +/// @brief Replace the file extension of \a path with \a extension. +/// +/// @code +/// ./filename.cpp => ./filename.extension +/// ./filename => ./filename.extension +/// ./ => ./.extension +/// @endcode +/// +/// @param path A path that has its extension replaced with \a extension. +/// @param extension The extension to be added. It may be empty. It may also +/// optionally start with a '.', if it does not, one will be +/// prepended. +void replace_extension(SmallVectorImpl<char> &path, const Twine &extension); + +/// @brief Replace matching path prefix with another path. +/// +/// @code +/// /foo, /old, /new => /foo +/// /old/foo, /old, /new => /new/foo +/// /foo, <empty>, /new => /new/foo +/// /old/foo, /old, <empty> => /foo +/// @endcode +/// +/// @param Path If \a Path starts with \a OldPrefix modify to instead +/// start with \a NewPrefix. +/// @param OldPrefix The path prefix to strip from \a Path. +/// @param NewPrefix The path prefix to replace \a NewPrefix with. +void replace_path_prefix(SmallVectorImpl<char> &Path, + const StringRef &OldPrefix, + const StringRef &NewPrefix); + +/// @brief Append to path. +/// +/// @code +/// /foo + bar/f => /foo/bar/f +/// /foo/ + bar/f => /foo/bar/f +/// foo + bar/f => foo/bar/f +/// @endcode +/// +/// @param path Set to \a path + \a component. +/// @param a The component to be appended to \a path. +void append(SmallVectorImpl<char> &path, const Twine &a, + const Twine &b = "", + const Twine &c = "", + const Twine &d = ""); + +/// @brief Append to path. +/// +/// @code +/// /foo + [bar,f] => /foo/bar/f +/// /foo/ + [bar,f] => /foo/bar/f +/// foo + [bar,f] => foo/bar/f +/// @endcode +/// +/// @param path Set to \a path + [\a begin, \a end). +/// @param begin Start of components to append. +/// @param end One past the end of components to append. +void append(SmallVectorImpl<char> &path, + const_iterator begin, const_iterator end); + +/// @} +/// @name Transforms (or some other better name) +/// @{ + +/// Convert path to the native form. This is used to give paths to users and +/// operating system calls in the platform's normal way. For example, on Windows +/// all '/' are converted to '\'. +/// +/// @param path A path that is transformed to native format. +/// @param result Holds the result of the transformation. +void native(const Twine &path, SmallVectorImpl<char> &result); + +/// Convert path to the native form in place. This is used to give paths to +/// users and operating system calls in the platform's normal way. For example, +/// on Windows all '/' are converted to '\'. +/// +/// @param path A path that is transformed to native format. +void native(SmallVectorImpl<char> &path); + +/// @} +/// @name Lexical Observers +/// @{ + +/// @brief Get root name. +/// +/// @code +/// //net/hello => //net +/// c:/hello => c: (on Windows, on other platforms nothing) +/// /hello => <empty> +/// @endcode +/// +/// @param path Input path. +/// @result The root name of \a path if it has one, otherwise "". +StringRef root_name(StringRef path); + +/// @brief Get root directory. +/// +/// @code +/// /goo/hello => / +/// c:/hello => / +/// d/file.txt => <empty> +/// @endcode +/// +/// @param path Input path. +/// @result The root directory of \a path if it has one, otherwise +/// "". +StringRef root_directory(StringRef path); + +/// @brief Get root path. +/// +/// Equivalent to root_name + root_directory. +/// +/// @param path Input path. +/// @result The root path of \a path if it has one, otherwise "". +StringRef root_path(StringRef path); + +/// @brief Get relative path. +/// +/// @code +/// C:\hello\world => hello\world +/// foo/bar => foo/bar +/// /foo/bar => foo/bar +/// @endcode +/// +/// @param path Input path. +/// @result The path starting after root_path if one exists, otherwise "". +StringRef relative_path(StringRef path); + +/// @brief Get parent path. +/// +/// @code +/// / => <empty> +/// /foo => / +/// foo/../bar => foo/.. +/// @endcode +/// +/// @param path Input path. +/// @result The parent path of \a path if one exists, otherwise "". +StringRef parent_path(StringRef path); + +/// @brief Get filename. +/// +/// @code +/// /foo.txt => foo.txt +/// . => . +/// .. => .. +/// / => / +/// @endcode +/// +/// @param path Input path. +/// @result The filename part of \a path. This is defined as the last component +/// of \a path. +StringRef filename(StringRef path); + +/// @brief Get stem. +/// +/// If filename contains a dot but not solely one or two dots, result is the +/// substring of filename ending at (but not including) the last dot. Otherwise +/// it is filename. +/// +/// @code +/// /foo/bar.txt => bar +/// /foo/bar => bar +/// /foo/.txt => <empty> +/// /foo/. => . +/// /foo/.. => .. +/// @endcode +/// +/// @param path Input path. +/// @result The stem of \a path. +StringRef stem(StringRef path); + +/// @brief Get extension. +/// +/// If filename contains a dot but not solely one or two dots, result is the +/// substring of filename starting at (and including) the last dot, and ending +/// at the end of \a path. Otherwise "". +/// +/// @code +/// /foo/bar.txt => .txt +/// /foo/bar => <empty> +/// /foo/.txt => .txt +/// @endcode +/// +/// @param path Input path. +/// @result The extension of \a path. +StringRef extension(StringRef path); + +/// @brief Check whether the given char is a path separator on the host OS. +/// +/// @param value a character +/// @result true if \a value is a path separator character on the host OS +bool is_separator(char value); + +/// @brief Return the preferred separator for this platform. +/// +/// @result StringRef of the preferred separator, null-terminated. +StringRef get_separator(); + +/// @brief Get the typical temporary directory for the system, e.g., +/// "/var/tmp" or "C:/TEMP" +/// +/// @param erasedOnReboot Whether to favor a path that is erased on reboot +/// rather than one that potentially persists longer. This parameter will be +/// ignored if the user or system has set the typical environment variable +/// (e.g., TEMP on Windows, TMPDIR on *nix) to specify a temporary directory. +/// +/// @param result Holds the resulting path name. +void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result); + +/// @brief Get the user's home directory. +/// +/// @param result Holds the resulting path name. +/// @result True if a home directory is set, false otherwise. +bool home_directory(SmallVectorImpl<char> &result); + +/// @brief Get the user's cache directory. +/// +/// Expect the resulting path to be a directory shared with other +/// applications/services used by the user. Params \p Path1 to \p Path3 can be +/// used to append additional directory names to the resulting path. Recommended +/// pattern is <user_cache_directory>/<vendor>/<application>. +/// +/// @param Result Holds the resulting path. +/// @param Path1 Additional path to be appended to the user's cache directory +/// path. "" can be used to append nothing. +/// @param Path2 Second additional path to be appended. +/// @param Path3 Third additional path to be appended. +/// @result True if a cache directory path is set, false otherwise. +bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1, + const Twine &Path2 = "", const Twine &Path3 = ""); + +/// @brief Has root name? +/// +/// root_name != "" +/// +/// @param path Input path. +/// @result True if the path has a root name, false otherwise. +bool has_root_name(const Twine &path); + +/// @brief Has root directory? +/// +/// root_directory != "" +/// +/// @param path Input path. +/// @result True if the path has a root directory, false otherwise. +bool has_root_directory(const Twine &path); + +/// @brief Has root path? +/// +/// root_path != "" +/// +/// @param path Input path. +/// @result True if the path has a root path, false otherwise. +bool has_root_path(const Twine &path); + +/// @brief Has relative path? +/// +/// relative_path != "" +/// +/// @param path Input path. +/// @result True if the path has a relative path, false otherwise. +bool has_relative_path(const Twine &path); + +/// @brief Has parent path? +/// +/// parent_path != "" +/// +/// @param path Input path. +/// @result True if the path has a parent path, false otherwise. +bool has_parent_path(const Twine &path); + +/// @brief Has filename? +/// +/// filename != "" +/// +/// @param path Input path. +/// @result True if the path has a filename, false otherwise. +bool has_filename(const Twine &path); + +/// @brief Has stem? +/// +/// stem != "" +/// +/// @param path Input path. +/// @result True if the path has a stem, false otherwise. +bool has_stem(const Twine &path); + +/// @brief Has extension? +/// +/// extension != "" +/// +/// @param path Input path. +/// @result True if the path has a extension, false otherwise. +bool has_extension(const Twine &path); + +/// @brief Is path absolute? +/// +/// @param path Input path. +/// @result True if the path is absolute, false if it is not. +bool is_absolute(const Twine &path); + +/// @brief Is path relative? +/// +/// @param path Input path. +/// @result True if the path is relative, false if it is not. +bool is_relative(const Twine &path); + +/// @brief Remove redundant leading "./" pieces and consecutive separators. +/// +/// @param path Input path. +/// @result The cleaned-up \a path. +StringRef remove_leading_dotslash(StringRef path); + +/// @brief In-place remove any './' and optionally '../' components from a path. +/// +/// @param path processed path +/// @param remove_dot_dot specify if '../' should be removed +/// @result True if path was changed +bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot = false); + +} // end namespace path +} // end namespace sys +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/PointerLikeTypeTraits.h b/third_party/llvm-subzero/include/llvm/Support/PointerLikeTypeTraits.h new file mode 100644 index 0000000..96cdaed --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/PointerLikeTypeTraits.h
@@ -0,0 +1,94 @@ +//===- llvm/Support/PointerLikeTypeTraits.h - Pointer Traits ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PointerLikeTypeTraits class. This allows data +// structures to reason about pointers and other things that are pointer sized. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H +#define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H + +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +/// A traits type that is used to handle pointer types and things that are just +/// wrappers for pointers as a uniform entity. +template <typename T> class PointerLikeTypeTraits { + // getAsVoidPointer + // getFromVoidPointer + // getNumLowBitsAvailable +}; + +namespace detail { +/// A tiny meta function to compute the log2 of a compile time constant. +template <size_t N> +struct ConstantLog2 + : std::integral_constant<size_t, ConstantLog2<N / 2>::value + 1> {}; +template <> struct ConstantLog2<1> : std::integral_constant<size_t, 0> {}; +} + +// Provide PointerLikeTypeTraits for non-cvr pointers. +template <typename T> class PointerLikeTypeTraits<T *> { +public: + static inline void *getAsVoidPointer(T *P) { return P; } + static inline T *getFromVoidPointer(void *P) { return static_cast<T *>(P); } + + enum { + NumLowBitsAvailable = detail::ConstantLog2<AlignOf<T>::Alignment>::value + }; +}; + +template <> class PointerLikeTypeTraits<void *> { +public: + static inline void *getAsVoidPointer(void *P) { return P; } + static inline void *getFromVoidPointer(void *P) { return P; } + + /// Note, we assume here that void* is related to raw malloc'ed memory and + /// that malloc returns objects at least 4-byte aligned. However, this may be + /// wrong, or pointers may be from something other than malloc. In this case, + /// you should specify a real typed pointer or avoid this template. + /// + /// All clients should use assertions to do a run-time check to ensure that + /// this is actually true. + enum { NumLowBitsAvailable = 2 }; +}; + +// Provide PointerLikeTypeTraits for const pointers. +template <typename T> class PointerLikeTypeTraits<const T *> { + typedef PointerLikeTypeTraits<T *> NonConst; + +public: + static inline const void *getAsVoidPointer(const T *P) { + return NonConst::getAsVoidPointer(const_cast<T *>(P)); + } + static inline const T *getFromVoidPointer(const void *P) { + return NonConst::getFromVoidPointer(const_cast<void *>(P)); + } + enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable }; +}; + +// Provide PointerLikeTypeTraits for uintptr_t. +template <> class PointerLikeTypeTraits<uintptr_t> { +public: + static inline void *getAsVoidPointer(uintptr_t P) { + return reinterpret_cast<void *>(P); + } + static inline uintptr_t getFromVoidPointer(void *P) { + return reinterpret_cast<uintptr_t>(P); + } + // No bits are available! + enum { NumLowBitsAvailable = 0 }; +}; + +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Process.h b/third_party/llvm-subzero/include/llvm/Support/Process.h new file mode 100644 index 0000000..06fd0af --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Process.h
@@ -0,0 +1,193 @@ +//===- llvm/Support/Process.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// Provides a library for accessing information about this process and other +/// processes on the operating system. Also provides means of spawning +/// subprocess for commands. The design of this library is modeled after the +/// proposed design of the Boost.Process library, and is design specifically to +/// follow the style of standard libraries and potentially become a proposal +/// for a standard library. +/// +/// This file declares the llvm::sys::Process class which contains a collection +/// of legacy static interfaces for extracting various information about the +/// current process. The goal is to migrate users of this API over to the new +/// interfaces. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PROCESS_H +#define LLVM_SUPPORT_PROCESS_H + +#include "llvm/ADT/Optional.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/TimeValue.h" +#include <system_error> + +namespace llvm { +template <typename T> class ArrayRef; +class StringRef; + +namespace sys { + + +/// \brief A collection of legacy interfaces for querying information about the +/// current executing process. +class Process { +public: + static unsigned getPageSize(); + + /// \brief Return process memory usage. + /// This static function will return the total amount of memory allocated + /// by the process. This only counts the memory allocated via the malloc, + /// calloc and realloc functions and includes any "free" holes in the + /// allocated space. + static size_t GetMallocUsage(); + + /// This static function will set \p user_time to the amount of CPU time + /// spent in user (non-kernel) mode and \p sys_time to the amount of CPU + /// time spent in system (kernel) mode. If the operating system does not + /// support collection of these metrics, a zero TimeValue will be for both + /// values. + /// \param elapsed Returns the TimeValue::now() giving current time + /// \param user_time Returns the current amount of user time for the process + /// \param sys_time Returns the current amount of system time for the process + static void GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, + TimeValue &sys_time); + + /// This function makes the necessary calls to the operating system to + /// prevent core files or any other kind of large memory dumps that can + /// occur when a program fails. + /// @brief Prevent core file generation. + static void PreventCoreFiles(); + + /// \brief true if PreventCoreFiles has been called, false otherwise. + static bool AreCoreFilesPrevented(); + + // This function returns the environment variable \arg name's value as a UTF-8 + // string. \arg Name is assumed to be in UTF-8 encoding too. + static Optional<std::string> GetEnv(StringRef name); + + /// This function searches for an existing file in the list of directories + /// in a PATH like environment variable, and returns the first file found, + /// according to the order of the entries in the PATH like environment + /// variable. + static Optional<std::string> FindInEnvPath(const std::string& EnvName, + const std::string& FileName); + + /// This function returns a SmallVector containing the arguments passed from + /// the operating system to the program. This function expects to be handed + /// the vector passed in from main. + static std::error_code + GetArgumentVector(SmallVectorImpl<const char *> &Args, + ArrayRef<const char *> ArgsFromMain, + SpecificBumpPtrAllocator<char> &ArgAllocator); + + // This functions ensures that the standard file descriptors (input, output, + // and error) are properly mapped to a file descriptor before we use any of + // them. This should only be called by standalone programs, library + // components should not call this. + static std::error_code FixupStandardFileDescriptors(); + + // This function safely closes a file descriptor. It is not safe to retry + // close(2) when it returns with errno equivalent to EINTR; this is because + // *nixen cannot agree if the file descriptor is, in fact, closed when this + // occurs. + // + // N.B. Some operating systems, due to thread cancellation, cannot properly + // guarantee that it will or will not be closed one way or the other! + static std::error_code SafelyCloseFileDescriptor(int FD); + + /// This function determines if the standard input is connected directly + /// to a user's input (keyboard probably), rather than coming from a file + /// or pipe. + static bool StandardInIsUserInput(); + + /// This function determines if the standard output is connected to a + /// "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool StandardOutIsDisplayed(); + + /// This function determines if the standard error is connected to a + /// "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool StandardErrIsDisplayed(); + + /// This function determines if the given file descriptor is connected to + /// a "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool FileDescriptorIsDisplayed(int fd); + + /// This function determines if the given file descriptor is displayd and + /// supports colors. + static bool FileDescriptorHasColors(int fd); + + /// This function determines the number of columns in the window + /// if standard output is connected to a "tty" or "console" + /// window. If standard output is not connected to a tty or + /// console, or if the number of columns cannot be determined, + /// this routine returns zero. + static unsigned StandardOutColumns(); + + /// This function determines the number of columns in the window + /// if standard error is connected to a "tty" or "console" + /// window. If standard error is not connected to a tty or + /// console, or if the number of columns cannot be determined, + /// this routine returns zero. + static unsigned StandardErrColumns(); + + /// This function determines whether the terminal connected to standard + /// output supports colors. If standard output is not connected to a + /// terminal, this function returns false. + static bool StandardOutHasColors(); + + /// This function determines whether the terminal connected to standard + /// error supports colors. If standard error is not connected to a + /// terminal, this function returns false. + static bool StandardErrHasColors(); + + /// Enables or disables whether ANSI escape sequences are used to output + /// colors. This only has an effect on Windows. + /// Note: Setting this option is not thread-safe and should only be done + /// during initialization. + static void UseANSIEscapeCodes(bool enable); + + /// Whether changing colors requires the output to be flushed. + /// This is needed on systems that don't support escape sequences for + /// changing colors. + static bool ColorNeedsFlush(); + + /// This function returns the colorcode escape sequences. + /// If ColorNeedsFlush() is true then this function will change the colors + /// and return an empty escape sequence. In that case it is the + /// responsibility of the client to flush the output stream prior to + /// calling this function. + static const char *OutputColor(char c, bool bold, bool bg); + + /// Same as OutputColor, but only enables the bold attribute. + static const char *OutputBold(bool bg); + + /// This function returns the escape sequence to reverse forground and + /// background colors. + static const char *OutputReverse(); + + /// Resets the terminals colors, or returns an escape sequence to do so. + static const char *ResetColor(); + + /// Get the result of a process wide random number generator. The + /// generator will be automatically seeded in non-deterministic fashion. + static unsigned GetRandomNumber(); +}; + +} +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Program.h b/third_party/llvm-subzero/include/llvm/Support/Program.h new file mode 100644 index 0000000..055f016 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Program.h
@@ -0,0 +1,194 @@ +//===- llvm/Support/Program.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::Program class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PROGRAM_H +#define LLVM_SUPPORT_PROGRAM_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/ErrorOr.h" +#include <system_error> + +namespace llvm { +class StringRef; + +namespace sys { + + /// This is the OS-specific separator for PATH like environment variables: + // a colon on Unix or a semicolon on Windows. +#if defined(LLVM_ON_UNIX) + const char EnvPathSeparator = ':'; +#elif defined (LLVM_ON_WIN32) + const char EnvPathSeparator = ';'; +#endif + +/// @brief This struct encapsulates information about a process. +struct ProcessInfo { +#if defined(LLVM_ON_UNIX) + typedef pid_t ProcessId; +#elif defined(LLVM_ON_WIN32) + typedef unsigned long ProcessId; // Must match the type of DWORD on Windows. + typedef void * HANDLE; // Must match the type of HANDLE on Windows. + /// The handle to the process (available on Windows only). + HANDLE ProcessHandle; +#else +#error "ProcessInfo is not defined for this platform!" +#endif + + enum : ProcessId { InvalidPid = 0 }; + + /// The process identifier. + ProcessId Pid; + + /// The return code, set after execution. + int ReturnCode; + + ProcessInfo(); +}; + + /// \brief Find the first executable file \p Name in \p Paths. + /// + /// This does not perform hashing as a shell would but instead stats each PATH + /// entry individually so should generally be avoided. Core LLVM library + /// functions and options should instead require fully specified paths. + /// + /// \param Name name of the executable to find. If it contains any system + /// slashes, it will be returned as is. + /// \param Paths optional list of paths to search for \p Name. If empty it + /// will use the system PATH environment instead. + /// + /// \returns The fully qualified path to the first \p Name in \p Paths if it + /// exists. \p Name if \p Name has slashes in it. Otherwise an error. + ErrorOr<std::string> + findProgramByName(StringRef Name, ArrayRef<StringRef> Paths = None); + + // These functions change the specified standard stream (stdin or stdout) to + // binary mode. They return errc::success if the specified stream + // was changed. Otherwise a platform dependent error is returned. + std::error_code ChangeStdinToBinary(); + std::error_code ChangeStdoutToBinary(); + + /// This function executes the program using the arguments provided. The + /// invoked program will inherit the stdin, stdout, and stderr file + /// descriptors, the environment and other configuration settings of the + /// invoking program. + /// This function waits for the program to finish, so should be avoided in + /// library functions that aren't expected to block. Consider using + /// ExecuteNoWait() instead. + /// @returns an integer result code indicating the status of the program. + /// A zero or positive value indicates the result code of the program. + /// -1 indicates failure to execute + /// -2 indicates a crash during execution or timeout + int ExecuteAndWait( + StringRef Program, ///< Path of the program to be executed. It is + ///< presumed this is the result of the findProgramByName method. + const char **args, ///< A vector of strings that are passed to the + ///< program. The first element should be the name of the program. + ///< The list *must* be terminated by a null char* entry. + const char **env = nullptr, ///< An optional vector of strings to use for + ///< the program's environment. If not provided, the current program's + ///< environment will be used. + const StringRef **redirects = nullptr, ///< An optional array of pointers + ///< to paths. If the array is null, no redirection is done. The array + ///< should have a size of at least three. The inferior process's + ///< stdin(0), stdout(1), and stderr(2) will be redirected to the + ///< corresponding paths. + ///< When an empty path is passed in, the corresponding file + ///< descriptor will be disconnected (ie, /dev/null'd) in a portable + ///< way. + unsigned secondsToWait = 0, ///< If non-zero, this specifies the amount + ///< of time to wait for the child process to exit. If the time + ///< expires, the child is killed and this call returns. If zero, + ///< this function will wait until the child finishes or forever if + ///< it doesn't. + unsigned memoryLimit = 0, ///< If non-zero, this specifies max. amount + ///< of memory can be allocated by process. If memory usage will be + ///< higher limit, the child is killed and this call returns. If zero + ///< - no memory limit. + std::string *ErrMsg = nullptr, ///< If non-zero, provides a pointer to a + ///< string instance in which error messages will be returned. If the + ///< string is non-empty upon return an error occurred while invoking the + ///< program. + bool *ExecutionFailed = nullptr); + + /// Similar to ExecuteAndWait, but returns immediately. + /// @returns The \see ProcessInfo of the newly launced process. + /// \note On Microsoft Windows systems, users will need to either call \see + /// Wait until the process finished execution or win32 CloseHandle() API on + /// ProcessInfo.ProcessHandle to avoid memory leaks. + ProcessInfo + ExecuteNoWait(StringRef Program, const char **args, const char **env = nullptr, + const StringRef **redirects = nullptr, unsigned memoryLimit = 0, + std::string *ErrMsg = nullptr, bool *ExecutionFailed = nullptr); + + /// Return true if the given arguments fit within system-specific + /// argument length limits. + bool commandLineFitsWithinSystemLimits(StringRef Program, ArrayRef<const char*> Args); + + /// File encoding options when writing contents that a non-UTF8 tool will + /// read (on Windows systems). For UNIX, we always use UTF-8. + enum WindowsEncodingMethod { + /// UTF-8 is the LLVM native encoding, being the same as "do not perform + /// encoding conversion". + WEM_UTF8, + WEM_CurrentCodePage, + WEM_UTF16 + }; + + /// Saves the UTF8-encoded \p contents string into the file \p FileName + /// using a specific encoding. + /// + /// This write file function adds the possibility to choose which encoding + /// to use when writing a text file. On Windows, this is important when + /// writing files with internationalization support with an encoding that is + /// different from the one used in LLVM (UTF-8). We use this when writing + /// response files, since GCC tools on MinGW only understand legacy code + /// pages, and VisualStudio tools only understand UTF-16. + /// For UNIX, using different encodings is silently ignored, since all tools + /// work well with UTF-8. + /// This function assumes that you only use UTF-8 *text* data and will convert + /// it to your desired encoding before writing to the file. + /// + /// FIXME: We use EM_CurrentCodePage to write response files for GNU tools in + /// a MinGW/MinGW-w64 environment, which has serious flaws but currently is + /// our best shot to make gcc/ld understand international characters. This + /// should be changed as soon as binutils fix this to support UTF16 on mingw. + /// + /// \returns non-zero error_code if failed + std::error_code + writeFileWithEncoding(StringRef FileName, StringRef Contents, + WindowsEncodingMethod Encoding = WEM_UTF8); + + /// This function waits for the process specified by \p PI to finish. + /// \returns A \see ProcessInfo struct with Pid set to: + /// \li The process id of the child process if the child process has changed + /// state. + /// \li 0 if the child process has not changed state. + /// \note Users of this function should always check the ReturnCode member of + /// the \see ProcessInfo returned from this function. + ProcessInfo Wait( + const ProcessInfo &PI, ///< The child process that should be waited on. + unsigned SecondsToWait, ///< If non-zero, this specifies the amount of + ///< time to wait for the child process to exit. If the time expires, the + ///< child is killed and this function returns. If zero, this function + ///< will perform a non-blocking wait on the child process. + bool WaitUntilTerminates, ///< If true, ignores \p SecondsToWait and waits + ///< until child has terminated. + std::string *ErrMsg = nullptr ///< If non-zero, provides a pointer to a + ///< string instance in which error messages will be returned. If the + ///< string is non-empty upon return an error occurred while invoking the + ///< program. + ); + } +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Signals.h b/third_party/llvm-subzero/include/llvm/Support/Signals.h new file mode 100644 index 0000000..cbd6f68 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Signals.h
@@ -0,0 +1,77 @@ +//===- llvm/Support/Signals.h - Signal Handling support ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines some helpful functions for dealing with the possibility of +// unix signals occurring while your program is running. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SIGNALS_H +#define LLVM_SUPPORT_SIGNALS_H + +#include <string> + +namespace llvm { +class StringRef; +class raw_ostream; + +namespace sys { + + /// This function runs all the registered interrupt handlers, including the + /// removal of files registered by RemoveFileOnSignal. + void RunInterruptHandlers(); + + /// This function registers signal handlers to ensure that if a signal gets + /// delivered that the named file is removed. + /// @brief Remove a file if a fatal signal occurs. + bool RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg = nullptr); + + /// This function removes a file from the list of files to be removed on + /// signal delivery. + void DontRemoveFileOnSignal(StringRef Filename); + + /// When an error signal (such as SIBABRT or SIGSEGV) is delivered to the + /// process, print a stack trace and then exit. + /// \brief Print a stack trace if a fatal signal occurs. + /// \param Argv0 the current binary name, used to find the symbolizer + /// relative to the current binary before searching $PATH; can be + /// StringRef(), in which case we will only search $PATH. + /// \param DisableCrashReporting if \c true, disable the normal crash + /// reporting mechanisms on the underlying operating system. + void PrintStackTraceOnErrorSignal(StringRef Argv0, + bool DisableCrashReporting = false); + + /// Disable all system dialog boxes that appear when the process crashes. + void DisableSystemDialogsOnCrash(); + + /// \brief Print the stack trace using the given \c raw_ostream object. + void PrintStackTrace(raw_ostream &OS); + + // Run all registered signal handlers. + void RunSignalHandlers(); + + /// AddSignalHandler - Add a function to be called when an abort/kill signal + /// is delivered to the process. The handler can have a cookie passed to it + /// to identify what instance of the handler it is. + void AddSignalHandler(void (*FnPtr)(void *), void *Cookie); + + /// This function registers a function to be called when the user "interrupts" + /// the program (typically by pressing ctrl-c). When the user interrupts the + /// program, the specified interrupt function is called instead of the program + /// being killed, and the interrupt function automatically disabled. Note + /// that interrupt functions are not allowed to call any non-reentrant + /// functions. An null interrupt function pointer disables the current + /// installed function. Note also that the handler may be executed on a + /// different thread on some platforms. + /// @brief Register a function to be called when ctrl-c is pressed. + void SetInterruptFunction(void (*IF)()); +} // End sys namespace +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/StreamingMemoryObject.h b/third_party/llvm-subzero/include/llvm/Support/StreamingMemoryObject.h new file mode 100644 index 0000000..1ab8537 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/StreamingMemoryObject.h
@@ -0,0 +1,87 @@ +//===- StreamingMemoryObject.h - Streamable data interface -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_STREAMINGMEMORYOBJECT_H +#define LLVM_SUPPORT_STREAMINGMEMORYOBJECT_H + +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataStream.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryObject.h" +#include <memory> +#include <vector> + +namespace llvm { + +/// Interface to data which is actually streamed from a DataStreamer. In +/// addition to inherited members, it has the dropLeadingBytes and +/// setKnownObjectSize methods which are not applicable to non-streamed objects. +class StreamingMemoryObject : public MemoryObject { +public: + StreamingMemoryObject(std::unique_ptr<DataStreamer> Streamer); + uint64_t getExtent() const override; + uint64_t readBytes(uint8_t *Buf, uint64_t Size, + uint64_t Address) const override; + const uint8_t *getPointer(uint64_t Address, uint64_t Size) const override; + bool isValidAddress(uint64_t address) const override; + + /// Drop s bytes from the front of the stream, pushing the positions of the + /// remaining bytes down by s. This is used to skip past the bitcode header, + /// since we don't know a priori if it's present, and we can't put bytes + /// back into the stream once we've read them. + bool dropLeadingBytes(size_t s); + + /// If the data object size is known in advance, many of the operations can + /// be made more efficient, so this method should be called before reading + /// starts (although it can be called anytime). + void setKnownObjectSize(size_t size); + + /// The number of bytes read at a time from the data streamer. + static const uint32_t kChunkSize = 4096 * 4; + +private: + mutable std::vector<unsigned char> Bytes; + std::unique_ptr<DataStreamer> Streamer; + mutable size_t BytesRead; // Bytes read from stream + size_t BytesSkipped;// Bytes skipped at start of stream (e.g. wrapper/header) + mutable size_t ObjectSize; // 0 if unknown, set if wrapper seen or EOF reached + mutable bool EOFReached; + + // Fetch enough bytes such that Pos can be read (i.e. BytesRead > + // Pos). Returns true if Pos can be read. Unlike most of the + // functions in BitcodeReader, returns true on success. Most of the + // requests will be small, but we fetch at kChunkSize bytes at a + // time to avoid making too many potentially expensive GetBytes + // calls. + bool fetchToPos(size_t Pos) const { + while (Pos >= BytesRead) { + if (EOFReached) + return false; + Bytes.resize(BytesRead + BytesSkipped + kChunkSize); + size_t bytes = Streamer->GetBytes(&Bytes[BytesRead + BytesSkipped], + kChunkSize); + BytesRead += bytes; + if (bytes == 0) { // reached EOF/ran out of bytes + if (ObjectSize == 0) + ObjectSize = BytesRead; + EOFReached = true; + } + } + return !ObjectSize || Pos < ObjectSize; + } + + StreamingMemoryObject(const StreamingMemoryObject&) = delete; + void operator=(const StreamingMemoryObject&) = delete; +}; + +MemoryObject *getNonStreamedMemoryObject( + const unsigned char *Start, const unsigned char *End); + +} +#endif // STREAMINGMEMORYOBJECT_H_
diff --git a/third_party/llvm-subzero/include/llvm/Support/StringSaver.h b/third_party/llvm-subzero/include/llvm/Support/StringSaver.h new file mode 100644 index 0000000..38fb7bb --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/StringSaver.h
@@ -0,0 +1,32 @@ +//===- llvm/Support/StringSaver.h -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_STRINGSAVER_H +#define LLVM_SUPPORT_STRINGSAVER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Allocator.h" + +namespace llvm { + +/// \brief Saves strings in the inheritor's stable storage and returns a stable +/// raw character pointer. +class StringSaver final { + BumpPtrAllocator &Alloc; + +public: + StringSaver(BumpPtrAllocator &Alloc) : Alloc(Alloc) {} + const char *save(const char *S) { return save(StringRef(S)); } + const char *save(StringRef S); + const char *save(const Twine &S) { return save(StringRef(S.str())); } + const char *save(std::string &S) { return save(StringRef(S)); } +}; +} +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/SwapByteOrder.h b/third_party/llvm-subzero/include/llvm/Support/SwapByteOrder.h new file mode 100644 index 0000000..91693ac --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/SwapByteOrder.h
@@ -0,0 +1,124 @@ +//===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares generic and optimized functions to swap the byte order of +// an integral type. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SWAPBYTEORDER_H +#define LLVM_SUPPORT_SWAPBYTEORDER_H + +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" +#include <cstddef> + +namespace llvm { +namespace sys { + +/// SwapByteOrder_16 - This function returns a byte-swapped representation of +/// the 16-bit argument. +inline uint16_t SwapByteOrder_16(uint16_t value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return _byteswap_ushort(value); +#else + uint16_t Hi = value << 8; + uint16_t Lo = value >> 8; + return Hi | Lo; +#endif +} + +/// SwapByteOrder_32 - This function returns a byte-swapped representation of +/// the 32-bit argument. +inline uint32_t SwapByteOrder_32(uint32_t value) { +#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC)) + return __builtin_bswap32(value); +#elif defined(_MSC_VER) && !defined(_DEBUG) + return _byteswap_ulong(value); +#else + uint32_t Byte0 = value & 0x000000FF; + uint32_t Byte1 = value & 0x0000FF00; + uint32_t Byte2 = value & 0x00FF0000; + uint32_t Byte3 = value & 0xFF000000; + return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); +#endif +} + +/// SwapByteOrder_64 - This function returns a byte-swapped representation of +/// the 64-bit argument. +inline uint64_t SwapByteOrder_64(uint64_t value) { +#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC)) + return __builtin_bswap64(value); +#elif defined(_MSC_VER) && !defined(_DEBUG) + return _byteswap_uint64(value); +#else + uint64_t Hi = SwapByteOrder_32(uint32_t(value)); + uint32_t Lo = SwapByteOrder_32(uint32_t(value >> 32)); + return (Hi << 32) | Lo; +#endif +} + +inline unsigned char getSwappedBytes(unsigned char C) { return C; } +inline signed char getSwappedBytes(signed char C) { return C; } +inline char getSwappedBytes(char C) { return C; } + +inline unsigned short getSwappedBytes(unsigned short C) { return SwapByteOrder_16(C); } +inline signed short getSwappedBytes( signed short C) { return SwapByteOrder_16(C); } + +inline unsigned int getSwappedBytes(unsigned int C) { return SwapByteOrder_32(C); } +inline signed int getSwappedBytes( signed int C) { return SwapByteOrder_32(C); } + +#if __LONG_MAX__ == __INT_MAX__ +inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_32(C); } +inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_32(C); } +#elif __LONG_MAX__ == __LONG_LONG_MAX__ +inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_64(C); } +inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_64(C); } +#else +#error "Unknown long size!" +#endif + +inline unsigned long long getSwappedBytes(unsigned long long C) { + return SwapByteOrder_64(C); +} +inline signed long long getSwappedBytes(signed long long C) { + return SwapByteOrder_64(C); +} + +inline float getSwappedBytes(float C) { + union { + uint32_t i; + float f; + } in, out; + in.f = C; + out.i = SwapByteOrder_32(in.i); + return out.f; +} + +inline double getSwappedBytes(double C) { + union { + uint64_t i; + double d; + } in, out; + in.d = C; + out.i = SwapByteOrder_64(in.i); + return out.d; +} + +template<typename T> +inline void swapByteOrder(T &Value) { + Value = getSwappedBytes(Value); +} + +} // end namespace sys +} // end namespace llvm + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/TargetParser.h b/third_party/llvm-subzero/include/llvm/Support/TargetParser.h new file mode 100644 index 0000000..92b20ea --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/TargetParser.h
@@ -0,0 +1,208 @@ +//===-- TargetParser - Parser for target features ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a target parser to recognise hardware features such as +// FPU/CPU/ARCH names as well as specific support such as HDIV, etc. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TARGETPARSER_H +#define LLVM_SUPPORT_TARGETPARSER_H + +// FIXME: vector is used because that's what clang uses for subtarget feature +// lists, but SmallVector would probably be better +#include <vector> + +namespace llvm { +class StringRef; + +// Target specific information into their own namespaces. These should be +// generated from TableGen because the information is already there, and there +// is where new information about targets will be added. +// FIXME: To TableGen this we need to make some table generated files available +// even if the back-end is not compiled with LLVM, plus we need to create a new +// back-end to TableGen to create these clean tables. +namespace ARM { + +// FPU names. +enum FPUKind { +#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) KIND, +#include "ARMTargetParser.def" + FK_LAST +}; + +// FPU Version +enum FPUVersion { + FV_NONE = 0, + FV_VFPV2, + FV_VFPV3, + FV_VFPV3_FP16, + FV_VFPV4, + FV_VFPV5 +}; + +// An FPU name implies one of three levels of Neon support: +enum NeonSupportLevel { + NS_None = 0, ///< No Neon + NS_Neon, ///< Neon + NS_Crypto ///< Neon with Crypto +}; + +// An FPU name restricts the FPU in one of three ways: +enum FPURestriction { + FR_None = 0, ///< No restriction + FR_D16, ///< Only 16 D registers + FR_SP_D16 ///< Only single-precision instructions, with 16 D registers +}; + +// Arch names. +enum ArchKind { +#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) ID, +#include "ARMTargetParser.def" + AK_LAST +}; + +// Arch extension modifiers for CPUs. +enum ArchExtKind : unsigned { + AEK_INVALID = 0x0, + AEK_NONE = 0x1, + AEK_CRC = 0x2, + AEK_CRYPTO = 0x4, + AEK_FP = 0x8, + AEK_HWDIV = 0x10, + AEK_HWDIVARM = 0x20, + AEK_MP = 0x40, + AEK_SIMD = 0x80, + AEK_SEC = 0x100, + AEK_VIRT = 0x200, + AEK_DSP = 0x400, + AEK_FP16 = 0x800, + AEK_RAS = 0x1000, + // Unsupported extensions. + AEK_OS = 0x8000000, + AEK_IWMMXT = 0x10000000, + AEK_IWMMXT2 = 0x20000000, + AEK_MAVERICK = 0x40000000, + AEK_XSCALE = 0x80000000, +}; + +// ISA kinds. +enum ISAKind { IK_INVALID = 0, IK_ARM, IK_THUMB, IK_AARCH64 }; + +// Endianness +// FIXME: BE8 vs. BE32? +enum EndianKind { EK_INVALID = 0, EK_LITTLE, EK_BIG }; + +// v6/v7/v8 Profile +enum ProfileKind { PK_INVALID = 0, PK_A, PK_R, PK_M }; + +StringRef getCanonicalArchName(StringRef Arch); + +// Information by ID +StringRef getFPUName(unsigned FPUKind); +unsigned getFPUVersion(unsigned FPUKind); +unsigned getFPUNeonSupportLevel(unsigned FPUKind); +unsigned getFPURestriction(unsigned FPUKind); + +// FIXME: These should be moved to TargetTuple once it exists +bool getFPUFeatures(unsigned FPUKind, std::vector<const char *> &Features); +bool getHWDivFeatures(unsigned HWDivKind, std::vector<const char *> &Features); +bool getExtensionFeatures(unsigned Extensions, + std::vector<const char*> &Features); + +StringRef getArchName(unsigned ArchKind); +unsigned getArchAttr(unsigned ArchKind); +StringRef getCPUAttr(unsigned ArchKind); +StringRef getSubArch(unsigned ArchKind); +StringRef getArchExtName(unsigned ArchExtKind); +const char *getArchExtFeature(StringRef ArchExt); +StringRef getHWDivName(unsigned HWDivKind); + +// Information by Name +unsigned getDefaultFPU(StringRef CPU, unsigned ArchKind); +unsigned getDefaultExtensions(StringRef CPU, unsigned ArchKind); +StringRef getDefaultCPU(StringRef Arch); + +// Parser +unsigned parseHWDiv(StringRef HWDiv); +unsigned parseFPU(StringRef FPU); +unsigned parseArch(StringRef Arch); +unsigned parseArchExt(StringRef ArchExt); +unsigned parseCPUArch(StringRef CPU); +unsigned parseArchISA(StringRef Arch); +unsigned parseArchEndian(StringRef Arch); +unsigned parseArchProfile(StringRef Arch); +unsigned parseArchVersion(StringRef Arch); + +} // namespace ARM + +// FIXME:This should be made into class design,to avoid dupplication. +namespace AArch64 { + +// Arch names. +enum class ArchKind { +#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) ID, +#include "AArch64TargetParser.def" + AK_LAST +}; + +// Arch extension modifiers for CPUs. +enum ArchExtKind : unsigned { + AEK_INVALID = 0x0, + AEK_NONE = 0x1, + AEK_CRC = 0x2, + AEK_CRYPTO = 0x4, + AEK_FP = 0x8, + AEK_SIMD = 0x10, + AEK_FP16 = 0x20, + AEK_PROFILE = 0x40, + AEK_RAS = 0x80 +}; + +StringRef getCanonicalArchName(StringRef Arch); + +// Information by ID +StringRef getFPUName(unsigned FPUKind); +unsigned getFPUVersion(unsigned FPUKind); +unsigned getFPUNeonSupportLevel(unsigned FPUKind); +unsigned getFPURestriction(unsigned FPUKind); + +// FIXME: These should be moved to TargetTuple once it exists +bool getFPUFeatures(unsigned FPUKind, std::vector<const char *> &Features); +bool getExtensionFeatures(unsigned Extensions, + std::vector<const char*> &Features); +bool getArchFeatures(unsigned ArchKind, std::vector<const char *> &Features); + +StringRef getArchName(unsigned ArchKind); +unsigned getArchAttr(unsigned ArchKind); +StringRef getCPUAttr(unsigned ArchKind); +StringRef getSubArch(unsigned ArchKind); +StringRef getArchExtName(unsigned ArchExtKind); +const char *getArchExtFeature(StringRef ArchExt); +unsigned checkArchVersion(StringRef Arch); + +// Information by Name +unsigned getDefaultFPU(StringRef CPU, unsigned ArchKind); +unsigned getDefaultExtensions(StringRef CPU, unsigned ArchKind); +StringRef getDefaultCPU(StringRef Arch); + +// Parser +unsigned parseFPU(StringRef FPU); +unsigned parseArch(StringRef Arch); +unsigned parseArchExt(StringRef ArchExt); +unsigned parseCPUArch(StringRef CPU); +unsigned parseArchISA(StringRef Arch); +unsigned parseArchEndian(StringRef Arch); +unsigned parseArchProfile(StringRef Arch); +unsigned parseArchVersion(StringRef Arch); + +} // namespace AArch64 +} // namespace llvm + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Threading.h b/third_party/llvm-subzero/include/llvm/Support/Threading.h new file mode 100644 index 0000000..09b96df --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Threading.h
@@ -0,0 +1,120 @@ +//===-- llvm/Support/Threading.h - Control multithreading mode --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares helper functions for running LLVM in a multi-threaded +// environment. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_THREADING_H +#define LLVM_SUPPORT_THREADING_H + +#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX +#include "llvm/Support/Compiler.h" +#include <ciso646> // So we can check the C++ standard lib macros. +#include <functional> + +// We use std::call_once on all Unix platforms except for NetBSD with +// libstdc++. That platform has a bug they are working to fix, and they'll +// remove the NetBSD checks once fixed. +#if defined(LLVM_ON_UNIX) && \ + !(defined(__NetBSD__) && !defined(_LIBCPP_VERSION)) && !defined(__ppc__) +#define LLVM_THREADING_USE_STD_CALL_ONCE 1 +#else +#define LLVM_THREADING_USE_STD_CALL_ONCE 0 +#endif + +#if LLVM_THREADING_USE_STD_CALL_ONCE +#include <mutex> +#else +#include "llvm/Support/Atomic.h" +#endif + +namespace llvm { + /// Returns true if LLVM is compiled with support for multi-threading, and + /// false otherwise. + bool llvm_is_multithreaded(); + + /// llvm_execute_on_thread - Execute the given \p UserFn on a separate + /// thread, passing it the provided \p UserData and waits for thread + /// completion. + /// + /// This function does not guarantee that the code will actually be executed + /// on a separate thread or honoring the requested stack size, but tries to do + /// so where system support is available. + /// + /// \param UserFn - The callback to execute. + /// \param UserData - An argument to pass to the callback function. + /// \param RequestedStackSize - If non-zero, a requested size (in bytes) for + /// the thread stack. + void llvm_execute_on_thread(void (*UserFn)(void*), void *UserData, + unsigned RequestedStackSize = 0); + +#if LLVM_THREADING_USE_STD_CALL_ONCE + + typedef std::once_flag once_flag; + + /// This macro is the only way you should define your once flag for LLVM's + /// call_once. +#define LLVM_DEFINE_ONCE_FLAG(flag) static once_flag flag + +#else + + enum InitStatus { Uninitialized = 0, Wait = 1, Done = 2 }; + typedef volatile sys::cas_flag once_flag; + + /// This macro is the only way you should define your once flag for LLVM's + /// call_once. +#define LLVM_DEFINE_ONCE_FLAG(flag) static once_flag flag = Uninitialized + +#endif + + /// \brief Execute the function specified as a parameter once. + /// + /// Typical usage: + /// \code + /// void foo() {...}; + /// ... + /// LLVM_DEFINE_ONCE_FLAG(flag); + /// call_once(flag, foo); + /// \endcode + /// + /// \param flag Flag used for tracking whether or not this has run. + /// \param F Function to call once. + template <typename Function, typename... Args> + void call_once(once_flag &flag, Function &&F, Args &&... ArgList) { +#if LLVM_THREADING_USE_STD_CALL_ONCE + std::call_once(flag, std::forward<Function>(F), + std::forward<Args>(ArgList)...); +#else + // For other platforms we use a generic (if brittle) version based on our + // atomics. + sys::cas_flag old_val = sys::CompareAndSwap(&flag, Wait, Uninitialized); + if (old_val == Uninitialized) { + std::forward<Function>(F)(std::forward<Args>(ArgList)...); + sys::MemoryFence(); + TsanIgnoreWritesBegin(); + TsanHappensBefore(&flag); + flag = Done; + TsanIgnoreWritesEnd(); + } else { + // Wait until any thread doing the call has finished. + sys::cas_flag tmp = flag; + sys::MemoryFence(); + while (tmp != Done) { + tmp = flag; + sys::MemoryFence(); + } + } + TsanHappensAfter(&flag); +#endif + } +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/TimeValue.h b/third_party/llvm-subzero/include/llvm/Support/TimeValue.h new file mode 100644 index 0000000..6bca58b --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/TimeValue.h
@@ -0,0 +1,386 @@ +//===-- TimeValue.h - Declare OS TimeValue Concept --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file declares the operating system TimeValue concept. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TIMEVALUE_H +#define LLVM_SUPPORT_TIMEVALUE_H + +#include "llvm/Support/DataTypes.h" +#include <string> + +namespace llvm { +namespace sys { + /// This class is used where a precise fixed point in time is required. The + /// range of TimeValue spans many hundreds of billions of years both past and + /// present. The precision of TimeValue is to the nanosecond. However, the + /// actual precision of its values will be determined by the resolution of + /// the system clock. The TimeValue class is used in conjunction with several + /// other lib/System interfaces to specify the time at which a call should + /// timeout, etc. + /// @since 1.4 + /// @brief Provides an abstraction for a fixed point in time. + class TimeValue { + + /// @name Constants + /// @{ + public: + + /// A constant TimeValue representing the smallest time + /// value permissible by the class. MinTime is some point + /// in the distant past, about 300 billion years BCE. + /// @brief The smallest possible time value. + static TimeValue MinTime() { + return TimeValue ( INT64_MIN,0 ); + } + + /// A constant TimeValue representing the largest time + /// value permissible by the class. MaxTime is some point + /// in the distant future, about 300 billion years AD. + /// @brief The largest possible time value. + static TimeValue MaxTime() { + return TimeValue ( INT64_MAX,0 ); + } + + /// A constant TimeValue representing the base time, + /// or zero time of 00:00:00 (midnight) January 1st, 2000. + /// @brief 00:00:00 Jan 1, 2000 UTC. + static TimeValue ZeroTime() { + return TimeValue ( 0,0 ); + } + + /// A constant TimeValue for the Posix base time which is + /// 00:00:00 (midnight) January 1st, 1970. + /// @brief 00:00:00 Jan 1, 1970 UTC. + static TimeValue PosixZeroTime() { + return TimeValue ( PosixZeroTimeSeconds,0 ); + } + + /// A constant TimeValue for the Win32 base time which is + /// 00:00:00 (midnight) January 1st, 1601. + /// @brief 00:00:00 Jan 1, 1601 UTC. + static TimeValue Win32ZeroTime() { + return TimeValue ( Win32ZeroTimeSeconds,0 ); + } + + /// @} + /// @name Types + /// @{ + public: + typedef int64_t SecondsType; ///< Type used for representing seconds. + typedef int32_t NanoSecondsType;///< Type used for representing nanoseconds. + + enum TimeConversions { + NANOSECONDS_PER_SECOND = 1000000000, ///< One Billion + MICROSECONDS_PER_SECOND = 1000000, ///< One Million + MILLISECONDS_PER_SECOND = 1000, ///< One Thousand + NANOSECONDS_PER_MICROSECOND = 1000, ///< One Thousand + NANOSECONDS_PER_MILLISECOND = 1000000,///< One Million + NANOSECONDS_PER_WIN32_TICK = 100 ///< Win32 tick is 10^7 Hz (10ns) + }; + + /// @} + /// @name Constructors + /// @{ + public: + /// \brief Default construct a time value, initializing to ZeroTime. + TimeValue() : seconds_(0), nanos_(0) {} + + /// Caller provides the exact value in seconds and nanoseconds. The + /// \p nanos argument defaults to zero for convenience. + /// @brief Explicit constructor + explicit TimeValue (SecondsType seconds, NanoSecondsType nanos = 0) + : seconds_( seconds ), nanos_( nanos ) { this->normalize(); } + + /// Caller provides the exact value as a double in seconds with the + /// fractional part representing nanoseconds. + /// @brief Double Constructor. + explicit TimeValue( double new_time ) + : seconds_( 0 ) , nanos_ ( 0 ) { + SecondsType integer_part = static_cast<SecondsType>( new_time ); + seconds_ = integer_part; + nanos_ = static_cast<NanoSecondsType>( (new_time - + static_cast<double>(integer_part)) * NANOSECONDS_PER_SECOND ); + this->normalize(); + } + + /// This is a static constructor that returns a TimeValue that represents + /// the current time. + /// @brief Creates a TimeValue with the current time (UTC). + static TimeValue now(); + + /// @} + /// @name Operators + /// @{ + public: + /// Add \p that to \p this. + /// @returns this + /// @brief Incrementing assignment operator. + TimeValue& operator += (const TimeValue& that ) { + this->seconds_ += that.seconds_ ; + this->nanos_ += that.nanos_ ; + this->normalize(); + return *this; + } + + /// Subtract \p that from \p this. + /// @returns this + /// @brief Decrementing assignment operator. + TimeValue& operator -= (const TimeValue &that ) { + this->seconds_ -= that.seconds_ ; + this->nanos_ -= that.nanos_ ; + this->normalize(); + return *this; + } + + /// Determine if \p this is less than \p that. + /// @returns True iff *this < that. + /// @brief True if this < that. + int operator < (const TimeValue &that) const { return that > *this; } + + /// Determine if \p this is greather than \p that. + /// @returns True iff *this > that. + /// @brief True if this > that. + int operator > (const TimeValue &that) const { + if ( this->seconds_ > that.seconds_ ) { + return 1; + } else if ( this->seconds_ == that.seconds_ ) { + if ( this->nanos_ > that.nanos_ ) return 1; + } + return 0; + } + + /// Determine if \p this is less than or equal to \p that. + /// @returns True iff *this <= that. + /// @brief True if this <= that. + int operator <= (const TimeValue &that) const { return that >= *this; } + + /// Determine if \p this is greater than or equal to \p that. + /// @returns True iff *this >= that. + int operator >= (const TimeValue &that) const { + if ( this->seconds_ > that.seconds_ ) { + return 1; + } else if ( this->seconds_ == that.seconds_ ) { + if ( this->nanos_ >= that.nanos_ ) return 1; + } + return 0; + } + + /// Determines if two TimeValue objects represent the same moment in time. + /// @returns True iff *this == that. + int operator == (const TimeValue &that) const { + return (this->seconds_ == that.seconds_) && + (this->nanos_ == that.nanos_); + } + + /// Determines if two TimeValue objects represent times that are not the + /// same. + /// @returns True iff *this != that. + int operator != (const TimeValue &that) const { return !(*this == that); } + + /// Adds two TimeValue objects together. + /// @returns The sum of the two operands as a new TimeValue + /// @brief Addition operator. + friend TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2); + + /// Subtracts two TimeValue objects. + /// @returns The difference of the two operands as a new TimeValue + /// @brief Subtraction operator. + friend TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2); + + /// @} + /// @name Accessors + /// @{ + public: + + /// Returns only the seconds component of the TimeValue. The nanoseconds + /// portion is ignored. No rounding is performed. + /// @brief Retrieve the seconds component + SecondsType seconds() const { return seconds_; } + + /// Returns only the nanoseconds component of the TimeValue. The seconds + /// portion is ignored. + /// @brief Retrieve the nanoseconds component. + NanoSecondsType nanoseconds() const { return nanos_; } + + /// Returns only the fractional portion of the TimeValue rounded down to the + /// nearest microsecond (divide by one thousand). + /// @brief Retrieve the fractional part as microseconds; + uint32_t microseconds() const { + return nanos_ / NANOSECONDS_PER_MICROSECOND; + } + + /// Returns only the fractional portion of the TimeValue rounded down to the + /// nearest millisecond (divide by one million). + /// @brief Retrieve the fractional part as milliseconds; + uint32_t milliseconds() const { + return nanos_ / NANOSECONDS_PER_MILLISECOND; + } + + /// Returns the TimeValue as a number of microseconds. Note that the value + /// returned can overflow because the range of a uint64_t is smaller than + /// the range of a TimeValue. Nevertheless, this is useful on some operating + /// systems and is therefore provided. + /// @brief Convert to a number of microseconds (can overflow) + uint64_t usec() const { + return seconds_ * MICROSECONDS_PER_SECOND + + ( nanos_ / NANOSECONDS_PER_MICROSECOND ); + } + + /// Returns the TimeValue as a number of milliseconds. Note that the value + /// returned can overflow because the range of a uint64_t is smaller than + /// the range of a TimeValue. Nevertheless, this is useful on some operating + /// systems and is therefore provided. + /// @brief Convert to a number of milliseconds (can overflow) + uint64_t msec() const { + return seconds_ * MILLISECONDS_PER_SECOND + + ( nanos_ / NANOSECONDS_PER_MILLISECOND ); + } + + /// Converts the TimeValue into the corresponding number of seconds + /// since the epoch (00:00:00 Jan 1,1970). + uint64_t toEpochTime() const { + return seconds_ - PosixZeroTimeSeconds; + } + + /// Converts the TimeValue into the corresponding number of "ticks" for + /// Win32 platforms, correcting for the difference in Win32 zero time. + /// @brief Convert to Win32's FILETIME + /// (100ns intervals since 00:00:00 Jan 1, 1601 UTC) + uint64_t toWin32Time() const { + uint64_t result = (uint64_t)10000000 * (seconds_ - Win32ZeroTimeSeconds); + result += nanos_ / NANOSECONDS_PER_WIN32_TICK; + return result; + } + + /// Provides the seconds and nanoseconds as results in its arguments after + /// correction for the Posix zero time. + /// @brief Convert to timespec time (ala POSIX.1b) + void getTimespecTime( uint64_t& seconds, uint32_t& nanos ) const { + seconds = seconds_ - PosixZeroTimeSeconds; + nanos = nanos_; + } + + /// Provides conversion of the TimeValue into a readable time & date. + /// @returns std::string containing the readable time value + /// @brief Convert time to a string. + std::string str() const; + + /// @} + /// @name Mutators + /// @{ + public: + /// The seconds component of the TimeValue is set to \p sec without + /// modifying the nanoseconds part. This is useful for whole second + /// arithmetic. + /// @brief Set the seconds component. + void seconds (SecondsType sec ) { + this->seconds_ = sec; + this->normalize(); + } + + /// The nanoseconds component of the TimeValue is set to \p nanos without + /// modifying the seconds part. This is useful for basic computations + /// involving just the nanoseconds portion. Note that the TimeValue will be + /// normalized after this call so that the fractional (nanoseconds) portion + /// will have the smallest equivalent value. + /// @brief Set the nanoseconds component using a number of nanoseconds. + void nanoseconds ( NanoSecondsType nanos ) { + this->nanos_ = nanos; + this->normalize(); + } + + /// The seconds component remains unchanged. + /// @brief Set the nanoseconds component using a number of microseconds. + void microseconds ( int32_t micros ) { + this->nanos_ = micros * NANOSECONDS_PER_MICROSECOND; + this->normalize(); + } + + /// The seconds component remains unchanged. + /// @brief Set the nanoseconds component using a number of milliseconds. + void milliseconds ( int32_t millis ) { + this->nanos_ = millis * NANOSECONDS_PER_MILLISECOND; + this->normalize(); + } + + /// @brief Converts from microsecond format to TimeValue format + void usec( int64_t microseconds ) { + this->seconds_ = microseconds / MICROSECONDS_PER_SECOND; + this->nanos_ = NanoSecondsType(microseconds % MICROSECONDS_PER_SECOND) * + NANOSECONDS_PER_MICROSECOND; + this->normalize(); + } + + /// @brief Converts from millisecond format to TimeValue format + void msec( int64_t milliseconds ) { + this->seconds_ = milliseconds / MILLISECONDS_PER_SECOND; + this->nanos_ = NanoSecondsType(milliseconds % MILLISECONDS_PER_SECOND) * + NANOSECONDS_PER_MILLISECOND; + this->normalize(); + } + + /// Converts the \p seconds argument from PosixTime to the corresponding + /// TimeValue and assigns that value to \p this. + /// @brief Convert seconds form PosixTime to TimeValue + void fromEpochTime( SecondsType seconds ) { + seconds_ = seconds + PosixZeroTimeSeconds; + nanos_ = 0; + this->normalize(); + } + + /// Converts the \p win32Time argument from Windows FILETIME to the + /// corresponding TimeValue and assigns that value to \p this. + /// @brief Convert seconds form Windows FILETIME to TimeValue + void fromWin32Time( uint64_t win32Time ) { + this->seconds_ = win32Time / 10000000 + Win32ZeroTimeSeconds; + this->nanos_ = NanoSecondsType(win32Time % 10000000) * 100; + } + + /// @} + /// @name Implementation + /// @{ + private: + /// This causes the values to be represented so that the fractional + /// part is minimized, possibly incrementing the seconds part. + /// @brief Normalize to canonical form. + void normalize(); + + /// @} + /// @name Data + /// @{ + private: + /// Store the values as a <timeval>. + SecondsType seconds_;///< Stores the seconds part of the TimeVal + NanoSecondsType nanos_; ///< Stores the nanoseconds part of the TimeVal + + static const SecondsType PosixZeroTimeSeconds; + static const SecondsType Win32ZeroTimeSeconds; + /// @} + + }; + +inline TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2) { + TimeValue sum (tv1.seconds_ + tv2.seconds_, tv1.nanos_ + tv2.nanos_); + sum.normalize (); + return sum; +} + +inline TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2) { + TimeValue difference (tv1.seconds_ - tv2.seconds_, tv1.nanos_ - tv2.nanos_ ); + difference.normalize (); + return difference; +} + +} +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Timer.h b/third_party/llvm-subzero/include/llvm/Support/Timer.h new file mode 100644 index 0000000..f0cb075 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Timer.h
@@ -0,0 +1,199 @@ +//===-- llvm/Support/Timer.h - Interval Timing Support ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TIMER_H +#define LLVM_SUPPORT_TIMER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include <cassert> +#include <string> +#include <utility> +#include <vector> + +namespace llvm { + +class Timer; +class TimerGroup; +class raw_ostream; + +class TimeRecord { + double WallTime; // Wall clock time elapsed in seconds + double UserTime; // User time elapsed + double SystemTime; // System time elapsed + ssize_t MemUsed; // Memory allocated (in bytes) +public: + TimeRecord() : WallTime(0), UserTime(0), SystemTime(0), MemUsed(0) {} + + /// getCurrentTime - Get the current time and memory usage. If Start is true + /// we get the memory usage before the time, otherwise we get time before + /// memory usage. This matters if the time to get the memory usage is + /// significant and shouldn't be counted as part of a duration. + static TimeRecord getCurrentTime(bool Start = true); + + double getProcessTime() const { return UserTime + SystemTime; } + double getUserTime() const { return UserTime; } + double getSystemTime() const { return SystemTime; } + double getWallTime() const { return WallTime; } + ssize_t getMemUsed() const { return MemUsed; } + + // operator< - Allow sorting. + bool operator<(const TimeRecord &T) const { + // Sort by Wall Time elapsed, as it is the only thing really accurate + return WallTime < T.WallTime; + } + + void operator+=(const TimeRecord &RHS) { + WallTime += RHS.WallTime; + UserTime += RHS.UserTime; + SystemTime += RHS.SystemTime; + MemUsed += RHS.MemUsed; + } + void operator-=(const TimeRecord &RHS) { + WallTime -= RHS.WallTime; + UserTime -= RHS.UserTime; + SystemTime -= RHS.SystemTime; + MemUsed -= RHS.MemUsed; + } + + /// Print the current time record to \p OS, with a breakdown showing + /// contributions to the \p Total time record. + void print(const TimeRecord &Total, raw_ostream &OS) const; +}; + +/// Timer - This class is used to track the amount of time spent between +/// invocations of its startTimer()/stopTimer() methods. Given appropriate OS +/// support it can also keep track of the RSS of the program at various points. +/// By default, the Timer will print the amount of time it has captured to +/// standard error when the last timer is destroyed, otherwise it is printed +/// when its TimerGroup is destroyed. Timers do not print their information +/// if they are never started. +/// +class Timer { + TimeRecord Time; // The total time captured + TimeRecord StartTime; // The time startTimer() was last called + std::string Name; // The name of this time variable. + bool Running; // Is the timer currently running? + bool Triggered; // Has the timer ever been triggered? + TimerGroup *TG; // The TimerGroup this Timer is in. + + Timer **Prev, *Next; // Doubly linked list of timers in the group. +public: + explicit Timer(StringRef N) : TG(nullptr) { init(N); } + Timer(StringRef N, TimerGroup &tg) : TG(nullptr) { init(N, tg); } + Timer(const Timer &RHS) : TG(nullptr) { + assert(!RHS.TG && "Can only copy uninitialized timers"); + } + const Timer &operator=(const Timer &T) { + assert(!TG && !T.TG && "Can only assign uninit timers"); + return *this; + } + ~Timer(); + + // Create an uninitialized timer, client must use 'init'. + explicit Timer() : TG(nullptr) {} + void init(StringRef N); + void init(StringRef N, TimerGroup &tg); + + const std::string &getName() const { return Name; } + bool isInitialized() const { return TG != nullptr; } + + /// Check if the timer is currently running. + bool isRunning() const { return Running; } + + /// Check if startTimer() has ever been called on this timer. + bool hasTriggered() const { return Triggered; } + + /// Start the timer running. Time between calls to startTimer/stopTimer is + /// counted by the Timer class. Note that these calls must be correctly + /// paired. + void startTimer(); + + /// Stop the timer. + void stopTimer(); + + /// Clear the timer state. + void clear(); + + /// Return the duration for which this timer has been running. + TimeRecord getTotalTime() const { return Time; } + +private: + friend class TimerGroup; +}; + +/// The TimeRegion class is used as a helper class to call the startTimer() and +/// stopTimer() methods of the Timer class. When the object is constructed, it +/// starts the timer specified as its argument. When it is destroyed, it stops +/// the relevant timer. This makes it easy to time a region of code. +/// +class TimeRegion { + Timer *T; + TimeRegion(const TimeRegion &) = delete; + +public: + explicit TimeRegion(Timer &t) : T(&t) { + T->startTimer(); + } + explicit TimeRegion(Timer *t) : T(t) { + if (T) T->startTimer(); + } + ~TimeRegion() { + if (T) T->stopTimer(); + } +}; + +/// NamedRegionTimer - This class is basically a combination of TimeRegion and +/// Timer. It allows you to declare a new timer, AND specify the region to +/// time, all in one statement. All timers with the same name are merged. This +/// is primarily used for debugging and for hunting performance problems. +/// +struct NamedRegionTimer : public TimeRegion { + explicit NamedRegionTimer(StringRef Name, + bool Enabled = true); + explicit NamedRegionTimer(StringRef Name, StringRef GroupName, + bool Enabled = true); +}; + +/// The TimerGroup class is used to group together related timers into a single +/// report that is printed when the TimerGroup is destroyed. It is illegal to +/// destroy a TimerGroup object before all of the Timers in it are gone. A +/// TimerGroup can be specified for a newly created timer in its constructor. +/// +class TimerGroup { + std::string Name; + Timer *FirstTimer; // First timer in the group. + std::vector<std::pair<TimeRecord, std::string>> TimersToPrint; + + TimerGroup **Prev, *Next; // Doubly linked list of TimerGroup's. + TimerGroup(const TimerGroup &TG) = delete; + void operator=(const TimerGroup &TG) = delete; + +public: + explicit TimerGroup(StringRef name); + ~TimerGroup(); + + void setName(StringRef name) { Name.assign(name.begin(), name.end()); } + + /// print - Print any started timers in this group and zero them. + void print(raw_ostream &OS); + + /// printAll - This static method prints all timers and clears them all out. + static void printAll(raw_ostream &OS); + +private: + friend class Timer; + void addTimer(Timer &T); + void removeTimer(Timer &T); + void PrintQueuedTimers(raw_ostream &OS); +}; + +} // End llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Valgrind.h b/third_party/llvm-subzero/include/llvm/Support/Valgrind.h new file mode 100644 index 0000000..084b901 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/Valgrind.h
@@ -0,0 +1,32 @@ +//===- llvm/Support/Valgrind.h - Communication with Valgrind ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Methods for communicating with a valgrind instance this program is running +// under. These are all no-ops unless LLVM was configured on a system with the +// valgrind headers installed and valgrind is controlling this process. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_VALGRIND_H +#define LLVM_SUPPORT_VALGRIND_H + +#include <cstddef> + +namespace llvm { +namespace sys { + // True if Valgrind is controlling this process. + bool RunningOnValgrind(); + + // Discard valgrind's translation of code in the range [Addr .. Addr + Len). + // Otherwise valgrind may continue to execute the old version of the code. + void ValgrindDiscardTranslations(const void *Addr, size_t Len); +} // namespace sys +} // end namespace llvm + +#endif // LLVM_SUPPORT_VALGRIND_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/WindowsError.h b/third_party/llvm-subzero/include/llvm/Support/WindowsError.h new file mode 100644 index 0000000..63bfe59 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/WindowsError.h
@@ -0,0 +1,19 @@ +//===-- WindowsError.h - Support for mapping windows errors to posix-------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_WINDOWSERROR_H +#define LLVM_SUPPORT_WINDOWSERROR_H + +#include <system_error> + +namespace llvm { +std::error_code mapWindowsError(unsigned EV); +} + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/circular_raw_ostream.h b/third_party/llvm-subzero/include/llvm/Support/circular_raw_ostream.h new file mode 100644 index 0000000..b46fd7f --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/circular_raw_ostream.h
@@ -0,0 +1,156 @@ +//===-- llvm/Support/circular_raw_ostream.h - Buffered streams --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains raw_ostream implementations for streams to do circular +// buffering of their output. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H +#define LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H + +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + /// circular_raw_ostream - A raw_ostream which *can* save its data + /// to a circular buffer, or can pass it through directly to an + /// underlying stream if specified with a buffer of zero. + /// + class circular_raw_ostream : public raw_ostream { + public: + /// TAKE_OWNERSHIP - Tell this stream that it owns the underlying + /// stream and is responsible for cleanup, memory management + /// issues, etc. + /// + static const bool TAKE_OWNERSHIP = true; + + /// REFERENCE_ONLY - Tell this stream it should not manage the + /// held stream. + /// + static const bool REFERENCE_ONLY = false; + + private: + /// TheStream - The real stream we output to. We set it to be + /// unbuffered, since we're already doing our own buffering. + /// + raw_ostream *TheStream; + + /// OwnsStream - Are we responsible for managing the underlying + /// stream? + /// + bool OwnsStream; + + /// BufferSize - The size of the buffer in bytes. + /// + size_t BufferSize; + + /// BufferArray - The actual buffer storage. + /// + char *BufferArray; + + /// Cur - Pointer to the current output point in BufferArray. + /// + char *Cur; + + /// Filled - Indicate whether the buffer has been completely + /// filled. This helps avoid garbage output. + /// + bool Filled; + + /// Banner - A pointer to a banner to print before dumping the + /// log. + /// + const char *Banner; + + /// flushBuffer - Dump the contents of the buffer to Stream. + /// + void flushBuffer() { + if (Filled) + // Write the older portion of the buffer. + TheStream->write(Cur, BufferArray + BufferSize - Cur); + // Write the newer portion of the buffer. + TheStream->write(BufferArray, Cur - BufferArray); + Cur = BufferArray; + Filled = false; + } + + void write_impl(const char *Ptr, size_t Size) override; + + /// current_pos - Return the current position within the stream, + /// not counting the bytes currently in the buffer. + /// + uint64_t current_pos() const override { + // This has the same effect as calling TheStream.current_pos(), + // but that interface is private. + return TheStream->tell() - TheStream->GetNumBytesInBuffer(); + } + + public: + /// circular_raw_ostream - Construct an optionally + /// circular-buffered stream, handing it an underlying stream to + /// do the "real" output. + /// + /// As a side effect, if BuffSize is nonzero, the given Stream is + /// set to be Unbuffered. This is because circular_raw_ostream + /// does its own buffering, so it doesn't want another layer of + /// buffering to be happening underneath it. + /// + /// "Owns" tells the circular_raw_ostream whether it is + /// responsible for managing the held stream, doing memory + /// management of it, etc. + /// + circular_raw_ostream(raw_ostream &Stream, const char *Header, + size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) + : raw_ostream(/*unbuffered*/ true), TheStream(nullptr), + OwnsStream(Owns), BufferSize(BuffSize), BufferArray(nullptr), + Filled(false), Banner(Header) { + if (BufferSize != 0) + BufferArray = new char[BufferSize]; + Cur = BufferArray; + setStream(Stream, Owns); + } + + ~circular_raw_ostream() override { + flush(); + flushBufferWithBanner(); + releaseStream(); + delete[] BufferArray; + } + + /// setStream - Tell the circular_raw_ostream to output a + /// different stream. "Owns" tells circular_raw_ostream whether + /// it should take responsibility for managing the underlying + /// stream. + /// + void setStream(raw_ostream &Stream, bool Owns = REFERENCE_ONLY) { + releaseStream(); + TheStream = &Stream; + OwnsStream = Owns; + } + + /// flushBufferWithBanner - Force output of the buffer along with + /// a small header. + /// + void flushBufferWithBanner(); + + private: + /// releaseStream - Delete the held stream if needed. Otherwise, + /// transfer the buffer settings from this circular_raw_ostream + /// back to the underlying stream. + /// + void releaseStream() { + if (!TheStream) + return; + if (OwnsStream) + delete TheStream; + } + }; +} // end llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/raw_os_ostream.h b/third_party/llvm-subzero/include/llvm/Support/raw_os_ostream.h new file mode 100644 index 0000000..a983aeb --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/raw_os_ostream.h
@@ -0,0 +1,42 @@ +//===- raw_os_ostream.h - std::ostream adaptor for raw_ostream --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the raw_os_ostream class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_RAW_OS_OSTREAM_H +#define LLVM_SUPPORT_RAW_OS_OSTREAM_H + +#include "llvm/Support/raw_ostream.h" +#include <iosfwd> + +namespace llvm { + +/// raw_os_ostream - A raw_ostream that writes to an std::ostream. This is a +/// simple adaptor class. It does not check for output errors; clients should +/// use the underlying stream to detect errors. +class raw_os_ostream : public raw_ostream { + std::ostream &OS; + + /// write_impl - See raw_ostream::write_impl. + void write_impl(const char *Ptr, size_t Size) override; + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + uint64_t current_pos() const override; + +public: + raw_os_ostream(std::ostream &O) : OS(O) {} + ~raw_os_ostream() override; +}; + +} // end llvm namespace + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/raw_ostream.h b/third_party/llvm-subzero/include/llvm/Support/raw_ostream.h new file mode 100644 index 0000000..d1e96f8 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/raw_ostream.h
@@ -0,0 +1,530 @@ +//===--- raw_ostream.h - Raw output stream ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the raw_ostream class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_RAW_OSTREAM_H +#define LLVM_SUPPORT_RAW_OSTREAM_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include <system_error> + +namespace llvm { +class format_object_base; +class FormattedString; +class FormattedNumber; +template <typename T> class SmallVectorImpl; + +namespace sys { +namespace fs { +enum OpenFlags : unsigned; +} +} + +/// This class implements an extremely fast bulk output stream that can *only* +/// output to a stream. It does not support seeking, reopening, rewinding, line +/// buffered disciplines etc. It is a simple buffer that outputs +/// a chunk at a time. +class raw_ostream { +private: + void operator=(const raw_ostream &) = delete; + raw_ostream(const raw_ostream &) = delete; + + /// The buffer is handled in such a way that the buffer is + /// uninitialized, unbuffered, or out of space when OutBufCur >= + /// OutBufEnd. Thus a single comparison suffices to determine if we + /// need to take the slow path to write a single character. + /// + /// The buffer is in one of three states: + /// 1. Unbuffered (BufferMode == Unbuffered) + /// 1. Uninitialized (BufferMode != Unbuffered && OutBufStart == 0). + /// 2. Buffered (BufferMode != Unbuffered && OutBufStart != 0 && + /// OutBufEnd - OutBufStart >= 1). + /// + /// If buffered, then the raw_ostream owns the buffer if (BufferMode == + /// InternalBuffer); otherwise the buffer has been set via SetBuffer and is + /// managed by the subclass. + /// + /// If a subclass installs an external buffer using SetBuffer then it can wait + /// for a \see write_impl() call to handle the data which has been put into + /// this buffer. + char *OutBufStart, *OutBufEnd, *OutBufCur; + + enum BufferKind { + Unbuffered = 0, + InternalBuffer, + ExternalBuffer + } BufferMode; + +public: + // color order matches ANSI escape sequence, don't change + enum Colors { + BLACK=0, + RED, + GREEN, + YELLOW, + BLUE, + MAGENTA, + CYAN, + WHITE, + SAVEDCOLOR + }; + + explicit raw_ostream(bool unbuffered = false) + : BufferMode(unbuffered ? Unbuffered : InternalBuffer) { + // Start out ready to flush. + OutBufStart = OutBufEnd = OutBufCur = nullptr; + } + + virtual ~raw_ostream(); + + /// tell - Return the current offset with the file. + uint64_t tell() const { return current_pos() + GetNumBytesInBuffer(); } + + //===--------------------------------------------------------------------===// + // Configuration Interface + //===--------------------------------------------------------------------===// + + /// Set the stream to be buffered, with an automatically determined buffer + /// size. + void SetBuffered(); + + /// Set the stream to be buffered, using the specified buffer size. + void SetBufferSize(size_t Size) { + flush(); + SetBufferAndMode(new char[Size], Size, InternalBuffer); + } + + size_t GetBufferSize() const { + // If we're supposed to be buffered but haven't actually gotten around + // to allocating the buffer yet, return the value that would be used. + if (BufferMode != Unbuffered && OutBufStart == nullptr) + return preferred_buffer_size(); + + // Otherwise just return the size of the allocated buffer. + return OutBufEnd - OutBufStart; + } + + /// Set the stream to be unbuffered. When unbuffered, the stream will flush + /// after every write. This routine will also flush the buffer immediately + /// when the stream is being set to unbuffered. + void SetUnbuffered() { + flush(); + SetBufferAndMode(nullptr, 0, Unbuffered); + } + + size_t GetNumBytesInBuffer() const { + return OutBufCur - OutBufStart; + } + + //===--------------------------------------------------------------------===// + // Data Output Interface + //===--------------------------------------------------------------------===// + + void flush() { + if (OutBufCur != OutBufStart) + flush_nonempty(); + } + + raw_ostream &operator<<(char C) { + if (OutBufCur >= OutBufEnd) + return write(C); + *OutBufCur++ = C; + return *this; + } + + raw_ostream &operator<<(unsigned char C) { + if (OutBufCur >= OutBufEnd) + return write(C); + *OutBufCur++ = C; + return *this; + } + + raw_ostream &operator<<(signed char C) { + if (OutBufCur >= OutBufEnd) + return write(C); + *OutBufCur++ = C; + return *this; + } + + raw_ostream &operator<<(StringRef Str) { + // Inline fast path, particularly for strings with a known length. + size_t Size = Str.size(); + + // Make sure we can use the fast path. + if (Size > (size_t)(OutBufEnd - OutBufCur)) + return write(Str.data(), Size); + + if (Size) { + memcpy(OutBufCur, Str.data(), Size); + OutBufCur += Size; + } + return *this; + } + + raw_ostream &operator<<(const char *Str) { + // Inline fast path, particularly for constant strings where a sufficiently + // smart compiler will simplify strlen. + + return this->operator<<(StringRef(Str)); + } + + raw_ostream &operator<<(const std::string &Str) { + // Avoid the fast path, it would only increase code size for a marginal win. + return write(Str.data(), Str.length()); + } + + raw_ostream &operator<<(const llvm::SmallVectorImpl<char> &Str) { + return write(Str.data(), Str.size()); + } + + raw_ostream &operator<<(unsigned long N); + raw_ostream &operator<<(long N); + raw_ostream &operator<<(unsigned long long N); + raw_ostream &operator<<(long long N); + raw_ostream &operator<<(const void *P); + raw_ostream &operator<<(unsigned int N) { + return this->operator<<(static_cast<unsigned long>(N)); + } + + raw_ostream &operator<<(int N) { + return this->operator<<(static_cast<long>(N)); + } + + raw_ostream &operator<<(double N); + + /// Output \p N in hexadecimal, without any prefix or padding. + raw_ostream &write_hex(unsigned long long N); + + /// Output \p Str, turning '\\', '\t', '\n', '"', and anything that doesn't + /// satisfy std::isprint into an escape sequence. + raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false); + + raw_ostream &write(unsigned char C); + raw_ostream &write(const char *Ptr, size_t Size); + + // Formatted output, see the format() function in Support/Format.h. + raw_ostream &operator<<(const format_object_base &Fmt); + + // Formatted output, see the leftJustify() function in Support/Format.h. + raw_ostream &operator<<(const FormattedString &); + + // Formatted output, see the formatHex() function in Support/Format.h. + raw_ostream &operator<<(const FormattedNumber &); + + /// indent - Insert 'NumSpaces' spaces. + raw_ostream &indent(unsigned NumSpaces); + + /// Changes the foreground color of text that will be output from this point + /// forward. + /// @param Color ANSI color to use, the special SAVEDCOLOR can be used to + /// change only the bold attribute, and keep colors untouched + /// @param Bold bold/brighter text, default false + /// @param BG if true change the background, default: change foreground + /// @returns itself so it can be used within << invocations + virtual raw_ostream &changeColor(enum Colors Color, + bool Bold = false, + bool BG = false) { + (void)Color; + (void)Bold; + (void)BG; + return *this; + } + + /// Resets the colors to terminal defaults. Call this when you are done + /// outputting colored text, or before program exit. + virtual raw_ostream &resetColor() { return *this; } + + /// Reverses the foreground and background colors. + virtual raw_ostream &reverseColor() { return *this; } + + /// This function determines if this stream is connected to a "tty" or + /// "console" window. That is, the output would be displayed to the user + /// rather than being put on a pipe or stored in a file. + virtual bool is_displayed() const { return false; } + + /// This function determines if this stream is displayed and supports colors. + virtual bool has_colors() const { return is_displayed(); } + + //===--------------------------------------------------------------------===// + // Subclass Interface + //===--------------------------------------------------------------------===// + +private: + /// The is the piece of the class that is implemented by subclasses. This + /// writes the \p Size bytes starting at + /// \p Ptr to the underlying stream. + /// + /// This function is guaranteed to only be called at a point at which it is + /// safe for the subclass to install a new buffer via SetBuffer. + /// + /// \param Ptr The start of the data to be written. For buffered streams this + /// is guaranteed to be the start of the buffer. + /// + /// \param Size The number of bytes to be written. + /// + /// \invariant { Size > 0 } + virtual void write_impl(const char *Ptr, size_t Size) = 0; + + // An out of line virtual method to provide a home for the class vtable. + virtual void handle(); + + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. + virtual uint64_t current_pos() const = 0; + +protected: + /// Use the provided buffer as the raw_ostream buffer. This is intended for + /// use only by subclasses which can arrange for the output to go directly + /// into the desired output buffer, instead of being copied on each flush. + void SetBuffer(char *BufferStart, size_t Size) { + SetBufferAndMode(BufferStart, Size, ExternalBuffer); + } + + /// Return an efficient buffer size for the underlying output mechanism. + virtual size_t preferred_buffer_size() const; + + /// Return the beginning of the current stream buffer, or 0 if the stream is + /// unbuffered. + const char *getBufferStart() const { return OutBufStart; } + + //===--------------------------------------------------------------------===// + // Private Interface + //===--------------------------------------------------------------------===// +private: + /// Install the given buffer and mode. + void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode); + + /// Flush the current buffer, which is known to be non-empty. This outputs the + /// currently buffered data and resets the buffer to empty. + void flush_nonempty(); + + /// Copy data into the buffer. Size must not be greater than the number of + /// unused bytes in the buffer. + void copy_to_buffer(const char *Ptr, size_t Size); +}; + +/// An abstract base class for streams implementations that also support a +/// pwrite operation. This is useful for code that can mostly stream out data, +/// but needs to patch in a header that needs to know the output size. +class raw_pwrite_stream : public raw_ostream { + virtual void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) = 0; + +public: + explicit raw_pwrite_stream(bool Unbuffered = false) + : raw_ostream(Unbuffered) {} + void pwrite(const char *Ptr, size_t Size, uint64_t Offset) { +#ifndef NDBEBUG + uint64_t Pos = tell(); + // /dev/null always reports a pos of 0, so we cannot perform this check + // in that case. + if (Pos) + assert(Size + Offset <= Pos && "We don't support extending the stream"); +#endif + pwrite_impl(Ptr, Size, Offset); + } +}; + +//===----------------------------------------------------------------------===// +// File Output Streams +//===----------------------------------------------------------------------===// + +/// A raw_ostream that writes to a file descriptor. +/// +class raw_fd_ostream : public raw_pwrite_stream { + int FD; + bool ShouldClose; + + /// Error This flag is true if an error of any kind has been detected. + /// + bool Error; + + uint64_t pos; + + bool SupportsSeeking; + + /// See raw_ostream::write_impl. + void write_impl(const char *Ptr, size_t Size) override; + + void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override; + + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. + uint64_t current_pos() const override { return pos; } + + /// Determine an efficient buffer size. + size_t preferred_buffer_size() const override; + + /// Set the flag indicating that an output error has been encountered. + void error_detected() { Error = true; } + +public: + /// Open the specified file for writing. If an error occurs, information + /// about the error is put into EC, and the stream should be immediately + /// destroyed; + /// \p Flags allows optional flags to control how the file will be opened. + /// + /// As a special case, if Filename is "-", then the stream will use + /// STDOUT_FILENO instead of opening a file. Note that it will still consider + /// itself to own the file descriptor. In particular, it will close the + /// file descriptor when it is done (this is necessary to detect + /// output errors). + raw_fd_ostream(StringRef Filename, std::error_code &EC, + sys::fs::OpenFlags Flags); + + /// FD is the file descriptor that this writes to. If ShouldClose is true, + /// this closes the file when the stream is destroyed. + raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false); + + ~raw_fd_ostream() override; + + /// Manually flush the stream and close the file. Note that this does not call + /// fsync. + void close(); + + bool supportsSeeking() { return SupportsSeeking; } + + /// Flushes the stream and repositions the underlying file descriptor position + /// to the offset specified from the beginning of the file. + uint64_t seek(uint64_t off); + + raw_ostream &changeColor(enum Colors colors, bool bold=false, + bool bg=false) override; + raw_ostream &resetColor() override; + + raw_ostream &reverseColor() override; + + bool is_displayed() const override; + + bool has_colors() const override; + + /// Return the value of the flag in this raw_fd_ostream indicating whether an + /// output error has been encountered. + /// This doesn't implicitly flush any pending output. Also, it doesn't + /// guarantee to detect all errors unless the stream has been closed. + bool has_error() const { + return Error; + } + + /// Set the flag read by has_error() to false. If the error flag is set at the + /// time when this raw_ostream's destructor is called, report_fatal_error is + /// called to report the error. Use clear_error() after handling the error to + /// avoid this behavior. + /// + /// "Errors should never pass silently. + /// Unless explicitly silenced." + /// - from The Zen of Python, by Tim Peters + /// + void clear_error() { + Error = false; + } +}; + +/// This returns a reference to a raw_ostream for standard output. Use it like: +/// outs() << "foo" << "bar"; +raw_ostream &outs(); + +/// This returns a reference to a raw_ostream for standard error. Use it like: +/// errs() << "foo" << "bar"; +raw_ostream &errs(); + +/// This returns a reference to a raw_ostream which simply discards output. +raw_ostream &nulls(); + +//===----------------------------------------------------------------------===// +// Output Stream Adaptors +//===----------------------------------------------------------------------===// + +/// A raw_ostream that writes to an std::string. This is a simple adaptor +/// class. This class does not encounter output errors. +class raw_string_ostream : public raw_ostream { + std::string &OS; + + /// See raw_ostream::write_impl. + void write_impl(const char *Ptr, size_t Size) override; + + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. + uint64_t current_pos() const override { return OS.size(); } + +public: + explicit raw_string_ostream(std::string &O) : OS(O) {} + ~raw_string_ostream() override; + + /// Flushes the stream contents to the target string and returns the string's + /// reference. + std::string& str() { + flush(); + return OS; + } +}; + +/// A raw_ostream that writes to an SmallVector or SmallString. This is a +/// simple adaptor class. This class does not encounter output errors. +/// raw_svector_ostream operates without a buffer, delegating all memory +/// management to the SmallString. Thus the SmallString is always up-to-date, +/// may be used directly and there is no need to call flush(). +class raw_svector_ostream : public raw_pwrite_stream { + SmallVectorImpl<char> &OS; + + /// See raw_ostream::write_impl. + void write_impl(const char *Ptr, size_t Size) override; + + void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override; + + /// Return the current position within the stream. + uint64_t current_pos() const override; + +public: + /// Construct a new raw_svector_ostream. + /// + /// \param O The vector to write to; this should generally have at least 128 + /// bytes free to avoid any extraneous memory overhead. + explicit raw_svector_ostream(SmallVectorImpl<char> &O) : OS(O) { + SetUnbuffered(); + } + ~raw_svector_ostream() override {} + + void flush() = delete; + + /// Return a StringRef for the vector contents. + StringRef str() { return StringRef(OS.data(), OS.size()); } +}; + +/// A raw_ostream that discards all output. +class raw_null_ostream : public raw_pwrite_stream { + /// See raw_ostream::write_impl. + void write_impl(const char *Ptr, size_t size) override; + void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override; + + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. + uint64_t current_pos() const override; + +public: + explicit raw_null_ostream() {} + ~raw_null_ostream() override; +}; + +class buffer_ostream : public raw_svector_ostream { + raw_ostream &OS; + SmallVector<char, 0> Buffer; + +public: + buffer_ostream(raw_ostream &OS) : raw_svector_ostream(Buffer), OS(OS) {} + ~buffer_ostream() override { OS << str(); } +}; + +} // end llvm namespace + +#endif // LLVM_SUPPORT_RAW_OSTREAM_H
diff --git a/third_party/llvm-subzero/include/llvm/Support/thread.h b/third_party/llvm-subzero/include/llvm/Support/thread.h new file mode 100644 index 0000000..9c45418 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/thread.h
@@ -0,0 +1,67 @@ +//===-- llvm/Support/thread.h - Wrapper for <thread> ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header is a wrapper for <thread> that works around problems with the +// MSVC headers when exceptions are disabled. It also provides llvm::thread, +// which is either a typedef of std::thread or a replacement that calls the +// function synchronously depending on the value of LLVM_ENABLE_THREADS. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_THREAD_H +#define LLVM_SUPPORT_THREAD_H + +#include "llvm/Config/llvm-config.h" + +#if LLVM_ENABLE_THREADS + +#ifdef _MSC_VER +// concrt.h depends on eh.h for __uncaught_exception declaration +// even if we disable exceptions. +#include <eh.h> + +// Suppress 'C++ exception handler used, but unwind semantics are not enabled.' +#pragma warning(push) +#pragma warning(disable:4530) +#endif + +#include <thread> + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +namespace llvm { +typedef std::thread thread; +} + +#else // !LLVM_ENABLE_THREADS + +#include <utility> + +namespace llvm { + +struct thread { + thread() {} + thread(thread &&other) {} + template <class Function, class... Args> + explicit thread(Function &&f, Args &&... args) { + f(std::forward<Args>(args)...); + } + thread(const thread &) = delete; + + void join() {} + static unsigned hardware_concurrency() { return 1; }; +}; + +} + +#endif // LLVM_ENABLE_THREADS + +#endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/type_traits.h b/third_party/llvm-subzero/include/llvm/Support/type_traits.h new file mode 100644 index 0000000..7706ff5 --- /dev/null +++ b/third_party/llvm-subzero/include/llvm/Support/type_traits.h
@@ -0,0 +1,113 @@ +//===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides useful additions to the standard type_traits library. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TYPE_TRAITS_H +#define LLVM_SUPPORT_TYPE_TRAITS_H + +#include <type_traits> +#include <utility> + +#include "llvm/Support/Compiler.h" + +#ifndef __has_feature +#define LLVM_DEFINED_HAS_FEATURE +#define __has_feature(x) 0 +#endif + +namespace llvm { + +/// isPodLike - This is a type trait that is used to determine whether a given +/// type can be copied around with memcpy instead of running ctors etc. +template <typename T> +struct isPodLike { + // std::is_trivially_copyable is available in libc++ with clang, libstdc++ + // that comes with GCC 5. +#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \ + (defined(__GNUC__) && __GNUC__ >= 5) + // If the compiler supports the is_trivially_copyable trait use it, as it + // matches the definition of isPodLike closely. + static const bool value = std::is_trivially_copyable<T>::value; +#elif __has_feature(is_trivially_copyable) + // Use the internal name if the compiler supports is_trivially_copyable but we + // don't know if the standard library does. This is the case for clang in + // conjunction with libstdc++ from GCC 4.x. + static const bool value = __is_trivially_copyable(T); +#else + // If we don't know anything else, we can (at least) assume that all non-class + // types are PODs. + static const bool value = !std::is_class<T>::value; +#endif +}; + +// std::pair's are pod-like if their elements are. +template<typename T, typename U> +struct isPodLike<std::pair<T, U> > { + static const bool value = isPodLike<T>::value && isPodLike<U>::value; +}; + +/// \brief Metafunction that determines whether the given type is either an +/// integral type or an enumeration type, including enum classes. +/// +/// Note that this accepts potentially more integral types than is_integral +/// because it is based on being implicitly convertible to an integral type. +/// Also note that enum classes aren't implicitly convertible to integral types, +/// the value may therefore need to be explicitly converted before being used. +template <typename T> class is_integral_or_enum { + typedef typename std::remove_reference<T>::type UnderlyingT; + +public: + static const bool value = + !std::is_class<UnderlyingT>::value && // Filter conversion operators. + !std::is_pointer<UnderlyingT>::value && + !std::is_floating_point<UnderlyingT>::value && + (std::is_enum<UnderlyingT>::value || + std::is_convertible<UnderlyingT, unsigned long long>::value); +}; + +/// \brief If T is a pointer, just return it. If it is not, return T&. +template<typename T, typename Enable = void> +struct add_lvalue_reference_if_not_pointer { typedef T &type; }; + +template <typename T> +struct add_lvalue_reference_if_not_pointer< + T, typename std::enable_if<std::is_pointer<T>::value>::type> { + typedef T type; +}; + +/// \brief If T is a pointer to X, return a pointer to const X. If it is not, +/// return const T. +template<typename T, typename Enable = void> +struct add_const_past_pointer { typedef const T type; }; + +template <typename T> +struct add_const_past_pointer< + T, typename std::enable_if<std::is_pointer<T>::value>::type> { + typedef const typename std::remove_pointer<T>::type *type; +}; + +} + +// If the compiler supports detecting whether a class is final, define +// an LLVM_IS_FINAL macro. If it cannot be defined properly, this +// macro will be left undefined. +#if __cplusplus >= 201402L +#define LLVM_IS_FINAL(Ty) std::is_final<Ty>() +#elif __has_feature(is_final) || LLVM_GNUC_PREREQ(4, 7, 0) +#define LLVM_IS_FINAL(Ty) __is_final(Ty) +#endif + +#ifdef LLVM_DEFINED_HAS_FEATURE +#undef __has_feature +#endif + +#endif
diff --git a/third_party/llvm-subzero/lib/Support/APInt.cpp b/third_party/llvm-subzero/lib/Support/APInt.cpp new file mode 100644 index 0000000..318ce10 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/APInt.cpp
@@ -0,0 +1,2887 @@ +//===-- APInt.cpp - Implement APInt class ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a class to represent arbitrary precision integer +// constant values and provide a variety of arithmetic operations on them. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include <cmath> +#include <cstdlib> +#include <cstring> +#include <limits> +using namespace llvm; + +#define DEBUG_TYPE "apint" + +/// A utility function for allocating memory, checking for allocation failures, +/// and ensuring the contents are zeroed. +inline static uint64_t* getClearedMemory(unsigned numWords) { + uint64_t * result = new uint64_t[numWords]; + assert(result && "APInt memory allocation fails!"); + memset(result, 0, numWords * sizeof(uint64_t)); + return result; +} + +/// A utility function for allocating memory and checking for allocation +/// failure. The content is not zeroed. +inline static uint64_t* getMemory(unsigned numWords) { + uint64_t * result = new uint64_t[numWords]; + assert(result && "APInt memory allocation fails!"); + return result; +} + +/// A utility function that converts a character to a digit. +inline static unsigned getDigit(char cdigit, uint8_t radix) { + unsigned r; + + if (radix == 16 || radix == 36) { + r = cdigit - '0'; + if (r <= 9) + return r; + + r = cdigit - 'A'; + if (r <= radix - 11U) + return r + 10; + + r = cdigit - 'a'; + if (r <= radix - 11U) + return r + 10; + + radix = 10; + } + + r = cdigit - '0'; + if (r < radix) + return r; + + return -1U; +} + + +void APInt::initSlowCase(uint64_t val, bool isSigned) { + pVal = getClearedMemory(getNumWords()); + pVal[0] = val; + if (isSigned && int64_t(val) < 0) + for (unsigned i = 1; i < getNumWords(); ++i) + pVal[i] = -1ULL; +} + +void APInt::initSlowCase(const APInt& that) { + pVal = getMemory(getNumWords()); + memcpy(pVal, that.pVal, getNumWords() * APINT_WORD_SIZE); +} + +void APInt::initFromArray(ArrayRef<uint64_t> bigVal) { + assert(BitWidth && "Bitwidth too small"); + assert(bigVal.data() && "Null pointer detected!"); + if (isSingleWord()) + VAL = bigVal[0]; + else { + // Get memory, cleared to 0 + pVal = getClearedMemory(getNumWords()); + // Calculate the number of words to copy + unsigned words = std::min<unsigned>(bigVal.size(), getNumWords()); + // Copy the words from bigVal to pVal + memcpy(pVal, bigVal.data(), words * APINT_WORD_SIZE); + } + // Make sure unused high bits are cleared + clearUnusedBits(); +} + +APInt::APInt(unsigned numBits, ArrayRef<uint64_t> bigVal) + : BitWidth(numBits), VAL(0) { + initFromArray(bigVal); +} + +APInt::APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]) + : BitWidth(numBits), VAL(0) { + initFromArray(makeArrayRef(bigVal, numWords)); +} + +APInt::APInt(unsigned numbits, StringRef Str, uint8_t radix) + : BitWidth(numbits), VAL(0) { + assert(BitWidth && "Bitwidth too small"); + fromString(numbits, Str, radix); +} + +APInt& APInt::AssignSlowCase(const APInt& RHS) { + // Don't do anything for X = X + if (this == &RHS) + return *this; + + if (BitWidth == RHS.getBitWidth()) { + // assume same bit-width single-word case is already handled + assert(!isSingleWord()); + memcpy(pVal, RHS.pVal, getNumWords() * APINT_WORD_SIZE); + return *this; + } + + if (isSingleWord()) { + // assume case where both are single words is already handled + assert(!RHS.isSingleWord()); + VAL = 0; + pVal = getMemory(RHS.getNumWords()); + memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE); + } else if (getNumWords() == RHS.getNumWords()) + memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE); + else if (RHS.isSingleWord()) { + delete [] pVal; + VAL = RHS.VAL; + } else { + delete [] pVal; + pVal = getMemory(RHS.getNumWords()); + memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE); + } + BitWidth = RHS.BitWidth; + return clearUnusedBits(); +} + +APInt& APInt::operator=(uint64_t RHS) { + if (isSingleWord()) + VAL = RHS; + else { + pVal[0] = RHS; + memset(pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE); + } + return clearUnusedBits(); +} + +/// This method 'profiles' an APInt for use with FoldingSet. +void APInt::Profile(FoldingSetNodeID& ID) const { + ID.AddInteger(BitWidth); + + if (isSingleWord()) { + ID.AddInteger(VAL); + return; + } + + unsigned NumWords = getNumWords(); + for (unsigned i = 0; i < NumWords; ++i) + ID.AddInteger(pVal[i]); +} + +/// This function adds a single "digit" integer, y, to the multiple +/// "digit" integer array, x[]. x[] is modified to reflect the addition and +/// 1 is returned if there is a carry out, otherwise 0 is returned. +/// @returns the carry of the addition. +static bool add_1(uint64_t dest[], uint64_t x[], unsigned len, uint64_t y) { + for (unsigned i = 0; i < len; ++i) { + dest[i] = y + x[i]; + if (dest[i] < y) + y = 1; // Carry one to next digit. + else { + y = 0; // No need to carry so exit early + break; + } + } + return y; +} + +/// @brief Prefix increment operator. Increments the APInt by one. +APInt& APInt::operator++() { + if (isSingleWord()) + ++VAL; + else + add_1(pVal, pVal, getNumWords(), 1); + return clearUnusedBits(); +} + +/// This function subtracts a single "digit" (64-bit word), y, from +/// the multi-digit integer array, x[], propagating the borrowed 1 value until +/// no further borrowing is neeeded or it runs out of "digits" in x. The result +/// is 1 if "borrowing" exhausted the digits in x, or 0 if x was not exhausted. +/// In other words, if y > x then this function returns 1, otherwise 0. +/// @returns the borrow out of the subtraction +static bool sub_1(uint64_t x[], unsigned len, uint64_t y) { + for (unsigned i = 0; i < len; ++i) { + uint64_t X = x[i]; + x[i] -= y; + if (y > X) + y = 1; // We have to "borrow 1" from next "digit" + else { + y = 0; // No need to borrow + break; // Remaining digits are unchanged so exit early + } + } + return bool(y); +} + +/// @brief Prefix decrement operator. Decrements the APInt by one. +APInt& APInt::operator--() { + if (isSingleWord()) + --VAL; + else + sub_1(pVal, getNumWords(), 1); + return clearUnusedBits(); +} + +/// This function adds the integer array x to the integer array Y and +/// places the result in dest. +/// @returns the carry out from the addition +/// @brief General addition of 64-bit integer arrays +static bool add(uint64_t *dest, const uint64_t *x, const uint64_t *y, + unsigned len) { + bool carry = false; + for (unsigned i = 0; i< len; ++i) { + uint64_t limit = std::min(x[i],y[i]); // must come first in case dest == x + dest[i] = x[i] + y[i] + carry; + carry = dest[i] < limit || (carry && dest[i] == limit); + } + return carry; +} + +/// Adds the RHS APint to this APInt. +/// @returns this, after addition of RHS. +/// @brief Addition assignment operator. +APInt& APInt::operator+=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + VAL += RHS.VAL; + else { + add(pVal, pVal, RHS.pVal, getNumWords()); + } + return clearUnusedBits(); +} + +APInt& APInt::operator+=(uint64_t RHS) { + if (isSingleWord()) + VAL += RHS; + else + add_1(pVal, pVal, getNumWords(), RHS); + return clearUnusedBits(); +} + +/// Subtracts the integer array y from the integer array x +/// @returns returns the borrow out. +/// @brief Generalized subtraction of 64-bit integer arrays. +static bool sub(uint64_t *dest, const uint64_t *x, const uint64_t *y, + unsigned len) { + bool borrow = false; + for (unsigned i = 0; i < len; ++i) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = y[i] > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - y[i]; + } + return borrow; +} + +/// Subtracts the RHS APInt from this APInt +/// @returns this, after subtraction +/// @brief Subtraction assignment operator. +APInt& APInt::operator-=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + VAL -= RHS.VAL; + else + sub(pVal, pVal, RHS.pVal, getNumWords()); + return clearUnusedBits(); +} + +APInt& APInt::operator-=(uint64_t RHS) { + if (isSingleWord()) + VAL -= RHS; + else + sub_1(pVal, getNumWords(), RHS); + return clearUnusedBits(); +} + +/// Multiplies an integer array, x, by a uint64_t integer and places the result +/// into dest. +/// @returns the carry out of the multiplication. +/// @brief Multiply a multi-digit APInt by a single digit (64-bit) integer. +static uint64_t mul_1(uint64_t dest[], uint64_t x[], unsigned len, uint64_t y) { + // Split y into high 32-bit part (hy) and low 32-bit part (ly) + uint64_t ly = y & 0xffffffffULL, hy = y >> 32; + uint64_t carry = 0; + + // For each digit of x. + for (unsigned i = 0; i < len; ++i) { + // Split x into high and low words + uint64_t lx = x[i] & 0xffffffffULL; + uint64_t hx = x[i] >> 32; + // hasCarry - A flag to indicate if there is a carry to the next digit. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + dest[i] = carry + lx * ly; + // Determine if the add above introduces carry. + hasCarry = (dest[i] < carry) ? 1 : 0; + carry = hx * ly + (dest[i] >> 32) + (hasCarry ? (1ULL << 32) : 0); + // The upper limit of carry can be (2^32 - 1)(2^32 - 1) + + // (2^32 - 1) + 2^32 = 2^64. + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + + carry += (lx * hy) & 0xffffffffULL; + dest[i] = (carry << 32) | (dest[i] & 0xffffffffULL); + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0) + + (carry >> 32) + ((lx * hy) >> 32) + hx * hy; + } + return carry; +} + +/// Multiplies integer array x by integer array y and stores the result into +/// the integer array dest. Note that dest's size must be >= xlen + ylen. +/// @brief Generalized multiplicate of integer arrays. +static void mul(uint64_t dest[], uint64_t x[], unsigned xlen, uint64_t y[], + unsigned ylen) { + dest[xlen] = mul_1(dest, x, xlen, y[0]); + for (unsigned i = 1; i < ylen; ++i) { + uint64_t ly = y[i] & 0xffffffffULL, hy = y[i] >> 32; + uint64_t carry = 0, lx = 0, hx = 0; + for (unsigned j = 0; j < xlen; ++j) { + lx = x[j] & 0xffffffffULL; + hx = x[j] >> 32; + // hasCarry - A flag to indicate if has carry. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + uint64_t resul = carry + lx * ly; + hasCarry = (resul < carry) ? 1 : 0; + carry = (hasCarry ? (1ULL << 32) : 0) + hx * ly + (resul >> 32); + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + + carry += (lx * hy) & 0xffffffffULL; + resul = (carry << 32) | (resul & 0xffffffffULL); + dest[i+j] += resul; + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0)+ + (carry >> 32) + (dest[i+j] < resul ? 1 : 0) + + ((lx * hy) >> 32) + hx * hy; + } + dest[i+xlen] = carry; + } +} + +APInt& APInt::operator*=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) { + VAL *= RHS.VAL; + clearUnusedBits(); + return *this; + } + + // Get some bit facts about LHS and check for zero + unsigned lhsBits = getActiveBits(); + unsigned lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) + // 0 * X ===> 0 + return *this; + + // Get some bit facts about RHS and check for zero + unsigned rhsBits = RHS.getActiveBits(); + unsigned rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + clearAllBits(); + return *this; + } + + // Allocate space for the result + unsigned destWords = rhsWords + lhsWords; + uint64_t *dest = getMemory(destWords); + + // Perform the long multiply + mul(dest, pVal, lhsWords, RHS.pVal, rhsWords); + + // Copy result back into *this + clearAllBits(); + unsigned wordsToCopy = destWords >= getNumWords() ? getNumWords() : destWords; + memcpy(pVal, dest, wordsToCopy * APINT_WORD_SIZE); + clearUnusedBits(); + + // delete dest array and return + delete[] dest; + return *this; +} + +APInt& APInt::operator&=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) { + VAL &= RHS.VAL; + return *this; + } + unsigned numWords = getNumWords(); + for (unsigned i = 0; i < numWords; ++i) + pVal[i] &= RHS.pVal[i]; + return *this; +} + +APInt& APInt::operator|=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) { + VAL |= RHS.VAL; + return *this; + } + unsigned numWords = getNumWords(); + for (unsigned i = 0; i < numWords; ++i) + pVal[i] |= RHS.pVal[i]; + return *this; +} + +APInt& APInt::operator^=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) { + VAL ^= RHS.VAL; + this->clearUnusedBits(); + return *this; + } + unsigned numWords = getNumWords(); + for (unsigned i = 0; i < numWords; ++i) + pVal[i] ^= RHS.pVal[i]; + return clearUnusedBits(); +} + +APInt APInt::AndSlowCase(const APInt& RHS) const { + unsigned numWords = getNumWords(); + uint64_t* val = getMemory(numWords); + for (unsigned i = 0; i < numWords; ++i) + val[i] = pVal[i] & RHS.pVal[i]; + return APInt(val, getBitWidth()); +} + +APInt APInt::OrSlowCase(const APInt& RHS) const { + unsigned numWords = getNumWords(); + uint64_t *val = getMemory(numWords); + for (unsigned i = 0; i < numWords; ++i) + val[i] = pVal[i] | RHS.pVal[i]; + return APInt(val, getBitWidth()); +} + +APInt APInt::XorSlowCase(const APInt& RHS) const { + unsigned numWords = getNumWords(); + uint64_t *val = getMemory(numWords); + for (unsigned i = 0; i < numWords; ++i) + val[i] = pVal[i] ^ RHS.pVal[i]; + + APInt Result(val, getBitWidth()); + // 0^0==1 so clear the high bits in case they got set. + Result.clearUnusedBits(); + return Result; +} + +APInt APInt::operator*(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(BitWidth, VAL * RHS.VAL); + APInt Result(*this); + Result *= RHS; + return Result; +} + +bool APInt::EqualSlowCase(const APInt& RHS) const { + return std::equal(pVal, pVal + getNumWords(), RHS.pVal); +} + +bool APInt::EqualSlowCase(uint64_t Val) const { + unsigned n = getActiveBits(); + if (n <= APINT_BITS_PER_WORD) + return pVal[0] == Val; + else + return false; +} + +bool APInt::ult(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison"); + if (isSingleWord()) + return VAL < RHS.VAL; + + // Get active bit length of both operands + unsigned n1 = getActiveBits(); + unsigned n2 = RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS.pVal[0]; + + // Otherwise, compare all words + unsigned topWord = whichWord(std::max(n1,n2)-1); + for (int i = topWord; i >= 0; --i) { + if (pVal[i] > RHS.pVal[i]) + return false; + if (pVal[i] < RHS.pVal[i]) + return true; + } + return false; +} + +bool APInt::slt(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison"); + if (isSingleWord()) { + int64_t lhsSext = SignExtend64(VAL, BitWidth); + int64_t rhsSext = SignExtend64(RHS.VAL, BitWidth); + return lhsSext < rhsSext; + } + + bool lhsNeg = isNegative(); + bool rhsNeg = RHS.isNegative(); + + // If the sign bits don't match, then (LHS < RHS) if LHS is negative + if (lhsNeg != rhsNeg) + return lhsNeg; + + // Otherwise we can just use an unsigned comparision, because even negative + // numbers compare correctly this way if both have the same signed-ness. + return ult(RHS); +} + +void APInt::setBit(unsigned bitPosition) { + if (isSingleWord()) + VAL |= maskBit(bitPosition); + else + pVal[whichWord(bitPosition)] |= maskBit(bitPosition); +} + +/// Set the given bit to 0 whose position is given as "bitPosition". +/// @brief Set a given bit to 0. +void APInt::clearBit(unsigned bitPosition) { + if (isSingleWord()) + VAL &= ~maskBit(bitPosition); + else + pVal[whichWord(bitPosition)] &= ~maskBit(bitPosition); +} + +/// @brief Toggle every bit to its opposite value. + +/// Toggle a given bit to its opposite value whose position is given +/// as "bitPosition". +/// @brief Toggles a given bit to its opposite value. +void APInt::flipBit(unsigned bitPosition) { + assert(bitPosition < BitWidth && "Out of the bit-width range!"); + if ((*this)[bitPosition]) clearBit(bitPosition); + else setBit(bitPosition); +} + +unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) { + assert(!str.empty() && "Invalid string length"); + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2 || + radix == 36) && + "Radix should be 2, 8, 10, 16, or 36!"); + + size_t slen = str.size(); + + // Each computation below needs to know if it's negative. + StringRef::iterator p = str.begin(); + unsigned isNegative = *p == '-'; + if (*p == '-' || *p == '+') { + p++; + slen--; + assert(slen && "String is only a sign, needs a value."); + } + + // For radixes of power-of-two values, the bits required is accurately and + // easily computed + if (radix == 2) + return slen + isNegative; + if (radix == 8) + return slen * 3 + isNegative; + if (radix == 16) + return slen * 4 + isNegative; + + // FIXME: base 36 + + // This is grossly inefficient but accurate. We could probably do something + // with a computation of roughly slen*64/20 and then adjust by the value of + // the first few digits. But, I'm not sure how accurate that could be. + + // Compute a sufficient number of bits that is always large enough but might + // be too large. This avoids the assertion in the constructor. This + // calculation doesn't work appropriately for the numbers 0-9, so just use 4 + // bits in that case. + unsigned sufficient + = radix == 10? (slen == 1 ? 4 : slen * 64/18) + : (slen == 1 ? 7 : slen * 16/3); + + // Convert to the actual binary value. + APInt tmp(sufficient, StringRef(p, slen), radix); + + // Compute how many bits are required. If the log is infinite, assume we need + // just bit. + unsigned log = tmp.logBase2(); + if (log == (unsigned)-1) { + return isNegative + 1; + } else { + return isNegative + log + 1; + } +} + +hash_code llvm::hash_value(const APInt &Arg) { + if (Arg.isSingleWord()) + return hash_combine(Arg.VAL); + + return hash_combine_range(Arg.pVal, Arg.pVal + Arg.getNumWords()); +} + +bool APInt::isSplat(unsigned SplatSizeInBits) const { + assert(getBitWidth() % SplatSizeInBits == 0 && + "SplatSizeInBits must divide width!"); + // We can check that all parts of an integer are equal by making use of a + // little trick: rotate and check if it's still the same value. + return *this == rotl(SplatSizeInBits); +} + +/// This function returns the high "numBits" bits of this APInt. +APInt APInt::getHiBits(unsigned numBits) const { + return APIntOps::lshr(*this, BitWidth - numBits); +} + +/// This function returns the low "numBits" bits of this APInt. +APInt APInt::getLoBits(unsigned numBits) const { + return APIntOps::lshr(APIntOps::shl(*this, BitWidth - numBits), + BitWidth - numBits); +} + +unsigned APInt::countLeadingZerosSlowCase() const { + unsigned Count = 0; + for (int i = getNumWords()-1; i >= 0; --i) { + integerPart V = pVal[i]; + if (V == 0) + Count += APINT_BITS_PER_WORD; + else { + Count += llvm::countLeadingZeros(V); + break; + } + } + // Adjust for unused bits in the most significant word (they are zero). + unsigned Mod = BitWidth % APINT_BITS_PER_WORD; + Count -= Mod > 0 ? APINT_BITS_PER_WORD - Mod : 0; + return Count; +} + +unsigned APInt::countLeadingOnes() const { + if (isSingleWord()) + return llvm::countLeadingOnes(VAL << (APINT_BITS_PER_WORD - BitWidth)); + + unsigned highWordBits = BitWidth % APINT_BITS_PER_WORD; + unsigned shift; + if (!highWordBits) { + highWordBits = APINT_BITS_PER_WORD; + shift = 0; + } else { + shift = APINT_BITS_PER_WORD - highWordBits; + } + int i = getNumWords() - 1; + unsigned Count = llvm::countLeadingOnes(pVal[i] << shift); + if (Count == highWordBits) { + for (i--; i >= 0; --i) { + if (pVal[i] == -1ULL) + Count += APINT_BITS_PER_WORD; + else { + Count += llvm::countLeadingOnes(pVal[i]); + break; + } + } + } + return Count; +} + +unsigned APInt::countTrailingZeros() const { + if (isSingleWord()) + return std::min(unsigned(llvm::countTrailingZeros(VAL)), BitWidth); + unsigned Count = 0; + unsigned i = 0; + for (; i < getNumWords() && pVal[i] == 0; ++i) + Count += APINT_BITS_PER_WORD; + if (i < getNumWords()) + Count += llvm::countTrailingZeros(pVal[i]); + return std::min(Count, BitWidth); +} + +unsigned APInt::countTrailingOnesSlowCase() const { + unsigned Count = 0; + unsigned i = 0; + for (; i < getNumWords() && pVal[i] == -1ULL; ++i) + Count += APINT_BITS_PER_WORD; + if (i < getNumWords()) + Count += llvm::countTrailingOnes(pVal[i]); + return std::min(Count, BitWidth); +} + +unsigned APInt::countPopulationSlowCase() const { + unsigned Count = 0; + for (unsigned i = 0; i < getNumWords(); ++i) + Count += llvm::countPopulation(pVal[i]); + return Count; +} + +/// Perform a logical right-shift from Src to Dst, which must be equal or +/// non-overlapping, of Words words, by Shift, which must be less than 64. +static void lshrNear(uint64_t *Dst, uint64_t *Src, unsigned Words, + unsigned Shift) { + uint64_t Carry = 0; + for (int I = Words - 1; I >= 0; --I) { + uint64_t Tmp = Src[I]; + Dst[I] = (Tmp >> Shift) | Carry; + Carry = Tmp << (64 - Shift); + } +} + +APInt APInt::byteSwap() const { + assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!"); + if (BitWidth == 16) + return APInt(BitWidth, ByteSwap_16(uint16_t(VAL))); + if (BitWidth == 32) + return APInt(BitWidth, ByteSwap_32(unsigned(VAL))); + if (BitWidth == 48) { + unsigned Tmp1 = unsigned(VAL >> 16); + Tmp1 = ByteSwap_32(Tmp1); + uint16_t Tmp2 = uint16_t(VAL); + Tmp2 = ByteSwap_16(Tmp2); + return APInt(BitWidth, (uint64_t(Tmp2) << 32) | Tmp1); + } + if (BitWidth == 64) + return APInt(BitWidth, ByteSwap_64(VAL)); + + APInt Result(getNumWords() * APINT_BITS_PER_WORD, 0); + for (unsigned I = 0, N = getNumWords(); I != N; ++I) + Result.pVal[I] = ByteSwap_64(pVal[N - I - 1]); + if (Result.BitWidth != BitWidth) { + lshrNear(Result.pVal, Result.pVal, getNumWords(), + Result.BitWidth - BitWidth); + Result.BitWidth = BitWidth; + } + return Result; +} + +APInt APInt::reverseBits() const { + switch (BitWidth) { + case 64: + return APInt(BitWidth, llvm::reverseBits<uint64_t>(VAL)); + case 32: + return APInt(BitWidth, llvm::reverseBits<uint32_t>(VAL)); + case 16: + return APInt(BitWidth, llvm::reverseBits<uint16_t>(VAL)); + case 8: + return APInt(BitWidth, llvm::reverseBits<uint8_t>(VAL)); + default: + break; + } + + APInt Val(*this); + APInt Reversed(*this); + int S = BitWidth - 1; + + const APInt One(BitWidth, 1); + + for ((Val = Val.lshr(1)); Val != 0; (Val = Val.lshr(1))) { + Reversed <<= 1; + Reversed |= (Val & One); + --S; + } + + Reversed <<= S; + return Reversed; +} + +APInt llvm::APIntOps::GreatestCommonDivisor(const APInt& API1, + const APInt& API2) { + APInt A = API1, B = API2; + while (!!B) { + APInt T = B; + B = APIntOps::urem(A, B); + A = T; + } + return A; +} + +APInt llvm::APIntOps::RoundDoubleToAPInt(double Double, unsigned width) { + union { + double D; + uint64_t I; + } T; + T.D = Double; + + // Get the sign bit from the highest order bit + bool isNeg = T.I >> 63; + + // Get the 11-bit exponent and adjust for the 1023 bit bias + int64_t exp = ((T.I >> 52) & 0x7ff) - 1023; + + // If the exponent is negative, the value is < 0 so just return 0. + if (exp < 0) + return APInt(width, 0u); + + // Extract the mantissa by clearing the top 12 bits (sign + exponent). + uint64_t mantissa = (T.I & (~0ULL >> 12)) | 1ULL << 52; + + // If the exponent doesn't shift all bits out of the mantissa + if (exp < 52) + return isNeg ? -APInt(width, mantissa >> (52 - exp)) : + APInt(width, mantissa >> (52 - exp)); + + // If the client didn't provide enough bits for us to shift the mantissa into + // then the result is undefined, just return 0 + if (width <= exp - 52) + return APInt(width, 0); + + // Otherwise, we have to shift the mantissa bits up to the right location + APInt Tmp(width, mantissa); + Tmp = Tmp.shl((unsigned)exp - 52); + return isNeg ? -Tmp : Tmp; +} + +/// This function converts this APInt to a double. +/// The layout for double is as following (IEEE Standard 754): +/// -------------------------------------- +/// | Sign Exponent Fraction Bias | +/// |-------------------------------------- | +/// | 1[63] 11[62-52] 52[51-00] 1023 | +/// -------------------------------------- +double APInt::roundToDouble(bool isSigned) const { + + // Handle the simple case where the value is contained in one uint64_t. + // It is wrong to optimize getWord(0) to VAL; there might be more than one word. + if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) { + if (isSigned) { + int64_t sext = SignExtend64(getWord(0), BitWidth); + return double(sext); + } else + return double(getWord(0)); + } + + // Determine if the value is negative. + bool isNeg = isSigned ? (*this)[BitWidth-1] : false; + + // Construct the absolute value if we're negative. + APInt Tmp(isNeg ? -(*this) : (*this)); + + // Figure out how many bits we're using. + unsigned n = Tmp.getActiveBits(); + + // The exponent (without bias normalization) is just the number of bits + // we are using. Note that the sign bit is gone since we constructed the + // absolute value. + uint64_t exp = n; + + // Return infinity for exponent overflow + if (exp > 1023) { + if (!isSigned || !isNeg) + return std::numeric_limits<double>::infinity(); + else + return -std::numeric_limits<double>::infinity(); + } + exp += 1023; // Increment for 1023 bias + + // Number of bits in mantissa is 52. To obtain the mantissa value, we must + // extract the high 52 bits from the correct words in pVal. + uint64_t mantissa; + unsigned hiWord = whichWord(n-1); + if (hiWord == 0) { + mantissa = Tmp.pVal[0]; + if (n > 52) + mantissa >>= n - 52; // shift down, we want the top 52 bits. + } else { + assert(hiWord > 0 && "huh?"); + uint64_t hibits = Tmp.pVal[hiWord] << (52 - n % APINT_BITS_PER_WORD); + uint64_t lobits = Tmp.pVal[hiWord-1] >> (11 + n % APINT_BITS_PER_WORD); + mantissa = hibits | lobits; + } + + // The leading bit of mantissa is implicit, so get rid of it. + uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0; + union { + double D; + uint64_t I; + } T; + T.I = sign | (exp << 52) | mantissa; + return T.D; +} + +// Truncate to new width. +APInt APInt::trunc(unsigned width) const { + assert(width < BitWidth && "Invalid APInt Truncate request"); + assert(width && "Can't truncate to 0 bits"); + + if (width <= APINT_BITS_PER_WORD) + return APInt(width, getRawData()[0]); + + APInt Result(getMemory(getNumWords(width)), width); + + // Copy full words. + unsigned i; + for (i = 0; i != width / APINT_BITS_PER_WORD; i++) + Result.pVal[i] = pVal[i]; + + // Truncate and copy any partial word. + unsigned bits = (0 - width) % APINT_BITS_PER_WORD; + if (bits != 0) + Result.pVal[i] = pVal[i] << bits >> bits; + + return Result; +} + +// Sign extend to a new width. +APInt APInt::sext(unsigned width) const { + assert(width > BitWidth && "Invalid APInt SignExtend request"); + + if (width <= APINT_BITS_PER_WORD) { + uint64_t val = VAL << (APINT_BITS_PER_WORD - BitWidth); + val = (int64_t)val >> (width - BitWidth); + return APInt(width, val >> (APINT_BITS_PER_WORD - width)); + } + + APInt Result(getMemory(getNumWords(width)), width); + + // Copy full words. + unsigned i; + uint64_t word = 0; + for (i = 0; i != BitWidth / APINT_BITS_PER_WORD; i++) { + word = getRawData()[i]; + Result.pVal[i] = word; + } + + // Read and sign-extend any partial word. + unsigned bits = (0 - BitWidth) % APINT_BITS_PER_WORD; + if (bits != 0) + word = (int64_t)getRawData()[i] << bits >> bits; + else + word = (int64_t)word >> (APINT_BITS_PER_WORD - 1); + + // Write remaining full words. + for (; i != width / APINT_BITS_PER_WORD; i++) { + Result.pVal[i] = word; + word = (int64_t)word >> (APINT_BITS_PER_WORD - 1); + } + + // Write any partial word. + bits = (0 - width) % APINT_BITS_PER_WORD; + if (bits != 0) + Result.pVal[i] = word << bits >> bits; + + return Result; +} + +// Zero extend to a new width. +APInt APInt::zext(unsigned width) const { + assert(width > BitWidth && "Invalid APInt ZeroExtend request"); + + if (width <= APINT_BITS_PER_WORD) + return APInt(width, VAL); + + APInt Result(getMemory(getNumWords(width)), width); + + // Copy words. + unsigned i; + for (i = 0; i != getNumWords(); i++) + Result.pVal[i] = getRawData()[i]; + + // Zero remaining words. + memset(&Result.pVal[i], 0, (Result.getNumWords() - i) * APINT_WORD_SIZE); + + return Result; +} + +APInt APInt::zextOrTrunc(unsigned width) const { + if (BitWidth < width) + return zext(width); + if (BitWidth > width) + return trunc(width); + return *this; +} + +APInt APInt::sextOrTrunc(unsigned width) const { + if (BitWidth < width) + return sext(width); + if (BitWidth > width) + return trunc(width); + return *this; +} + +APInt APInt::zextOrSelf(unsigned width) const { + if (BitWidth < width) + return zext(width); + return *this; +} + +APInt APInt::sextOrSelf(unsigned width) const { + if (BitWidth < width) + return sext(width); + return *this; +} + +/// Arithmetic right-shift this APInt by shiftAmt. +/// @brief Arithmetic right-shift function. +APInt APInt::ashr(const APInt &shiftAmt) const { + return ashr((unsigned)shiftAmt.getLimitedValue(BitWidth)); +} + +/// Arithmetic right-shift this APInt by shiftAmt. +/// @brief Arithmetic right-shift function. +APInt APInt::ashr(unsigned shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount"); + // Handle a degenerate case + if (shiftAmt == 0) + return *this; + + // Handle single word shifts with built-in ashr + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); // undefined + return APInt(BitWidth, SignExtend64(VAL, BitWidth) >> shiftAmt); + } + + // If all the bits were shifted out, the result is, technically, undefined. + // We return -1 if it was negative, 0 otherwise. We check this early to avoid + // issues in the algorithm below. + if (shiftAmt == BitWidth) { + if (isNegative()) + return APInt(BitWidth, -1ULL, true); + else + return APInt(BitWidth, 0); + } + + // Create some space for the result. + uint64_t * val = new uint64_t[getNumWords()]; + + // Compute some values needed by the following shift algorithms + unsigned wordShift = shiftAmt % APINT_BITS_PER_WORD; // bits to shift per word + unsigned offset = shiftAmt / APINT_BITS_PER_WORD; // word offset for shift + unsigned breakWord = getNumWords() - 1 - offset; // last word affected + unsigned bitsInWord = whichBit(BitWidth); // how many bits in last word? + if (bitsInWord == 0) + bitsInWord = APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + // Move the words containing significant bits + for (unsigned i = 0; i <= breakWord; ++i) + val[i] = pVal[i+offset]; // move whole word + + // Adjust the top significant word for sign bit fill, if negative + if (isNegative()) + if (bitsInWord < APINT_BITS_PER_WORD) + val[breakWord] |= ~0ULL << bitsInWord; // set high bits + } else { + // Shift the low order words + for (unsigned i = 0; i < breakWord; ++i) { + // This combines the shifted corresponding word with the low bits from + // the next word (shifted into this word's high bits). + val[i] = (pVal[i+offset] >> wordShift) | + (pVal[i+offset+1] << (APINT_BITS_PER_WORD - wordShift)); + } + + // Shift the break word. In this case there are no bits from the next word + // to include in this word. + val[breakWord] = pVal[breakWord+offset] >> wordShift; + + // Deal with sign extension in the break word, and possibly the word before + // it. + if (isNegative()) { + if (wordShift > bitsInWord) { + if (breakWord > 0) + val[breakWord-1] |= + ~0ULL << (APINT_BITS_PER_WORD - (wordShift - bitsInWord)); + val[breakWord] |= ~0ULL; + } else + val[breakWord] |= (~0ULL << (bitsInWord - wordShift)); + } + } + + // Remaining words are 0 or -1, just assign them. + uint64_t fillValue = (isNegative() ? -1ULL : 0); + for (unsigned i = breakWord+1; i < getNumWords(); ++i) + val[i] = fillValue; + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; +} + +/// Logical right-shift this APInt by shiftAmt. +/// @brief Logical right-shift function. +APInt APInt::lshr(const APInt &shiftAmt) const { + return lshr((unsigned)shiftAmt.getLimitedValue(BitWidth)); +} + +/// Logical right-shift this APInt by shiftAmt. +/// @brief Logical right-shift function. +APInt APInt::lshr(unsigned shiftAmt) const { + if (isSingleWord()) { + if (shiftAmt >= BitWidth) + return APInt(BitWidth, 0); + else + return APInt(BitWidth, this->VAL >> shiftAmt); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt >= BitWidth) + return APInt(BitWidth, 0); + + // If none of the bits are shifted out, the result is *this. This avoids + // issues with shifting by the size of the integer type, which produces + // undefined results in the code below. This is also an optimization. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + uint64_t * val = new uint64_t[getNumWords()]; + + // If we are shifting less than a word, compute the shift with a simple carry + if (shiftAmt < APINT_BITS_PER_WORD) { + lshrNear(val, pVal, getNumWords(), shiftAmt); + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; + } + + // Compute some values needed by the remaining shift algorithms + unsigned wordShift = shiftAmt % APINT_BITS_PER_WORD; + unsigned offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (unsigned i = 0; i < getNumWords() - offset; ++i) + val[i] = pVal[i+offset]; + for (unsigned i = getNumWords()-offset; i < getNumWords(); i++) + val[i] = 0; + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; + } + + // Shift the low order words + unsigned breakWord = getNumWords() - offset -1; + for (unsigned i = 0; i < breakWord; ++i) + val[i] = (pVal[i+offset] >> wordShift) | + (pVal[i+offset+1] << (APINT_BITS_PER_WORD - wordShift)); + // Shift the break word. + val[breakWord] = pVal[breakWord+offset] >> wordShift; + + // Remaining words are 0 + for (unsigned i = breakWord+1; i < getNumWords(); ++i) + val[i] = 0; + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; +} + +/// Left-shift this APInt by shiftAmt. +/// @brief Left-shift function. +APInt APInt::shl(const APInt &shiftAmt) const { + // It's undefined behavior in C to shift by BitWidth or greater. + return shl((unsigned)shiftAmt.getLimitedValue(BitWidth)); +} + +APInt APInt::shlSlowCase(unsigned shiftAmt) const { + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); + + // If none of the bits are shifted out, the result is *this. This avoids a + // lshr by the words size in the loop below which can produce incorrect + // results. It also avoids the expensive computation below for a common case. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + uint64_t * val = new uint64_t[getNumWords()]; + + // If we are shifting less than a word, do it the easy way + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (unsigned i = 0; i < getNumWords(); i++) { + val[i] = pVal[i] << shiftAmt | carry; + carry = pVal[i] >> (APINT_BITS_PER_WORD - shiftAmt); + } + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; + } + + // Compute some values needed by the remaining shift algorithms + unsigned wordShift = shiftAmt % APINT_BITS_PER_WORD; + unsigned offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (unsigned i = 0; i < offset; i++) + val[i] = 0; + for (unsigned i = offset; i < getNumWords(); i++) + val[i] = pVal[i-offset]; + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; + } + + // Copy whole words from this to Result. + unsigned i = getNumWords() - 1; + for (; i > offset; --i) + val[i] = pVal[i-offset] << wordShift | + pVal[i-offset-1] >> (APINT_BITS_PER_WORD - wordShift); + val[offset] = pVal[0] << wordShift; + for (i = 0; i < offset; ++i) + val[i] = 0; + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; +} + +APInt APInt::rotl(const APInt &rotateAmt) const { + return rotl((unsigned)rotateAmt.getLimitedValue(BitWidth)); +} + +APInt APInt::rotl(unsigned rotateAmt) const { + rotateAmt %= BitWidth; + if (rotateAmt == 0) + return *this; + return shl(rotateAmt) | lshr(BitWidth - rotateAmt); +} + +APInt APInt::rotr(const APInt &rotateAmt) const { + return rotr((unsigned)rotateAmt.getLimitedValue(BitWidth)); +} + +APInt APInt::rotr(unsigned rotateAmt) const { + rotateAmt %= BitWidth; + if (rotateAmt == 0) + return *this; + return lshr(rotateAmt) | shl(BitWidth - rotateAmt); +} + +// Square Root - this method computes and returns the square root of "this". +// Three mechanisms are used for computation. For small values (<= 5 bits), +// a table lookup is done. This gets some performance for common cases. For +// values using less than 52 bits, the value is converted to double and then +// the libc sqrt function is called. The result is rounded and then converted +// back to a uint64_t which is then used to construct the result. Finally, +// the Babylonian method for computing square roots is used. +APInt APInt::sqrt() const { + + // Determine the magnitude of the value. + unsigned magnitude = getActiveBits(); + + // Use a fast table for some small values. This also gets rid of some + // rounding errors in libc sqrt for small values. + if (magnitude <= 5) { + static const uint8_t results[32] = { + /* 0 */ 0, + /* 1- 2 */ 1, 1, + /* 3- 6 */ 2, 2, 2, 2, + /* 7-12 */ 3, 3, 3, 3, 3, 3, + /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4, + /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + /* 31 */ 6 + }; + return APInt(BitWidth, results[ (isSingleWord() ? VAL : pVal[0]) ]); + } + + // If the magnitude of the value fits in less than 52 bits (the precision of + // an IEEE double precision floating point value), then we can use the + // libc sqrt function which will probably use a hardware sqrt computation. + // This should be faster than the algorithm below. + if (magnitude < 52) { + return APInt(BitWidth, + uint64_t(::round(::sqrt(double(isSingleWord()?VAL:pVal[0]))))); + } + + // Okay, all the short cuts are exhausted. We must compute it. The following + // is a classical Babylonian method for computing the square root. This code + // was adapted to APInt from a wikipedia article on such computations. + // See http://www.wikipedia.org/ and go to the page named + // Calculate_an_integer_square_root. + unsigned nbits = BitWidth, i = 4; + APInt testy(BitWidth, 16); + APInt x_old(BitWidth, 1); + APInt x_new(BitWidth, 0); + APInt two(BitWidth, 2); + + // Select a good starting value using binary logarithms. + for (;; i += 2, testy = testy.shl(2)) + if (i >= nbits || this->ule(testy)) { + x_old = x_old.shl(i / 2); + break; + } + + // Use the Babylonian method to arrive at the integer square root: + for (;;) { + x_new = (this->udiv(x_old) + x_old).udiv(two); + if (x_old.ule(x_new)) + break; + x_old = x_new; + } + + // Make sure we return the closest approximation + // NOTE: The rounding calculation below is correct. It will produce an + // off-by-one discrepancy with results from pari/gp. That discrepancy has been + // determined to be a rounding issue with pari/gp as it begins to use a + // floating point representation after 192 bits. There are no discrepancies + // between this algorithm and pari/gp for bit widths < 192 bits. + APInt square(x_old * x_old); + APInt nextSquare((x_old + 1) * (x_old +1)); + if (this->ult(square)) + return x_old; + assert(this->ule(nextSquare) && "Error in APInt::sqrt computation"); + APInt midpoint((nextSquare - square).udiv(two)); + APInt offset(*this - square); + if (offset.ult(midpoint)) + return x_old; + return x_old + 1; +} + +/// Computes the multiplicative inverse of this APInt for a given modulo. The +/// iterative extended Euclidean algorithm is used to solve for this value, +/// however we simplify it to speed up calculating only the inverse, and take +/// advantage of div+rem calculations. We also use some tricks to avoid copying +/// (potentially large) APInts around. +APInt APInt::multiplicativeInverse(const APInt& modulo) const { + assert(ult(modulo) && "This APInt must be smaller than the modulo"); + + // Using the properties listed at the following web page (accessed 06/21/08): + // http://www.numbertheory.org/php/euclid.html + // (especially the properties numbered 3, 4 and 9) it can be proved that + // BitWidth bits suffice for all the computations in the algorithm implemented + // below. More precisely, this number of bits suffice if the multiplicative + // inverse exists, but may not suffice for the general extended Euclidean + // algorithm. + + APInt r[2] = { modulo, *this }; + APInt t[2] = { APInt(BitWidth, 0), APInt(BitWidth, 1) }; + APInt q(BitWidth, 0); + + unsigned i; + for (i = 0; r[i^1] != 0; i ^= 1) { + // An overview of the math without the confusing bit-flipping: + // q = r[i-2] / r[i-1] + // r[i] = r[i-2] % r[i-1] + // t[i] = t[i-2] - t[i-1] * q + udivrem(r[i], r[i^1], q, r[i]); + t[i] -= t[i^1] * q; + } + + // If this APInt and the modulo are not coprime, there is no multiplicative + // inverse, so return 0. We check this by looking at the next-to-last + // remainder, which is the gcd(*this,modulo) as calculated by the Euclidean + // algorithm. + if (r[i] != 1) + return APInt(BitWidth, 0); + + // The next-to-last t is the multiplicative inverse. However, we are + // interested in a positive inverse. Calcuate a positive one from a negative + // one if necessary. A simple addition of the modulo suffices because + // abs(t[i]) is known to be less than *this/2 (see the link above). + return t[i].isNegative() ? t[i] + modulo : t[i]; +} + +/// Calculate the magic numbers required to implement a signed integer division +/// by a constant as a sequence of multiplies, adds and shifts. Requires that +/// the divisor not be 0, 1, or -1. Taken from "Hacker's Delight", Henry S. +/// Warren, Jr., chapter 10. +APInt::ms APInt::magic() const { + const APInt& d = *this; + unsigned p; + APInt ad, anc, delta, q1, r1, q2, r2, t; + APInt signedMin = APInt::getSignedMinValue(d.getBitWidth()); + struct ms mag; + + ad = d.abs(); + t = signedMin + (d.lshr(d.getBitWidth() - 1)); + anc = t - 1 - t.urem(ad); // absolute value of nc + p = d.getBitWidth() - 1; // initialize p + q1 = signedMin.udiv(anc); // initialize q1 = 2p/abs(nc) + r1 = signedMin - q1*anc; // initialize r1 = rem(2p,abs(nc)) + q2 = signedMin.udiv(ad); // initialize q2 = 2p/abs(d) + r2 = signedMin - q2*ad; // initialize r2 = rem(2p,abs(d)) + do { + p = p + 1; + q1 = q1<<1; // update q1 = 2p/abs(nc) + r1 = r1<<1; // update r1 = rem(2p/abs(nc)) + if (r1.uge(anc)) { // must be unsigned comparison + q1 = q1 + 1; + r1 = r1 - anc; + } + q2 = q2<<1; // update q2 = 2p/abs(d) + r2 = r2<<1; // update r2 = rem(2p/abs(d)) + if (r2.uge(ad)) { // must be unsigned comparison + q2 = q2 + 1; + r2 = r2 - ad; + } + delta = ad - r2; + } while (q1.ult(delta) || (q1 == delta && r1 == 0)); + + mag.m = q2 + 1; + if (d.isNegative()) mag.m = -mag.m; // resulting magic number + mag.s = p - d.getBitWidth(); // resulting shift + return mag; +} + +/// Calculate the magic numbers required to implement an unsigned integer +/// division by a constant as a sequence of multiplies, adds and shifts. +/// Requires that the divisor not be 0. Taken from "Hacker's Delight", Henry +/// S. Warren, Jr., chapter 10. +/// LeadingZeros can be used to simplify the calculation if the upper bits +/// of the divided value are known zero. +APInt::mu APInt::magicu(unsigned LeadingZeros) const { + const APInt& d = *this; + unsigned p; + APInt nc, delta, q1, r1, q2, r2; + struct mu magu; + magu.a = 0; // initialize "add" indicator + APInt allOnes = APInt::getAllOnesValue(d.getBitWidth()).lshr(LeadingZeros); + APInt signedMin = APInt::getSignedMinValue(d.getBitWidth()); + APInt signedMax = APInt::getSignedMaxValue(d.getBitWidth()); + + nc = allOnes - (allOnes - d).urem(d); + p = d.getBitWidth() - 1; // initialize p + q1 = signedMin.udiv(nc); // initialize q1 = 2p/nc + r1 = signedMin - q1*nc; // initialize r1 = rem(2p,nc) + q2 = signedMax.udiv(d); // initialize q2 = (2p-1)/d + r2 = signedMax - q2*d; // initialize r2 = rem((2p-1),d) + do { + p = p + 1; + if (r1.uge(nc - r1)) { + q1 = q1 + q1 + 1; // update q1 + r1 = r1 + r1 - nc; // update r1 + } + else { + q1 = q1+q1; // update q1 + r1 = r1+r1; // update r1 + } + if ((r2 + 1).uge(d - r2)) { + if (q2.uge(signedMax)) magu.a = 1; + q2 = q2+q2 + 1; // update q2 + r2 = r2+r2 + 1 - d; // update r2 + } + else { + if (q2.uge(signedMin)) magu.a = 1; + q2 = q2+q2; // update q2 + r2 = r2+r2 + 1; // update r2 + } + delta = d - 1 - r2; + } while (p < d.getBitWidth()*2 && + (q1.ult(delta) || (q1 == delta && r1 == 0))); + magu.m = q2 + 1; // resulting magic number + magu.s = p - d.getBitWidth(); // resulting shift + return magu; +} + +/// Implementation of Knuth's Algorithm D (Division of nonnegative integers) +/// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The +/// variables here have the same names as in the algorithm. Comments explain +/// the algorithm and any deviation from it. +static void KnuthDiv(unsigned *u, unsigned *v, unsigned *q, unsigned* r, + unsigned m, unsigned n) { + assert(u && "Must provide dividend"); + assert(v && "Must provide divisor"); + assert(q && "Must provide quotient"); + assert(u != v && u != q && v != q && "Must use different memory"); + assert(n>1 && "n must be > 1"); + + // b denotes the base of the number system. In our case b is 2^32. + const uint64_t b = uint64_t(1) << 32; + + DEBUG(dbgs() << "KnuthDiv: m=" << m << " n=" << n << '\n'); + DEBUG(dbgs() << "KnuthDiv: original:"); + DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]); + DEBUG(dbgs() << " by"); + DEBUG(for (int i = n; i >0; i--) dbgs() << " " << v[i-1]); + DEBUG(dbgs() << '\n'); + // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of + // u and v by d. Note that we have taken Knuth's advice here to use a power + // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of + // 2 allows us to shift instead of multiply and it is easy to determine the + // shift amount from the leading zeros. We are basically normalizing the u + // and v so that its high bits are shifted to the top of v's range without + // overflow. Note that this can require an extra word in u so that u must + // be of length m+n+1. + unsigned shift = countLeadingZeros(v[n-1]); + unsigned v_carry = 0; + unsigned u_carry = 0; + if (shift) { + for (unsigned i = 0; i < m+n; ++i) { + unsigned u_tmp = u[i] >> (32 - shift); + u[i] = (u[i] << shift) | u_carry; + u_carry = u_tmp; + } + for (unsigned i = 0; i < n; ++i) { + unsigned v_tmp = v[i] >> (32 - shift); + v[i] = (v[i] << shift) | v_carry; + v_carry = v_tmp; + } + } + u[m+n] = u_carry; + + DEBUG(dbgs() << "KnuthDiv: normal:"); + DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]); + DEBUG(dbgs() << " by"); + DEBUG(for (int i = n; i >0; i--) dbgs() << " " << v[i-1]); + DEBUG(dbgs() << '\n'); + + // D2. [Initialize j.] Set j to m. This is the loop counter over the places. + int j = m; + do { + DEBUG(dbgs() << "KnuthDiv: quotient digit #" << j << '\n'); + // D3. [Calculate q'.]. + // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q') + // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r') + // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease + // qp by 1, inrease rp by v[n-1], and repeat this test if rp < b. The test + // on v[n-2] determines at high speed most of the cases in which the trial + // value qp is one too large, and it eliminates all cases where qp is two + // too large. + uint64_t dividend = ((uint64_t(u[j+n]) << 32) + u[j+n-1]); + DEBUG(dbgs() << "KnuthDiv: dividend == " << dividend << '\n'); + uint64_t qp = dividend / v[n-1]; + uint64_t rp = dividend % v[n-1]; + if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) { + qp--; + rp += v[n-1]; + if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2])) + qp--; + } + DEBUG(dbgs() << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n'); + + // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with + // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation + // consists of a simple multiplication by a one-place number, combined with + // a subtraction. + // The digits (u[j+n]...u[j]) should be kept positive; if the result of + // this step is actually negative, (u[j+n]...u[j]) should be left as the + // true value plus b**(n+1), namely as the b's complement of + // the true value, and a "borrow" to the left should be remembered. + int64_t borrow = 0; + for (unsigned i = 0; i < n; ++i) { + uint64_t p = uint64_t(qp) * uint64_t(v[i]); + int64_t subres = int64_t(u[j+i]) - borrow - (unsigned)p; + u[j+i] = (unsigned)subres; + borrow = (p >> 32) - (subres >> 32); + DEBUG(dbgs() << "KnuthDiv: u[j+i] = " << u[j+i] + << ", borrow = " << borrow << '\n'); + } + bool isNeg = u[j+n] < borrow; + u[j+n] -= (unsigned)borrow; + + DEBUG(dbgs() << "KnuthDiv: after subtraction:"); + DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]); + DEBUG(dbgs() << '\n'); + + // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was + // negative, go to step D6; otherwise go on to step D7. + q[j] = (unsigned)qp; + if (isNeg) { + // D6. [Add back]. The probability that this step is necessary is very + // small, on the order of only 2/b. Make sure that test data accounts for + // this possibility. Decrease q[j] by 1 + q[j]--; + // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]). + // A carry will occur to the left of u[j+n], and it should be ignored + // since it cancels with the borrow that occurred in D4. + bool carry = false; + for (unsigned i = 0; i < n; i++) { + unsigned limit = std::min(u[j+i],v[i]); + u[j+i] += v[i] + carry; + carry = u[j+i] < limit || (carry && u[j+i] == limit); + } + u[j+n] += carry; + } + DEBUG(dbgs() << "KnuthDiv: after correction:"); + DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]); + DEBUG(dbgs() << "\nKnuthDiv: digit result = " << q[j] << '\n'); + + // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3. + } while (--j >= 0); + + DEBUG(dbgs() << "KnuthDiv: quotient:"); + DEBUG(for (int i = m; i >=0; i--) dbgs() <<" " << q[i]); + DEBUG(dbgs() << '\n'); + + // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired + // remainder may be obtained by dividing u[...] by d. If r is non-null we + // compute the remainder (urem uses this). + if (r) { + // The value d is expressed by the "shift" value above since we avoided + // multiplication by d by using a shift left. So, all we have to do is + // shift right here. In order to mak + if (shift) { + unsigned carry = 0; + DEBUG(dbgs() << "KnuthDiv: remainder:"); + for (int i = n-1; i >= 0; i--) { + r[i] = (u[i] >> shift) | carry; + carry = u[i] << (32 - shift); + DEBUG(dbgs() << " " << r[i]); + } + } else { + for (int i = n-1; i >= 0; i--) { + r[i] = u[i]; + DEBUG(dbgs() << " " << r[i]); + } + } + DEBUG(dbgs() << '\n'); + } + DEBUG(dbgs() << '\n'); +} + +void APInt::divide(const APInt &LHS, unsigned lhsWords, const APInt &RHS, + unsigned rhsWords, APInt *Quotient, APInt *Remainder) { + assert(lhsWords >= rhsWords && "Fractional result"); + + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthermore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(unsigned)*CHAR_BIT); + unsigned n = rhsWords * 2; + unsigned m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + unsigned SPACE[128]; + unsigned *U = nullptr; + unsigned *V = nullptr; + unsigned *Q = nullptr; + unsigned *R = nullptr; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + U = &SPACE[0]; + V = &SPACE[m+n+1]; + Q = &SPACE[(m+n+1) + n]; + if (Remainder) + R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + U = new unsigned[m + n + 1]; + V = new unsigned[n]; + Q = new unsigned[m+n]; + if (Remainder) + R = new unsigned[n]; + } + + // Initialize the dividend + memset(U, 0, (m+n+1)*sizeof(unsigned)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + U[i * 2] = (unsigned)(tmp & mask); + U[i * 2 + 1] = (unsigned)(tmp >> (sizeof(unsigned)*CHAR_BIT)); + } + U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(V, 0, (n)*sizeof(unsigned)); + for (unsigned i = 0; i < rhsWords; ++i) { + uint64_t tmp = (RHS.getNumWords() == 1 ? RHS.VAL : RHS.pVal[i]); + V[i * 2] = (unsigned)(tmp & mask); + V[i * 2 + 1] = (unsigned)(tmp >> (sizeof(unsigned)*CHAR_BIT)); + } + + // initialize the quotient and remainder + memset(Q, 0, (m+n) * sizeof(unsigned)); + if (Remainder) + memset(R, 0, n * sizeof(unsigned)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + unsigned divisor = V[0]; + unsigned remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = uint64_t(remainder) << 32 | U[i]; + if (partial_dividend == 0) { + Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + Q[i] = 0; + remainder = (unsigned)partial_dividend; + } else if (partial_dividend == divisor) { + Q[i] = 1; + remainder = 0; + } else { + Q[i] = (unsigned)(partial_dividend / divisor); + remainder = (unsigned)(partial_dividend - (Q[i] * divisor)); + } + } + if (R) + R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(U, V, Q, R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + else + delete [] Quotient->pVal; + Quotient->BitWidth = LHS.BitWidth; + if (!Quotient->isSingleWord()) + Quotient->pVal = getClearedMemory(Quotient->getNumWords()); + } else + Quotient->clearAllBits(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + // This case is currently dead as all users of divide() handle trivial cases + // earlier. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(Q[0]) | (uint64_t(Q[1]) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient APInt not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(Q[i*2]) | (uint64_t(Q[i*2+1]) << (APINT_BITS_PER_WORD / 2)); + } + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != RHS.BitWidth) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + else + delete [] Remainder->pVal; + Remainder->BitWidth = RHS.BitWidth; + if (!Remainder->isSingleWord()) + Remainder->pVal = getClearedMemory(Remainder->getNumWords()); + } else + Remainder->clearAllBits(); + + // The remainder is in R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(R[0]) | (uint64_t(R[1]) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder APInt not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(R[i*2]) | (uint64_t(R[i*2+1]) << (APINT_BITS_PER_WORD / 2)); + } + } + + // Clean up the memory we allocated. + if (U != &SPACE[0]) { + delete [] U; + delete [] V; + delete [] Q; + delete [] R; + } +} + +APInt APInt::udiv(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + + // First, deal with the easy case + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Divide by zero?"); + return APInt(BitWidth, VAL / RHS.VAL); + } + + // Get some facts about the LHS and RHS number of bits and words + unsigned rhsBits = RHS.getActiveBits(); + unsigned rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Divided by zero???"); + unsigned lhsBits = this->getActiveBits(); + unsigned lhsWords = !lhsBits ? 0 : (APInt::whichWord(lhsBits - 1) + 1); + + // Deal with some degenerate cases + if (!lhsWords) + // 0 / X ===> 0 + return APInt(BitWidth, 0); + else if (lhsWords < rhsWords || this->ult(RHS)) { + // X / Y ===> 0, iff X < Y + return APInt(BitWidth, 0); + } else if (*this == RHS) { + // X / X ===> 1 + return APInt(BitWidth, 1); + } else if (lhsWords == 1 && rhsWords == 1) { + // All high words are zero, just use native divide + return APInt(BitWidth, this->pVal[0] / RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + APInt Quotient(1,0); // to hold result. + divide(*this, lhsWords, RHS, rhsWords, &Quotient, nullptr); + return Quotient; +} + +APInt APInt::sdiv(const APInt &RHS) const { + if (isNegative()) { + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + return -((-(*this)).udiv(RHS)); + } + if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); +} + +APInt APInt::urem(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Remainder by zero?"); + return APInt(BitWidth, VAL % RHS.VAL); + } + + // Get some facts about the LHS + unsigned lhsBits = getActiveBits(); + unsigned lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Get some facts about the RHS + unsigned rhsBits = RHS.getActiveBits(); + unsigned rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return APInt(BitWidth, 0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return APInt(BitWidth, 0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return APInt(BitWidth, pVal[0] % RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + APInt Remainder(1,0); + divide(*this, lhsWords, RHS, rhsWords, nullptr, &Remainder); + return Remainder; +} + +APInt APInt::srem(const APInt &RHS) const { + if (isNegative()) { + if (RHS.isNegative()) + return -((-(*this)).urem(-RHS)); + return -((-(*this)).urem(RHS)); + } + if (RHS.isNegative()) + return this->urem(-RHS); + return this->urem(RHS); +} + +void APInt::udivrem(const APInt &LHS, const APInt &RHS, + APInt &Quotient, APInt &Remainder) { + assert(LHS.BitWidth == RHS.BitWidth && "Bit widths must be the same"); + + // First, deal with the easy case + if (LHS.isSingleWord()) { + assert(RHS.VAL != 0 && "Divide by zero?"); + uint64_t QuotVal = LHS.VAL / RHS.VAL; + uint64_t RemVal = LHS.VAL % RHS.VAL; + Quotient = APInt(LHS.BitWidth, QuotVal); + Remainder = APInt(LHS.BitWidth, RemVal); + return; + } + + // Get some size facts about the dividend and divisor + unsigned lhsBits = LHS.getActiveBits(); + unsigned lhsWords = !lhsBits ? 0 : (APInt::whichWord(lhsBits - 1) + 1); + unsigned rhsBits = RHS.getActiveBits(); + unsigned rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1); + + // Check the degenerate cases + if (lhsWords == 0) { + Quotient = 0; // 0 / Y ===> 0 + Remainder = 0; // 0 % Y ===> 0 + return; + } + + if (lhsWords < rhsWords || LHS.ult(RHS)) { + Remainder = LHS; // X % Y ===> X, iff X < Y + Quotient = 0; // X / Y ===> 0, iff X < Y + return; + } + + if (LHS == RHS) { + Quotient = 1; // X / X ===> 1 + Remainder = 0; // X % X ===> 0; + return; + } + + if (lhsWords == 1 && rhsWords == 1) { + // There is only one word to consider so use the native versions. + uint64_t lhsValue = LHS.isSingleWord() ? LHS.VAL : LHS.pVal[0]; + uint64_t rhsValue = RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0]; + Quotient = APInt(LHS.getBitWidth(), lhsValue / rhsValue); + Remainder = APInt(LHS.getBitWidth(), lhsValue % rhsValue); + return; + } + + // Okay, lets do it the long way + divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder); +} + +void APInt::sdivrem(const APInt &LHS, const APInt &RHS, + APInt &Quotient, APInt &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + APInt::udivrem(-LHS, -RHS, Quotient, Remainder); + else { + APInt::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + } + Remainder = -Remainder; + } else if (RHS.isNegative()) { + APInt::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + APInt::udivrem(LHS, RHS, Quotient, Remainder); + } +} + +APInt APInt::sadd_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this+RHS; + Overflow = isNonNegative() == RHS.isNonNegative() && + Res.isNonNegative() != isNonNegative(); + return Res; +} + +APInt APInt::uadd_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this+RHS; + Overflow = Res.ult(RHS); + return Res; +} + +APInt APInt::ssub_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this - RHS; + Overflow = isNonNegative() != RHS.isNonNegative() && + Res.isNonNegative() != isNonNegative(); + return Res; +} + +APInt APInt::usub_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this-RHS; + Overflow = Res.ugt(*this); + return Res; +} + +APInt APInt::sdiv_ov(const APInt &RHS, bool &Overflow) const { + // MININT/-1 --> overflow. + Overflow = isMinSignedValue() && RHS.isAllOnesValue(); + return sdiv(RHS); +} + +APInt APInt::smul_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this * RHS; + + if (*this != 0 && RHS != 0) + Overflow = Res.sdiv(RHS) != *this || Res.sdiv(*this) != RHS; + else + Overflow = false; + return Res; +} + +APInt APInt::umul_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this * RHS; + + if (*this != 0 && RHS != 0) + Overflow = Res.udiv(RHS) != *this || Res.udiv(*this) != RHS; + else + Overflow = false; + return Res; +} + +APInt APInt::sshl_ov(const APInt &ShAmt, bool &Overflow) const { + Overflow = ShAmt.uge(getBitWidth()); + if (Overflow) + return APInt(BitWidth, 0); + + if (isNonNegative()) // Don't allow sign change. + Overflow = ShAmt.uge(countLeadingZeros()); + else + Overflow = ShAmt.uge(countLeadingOnes()); + + return *this << ShAmt; +} + +APInt APInt::ushl_ov(const APInt &ShAmt, bool &Overflow) const { + Overflow = ShAmt.uge(getBitWidth()); + if (Overflow) + return APInt(BitWidth, 0); + + Overflow = ShAmt.ugt(countLeadingZeros()); + + return *this << ShAmt; +} + + + + +void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) { + // Check our assumptions here + assert(!str.empty() && "Invalid string length"); + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2 || + radix == 36) && + "Radix should be 2, 8, 10, 16, or 36!"); + + StringRef::iterator p = str.begin(); + size_t slen = str.size(); + bool isNeg = *p == '-'; + if (*p == '-' || *p == '+') { + p++; + slen--; + assert(slen && "String is only a sign, needs a value."); + } + assert((slen <= numbits || radix != 2) && "Insufficient bit width"); + assert(((slen-1)*3 <= numbits || radix != 8) && "Insufficient bit width"); + assert(((slen-1)*4 <= numbits || radix != 16) && "Insufficient bit width"); + assert((((slen-1)*64)/22 <= numbits || radix != 10) && + "Insufficient bit width"); + + // Allocate memory + if (!isSingleWord()) + pVal = getClearedMemory(getNumWords()); + + // Figure out if we can shift instead of multiply + unsigned shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0); + + // Set up an APInt for the digit to add outside the loop so we don't + // constantly construct/destruct it. + APInt apdigit(getBitWidth(), 0); + APInt apradix(getBitWidth(), radix); + + // Enter digit traversal loop + for (StringRef::iterator e = str.end(); p != e; ++p) { + unsigned digit = getDigit(*p, radix); + assert(digit < radix && "Invalid character in digit string"); + + // Shift or multiply the value by the radix + if (slen > 1) { + if (shift) + *this <<= shift; + else + *this *= apradix; + } + + // Add in the digit we just interpreted + if (apdigit.isSingleWord()) + apdigit.VAL = digit; + else + apdigit.pVal[0] = digit; + *this += apdigit; + } + // If its negative, put it in two's complement form + if (isNeg) { + --(*this); + this->flipAllBits(); + } +} + +void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, + bool Signed, bool formatAsCLiteral) const { + assert((Radix == 10 || Radix == 8 || Radix == 16 || Radix == 2 || + Radix == 36) && + "Radix should be 2, 8, 10, 16, or 36!"); + + const char *Prefix = ""; + if (formatAsCLiteral) { + switch (Radix) { + case 2: + // Binary literals are a non-standard extension added in gcc 4.3: + // http://gcc.gnu.org/onlinedocs/gcc-4.3.0/gcc/Binary-constants.html + Prefix = "0b"; + break; + case 8: + Prefix = "0"; + break; + case 10: + break; // No prefix + case 16: + Prefix = "0x"; + break; + default: + llvm_unreachable("Invalid radix!"); + } + } + + // First, check for a zero value and just short circuit the logic below. + if (*this == 0) { + while (*Prefix) { + Str.push_back(*Prefix); + ++Prefix; + }; + Str.push_back('0'); + return; + } + + static const char Digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + if (isSingleWord()) { + char Buffer[65]; + char *BufPtr = Buffer+65; + + uint64_t N; + if (!Signed) { + N = getZExtValue(); + } else { + int64_t I = getSExtValue(); + if (I >= 0) { + N = I; + } else { + Str.push_back('-'); + N = -(uint64_t)I; + } + } + + while (*Prefix) { + Str.push_back(*Prefix); + ++Prefix; + }; + + while (N) { + *--BufPtr = Digits[N % Radix]; + N /= Radix; + } + Str.append(BufPtr, Buffer+65); + return; + } + + APInt Tmp(*this); + + if (Signed && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + Tmp.flipAllBits(); + ++Tmp; + Str.push_back('-'); + } + + while (*Prefix) { + Str.push_back(*Prefix); + ++Prefix; + }; + + // We insert the digits backward, then reverse them to get the right order. + unsigned StartDig = Str.size(); + + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1, 3 and 4 respectively) divides + // equaly. We just shift until the value is zero. + if (Radix == 2 || Radix == 8 || Radix == 16) { + // Just shift tmp right for each digit width until it becomes zero + unsigned ShiftAmt = (Radix == 16 ? 4 : (Radix == 8 ? 3 : 1)); + unsigned MaskAmt = Radix - 1; + + while (Tmp != 0) { + unsigned Digit = unsigned(Tmp.getRawData()[0]) & MaskAmt; + Str.push_back(Digits[Digit]); + Tmp = Tmp.lshr(ShiftAmt); + } + } else { + APInt divisor(Radix == 10? 4 : 8, Radix); + while (Tmp != 0) { + APInt APdigit(1, 0); + APInt tmp2(Tmp.getBitWidth(), 0); + divide(Tmp, Tmp.getNumWords(), divisor, divisor.getNumWords(), &tmp2, + &APdigit); + unsigned Digit = (unsigned)APdigit.getZExtValue(); + assert(Digit < Radix && "divide failed"); + Str.push_back(Digits[Digit]); + Tmp = tmp2; + } + } + + // Reverse the digits before returning. + std::reverse(Str.begin()+StartDig, Str.end()); +} + +/// Returns the APInt as a std::string. Note that this is an inefficient method. +/// It is better to pass in a SmallVector/SmallString to the methods above. +std::string APInt::toString(unsigned Radix = 10, bool Signed = true) const { + SmallString<40> S; + toString(S, Radix, Signed, /* formatAsCLiteral = */false); + return S.str(); +} + + +LLVM_DUMP_METHOD void APInt::dump() const { + SmallString<40> S, U; + this->toStringUnsigned(U); + this->toStringSigned(S); + dbgs() << "APInt(" << BitWidth << "b, " + << U << "u " << S << "s)"; +} + +void APInt::print(raw_ostream &OS, bool isSigned) const { + SmallString<40> S; + this->toString(S, 10, isSigned, /* formatAsCLiteral = */false); + OS << S; +} + +// This implements a variety of operations on a representation of +// arbitrary precision, two's-complement, bignum integer values. + +// Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe +// and unrestricting assumption. +static_assert(integerPartWidth % 2 == 0, "Part width must be divisible by 2!"); + +/* Some handy functions local to this file. */ +namespace { + + /* Returns the integer part with the least significant BITS set. + BITS cannot be zero. */ + static inline integerPart + lowBitMask(unsigned int bits) + { + assert(bits != 0 && bits <= integerPartWidth); + + return ~(integerPart) 0 >> (integerPartWidth - bits); + } + + /* Returns the value of the lower half of PART. */ + static inline integerPart + lowHalf(integerPart part) + { + return part & lowBitMask(integerPartWidth / 2); + } + + /* Returns the value of the upper half of PART. */ + static inline integerPart + highHalf(integerPart part) + { + return part >> (integerPartWidth / 2); + } + + /* Returns the bit number of the most significant set bit of a part. + If the input number has no bits set -1U is returned. */ + static unsigned int + partMSB(integerPart value) + { + return findLastSet(value, ZB_Max); + } + + /* Returns the bit number of the least significant set bit of a + part. If the input number has no bits set -1U is returned. */ + static unsigned int + partLSB(integerPart value) + { + return findFirstSet(value, ZB_Max); + } +} + +/* Sets the least significant part of a bignum to the input value, and + zeroes out higher parts. */ +void +APInt::tcSet(integerPart *dst, integerPart part, unsigned int parts) +{ + unsigned int i; + + assert(parts > 0); + + dst[0] = part; + for (i = 1; i < parts; i++) + dst[i] = 0; +} + +/* Assign one bignum to another. */ +void +APInt::tcAssign(integerPart *dst, const integerPart *src, unsigned int parts) +{ + unsigned int i; + + for (i = 0; i < parts; i++) + dst[i] = src[i]; +} + +/* Returns true if a bignum is zero, false otherwise. */ +bool +APInt::tcIsZero(const integerPart *src, unsigned int parts) +{ + unsigned int i; + + for (i = 0; i < parts; i++) + if (src[i]) + return false; + + return true; +} + +/* Extract the given bit of a bignum; returns 0 or 1. */ +int +APInt::tcExtractBit(const integerPart *parts, unsigned int bit) +{ + return (parts[bit / integerPartWidth] & + ((integerPart) 1 << bit % integerPartWidth)) != 0; +} + +/* Set the given bit of a bignum. */ +void +APInt::tcSetBit(integerPart *parts, unsigned int bit) +{ + parts[bit / integerPartWidth] |= (integerPart) 1 << (bit % integerPartWidth); +} + +/* Clears the given bit of a bignum. */ +void +APInt::tcClearBit(integerPart *parts, unsigned int bit) +{ + parts[bit / integerPartWidth] &= + ~((integerPart) 1 << (bit % integerPartWidth)); +} + +/* Returns the bit number of the least significant set bit of a + number. If the input number has no bits set -1U is returned. */ +unsigned int +APInt::tcLSB(const integerPart *parts, unsigned int n) +{ + unsigned int i, lsb; + + for (i = 0; i < n; i++) { + if (parts[i] != 0) { + lsb = partLSB(parts[i]); + + return lsb + i * integerPartWidth; + } + } + + return -1U; +} + +/* Returns the bit number of the most significant set bit of a number. + If the input number has no bits set -1U is returned. */ +unsigned int +APInt::tcMSB(const integerPart *parts, unsigned int n) +{ + unsigned int msb; + + do { + --n; + + if (parts[n] != 0) { + msb = partMSB(parts[n]); + + return msb + n * integerPartWidth; + } + } while (n); + + return -1U; +} + +/* Copy the bit vector of width srcBITS from SRC, starting at bit + srcLSB, to DST, of dstCOUNT parts, such that the bit srcLSB becomes + the least significant bit of DST. All high bits above srcBITS in + DST are zero-filled. */ +void +APInt::tcExtract(integerPart *dst, unsigned int dstCount,const integerPart *src, + unsigned int srcBits, unsigned int srcLSB) +{ + unsigned int firstSrcPart, dstParts, shift, n; + + dstParts = (srcBits + integerPartWidth - 1) / integerPartWidth; + assert(dstParts <= dstCount); + + firstSrcPart = srcLSB / integerPartWidth; + tcAssign (dst, src + firstSrcPart, dstParts); + + shift = srcLSB % integerPartWidth; + tcShiftRight (dst, dstParts, shift); + + /* We now have (dstParts * integerPartWidth - shift) bits from SRC + in DST. If this is less that srcBits, append the rest, else + clear the high bits. */ + n = dstParts * integerPartWidth - shift; + if (n < srcBits) { + integerPart mask = lowBitMask (srcBits - n); + dst[dstParts - 1] |= ((src[firstSrcPart + dstParts] & mask) + << n % integerPartWidth); + } else if (n > srcBits) { + if (srcBits % integerPartWidth) + dst[dstParts - 1] &= lowBitMask (srcBits % integerPartWidth); + } + + /* Clear high parts. */ + while (dstParts < dstCount) + dst[dstParts++] = 0; +} + +/* DST += RHS + C where C is zero or one. Returns the carry flag. */ +integerPart +APInt::tcAdd(integerPart *dst, const integerPart *rhs, + integerPart c, unsigned int parts) +{ + unsigned int i; + + assert(c <= 1); + + for (i = 0; i < parts; i++) { + integerPart l; + + l = dst[i]; + if (c) { + dst[i] += rhs[i] + 1; + c = (dst[i] <= l); + } else { + dst[i] += rhs[i]; + c = (dst[i] < l); + } + } + + return c; +} + +/* DST -= RHS + C where C is zero or one. Returns the carry flag. */ +integerPart +APInt::tcSubtract(integerPart *dst, const integerPart *rhs, + integerPart c, unsigned int parts) +{ + unsigned int i; + + assert(c <= 1); + + for (i = 0; i < parts; i++) { + integerPart l; + + l = dst[i]; + if (c) { + dst[i] -= rhs[i] + 1; + c = (dst[i] >= l); + } else { + dst[i] -= rhs[i]; + c = (dst[i] > l); + } + } + + return c; +} + +/* Negate a bignum in-place. */ +void +APInt::tcNegate(integerPart *dst, unsigned int parts) +{ + tcComplement(dst, parts); + tcIncrement(dst, parts); +} + +/* DST += SRC * MULTIPLIER + CARRY if add is true + DST = SRC * MULTIPLIER + CARRY if add is false + + Requires 0 <= DSTPARTS <= SRCPARTS + 1. If DST overlaps SRC + they must start at the same point, i.e. DST == SRC. + + If DSTPARTS == SRCPARTS + 1 no overflow occurs and zero is + returned. Otherwise DST is filled with the least significant + DSTPARTS parts of the result, and if all of the omitted higher + parts were zero return zero, otherwise overflow occurred and + return one. */ +int +APInt::tcMultiplyPart(integerPart *dst, const integerPart *src, + integerPart multiplier, integerPart carry, + unsigned int srcParts, unsigned int dstParts, + bool add) +{ + unsigned int i, n; + + /* Otherwise our writes of DST kill our later reads of SRC. */ + assert(dst <= src || dst >= src + srcParts); + assert(dstParts <= srcParts + 1); + + /* N loops; minimum of dstParts and srcParts. */ + n = dstParts < srcParts ? dstParts: srcParts; + + for (i = 0; i < n; i++) { + integerPart low, mid, high, srcPart; + + /* [ LOW, HIGH ] = MULTIPLIER * SRC[i] + DST[i] + CARRY. + + This cannot overflow, because + + (n - 1) * (n - 1) + 2 (n - 1) = (n - 1) * (n + 1) + + which is less than n^2. */ + + srcPart = src[i]; + + if (multiplier == 0 || srcPart == 0) { + low = carry; + high = 0; + } else { + low = lowHalf(srcPart) * lowHalf(multiplier); + high = highHalf(srcPart) * highHalf(multiplier); + + mid = lowHalf(srcPart) * highHalf(multiplier); + high += highHalf(mid); + mid <<= integerPartWidth / 2; + if (low + mid < low) + high++; + low += mid; + + mid = highHalf(srcPart) * lowHalf(multiplier); + high += highHalf(mid); + mid <<= integerPartWidth / 2; + if (low + mid < low) + high++; + low += mid; + + /* Now add carry. */ + if (low + carry < low) + high++; + low += carry; + } + + if (add) { + /* And now DST[i], and store the new low part there. */ + if (low + dst[i] < low) + high++; + dst[i] += low; + } else + dst[i] = low; + + carry = high; + } + + if (i < dstParts) { + /* Full multiplication, there is no overflow. */ + assert(i + 1 == dstParts); + dst[i] = carry; + return 0; + } else { + /* We overflowed if there is carry. */ + if (carry) + return 1; + + /* We would overflow if any significant unwritten parts would be + non-zero. This is true if any remaining src parts are non-zero + and the multiplier is non-zero. */ + if (multiplier) + for (; i < srcParts; i++) + if (src[i]) + return 1; + + /* We fitted in the narrow destination. */ + return 0; + } +} + +/* DST = LHS * RHS, where DST has the same width as the operands and + is filled with the least significant parts of the result. Returns + one if overflow occurred, otherwise zero. DST must be disjoint + from both operands. */ +int +APInt::tcMultiply(integerPart *dst, const integerPart *lhs, + const integerPart *rhs, unsigned int parts) +{ + unsigned int i; + int overflow; + + assert(dst != lhs && dst != rhs); + + overflow = 0; + tcSet(dst, 0, parts); + + for (i = 0; i < parts; i++) + overflow |= tcMultiplyPart(&dst[i], lhs, rhs[i], 0, parts, + parts - i, true); + + return overflow; +} + +/* DST = LHS * RHS, where DST has width the sum of the widths of the + operands. No overflow occurs. DST must be disjoint from both + operands. Returns the number of parts required to hold the + result. */ +unsigned int +APInt::tcFullMultiply(integerPart *dst, const integerPart *lhs, + const integerPart *rhs, unsigned int lhsParts, + unsigned int rhsParts) +{ + /* Put the narrower number on the LHS for less loops below. */ + if (lhsParts > rhsParts) { + return tcFullMultiply (dst, rhs, lhs, rhsParts, lhsParts); + } else { + unsigned int n; + + assert(dst != lhs && dst != rhs); + + tcSet(dst, 0, rhsParts); + + for (n = 0; n < lhsParts; n++) + tcMultiplyPart(&dst[n], rhs, lhs[n], 0, rhsParts, rhsParts + 1, true); + + n = lhsParts + rhsParts; + + return n - (dst[n - 1] == 0); + } +} + +/* If RHS is zero LHS and REMAINDER are left unchanged, return one. + Otherwise set LHS to LHS / RHS with the fractional part discarded, + set REMAINDER to the remainder, return zero. i.e. + + OLD_LHS = RHS * LHS + REMAINDER + + SCRATCH is a bignum of the same size as the operands and result for + use by the routine; its contents need not be initialized and are + destroyed. LHS, REMAINDER and SCRATCH must be distinct. +*/ +int +APInt::tcDivide(integerPart *lhs, const integerPart *rhs, + integerPart *remainder, integerPart *srhs, + unsigned int parts) +{ + unsigned int n, shiftCount; + integerPart mask; + + assert(lhs != remainder && lhs != srhs && remainder != srhs); + + shiftCount = tcMSB(rhs, parts) + 1; + if (shiftCount == 0) + return true; + + shiftCount = parts * integerPartWidth - shiftCount; + n = shiftCount / integerPartWidth; + mask = (integerPart) 1 << (shiftCount % integerPartWidth); + + tcAssign(srhs, rhs, parts); + tcShiftLeft(srhs, parts, shiftCount); + tcAssign(remainder, lhs, parts); + tcSet(lhs, 0, parts); + + /* Loop, subtracting SRHS if REMAINDER is greater and adding that to + the total. */ + for (;;) { + int compare; + + compare = tcCompare(remainder, srhs, parts); + if (compare >= 0) { + tcSubtract(remainder, srhs, 0, parts); + lhs[n] |= mask; + } + + if (shiftCount == 0) + break; + shiftCount--; + tcShiftRight(srhs, parts, 1); + if ((mask >>= 1) == 0) { + mask = (integerPart) 1 << (integerPartWidth - 1); + n--; + } + } + + return false; +} + +/* Shift a bignum left COUNT bits in-place. Shifted in bits are zero. + There are no restrictions on COUNT. */ +void +APInt::tcShiftLeft(integerPart *dst, unsigned int parts, unsigned int count) +{ + if (count) { + unsigned int jump, shift; + + /* Jump is the inter-part jump; shift is is intra-part shift. */ + jump = count / integerPartWidth; + shift = count % integerPartWidth; + + while (parts > jump) { + integerPart part; + + parts--; + + /* dst[i] comes from the two parts src[i - jump] and, if we have + an intra-part shift, src[i - jump - 1]. */ + part = dst[parts - jump]; + if (shift) { + part <<= shift; + if (parts >= jump + 1) + part |= dst[parts - jump - 1] >> (integerPartWidth - shift); + } + + dst[parts] = part; + } + + while (parts > 0) + dst[--parts] = 0; + } +} + +/* Shift a bignum right COUNT bits in-place. Shifted in bits are + zero. There are no restrictions on COUNT. */ +void +APInt::tcShiftRight(integerPart *dst, unsigned int parts, unsigned int count) +{ + if (count) { + unsigned int i, jump, shift; + + /* Jump is the inter-part jump; shift is is intra-part shift. */ + jump = count / integerPartWidth; + shift = count % integerPartWidth; + + /* Perform the shift. This leaves the most significant COUNT bits + of the result at zero. */ + for (i = 0; i < parts; i++) { + integerPart part; + + if (i + jump >= parts) { + part = 0; + } else { + part = dst[i + jump]; + if (shift) { + part >>= shift; + if (i + jump + 1 < parts) + part |= dst[i + jump + 1] << (integerPartWidth - shift); + } + } + + dst[i] = part; + } + } +} + +/* Bitwise and of two bignums. */ +void +APInt::tcAnd(integerPart *dst, const integerPart *rhs, unsigned int parts) +{ + unsigned int i; + + for (i = 0; i < parts; i++) + dst[i] &= rhs[i]; +} + +/* Bitwise inclusive or of two bignums. */ +void +APInt::tcOr(integerPart *dst, const integerPart *rhs, unsigned int parts) +{ + unsigned int i; + + for (i = 0; i < parts; i++) + dst[i] |= rhs[i]; +} + +/* Bitwise exclusive or of two bignums. */ +void +APInt::tcXor(integerPart *dst, const integerPart *rhs, unsigned int parts) +{ + unsigned int i; + + for (i = 0; i < parts; i++) + dst[i] ^= rhs[i]; +} + +/* Complement a bignum in-place. */ +void +APInt::tcComplement(integerPart *dst, unsigned int parts) +{ + unsigned int i; + + for (i = 0; i < parts; i++) + dst[i] = ~dst[i]; +} + +/* Comparison (unsigned) of two bignums. */ +int +APInt::tcCompare(const integerPart *lhs, const integerPart *rhs, + unsigned int parts) +{ + while (parts) { + parts--; + if (lhs[parts] == rhs[parts]) + continue; + + if (lhs[parts] > rhs[parts]) + return 1; + else + return -1; + } + + return 0; +} + +/* Increment a bignum in-place, return the carry flag. */ +integerPart +APInt::tcIncrement(integerPart *dst, unsigned int parts) +{ + unsigned int i; + + for (i = 0; i < parts; i++) + if (++dst[i] != 0) + break; + + return i == parts; +} + +/* Decrement a bignum in-place, return the borrow flag. */ +integerPart +APInt::tcDecrement(integerPart *dst, unsigned int parts) { + for (unsigned int i = 0; i < parts; i++) { + // If the current word is non-zero, then the decrement has no effect on the + // higher-order words of the integer and no borrow can occur. Exit early. + if (dst[i]--) + return 0; + } + // If every word was zero, then there is a borrow. + return 1; +} + + +/* Set the least significant BITS bits of a bignum, clear the + rest. */ +void +APInt::tcSetLeastSignificantBits(integerPart *dst, unsigned int parts, + unsigned int bits) +{ + unsigned int i; + + i = 0; + while (bits > integerPartWidth) { + dst[i++] = ~(integerPart) 0; + bits -= integerPartWidth; + } + + if (bits) + dst[i++] = ~(integerPart) 0 >> (integerPartWidth - bits); + + while (i < parts) + dst[i++] = 0; +}
diff --git a/third_party/llvm-subzero/lib/Support/Atomic.cpp b/third_party/llvm-subzero/lib/Support/Atomic.cpp new file mode 100644 index 0000000..80550e2 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Atomic.cpp
@@ -0,0 +1,58 @@ +//===-- Atomic.cpp - Atomic Operations --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements atomic operations. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Atomic.h" +#include "llvm/Config/llvm-config.h" + +using namespace llvm; + +#if defined(_MSC_VER) +#include <Intrin.h> +#include <windows.h> +#undef MemoryFence +#endif + +#if defined(__GNUC__) || (defined(__IBMCPP__) && __IBMCPP__ >= 1210) +#define GNU_ATOMICS +#endif + +void sys::MemoryFence() { +#if LLVM_HAS_ATOMICS == 0 + return; +#else +# if defined(GNU_ATOMICS) + __sync_synchronize(); +# elif defined(_MSC_VER) + MemoryBarrier(); +# else +# error No memory fence implementation for your platform! +# endif +#endif +} + +sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr, + sys::cas_flag new_value, + sys::cas_flag old_value) { +#if LLVM_HAS_ATOMICS == 0 + sys::cas_flag result = *ptr; + if (result == old_value) + *ptr = new_value; + return result; +#elif defined(GNU_ATOMICS) + return __sync_val_compare_and_swap(ptr, old_value, new_value); +#elif defined(_MSC_VER) + return InterlockedCompareExchange(ptr, new_value, old_value); +#else +# error No compare-and-swap implementation for your platform! +#endif +}
diff --git a/third_party/llvm-subzero/lib/Support/CommandLine.cpp b/third_party/llvm-subzero/lib/Support/CommandLine.cpp new file mode 100644 index 0000000..551cdef --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/CommandLine.cpp
@@ -0,0 +1,2136 @@ +//===-- CommandLine.cpp - Command line parser implementation --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements a command line argument processor that is useful when +// creating a tool. It provides a simple, minimalistic interface that is easily +// extensible and supports nonlocal (library) command line options. +// +// Note that rather than trying to figure out what this code does, you could try +// reading the library documentation located in docs/CommandLine.html +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/CommandLine.h" +#include "llvm-c/Support.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Config/config.h" +#include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/StringSaver.h" +#include "llvm/Support/raw_ostream.h" +#include <cstdlib> +#include <map> +using namespace llvm; +using namespace cl; + +#define DEBUG_TYPE "commandline" + +//===----------------------------------------------------------------------===// +// Template instantiations and anchors. +// +namespace llvm { +namespace cl { +template class basic_parser<bool>; +template class basic_parser<boolOrDefault>; +template class basic_parser<int>; +template class basic_parser<unsigned>; +template class basic_parser<unsigned long long>; +template class basic_parser<double>; +template class basic_parser<float>; +template class basic_parser<std::string>; +template class basic_parser<char>; + +template class opt<unsigned>; +template class opt<int>; +template class opt<std::string>; +template class opt<char>; +template class opt<bool>; +} +} // end namespace llvm::cl + +// Pin the vtables to this file. +void GenericOptionValue::anchor() {} +void OptionValue<boolOrDefault>::anchor() {} +void OptionValue<std::string>::anchor() {} +void Option::anchor() {} +void basic_parser_impl::anchor() {} +void parser<bool>::anchor() {} +void parser<boolOrDefault>::anchor() {} +void parser<int>::anchor() {} +void parser<unsigned>::anchor() {} +void parser<unsigned long long>::anchor() {} +void parser<double>::anchor() {} +void parser<float>::anchor() {} +void parser<std::string>::anchor() {} +void parser<char>::anchor() {} + +//===----------------------------------------------------------------------===// + +namespace { + +class CommandLineParser { +public: + // Globals for name and overview of program. Program name is not a string to + // avoid static ctor/dtor issues. + std::string ProgramName; + const char *ProgramOverview; + + // This collects additional help to be printed. + std::vector<const char *> MoreHelp; + + // This collects the different option categories that have been registered. + SmallPtrSet<OptionCategory *, 16> RegisteredOptionCategories; + + // This collects the different subcommands that have been registered. + SmallPtrSet<SubCommand *, 4> RegisteredSubCommands; + + CommandLineParser() : ProgramOverview(nullptr), ActiveSubCommand(nullptr) { + registerSubCommand(&*TopLevelSubCommand); + registerSubCommand(&*AllSubCommands); + } + + void ResetAllOptionOccurrences(); + + bool ParseCommandLineOptions(int argc, const char *const *argv, + const char *Overview, bool IgnoreErrors); + + void addLiteralOption(Option &Opt, SubCommand *SC, const char *Name) { + if (Opt.hasArgStr()) + return; + if (!SC->OptionsMap.insert(std::make_pair(Name, &Opt)).second) { + errs() << ProgramName << ": CommandLine Error: Option '" << Name + << "' registered more than once!\n"; + report_fatal_error("inconsistency in registered CommandLine options"); + } + + // If we're adding this to all sub-commands, add it to the ones that have + // already been registered. + if (SC == &*AllSubCommands) { + for (const auto &Sub : RegisteredSubCommands) { + if (SC == Sub) + continue; + addLiteralOption(Opt, Sub, Name); + } + } + } + + void addLiteralOption(Option &Opt, const char *Name) { + if (Opt.Subs.empty()) + addLiteralOption(Opt, &*TopLevelSubCommand, Name); + else { + for (auto SC : Opt.Subs) + addLiteralOption(Opt, SC, Name); + } + } + + void addOption(Option *O, SubCommand *SC) { + bool HadErrors = false; + if (O->hasArgStr()) { + // Add argument to the argument map! + if (!SC->OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) { + errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr + << "' registered more than once!\n"; + HadErrors = true; + } + } + + // Remember information about positional options. + if (O->getFormattingFlag() == cl::Positional) + SC->PositionalOpts.push_back(O); + else if (O->getMiscFlags() & cl::Sink) // Remember sink options + SC->SinkOpts.push_back(O); + else if (O->getNumOccurrencesFlag() == cl::ConsumeAfter) { + if (SC->ConsumeAfterOpt) { + O->error("Cannot specify more than one option with cl::ConsumeAfter!"); + HadErrors = true; + } + SC->ConsumeAfterOpt = O; + } + + // Fail hard if there were errors. These are strictly unrecoverable and + // indicate serious issues such as conflicting option names or an + // incorrectly + // linked LLVM distribution. + if (HadErrors) + report_fatal_error("inconsistency in registered CommandLine options"); + + // If we're adding this to all sub-commands, add it to the ones that have + // already been registered. + if (SC == &*AllSubCommands) { + for (const auto &Sub : RegisteredSubCommands) { + if (SC == Sub) + continue; + addOption(O, Sub); + } + } + } + + void addOption(Option *O) { + if (O->Subs.empty()) { + addOption(O, &*TopLevelSubCommand); + } else { + for (auto SC : O->Subs) + addOption(O, SC); + } + } + + void removeOption(Option *O, SubCommand *SC) { + SmallVector<StringRef, 16> OptionNames; + O->getExtraOptionNames(OptionNames); + if (O->hasArgStr()) + OptionNames.push_back(O->ArgStr); + + SubCommand &Sub = *SC; + for (auto Name : OptionNames) + Sub.OptionsMap.erase(Name); + + if (O->getFormattingFlag() == cl::Positional) + for (auto Opt = Sub.PositionalOpts.begin(); + Opt != Sub.PositionalOpts.end(); ++Opt) { + if (*Opt == O) { + Sub.PositionalOpts.erase(Opt); + break; + } + } + else if (O->getMiscFlags() & cl::Sink) + for (auto Opt = Sub.SinkOpts.begin(); Opt != Sub.SinkOpts.end(); ++Opt) { + if (*Opt == O) { + Sub.SinkOpts.erase(Opt); + break; + } + } + else if (O == Sub.ConsumeAfterOpt) + Sub.ConsumeAfterOpt = nullptr; + } + + void removeOption(Option *O) { + if (O->Subs.empty()) + removeOption(O, &*TopLevelSubCommand); + else { + if (O->isInAllSubCommands()) { + for (auto SC : RegisteredSubCommands) + removeOption(O, SC); + } else { + for (auto SC : O->Subs) + removeOption(O, SC); + } + } + } + + bool hasOptions(const SubCommand &Sub) const { + return (!Sub.OptionsMap.empty() || !Sub.PositionalOpts.empty() || + nullptr != Sub.ConsumeAfterOpt); + } + + bool hasOptions() const { + for (const auto &S : RegisteredSubCommands) { + if (hasOptions(*S)) + return true; + } + return false; + } + + SubCommand *getActiveSubCommand() { return ActiveSubCommand; } + + void updateArgStr(Option *O, StringRef NewName, SubCommand *SC) { + SubCommand &Sub = *SC; + if (!Sub.OptionsMap.insert(std::make_pair(NewName, O)).second) { + errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr + << "' registered more than once!\n"; + report_fatal_error("inconsistency in registered CommandLine options"); + } + Sub.OptionsMap.erase(O->ArgStr); + } + + void updateArgStr(Option *O, StringRef NewName) { + if (O->Subs.empty()) + updateArgStr(O, NewName, &*TopLevelSubCommand); + else { + for (auto SC : O->Subs) + updateArgStr(O, NewName, SC); + } + } + + void printOptionValues(); + + void registerCategory(OptionCategory *cat) { + assert(count_if(RegisteredOptionCategories, + [cat](const OptionCategory *Category) { + return cat->getName() == Category->getName(); + }) == 0 && + "Duplicate option categories"); + + RegisteredOptionCategories.insert(cat); + } + + void registerSubCommand(SubCommand *sub) { + assert(count_if(RegisteredSubCommands, + [sub](const SubCommand *Sub) { + return (sub->getName() != nullptr) && + (Sub->getName() == sub->getName()); + }) == 0 && + "Duplicate subcommands"); + RegisteredSubCommands.insert(sub); + + // For all options that have been registered for all subcommands, add the + // option to this subcommand now. + if (sub != &*AllSubCommands) { + for (auto &E : AllSubCommands->OptionsMap) { + Option *O = E.second; + if ((O->isPositional() || O->isSink() || O->isConsumeAfter()) || + O->hasArgStr()) + addOption(O, sub); + else + addLiteralOption(*O, sub, E.first().str().c_str()); + } + } + } + + void unregisterSubCommand(SubCommand *sub) { + RegisteredSubCommands.erase(sub); + } + + void reset() { + ActiveSubCommand = nullptr; + ProgramName.clear(); + ProgramOverview = nullptr; + + MoreHelp.clear(); + RegisteredOptionCategories.clear(); + + ResetAllOptionOccurrences(); + RegisteredSubCommands.clear(); + + TopLevelSubCommand->reset(); + AllSubCommands->reset(); + registerSubCommand(&*TopLevelSubCommand); + registerSubCommand(&*AllSubCommands); + } + +private: + SubCommand *ActiveSubCommand; + + Option *LookupOption(SubCommand &Sub, StringRef &Arg, StringRef &Value); + SubCommand *LookupSubCommand(const char *Name); +}; + +} // namespace + +static ManagedStatic<CommandLineParser> GlobalParser; + +void cl::AddLiteralOption(Option &O, const char *Name) { + GlobalParser->addLiteralOption(O, Name); +} + +extrahelp::extrahelp(const char *Help) : morehelp(Help) { + GlobalParser->MoreHelp.push_back(Help); +} + +void Option::addArgument() { + GlobalParser->addOption(this); + FullyInitialized = true; +} + +void Option::removeArgument() { GlobalParser->removeOption(this); } + +void Option::setArgStr(StringRef S) { + if (FullyInitialized) + GlobalParser->updateArgStr(this, S); + ArgStr = S; +} + +// Initialise the general option category. +OptionCategory llvm::cl::GeneralCategory("General options"); + +void OptionCategory::registerCategory() { + GlobalParser->registerCategory(this); +} + +// A special subcommand representing no subcommand +ManagedStatic<SubCommand> llvm::cl::TopLevelSubCommand; + +// A special subcommand that can be used to put an option into all subcommands. +ManagedStatic<SubCommand> llvm::cl::AllSubCommands; + +void SubCommand::registerSubCommand() { + GlobalParser->registerSubCommand(this); +} + +void SubCommand::unregisterSubCommand() { + GlobalParser->unregisterSubCommand(this); +} + +void SubCommand::reset() { + PositionalOpts.clear(); + SinkOpts.clear(); + OptionsMap.clear(); + + ConsumeAfterOpt = nullptr; +} + +SubCommand::operator bool() const { + return (GlobalParser->getActiveSubCommand() == this); +} + +//===----------------------------------------------------------------------===// +// Basic, shared command line option processing machinery. +// + +/// LookupOption - Lookup the option specified by the specified option on the +/// command line. If there is a value specified (after an equal sign) return +/// that as well. This assumes that leading dashes have already been stripped. +Option *CommandLineParser::LookupOption(SubCommand &Sub, StringRef &Arg, + StringRef &Value) { + // Reject all dashes. + if (Arg.empty()) + return nullptr; + assert(&Sub != &*AllSubCommands); + + size_t EqualPos = Arg.find('='); + + // If we have an equals sign, remember the value. + if (EqualPos == StringRef::npos) { + // Look up the option. + auto I = Sub.OptionsMap.find(Arg); + if (I == Sub.OptionsMap.end()) + return nullptr; + + return I != Sub.OptionsMap.end() ? I->second : nullptr; + } + + // If the argument before the = is a valid option name, we match. If not, + // return Arg unmolested. + auto I = Sub.OptionsMap.find(Arg.substr(0, EqualPos)); + if (I == Sub.OptionsMap.end()) + return nullptr; + + Value = Arg.substr(EqualPos + 1); + Arg = Arg.substr(0, EqualPos); + return I->second; +} + +SubCommand *CommandLineParser::LookupSubCommand(const char *Name) { + if (Name == nullptr) + return &*TopLevelSubCommand; + for (auto S : RegisteredSubCommands) { + if (S == &*AllSubCommands) + continue; + if (S->getName() == nullptr) + continue; + + if (StringRef(S->getName()) == StringRef(Name)) + return S; + } + return &*TopLevelSubCommand; +} + +/// LookupNearestOption - Lookup the closest match to the option specified by +/// the specified option on the command line. If there is a value specified +/// (after an equal sign) return that as well. This assumes that leading dashes +/// have already been stripped. +static Option *LookupNearestOption(StringRef Arg, + const StringMap<Option *> &OptionsMap, + std::string &NearestString) { + // Reject all dashes. + if (Arg.empty()) + return nullptr; + + // Split on any equal sign. + std::pair<StringRef, StringRef> SplitArg = Arg.split('='); + StringRef &LHS = SplitArg.first; // LHS == Arg when no '=' is present. + StringRef &RHS = SplitArg.second; + + // Find the closest match. + Option *Best = nullptr; + unsigned BestDistance = 0; + for (StringMap<Option *>::const_iterator it = OptionsMap.begin(), + ie = OptionsMap.end(); + it != ie; ++it) { + Option *O = it->second; + SmallVector<StringRef, 16> OptionNames; + O->getExtraOptionNames(OptionNames); + if (O->hasArgStr()) + OptionNames.push_back(O->ArgStr); + + bool PermitValue = O->getValueExpectedFlag() != cl::ValueDisallowed; + StringRef Flag = PermitValue ? LHS : Arg; + for (auto Name : OptionNames) { + unsigned Distance = StringRef(Name).edit_distance( + Flag, /*AllowReplacements=*/true, /*MaxEditDistance=*/BestDistance); + if (!Best || Distance < BestDistance) { + Best = O; + BestDistance = Distance; + if (RHS.empty() || !PermitValue) + NearestString = Name; + else + NearestString = (Twine(Name) + "=" + RHS).str(); + } + } + } + + return Best; +} + +/// CommaSeparateAndAddOccurrence - A wrapper around Handler->addOccurrence() +/// that does special handling of cl::CommaSeparated options. +static bool CommaSeparateAndAddOccurrence(Option *Handler, unsigned pos, + StringRef ArgName, StringRef Value, + bool MultiArg = false) { + // Check to see if this option accepts a comma separated list of values. If + // it does, we have to split up the value into multiple values. + if (Handler->getMiscFlags() & CommaSeparated) { + StringRef Val(Value); + StringRef::size_type Pos = Val.find(','); + + while (Pos != StringRef::npos) { + // Process the portion before the comma. + if (Handler->addOccurrence(pos, ArgName, Val.substr(0, Pos), MultiArg)) + return true; + // Erase the portion before the comma, AND the comma. + Val = Val.substr(Pos + 1); + // Check for another comma. + Pos = Val.find(','); + } + + Value = Val; + } + + return Handler->addOccurrence(pos, ArgName, Value, MultiArg); +} + +/// ProvideOption - For Value, this differentiates between an empty value ("") +/// and a null value (StringRef()). The later is accepted for arguments that +/// don't allow a value (-foo) the former is rejected (-foo=). +static inline bool ProvideOption(Option *Handler, StringRef ArgName, + StringRef Value, int argc, + const char *const *argv, int &i) { + // Is this a multi-argument option? + unsigned NumAdditionalVals = Handler->getNumAdditionalVals(); + + // Enforce value requirements + switch (Handler->getValueExpectedFlag()) { + case ValueRequired: + if (!Value.data()) { // No value specified? + if (i + 1 >= argc) + return Handler->error("requires a value!"); + // Steal the next argument, like for '-o filename' + assert(argv && "null check"); + Value = argv[++i]; + } + break; + case ValueDisallowed: + if (NumAdditionalVals > 0) + return Handler->error("multi-valued option specified" + " with ValueDisallowed modifier!"); + + if (Value.data()) + return Handler->error("does not allow a value! '" + Twine(Value) + + "' specified."); + break; + case ValueOptional: + break; + } + + // If this isn't a multi-arg option, just run the handler. + if (NumAdditionalVals == 0) + return CommaSeparateAndAddOccurrence(Handler, i, ArgName, Value); + + // If it is, run the handle several times. + bool MultiArg = false; + + if (Value.data()) { + if (CommaSeparateAndAddOccurrence(Handler, i, ArgName, Value, MultiArg)) + return true; + --NumAdditionalVals; + MultiArg = true; + } + + while (NumAdditionalVals > 0) { + if (i + 1 >= argc) + return Handler->error("not enough values!"); + assert(argv && "null check"); + Value = argv[++i]; + + if (CommaSeparateAndAddOccurrence(Handler, i, ArgName, Value, MultiArg)) + return true; + MultiArg = true; + --NumAdditionalVals; + } + return false; +} + +static bool ProvidePositionalOption(Option *Handler, StringRef Arg, int i) { + int Dummy = i; + return ProvideOption(Handler, Handler->ArgStr, Arg, 0, nullptr, Dummy); +} + +// Option predicates... +static inline bool isGrouping(const Option *O) { + return O->getFormattingFlag() == cl::Grouping; +} +static inline bool isPrefixedOrGrouping(const Option *O) { + return isGrouping(O) || O->getFormattingFlag() == cl::Prefix; +} + +// getOptionPred - Check to see if there are any options that satisfy the +// specified predicate with names that are the prefixes in Name. This is +// checked by progressively stripping characters off of the name, checking to +// see if there options that satisfy the predicate. If we find one, return it, +// otherwise return null. +// +static Option *getOptionPred(StringRef Name, size_t &Length, + bool (*Pred)(const Option *), + const StringMap<Option *> &OptionsMap) { + + StringMap<Option *>::const_iterator OMI = OptionsMap.find(Name); + + // Loop while we haven't found an option and Name still has at least two + // characters in it (so that the next iteration will not be the empty + // string. + while (OMI == OptionsMap.end() && Name.size() > 1) { + Name = Name.substr(0, Name.size() - 1); // Chop off the last character. + OMI = OptionsMap.find(Name); + } + + if (OMI != OptionsMap.end() && Pred(OMI->second)) { + Length = Name.size(); + return OMI->second; // Found one! + } + return nullptr; // No option found! +} + +/// HandlePrefixedOrGroupedOption - The specified argument string (which started +/// with at least one '-') does not fully match an available option. Check to +/// see if this is a prefix or grouped option. If so, split arg into output an +/// Arg/Value pair and return the Option to parse it with. +static Option * +HandlePrefixedOrGroupedOption(StringRef &Arg, StringRef &Value, + bool &ErrorParsing, + const StringMap<Option *> &OptionsMap) { + if (Arg.size() == 1) + return nullptr; + + // Do the lookup! + size_t Length = 0; + Option *PGOpt = getOptionPred(Arg, Length, isPrefixedOrGrouping, OptionsMap); + if (!PGOpt) + return nullptr; + + // If the option is a prefixed option, then the value is simply the + // rest of the name... so fall through to later processing, by + // setting up the argument name flags and value fields. + if (PGOpt->getFormattingFlag() == cl::Prefix) { + Value = Arg.substr(Length); + Arg = Arg.substr(0, Length); + assert(OptionsMap.count(Arg) && OptionsMap.find(Arg)->second == PGOpt); + return PGOpt; + } + + // This must be a grouped option... handle them now. Grouping options can't + // have values. + assert(isGrouping(PGOpt) && "Broken getOptionPred!"); + + do { + // Move current arg name out of Arg into OneArgName. + StringRef OneArgName = Arg.substr(0, Length); + Arg = Arg.substr(Length); + + // Because ValueRequired is an invalid flag for grouped arguments, + // we don't need to pass argc/argv in. + assert(PGOpt->getValueExpectedFlag() != cl::ValueRequired && + "Option can not be cl::Grouping AND cl::ValueRequired!"); + int Dummy = 0; + ErrorParsing |= + ProvideOption(PGOpt, OneArgName, StringRef(), 0, nullptr, Dummy); + + // Get the next grouping option. + PGOpt = getOptionPred(Arg, Length, isGrouping, OptionsMap); + } while (PGOpt && Length != Arg.size()); + + // Return the last option with Arg cut down to just the last one. + return PGOpt; +} + +static bool RequiresValue(const Option *O) { + return O->getNumOccurrencesFlag() == cl::Required || + O->getNumOccurrencesFlag() == cl::OneOrMore; +} + +static bool EatsUnboundedNumberOfValues(const Option *O) { + return O->getNumOccurrencesFlag() == cl::ZeroOrMore || + O->getNumOccurrencesFlag() == cl::OneOrMore; +} + +static bool isWhitespace(char C) { return strchr(" \t\n\r\f\v", C); } + +static bool isQuote(char C) { return C == '\"' || C == '\''; } + +void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver, + SmallVectorImpl<const char *> &NewArgv, + bool MarkEOLs) { + SmallString<128> Token; + for (size_t I = 0, E = Src.size(); I != E; ++I) { + // Consume runs of whitespace. + if (Token.empty()) { + while (I != E && isWhitespace(Src[I])) { + // Mark the end of lines in response files + if (MarkEOLs && Src[I] == '\n') + NewArgv.push_back(nullptr); + ++I; + } + if (I == E) + break; + } + + // Backslash escapes the next character. + if (I + 1 < E && Src[I] == '\\') { + ++I; // Skip the escape. + Token.push_back(Src[I]); + continue; + } + + // Consume a quoted string. + if (isQuote(Src[I])) { + char Quote = Src[I++]; + while (I != E && Src[I] != Quote) { + // Backslash escapes the next character. + if (Src[I] == '\\' && I + 1 != E) + ++I; + Token.push_back(Src[I]); + ++I; + } + if (I == E) + break; + continue; + } + + // End the token if this is whitespace. + if (isWhitespace(Src[I])) { + if (!Token.empty()) + NewArgv.push_back(Saver.save(Token.c_str())); + Token.clear(); + continue; + } + + // This is a normal character. Append it. + Token.push_back(Src[I]); + } + + // Append the last token after hitting EOF with no whitespace. + if (!Token.empty()) + NewArgv.push_back(Saver.save(Token.c_str())); + // Mark the end of response files + if (MarkEOLs) + NewArgv.push_back(nullptr); +} + +/// Backslashes are interpreted in a rather complicated way in the Windows-style +/// command line, because backslashes are used both to separate path and to +/// escape double quote. This method consumes runs of backslashes as well as the +/// following double quote if it's escaped. +/// +/// * If an even number of backslashes is followed by a double quote, one +/// backslash is output for every pair of backslashes, and the last double +/// quote remains unconsumed. The double quote will later be interpreted as +/// the start or end of a quoted string in the main loop outside of this +/// function. +/// +/// * If an odd number of backslashes is followed by a double quote, one +/// backslash is output for every pair of backslashes, and a double quote is +/// output for the last pair of backslash-double quote. The double quote is +/// consumed in this case. +/// +/// * Otherwise, backslashes are interpreted literally. +static size_t parseBackslash(StringRef Src, size_t I, SmallString<128> &Token) { + size_t E = Src.size(); + int BackslashCount = 0; + // Skip the backslashes. + do { + ++I; + ++BackslashCount; + } while (I != E && Src[I] == '\\'); + + bool FollowedByDoubleQuote = (I != E && Src[I] == '"'); + if (FollowedByDoubleQuote) { + Token.append(BackslashCount / 2, '\\'); + if (BackslashCount % 2 == 0) + return I - 1; + Token.push_back('"'); + return I; + } + Token.append(BackslashCount, '\\'); + return I - 1; +} + +void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver, + SmallVectorImpl<const char *> &NewArgv, + bool MarkEOLs) { + SmallString<128> Token; + + // This is a small state machine to consume characters until it reaches the + // end of the source string. + enum { INIT, UNQUOTED, QUOTED } State = INIT; + for (size_t I = 0, E = Src.size(); I != E; ++I) { + // INIT state indicates that the current input index is at the start of + // the string or between tokens. + if (State == INIT) { + if (isWhitespace(Src[I])) { + // Mark the end of lines in response files + if (MarkEOLs && Src[I] == '\n') + NewArgv.push_back(nullptr); + continue; + } + if (Src[I] == '"') { + State = QUOTED; + continue; + } + if (Src[I] == '\\') { + I = parseBackslash(Src, I, Token); + State = UNQUOTED; + continue; + } + Token.push_back(Src[I]); + State = UNQUOTED; + continue; + } + + // UNQUOTED state means that it's reading a token not quoted by double + // quotes. + if (State == UNQUOTED) { + // Whitespace means the end of the token. + if (isWhitespace(Src[I])) { + NewArgv.push_back(Saver.save(Token.c_str())); + Token.clear(); + State = INIT; + // Mark the end of lines in response files + if (MarkEOLs && Src[I] == '\n') + NewArgv.push_back(nullptr); + continue; + } + if (Src[I] == '"') { + State = QUOTED; + continue; + } + if (Src[I] == '\\') { + I = parseBackslash(Src, I, Token); + continue; + } + Token.push_back(Src[I]); + continue; + } + + // QUOTED state means that it's reading a token quoted by double quotes. + if (State == QUOTED) { + if (Src[I] == '"') { + State = UNQUOTED; + continue; + } + if (Src[I] == '\\') { + I = parseBackslash(Src, I, Token); + continue; + } + Token.push_back(Src[I]); + } + } + // Append the last token after hitting EOF with no whitespace. + if (!Token.empty()) + NewArgv.push_back(Saver.save(Token.c_str())); + // Mark the end of response files + if (MarkEOLs) + NewArgv.push_back(nullptr); +} + +// It is called byte order marker but the UTF-8 BOM is actually not affected +// by the host system's endianness. +static bool hasUTF8ByteOrderMark(ArrayRef<char> S) { + return (S.size() >= 3 && S[0] == '\xef' && S[1] == '\xbb' && S[2] == '\xbf'); +} + +static bool ExpandResponseFile(const char *FName, StringSaver &Saver, + TokenizerCallback Tokenizer, + SmallVectorImpl<const char *> &NewArgv, + bool MarkEOLs = false) { + ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr = + MemoryBuffer::getFile(FName); + if (!MemBufOrErr) + return false; + MemoryBuffer &MemBuf = *MemBufOrErr.get(); + StringRef Str(MemBuf.getBufferStart(), MemBuf.getBufferSize()); + + // If we have a UTF-16 byte order mark, convert to UTF-8 for parsing. + ArrayRef<char> BufRef(MemBuf.getBufferStart(), MemBuf.getBufferEnd()); + std::string UTF8Buf; + if (hasUTF16ByteOrderMark(BufRef)) { + if (!convertUTF16ToUTF8String(BufRef, UTF8Buf)) + return false; + Str = StringRef(UTF8Buf); + } + // If we see UTF-8 BOM sequence at the beginning of a file, we shall remove + // these bytes before parsing. + // Reference: http://en.wikipedia.org/wiki/UTF-8#Byte_order_mark + else if (hasUTF8ByteOrderMark(BufRef)) + Str = StringRef(BufRef.data() + 3, BufRef.size() - 3); + + // Tokenize the contents into NewArgv. + Tokenizer(Str, Saver, NewArgv, MarkEOLs); + + return true; +} + +/// \brief Expand response files on a command line recursively using the given +/// StringSaver and tokenization strategy. +bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, + SmallVectorImpl<const char *> &Argv, + bool MarkEOLs) { + unsigned RspFiles = 0; + bool AllExpanded = true; + + // Don't cache Argv.size() because it can change. + for (unsigned I = 0; I != Argv.size();) { + const char *Arg = Argv[I]; + // Check if it is an EOL marker + if (Arg == nullptr) { + ++I; + continue; + } + if (Arg[0] != '@') { + ++I; + continue; + } + + // If we have too many response files, leave some unexpanded. This avoids + // crashing on self-referential response files. + if (RspFiles++ > 20) + return false; + + // Replace this response file argument with the tokenization of its + // contents. Nested response files are expanded in subsequent iterations. + // FIXME: If a nested response file uses a relative path, is it relative to + // the cwd of the process or the response file? + SmallVector<const char *, 0> ExpandedArgv; + if (!ExpandResponseFile(Arg + 1, Saver, Tokenizer, ExpandedArgv, + MarkEOLs)) { + // We couldn't read this file, so we leave it in the argument stream and + // move on. + AllExpanded = false; + ++I; + continue; + } + Argv.erase(Argv.begin() + I); + Argv.insert(Argv.begin() + I, ExpandedArgv.begin(), ExpandedArgv.end()); + } + return AllExpanded; +} + +/// ParseEnvironmentOptions - An alternative entry point to the +/// CommandLine library, which allows you to read the program's name +/// from the caller (as PROGNAME) and its command-line arguments from +/// an environment variable (whose name is given in ENVVAR). +/// +void cl::ParseEnvironmentOptions(const char *progName, const char *envVar, + const char *Overview) { + // Check args. + assert(progName && "Program name not specified"); + assert(envVar && "Environment variable name missing"); + + // Get the environment variable they want us to parse options out of. + llvm::Optional<std::string> envValue = sys::Process::GetEnv(envVar); + if (!envValue) + return; + + // Get program's "name", which we wouldn't know without the caller + // telling us. + SmallVector<const char *, 20> newArgv; + BumpPtrAllocator A; + StringSaver Saver(A); + newArgv.push_back(Saver.save(progName)); + + // Parse the value of the environment variable into a "command line" + // and hand it off to ParseCommandLineOptions(). + TokenizeGNUCommandLine(*envValue, Saver, newArgv); + int newArgc = static_cast<int>(newArgv.size()); + ParseCommandLineOptions(newArgc, &newArgv[0], Overview); +} + +bool cl::ParseCommandLineOptions(int argc, const char *const *argv, + const char *Overview, bool IgnoreErrors) { + return GlobalParser->ParseCommandLineOptions(argc, argv, Overview, + IgnoreErrors); +} + +void CommandLineParser::ResetAllOptionOccurrences() { + // So that we can parse different command lines multiple times in succession + // we reset all option values to look like they have never been seen before. + for (auto SC : RegisteredSubCommands) { + for (auto &O : SC->OptionsMap) + O.second->reset(); + } +} + +bool CommandLineParser::ParseCommandLineOptions(int argc, + const char *const *argv, + const char *Overview, + bool IgnoreErrors) { + assert(hasOptions() && "No options specified!"); + + // Expand response files. + SmallVector<const char *, 20> newArgv(argv, argv + argc); + BumpPtrAllocator A; + StringSaver Saver(A); + ExpandResponseFiles(Saver, TokenizeGNUCommandLine, newArgv); + argv = &newArgv[0]; + argc = static_cast<int>(newArgv.size()); + + // Copy the program name into ProgName, making sure not to overflow it. + ProgramName = sys::path::filename(argv[0]); + + ProgramOverview = Overview; + bool ErrorParsing = false; + + // Check out the positional arguments to collect information about them. + unsigned NumPositionalRequired = 0; + + // Determine whether or not there are an unlimited number of positionals + bool HasUnlimitedPositionals = false; + + int FirstArg = 1; + SubCommand *ChosenSubCommand = &*TopLevelSubCommand; + if (argc >= 2 && argv[FirstArg][0] != '-') { + // If the first argument specifies a valid subcommand, start processing + // options from the second argument. + ChosenSubCommand = LookupSubCommand(argv[FirstArg]); + if (ChosenSubCommand != &*TopLevelSubCommand) + FirstArg = 2; + } + GlobalParser->ActiveSubCommand = ChosenSubCommand; + + assert(ChosenSubCommand); + auto &ConsumeAfterOpt = ChosenSubCommand->ConsumeAfterOpt; + auto &PositionalOpts = ChosenSubCommand->PositionalOpts; + auto &SinkOpts = ChosenSubCommand->SinkOpts; + auto &OptionsMap = ChosenSubCommand->OptionsMap; + + if (ConsumeAfterOpt) { + assert(PositionalOpts.size() > 0 && + "Cannot specify cl::ConsumeAfter without a positional argument!"); + } + if (!PositionalOpts.empty()) { + + // Calculate how many positional values are _required_. + bool UnboundedFound = false; + for (size_t i = 0, e = PositionalOpts.size(); i != e; ++i) { + Option *Opt = PositionalOpts[i]; + if (RequiresValue(Opt)) + ++NumPositionalRequired; + else if (ConsumeAfterOpt) { + // ConsumeAfter cannot be combined with "optional" positional options + // unless there is only one positional argument... + if (PositionalOpts.size() > 1) { + if (!IgnoreErrors) + Opt->error("error - this positional option will never be matched, " + "because it does not Require a value, and a " + "cl::ConsumeAfter option is active!"); + ErrorParsing = true; + } + } else if (UnboundedFound && !Opt->hasArgStr()) { + // This option does not "require" a value... Make sure this option is + // not specified after an option that eats all extra arguments, or this + // one will never get any! + // + if (!IgnoreErrors) { + Opt->error("error - option can never match, because " + "another positional argument will match an " + "unbounded number of values, and this option" + " does not require a value!"); + errs() << ProgramName << ": CommandLine Error: Option '" + << Opt->ArgStr << "' is all messed up!\n"; + errs() << PositionalOpts.size(); + } + ErrorParsing = true; + } + UnboundedFound |= EatsUnboundedNumberOfValues(Opt); + } + HasUnlimitedPositionals = UnboundedFound || ConsumeAfterOpt; + } + + // PositionalVals - A vector of "positional" arguments we accumulate into + // the process at the end. + // + SmallVector<std::pair<StringRef, unsigned>, 4> PositionalVals; + + // If the program has named positional arguments, and the name has been run + // across, keep track of which positional argument was named. Otherwise put + // the positional args into the PositionalVals list... + Option *ActivePositionalArg = nullptr; + + // Loop over all of the arguments... processing them. + bool DashDashFound = false; // Have we read '--'? + for (int i = FirstArg; i < argc; ++i) { + Option *Handler = nullptr; + Option *NearestHandler = nullptr; + std::string NearestHandlerString; + StringRef Value; + StringRef ArgName = ""; + + // Check to see if this is a positional argument. This argument is + // considered to be positional if it doesn't start with '-', if it is "-" + // itself, or if we have seen "--" already. + // + if (argv[i][0] != '-' || argv[i][1] == 0 || DashDashFound) { + // Positional argument! + if (ActivePositionalArg) { + ProvidePositionalOption(ActivePositionalArg, argv[i], i); + continue; // We are done! + } + + if (!PositionalOpts.empty()) { + PositionalVals.push_back(std::make_pair(argv[i], i)); + + // All of the positional arguments have been fulfulled, give the rest to + // the consume after option... if it's specified... + // + if (PositionalVals.size() >= NumPositionalRequired && ConsumeAfterOpt) { + for (++i; i < argc; ++i) + PositionalVals.push_back(std::make_pair(argv[i], i)); + break; // Handle outside of the argument processing loop... + } + + // Delay processing positional arguments until the end... + continue; + } + } else if (argv[i][0] == '-' && argv[i][1] == '-' && argv[i][2] == 0 && + !DashDashFound) { + DashDashFound = true; // This is the mythical "--"? + continue; // Don't try to process it as an argument itself. + } else if (ActivePositionalArg && + (ActivePositionalArg->getMiscFlags() & PositionalEatsArgs)) { + // If there is a positional argument eating options, check to see if this + // option is another positional argument. If so, treat it as an argument, + // otherwise feed it to the eating positional. + ArgName = argv[i] + 1; + // Eat leading dashes. + while (!ArgName.empty() && ArgName[0] == '-') + ArgName = ArgName.substr(1); + + Handler = LookupOption(*ChosenSubCommand, ArgName, Value); + if (!Handler || Handler->getFormattingFlag() != cl::Positional) { + ProvidePositionalOption(ActivePositionalArg, argv[i], i); + continue; // We are done! + } + + } else { // We start with a '-', must be an argument. + ArgName = argv[i] + 1; + // Eat leading dashes. + while (!ArgName.empty() && ArgName[0] == '-') + ArgName = ArgName.substr(1); + + Handler = LookupOption(*ChosenSubCommand, ArgName, Value); + + // Check to see if this "option" is really a prefixed or grouped argument. + if (!Handler) + Handler = HandlePrefixedOrGroupedOption(ArgName, Value, ErrorParsing, + OptionsMap); + + // Otherwise, look for the closest available option to report to the user + // in the upcoming error. + if (!Handler && SinkOpts.empty()) + NearestHandler = + LookupNearestOption(ArgName, OptionsMap, NearestHandlerString); + } + + if (!Handler) { + if (SinkOpts.empty()) { + if (!IgnoreErrors) { + errs() << ProgramName << ": Unknown command line argument '" + << argv[i] << "'. Try: '" << argv[0] << " -help'\n"; + + if (NearestHandler) { + // If we know a near match, report it as well. + errs() << ProgramName << ": Did you mean '-" << NearestHandlerString + << "'?\n"; + } + } + + ErrorParsing = true; + } else { + for (SmallVectorImpl<Option *>::iterator I = SinkOpts.begin(), + E = SinkOpts.end(); + I != E; ++I) + (*I)->addOccurrence(i, "", argv[i]); + } + continue; + } + + // If this is a named positional argument, just remember that it is the + // active one... + if (Handler->getFormattingFlag() == cl::Positional) + ActivePositionalArg = Handler; + else + ErrorParsing |= ProvideOption(Handler, ArgName, Value, argc, argv, i); + } + + // Check and handle positional arguments now... + if (NumPositionalRequired > PositionalVals.size()) { + if (!IgnoreErrors) { + errs() << ProgramName + << ": Not enough positional command line arguments specified!\n" + << "Must specify at least " << NumPositionalRequired + << " positional argument" << (NumPositionalRequired > 1 ? "s" : "") + << ": See: " << argv[0] << " - help\n"; + } + + ErrorParsing = true; + } else if (!HasUnlimitedPositionals && + PositionalVals.size() > PositionalOpts.size()) { + if (!IgnoreErrors) { + errs() << ProgramName << ": Too many positional arguments specified!\n" + << "Can specify at most " << PositionalOpts.size() + << " positional arguments: See: " << argv[0] << " -help\n"; + } + ErrorParsing = true; + + } else if (!ConsumeAfterOpt) { + // Positional args have already been handled if ConsumeAfter is specified. + unsigned ValNo = 0, NumVals = static_cast<unsigned>(PositionalVals.size()); + for (size_t i = 0, e = PositionalOpts.size(); i != e; ++i) { + if (RequiresValue(PositionalOpts[i])) { + ProvidePositionalOption(PositionalOpts[i], PositionalVals[ValNo].first, + PositionalVals[ValNo].second); + ValNo++; + --NumPositionalRequired; // We fulfilled our duty... + } + + // If we _can_ give this option more arguments, do so now, as long as we + // do not give it values that others need. 'Done' controls whether the + // option even _WANTS_ any more. + // + bool Done = PositionalOpts[i]->getNumOccurrencesFlag() == cl::Required; + while (NumVals - ValNo > NumPositionalRequired && !Done) { + switch (PositionalOpts[i]->getNumOccurrencesFlag()) { + case cl::Optional: + Done = true; // Optional arguments want _at most_ one value + LLVM_FALLTHROUGH; + case cl::ZeroOrMore: // Zero or more will take all they can get... + case cl::OneOrMore: // One or more will take all they can get... + ProvidePositionalOption(PositionalOpts[i], + PositionalVals[ValNo].first, + PositionalVals[ValNo].second); + ValNo++; + break; + default: + llvm_unreachable("Internal error, unexpected NumOccurrences flag in " + "positional argument processing!"); + } + } + } + } else { + assert(ConsumeAfterOpt && NumPositionalRequired <= PositionalVals.size()); + unsigned ValNo = 0; + for (size_t j = 1, e = PositionalOpts.size(); j != e; ++j) + if (RequiresValue(PositionalOpts[j])) { + ErrorParsing |= ProvidePositionalOption(PositionalOpts[j], + PositionalVals[ValNo].first, + PositionalVals[ValNo].second); + ValNo++; + } + + // Handle the case where there is just one positional option, and it's + // optional. In this case, we want to give JUST THE FIRST option to the + // positional option and keep the rest for the consume after. The above + // loop would have assigned no values to positional options in this case. + // + if (PositionalOpts.size() == 1 && ValNo == 0 && !PositionalVals.empty()) { + ErrorParsing |= ProvidePositionalOption(PositionalOpts[0], + PositionalVals[ValNo].first, + PositionalVals[ValNo].second); + ValNo++; + } + + // Handle over all of the rest of the arguments to the + // cl::ConsumeAfter command line option... + for (; ValNo != PositionalVals.size(); ++ValNo) + ErrorParsing |= + ProvidePositionalOption(ConsumeAfterOpt, PositionalVals[ValNo].first, + PositionalVals[ValNo].second); + } + + // Loop over args and make sure all required args are specified! + for (const auto &Opt : OptionsMap) { + switch (Opt.second->getNumOccurrencesFlag()) { + case Required: + case OneOrMore: + if (Opt.second->getNumOccurrences() == 0) { + Opt.second->error("must be specified at least once!"); + ErrorParsing = true; + } + LLVM_FALLTHROUGH; + default: + break; + } + } + + // Now that we know if -debug is specified, we can use it. + // Note that if ReadResponseFiles == true, this must be done before the + // memory allocated for the expanded command line is free()d below. + DEBUG(dbgs() << "Args: "; + for (int i = 0; i < argc; ++i) dbgs() << argv[i] << ' '; + dbgs() << '\n';); + + // Free all of the memory allocated to the map. Command line options may only + // be processed once! + MoreHelp.clear(); + + // If we had an error processing our arguments, don't let the program execute + if (ErrorParsing) { + if (!IgnoreErrors) + exit(1); + return false; + } + return true; +} + +//===----------------------------------------------------------------------===// +// Option Base class implementation +// + +bool Option::error(const Twine &Message, StringRef ArgName) { + if (!ArgName.data()) + ArgName = ArgStr; + if (ArgName.empty()) + errs() << HelpStr; // Be nice for positional arguments + else + errs() << GlobalParser->ProgramName << ": for the -" << ArgName; + + errs() << " option: " << Message << "\n"; + return true; +} + +bool Option::addOccurrence(unsigned pos, StringRef ArgName, StringRef Value, + bool MultiArg) { + if (!MultiArg) + NumOccurrences++; // Increment the number of times we have been seen + + switch (getNumOccurrencesFlag()) { + case Optional: + if (NumOccurrences > 1) + return error("may only occur zero or one times!", ArgName); + break; + case Required: + if (NumOccurrences > 1) + return error("must occur exactly one time!", ArgName); + LLVM_FALLTHROUGH; + case OneOrMore: + case ZeroOrMore: + case ConsumeAfter: + break; + } + + return handleOccurrence(pos, ArgName, Value); +} + +// getValueStr - Get the value description string, using "DefaultMsg" if nothing +// has been specified yet. +// +static StringRef getValueStr(const Option &O, StringRef DefaultMsg) { + if (O.ValueStr.empty()) + return DefaultMsg; + return O.ValueStr; +} + +//===----------------------------------------------------------------------===// +// cl::alias class implementation +// + +// Return the width of the option tag for printing... +size_t alias::getOptionWidth() const { return ArgStr.size() + 6; } + +static void printHelpStr(StringRef HelpStr, size_t Indent, + size_t FirstLineIndentedBy) { + std::pair<StringRef, StringRef> Split = HelpStr.split('\n'); + outs().indent(Indent - FirstLineIndentedBy) << " - " << Split.first << "\n"; + while (!Split.second.empty()) { + Split = Split.second.split('\n'); + outs().indent(Indent) << Split.first << "\n"; + } +} + +// Print out the option for the alias. +void alias::printOptionInfo(size_t GlobalWidth) const { + outs() << " -" << ArgStr; + printHelpStr(HelpStr, GlobalWidth, ArgStr.size() + 6); +} + +//===----------------------------------------------------------------------===// +// Parser Implementation code... +// + +// basic_parser implementation +// + +// Return the width of the option tag for printing... +size_t basic_parser_impl::getOptionWidth(const Option &O) const { + size_t Len = O.ArgStr.size(); + if (const char *ValName = getValueName()) + Len += getValueStr(O, ValName).size() + 3; + + return Len + 6; +} + +// printOptionInfo - Print out information about this option. The +// to-be-maintained width is specified. +// +void basic_parser_impl::printOptionInfo(const Option &O, + size_t GlobalWidth) const { + outs() << " -" << O.ArgStr; + + if (const char *ValName = getValueName()) + outs() << "=<" << getValueStr(O, ValName) << '>'; + + printHelpStr(O.HelpStr, GlobalWidth, getOptionWidth(O)); +} + +void basic_parser_impl::printOptionName(const Option &O, + size_t GlobalWidth) const { + outs() << " -" << O.ArgStr; + outs().indent(GlobalWidth - O.ArgStr.size()); +} + +// parser<bool> implementation +// +bool parser<bool>::parse(Option &O, StringRef ArgName, StringRef Arg, + bool &Value) { + if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" || + Arg == "1") { + Value = true; + return false; + } + + if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") { + Value = false; + return false; + } + return O.error("'" + Arg + + "' is invalid value for boolean argument! Try 0 or 1"); +} + +// parser<boolOrDefault> implementation +// +bool parser<boolOrDefault>::parse(Option &O, StringRef ArgName, StringRef Arg, + boolOrDefault &Value) { + if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" || + Arg == "1") { + Value = BOU_TRUE; + return false; + } + if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") { + Value = BOU_FALSE; + return false; + } + + return O.error("'" + Arg + + "' is invalid value for boolean argument! Try 0 or 1"); +} + +// parser<int> implementation +// +bool parser<int>::parse(Option &O, StringRef ArgName, StringRef Arg, + int &Value) { + if (Arg.getAsInteger(0, Value)) + return O.error("'" + Arg + "' value invalid for integer argument!"); + return false; +} + +// parser<unsigned> implementation +// +bool parser<unsigned>::parse(Option &O, StringRef ArgName, StringRef Arg, + unsigned &Value) { + + if (Arg.getAsInteger(0, Value)) + return O.error("'" + Arg + "' value invalid for uint argument!"); + return false; +} + +// parser<unsigned long long> implementation +// +bool parser<unsigned long long>::parse(Option &O, StringRef ArgName, + StringRef Arg, + unsigned long long &Value) { + + if (Arg.getAsInteger(0, Value)) + return O.error("'" + Arg + "' value invalid for uint argument!"); + return false; +} + +// parser<double>/parser<float> implementation +// +static bool parseDouble(Option &O, StringRef Arg, double &Value) { + SmallString<32> TmpStr(Arg.begin(), Arg.end()); + const char *ArgStart = TmpStr.c_str(); + char *End; + Value = strtod(ArgStart, &End); + if (*End != 0) + return O.error("'" + Arg + "' value invalid for floating point argument!"); + return false; +} + +bool parser<double>::parse(Option &O, StringRef ArgName, StringRef Arg, + double &Val) { + return parseDouble(O, Arg, Val); +} + +bool parser<float>::parse(Option &O, StringRef ArgName, StringRef Arg, + float &Val) { + double dVal; + if (parseDouble(O, Arg, dVal)) + return true; + Val = (float)dVal; + return false; +} + +// generic_parser_base implementation +// + +// findOption - Return the option number corresponding to the specified +// argument string. If the option is not found, getNumOptions() is returned. +// +unsigned generic_parser_base::findOption(const char *Name) { + unsigned e = getNumOptions(); + + for (unsigned i = 0; i != e; ++i) { + if (strcmp(getOption(i), Name) == 0) + return i; + } + return e; +} + +// Return the width of the option tag for printing... +size_t generic_parser_base::getOptionWidth(const Option &O) const { + if (O.hasArgStr()) { + size_t Size = O.ArgStr.size() + 6; + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) + Size = std::max(Size, std::strlen(getOption(i)) + 8); + return Size; + } else { + size_t BaseSize = 0; + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) + BaseSize = std::max(BaseSize, std::strlen(getOption(i)) + 8); + return BaseSize; + } +} + +// printOptionInfo - Print out information about this option. The +// to-be-maintained width is specified. +// +void generic_parser_base::printOptionInfo(const Option &O, + size_t GlobalWidth) const { + if (O.hasArgStr()) { + outs() << " -" << O.ArgStr; + printHelpStr(O.HelpStr, GlobalWidth, O.ArgStr.size() + 6); + + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { + size_t NumSpaces = GlobalWidth - strlen(getOption(i)) - 8; + outs() << " =" << getOption(i); + outs().indent(NumSpaces) << " - " << getDescription(i) << '\n'; + } + } else { + if (!O.HelpStr.empty()) + outs() << " " << O.HelpStr << '\n'; + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { + const char *Option = getOption(i); + outs() << " -" << Option; + printHelpStr(getDescription(i), GlobalWidth, std::strlen(Option) + 8); + } + } +} + +static const size_t MaxOptWidth = 8; // arbitrary spacing for printOptionDiff + +// printGenericOptionDiff - Print the value of this option and it's default. +// +// "Generic" options have each value mapped to a name. +void generic_parser_base::printGenericOptionDiff( + const Option &O, const GenericOptionValue &Value, + const GenericOptionValue &Default, size_t GlobalWidth) const { + outs() << " -" << O.ArgStr; + outs().indent(GlobalWidth - O.ArgStr.size()); + + unsigned NumOpts = getNumOptions(); + for (unsigned i = 0; i != NumOpts; ++i) { + if (Value.compare(getOptionValue(i))) + continue; + + outs() << "= " << getOption(i); + size_t L = std::strlen(getOption(i)); + size_t NumSpaces = MaxOptWidth > L ? MaxOptWidth - L : 0; + outs().indent(NumSpaces) << " (default: "; + for (unsigned j = 0; j != NumOpts; ++j) { + if (Default.compare(getOptionValue(j))) + continue; + outs() << getOption(j); + break; + } + outs() << ")\n"; + return; + } + outs() << "= *unknown option value*\n"; +} + +// printOptionDiff - Specializations for printing basic value types. +// +#define PRINT_OPT_DIFF(T) \ + void parser<T>::printOptionDiff(const Option &O, T V, OptionValue<T> D, \ + size_t GlobalWidth) const { \ + printOptionName(O, GlobalWidth); \ + std::string Str; \ + { \ + raw_string_ostream SS(Str); \ + SS << V; \ + } \ + outs() << "= " << Str; \ + size_t NumSpaces = \ + MaxOptWidth > Str.size() ? MaxOptWidth - Str.size() : 0; \ + outs().indent(NumSpaces) << " (default: "; \ + if (D.hasValue()) \ + outs() << D.getValue(); \ + else \ + outs() << "*no default*"; \ + outs() << ")\n"; \ + } + +PRINT_OPT_DIFF(bool) +PRINT_OPT_DIFF(boolOrDefault) +PRINT_OPT_DIFF(int) +PRINT_OPT_DIFF(unsigned) +PRINT_OPT_DIFF(unsigned long long) +PRINT_OPT_DIFF(double) +PRINT_OPT_DIFF(float) +PRINT_OPT_DIFF(char) + +void parser<std::string>::printOptionDiff(const Option &O, StringRef V, + const OptionValue<std::string> &D, + size_t GlobalWidth) const { + printOptionName(O, GlobalWidth); + outs() << "= " << V; + size_t NumSpaces = MaxOptWidth > V.size() ? MaxOptWidth - V.size() : 0; + outs().indent(NumSpaces) << " (default: "; + if (D.hasValue()) + outs() << D.getValue(); + else + outs() << "*no default*"; + outs() << ")\n"; +} + +// Print a placeholder for options that don't yet support printOptionDiff(). +void basic_parser_impl::printOptionNoValue(const Option &O, + size_t GlobalWidth) const { + printOptionName(O, GlobalWidth); + outs() << "= *cannot print option value*\n"; +} + +//===----------------------------------------------------------------------===// +// -help and -help-hidden option implementation +// + +static int OptNameCompare(const std::pair<const char *, Option *> *LHS, + const std::pair<const char *, Option *> *RHS) { + return strcmp(LHS->first, RHS->first); +} + +static int SubNameCompare(const std::pair<const char *, SubCommand *> *LHS, + const std::pair<const char *, SubCommand *> *RHS) { + return strcmp(LHS->first, RHS->first); +} + +// Copy Options into a vector so we can sort them as we like. +static void sortOpts(StringMap<Option *> &OptMap, + SmallVectorImpl<std::pair<const char *, Option *>> &Opts, + bool ShowHidden) { + SmallPtrSet<Option *, 32> OptionSet; // Duplicate option detection. + + for (StringMap<Option *>::iterator I = OptMap.begin(), E = OptMap.end(); + I != E; ++I) { + // Ignore really-hidden options. + if (I->second->getOptionHiddenFlag() == ReallyHidden) + continue; + + // Unless showhidden is set, ignore hidden flags. + if (I->second->getOptionHiddenFlag() == Hidden && !ShowHidden) + continue; + + // If we've already seen this option, don't add it to the list again. + if (!OptionSet.insert(I->second).second) + continue; + + Opts.push_back( + std::pair<const char *, Option *>(I->getKey().data(), I->second)); + } + + // Sort the options list alphabetically. + array_pod_sort(Opts.begin(), Opts.end(), OptNameCompare); +} + +static void +sortSubCommands(const SmallPtrSetImpl<SubCommand *> &SubMap, + SmallVectorImpl<std::pair<const char *, SubCommand *>> &Subs) { + for (const auto &S : SubMap) { + if (S->getName() == nullptr) + continue; + Subs.push_back(std::make_pair(S->getName(), S)); + } + array_pod_sort(Subs.begin(), Subs.end(), SubNameCompare); +} + +namespace { + +class HelpPrinter { +protected: + const bool ShowHidden; + typedef SmallVector<std::pair<const char *, Option *>, 128> + StrOptionPairVector; + typedef SmallVector<std::pair<const char *, SubCommand *>, 128> + StrSubCommandPairVector; + // Print the options. Opts is assumed to be alphabetically sorted. + virtual void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) { + for (size_t i = 0, e = Opts.size(); i != e; ++i) + Opts[i].second->printOptionInfo(MaxArgLen); + } + + void printSubCommands(StrSubCommandPairVector &Subs, size_t MaxSubLen) { + for (const auto &S : Subs) { + outs() << " " << S.first; + if (S.second->getDescription()) { + outs().indent(MaxSubLen - strlen(S.first)); + outs() << " - " << S.second->getDescription(); + } + outs() << "\n"; + } + } + +public: + explicit HelpPrinter(bool showHidden) : ShowHidden(showHidden) {} + virtual ~HelpPrinter() {} + + // Invoke the printer. + void operator=(bool Value) { + if (!Value) + return; + + SubCommand *Sub = GlobalParser->getActiveSubCommand(); + auto &OptionsMap = Sub->OptionsMap; + auto &PositionalOpts = Sub->PositionalOpts; + auto &ConsumeAfterOpt = Sub->ConsumeAfterOpt; + + StrOptionPairVector Opts; + sortOpts(OptionsMap, Opts, ShowHidden); + + StrSubCommandPairVector Subs; + sortSubCommands(GlobalParser->RegisteredSubCommands, Subs); + + if (GlobalParser->ProgramOverview) + outs() << "OVERVIEW: " << GlobalParser->ProgramOverview << "\n"; + + if (Sub == &*TopLevelSubCommand) + outs() << "USAGE: " << GlobalParser->ProgramName + << " [subcommand] [options]"; + else { + if (Sub->getDescription() != nullptr) { + outs() << "SUBCOMMAND '" << Sub->getName() + << "': " << Sub->getDescription() << "\n\n"; + } + outs() << "USAGE: " << GlobalParser->ProgramName << " " << Sub->getName() + << " [options]"; + } + + for (auto Opt : PositionalOpts) { + if (Opt->hasArgStr()) + outs() << " --" << Opt->ArgStr; + outs() << " " << Opt->HelpStr; + } + + // Print the consume after option info if it exists... + if (ConsumeAfterOpt) + outs() << " " << ConsumeAfterOpt->HelpStr; + + if (Sub == &*TopLevelSubCommand && Subs.size() > 2) { + // Compute the maximum subcommand length... + size_t MaxSubLen = 0; + for (size_t i = 0, e = Subs.size(); i != e; ++i) + MaxSubLen = std::max(MaxSubLen, strlen(Subs[i].first)); + + outs() << "\n\n"; + outs() << "SUBCOMMANDS:\n\n"; + printSubCommands(Subs, MaxSubLen); + outs() << "\n"; + outs() << " Type \"" << GlobalParser->ProgramName + << " <subcommand> -help\" to get more help on a specific " + "subcommand"; + } + + outs() << "\n\n"; + + // Compute the maximum argument length... + size_t MaxArgLen = 0; + for (size_t i = 0, e = Opts.size(); i != e; ++i) + MaxArgLen = std::max(MaxArgLen, Opts[i].second->getOptionWidth()); + + outs() << "OPTIONS:\n"; + printOptions(Opts, MaxArgLen); + + // Print any extra help the user has declared. + for (auto I : GlobalParser->MoreHelp) + outs() << I; + GlobalParser->MoreHelp.clear(); + + // Halt the program since help information was printed + exit(0); + } +}; + +class CategorizedHelpPrinter : public HelpPrinter { +public: + explicit CategorizedHelpPrinter(bool showHidden) : HelpPrinter(showHidden) {} + + // Helper function for printOptions(). + // It shall return a negative value if A's name should be lexicographically + // ordered before B's name. It returns a value greater equal zero otherwise. + static int OptionCategoryCompare(OptionCategory *const *A, + OptionCategory *const *B) { + return strcmp((*A)->getName(), (*B)->getName()); + } + + // Make sure we inherit our base class's operator=() + using HelpPrinter::operator=; + +protected: + void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) override { + std::vector<OptionCategory *> SortedCategories; + std::map<OptionCategory *, std::vector<Option *>> CategorizedOptions; + + // Collect registered option categories into vector in preparation for + // sorting. + for (auto I = GlobalParser->RegisteredOptionCategories.begin(), + E = GlobalParser->RegisteredOptionCategories.end(); + I != E; ++I) { + SortedCategories.push_back(*I); + } + + // Sort the different option categories alphabetically. + assert(SortedCategories.size() > 0 && "No option categories registered!"); + array_pod_sort(SortedCategories.begin(), SortedCategories.end(), + OptionCategoryCompare); + + // Create map to empty vectors. + for (std::vector<OptionCategory *>::const_iterator + I = SortedCategories.begin(), + E = SortedCategories.end(); + I != E; ++I) + CategorizedOptions[*I] = std::vector<Option *>(); + + // Walk through pre-sorted options and assign into categories. + // Because the options are already alphabetically sorted the + // options within categories will also be alphabetically sorted. + for (size_t I = 0, E = Opts.size(); I != E; ++I) { + Option *Opt = Opts[I].second; + assert(CategorizedOptions.count(Opt->Category) > 0 && + "Option has an unregistered category"); + CategorizedOptions[Opt->Category].push_back(Opt); + } + + // Now do printing. + for (std::vector<OptionCategory *>::const_iterator + Category = SortedCategories.begin(), + E = SortedCategories.end(); + Category != E; ++Category) { + // Hide empty categories for -help, but show for -help-hidden. + const auto &CategoryOptions = CategorizedOptions[*Category]; + bool IsEmptyCategory = CategoryOptions.empty(); + if (!ShowHidden && IsEmptyCategory) + continue; + + // Print category information. + outs() << "\n"; + outs() << (*Category)->getName() << ":\n"; + + // Check if description is set. + if ((*Category)->getDescription() != nullptr) + outs() << (*Category)->getDescription() << "\n\n"; + else + outs() << "\n"; + + // When using -help-hidden explicitly state if the category has no + // options associated with it. + if (IsEmptyCategory) { + outs() << " This option category has no options.\n"; + continue; + } + // Loop over the options in the category and print. + for (const Option *Opt : CategoryOptions) + Opt->printOptionInfo(MaxArgLen); + } + } +}; + +// This wraps the Uncategorizing and Categorizing printers and decides +// at run time which should be invoked. +class HelpPrinterWrapper { +private: + HelpPrinter &UncategorizedPrinter; + CategorizedHelpPrinter &CategorizedPrinter; + +public: + explicit HelpPrinterWrapper(HelpPrinter &UncategorizedPrinter, + CategorizedHelpPrinter &CategorizedPrinter) + : UncategorizedPrinter(UncategorizedPrinter), + CategorizedPrinter(CategorizedPrinter) {} + + // Invoke the printer. + void operator=(bool Value); +}; + +} // End anonymous namespace + +// Declare the four HelpPrinter instances that are used to print out help, or +// help-hidden as an uncategorized list or in categories. +static HelpPrinter UncategorizedNormalPrinter(false); +static HelpPrinter UncategorizedHiddenPrinter(true); +static CategorizedHelpPrinter CategorizedNormalPrinter(false); +static CategorizedHelpPrinter CategorizedHiddenPrinter(true); + +// Declare HelpPrinter wrappers that will decide whether or not to invoke +// a categorizing help printer +static HelpPrinterWrapper WrappedNormalPrinter(UncategorizedNormalPrinter, + CategorizedNormalPrinter); +static HelpPrinterWrapper WrappedHiddenPrinter(UncategorizedHiddenPrinter, + CategorizedHiddenPrinter); + +// Define a category for generic options that all tools should have. +static cl::OptionCategory GenericCategory("Generic Options"); + +// Define uncategorized help printers. +// -help-list is hidden by default because if Option categories are being used +// then -help behaves the same as -help-list. +static cl::opt<HelpPrinter, true, parser<bool>> HLOp( + "help-list", + cl::desc("Display list of available options (-help-list-hidden for more)"), + cl::location(UncategorizedNormalPrinter), cl::Hidden, cl::ValueDisallowed, + cl::cat(GenericCategory), cl::sub(*AllSubCommands)); + +static cl::opt<HelpPrinter, true, parser<bool>> + HLHOp("help-list-hidden", cl::desc("Display list of all available options"), + cl::location(UncategorizedHiddenPrinter), cl::Hidden, + cl::ValueDisallowed, cl::cat(GenericCategory), + cl::sub(*AllSubCommands)); + +// Define uncategorized/categorized help printers. These printers change their +// behaviour at runtime depending on whether one or more Option categories have +// been declared. +static cl::opt<HelpPrinterWrapper, true, parser<bool>> + HOp("help", cl::desc("Display available options (-help-hidden for more)"), + cl::location(WrappedNormalPrinter), cl::ValueDisallowed, + cl::cat(GenericCategory), cl::sub(*AllSubCommands)); + +static cl::opt<HelpPrinterWrapper, true, parser<bool>> + HHOp("help-hidden", cl::desc("Display all available options"), + cl::location(WrappedHiddenPrinter), cl::Hidden, cl::ValueDisallowed, + cl::cat(GenericCategory), cl::sub(*AllSubCommands)); + +static cl::opt<bool> PrintOptions( + "print-options", + cl::desc("Print non-default options after command line parsing"), + cl::Hidden, cl::init(false), cl::cat(GenericCategory), + cl::sub(*AllSubCommands)); + +static cl::opt<bool> PrintAllOptions( + "print-all-options", + cl::desc("Print all option values after command line parsing"), cl::Hidden, + cl::init(false), cl::cat(GenericCategory), cl::sub(*AllSubCommands)); + +void HelpPrinterWrapper::operator=(bool Value) { + if (!Value) + return; + + // Decide which printer to invoke. If more than one option category is + // registered then it is useful to show the categorized help instead of + // uncategorized help. + if (GlobalParser->RegisteredOptionCategories.size() > 1) { + // unhide -help-list option so user can have uncategorized output if they + // want it. + HLOp.setHiddenFlag(NotHidden); + + CategorizedPrinter = true; // Invoke categorized printer + } else + UncategorizedPrinter = true; // Invoke uncategorized printer +} + +// Print the value of each option. +void cl::PrintOptionValues() { GlobalParser->printOptionValues(); } + +void CommandLineParser::printOptionValues() { + if (!PrintOptions && !PrintAllOptions) + return; + + SmallVector<std::pair<const char *, Option *>, 128> Opts; + sortOpts(ActiveSubCommand->OptionsMap, Opts, /*ShowHidden*/ true); + + // Compute the maximum argument length... + size_t MaxArgLen = 0; + for (size_t i = 0, e = Opts.size(); i != e; ++i) + MaxArgLen = std::max(MaxArgLen, Opts[i].second->getOptionWidth()); + + for (size_t i = 0, e = Opts.size(); i != e; ++i) + Opts[i].second->printOptionValue(MaxArgLen, PrintAllOptions); +} + +static void (*OverrideVersionPrinter)() = nullptr; + +static std::vector<void (*)()> *ExtraVersionPrinters = nullptr; + +namespace { +class VersionPrinter { +public: + void print() { + raw_ostream &OS = outs(); +#ifdef PACKAGE_VENDOR + OS << PACKAGE_VENDOR << " "; +#else + OS << "LLVM (http://llvm.org/):\n "; +#endif + OS << PACKAGE_NAME << " version " << PACKAGE_VERSION; +#ifdef LLVM_VERSION_INFO + OS << " " << LLVM_VERSION_INFO; +#endif + OS << "\n "; +#ifndef __OPTIMIZE__ + OS << "DEBUG build"; +#else + OS << "Optimized build"; +#endif +#ifndef NDEBUG + OS << " with assertions"; +#endif + std::string CPU = sys::getHostCPUName(); + if (CPU == "generic") + CPU = "(unknown)"; + OS << ".\n" + << " Default target: " << sys::getDefaultTargetTriple() << '\n' + << " Host CPU: " << CPU << '\n'; + } + void operator=(bool OptionWasSpecified) { + if (!OptionWasSpecified) + return; + + if (OverrideVersionPrinter != nullptr) { + (*OverrideVersionPrinter)(); + exit(0); + } + print(); + + // Iterate over any registered extra printers and call them to add further + // information. + if (ExtraVersionPrinters != nullptr) { + outs() << '\n'; + for (std::vector<void (*)()>::iterator I = ExtraVersionPrinters->begin(), + E = ExtraVersionPrinters->end(); + I != E; ++I) + (*I)(); + } + + exit(0); + } +}; +} // End anonymous namespace + +// Define the --version option that prints out the LLVM version for the tool +static VersionPrinter VersionPrinterInstance; + +static cl::opt<VersionPrinter, true, parser<bool>> + VersOp("version", cl::desc("Display the version of this program"), + cl::location(VersionPrinterInstance), cl::ValueDisallowed, + cl::cat(GenericCategory)); + +// Utility function for printing the help message. +void cl::PrintHelpMessage(bool Hidden, bool Categorized) { + // This looks weird, but it actually prints the help message. The Printers are + // types of HelpPrinter and the help gets printed when its operator= is + // invoked. That's because the "normal" usages of the help printer is to be + // assigned true/false depending on whether -help or -help-hidden was given or + // not. Since we're circumventing that we have to make it look like -help or + // -help-hidden were given, so we assign true. + + if (!Hidden && !Categorized) + UncategorizedNormalPrinter = true; + else if (!Hidden && Categorized) + CategorizedNormalPrinter = true; + else if (Hidden && !Categorized) + UncategorizedHiddenPrinter = true; + else + CategorizedHiddenPrinter = true; +} + +/// Utility function for printing version number. +void cl::PrintVersionMessage() { VersionPrinterInstance.print(); } + +void cl::SetVersionPrinter(void (*func)()) { OverrideVersionPrinter = func; } + +void cl::AddExtraVersionPrinter(void (*func)()) { + if (!ExtraVersionPrinters) + ExtraVersionPrinters = new std::vector<void (*)()>; + + ExtraVersionPrinters->push_back(func); +} + +StringMap<Option *> &cl::getRegisteredOptions(SubCommand &Sub) { + auto &Subs = GlobalParser->RegisteredSubCommands; + (void)Subs; + assert(is_contained(Subs, &Sub)); + return Sub.OptionsMap; +} + +void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) { + for (auto &I : Sub.OptionsMap) { + if (I.second->Category != &Category && + I.second->Category != &GenericCategory) + I.second->setHiddenFlag(cl::ReallyHidden); + } +} + +void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories, + SubCommand &Sub) { + auto CategoriesBegin = Categories.begin(); + auto CategoriesEnd = Categories.end(); + for (auto &I : Sub.OptionsMap) { + if (std::find(CategoriesBegin, CategoriesEnd, I.second->Category) == + CategoriesEnd && + I.second->Category != &GenericCategory) + I.second->setHiddenFlag(cl::ReallyHidden); + } +} + +void cl::ResetCommandLineParser() { GlobalParser->reset(); } +void cl::ResetAllOptionOccurrences() { + GlobalParser->ResetAllOptionOccurrences(); +} + +void LLVMParseCommandLineOptions(int argc, const char *const *argv, + const char *Overview) { + llvm::cl::ParseCommandLineOptions(argc, argv, Overview, true); +}
diff --git a/third_party/llvm-subzero/lib/Support/ConvertUTF.c b/third_party/llvm-subzero/lib/Support/ConvertUTF.c new file mode 100644 index 0000000..128459a --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/ConvertUTF.c
@@ -0,0 +1,708 @@ +/*===--- ConvertUTF.c - Universal Character Names conversions ---------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===------------------------------------------------------------------------=*/ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Source code file. + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Sept 2001: fixed const & error conditions per + mods suggested by S. Parent & A. Lillich. + June 2002: Tim Dodd added detection and handling of incomplete + source sequences, enhanced error detection, added casts + to eliminate compiler warnings. + July 2003: slight mods to back out aggressive FFFE detection. + Jan 2004: updated switches in from-UTF8 conversions. + Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. + + See the header file "ConvertUTF.h" for complete documentation. + +------------------------------------------------------------------------ */ + + +#include "llvm/Support/ConvertUTF.h" +#ifdef CVTUTF_DEBUG +#include <stdio.h> +#endif +#include <assert.h> + +static const int halfShift = 10; /* used for shifting by 10 bits */ + +static const UTF32 halfBase = 0x0010000UL; +static const UTF32 halfMask = 0x3FFUL; + +#define UNI_SUR_HIGH_START (UTF32)0xD800 +#define UNI_SUR_HIGH_END (UTF32)0xDBFF +#define UNI_SUR_LOW_START (UTF32)0xDC00 +#define UNI_SUR_LOW_END (UTF32)0xDFFF +#define false 0 +#define true 1 + +/* --------------------------------------------------------------------- */ + +/* + * Index into the table below with the first byte of a UTF-8 sequence to + * get the number of trailing bytes that are supposed to follow it. + * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is + * left as-is for anyone who may want to do such conversion, which was + * allowed in earlier algorithms. + */ +static const char trailingBytesForUTF8[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + +/* + * Magic values subtracted from a buffer value during UTF8 conversion. + * This table contains as many values as there might be trailing bytes + * in a UTF-8 sequence. + */ +static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, + 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; + +/* + * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed + * into the first byte, depending on how many bytes follow. There are + * as many entries in this table as there are UTF-8 sequence types. + * (I.e., one byte sequence, two byte... etc.). Remember that sequencs + * for *legal* UTF-8 will be 4 or fewer bytes total. + */ +static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +/* --------------------------------------------------------------------- */ + +/* The interface converts a whole buffer to avoid function-call overhead. + * Constants have been gathered. Loops & conditionals have been removed as + * much as possible for efficiency, in favor of drop-through switches. + * (See "Note A" at the bottom of the file for equivalent code.) + * If your compiler supports it, the "isLegalUTF8" call can be turned + * into an inline function. + */ + + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF32toUTF16 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF32* source = *sourceStart; + UTF16* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + if (target >= targetEnd) { + result = targetExhausted; break; + } + ch = *source++; + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_LEGAL_UTF32) { + if (flags == strictConversion) { + result = sourceIllegal; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + --source; /* Back up source pointer! */ + result = targetExhausted; break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF16toUTF32 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16* source = *sourceStart; + UTF32* target = *targetStart; + UTF32 ch, ch2; + while (source < sourceEnd) { + const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + if (target >= targetEnd) { + source = oldSource; /* Back up source pointer! */ + result = targetExhausted; break; + } + *target++ = ch; + } + *sourceStart = source; + *targetStart = target; +#ifdef CVTUTF_DEBUG +if (result == sourceIllegal) { + fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); + fflush(stderr); +} +#endif + return result; +} +ConversionResult ConvertUTF16toUTF8 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16* source = *sourceStart; + UTF8* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + UTF32 ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* Figure out how many bytes the result will require */ + if (ch < (UTF32)0x80) { bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; + } else if (ch < (UTF32)0x110000) { bytesToWrite = 4; + } else { bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + } + + target += bytesToWrite; + if (target > targetEnd) { + source = oldSource; /* Back up source pointer! */ + target -= bytesToWrite; result = targetExhausted; break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF32toUTF8 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF32* source = *sourceStart; + UTF8* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + ch = *source++; + if (flags == strictConversion ) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* + * Figure out how many bytes the result will require. Turn any + * illegally large UTF32 things (> Plane 17) into replacement chars. + */ + if (ch < (UTF32)0x80) { bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; + } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4; + } else { bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + result = sourceIllegal; + } + + target += bytesToWrite; + if (target > targetEnd) { + --source; /* Back up source pointer! */ + target -= bytesToWrite; result = targetExhausted; break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +/* + * Utility routine to tell whether a sequence of bytes is legal UTF-8. + * This must be called with the length pre-determined by the first byte. + * If not calling this from ConvertUTF8to*, then the length can be set by: + * length = trailingBytesForUTF8[*source]+1; + * and the sequence is illegal right away if there aren't that many bytes + * available. + * If presented with a length > 4, this returns false. The Unicode + * definition of UTF-8 goes up to 4-byte sequences. + */ + +static Boolean isLegalUTF8(const UTF8 *source, int length) { + UTF8 a; + const UTF8 *srcptr = source+length; + switch (length) { + default: return false; + /* Everything else falls through when "true"... */ + case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 2: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + + switch (*source) { + /* no fall-through in this inner switch */ + case 0xE0: if (a < 0xA0) return false; break; + case 0xED: if (a > 0x9F) return false; break; + case 0xF0: if (a < 0x90) return false; break; + case 0xF4: if (a > 0x8F) return false; break; + default: if (a < 0x80) return false; + } + + case 1: if (*source >= 0x80 && *source < 0xC2) return false; + } + if (*source > 0xF4) return false; + return true; +} + +/* --------------------------------------------------------------------- */ + +/* + * Exported function to return whether a UTF-8 sequence is legal or not. + * This is not used here; it's just exported. + */ +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { + int length = trailingBytesForUTF8[*source]+1; + if (length > sourceEnd - source) { + return false; + } + return isLegalUTF8(source, length); +} + +/* --------------------------------------------------------------------- */ + +static unsigned +findMaximalSubpartOfIllFormedUTF8Sequence(const UTF8 *source, + const UTF8 *sourceEnd) { + UTF8 b1, b2, b3; + + assert(!isLegalUTF8Sequence(source, sourceEnd)); + + /* + * Unicode 6.3.0, D93b: + * + * Maximal subpart of an ill-formed subsequence: The longest code unit + * subsequence starting at an unconvertible offset that is either: + * a. the initial subsequence of a well-formed code unit sequence, or + * b. a subsequence of length one. + */ + + if (source == sourceEnd) + return 0; + + /* + * Perform case analysis. See Unicode 6.3.0, Table 3-7. Well-Formed UTF-8 + * Byte Sequences. + */ + + b1 = *source; + ++source; + if (b1 >= 0xC2 && b1 <= 0xDF) { + /* + * First byte is valid, but we know that this code unit sequence is + * invalid, so the maximal subpart has to end after the first byte. + */ + return 1; + } + + if (source == sourceEnd) + return 1; + + b2 = *source; + ++source; + + if (b1 == 0xE0) { + return (b2 >= 0xA0 && b2 <= 0xBF) ? 2 : 1; + } + if (b1 >= 0xE1 && b1 <= 0xEC) { + return (b2 >= 0x80 && b2 <= 0xBF) ? 2 : 1; + } + if (b1 == 0xED) { + return (b2 >= 0x80 && b2 <= 0x9F) ? 2 : 1; + } + if (b1 >= 0xEE && b1 <= 0xEF) { + return (b2 >= 0x80 && b2 <= 0xBF) ? 2 : 1; + } + if (b1 == 0xF0) { + if (b2 >= 0x90 && b2 <= 0xBF) { + if (source == sourceEnd) + return 2; + + b3 = *source; + return (b3 >= 0x80 && b3 <= 0xBF) ? 3 : 2; + } + return 1; + } + if (b1 >= 0xF1 && b1 <= 0xF3) { + if (b2 >= 0x80 && b2 <= 0xBF) { + if (source == sourceEnd) + return 2; + + b3 = *source; + return (b3 >= 0x80 && b3 <= 0xBF) ? 3 : 2; + } + return 1; + } + if (b1 == 0xF4) { + if (b2 >= 0x80 && b2 <= 0x8F) { + if (source == sourceEnd) + return 2; + + b3 = *source; + return (b3 >= 0x80 && b3 <= 0xBF) ? 3 : 2; + } + return 1; + } + + assert((b1 >= 0x80 && b1 <= 0xC1) || b1 >= 0xF5); + /* + * There are no valid sequences that start with these bytes. Maximal subpart + * is defined to have length 1 in these cases. + */ + return 1; +} + +/* --------------------------------------------------------------------- */ + +/* + * Exported function to return the total number of bytes in a codepoint + * represented in UTF-8, given the value of the first byte. + */ +unsigned getNumBytesForUTF8(UTF8 first) { + return trailingBytesForUTF8[first] + 1; +} + +/* --------------------------------------------------------------------- */ + +/* + * Exported function to return whether a UTF-8 string is legal or not. + * This is not used here; it's just exported. + */ +Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd) { + while (*source != sourceEnd) { + int length = trailingBytesForUTF8[**source] + 1; + if (length > sourceEnd - *source || !isLegalUTF8(*source, length)) + return false; + *source += length; + } + return true; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF16 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8* source = *sourceStart; + UTF16* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (extraBytesToRead >= sourceEnd - source) { + result = sourceExhausted; break; + } + /* Do this check whether lenient or strict */ + if (!isLegalUTF8(source, extraBytesToRead+1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ + case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ + case 3: ch += *source++; ch <<= 6; + case 2: ch += *source++; ch <<= 6; + case 1: ch += *source++; ch <<= 6; + case 0: ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up source pointer! */ + result = targetExhausted; break; + } + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead+1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_UTF16) { + if (flags == strictConversion) { + result = sourceIllegal; + source -= (extraBytesToRead+1); /* return to the start */ + break; /* Bail out; shouldn't continue */ + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up source pointer! */ + result = targetExhausted; break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +static ConversionResult ConvertUTF8toUTF32Impl( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags, + Boolean InputIsPartial) { + ConversionResult result = conversionOK; + const UTF8* source = *sourceStart; + UTF32* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (extraBytesToRead >= sourceEnd - source) { + if (flags == strictConversion || InputIsPartial) { + result = sourceExhausted; + break; + } else { + result = sourceIllegal; + + /* + * Replace the maximal subpart of ill-formed sequence with + * replacement character. + */ + source += findMaximalSubpartOfIllFormedUTF8Sequence(source, + sourceEnd); + *target++ = UNI_REPLACEMENT_CHAR; + continue; + } + } + if (target >= targetEnd) { + result = targetExhausted; break; + } + + /* Do this check whether lenient or strict */ + if (!isLegalUTF8(source, extraBytesToRead+1)) { + result = sourceIllegal; + if (flags == strictConversion) { + /* Abort conversion. */ + break; + } else { + /* + * Replace the maximal subpart of ill-formed sequence with + * replacement character. + */ + source += findMaximalSubpartOfIllFormedUTF8Sequence(source, + sourceEnd); + *target++ = UNI_REPLACEMENT_CHAR; + continue; + } + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: ch += *source++; ch <<= 6; + case 4: ch += *source++; ch <<= 6; + case 3: ch += *source++; ch <<= 6; + case 2: ch += *source++; ch <<= 6; + case 1: ch += *source++; ch <<= 6; + case 0: ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (ch <= UNI_MAX_LEGAL_UTF32) { + /* + * UTF-16 surrogate values are illegal in UTF-32, and anything + * over Plane 17 (> 0x10FFFF) is illegal. + */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead+1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = ch; + } + } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ + result = sourceIllegal; + *target++ = UNI_REPLACEMENT_CHAR; + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +ConversionResult ConvertUTF8toUTF32Partial(const UTF8 **sourceStart, + const UTF8 *sourceEnd, + UTF32 **targetStart, + UTF32 *targetEnd, + ConversionFlags flags) { + return ConvertUTF8toUTF32Impl(sourceStart, sourceEnd, targetStart, targetEnd, + flags, /*InputIsPartial=*/true); +} + +ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart, + const UTF8 *sourceEnd, UTF32 **targetStart, + UTF32 *targetEnd, ConversionFlags flags) { + return ConvertUTF8toUTF32Impl(sourceStart, sourceEnd, targetStart, targetEnd, + flags, /*InputIsPartial=*/false); +} + +/* --------------------------------------------------------------------- + + Note A. + The fall-through switches in UTF-8 reading code save a + temp variable, some decrements & conditionals. The switches + are equivalent to the following loop: + { + int tmpBytesToRead = extraBytesToRead+1; + do { + ch += *source++; + --tmpBytesToRead; + if (tmpBytesToRead) ch <<= 6; + } while (tmpBytesToRead > 0); + } + In UTF-8 writing code, the switches on "bytesToWrite" are + similarly unrolled loops. + + --------------------------------------------------------------------- */
diff --git a/third_party/llvm-subzero/lib/Support/ConvertUTFWrapper.cpp b/third_party/llvm-subzero/lib/Support/ConvertUTFWrapper.cpp new file mode 100644 index 0000000..217cedb --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/ConvertUTFWrapper.cpp
@@ -0,0 +1,251 @@ +//===-- ConvertUTFWrapper.cpp - Wrap ConvertUTF.h with clang data types -----=== +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ConvertUTF.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SwapByteOrder.h" +#include <string> +#include <vector> + +namespace llvm { + +bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source, + char *&ResultPtr, const UTF8 *&ErrorPtr) { + assert(WideCharWidth == 1 || WideCharWidth == 2 || WideCharWidth == 4); + ConversionResult result = conversionOK; + // Copy the character span over. + if (WideCharWidth == 1) { + const UTF8 *Pos = reinterpret_cast<const UTF8*>(Source.begin()); + if (!isLegalUTF8String(&Pos, reinterpret_cast<const UTF8*>(Source.end()))) { + result = sourceIllegal; + ErrorPtr = Pos; + } else { + memcpy(ResultPtr, Source.data(), Source.size()); + ResultPtr += Source.size(); + } + } else if (WideCharWidth == 2) { + const UTF8 *sourceStart = (const UTF8*)Source.data(); + // FIXME: Make the type of the result buffer correct instead of + // using reinterpret_cast. + UTF16 *targetStart = reinterpret_cast<UTF16*>(ResultPtr); + ConversionFlags flags = strictConversion; + result = ConvertUTF8toUTF16( + &sourceStart, sourceStart + Source.size(), + &targetStart, targetStart + Source.size(), flags); + if (result == conversionOK) + ResultPtr = reinterpret_cast<char*>(targetStart); + else + ErrorPtr = sourceStart; + } else if (WideCharWidth == 4) { + const UTF8 *sourceStart = (const UTF8*)Source.data(); + // FIXME: Make the type of the result buffer correct instead of + // using reinterpret_cast. + UTF32 *targetStart = reinterpret_cast<UTF32*>(ResultPtr); + ConversionFlags flags = strictConversion; + result = ConvertUTF8toUTF32( + &sourceStart, sourceStart + Source.size(), + &targetStart, targetStart + Source.size(), flags); + if (result == conversionOK) + ResultPtr = reinterpret_cast<char*>(targetStart); + else + ErrorPtr = sourceStart; + } + assert((result != targetExhausted) + && "ConvertUTF8toUTFXX exhausted target buffer"); + return result == conversionOK; +} + +bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr) { + const UTF32 *SourceStart = &Source; + const UTF32 *SourceEnd = SourceStart + 1; + UTF8 *TargetStart = reinterpret_cast<UTF8 *>(ResultPtr); + UTF8 *TargetEnd = TargetStart + 4; + ConversionResult CR = ConvertUTF32toUTF8(&SourceStart, SourceEnd, + &TargetStart, TargetEnd, + strictConversion); + if (CR != conversionOK) + return false; + + ResultPtr = reinterpret_cast<char*>(TargetStart); + return true; +} + +bool hasUTF16ByteOrderMark(ArrayRef<char> S) { + return (S.size() >= 2 && + ((S[0] == '\xff' && S[1] == '\xfe') || + (S[0] == '\xfe' && S[1] == '\xff'))); +} + +bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out) { + assert(Out.empty()); + + // Error out on an uneven byte count. + if (SrcBytes.size() % 2) + return false; + + // Avoid OOB by returning early on empty input. + if (SrcBytes.empty()) + return true; + + const UTF16 *Src = reinterpret_cast<const UTF16 *>(SrcBytes.begin()); + const UTF16 *SrcEnd = reinterpret_cast<const UTF16 *>(SrcBytes.end()); + + // Byteswap if necessary. + std::vector<UTF16> ByteSwapped; + if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_SWAPPED) { + ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd); + for (unsigned I = 0, E = ByteSwapped.size(); I != E; ++I) + ByteSwapped[I] = llvm::sys::SwapByteOrder_16(ByteSwapped[I]); + Src = &ByteSwapped[0]; + SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1; + } + + // Skip the BOM for conversion. + if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_NATIVE) + Src++; + + // Just allocate enough space up front. We'll shrink it later. Allocate + // enough that we can fit a null terminator without reallocating. + Out.resize(SrcBytes.size() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT + 1); + UTF8 *Dst = reinterpret_cast<UTF8 *>(&Out[0]); + UTF8 *DstEnd = Dst + Out.size(); + + ConversionResult CR = + ConvertUTF16toUTF8(&Src, SrcEnd, &Dst, DstEnd, strictConversion); + assert(CR != targetExhausted); + + if (CR != conversionOK) { + Out.clear(); + return false; + } + + Out.resize(reinterpret_cast<char *>(Dst) - &Out[0]); + Out.push_back(0); + Out.pop_back(); + return true; +} + +bool convertUTF16ToUTF8String(ArrayRef<UTF16> Src, std::string &Out) +{ + return convertUTF16ToUTF8String( + llvm::ArrayRef<char>(reinterpret_cast<const char *>(Src.data()), + Src.size() * sizeof(UTF16)), Out); +} + +bool convertUTF8ToUTF16String(StringRef SrcUTF8, + SmallVectorImpl<UTF16> &DstUTF16) { + assert(DstUTF16.empty()); + + // Avoid OOB by returning early on empty input. + if (SrcUTF8.empty()) { + DstUTF16.push_back(0); + DstUTF16.pop_back(); + return true; + } + + const UTF8 *Src = reinterpret_cast<const UTF8 *>(SrcUTF8.begin()); + const UTF8 *SrcEnd = reinterpret_cast<const UTF8 *>(SrcUTF8.end()); + + // Allocate the same number of UTF-16 code units as UTF-8 code units. Encoding + // as UTF-16 should always require the same amount or less code units than the + // UTF-8 encoding. Allocate one extra byte for the null terminator though, + // so that someone calling DstUTF16.data() gets a null terminated string. + // We resize down later so we don't have to worry that this over allocates. + DstUTF16.resize(SrcUTF8.size()+1); + UTF16 *Dst = &DstUTF16[0]; + UTF16 *DstEnd = Dst + DstUTF16.size(); + + ConversionResult CR = + ConvertUTF8toUTF16(&Src, SrcEnd, &Dst, DstEnd, strictConversion); + assert(CR != targetExhausted); + + if (CR != conversionOK) { + DstUTF16.clear(); + return false; + } + + DstUTF16.resize(Dst - &DstUTF16[0]); + DstUTF16.push_back(0); + DstUTF16.pop_back(); + return true; +} + +static_assert(sizeof(wchar_t) == 1 || sizeof(wchar_t) == 2 || + sizeof(wchar_t) == 4, + "Expected wchar_t to be 1, 2, or 4 bytes"); + +template <typename TResult> +static inline bool ConvertUTF8toWideInternal(llvm::StringRef Source, + TResult &Result) { + // Even in the case of UTF-16, the number of bytes in a UTF-8 string is + // at least as large as the number of elements in the resulting wide + // string, because surrogate pairs take at least 4 bytes in UTF-8. + Result.resize(Source.size() + 1); + char *ResultPtr = reinterpret_cast<char *>(&Result[0]); + const UTF8 *ErrorPtr; + if (!ConvertUTF8toWide(sizeof(wchar_t), Source, ResultPtr, ErrorPtr)) { + Result.clear(); + return false; + } + Result.resize(reinterpret_cast<wchar_t *>(ResultPtr) - &Result[0]); + return true; +} + +bool ConvertUTF8toWide(llvm::StringRef Source, std::wstring &Result) { + return ConvertUTF8toWideInternal(Source, Result); +} + +bool ConvertUTF8toWide(const char *Source, std::wstring &Result) { + if (!Source) { + Result.clear(); + return true; + } + return ConvertUTF8toWide(llvm::StringRef(Source), Result); +} + +bool convertWideToUTF8(const std::wstring &Source, std::string &Result) { + if (sizeof(wchar_t) == 1) { + const UTF8 *Start = reinterpret_cast<const UTF8 *>(Source.data()); + const UTF8 *End = + reinterpret_cast<const UTF8 *>(Source.data() + Source.size()); + if (!isLegalUTF8String(&Start, End)) + return false; + Result.resize(Source.size()); + memcpy(&Result[0], Source.data(), Source.size()); + return true; + } else if (sizeof(wchar_t) == 2) { + return convertUTF16ToUTF8String( + llvm::ArrayRef<UTF16>(reinterpret_cast<const UTF16 *>(Source.data()), + Source.size()), + Result); + } else if (sizeof(wchar_t) == 4) { + const UTF32 *Start = reinterpret_cast<const UTF32 *>(Source.data()); + const UTF32 *End = + reinterpret_cast<const UTF32 *>(Source.data() + Source.size()); + Result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * Source.size()); + UTF8 *ResultPtr = reinterpret_cast<UTF8 *>(&Result[0]); + UTF8 *ResultEnd = reinterpret_cast<UTF8 *>(&Result[0] + Result.size()); + if (ConvertUTF32toUTF8(&Start, End, &ResultPtr, ResultEnd, + strictConversion) == conversionOK) { + Result.resize(reinterpret_cast<char *>(ResultPtr) - &Result[0]); + return true; + } else { + Result.clear(); + return false; + } + } else { + llvm_unreachable( + "Control should never reach this point; see static_assert further up"); + } +} + +} // end namespace llvm +
diff --git a/third_party/llvm-subzero/lib/Support/Debug.cpp b/third_party/llvm-subzero/lib/Support/Debug.cpp new file mode 100644 index 0000000..323d532 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Debug.cpp
@@ -0,0 +1,158 @@ +//===-- Debug.cpp - An easy way to add debug output to your code ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a handy way of adding debugging information to your +// code, without it being enabled all of the time, and without having to add +// command line options to enable it. +// +// In particular, just wrap your code with the DEBUG() macro, and it will be +// enabled automatically if you specify '-debug' on the command-line. +// Alternatively, you can also use the SET_DEBUG_TYPE("foo") macro to specify +// that your debug code belongs to class "foo". Then, on the command line, you +// can specify '-debug-only=foo' to enable JUST the debug information for the +// foo class. +// +// When compiling without assertions, the -debug-* options and all code in +// DEBUG() statements disappears, so it does not affect the runtime of the code. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Debug.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/circular_raw_ostream.h" +#include "llvm/Support/raw_ostream.h" + +#undef isCurrentDebugType +#undef setCurrentDebugType + +using namespace llvm; + +// Even though LLVM might be built with NDEBUG, define symbols that the code +// built without NDEBUG can depend on via the llvm/Support/Debug.h header. +namespace llvm { +/// Exported boolean set by the -debug option. +bool DebugFlag = false; + +static ManagedStatic<std::vector<std::string>> CurrentDebugType; + +/// Return true if the specified string is the debug type +/// specified on the command line, or if none was specified on the command line +/// with the -debug-only=X option. +bool isCurrentDebugType(const char *DebugType) { + if (CurrentDebugType->empty()) + return true; + // See if DebugType is in list. Note: do not use find() as that forces us to + // unnecessarily create an std::string instance. + for (auto &d : *CurrentDebugType) { + if (d == DebugType) + return true; + } + return false; +} + +/// Set the current debug type, as if the -debug-only=X +/// option were specified. Note that DebugFlag also needs to be set to true for +/// debug output to be produced. +/// +void setCurrentDebugType(const char *Type) { + CurrentDebugType->clear(); + CurrentDebugType->push_back(Type); +} + +} // namespace llvm + +// All Debug.h functionality is a no-op in NDEBUG mode. +#ifndef NDEBUG + +// -debug - Command line option to enable the DEBUG statements in the passes. +// This flag may only be enabled in debug builds. +static cl::opt<bool, true> +Debug("debug", cl::desc("Enable debug output"), cl::Hidden, + cl::location(DebugFlag)); + +// -debug-buffer-size - Buffer the last N characters of debug output +//until program termination. +static cl::opt<unsigned> +DebugBufferSize("debug-buffer-size", + cl::desc("Buffer the last N characters of debug output " + "until program termination. " + "[default 0 -- immediate print-out]"), + cl::Hidden, + cl::init(0)); + +namespace { + +struct DebugOnlyOpt { + void operator=(const std::string &Val) const { + if (Val.empty()) + return; + DebugFlag = true; + SmallVector<StringRef,8> dbgTypes; + StringRef(Val).split(dbgTypes, ',', -1, false); + for (auto dbgType : dbgTypes) + CurrentDebugType->push_back(dbgType); + } +}; + +} + +static DebugOnlyOpt DebugOnlyOptLoc; + +static cl::opt<DebugOnlyOpt, true, cl::parser<std::string> > +DebugOnly("debug-only", cl::desc("Enable a specific type of debug output (comma separated list of types)"), + cl::Hidden, cl::ZeroOrMore, cl::value_desc("debug string"), + cl::location(DebugOnlyOptLoc), cl::ValueRequired); +// Signal handlers - dump debug output on termination. +static void debug_user_sig_handler(void *Cookie) { + // This is a bit sneaky. Since this is under #ifndef NDEBUG, we + // know that debug mode is enabled and dbgs() really is a + // circular_raw_ostream. If NDEBUG is defined, then dbgs() == + // errs() but this will never be invoked. + llvm::circular_raw_ostream &dbgout = + static_cast<circular_raw_ostream &>(llvm::dbgs()); + dbgout.flushBufferWithBanner(); +} + +/// dbgs - Return a circular-buffered debug stream. +raw_ostream &llvm::dbgs() { + // Do one-time initialization in a thread-safe way. + static struct dbgstream { + circular_raw_ostream strm; + + dbgstream() : + strm(errs(), "*** Debug Log Output ***\n", + (!EnableDebugBuffering || !DebugFlag) ? 0 : DebugBufferSize) { + if (EnableDebugBuffering && DebugFlag && DebugBufferSize != 0) + // TODO: Add a handler for SIGUSER1-type signals so the user can + // force a debug dump. + sys::AddSignalHandler(&debug_user_sig_handler, nullptr); + // Otherwise we've already set the debug stream buffer size to + // zero, disabling buffering so it will output directly to errs(). + } + } thestrm; + + return thestrm.strm; +} + +#else +// Avoid "has no symbols" warning. +namespace llvm { + /// dbgs - Return errs(). + raw_ostream &dbgs() { + return errs(); + } +} + +#endif + +/// EnableDebugBuffering - Turn on signal handler installation. +/// +bool llvm::EnableDebugBuffering = false;
diff --git a/third_party/llvm-subzero/lib/Support/ErrorHandling.cpp b/third_party/llvm-subzero/lib/Support/ErrorHandling.cpp new file mode 100644 index 0000000..a7d3a18 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/ErrorHandling.cpp
@@ -0,0 +1,207 @@ +//===- lib/Support/ErrorHandling.cpp - Callbacks for errors ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an API used to indicate fatal error conditions. Non-fatal +// errors (most of them) should be handled through LLVMContext. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ErrorHandling.h" +#include "llvm-c/ErrorHandling.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Config/config.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/MutexGuard.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/Threading.h" +#include "llvm/Support/WindowsError.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstdlib> + +#if defined(HAVE_UNISTD_H) +# include <unistd.h> +#endif +#if defined(_MSC_VER) +# include <io.h> +# include <fcntl.h> +#endif + +using namespace llvm; + +static fatal_error_handler_t ErrorHandler = nullptr; +static void *ErrorHandlerUserData = nullptr; + +static ManagedStatic<sys::Mutex> ErrorHandlerMutex; + +void llvm::install_fatal_error_handler(fatal_error_handler_t handler, + void *user_data) { + llvm::MutexGuard Lock(*ErrorHandlerMutex); + assert(!ErrorHandler && "Error handler already registered!\n"); + ErrorHandler = handler; + ErrorHandlerUserData = user_data; +} + +void llvm::remove_fatal_error_handler() { + llvm::MutexGuard Lock(*ErrorHandlerMutex); + ErrorHandler = nullptr; + ErrorHandlerUserData = nullptr; +} + +void llvm::report_fatal_error(const char *Reason, bool GenCrashDiag) { + report_fatal_error(Twine(Reason), GenCrashDiag); +} + +void llvm::report_fatal_error(const std::string &Reason, bool GenCrashDiag) { + report_fatal_error(Twine(Reason), GenCrashDiag); +} + +void llvm::report_fatal_error(StringRef Reason, bool GenCrashDiag) { + report_fatal_error(Twine(Reason), GenCrashDiag); +} + +void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) { + llvm::fatal_error_handler_t handler = nullptr; + void* handlerData = nullptr; + { + // Only acquire the mutex while reading the handler, so as not to invoke a + // user-supplied callback under a lock. + llvm::MutexGuard Lock(*ErrorHandlerMutex); + handler = ErrorHandler; + handlerData = ErrorHandlerUserData; + } + + if (handler) { + handler(handlerData, Reason.str(), GenCrashDiag); + } else { + // Blast the result out to stderr. We don't try hard to make sure this + // succeeds (e.g. handling EINTR) and we can't use errs() here because + // raw ostreams can call report_fatal_error. + SmallVector<char, 64> Buffer; + raw_svector_ostream OS(Buffer); + OS << "LLVM ERROR: " << Reason << "\n"; + StringRef MessageStr = OS.str(); + ssize_t written = ::write(2, MessageStr.data(), MessageStr.size()); + (void)written; // If something went wrong, we deliberately just give up. + } + + // If we reached here, we are failing ungracefully. Run the interrupt handlers + // to make sure any special cleanups get done, in particular that we remove + // files registered with RemoveFileOnSignal. + sys::RunInterruptHandlers(); + + exit(1); +} + +void llvm::llvm_unreachable_internal(const char *msg, const char *file, + unsigned line) { + // This code intentionally doesn't call the ErrorHandler callback, because + // llvm_unreachable is intended to be used to indicate "impossible" + // situations, and not legitimate runtime errors. + if (msg) + dbgs() << msg << "\n"; + dbgs() << "UNREACHABLE executed"; + if (file) + dbgs() << " at " << file << ":" << line; + dbgs() << "!\n"; + abort(); +#ifdef LLVM_BUILTIN_UNREACHABLE + // Windows systems and possibly others don't declare abort() to be noreturn, + // so use the unreachable builtin to avoid a Clang self-host warning. + LLVM_BUILTIN_UNREACHABLE; +#endif +} + +static void bindingsErrorHandler(void *user_data, const std::string& reason, + bool gen_crash_diag) { + LLVMFatalErrorHandler handler = + LLVM_EXTENSION reinterpret_cast<LLVMFatalErrorHandler>(user_data); + handler(reason.c_str()); +} + +void LLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler) { + install_fatal_error_handler(bindingsErrorHandler, + LLVM_EXTENSION reinterpret_cast<void *>(Handler)); +} + +void LLVMResetFatalErrorHandler() { + remove_fatal_error_handler(); +} + +#ifdef LLVM_ON_WIN32 + +#include <winerror.h> + +// I'd rather not double the line count of the following. +#define MAP_ERR_TO_COND(x, y) \ + case x: \ + return make_error_code(errc::y) + +std::error_code llvm::mapWindowsError(unsigned EV) { + switch (EV) { + MAP_ERR_TO_COND(ERROR_ACCESS_DENIED, permission_denied); + MAP_ERR_TO_COND(ERROR_ALREADY_EXISTS, file_exists); + MAP_ERR_TO_COND(ERROR_BAD_UNIT, no_such_device); + MAP_ERR_TO_COND(ERROR_BUFFER_OVERFLOW, filename_too_long); + MAP_ERR_TO_COND(ERROR_BUSY, device_or_resource_busy); + MAP_ERR_TO_COND(ERROR_BUSY_DRIVE, device_or_resource_busy); + MAP_ERR_TO_COND(ERROR_CANNOT_MAKE, permission_denied); + MAP_ERR_TO_COND(ERROR_CANTOPEN, io_error); + MAP_ERR_TO_COND(ERROR_CANTREAD, io_error); + MAP_ERR_TO_COND(ERROR_CANTWRITE, io_error); + MAP_ERR_TO_COND(ERROR_CURRENT_DIRECTORY, permission_denied); + MAP_ERR_TO_COND(ERROR_DEV_NOT_EXIST, no_such_device); + MAP_ERR_TO_COND(ERROR_DEVICE_IN_USE, device_or_resource_busy); + MAP_ERR_TO_COND(ERROR_DIR_NOT_EMPTY, directory_not_empty); + MAP_ERR_TO_COND(ERROR_DIRECTORY, invalid_argument); + MAP_ERR_TO_COND(ERROR_DISK_FULL, no_space_on_device); + MAP_ERR_TO_COND(ERROR_FILE_EXISTS, file_exists); + MAP_ERR_TO_COND(ERROR_FILE_NOT_FOUND, no_such_file_or_directory); + MAP_ERR_TO_COND(ERROR_HANDLE_DISK_FULL, no_space_on_device); + MAP_ERR_TO_COND(ERROR_INVALID_ACCESS, permission_denied); + MAP_ERR_TO_COND(ERROR_INVALID_DRIVE, no_such_device); + MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION, function_not_supported); + MAP_ERR_TO_COND(ERROR_INVALID_HANDLE, invalid_argument); + MAP_ERR_TO_COND(ERROR_INVALID_NAME, invalid_argument); + MAP_ERR_TO_COND(ERROR_LOCK_VIOLATION, no_lock_available); + MAP_ERR_TO_COND(ERROR_LOCKED, no_lock_available); + MAP_ERR_TO_COND(ERROR_NEGATIVE_SEEK, invalid_argument); + MAP_ERR_TO_COND(ERROR_NOACCESS, permission_denied); + MAP_ERR_TO_COND(ERROR_NOT_ENOUGH_MEMORY, not_enough_memory); + MAP_ERR_TO_COND(ERROR_NOT_READY, resource_unavailable_try_again); + MAP_ERR_TO_COND(ERROR_OPEN_FAILED, io_error); + MAP_ERR_TO_COND(ERROR_OPEN_FILES, device_or_resource_busy); + MAP_ERR_TO_COND(ERROR_OUTOFMEMORY, not_enough_memory); + MAP_ERR_TO_COND(ERROR_PATH_NOT_FOUND, no_such_file_or_directory); + MAP_ERR_TO_COND(ERROR_BAD_NETPATH, no_such_file_or_directory); + MAP_ERR_TO_COND(ERROR_READ_FAULT, io_error); + MAP_ERR_TO_COND(ERROR_RETRY, resource_unavailable_try_again); + MAP_ERR_TO_COND(ERROR_SEEK, io_error); + MAP_ERR_TO_COND(ERROR_SHARING_VIOLATION, permission_denied); + MAP_ERR_TO_COND(ERROR_TOO_MANY_OPEN_FILES, too_many_files_open); + MAP_ERR_TO_COND(ERROR_WRITE_FAULT, io_error); + MAP_ERR_TO_COND(ERROR_WRITE_PROTECT, permission_denied); + MAP_ERR_TO_COND(WSAEACCES, permission_denied); + MAP_ERR_TO_COND(WSAEBADF, bad_file_descriptor); + MAP_ERR_TO_COND(WSAEFAULT, bad_address); + MAP_ERR_TO_COND(WSAEINTR, interrupted); + MAP_ERR_TO_COND(WSAEINVAL, invalid_argument); + MAP_ERR_TO_COND(WSAEMFILE, too_many_files_open); + MAP_ERR_TO_COND(WSAENAMETOOLONG, filename_too_long); + default: + return std::error_code(EV, std::system_category()); + } +} + +#endif
diff --git a/third_party/llvm-subzero/lib/Support/FoldingSet.cpp b/third_party/llvm-subzero/lib/Support/FoldingSet.cpp new file mode 100644 index 0000000..a27d317 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/FoldingSet.cpp
@@ -0,0 +1,462 @@ +//===-- Support/FoldingSet.cpp - Uniquing Hash Set --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a hash set that can be used to remove duplication of +// nodes in a graph. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/MathExtras.h" +#include <cassert> +#include <cstring> +using namespace llvm; + +//===----------------------------------------------------------------------===// +// FoldingSetNodeIDRef Implementation + +/// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef, +/// used to lookup the node in the FoldingSetImpl. +unsigned FoldingSetNodeIDRef::ComputeHash() const { + return static_cast<unsigned>(hash_combine_range(Data, Data+Size)); +} + +bool FoldingSetNodeIDRef::operator==(FoldingSetNodeIDRef RHS) const { + if (Size != RHS.Size) return false; + return memcmp(Data, RHS.Data, Size*sizeof(*Data)) == 0; +} + +/// Used to compare the "ordering" of two nodes as defined by the +/// profiled bits and their ordering defined by memcmp(). +bool FoldingSetNodeIDRef::operator<(FoldingSetNodeIDRef RHS) const { + if (Size != RHS.Size) + return Size < RHS.Size; + return memcmp(Data, RHS.Data, Size*sizeof(*Data)) < 0; +} + +//===----------------------------------------------------------------------===// +// FoldingSetNodeID Implementation + +/// Add* - Add various data types to Bit data. +/// +void FoldingSetNodeID::AddPointer(const void *Ptr) { + // Note: this adds pointers to the hash using sizes and endianness that + // depend on the host. It doesn't matter, however, because hashing on + // pointer values is inherently unstable. Nothing should depend on the + // ordering of nodes in the folding set. + Bits.append(reinterpret_cast<unsigned *>(&Ptr), + reinterpret_cast<unsigned *>(&Ptr+1)); +} +void FoldingSetNodeID::AddInteger(signed I) { + Bits.push_back(I); +} +void FoldingSetNodeID::AddInteger(unsigned I) { + Bits.push_back(I); +} +void FoldingSetNodeID::AddInteger(long I) { + AddInteger((unsigned long)I); +} +void FoldingSetNodeID::AddInteger(unsigned long I) { + if (sizeof(long) == sizeof(int)) + AddInteger(unsigned(I)); + else if (sizeof(long) == sizeof(long long)) { + AddInteger((unsigned long long)I); + } else { + llvm_unreachable("unexpected sizeof(long)"); + } +} +void FoldingSetNodeID::AddInteger(long long I) { + AddInteger((unsigned long long)I); +} +void FoldingSetNodeID::AddInteger(unsigned long long I) { + AddInteger(unsigned(I)); + if ((uint64_t)(unsigned)I != I) + Bits.push_back(unsigned(I >> 32)); +} + +void FoldingSetNodeID::AddString(StringRef String) { + unsigned Size = String.size(); + Bits.push_back(Size); + if (!Size) return; + + unsigned Units = Size / 4; + unsigned Pos = 0; + const unsigned *Base = (const unsigned*) String.data(); + + // If the string is aligned do a bulk transfer. + if (!((intptr_t)Base & 3)) { + Bits.append(Base, Base + Units); + Pos = (Units + 1) * 4; + } else { + // Otherwise do it the hard way. + // To be compatible with above bulk transfer, we need to take endianness + // into account. + static_assert(sys::IsBigEndianHost || sys::IsLittleEndianHost, + "Unexpected host endianness"); + if (sys::IsBigEndianHost) { + for (Pos += 4; Pos <= Size; Pos += 4) { + unsigned V = ((unsigned char)String[Pos - 4] << 24) | + ((unsigned char)String[Pos - 3] << 16) | + ((unsigned char)String[Pos - 2] << 8) | + (unsigned char)String[Pos - 1]; + Bits.push_back(V); + } + } else { // Little-endian host + for (Pos += 4; Pos <= Size; Pos += 4) { + unsigned V = ((unsigned char)String[Pos - 1] << 24) | + ((unsigned char)String[Pos - 2] << 16) | + ((unsigned char)String[Pos - 3] << 8) | + (unsigned char)String[Pos - 4]; + Bits.push_back(V); + } + } + } + + // With the leftover bits. + unsigned V = 0; + // Pos will have overshot size by 4 - #bytes left over. + // No need to take endianness into account here - this is always executed. + switch (Pos - Size) { + case 1: V = (V << 8) | (unsigned char)String[Size - 3]; LLVM_FALLTHROUGH; + case 2: V = (V << 8) | (unsigned char)String[Size - 2]; LLVM_FALLTHROUGH; + case 3: V = (V << 8) | (unsigned char)String[Size - 1]; break; + default: return; // Nothing left. + } + + Bits.push_back(V); +} + +// AddNodeID - Adds the Bit data of another ID to *this. +void FoldingSetNodeID::AddNodeID(const FoldingSetNodeID &ID) { + Bits.append(ID.Bits.begin(), ID.Bits.end()); +} + +/// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used to +/// lookup the node in the FoldingSetImpl. +unsigned FoldingSetNodeID::ComputeHash() const { + return FoldingSetNodeIDRef(Bits.data(), Bits.size()).ComputeHash(); +} + +/// operator== - Used to compare two nodes to each other. +/// +bool FoldingSetNodeID::operator==(const FoldingSetNodeID &RHS) const { + return *this == FoldingSetNodeIDRef(RHS.Bits.data(), RHS.Bits.size()); +} + +/// operator== - Used to compare two nodes to each other. +/// +bool FoldingSetNodeID::operator==(FoldingSetNodeIDRef RHS) const { + return FoldingSetNodeIDRef(Bits.data(), Bits.size()) == RHS; +} + +/// Used to compare the "ordering" of two nodes as defined by the +/// profiled bits and their ordering defined by memcmp(). +bool FoldingSetNodeID::operator<(const FoldingSetNodeID &RHS) const { + return *this < FoldingSetNodeIDRef(RHS.Bits.data(), RHS.Bits.size()); +} + +bool FoldingSetNodeID::operator<(FoldingSetNodeIDRef RHS) const { + return FoldingSetNodeIDRef(Bits.data(), Bits.size()) < RHS; +} + +/// Intern - Copy this node's data to a memory region allocated from the +/// given allocator and return a FoldingSetNodeIDRef describing the +/// interned data. +FoldingSetNodeIDRef +FoldingSetNodeID::Intern(BumpPtrAllocator &Allocator) const { + unsigned *New = Allocator.Allocate<unsigned>(Bits.size()); + std::uninitialized_copy(Bits.begin(), Bits.end(), New); + return FoldingSetNodeIDRef(New, Bits.size()); +} + +//===----------------------------------------------------------------------===// +/// Helper functions for FoldingSetImpl. + +/// GetNextPtr - In order to save space, each bucket is a +/// singly-linked-list. In order to make deletion more efficient, we make +/// the list circular, so we can delete a node without computing its hash. +/// The problem with this is that the start of the hash buckets are not +/// Nodes. If NextInBucketPtr is a bucket pointer, this method returns null: +/// use GetBucketPtr when this happens. +static FoldingSetImpl::Node *GetNextPtr(void *NextInBucketPtr) { + // The low bit is set if this is the pointer back to the bucket. + if (reinterpret_cast<intptr_t>(NextInBucketPtr) & 1) + return nullptr; + + return static_cast<FoldingSetImpl::Node*>(NextInBucketPtr); +} + + +/// testing. +static void **GetBucketPtr(void *NextInBucketPtr) { + intptr_t Ptr = reinterpret_cast<intptr_t>(NextInBucketPtr); + assert((Ptr & 1) && "Not a bucket pointer"); + return reinterpret_cast<void**>(Ptr & ~intptr_t(1)); +} + +/// GetBucketFor - Hash the specified node ID and return the hash bucket for +/// the specified ID. +static void **GetBucketFor(unsigned Hash, void **Buckets, unsigned NumBuckets) { + // NumBuckets is always a power of 2. + unsigned BucketNum = Hash & (NumBuckets-1); + return Buckets + BucketNum; +} + +/// AllocateBuckets - Allocated initialized bucket memory. +static void **AllocateBuckets(unsigned NumBuckets) { + void **Buckets = static_cast<void**>(calloc(NumBuckets+1, sizeof(void*))); + // Set the very last bucket to be a non-null "pointer". + Buckets[NumBuckets] = reinterpret_cast<void*>(-1); + return Buckets; +} + +//===----------------------------------------------------------------------===// +// FoldingSetImpl Implementation + +void FoldingSetImpl::anchor() {} + +FoldingSetImpl::FoldingSetImpl(unsigned Log2InitSize) { + assert(5 < Log2InitSize && Log2InitSize < 32 && + "Initial hash table size out of range"); + NumBuckets = 1 << Log2InitSize; + Buckets = AllocateBuckets(NumBuckets); + NumNodes = 0; +} + +FoldingSetImpl::FoldingSetImpl(FoldingSetImpl &&Arg) + : Buckets(Arg.Buckets), NumBuckets(Arg.NumBuckets), NumNodes(Arg.NumNodes) { + Arg.Buckets = nullptr; + Arg.NumBuckets = 0; + Arg.NumNodes = 0; +} + +FoldingSetImpl &FoldingSetImpl::operator=(FoldingSetImpl &&RHS) { + free(Buckets); // This may be null if the set is in a moved-from state. + Buckets = RHS.Buckets; + NumBuckets = RHS.NumBuckets; + NumNodes = RHS.NumNodes; + RHS.Buckets = nullptr; + RHS.NumBuckets = 0; + RHS.NumNodes = 0; + return *this; +} + +FoldingSetImpl::~FoldingSetImpl() { + free(Buckets); +} + +void FoldingSetImpl::clear() { + // Set all but the last bucket to null pointers. + memset(Buckets, 0, NumBuckets*sizeof(void*)); + + // Set the very last bucket to be a non-null "pointer". + Buckets[NumBuckets] = reinterpret_cast<void*>(-1); + + // Reset the node count to zero. + NumNodes = 0; +} + +void FoldingSetImpl::GrowBucketCount(unsigned NewBucketCount) { + assert((NewBucketCount > NumBuckets) && "Can't shrink a folding set with GrowBucketCount"); + assert(isPowerOf2_32(NewBucketCount) && "Bad bucket count!"); + void **OldBuckets = Buckets; + unsigned OldNumBuckets = NumBuckets; + NumBuckets = NewBucketCount; + + // Clear out new buckets. + Buckets = AllocateBuckets(NumBuckets); + NumNodes = 0; + + // Walk the old buckets, rehashing nodes into their new place. + FoldingSetNodeID TempID; + for (unsigned i = 0; i != OldNumBuckets; ++i) { + void *Probe = OldBuckets[i]; + if (!Probe) continue; + while (Node *NodeInBucket = GetNextPtr(Probe)) { + // Figure out the next link, remove NodeInBucket from the old link. + Probe = NodeInBucket->getNextInBucket(); + NodeInBucket->SetNextInBucket(nullptr); + + // Insert the node into the new bucket, after recomputing the hash. + InsertNode(NodeInBucket, + GetBucketFor(ComputeNodeHash(NodeInBucket, TempID), + Buckets, NumBuckets)); + TempID.clear(); + } + } + + free(OldBuckets); +} + +/// GrowHashTable - Double the size of the hash table and rehash everything. +/// +void FoldingSetImpl::GrowHashTable() { + GrowBucketCount(NumBuckets * 2); +} + +void FoldingSetImpl::reserve(unsigned EltCount) { + // This will give us somewhere between EltCount / 2 and + // EltCount buckets. This puts us in the load factor + // range of 1.0 - 2.0. + if(EltCount < capacity()) + return; + GrowBucketCount(PowerOf2Floor(EltCount)); +} + +/// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, +/// return it. If not, return the insertion token that will make insertion +/// faster. +FoldingSetImpl::Node +*FoldingSetImpl::FindNodeOrInsertPos(const FoldingSetNodeID &ID, + void *&InsertPos) { + unsigned IDHash = ID.ComputeHash(); + void **Bucket = GetBucketFor(IDHash, Buckets, NumBuckets); + void *Probe = *Bucket; + + InsertPos = nullptr; + + FoldingSetNodeID TempID; + while (Node *NodeInBucket = GetNextPtr(Probe)) { + if (NodeEquals(NodeInBucket, ID, IDHash, TempID)) + return NodeInBucket; + TempID.clear(); + + Probe = NodeInBucket->getNextInBucket(); + } + + // Didn't find the node, return null with the bucket as the InsertPos. + InsertPos = Bucket; + return nullptr; +} + +/// InsertNode - Insert the specified node into the folding set, knowing that it +/// is not already in the map. InsertPos must be obtained from +/// FindNodeOrInsertPos. +void FoldingSetImpl::InsertNode(Node *N, void *InsertPos) { + assert(!N->getNextInBucket()); + // Do we need to grow the hashtable? + if (NumNodes+1 > capacity()) { + GrowHashTable(); + FoldingSetNodeID TempID; + InsertPos = GetBucketFor(ComputeNodeHash(N, TempID), Buckets, NumBuckets); + } + + ++NumNodes; + + /// The insert position is actually a bucket pointer. + void **Bucket = static_cast<void**>(InsertPos); + + void *Next = *Bucket; + + // If this is the first insertion into this bucket, its next pointer will be + // null. Pretend as if it pointed to itself, setting the low bit to indicate + // that it is a pointer to the bucket. + if (!Next) + Next = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(Bucket)|1); + + // Set the node's next pointer, and make the bucket point to the node. + N->SetNextInBucket(Next); + *Bucket = N; +} + +/// RemoveNode - Remove a node from the folding set, returning true if one was +/// removed or false if the node was not in the folding set. +bool FoldingSetImpl::RemoveNode(Node *N) { + // Because each bucket is a circular list, we don't need to compute N's hash + // to remove it. + void *Ptr = N->getNextInBucket(); + if (!Ptr) return false; // Not in folding set. + + --NumNodes; + N->SetNextInBucket(nullptr); + + // Remember what N originally pointed to, either a bucket or another node. + void *NodeNextPtr = Ptr; + + // Chase around the list until we find the node (or bucket) which points to N. + while (true) { + if (Node *NodeInBucket = GetNextPtr(Ptr)) { + // Advance pointer. + Ptr = NodeInBucket->getNextInBucket(); + + // We found a node that points to N, change it to point to N's next node, + // removing N from the list. + if (Ptr == N) { + NodeInBucket->SetNextInBucket(NodeNextPtr); + return true; + } + } else { + void **Bucket = GetBucketPtr(Ptr); + Ptr = *Bucket; + + // If we found that the bucket points to N, update the bucket to point to + // whatever is next. + if (Ptr == N) { + *Bucket = NodeNextPtr; + return true; + } + } + } +} + +/// GetOrInsertNode - If there is an existing simple Node exactly +/// equal to the specified node, return it. Otherwise, insert 'N' and it +/// instead. +FoldingSetImpl::Node *FoldingSetImpl::GetOrInsertNode(FoldingSetImpl::Node *N) { + FoldingSetNodeID ID; + GetNodeProfile(N, ID); + void *IP; + if (Node *E = FindNodeOrInsertPos(ID, IP)) + return E; + InsertNode(N, IP); + return N; +} + +//===----------------------------------------------------------------------===// +// FoldingSetIteratorImpl Implementation + +FoldingSetIteratorImpl::FoldingSetIteratorImpl(void **Bucket) { + // Skip to the first non-null non-self-cycle bucket. + while (*Bucket != reinterpret_cast<void*>(-1) && + (!*Bucket || !GetNextPtr(*Bucket))) + ++Bucket; + + NodePtr = static_cast<FoldingSetNode*>(*Bucket); +} + +void FoldingSetIteratorImpl::advance() { + // If there is another link within this bucket, go to it. + void *Probe = NodePtr->getNextInBucket(); + + if (FoldingSetNode *NextNodeInBucket = GetNextPtr(Probe)) + NodePtr = NextNodeInBucket; + else { + // Otherwise, this is the last link in this bucket. + void **Bucket = GetBucketPtr(Probe); + + // Skip to the next non-null non-self-cycle bucket. + do { + ++Bucket; + } while (*Bucket != reinterpret_cast<void*>(-1) && + (!*Bucket || !GetNextPtr(*Bucket))); + + NodePtr = static_cast<FoldingSetNode*>(*Bucket); + } +} + +//===----------------------------------------------------------------------===// +// FoldingSetBucketIteratorImpl Implementation + +FoldingSetBucketIteratorImpl::FoldingSetBucketIteratorImpl(void **Bucket) { + Ptr = (!*Bucket || !GetNextPtr(*Bucket)) ? (void*) Bucket : *Bucket; +}
diff --git a/third_party/llvm-subzero/lib/Support/Hashing.cpp b/third_party/llvm-subzero/lib/Support/Hashing.cpp new file mode 100644 index 0000000..c69efb7 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Hashing.cpp
@@ -0,0 +1,29 @@ +//===-------------- lib/Support/Hashing.cpp -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides implementation bits for the LLVM common hashing +// infrastructure. Documentation and most of the other information is in the +// header file. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Hashing.h" + +using namespace llvm; + +// Provide a definition and static initializer for the fixed seed. This +// initializer should always be zero to ensure its value can never appear to be +// non-zero, even during dynamic initialization. +size_t llvm::hashing::detail::fixed_seed_override = 0; + +// Implement the function for forced setting of the fixed seed. +// FIXME: Use atomic operations here so that there is no data race. +void llvm::set_fixed_execution_hash_seed(size_t fixed_value) { + hashing::detail::fixed_seed_override = fixed_value; +}
diff --git a/third_party/llvm-subzero/lib/Support/Host.cpp b/third_party/llvm-subzero/lib/Support/Host.cpp new file mode 100644 index 0000000..689e050 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Host.cpp
@@ -0,0 +1,1349 @@ +//===-- Host.cpp - Implement OS Host Concept --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the operating system Host concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Host.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Config/config.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h" +#include <string.h> +#include <assert.h> + +// Include the platform-specific parts of this class. +#ifdef LLVM_ON_UNIX +#include "Unix/Host.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Windows/Host.inc" +#endif +#ifdef _MSC_VER +#include <intrin.h> +#endif +#if defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__)) +#include <mach/host_info.h> +#include <mach/mach.h> +#include <mach/mach_host.h> +#include <mach/machine.h> +#endif + +#define DEBUG_TYPE "host-detection" + +//===----------------------------------------------------------------------===// +// +// Implementations of the CPU detection routines +// +//===----------------------------------------------------------------------===// + +using namespace llvm; + +#if defined(__linux__) +static ssize_t LLVM_ATTRIBUTE_UNUSED readCpuInfo(void *Buf, size_t Size) { + // Note: We cannot mmap /proc/cpuinfo here and then process the resulting + // memory buffer because the 'file' has 0 size (it can be read from only + // as a stream). + + int FD; + std::error_code EC = sys::fs::openFileForRead("/proc/cpuinfo", FD); + if (EC) { + DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << EC.message() << "\n"); + return -1; + } + int Ret = read(FD, Buf, Size); + int CloseStatus = close(FD); + if (CloseStatus) + return -1; + return Ret; +} +#endif + +#if defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64__) || defined(_M_X64) + +#if defined(__GNUC__) || defined(__clang__) +#include <cpuid.h> +#endif + +enum VendorSignatures { + SIG_INTEL = 0x756e6547 /* Genu */, + SIG_AMD = 0x68747541 /* Auth */ +}; + +enum ProcessorVendors { + VENDOR_INTEL = 1, + VENDOR_AMD, + VENDOR_OTHER, + VENDOR_MAX +}; + +enum ProcessorTypes { + INTEL_ATOM = 1, + INTEL_CORE2, + INTEL_COREI7, + AMDFAM10H, + AMDFAM15H, + INTEL_i386, + INTEL_i486, + INTEL_PENTIUM, + INTEL_PENTIUM_PRO, + INTEL_PENTIUM_II, + INTEL_PENTIUM_III, + INTEL_PENTIUM_IV, + INTEL_PENTIUM_M, + INTEL_CORE_DUO, + INTEL_XEONPHI, + INTEL_X86_64, + INTEL_NOCONA, + INTEL_PRESCOTT, + AMD_i486, + AMDPENTIUM, + AMDATHLON, + AMDFAM14H, + AMDFAM16H, + CPU_TYPE_MAX +}; + +enum ProcessorSubtypes { + INTEL_COREI7_NEHALEM = 1, + INTEL_COREI7_WESTMERE, + INTEL_COREI7_SANDYBRIDGE, + AMDFAM10H_BARCELONA, + AMDFAM10H_SHANGHAI, + AMDFAM10H_ISTANBUL, + AMDFAM15H_BDVER1, + AMDFAM15H_BDVER2, + INTEL_PENTIUM_MMX, + INTEL_CORE2_65, + INTEL_CORE2_45, + INTEL_COREI7_IVYBRIDGE, + INTEL_COREI7_HASWELL, + INTEL_COREI7_BROADWELL, + INTEL_COREI7_SKYLAKE, + INTEL_COREI7_SKYLAKE_AVX512, + INTEL_ATOM_BONNELL, + INTEL_ATOM_SILVERMONT, + INTEL_KNIGHTS_LANDING, + AMDPENTIUM_K6, + AMDPENTIUM_K62, + AMDPENTIUM_K63, + AMDPENTIUM_GEODE, + AMDATHLON_TBIRD, + AMDATHLON_MP, + AMDATHLON_XP, + AMDATHLON_K8SSE3, + AMDATHLON_OPTERON, + AMDATHLON_FX, + AMDATHLON_64, + AMD_BTVER1, + AMD_BTVER2, + AMDFAM15H_BDVER3, + AMDFAM15H_BDVER4, + CPU_SUBTYPE_MAX +}; + +enum ProcessorFeatures { + FEATURE_CMOV = 0, + FEATURE_MMX, + FEATURE_POPCNT, + FEATURE_SSE, + FEATURE_SSE2, + FEATURE_SSE3, + FEATURE_SSSE3, + FEATURE_SSE4_1, + FEATURE_SSE4_2, + FEATURE_AVX, + FEATURE_AVX2, + FEATURE_AVX512, + FEATURE_AVX512SAVE, + FEATURE_MOVBE, + FEATURE_ADX, + FEATURE_EM64T +}; + +/// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in +/// the specified arguments. If we can't run cpuid on the host, return true. +static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, + unsigned *rECX, unsigned *rEDX) { +#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) +#if defined(__GNUC__) || defined(__clang__) +#if defined(__x86_64__) + // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually. + // FIXME: should we save this for Clang? + __asm__("movq\t%%rbx, %%rsi\n\t" + "cpuid\n\t" + "xchgq\t%%rbx, %%rsi\n\t" + : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) + : "a"(value)); +#elif defined(__i386__) + __asm__("movl\t%%ebx, %%esi\n\t" + "cpuid\n\t" + "xchgl\t%%ebx, %%esi\n\t" + : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) + : "a"(value)); +#else + assert(0 && "This method is defined only for x86."); +#endif +#elif defined(_MSC_VER) + // The MSVC intrinsic is portable across x86 and x64. + int registers[4]; + __cpuid(registers, value); + *rEAX = registers[0]; + *rEBX = registers[1]; + *rECX = registers[2]; + *rEDX = registers[3]; +#endif + return false; +#else + return true; +#endif +} + +/// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return +/// the 4 values in the specified arguments. If we can't run cpuid on the host, +/// return true. +static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf, + unsigned *rEAX, unsigned *rEBX, unsigned *rECX, + unsigned *rEDX) { +#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) +#if defined(__x86_64__) || defined(_M_X64) +#if defined(__GNUC__) || defined(__clang__) + // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. + // FIXME: should we save this for Clang? + __asm__("movq\t%%rbx, %%rsi\n\t" + "cpuid\n\t" + "xchgq\t%%rbx, %%rsi\n\t" + : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) + : "a"(value), "c"(subleaf)); +#elif defined(_MSC_VER) + int registers[4]; + __cpuidex(registers, value, subleaf); + *rEAX = registers[0]; + *rEBX = registers[1]; + *rECX = registers[2]; + *rEDX = registers[3]; +#endif +#elif defined(__i386__) || defined(_M_IX86) +#if defined(__GNUC__) || defined(__clang__) + __asm__("movl\t%%ebx, %%esi\n\t" + "cpuid\n\t" + "xchgl\t%%ebx, %%esi\n\t" + : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) + : "a"(value), "c"(subleaf)); +#elif defined(_MSC_VER) + __asm { + mov eax,value + mov ecx,subleaf + cpuid + mov esi,rEAX + mov dword ptr [esi],eax + mov esi,rEBX + mov dword ptr [esi],ebx + mov esi,rECX + mov dword ptr [esi],ecx + mov esi,rEDX + mov dword ptr [esi],edx + } +#endif +#else + assert(0 && "This method is defined only for x86."); +#endif + return false; +#else + return true; +#endif +} + +static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) { +#if defined(__GNUC__) || defined(__clang__) + // Check xgetbv; this uses a .byte sequence instead of the instruction + // directly because older assemblers do not include support for xgetbv and + // there is no easy way to conditionally compile based on the assembler used. + __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0)); + return false; +#elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK) + unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK); + *rEAX = Result; + *rEDX = Result >> 32; + return false; +#else + return true; +#endif +} + +static void detectX86FamilyModel(unsigned EAX, unsigned *Family, + unsigned *Model) { + *Family = (EAX >> 8) & 0xf; // Bits 8 - 11 + *Model = (EAX >> 4) & 0xf; // Bits 4 - 7 + if (*Family == 6 || *Family == 0xf) { + if (*Family == 0xf) + // Examine extended family ID if family ID is F. + *Family += (EAX >> 20) & 0xff; // Bits 20 - 27 + // Examine extended model ID if family ID is 6 or F. + *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19 + } +} + +static void +getIntelProcessorTypeAndSubtype(unsigned int Family, unsigned int Model, + unsigned int Brand_id, unsigned int Features, + unsigned *Type, unsigned *Subtype) { + if (Brand_id != 0) + return; + switch (Family) { + case 3: + *Type = INTEL_i386; + break; + case 4: + switch (Model) { + case 0: // Intel486 DX processors + case 1: // Intel486 DX processors + case 2: // Intel486 SX processors + case 3: // Intel487 processors, IntelDX2 OverDrive processors, + // IntelDX2 processors + case 4: // Intel486 SL processor + case 5: // IntelSX2 processors + case 7: // Write-Back Enhanced IntelDX2 processors + case 8: // IntelDX4 OverDrive processors, IntelDX4 processors + default: + *Type = INTEL_i486; + break; + } + break; + case 5: + switch (Model) { + case 1: // Pentium OverDrive processor for Pentium processor (60, 66), + // Pentium processors (60, 66) + case 2: // Pentium OverDrive processor for Pentium processor (75, 90, + // 100, 120, 133), Pentium processors (75, 90, 100, 120, 133, + // 150, 166, 200) + case 3: // Pentium OverDrive processors for Intel486 processor-based + // systems + *Type = INTEL_PENTIUM; + break; + case 4: // Pentium OverDrive processor with MMX technology for Pentium + // processor (75, 90, 100, 120, 133), Pentium processor with + // MMX technology (166, 200) + *Type = INTEL_PENTIUM; + *Subtype = INTEL_PENTIUM_MMX; + break; + default: + *Type = INTEL_PENTIUM; + break; + } + break; + case 6: + switch (Model) { + case 0x01: // Pentium Pro processor + *Type = INTEL_PENTIUM_PRO; + break; + case 0x03: // Intel Pentium II OverDrive processor, Pentium II processor, + // model 03 + case 0x05: // Pentium II processor, model 05, Pentium II Xeon processor, + // model 05, and Intel Celeron processor, model 05 + case 0x06: // Celeron processor, model 06 + *Type = INTEL_PENTIUM_II; + break; + case 0x07: // Pentium III processor, model 07, and Pentium III Xeon + // processor, model 07 + case 0x08: // Pentium III processor, model 08, Pentium III Xeon processor, + // model 08, and Celeron processor, model 08 + case 0x0a: // Pentium III Xeon processor, model 0Ah + case 0x0b: // Pentium III processor, model 0Bh + *Type = INTEL_PENTIUM_III; + break; + case 0x09: // Intel Pentium M processor, Intel Celeron M processor model 09. + case 0x0d: // Intel Pentium M processor, Intel Celeron M processor, model + // 0Dh. All processors are manufactured using the 90 nm process. + case 0x15: // Intel EP80579 Integrated Processor and Intel EP80579 + // Integrated Processor with Intel QuickAssist Technology + *Type = INTEL_PENTIUM_M; + break; + case 0x0e: // Intel Core Duo processor, Intel Core Solo processor, model + // 0Eh. All processors are manufactured using the 65 nm process. + *Type = INTEL_CORE_DUO; + break; // yonah + case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile + // processor, Intel Core 2 Quad processor, Intel Core 2 Quad + // mobile processor, Intel Core 2 Extreme processor, Intel + // Pentium Dual-Core processor, Intel Xeon processor, model + // 0Fh. All processors are manufactured using the 65 nm process. + case 0x16: // Intel Celeron processor model 16h. All processors are + // manufactured using the 65 nm process + *Type = INTEL_CORE2; // "core2" + *Subtype = INTEL_CORE2_65; + break; + case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model + // 17h. All processors are manufactured using the 45 nm process. + // + // 45nm: Penryn , Wolfdale, Yorkfield (XE) + case 0x1d: // Intel Xeon processor MP. All processors are manufactured using + // the 45 nm process. + *Type = INTEL_CORE2; // "penryn" + *Subtype = INTEL_CORE2_45; + break; + case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All + // processors are manufactured using the 45 nm process. + case 0x1e: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz. + // As found in a Summer 2010 model iMac. + case 0x1f: + case 0x2e: // Nehalem EX + *Type = INTEL_COREI7; // "nehalem" + *Subtype = INTEL_COREI7_NEHALEM; + break; + case 0x25: // Intel Core i7, laptop version. + case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All + // processors are manufactured using the 32 nm process. + case 0x2f: // Westmere EX + *Type = INTEL_COREI7; // "westmere" + *Subtype = INTEL_COREI7_WESTMERE; + break; + case 0x2a: // Intel Core i7 processor. All processors are manufactured + // using the 32 nm process. + case 0x2d: + *Type = INTEL_COREI7; //"sandybridge" + *Subtype = INTEL_COREI7_SANDYBRIDGE; + break; + case 0x3a: + case 0x3e: // Ivy Bridge EP + *Type = INTEL_COREI7; // "ivybridge" + *Subtype = INTEL_COREI7_IVYBRIDGE; + break; + + // Haswell: + case 0x3c: + case 0x3f: + case 0x45: + case 0x46: + *Type = INTEL_COREI7; // "haswell" + *Subtype = INTEL_COREI7_HASWELL; + break; + + // Broadwell: + case 0x3d: + case 0x47: + case 0x4f: + case 0x56: + *Type = INTEL_COREI7; // "broadwell" + *Subtype = INTEL_COREI7_BROADWELL; + break; + + // Skylake: + case 0x4e: + *Type = INTEL_COREI7; // "skylake-avx512" + *Subtype = INTEL_COREI7_SKYLAKE_AVX512; + break; + case 0x5e: + *Type = INTEL_COREI7; // "skylake" + *Subtype = INTEL_COREI7_SKYLAKE; + break; + + case 0x1c: // Most 45 nm Intel Atom processors + case 0x26: // 45 nm Atom Lincroft + case 0x27: // 32 nm Atom Medfield + case 0x35: // 32 nm Atom Midview + case 0x36: // 32 nm Atom Midview + *Type = INTEL_ATOM; + *Subtype = INTEL_ATOM_BONNELL; + break; // "bonnell" + + // Atom Silvermont codes from the Intel software optimization guide. + case 0x37: + case 0x4a: + case 0x4d: + case 0x5a: + case 0x5d: + case 0x4c: // really airmont + *Type = INTEL_ATOM; + *Subtype = INTEL_ATOM_SILVERMONT; + break; // "silvermont" + + case 0x57: + *Type = INTEL_XEONPHI; // knl + *Subtype = INTEL_KNIGHTS_LANDING; + break; + + default: // Unknown family 6 CPU, try to guess. + if (Features & (1 << FEATURE_AVX512)) { + *Type = INTEL_XEONPHI; // knl + *Subtype = INTEL_KNIGHTS_LANDING; + break; + } + if (Features & (1 << FEATURE_ADX)) { + *Type = INTEL_COREI7; + *Subtype = INTEL_COREI7_BROADWELL; + break; + } + if (Features & (1 << FEATURE_AVX2)) { + *Type = INTEL_COREI7; + *Subtype = INTEL_COREI7_HASWELL; + break; + } + if (Features & (1 << FEATURE_AVX)) { + *Type = INTEL_COREI7; + *Subtype = INTEL_COREI7_SANDYBRIDGE; + break; + } + if (Features & (1 << FEATURE_SSE4_2)) { + if (Features & (1 << FEATURE_MOVBE)) { + *Type = INTEL_ATOM; + *Subtype = INTEL_ATOM_SILVERMONT; + } else { + *Type = INTEL_COREI7; + *Subtype = INTEL_COREI7_NEHALEM; + } + break; + } + if (Features & (1 << FEATURE_SSE4_1)) { + *Type = INTEL_CORE2; // "penryn" + *Subtype = INTEL_CORE2_45; + break; + } + if (Features & (1 << FEATURE_SSSE3)) { + if (Features & (1 << FEATURE_MOVBE)) { + *Type = INTEL_ATOM; + *Subtype = INTEL_ATOM_BONNELL; // "bonnell" + } else { + *Type = INTEL_CORE2; // "core2" + *Subtype = INTEL_CORE2_65; + } + break; + } + if (Features & (1 << FEATURE_EM64T)) { + *Type = INTEL_X86_64; + break; // x86-64 + } + if (Features & (1 << FEATURE_SSE2)) { + *Type = INTEL_PENTIUM_M; + break; + } + if (Features & (1 << FEATURE_SSE)) { + *Type = INTEL_PENTIUM_III; + break; + } + if (Features & (1 << FEATURE_MMX)) { + *Type = INTEL_PENTIUM_II; + break; + } + *Type = INTEL_PENTIUM_PRO; + break; + } + break; + case 15: { + switch (Model) { + case 0: // Pentium 4 processor, Intel Xeon processor. All processors are + // model 00h and manufactured using the 0.18 micron process. + case 1: // Pentium 4 processor, Intel Xeon processor, Intel Xeon + // processor MP, and Intel Celeron processor. All processors are + // model 01h and manufactured using the 0.18 micron process. + case 2: // Pentium 4 processor, Mobile Intel Pentium 4 processor - M, + // Intel Xeon processor, Intel Xeon processor MP, Intel Celeron + // processor, and Mobile Intel Celeron processor. All processors + // are model 02h and manufactured using the 0.13 micron process. + *Type = + ((Features & (1 << FEATURE_EM64T)) ? INTEL_X86_64 : INTEL_PENTIUM_IV); + break; + + case 3: // Pentium 4 processor, Intel Xeon processor, Intel Celeron D + // processor. All processors are model 03h and manufactured using + // the 90 nm process. + case 4: // Pentium 4 processor, Pentium 4 processor Extreme Edition, + // Pentium D processor, Intel Xeon processor, Intel Xeon + // processor MP, Intel Celeron D processor. All processors are + // model 04h and manufactured using the 90 nm process. + case 6: // Pentium 4 processor, Pentium D processor, Pentium processor + // Extreme Edition, Intel Xeon processor, Intel Xeon processor + // MP, Intel Celeron D processor. All processors are model 06h + // and manufactured using the 65 nm process. + *Type = + ((Features & (1 << FEATURE_EM64T)) ? INTEL_NOCONA : INTEL_PRESCOTT); + break; + + default: + *Type = + ((Features & (1 << FEATURE_EM64T)) ? INTEL_X86_64 : INTEL_PENTIUM_IV); + break; + } + break; + } + default: + break; /*"generic"*/ + } +} + +static void getAMDProcessorTypeAndSubtype(unsigned int Family, + unsigned int Model, + unsigned int Features, + unsigned *Type, + unsigned *Subtype) { + // FIXME: this poorly matches the generated SubtargetFeatureKV table. There + // appears to be no way to generate the wide variety of AMD-specific targets + // from the information returned from CPUID. + switch (Family) { + case 4: + *Type = AMD_i486; + break; + case 5: + *Type = AMDPENTIUM; + switch (Model) { + case 6: + case 7: + *Subtype = AMDPENTIUM_K6; + break; // "k6" + case 8: + *Subtype = AMDPENTIUM_K62; + break; // "k6-2" + case 9: + case 13: + *Subtype = AMDPENTIUM_K63; + break; // "k6-3" + case 10: + *Subtype = AMDPENTIUM_GEODE; + break; // "geode" + } + break; + case 6: + *Type = AMDATHLON; + switch (Model) { + case 4: + *Subtype = AMDATHLON_TBIRD; + break; // "athlon-tbird" + case 6: + case 7: + case 8: + *Subtype = AMDATHLON_MP; + break; // "athlon-mp" + case 10: + *Subtype = AMDATHLON_XP; + break; // "athlon-xp" + } + break; + case 15: + *Type = AMDATHLON; + if (Features & (1 << FEATURE_SSE3)) { + *Subtype = AMDATHLON_K8SSE3; + break; // "k8-sse3" + } + switch (Model) { + case 1: + *Subtype = AMDATHLON_OPTERON; + break; // "opteron" + case 5: + *Subtype = AMDATHLON_FX; + break; // "athlon-fx"; also opteron + default: + *Subtype = AMDATHLON_64; + break; // "athlon64" + } + break; + case 16: + *Type = AMDFAM10H; // "amdfam10" + switch (Model) { + case 2: + *Subtype = AMDFAM10H_BARCELONA; + break; + case 4: + *Subtype = AMDFAM10H_SHANGHAI; + break; + case 8: + *Subtype = AMDFAM10H_ISTANBUL; + break; + } + break; + case 20: + *Type = AMDFAM14H; + *Subtype = AMD_BTVER1; + break; // "btver1"; + case 21: + *Type = AMDFAM15H; + if (!(Features & + (1 << FEATURE_AVX))) { // If no AVX support, provide a sane fallback. + *Subtype = AMD_BTVER1; + break; // "btver1" + } + if (Model >= 0x50 && Model <= 0x6f) { + *Subtype = AMDFAM15H_BDVER4; + break; // "bdver4"; 50h-6Fh: Excavator + } + if (Model >= 0x30 && Model <= 0x3f) { + *Subtype = AMDFAM15H_BDVER3; + break; // "bdver3"; 30h-3Fh: Steamroller + } + if (Model >= 0x10 && Model <= 0x1f) { + *Subtype = AMDFAM15H_BDVER2; + break; // "bdver2"; 10h-1Fh: Piledriver + } + if (Model <= 0x0f) { + *Subtype = AMDFAM15H_BDVER1; + break; // "bdver1"; 00h-0Fh: Bulldozer + } + break; + case 22: + *Type = AMDFAM16H; + if (!(Features & + (1 << FEATURE_AVX))) { // If no AVX support provide a sane fallback. + *Subtype = AMD_BTVER1; + break; // "btver1"; + } + *Subtype = AMD_BTVER2; + break; // "btver2" + default: + break; // "generic" + } +} + +static unsigned getAvailableFeatures(unsigned int ECX, unsigned int EDX, + unsigned MaxLeaf) { + unsigned Features = 0; + unsigned int EAX, EBX; + Features |= (((EDX >> 23) & 1) << FEATURE_MMX); + Features |= (((EDX >> 25) & 1) << FEATURE_SSE); + Features |= (((EDX >> 26) & 1) << FEATURE_SSE2); + Features |= (((ECX >> 0) & 1) << FEATURE_SSE3); + Features |= (((ECX >> 9) & 1) << FEATURE_SSSE3); + Features |= (((ECX >> 19) & 1) << FEATURE_SSE4_1); + Features |= (((ECX >> 20) & 1) << FEATURE_SSE4_2); + Features |= (((ECX >> 22) & 1) << FEATURE_MOVBE); + + // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV + // indicates that the AVX registers will be saved and restored on context + // switch, then we have full AVX support. + const unsigned AVXBits = (1 << 27) | (1 << 28); + bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) && + ((EAX & 0x6) == 0x6); + bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0); + bool HasLeaf7 = + MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX); + bool HasADX = HasLeaf7 && ((EBX >> 19) & 1); + bool HasAVX2 = HasAVX && HasLeaf7 && (EBX & 0x20); + bool HasAVX512 = HasLeaf7 && HasAVX512Save && ((EBX >> 16) & 1); + Features |= (HasAVX << FEATURE_AVX); + Features |= (HasAVX2 << FEATURE_AVX2); + Features |= (HasAVX512 << FEATURE_AVX512); + Features |= (HasAVX512Save << FEATURE_AVX512SAVE); + Features |= (HasADX << FEATURE_ADX); + + getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); + Features |= (((EDX >> 29) & 0x1) << FEATURE_EM64T); + return Features; +} + +StringRef sys::getHostCPUName() { + unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; + unsigned MaxLeaf, Vendor; + +#if defined(__GNUC__) || defined(__clang__) + //FIXME: include cpuid.h from clang or copy __get_cpuid_max here + // and simplify it to not invoke __cpuid (like cpu_model.c in + // compiler-rt/lib/builtins/cpu_model.c? + if(!__get_cpuid_max(0, &Vendor)) + return "generic"; +#endif + if (getX86CpuIDAndInfo(0, &MaxLeaf, &Vendor, &ECX, &EDX)) + return "generic"; + if (getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX)) + return "generic"; + + unsigned Brand_id = EBX & 0xff; + unsigned Family = 0, Model = 0; + unsigned Features = 0; + detectX86FamilyModel(EAX, &Family, &Model); + Features = getAvailableFeatures(ECX, EDX, MaxLeaf); + + unsigned Type; + unsigned Subtype; + + if (Vendor == SIG_INTEL) { + getIntelProcessorTypeAndSubtype(Family, Model, Brand_id, Features, &Type, + &Subtype); + switch (Type) { + case INTEL_i386: + return "i386"; + case INTEL_i486: + return "i486"; + case INTEL_PENTIUM: + if (Subtype == INTEL_PENTIUM_MMX) + return "pentium-mmx"; + return "pentium"; + case INTEL_PENTIUM_PRO: + return "pentiumpro"; + case INTEL_PENTIUM_II: + return "pentium2"; + case INTEL_PENTIUM_III: + return "pentium3"; + case INTEL_PENTIUM_IV: + return "pentium4"; + case INTEL_PENTIUM_M: + return "pentium-m"; + case INTEL_CORE_DUO: + return "yonah"; + case INTEL_CORE2: + switch (Subtype) { + case INTEL_CORE2_65: + return "core2"; + case INTEL_CORE2_45: + return "penryn"; + default: + return "core2"; + } + case INTEL_COREI7: + switch (Subtype) { + case INTEL_COREI7_NEHALEM: + return "nehalem"; + case INTEL_COREI7_WESTMERE: + return "westmere"; + case INTEL_COREI7_SANDYBRIDGE: + return "sandybridge"; + case INTEL_COREI7_IVYBRIDGE: + return "ivybridge"; + case INTEL_COREI7_HASWELL: + return "haswell"; + case INTEL_COREI7_BROADWELL: + return "broadwell"; + case INTEL_COREI7_SKYLAKE: + return "skylake"; + case INTEL_COREI7_SKYLAKE_AVX512: + return "skylake-avx512"; + default: + return "corei7"; + } + case INTEL_ATOM: + switch (Subtype) { + case INTEL_ATOM_BONNELL: + return "bonnell"; + case INTEL_ATOM_SILVERMONT: + return "silvermont"; + default: + return "atom"; + } + case INTEL_XEONPHI: + return "knl"; /*update for more variants added*/ + case INTEL_X86_64: + return "x86-64"; + case INTEL_NOCONA: + return "nocona"; + case INTEL_PRESCOTT: + return "prescott"; + default: + return "generic"; + } + } else if (Vendor == SIG_AMD) { + getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type, &Subtype); + switch (Type) { + case AMD_i486: + return "i486"; + case AMDPENTIUM: + switch (Subtype) { + case AMDPENTIUM_K6: + return "k6"; + case AMDPENTIUM_K62: + return "k6-2"; + case AMDPENTIUM_K63: + return "k6-3"; + case AMDPENTIUM_GEODE: + return "geode"; + default: + return "pentium"; + } + case AMDATHLON: + switch (Subtype) { + case AMDATHLON_TBIRD: + return "athlon-tbird"; + case AMDATHLON_MP: + return "athlon-mp"; + case AMDATHLON_XP: + return "athlon-xp"; + case AMDATHLON_K8SSE3: + return "k8-sse3"; + case AMDATHLON_OPTERON: + return "opteron"; + case AMDATHLON_FX: + return "athlon-fx"; + case AMDATHLON_64: + return "athlon64"; + default: + return "athlon"; + } + case AMDFAM10H: + if(Subtype == AMDFAM10H_BARCELONA) + return "barcelona"; + return "amdfam10"; + case AMDFAM14H: + return "btver1"; + case AMDFAM15H: + switch (Subtype) { + case AMDFAM15H_BDVER1: + return "bdver1"; + case AMDFAM15H_BDVER2: + return "bdver2"; + case AMDFAM15H_BDVER3: + return "bdver3"; + case AMDFAM15H_BDVER4: + return "bdver4"; + case AMD_BTVER1: + return "btver1"; + default: + return "amdfam15"; + } + case AMDFAM16H: + switch (Subtype) { + case AMD_BTVER1: + return "btver1"; + case AMD_BTVER2: + return "btver2"; + default: + return "amdfam16"; + } + default: + return "generic"; + } + } + return "generic"; +} + +#elif defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__)) +StringRef sys::getHostCPUName() { + host_basic_info_data_t hostInfo; + mach_msg_type_number_t infoCount; + + infoCount = HOST_BASIC_INFO_COUNT; + host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, + &infoCount); + + if (hostInfo.cpu_type != CPU_TYPE_POWERPC) + return "generic"; + + switch (hostInfo.cpu_subtype) { + case CPU_SUBTYPE_POWERPC_601: + return "601"; + case CPU_SUBTYPE_POWERPC_602: + return "602"; + case CPU_SUBTYPE_POWERPC_603: + return "603"; + case CPU_SUBTYPE_POWERPC_603e: + return "603e"; + case CPU_SUBTYPE_POWERPC_603ev: + return "603ev"; + case CPU_SUBTYPE_POWERPC_604: + return "604"; + case CPU_SUBTYPE_POWERPC_604e: + return "604e"; + case CPU_SUBTYPE_POWERPC_620: + return "620"; + case CPU_SUBTYPE_POWERPC_750: + return "750"; + case CPU_SUBTYPE_POWERPC_7400: + return "7400"; + case CPU_SUBTYPE_POWERPC_7450: + return "7450"; + case CPU_SUBTYPE_POWERPC_970: + return "970"; + default:; + } + + return "generic"; +} +#elif defined(__linux__) && (defined(__ppc__) || defined(__powerpc__)) +StringRef sys::getHostCPUName() { + // Access to the Processor Version Register (PVR) on PowerPC is privileged, + // and so we must use an operating-system interface to determine the current + // processor type. On Linux, this is exposed through the /proc/cpuinfo file. + const char *generic = "generic"; + + // The cpu line is second (after the 'processor: 0' line), so if this + // buffer is too small then something has changed (or is wrong). + char buffer[1024]; + ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer)); + if (CPUInfoSize == -1) + return generic; + + const char *CPUInfoStart = buffer; + const char *CPUInfoEnd = buffer + CPUInfoSize; + + const char *CIP = CPUInfoStart; + + const char *CPUStart = 0; + size_t CPULen = 0; + + // We need to find the first line which starts with cpu, spaces, and a colon. + // After the colon, there may be some additional spaces and then the cpu type. + while (CIP < CPUInfoEnd && CPUStart == 0) { + if (CIP < CPUInfoEnd && *CIP == '\n') + ++CIP; + + if (CIP < CPUInfoEnd && *CIP == 'c') { + ++CIP; + if (CIP < CPUInfoEnd && *CIP == 'p') { + ++CIP; + if (CIP < CPUInfoEnd && *CIP == 'u') { + ++CIP; + while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t')) + ++CIP; + + if (CIP < CPUInfoEnd && *CIP == ':') { + ++CIP; + while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t')) + ++CIP; + + if (CIP < CPUInfoEnd) { + CPUStart = CIP; + while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' && + *CIP != ',' && *CIP != '\n')) + ++CIP; + CPULen = CIP - CPUStart; + } + } + } + } + } + + if (CPUStart == 0) + while (CIP < CPUInfoEnd && *CIP != '\n') + ++CIP; + } + + if (CPUStart == 0) + return generic; + + return StringSwitch<const char *>(StringRef(CPUStart, CPULen)) + .Case("604e", "604e") + .Case("604", "604") + .Case("7400", "7400") + .Case("7410", "7400") + .Case("7447", "7400") + .Case("7455", "7450") + .Case("G4", "g4") + .Case("POWER4", "970") + .Case("PPC970FX", "970") + .Case("PPC970MP", "970") + .Case("G5", "g5") + .Case("POWER5", "g5") + .Case("A2", "a2") + .Case("POWER6", "pwr6") + .Case("POWER7", "pwr7") + .Case("POWER8", "pwr8") + .Case("POWER8E", "pwr8") + .Case("POWER9", "pwr9") + .Default(generic); +} +#elif defined(__linux__) && defined(__arm__) +StringRef sys::getHostCPUName() { + // The cpuid register on arm is not accessible from user space. On Linux, + // it is exposed through the /proc/cpuinfo file. + + // Read 1024 bytes from /proc/cpuinfo, which should contain the CPU part line + // in all cases. + char buffer[1024]; + ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer)); + if (CPUInfoSize == -1) + return "generic"; + + StringRef Str(buffer, CPUInfoSize); + + SmallVector<StringRef, 32> Lines; + Str.split(Lines, "\n"); + + // Look for the CPU implementer line. + StringRef Implementer; + for (unsigned I = 0, E = Lines.size(); I != E; ++I) + if (Lines[I].startswith("CPU implementer")) + Implementer = Lines[I].substr(15).ltrim("\t :"); + + if (Implementer == "0x41") // ARM Ltd. + // Look for the CPU part line. + for (unsigned I = 0, E = Lines.size(); I != E; ++I) + if (Lines[I].startswith("CPU part")) + // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The + // values correspond to the "Part number" in the CP15/c0 register. The + // contents are specified in the various processor manuals. + return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :")) + .Case("0x926", "arm926ej-s") + .Case("0xb02", "mpcore") + .Case("0xb36", "arm1136j-s") + .Case("0xb56", "arm1156t2-s") + .Case("0xb76", "arm1176jz-s") + .Case("0xc08", "cortex-a8") + .Case("0xc09", "cortex-a9") + .Case("0xc0f", "cortex-a15") + .Case("0xc20", "cortex-m0") + .Case("0xc23", "cortex-m3") + .Case("0xc24", "cortex-m4") + .Default("generic"); + + if (Implementer == "0x51") // Qualcomm Technologies, Inc. + // Look for the CPU part line. + for (unsigned I = 0, E = Lines.size(); I != E; ++I) + if (Lines[I].startswith("CPU part")) + // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The + // values correspond to the "Part number" in the CP15/c0 register. The + // contents are specified in the various processor manuals. + return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :")) + .Case("0x06f", "krait") // APQ8064 + .Default("generic"); + + return "generic"; +} +#elif defined(__linux__) && defined(__s390x__) +StringRef sys::getHostCPUName() { + // STIDP is a privileged operation, so use /proc/cpuinfo instead. + + // The "processor 0:" line comes after a fair amount of other information, + // including a cache breakdown, but this should be plenty. + char buffer[2048]; + ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer)); + if (CPUInfoSize == -1) + return "generic"; + + StringRef Str(buffer, CPUInfoSize); + SmallVector<StringRef, 32> Lines; + Str.split(Lines, "\n"); + + // Look for the CPU features. + SmallVector<StringRef, 32> CPUFeatures; + for (unsigned I = 0, E = Lines.size(); I != E; ++I) + if (Lines[I].startswith("features")) { + size_t Pos = Lines[I].find(":"); + if (Pos != StringRef::npos) { + Lines[I].drop_front(Pos + 1).split(CPUFeatures, ' '); + break; + } + } + + // We need to check for the presence of vector support independently of + // the machine type, since we may only use the vector register set when + // supported by the kernel (and hypervisor). + bool HaveVectorSupport = false; + for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) { + if (CPUFeatures[I] == "vx") + HaveVectorSupport = true; + } + + // Now check the processor machine type. + for (unsigned I = 0, E = Lines.size(); I != E; ++I) { + if (Lines[I].startswith("processor ")) { + size_t Pos = Lines[I].find("machine = "); + if (Pos != StringRef::npos) { + Pos += sizeof("machine = ") - 1; + unsigned int Id; + if (!Lines[I].drop_front(Pos).getAsInteger(10, Id)) { + if (Id >= 2964 && HaveVectorSupport) + return "z13"; + if (Id >= 2827) + return "zEC12"; + if (Id >= 2817) + return "z196"; + } + } + break; + } + } + + return "generic"; +} +#else +StringRef sys::getHostCPUName() { return "generic"; } +#endif + +#if defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64__) || defined(_M_X64) +bool sys::getHostCPUFeatures(StringMap<bool> &Features) { + unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; + unsigned MaxLevel; + union { + unsigned u[3]; + char c[12]; + } text; + + if (getX86CpuIDAndInfo(0, &MaxLevel, text.u + 0, text.u + 2, text.u + 1) || + MaxLevel < 1) + return false; + + getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX); + + Features["cmov"] = (EDX >> 15) & 1; + Features["mmx"] = (EDX >> 23) & 1; + Features["sse"] = (EDX >> 25) & 1; + Features["sse2"] = (EDX >> 26) & 1; + Features["sse3"] = (ECX >> 0) & 1; + Features["ssse3"] = (ECX >> 9) & 1; + Features["sse4.1"] = (ECX >> 19) & 1; + Features["sse4.2"] = (ECX >> 20) & 1; + + Features["pclmul"] = (ECX >> 1) & 1; + Features["cx16"] = (ECX >> 13) & 1; + Features["movbe"] = (ECX >> 22) & 1; + Features["popcnt"] = (ECX >> 23) & 1; + Features["aes"] = (ECX >> 25) & 1; + Features["rdrnd"] = (ECX >> 30) & 1; + + // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV + // indicates that the AVX registers will be saved and restored on context + // switch, then we have full AVX support. + bool HasAVXSave = ((ECX >> 27) & 1) && ((ECX >> 28) & 1) && + !getX86XCR0(&EAX, &EDX) && ((EAX & 0x6) == 0x6); + Features["avx"] = HasAVXSave; + Features["fma"] = HasAVXSave && (ECX >> 12) & 1; + Features["f16c"] = HasAVXSave && (ECX >> 29) & 1; + + // Only enable XSAVE if OS has enabled support for saving YMM state. + Features["xsave"] = HasAVXSave && (ECX >> 26) & 1; + + // AVX512 requires additional context to be saved by the OS. + bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0); + + unsigned MaxExtLevel; + getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX); + + bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 && + !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); + Features["lzcnt"] = HasExtLeaf1 && ((ECX >> 5) & 1); + Features["sse4a"] = HasExtLeaf1 && ((ECX >> 6) & 1); + Features["prfchw"] = HasExtLeaf1 && ((ECX >> 8) & 1); + Features["xop"] = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave; + Features["fma4"] = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave; + Features["tbm"] = HasExtLeaf1 && ((ECX >> 21) & 1); + Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1); + + bool HasLeaf7 = + MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX); + + // AVX2 is only supported if we have the OS save support from AVX. + Features["avx2"] = HasAVXSave && HasLeaf7 && ((EBX >> 5) & 1); + + Features["fsgsbase"] = HasLeaf7 && ((EBX >> 0) & 1); + Features["sgx"] = HasLeaf7 && ((EBX >> 2) & 1); + Features["bmi"] = HasLeaf7 && ((EBX >> 3) & 1); + Features["hle"] = HasLeaf7 && ((EBX >> 4) & 1); + Features["bmi2"] = HasLeaf7 && ((EBX >> 8) & 1); + Features["invpcid"] = HasLeaf7 && ((EBX >> 10) & 1); + Features["rtm"] = HasLeaf7 && ((EBX >> 11) & 1); + Features["rdseed"] = HasLeaf7 && ((EBX >> 18) & 1); + Features["adx"] = HasLeaf7 && ((EBX >> 19) & 1); + Features["smap"] = HasLeaf7 && ((EBX >> 20) & 1); + Features["pcommit"] = HasLeaf7 && ((EBX >> 22) & 1); + Features["clflushopt"] = HasLeaf7 && ((EBX >> 23) & 1); + Features["clwb"] = HasLeaf7 && ((EBX >> 24) & 1); + Features["sha"] = HasLeaf7 && ((EBX >> 29) & 1); + + // AVX512 is only supported if the OS supports the context save for it. + Features["avx512f"] = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save; + Features["avx512dq"] = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save; + Features["avx512ifma"] = HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save; + Features["avx512pf"] = HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save; + Features["avx512er"] = HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save; + Features["avx512cd"] = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save; + Features["avx512bw"] = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save; + Features["avx512vl"] = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save; + + Features["prefetchwt1"] = HasLeaf7 && (ECX & 1); + Features["avx512vbmi"] = HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save; + // Enable protection keys + Features["pku"] = HasLeaf7 && ((ECX >> 4) & 1); + + bool HasLeafD = MaxLevel >= 0xd && + !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX); + + // Only enable XSAVE if OS has enabled support for saving YMM state. + Features["xsaveopt"] = HasAVXSave && HasLeafD && ((EAX >> 0) & 1); + Features["xsavec"] = HasAVXSave && HasLeafD && ((EAX >> 1) & 1); + Features["xsaves"] = HasAVXSave && HasLeafD && ((EAX >> 3) & 1); + + return true; +} +#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__)) +bool sys::getHostCPUFeatures(StringMap<bool> &Features) { + // Read 1024 bytes from /proc/cpuinfo, which should contain the Features line + // in all cases. + char buffer[1024]; + ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer)); + if (CPUInfoSize == -1) + return false; + + StringRef Str(buffer, CPUInfoSize); + + SmallVector<StringRef, 32> Lines; + Str.split(Lines, "\n"); + + SmallVector<StringRef, 32> CPUFeatures; + + // Look for the CPU features. + for (unsigned I = 0, E = Lines.size(); I != E; ++I) + if (Lines[I].startswith("Features")) { + Lines[I].split(CPUFeatures, ' '); + break; + } + +#if defined(__aarch64__) + // Keep track of which crypto features we have seen + enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 }; + uint32_t crypto = 0; +#endif + + for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) { + StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I]) +#if defined(__aarch64__) + .Case("asimd", "neon") + .Case("fp", "fp-armv8") + .Case("crc32", "crc") +#else + .Case("half", "fp16") + .Case("neon", "neon") + .Case("vfpv3", "vfp3") + .Case("vfpv3d16", "d16") + .Case("vfpv4", "vfp4") + .Case("idiva", "hwdiv-arm") + .Case("idivt", "hwdiv") +#endif + .Default(""); + +#if defined(__aarch64__) + // We need to check crypto separately since we need all of the crypto + // extensions to enable the subtarget feature + if (CPUFeatures[I] == "aes") + crypto |= CAP_AES; + else if (CPUFeatures[I] == "pmull") + crypto |= CAP_PMULL; + else if (CPUFeatures[I] == "sha1") + crypto |= CAP_SHA1; + else if (CPUFeatures[I] == "sha2") + crypto |= CAP_SHA2; +#endif + + if (LLVMFeatureStr != "") + Features[LLVMFeatureStr] = true; + } + +#if defined(__aarch64__) + // If we have all crypto bits we can add the feature + if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2)) + Features["crypto"] = true; +#endif + + return true; +} +#else +bool sys::getHostCPUFeatures(StringMap<bool> &Features) { return false; } +#endif + +std::string sys::getProcessTriple() { + Triple PT(Triple::normalize(LLVM_HOST_TRIPLE)); + + if (sizeof(void *) == 8 && PT.isArch32Bit()) + PT = PT.get64BitArchVariant(); + if (sizeof(void *) == 4 && PT.isArch64Bit()) + PT = PT.get32BitArchVariant(); + + return PT.str(); +}
diff --git a/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp b/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp new file mode 100644 index 0000000..7dd3131 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/ManagedStatic.cpp
@@ -0,0 +1,88 @@ +//===-- ManagedStatic.cpp - Static Global wrapper -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the ManagedStatic class and llvm_shutdown(). +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Config/config.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/MutexGuard.h" +#include "llvm/Support/Threading.h" +#include <cassert> +using namespace llvm; + +static const ManagedStaticBase *StaticList = nullptr; +static sys::Mutex *ManagedStaticMutex = nullptr; +LLVM_DEFINE_ONCE_FLAG(mutex_init_flag); + +static void initializeMutex() { + ManagedStaticMutex = new sys::Mutex(); +} + +static sys::Mutex* getManagedStaticMutex() { + // We need to use a function local static here, since this can get called + // during a static constructor and we need to guarantee that it's initialized + // correctly. + llvm::call_once(mutex_init_flag, initializeMutex); + return ManagedStaticMutex; +} + +void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), + void (*Deleter)(void*)) const { + assert(Creator); + if (llvm_is_multithreaded()) { + MutexGuard Lock(*getManagedStaticMutex()); + + if (!Ptr.load(std::memory_order_relaxed)) { + void *Tmp = Creator(); + + Ptr.store(Tmp, std::memory_order_release); + DeleterFn = Deleter; + + // Add to list of managed statics. + Next = StaticList; + StaticList = this; + } + } else { + assert(!Ptr && !DeleterFn && !Next && + "Partially initialized ManagedStatic!?"); + Ptr = Creator(); + DeleterFn = Deleter; + + // Add to list of managed statics. + Next = StaticList; + StaticList = this; + } +} + +void ManagedStaticBase::destroy() const { + assert(DeleterFn && "ManagedStatic not initialized correctly!"); + assert(StaticList == this && + "Not destroyed in reverse order of construction?"); + // Unlink from list. + StaticList = Next; + Next = nullptr; + + // Destroy memory. + DeleterFn(Ptr); + + // Cleanup. + Ptr = nullptr; + DeleterFn = nullptr; +} + +/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. +void llvm::llvm_shutdown() { + MutexGuard Lock(*getManagedStaticMutex()); + + while (StaticList) + StaticList->destroy(); +}
diff --git a/third_party/llvm-subzero/lib/Support/MemoryBuffer.cpp b/third_party/llvm-subzero/lib/Support/MemoryBuffer.cpp new file mode 100644 index 0000000..b935cbf --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/MemoryBuffer.cpp
@@ -0,0 +1,445 @@ +//===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the MemoryBuffer interface. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Config/config.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/Errno.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" +#include <cassert> +#include <cerrno> +#include <cstring> +#include <new> +#include <sys/types.h> +#include <system_error> +#if !defined(_MSC_VER) && !defined(__MINGW32__) +#include <unistd.h> +#else +#include <io.h> +#endif +using namespace llvm; + +//===----------------------------------------------------------------------===// +// MemoryBuffer implementation itself. +//===----------------------------------------------------------------------===// + +MemoryBuffer::~MemoryBuffer() { } + +/// init - Initialize this MemoryBuffer as a reference to externally allocated +/// memory, memory that we know is already null terminated. +void MemoryBuffer::init(const char *BufStart, const char *BufEnd, + bool RequiresNullTerminator) { + assert((!RequiresNullTerminator || BufEnd[0] == 0) && + "Buffer is not null terminated!"); + BufferStart = BufStart; + BufferEnd = BufEnd; +} + +//===----------------------------------------------------------------------===// +// MemoryBufferMem implementation. +//===----------------------------------------------------------------------===// + +/// CopyStringRef - Copies contents of a StringRef into a block of memory and +/// null-terminates it. +static void CopyStringRef(char *Memory, StringRef Data) { + if (!Data.empty()) + memcpy(Memory, Data.data(), Data.size()); + Memory[Data.size()] = 0; // Null terminate string. +} + +namespace { +struct NamedBufferAlloc { + const Twine &Name; + NamedBufferAlloc(const Twine &Name) : Name(Name) {} +}; +} + +void *operator new(size_t N, const NamedBufferAlloc &Alloc) { + SmallString<256> NameBuf; + StringRef NameRef = Alloc.Name.toStringRef(NameBuf); + + char *Mem = static_cast<char *>(operator new(N + NameRef.size() + 1)); + CopyStringRef(Mem + N, NameRef); + return Mem; +} + +namespace { +/// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory. +class MemoryBufferMem : public MemoryBuffer { +public: + MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) { + init(InputData.begin(), InputData.end(), RequiresNullTerminator); + } + + /// Disable sized deallocation for MemoryBufferMem, because it has + /// tail-allocated data. + void operator delete(void *p) { ::operator delete(p); } + + const char *getBufferIdentifier() const override { + // The name is stored after the class itself. + return reinterpret_cast<const char*>(this + 1); + } + + BufferKind getBufferKind() const override { + return MemoryBuffer_Malloc; + } +}; +} + +static ErrorOr<std::unique_ptr<MemoryBuffer>> +getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize, + uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize); + +std::unique_ptr<MemoryBuffer> +MemoryBuffer::getMemBuffer(StringRef InputData, StringRef BufferName, + bool RequiresNullTerminator) { + auto *Ret = new (NamedBufferAlloc(BufferName)) + MemoryBufferMem(InputData, RequiresNullTerminator); + return std::unique_ptr<MemoryBuffer>(Ret); +} + +std::unique_ptr<MemoryBuffer> +MemoryBuffer::getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator) { + return std::unique_ptr<MemoryBuffer>(getMemBuffer( + Ref.getBuffer(), Ref.getBufferIdentifier(), RequiresNullTerminator)); +} + +std::unique_ptr<MemoryBuffer> +MemoryBuffer::getMemBufferCopy(StringRef InputData, const Twine &BufferName) { + std::unique_ptr<MemoryBuffer> Buf = + getNewUninitMemBuffer(InputData.size(), BufferName); + if (!Buf) + return nullptr; + memcpy(const_cast<char*>(Buf->getBufferStart()), InputData.data(), + InputData.size()); + return Buf; +} + +std::unique_ptr<MemoryBuffer> +MemoryBuffer::getNewUninitMemBuffer(size_t Size, const Twine &BufferName) { + // Allocate space for the MemoryBuffer, the data and the name. It is important + // that MemoryBuffer and data are aligned so PointerIntPair works with them. + // TODO: Is 16-byte alignment enough? We copy small object files with large + // alignment expectations into this buffer. + SmallString<256> NameBuf; + StringRef NameRef = BufferName.toStringRef(NameBuf); + size_t AlignedStringLen = + alignTo(sizeof(MemoryBufferMem) + NameRef.size() + 1, 16); + size_t RealLen = AlignedStringLen + Size + 1; + char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow)); + if (!Mem) + return nullptr; + + // The name is stored after the class itself. + CopyStringRef(Mem + sizeof(MemoryBufferMem), NameRef); + + // The buffer begins after the name and must be aligned. + char *Buf = Mem + AlignedStringLen; + Buf[Size] = 0; // Null terminate buffer. + + auto *Ret = new (Mem) MemoryBufferMem(StringRef(Buf, Size), true); + return std::unique_ptr<MemoryBuffer>(Ret); +} + +std::unique_ptr<MemoryBuffer> +MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) { + std::unique_ptr<MemoryBuffer> SB = getNewUninitMemBuffer(Size, BufferName); + if (!SB) + return nullptr; + memset(const_cast<char*>(SB->getBufferStart()), 0, Size); + return SB; +} + +ErrorOr<std::unique_ptr<MemoryBuffer>> +MemoryBuffer::getFileOrSTDIN(const Twine &Filename, int64_t FileSize, + bool RequiresNullTerminator) { + SmallString<256> NameBuf; + StringRef NameRef = Filename.toStringRef(NameBuf); + + if (NameRef == "-") + return getSTDIN(); + return getFile(Filename, FileSize, RequiresNullTerminator); +} + +ErrorOr<std::unique_ptr<MemoryBuffer>> +MemoryBuffer::getFileSlice(const Twine &FilePath, uint64_t MapSize, + uint64_t Offset) { + return getFileAux(FilePath, -1, MapSize, Offset, false, false); +} + + +//===----------------------------------------------------------------------===// +// MemoryBuffer::getFile implementation. +//===----------------------------------------------------------------------===// + +namespace { +/// \brief Memory maps a file descriptor using sys::fs::mapped_file_region. +/// +/// This handles converting the offset into a legal offset on the platform. +class MemoryBufferMMapFile : public MemoryBuffer { + sys::fs::mapped_file_region MFR; + + static uint64_t getLegalMapOffset(uint64_t Offset) { + return Offset & ~(sys::fs::mapped_file_region::alignment() - 1); + } + + static uint64_t getLegalMapSize(uint64_t Len, uint64_t Offset) { + return Len + (Offset - getLegalMapOffset(Offset)); + } + + const char *getStart(uint64_t Len, uint64_t Offset) { + return MFR.const_data() + (Offset - getLegalMapOffset(Offset)); + } + +public: + MemoryBufferMMapFile(bool RequiresNullTerminator, int FD, uint64_t Len, + uint64_t Offset, std::error_code &EC) + : MFR(FD, sys::fs::mapped_file_region::readonly, + getLegalMapSize(Len, Offset), getLegalMapOffset(Offset), EC) { + if (!EC) { + const char *Start = getStart(Len, Offset); + init(Start, Start + Len, RequiresNullTerminator); + } + } + + /// Disable sized deallocation for MemoryBufferMMapFile, because it has + /// tail-allocated data. + void operator delete(void *p) { ::operator delete(p); } + + const char *getBufferIdentifier() const override { + // The name is stored after the class itself. + return reinterpret_cast<const char *>(this + 1); + } + + BufferKind getBufferKind() const override { + return MemoryBuffer_MMap; + } +}; +} + +static ErrorOr<std::unique_ptr<MemoryBuffer>> +getMemoryBufferForStream(int FD, const Twine &BufferName) { + const ssize_t ChunkSize = 4096*4; + SmallString<ChunkSize> Buffer; + ssize_t ReadBytes; + // Read into Buffer until we hit EOF. + do { + Buffer.reserve(Buffer.size() + ChunkSize); + ReadBytes = read(FD, Buffer.end(), ChunkSize); + if (ReadBytes == -1) { + if (errno == EINTR) continue; + return std::error_code(errno, std::generic_category()); + } + Buffer.set_size(Buffer.size() + ReadBytes); + } while (ReadBytes != 0); + + return MemoryBuffer::getMemBufferCopy(Buffer, BufferName); +} + + +ErrorOr<std::unique_ptr<MemoryBuffer>> +MemoryBuffer::getFile(const Twine &Filename, int64_t FileSize, + bool RequiresNullTerminator, bool IsVolatileSize) { + return getFileAux(Filename, FileSize, FileSize, 0, + RequiresNullTerminator, IsVolatileSize); +} + +static ErrorOr<std::unique_ptr<MemoryBuffer>> +getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize, + uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator, + bool IsVolatileSize); + +static ErrorOr<std::unique_ptr<MemoryBuffer>> +getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize, + uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize) { + int FD; + std::error_code EC = sys::fs::openFileForRead(Filename, FD); + if (EC) + return EC; + + ErrorOr<std::unique_ptr<MemoryBuffer>> Ret = + getOpenFileImpl(FD, Filename, FileSize, MapSize, Offset, + RequiresNullTerminator, IsVolatileSize); + close(FD); + return Ret; +} + +static bool shouldUseMmap(int FD, + size_t FileSize, + size_t MapSize, + off_t Offset, + bool RequiresNullTerminator, + int PageSize, + bool IsVolatileSize) { + // mmap may leave the buffer without null terminator if the file size changed + // by the time the last page is mapped in, so avoid it if the file size is + // likely to change. + if (IsVolatileSize) + return false; + + // We don't use mmap for small files because this can severely fragment our + // address space. + if (MapSize < 4 * 4096 || MapSize < (unsigned)PageSize) + return false; + + if (!RequiresNullTerminator) + return true; + + + // If we don't know the file size, use fstat to find out. fstat on an open + // file descriptor is cheaper than stat on a random path. + // FIXME: this chunk of code is duplicated, but it avoids a fstat when + // RequiresNullTerminator = false and MapSize != -1. + if (FileSize == size_t(-1)) { + sys::fs::file_status Status; + if (sys::fs::status(FD, Status)) + return false; + FileSize = Status.getSize(); + } + + // If we need a null terminator and the end of the map is inside the file, + // we cannot use mmap. + size_t End = Offset + MapSize; + assert(End <= FileSize); + if (End != FileSize) + return false; + + // Don't try to map files that are exactly a multiple of the system page size + // if we need a null terminator. + if ((FileSize & (PageSize -1)) == 0) + return false; + +#if defined(__CYGWIN__) + // Don't try to map files that are exactly a multiple of the physical page size + // if we need a null terminator. + // FIXME: We should reorganize again getPageSize() on Win32. + if ((FileSize & (4096 - 1)) == 0) + return false; +#endif + + return true; +} + +static ErrorOr<std::unique_ptr<MemoryBuffer>> +getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize, + uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator, + bool IsVolatileSize) { + static int PageSize = sys::Process::getPageSize(); + + // Default is to map the full file. + if (MapSize == uint64_t(-1)) { + // If we don't know the file size, use fstat to find out. fstat on an open + // file descriptor is cheaper than stat on a random path. + if (FileSize == uint64_t(-1)) { + sys::fs::file_status Status; + std::error_code EC = sys::fs::status(FD, Status); + if (EC) + return EC; + + // If this not a file or a block device (e.g. it's a named pipe + // or character device), we can't trust the size. Create the memory + // buffer by copying off the stream. + sys::fs::file_type Type = Status.type(); + if (Type != sys::fs::file_type::regular_file && + Type != sys::fs::file_type::block_file) + return getMemoryBufferForStream(FD, Filename); + + FileSize = Status.getSize(); + } + MapSize = FileSize; + } + + if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator, + PageSize, IsVolatileSize)) { + std::error_code EC; + std::unique_ptr<MemoryBuffer> Result( + new (NamedBufferAlloc(Filename)) + MemoryBufferMMapFile(RequiresNullTerminator, FD, MapSize, Offset, EC)); + if (!EC) + return std::move(Result); + } + + std::unique_ptr<MemoryBuffer> Buf = + MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename); + if (!Buf) { + // Failed to create a buffer. The only way it can fail is if + // new(std::nothrow) returns 0. + return make_error_code(errc::not_enough_memory); + } + + char *BufPtr = const_cast<char *>(Buf->getBufferStart()); + + size_t BytesLeft = MapSize; +#ifndef HAVE_PREAD + if (lseek(FD, Offset, SEEK_SET) == -1) + return std::error_code(errno, std::generic_category()); +#endif + + while (BytesLeft) { +#ifdef HAVE_PREAD + ssize_t NumRead = ::pread(FD, BufPtr, BytesLeft, MapSize-BytesLeft+Offset); +#else + ssize_t NumRead = ::read(FD, BufPtr, BytesLeft); +#endif + if (NumRead == -1) { + if (errno == EINTR) + continue; + // Error while reading. + return std::error_code(errno, std::generic_category()); + } + if (NumRead == 0) { + memset(BufPtr, 0, BytesLeft); // zero-initialize rest of the buffer. + break; + } + BytesLeft -= NumRead; + BufPtr += NumRead; + } + + return std::move(Buf); +} + +ErrorOr<std::unique_ptr<MemoryBuffer>> +MemoryBuffer::getOpenFile(int FD, const Twine &Filename, uint64_t FileSize, + bool RequiresNullTerminator, bool IsVolatileSize) { + return getOpenFileImpl(FD, Filename, FileSize, FileSize, 0, + RequiresNullTerminator, IsVolatileSize); +} + +ErrorOr<std::unique_ptr<MemoryBuffer>> +MemoryBuffer::getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize, + int64_t Offset) { + assert(MapSize != uint64_t(-1)); + return getOpenFileImpl(FD, Filename, -1, MapSize, Offset, false, + /*IsVolatileSize*/ false); +} + +ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getSTDIN() { + // Read in all of the data from stdin, we cannot mmap stdin. + // + // FIXME: That isn't necessarily true, we should try to mmap stdin and + // fallback if it fails. + sys::ChangeStdinToBinary(); + + return getMemoryBufferForStream(0, "<stdin>"); +} + +MemoryBufferRef MemoryBuffer::getMemBufferRef() const { + StringRef Data = getBuffer(); + StringRef Identifier = getBufferIdentifier(); + return MemoryBufferRef(Data, Identifier); +}
diff --git a/third_party/llvm-subzero/lib/Support/Mutex.cpp b/third_party/llvm-subzero/lib/Support/Mutex.cpp new file mode 100644 index 0000000..c8d3844 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Mutex.cpp
@@ -0,0 +1,122 @@ +//===- Mutex.cpp - Mutual Exclusion Lock ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the llvm::sys::Mutex class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" +#include "llvm/Support/Mutex.h" + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0 +// Define all methods as no-ops if threading is explicitly disabled +namespace llvm { +using namespace sys; +MutexImpl::MutexImpl( bool recursive) { } +MutexImpl::~MutexImpl() { } +bool MutexImpl::acquire() { return true; } +bool MutexImpl::release() { return true; } +bool MutexImpl::tryacquire() { return true; } +} +#else + +#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_MUTEX_LOCK) + +#include <cassert> +#include <pthread.h> +#include <stdlib.h> + +namespace llvm { +using namespace sys; + +// Construct a Mutex using pthread calls +MutexImpl::MutexImpl( bool recursive) + : data_(nullptr) +{ + // Declare the pthread_mutex data structures + pthread_mutex_t* mutex = + static_cast<pthread_mutex_t*>(malloc(sizeof(pthread_mutex_t))); + pthread_mutexattr_t attr; + + // Initialize the mutex attributes + int errorcode = pthread_mutexattr_init(&attr); + assert(errorcode == 0); (void)errorcode; + + // Initialize the mutex as a recursive mutex, if requested, or normal + // otherwise. + int kind = ( recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL ); + errorcode = pthread_mutexattr_settype(&attr, kind); + assert(errorcode == 0); + + // Initialize the mutex + errorcode = pthread_mutex_init(mutex, &attr); + assert(errorcode == 0); + + // Destroy the attributes + errorcode = pthread_mutexattr_destroy(&attr); + assert(errorcode == 0); + + // Assign the data member + data_ = mutex; +} + +// Destruct a Mutex +MutexImpl::~MutexImpl() +{ + pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_); + assert(mutex != nullptr); + pthread_mutex_destroy(mutex); + free(mutex); +} + +bool +MutexImpl::acquire() +{ + pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_); + assert(mutex != nullptr); + + int errorcode = pthread_mutex_lock(mutex); + return errorcode == 0; +} + +bool +MutexImpl::release() +{ + pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_); + assert(mutex != nullptr); + + int errorcode = pthread_mutex_unlock(mutex); + return errorcode == 0; +} + +bool +MutexImpl::tryacquire() +{ + pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_); + assert(mutex != nullptr); + + int errorcode = pthread_mutex_trylock(mutex); + return errorcode == 0; +} + +} + +#elif defined(LLVM_ON_UNIX) +#include "Unix/Mutex.inc" +#elif defined( LLVM_ON_WIN32) +#include "Windows/Mutex.inc" +#else +#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in Support/Mutex.cpp +#endif +#endif
diff --git a/third_party/llvm-subzero/lib/Support/Path.cpp b/third_party/llvm-subzero/lib/Support/Path.cpp new file mode 100644 index 0000000..f6355d1 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Path.cpp
@@ -0,0 +1,1188 @@ +//===-- Path.cpp - Implement OS Path Concept ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the operating system Path API. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/COFF.h" +#include "llvm/Support/MachO.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include <cctype> +#include <cstring> + +#if !defined(_MSC_VER) && !defined(__MINGW32__) +#include <unistd.h> +#else +#include <io.h> +#endif + +using namespace llvm; +using namespace llvm::support::endian; + +namespace { + using llvm::StringRef; + using llvm::sys::path::is_separator; + +#ifdef LLVM_ON_WIN32 + const char *separators = "\\/"; + const char preferred_separator = '\\'; +#else + const char separators = '/'; + const char preferred_separator = '/'; +#endif + + StringRef find_first_component(StringRef path) { + // Look for this first component in the following order. + // * empty (in this case we return an empty string) + // * either C: or {//,\\}net. + // * {/,\} + // * {file,directory}name + + if (path.empty()) + return path; + +#ifdef LLVM_ON_WIN32 + // C: + if (path.size() >= 2 && std::isalpha(static_cast<unsigned char>(path[0])) && + path[1] == ':') + return path.substr(0, 2); +#endif + + // //net + if ((path.size() > 2) && + is_separator(path[0]) && + path[0] == path[1] && + !is_separator(path[2])) { + // Find the next directory separator. + size_t end = path.find_first_of(separators, 2); + return path.substr(0, end); + } + + // {/,\} + if (is_separator(path[0])) + return path.substr(0, 1); + + // * {file,directory}name + size_t end = path.find_first_of(separators); + return path.substr(0, end); + } + + size_t filename_pos(StringRef str) { + if (str.size() == 2 && + is_separator(str[0]) && + str[0] == str[1]) + return 0; + + if (str.size() > 0 && is_separator(str[str.size() - 1])) + return str.size() - 1; + + size_t pos = str.find_last_of(separators, str.size() - 1); + +#ifdef LLVM_ON_WIN32 + if (pos == StringRef::npos) + pos = str.find_last_of(':', str.size() - 2); +#endif + + if (pos == StringRef::npos || + (pos == 1 && is_separator(str[0]))) + return 0; + + return pos + 1; + } + + size_t root_dir_start(StringRef str) { + // case "c:/" +#ifdef LLVM_ON_WIN32 + if (str.size() > 2 && + str[1] == ':' && + is_separator(str[2])) + return 2; +#endif + + // case "//" + if (str.size() == 2 && + is_separator(str[0]) && + str[0] == str[1]) + return StringRef::npos; + + // case "//net" + if (str.size() > 3 && + is_separator(str[0]) && + str[0] == str[1] && + !is_separator(str[2])) { + return str.find_first_of(separators, 2); + } + + // case "/" + if (str.size() > 0 && is_separator(str[0])) + return 0; + + return StringRef::npos; + } + + size_t parent_path_end(StringRef path) { + size_t end_pos = filename_pos(path); + + bool filename_was_sep = path.size() > 0 && is_separator(path[end_pos]); + + // Skip separators except for root dir. + size_t root_dir_pos = root_dir_start(path.substr(0, end_pos)); + + while(end_pos > 0 && + (end_pos - 1) != root_dir_pos && + is_separator(path[end_pos - 1])) + --end_pos; + + if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep) + return StringRef::npos; + + return end_pos; + } +} // end unnamed namespace + +enum FSEntity { + FS_Dir, + FS_File, + FS_Name +}; + +static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD, + SmallVectorImpl<char> &ResultPath, + bool MakeAbsolute, unsigned Mode, + FSEntity Type) { + SmallString<128> ModelStorage; + Model.toVector(ModelStorage); + + if (MakeAbsolute) { + // Make model absolute by prepending a temp directory if it's not already. + if (!sys::path::is_absolute(Twine(ModelStorage))) { + SmallString<128> TDir; + sys::path::system_temp_directory(true, TDir); + sys::path::append(TDir, Twine(ModelStorage)); + ModelStorage.swap(TDir); + } + } + + // From here on, DO NOT modify model. It may be needed if the randomly chosen + // path already exists. + ResultPath = ModelStorage; + // Null terminate. + ResultPath.push_back(0); + ResultPath.pop_back(); + +retry_random_path: + // Replace '%' with random chars. + for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) { + if (ModelStorage[i] == '%') + ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15]; + } + + // Try to open + create the file. + switch (Type) { + case FS_File: { + if (std::error_code EC = + sys::fs::openFileForWrite(Twine(ResultPath.begin()), ResultFD, + sys::fs::F_RW | sys::fs::F_Excl, Mode)) { + if (EC == errc::file_exists) + goto retry_random_path; + return EC; + } + + return std::error_code(); + } + + case FS_Name: { + std::error_code EC = + sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist); + if (EC == errc::no_such_file_or_directory) + return std::error_code(); + if (EC) + return EC; + goto retry_random_path; + } + + case FS_Dir: { + if (std::error_code EC = + sys::fs::create_directory(ResultPath.begin(), false)) { + if (EC == errc::file_exists) + goto retry_random_path; + return EC; + } + return std::error_code(); + } + } + llvm_unreachable("Invalid Type"); +} + +namespace llvm { +namespace sys { +namespace path { + +const_iterator begin(StringRef path) { + const_iterator i; + i.Path = path; + i.Component = find_first_component(path); + i.Position = 0; + return i; +} + +const_iterator end(StringRef path) { + const_iterator i; + i.Path = path; + i.Position = path.size(); + return i; +} + +const_iterator &const_iterator::operator++() { + assert(Position < Path.size() && "Tried to increment past end!"); + + // Increment Position to past the current component + Position += Component.size(); + + // Check for end. + if (Position == Path.size()) { + Component = StringRef(); + return *this; + } + + // Both POSIX and Windows treat paths that begin with exactly two separators + // specially. + bool was_net = Component.size() > 2 && + is_separator(Component[0]) && + Component[1] == Component[0] && + !is_separator(Component[2]); + + // Handle separators. + if (is_separator(Path[Position])) { + // Root dir. + if (was_net +#ifdef LLVM_ON_WIN32 + // c:/ + || Component.endswith(":") +#endif + ) { + Component = Path.substr(Position, 1); + return *this; + } + + // Skip extra separators. + while (Position != Path.size() && + is_separator(Path[Position])) { + ++Position; + } + + // Treat trailing '/' as a '.'. + if (Position == Path.size()) { + --Position; + Component = "."; + return *this; + } + } + + // Find next component. + size_t end_pos = Path.find_first_of(separators, Position); + Component = Path.slice(Position, end_pos); + + return *this; +} + +bool const_iterator::operator==(const const_iterator &RHS) const { + return Path.begin() == RHS.Path.begin() && Position == RHS.Position; +} + +ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const { + return Position - RHS.Position; +} + +reverse_iterator rbegin(StringRef Path) { + reverse_iterator I; + I.Path = Path; + I.Position = Path.size(); + return ++I; +} + +reverse_iterator rend(StringRef Path) { + reverse_iterator I; + I.Path = Path; + I.Component = Path.substr(0, 0); + I.Position = 0; + return I; +} + +reverse_iterator &reverse_iterator::operator++() { + // If we're at the end and the previous char was a '/', return '.' unless + // we are the root path. + size_t root_dir_pos = root_dir_start(Path); + if (Position == Path.size() && + Path.size() > root_dir_pos + 1 && + is_separator(Path[Position - 1])) { + --Position; + Component = "."; + return *this; + } + + // Skip separators unless it's the root directory. + size_t end_pos = Position; + + while(end_pos > 0 && + (end_pos - 1) != root_dir_pos && + is_separator(Path[end_pos - 1])) + --end_pos; + + // Find next separator. + size_t start_pos = filename_pos(Path.substr(0, end_pos)); + Component = Path.slice(start_pos, end_pos); + Position = start_pos; + return *this; +} + +bool reverse_iterator::operator==(const reverse_iterator &RHS) const { + return Path.begin() == RHS.Path.begin() && Component == RHS.Component && + Position == RHS.Position; +} + +ptrdiff_t reverse_iterator::operator-(const reverse_iterator &RHS) const { + return Position - RHS.Position; +} + +StringRef root_path(StringRef path) { + const_iterator b = begin(path), + pos = b, + e = end(path); + if (b != e) { + bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0]; + bool has_drive = +#ifdef LLVM_ON_WIN32 + b->endswith(":"); +#else + false; +#endif + + if (has_net || has_drive) { + if ((++pos != e) && is_separator((*pos)[0])) { + // {C:/,//net/}, so get the first two components. + return path.substr(0, b->size() + pos->size()); + } else { + // just {C:,//net}, return the first component. + return *b; + } + } + + // POSIX style root directory. + if (is_separator((*b)[0])) { + return *b; + } + } + + return StringRef(); +} + +StringRef root_name(StringRef path) { + const_iterator b = begin(path), + e = end(path); + if (b != e) { + bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0]; + bool has_drive = +#ifdef LLVM_ON_WIN32 + b->endswith(":"); +#else + false; +#endif + + if (has_net || has_drive) { + // just {C:,//net}, return the first component. + return *b; + } + } + + // No path or no name. + return StringRef(); +} + +StringRef root_directory(StringRef path) { + const_iterator b = begin(path), + pos = b, + e = end(path); + if (b != e) { + bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0]; + bool has_drive = +#ifdef LLVM_ON_WIN32 + b->endswith(":"); +#else + false; +#endif + + if ((has_net || has_drive) && + // {C:,//net}, skip to the next component. + (++pos != e) && is_separator((*pos)[0])) { + return *pos; + } + + // POSIX style root directory. + if (!has_net && is_separator((*b)[0])) { + return *b; + } + } + + // No path or no root. + return StringRef(); +} + +StringRef relative_path(StringRef path) { + StringRef root = root_path(path); + return path.substr(root.size()); +} + +void append(SmallVectorImpl<char> &path, const Twine &a, + const Twine &b, + const Twine &c, + const Twine &d) { + SmallString<32> a_storage; + SmallString<32> b_storage; + SmallString<32> c_storage; + SmallString<32> d_storage; + + SmallVector<StringRef, 4> components; + if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage)); + if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage)); + if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage)); + if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage)); + + for (auto &component : components) { + bool path_has_sep = !path.empty() && is_separator(path[path.size() - 1]); + bool component_has_sep = !component.empty() && is_separator(component[0]); + bool is_root_name = has_root_name(component); + + if (path_has_sep) { + // Strip separators from beginning of component. + size_t loc = component.find_first_not_of(separators); + StringRef c = component.substr(loc); + + // Append it. + path.append(c.begin(), c.end()); + continue; + } + + if (!component_has_sep && !(path.empty() || is_root_name)) { + // Add a separator. + path.push_back(preferred_separator); + } + + path.append(component.begin(), component.end()); + } +} + +void append(SmallVectorImpl<char> &path, + const_iterator begin, const_iterator end) { + for (; begin != end; ++begin) + path::append(path, *begin); +} + +StringRef parent_path(StringRef path) { + size_t end_pos = parent_path_end(path); + if (end_pos == StringRef::npos) + return StringRef(); + else + return path.substr(0, end_pos); +} + +void remove_filename(SmallVectorImpl<char> &path) { + size_t end_pos = parent_path_end(StringRef(path.begin(), path.size())); + if (end_pos != StringRef::npos) + path.set_size(end_pos); +} + +void replace_extension(SmallVectorImpl<char> &path, const Twine &extension) { + StringRef p(path.begin(), path.size()); + SmallString<32> ext_storage; + StringRef ext = extension.toStringRef(ext_storage); + + // Erase existing extension. + size_t pos = p.find_last_of('.'); + if (pos != StringRef::npos && pos >= filename_pos(p)) + path.set_size(pos); + + // Append '.' if needed. + if (ext.size() > 0 && ext[0] != '.') + path.push_back('.'); + + // Append extension. + path.append(ext.begin(), ext.end()); +} + +void replace_path_prefix(SmallVectorImpl<char> &Path, + const StringRef &OldPrefix, + const StringRef &NewPrefix) { + if (OldPrefix.empty() && NewPrefix.empty()) + return; + + StringRef OrigPath(Path.begin(), Path.size()); + if (!OrigPath.startswith(OldPrefix)) + return; + + // If prefixes have the same size we can simply copy the new one over. + if (OldPrefix.size() == NewPrefix.size()) { + std::copy(NewPrefix.begin(), NewPrefix.end(), Path.begin()); + return; + } + + StringRef RelPath = OrigPath.substr(OldPrefix.size()); + SmallString<256> NewPath; + path::append(NewPath, NewPrefix); + path::append(NewPath, RelPath); + Path.swap(NewPath); +} + +void native(const Twine &path, SmallVectorImpl<char> &result) { + assert((!path.isSingleStringRef() || + path.getSingleStringRef().data() != result.data()) && + "path and result are not allowed to overlap!"); + // Clear result. + result.clear(); + path.toVector(result); + native(result); +} + +void native(SmallVectorImpl<char> &Path) { +#ifdef LLVM_ON_WIN32 + std::replace(Path.begin(), Path.end(), '/', '\\'); +#else + for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) { + if (*PI == '\\') { + auto PN = PI + 1; + if (PN < PE && *PN == '\\') + ++PI; // increment once, the for loop will move over the escaped slash + else + *PI = '/'; + } + } +#endif +} + +StringRef filename(StringRef path) { + return *rbegin(path); +} + +StringRef stem(StringRef path) { + StringRef fname = filename(path); + size_t pos = fname.find_last_of('.'); + if (pos == StringRef::npos) + return fname; + else + if ((fname.size() == 1 && fname == ".") || + (fname.size() == 2 && fname == "..")) + return fname; + else + return fname.substr(0, pos); +} + +StringRef extension(StringRef path) { + StringRef fname = filename(path); + size_t pos = fname.find_last_of('.'); + if (pos == StringRef::npos) + return StringRef(); + else + if ((fname.size() == 1 && fname == ".") || + (fname.size() == 2 && fname == "..")) + return StringRef(); + else + return fname.substr(pos); +} + +bool is_separator(char value) { + switch(value) { +#ifdef LLVM_ON_WIN32 + case '\\': // fall through +#endif + case '/': return true; + default: return false; + } +} + +static const char preferred_separator_string[] = { preferred_separator, '\0' }; + +StringRef get_separator() { + return preferred_separator_string; +} + +bool has_root_name(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + return !root_name(p).empty(); +} + +bool has_root_directory(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + return !root_directory(p).empty(); +} + +bool has_root_path(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + return !root_path(p).empty(); +} + +bool has_relative_path(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + return !relative_path(p).empty(); +} + +bool has_filename(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + return !filename(p).empty(); +} + +bool has_parent_path(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + return !parent_path(p).empty(); +} + +bool has_stem(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + return !stem(p).empty(); +} + +bool has_extension(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + return !extension(p).empty(); +} + +bool is_absolute(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + bool rootDir = has_root_directory(p), +#ifdef LLVM_ON_WIN32 + rootName = has_root_name(p); +#else + rootName = true; +#endif + + return rootDir && rootName; +} + +bool is_relative(const Twine &path) { return !is_absolute(path); } + +StringRef remove_leading_dotslash(StringRef Path) { + // Remove leading "./" (or ".//" or "././" etc.) + while (Path.size() > 2 && Path[0] == '.' && is_separator(Path[1])) { + Path = Path.substr(2); + while (Path.size() > 0 && is_separator(Path[0])) + Path = Path.substr(1); + } + return Path; +} + +static SmallString<256> remove_dots(StringRef path, bool remove_dot_dot) { + SmallVector<StringRef, 16> components; + + // Skip the root path, then look for traversal in the components. + StringRef rel = path::relative_path(path); + for (StringRef C : llvm::make_range(path::begin(rel), path::end(rel))) { + if (C == ".") + continue; + if (remove_dot_dot) { + if (C == "..") { + if (!components.empty()) + components.pop_back(); + continue; + } + } + components.push_back(C); + } + + SmallString<256> buffer = path::root_path(path); + for (StringRef C : components) + path::append(buffer, C); + return buffer; +} + +bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot) { + StringRef p(path.data(), path.size()); + + SmallString<256> result = remove_dots(p, remove_dot_dot); + if (result == path) + return false; + + path.swap(result); + return true; +} + +} // end namespace path + +namespace fs { + +std::error_code getUniqueID(const Twine Path, UniqueID &Result) { + file_status Status; + std::error_code EC = status(Path, Status); + if (EC) + return EC; + Result = Status.getUniqueID(); + return std::error_code(); +} + +std::error_code createUniqueFile(const Twine &Model, int &ResultFd, + SmallVectorImpl<char> &ResultPath, + unsigned Mode) { + return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File); +} + +std::error_code createUniqueFile(const Twine &Model, + SmallVectorImpl<char> &ResultPath) { + int Dummy; + return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name); +} + +static std::error_code +createTemporaryFile(const Twine &Model, int &ResultFD, + llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) { + SmallString<128> Storage; + StringRef P = Model.toNullTerminatedStringRef(Storage); + assert(P.find_first_of(separators) == StringRef::npos && + "Model must be a simple filename."); + // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage. + return createUniqueEntity(P.begin(), ResultFD, ResultPath, + true, owner_read | owner_write, Type); +} + +static std::error_code +createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, + llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) { + const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%."; + return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath, + Type); +} + +std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, + int &ResultFD, + SmallVectorImpl<char> &ResultPath) { + return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File); +} + +std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, + SmallVectorImpl<char> &ResultPath) { + int Dummy; + return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name); +} + + +// This is a mkdtemp with a different pattern. We use createUniqueEntity mostly +// for consistency. We should try using mkdtemp. +std::error_code createUniqueDirectory(const Twine &Prefix, + SmallVectorImpl<char> &ResultPath) { + int Dummy; + return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath, + true, 0, FS_Dir); +} + +static std::error_code make_absolute(const Twine ¤t_directory, + SmallVectorImpl<char> &path, + bool use_current_directory) { + StringRef p(path.data(), path.size()); + + bool rootDirectory = path::has_root_directory(p), +#ifdef LLVM_ON_WIN32 + rootName = path::has_root_name(p); +#else + rootName = true; +#endif + + // Already absolute. + if (rootName && rootDirectory) + return std::error_code(); + + // All of the following conditions will need the current directory. + SmallString<128> current_dir; + if (use_current_directory) + current_directory.toVector(current_dir); + else if (std::error_code ec = current_path(current_dir)) + return ec; + + // Relative path. Prepend the current directory. + if (!rootName && !rootDirectory) { + // Append path to the current directory. + path::append(current_dir, p); + // Set path to the result. + path.swap(current_dir); + return std::error_code(); + } + + if (!rootName && rootDirectory) { + StringRef cdrn = path::root_name(current_dir); + SmallString<128> curDirRootName(cdrn.begin(), cdrn.end()); + path::append(curDirRootName, p); + // Set path to the result. + path.swap(curDirRootName); + return std::error_code(); + } + + if (rootName && !rootDirectory) { + StringRef pRootName = path::root_name(p); + StringRef bRootDirectory = path::root_directory(current_dir); + StringRef bRelativePath = path::relative_path(current_dir); + StringRef pRelativePath = path::relative_path(p); + + SmallString<128> res; + path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath); + path.swap(res); + return std::error_code(); + } + + llvm_unreachable("All rootName and rootDirectory combinations should have " + "occurred above!"); +} + +std::error_code make_absolute(const Twine ¤t_directory, + SmallVectorImpl<char> &path) { + return make_absolute(current_directory, path, true); +} + +std::error_code make_absolute(SmallVectorImpl<char> &path) { + return make_absolute(Twine(), path, false); +} + +std::error_code create_directories(const Twine &Path, bool IgnoreExisting, + perms Perms) { + SmallString<128> PathStorage; + StringRef P = Path.toStringRef(PathStorage); + + // Be optimistic and try to create the directory + std::error_code EC = create_directory(P, IgnoreExisting, Perms); + // If we succeeded, or had any error other than the parent not existing, just + // return it. + if (EC != errc::no_such_file_or_directory) + return EC; + + // We failed because of a no_such_file_or_directory, try to create the + // parent. + StringRef Parent = path::parent_path(P); + if (Parent.empty()) + return EC; + + if ((EC = create_directories(Parent, IgnoreExisting, Perms))) + return EC; + + return create_directory(P, IgnoreExisting, Perms); +} + +std::error_code copy_file(const Twine &From, const Twine &To) { + int ReadFD, WriteFD; + if (std::error_code EC = openFileForRead(From, ReadFD)) + return EC; + if (std::error_code EC = openFileForWrite(To, WriteFD, F_None)) { + close(ReadFD); + return EC; + } + + const size_t BufSize = 4096; + char *Buf = new char[BufSize]; + int BytesRead = 0, BytesWritten = 0; + for (;;) { + BytesRead = read(ReadFD, Buf, BufSize); + if (BytesRead <= 0) + break; + while (BytesRead) { + BytesWritten = write(WriteFD, Buf, BytesRead); + if (BytesWritten < 0) + break; + BytesRead -= BytesWritten; + } + if (BytesWritten < 0) + break; + } + close(ReadFD); + close(WriteFD); + delete[] Buf; + + if (BytesRead < 0 || BytesWritten < 0) + return std::error_code(errno, std::generic_category()); + return std::error_code(); +} + +bool exists(file_status status) { + return status_known(status) && status.type() != file_type::file_not_found; +} + +bool status_known(file_status s) { + return s.type() != file_type::status_error; +} + +bool is_directory(file_status status) { + return status.type() == file_type::directory_file; +} + +std::error_code is_directory(const Twine &path, bool &result) { + file_status st; + if (std::error_code ec = status(path, st)) + return ec; + result = is_directory(st); + return std::error_code(); +} + +bool is_regular_file(file_status status) { + return status.type() == file_type::regular_file; +} + +std::error_code is_regular_file(const Twine &path, bool &result) { + file_status st; + if (std::error_code ec = status(path, st)) + return ec; + result = is_regular_file(st); + return std::error_code(); +} + +bool is_other(file_status status) { + return exists(status) && + !is_regular_file(status) && + !is_directory(status); +} + +std::error_code is_other(const Twine &Path, bool &Result) { + file_status FileStatus; + if (std::error_code EC = status(Path, FileStatus)) + return EC; + Result = is_other(FileStatus); + return std::error_code(); +} + +void directory_entry::replace_filename(const Twine &filename, file_status st) { + SmallString<128> path = path::parent_path(Path); + path::append(path, filename); + Path = path.str(); + Status = st; +} + +/// @brief Identify the magic in magic. +file_magic identify_magic(StringRef Magic) { + if (Magic.size() < 4) + return file_magic::unknown; + switch ((unsigned char)Magic[0]) { + case 0x00: { + // COFF bigobj or short import library file + if (Magic[1] == (char)0x00 && Magic[2] == (char)0xff && + Magic[3] == (char)0xff) { + size_t MinSize = offsetof(COFF::BigObjHeader, UUID) + sizeof(COFF::BigObjMagic); + if (Magic.size() < MinSize) + return file_magic::coff_import_library; + + int BigObjVersion = read16le( + Magic.data() + offsetof(COFF::BigObjHeader, Version)); + if (BigObjVersion < COFF::BigObjHeader::MinBigObjectVersion) + return file_magic::coff_import_library; + + const char *Start = Magic.data() + offsetof(COFF::BigObjHeader, UUID); + if (memcmp(Start, COFF::BigObjMagic, sizeof(COFF::BigObjMagic)) != 0) + return file_magic::coff_import_library; + return file_magic::coff_object; + } + // Windows resource file + const char Expected[] = { 0, 0, 0, 0, '\x20', 0, 0, 0, '\xff' }; + if (Magic.size() >= sizeof(Expected) && + memcmp(Magic.data(), Expected, sizeof(Expected)) == 0) + return file_magic::windows_resource; + // 0x0000 = COFF unknown machine type + if (Magic[1] == 0) + return file_magic::coff_object; + break; + } + case 0xDE: // 0x0B17C0DE = BC wraper + if (Magic[1] == (char)0xC0 && Magic[2] == (char)0x17 && + Magic[3] == (char)0x0B) + return file_magic::bitcode; + break; + case 'B': + if (Magic[1] == 'C' && Magic[2] == (char)0xC0 && Magic[3] == (char)0xDE) + return file_magic::bitcode; + break; + case '!': + if (Magic.size() >= 8) + if (memcmp(Magic.data(), "!<arch>\n", 8) == 0 || + memcmp(Magic.data(), "!<thin>\n", 8) == 0) + return file_magic::archive; + break; + + case '\177': + if (Magic.size() >= 18 && Magic[1] == 'E' && Magic[2] == 'L' && + Magic[3] == 'F') { + bool Data2MSB = Magic[5] == 2; + unsigned high = Data2MSB ? 16 : 17; + unsigned low = Data2MSB ? 17 : 16; + if (Magic[high] == 0) + switch (Magic[low]) { + default: return file_magic::elf; + case 1: return file_magic::elf_relocatable; + case 2: return file_magic::elf_executable; + case 3: return file_magic::elf_shared_object; + case 4: return file_magic::elf_core; + } + else + // It's still some type of ELF file. + return file_magic::elf; + } + break; + + case 0xCA: + if (Magic[1] == char(0xFE) && Magic[2] == char(0xBA) && + (Magic[3] == char(0xBE) || Magic[3] == char(0xBF))) { + // This is complicated by an overlap with Java class files. + // See the Mach-O section in /usr/share/file/magic for details. + if (Magic.size() >= 8 && Magic[7] < 43) + return file_magic::macho_universal_binary; + } + break; + + // The two magic numbers for mach-o are: + // 0xfeedface - 32-bit mach-o + // 0xfeedfacf - 64-bit mach-o + case 0xFE: + case 0xCE: + case 0xCF: { + uint16_t type = 0; + if (Magic[0] == char(0xFE) && Magic[1] == char(0xED) && + Magic[2] == char(0xFA) && + (Magic[3] == char(0xCE) || Magic[3] == char(0xCF))) { + /* Native endian */ + size_t MinSize; + if (Magic[3] == char(0xCE)) + MinSize = sizeof(MachO::mach_header); + else + MinSize = sizeof(MachO::mach_header_64); + if (Magic.size() >= MinSize) + type = Magic[12] << 24 | Magic[13] << 12 | Magic[14] << 8 | Magic[15]; + } else if ((Magic[0] == char(0xCE) || Magic[0] == char(0xCF)) && + Magic[1] == char(0xFA) && Magic[2] == char(0xED) && + Magic[3] == char(0xFE)) { + /* Reverse endian */ + size_t MinSize; + if (Magic[0] == char(0xCE)) + MinSize = sizeof(MachO::mach_header); + else + MinSize = sizeof(MachO::mach_header_64); + if (Magic.size() >= MinSize) + type = Magic[15] << 24 | Magic[14] << 12 |Magic[13] << 8 | Magic[12]; + } + switch (type) { + default: break; + case 1: return file_magic::macho_object; + case 2: return file_magic::macho_executable; + case 3: return file_magic::macho_fixed_virtual_memory_shared_lib; + case 4: return file_magic::macho_core; + case 5: return file_magic::macho_preload_executable; + case 6: return file_magic::macho_dynamically_linked_shared_lib; + case 7: return file_magic::macho_dynamic_linker; + case 8: return file_magic::macho_bundle; + case 9: return file_magic::macho_dynamically_linked_shared_lib_stub; + case 10: return file_magic::macho_dsym_companion; + case 11: return file_magic::macho_kext_bundle; + } + break; + } + case 0xF0: // PowerPC Windows + case 0x83: // Alpha 32-bit + case 0x84: // Alpha 64-bit + case 0x66: // MPS R4000 Windows + case 0x50: // mc68K + case 0x4c: // 80386 Windows + case 0xc4: // ARMNT Windows + if (Magic[1] == 0x01) + return file_magic::coff_object; + + case 0x90: // PA-RISC Windows + case 0x68: // mc68K Windows + if (Magic[1] == 0x02) + return file_magic::coff_object; + break; + + case 'M': // Possible MS-DOS stub on Windows PE file + if (Magic[1] == 'Z') { + uint32_t off = read32le(Magic.data() + 0x3c); + // PE/COFF file, either EXE or DLL. + if (off < Magic.size() && + memcmp(Magic.data()+off, COFF::PEMagic, sizeof(COFF::PEMagic)) == 0) + return file_magic::pecoff_executable; + } + break; + + case 0x64: // x86-64 Windows. + if (Magic[1] == char(0x86)) + return file_magic::coff_object; + break; + + default: + break; + } + return file_magic::unknown; +} + +std::error_code identify_magic(const Twine &Path, file_magic &Result) { + int FD; + if (std::error_code EC = openFileForRead(Path, FD)) + return EC; + + char Buffer[32]; + int Length = read(FD, Buffer, sizeof(Buffer)); + if (close(FD) != 0 || Length < 0) + return std::error_code(errno, std::generic_category()); + + Result = identify_magic(StringRef(Buffer, Length)); + return std::error_code(); +} + +std::error_code directory_entry::status(file_status &result) const { + return fs::status(Path, result); +} + +} // end namespace fs +} // end namespace sys +} // end namespace llvm + +// Include the truly platform-specific parts. +#if defined(LLVM_ON_UNIX) +#include "Unix/Path.inc" +#endif +#if defined(LLVM_ON_WIN32) +#include "Windows/Path.inc" +#endif + +namespace llvm { +namespace sys { +namespace path { + +bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1, + const Twine &Path2, const Twine &Path3) { + if (getUserCacheDir(Result)) { + append(Result, Path1, Path2, Path3); + return true; + } + return false; +} + +} // end namespace path +} // end namsspace sys +} // end namespace llvm
diff --git a/third_party/llvm-subzero/lib/Support/Process.cpp b/third_party/llvm-subzero/lib/Support/Process.cpp new file mode 100644 index 0000000..290c30f --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Process.cpp
@@ -0,0 +1,89 @@ +//===-- Process.cpp - Implement OS Process Concept --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the operating system Process concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringExtras.h" +#include "llvm/Config/config.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" + +using namespace llvm; +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +Optional<std::string> Process::FindInEnvPath(const std::string& EnvName, + const std::string& FileName) +{ + assert(!path::is_absolute(FileName)); + Optional<std::string> FoundPath; + Optional<std::string> OptPath = Process::GetEnv(EnvName); + if (!OptPath.hasValue()) + return FoundPath; + + const char EnvPathSeparatorStr[] = {EnvPathSeparator, '\0'}; + SmallVector<StringRef, 8> Dirs; + SplitString(OptPath.getValue(), Dirs, EnvPathSeparatorStr); + + for (const auto &Dir : Dirs) { + if (Dir.empty()) + continue; + + SmallString<128> FilePath(Dir); + path::append(FilePath, FileName); + if (fs::exists(Twine(FilePath))) { + FoundPath = FilePath.str(); + break; + } + } + + return FoundPath; +} + + +#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m" + +#define ALLCOLORS(FGBG,BOLD) {\ + COLOR(FGBG, "0", BOLD),\ + COLOR(FGBG, "1", BOLD),\ + COLOR(FGBG, "2", BOLD),\ + COLOR(FGBG, "3", BOLD),\ + COLOR(FGBG, "4", BOLD),\ + COLOR(FGBG, "5", BOLD),\ + COLOR(FGBG, "6", BOLD),\ + COLOR(FGBG, "7", BOLD)\ + } + +static const char colorcodes[2][2][8][10] = { + { ALLCOLORS("3",""), ALLCOLORS("3","1;") }, + { ALLCOLORS("4",""), ALLCOLORS("4","1;") } +}; + +// This is set to true when Process::PreventCoreFiles() is called. +static bool coreFilesPrevented = false; + +bool Process::AreCoreFilesPrevented() { + return coreFilesPrevented; +} + +// Include the platform-specific parts of this class. +#ifdef LLVM_ON_UNIX +#include "Unix/Process.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Windows/Process.inc" +#endif
diff --git a/third_party/llvm-subzero/lib/Support/Program.cpp b/third_party/llvm-subzero/lib/Support/Program.cpp new file mode 100644 index 0000000..34e336b --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Program.cpp
@@ -0,0 +1,69 @@ +//===-- Program.cpp - Implement OS Program Concept --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the operating system Program concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Program.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Config/config.h" +#include <system_error> +using namespace llvm; +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +static bool Execute(ProcessInfo &PI, StringRef Program, const char **args, + const char **env, const StringRef **Redirects, + unsigned memoryLimit, std::string *ErrMsg); + +int sys::ExecuteAndWait(StringRef Program, const char **args, const char **envp, + const StringRef **redirects, unsigned secondsToWait, + unsigned memoryLimit, std::string *ErrMsg, + bool *ExecutionFailed) { + ProcessInfo PI; + if (Execute(PI, Program, args, envp, redirects, memoryLimit, ErrMsg)) { + if (ExecutionFailed) + *ExecutionFailed = false; + ProcessInfo Result = Wait( + PI, secondsToWait, /*WaitUntilTerminates=*/secondsToWait == 0, ErrMsg); + return Result.ReturnCode; + } + + if (ExecutionFailed) + *ExecutionFailed = true; + + return -1; +} + +ProcessInfo sys::ExecuteNoWait(StringRef Program, const char **args, + const char **envp, const StringRef **redirects, + unsigned memoryLimit, std::string *ErrMsg, + bool *ExecutionFailed) { + ProcessInfo PI; + if (ExecutionFailed) + *ExecutionFailed = false; + if (!Execute(PI, Program, args, envp, redirects, memoryLimit, ErrMsg)) + if (ExecutionFailed) + *ExecutionFailed = true; + + return PI; +} + +// Include the platform-specific parts of this class. +#ifdef LLVM_ON_UNIX +#include "Unix/Program.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Windows/Program.inc" +#endif
diff --git a/third_party/llvm-subzero/lib/Support/Signals.cpp b/third_party/llvm-subzero/lib/Support/Signals.cpp new file mode 100644 index 0000000..e5e38f5 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Signals.cpp
@@ -0,0 +1,184 @@ +//===- Signals.cpp - Signal Handling support --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines some helpful functions for dealing with the possibility of +// Unix signals occurring while your program is running. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Config/config.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/StringSaver.h" +#include "llvm/Support/raw_ostream.h" +#include <vector> + +namespace llvm { +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +static ManagedStatic<std::vector<std::pair<void (*)(void *), void *>>> + CallBacksToRun; +void sys::RunSignalHandlers() { + if (!CallBacksToRun.isConstructed()) + return; + for (auto &I : *CallBacksToRun) + I.first(I.second); + CallBacksToRun->clear(); +} +} + +using namespace llvm; + +static bool findModulesAndOffsets(void **StackTrace, int Depth, + const char **Modules, intptr_t *Offsets, + const char *MainExecutableName, + StringSaver &StrPool); + +/// Format a pointer value as hexadecimal. Zero pad it out so its always the +/// same width. +static FormattedNumber format_ptr(void *PC) { + // Each byte is two hex digits plus 2 for the 0x prefix. + unsigned PtrWidth = 2 + 2 * sizeof(void *); + return format_hex((uint64_t)PC, PtrWidth); +} + +static bool printSymbolizedStackTrace(StringRef Argv0, + void **StackTrace, int Depth, + llvm::raw_ostream &OS) + LLVM_ATTRIBUTE_USED; + +/// Helper that launches llvm-symbolizer and symbolizes a backtrace. +static bool printSymbolizedStackTrace(StringRef Argv0, + void **StackTrace, int Depth, + llvm::raw_ostream &OS) { + // Don't recursively invoke the llvm-symbolizer binary. + if (Argv0.find("llvm-symbolizer") != std::string::npos) + return false; + + // FIXME: Subtract necessary number from StackTrace entries to turn return addresses + // into actual instruction addresses. + // Use llvm-symbolizer tool to symbolize the stack traces. First look for it + // alongside our binary, then in $PATH. + ErrorOr<std::string> LLVMSymbolizerPathOrErr = std::error_code(); + if (!Argv0.empty()) { + StringRef Parent = llvm::sys::path::parent_path(Argv0); + if (!Parent.empty()) + LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer", Parent); + } + if (!LLVMSymbolizerPathOrErr) + LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer"); + if (!LLVMSymbolizerPathOrErr) + return false; + const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr; + + // If we don't know argv0 or the address of main() at this point, try + // to guess it anyway (it's possible on some platforms). + std::string MainExecutableName = + Argv0.empty() ? sys::fs::getMainExecutable(nullptr, nullptr) + : (std::string)Argv0; + BumpPtrAllocator Allocator; + StringSaver StrPool(Allocator); + std::vector<const char *> Modules(Depth, nullptr); + std::vector<intptr_t> Offsets(Depth, 0); + if (!findModulesAndOffsets(StackTrace, Depth, Modules.data(), Offsets.data(), + MainExecutableName.c_str(), StrPool)) + return false; + int InputFD; + SmallString<32> InputFile, OutputFile; + sys::fs::createTemporaryFile("symbolizer-input", "", InputFD, InputFile); + sys::fs::createTemporaryFile("symbolizer-output", "", OutputFile); + FileRemover InputRemover(InputFile.c_str()); + FileRemover OutputRemover(OutputFile.c_str()); + + { + raw_fd_ostream Input(InputFD, true); + for (int i = 0; i < Depth; i++) { + if (Modules[i]) + Input << Modules[i] << " " << (void*)Offsets[i] << "\n"; + } + } + + StringRef InputFileStr(InputFile); + StringRef OutputFileStr(OutputFile); + StringRef StderrFileStr; + const StringRef *Redirects[] = {&InputFileStr, &OutputFileStr, + &StderrFileStr}; + const char *Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining", +#ifdef LLVM_ON_WIN32 + // Pass --relative-address on Windows so that we don't + // have to add ImageBase from PE file. + // FIXME: Make this the default for llvm-symbolizer. + "--relative-address", +#endif + "--demangle", nullptr}; + int RunResult = + sys::ExecuteAndWait(LLVMSymbolizerPath, Args, nullptr, Redirects); + if (RunResult != 0) + return false; + + // This report format is based on the sanitizer stack trace printer. See + // sanitizer_stacktrace_printer.cc in compiler-rt. + auto OutputBuf = MemoryBuffer::getFile(OutputFile.c_str()); + if (!OutputBuf) + return false; + StringRef Output = OutputBuf.get()->getBuffer(); + SmallVector<StringRef, 32> Lines; + Output.split(Lines, "\n"); + auto CurLine = Lines.begin(); + int frame_no = 0; + for (int i = 0; i < Depth; i++) { + if (!Modules[i]) { + OS << '#' << frame_no++ << ' ' << format_ptr(StackTrace[i]) << '\n'; + continue; + } + // Read pairs of lines (function name and file/line info) until we + // encounter empty line. + for (;;) { + if (CurLine == Lines.end()) + return false; + StringRef FunctionName = *CurLine++; + if (FunctionName.empty()) + break; + OS << '#' << frame_no++ << ' ' << format_ptr(StackTrace[i]) << ' '; + if (!FunctionName.startswith("??")) + OS << FunctionName << ' '; + if (CurLine == Lines.end()) + return false; + StringRef FileLineInfo = *CurLine++; + if (!FileLineInfo.startswith("??")) + OS << FileLineInfo; + else + OS << "(" << Modules[i] << '+' << format_hex(Offsets[i], 0) << ")"; + OS << "\n"; + } + } + return true; +} + +// Include the platform-specific parts of this class. +#ifdef LLVM_ON_UNIX +#include "Unix/Signals.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Windows/Signals.inc" +#endif
diff --git a/third_party/llvm-subzero/lib/Support/SmallPtrSet.cpp b/third_party/llvm-subzero/lib/Support/SmallPtrSet.cpp new file mode 100644 index 0000000..8fb12ba --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/SmallPtrSet.cpp
@@ -0,0 +1,296 @@ +//===- llvm/ADT/SmallPtrSet.cpp - 'Normally small' pointer set ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SmallPtrSet class. See SmallPtrSet.h for an +// overview of the algorithm. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/Support/MathExtras.h" +#include <algorithm> +#include <cassert> +#include <cstdlib> + +using namespace llvm; + +void SmallPtrSetImplBase::shrink_and_clear() { + assert(!isSmall() && "Can't shrink a small set!"); + free(CurArray); + + // Reduce the number of buckets. + unsigned Size = size(); + CurArraySize = Size > 16 ? 1 << (Log2_32_Ceil(Size) + 1) : 32; + NumNonEmpty = NumTombstones = 0; + + // Install the new array. Clear all the buckets to empty. + CurArray = (const void**)malloc(sizeof(void*) * CurArraySize); + assert(CurArray && "Failed to allocate memory?"); + memset(CurArray, -1, CurArraySize*sizeof(void*)); +} + +std::pair<const void *const *, bool> +SmallPtrSetImplBase::insert_imp_big(const void *Ptr) { + if (LLVM_UNLIKELY(size() * 4 >= CurArraySize * 3)) { + // If more than 3/4 of the array is full, grow. + Grow(CurArraySize < 64 ? 128 : CurArraySize * 2); + } else if (LLVM_UNLIKELY(CurArraySize - NumNonEmpty < CurArraySize / 8)) { + // If fewer of 1/8 of the array is empty (meaning that many are filled with + // tombstones), rehash. + Grow(CurArraySize); + } + + // Okay, we know we have space. Find a hash bucket. + const void **Bucket = const_cast<const void**>(FindBucketFor(Ptr)); + if (*Bucket == Ptr) + return std::make_pair(Bucket, false); // Already inserted, good. + + // Otherwise, insert it! + if (*Bucket == getTombstoneMarker()) + --NumTombstones; + else + ++NumNonEmpty; // Track density. + *Bucket = Ptr; + return std::make_pair(Bucket, true); +} + +bool SmallPtrSetImplBase::erase_imp(const void * Ptr) { + if (isSmall()) { + // Check to see if it is in the set. + for (const void **APtr = CurArray, **E = CurArray + NumNonEmpty; APtr != E; + ++APtr) + if (*APtr == Ptr) { + // If it is in the set, replace this element. + *APtr = getTombstoneMarker(); + ++NumTombstones; + return true; + } + + return false; + } + + // Okay, we know we have space. Find a hash bucket. + void **Bucket = const_cast<void**>(FindBucketFor(Ptr)); + if (*Bucket != Ptr) return false; // Not in the set? + + // Set this as a tombstone. + *Bucket = getTombstoneMarker(); + ++NumTombstones; + return true; +} + +const void * const *SmallPtrSetImplBase::FindBucketFor(const void *Ptr) const { + unsigned Bucket = DenseMapInfo<void *>::getHashValue(Ptr) & (CurArraySize-1); + unsigned ArraySize = CurArraySize; + unsigned ProbeAmt = 1; + const void *const *Array = CurArray; + const void *const *Tombstone = nullptr; + while (true) { + // If we found an empty bucket, the pointer doesn't exist in the set. + // Return a tombstone if we've seen one so far, or the empty bucket if + // not. + if (LLVM_LIKELY(Array[Bucket] == getEmptyMarker())) + return Tombstone ? Tombstone : Array+Bucket; + + // Found Ptr's bucket? + if (LLVM_LIKELY(Array[Bucket] == Ptr)) + return Array+Bucket; + + // If this is a tombstone, remember it. If Ptr ends up not in the set, we + // prefer to return it than something that would require more probing. + if (Array[Bucket] == getTombstoneMarker() && !Tombstone) + Tombstone = Array+Bucket; // Remember the first tombstone found. + + // It's a hash collision or a tombstone. Reprobe. + Bucket = (Bucket + ProbeAmt++) & (ArraySize-1); + } +} + +/// Grow - Allocate a larger backing store for the buckets and move it over. +/// +void SmallPtrSetImplBase::Grow(unsigned NewSize) { + const void **OldBuckets = CurArray; + const void **OldEnd = EndPointer(); + bool WasSmall = isSmall(); + + // Install the new array. Clear all the buckets to empty. + CurArray = (const void**)malloc(sizeof(void*) * NewSize); + assert(CurArray && "Failed to allocate memory?"); + CurArraySize = NewSize; + memset(CurArray, -1, NewSize*sizeof(void*)); + + // Copy over all valid entries. + for (const void **BucketPtr = OldBuckets; BucketPtr != OldEnd; ++BucketPtr) { + // Copy over the element if it is valid. + const void *Elt = *BucketPtr; + if (Elt != getTombstoneMarker() && Elt != getEmptyMarker()) + *const_cast<void**>(FindBucketFor(Elt)) = const_cast<void*>(Elt); + } + + if (!WasSmall) + free(OldBuckets); + NumNonEmpty -= NumTombstones; + NumTombstones = 0; +} + +SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage, + const SmallPtrSetImplBase &that) { + SmallArray = SmallStorage; + + // If we're becoming small, prepare to insert into our stack space + if (that.isSmall()) { + CurArray = SmallArray; + // Otherwise, allocate new heap space (unless we were the same size) + } else { + CurArray = (const void**)malloc(sizeof(void*) * that.CurArraySize); + assert(CurArray && "Failed to allocate memory?"); + } + + // Copy over the that array. + CopyHelper(that); +} + +SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage, + unsigned SmallSize, + SmallPtrSetImplBase &&that) { + SmallArray = SmallStorage; + MoveHelper(SmallSize, std::move(that)); +} + +void SmallPtrSetImplBase::CopyFrom(const SmallPtrSetImplBase &RHS) { + assert(&RHS != this && "Self-copy should be handled by the caller."); + + if (isSmall() && RHS.isSmall()) + assert(CurArraySize == RHS.CurArraySize && + "Cannot assign sets with different small sizes"); + + // If we're becoming small, prepare to insert into our stack space + if (RHS.isSmall()) { + if (!isSmall()) + free(CurArray); + CurArray = SmallArray; + // Otherwise, allocate new heap space (unless we were the same size) + } else if (CurArraySize != RHS.CurArraySize) { + if (isSmall()) + CurArray = (const void**)malloc(sizeof(void*) * RHS.CurArraySize); + else { + const void **T = (const void**)realloc(CurArray, + sizeof(void*) * RHS.CurArraySize); + if (!T) + free(CurArray); + CurArray = T; + } + assert(CurArray && "Failed to allocate memory?"); + } + + CopyHelper(RHS); +} + +void SmallPtrSetImplBase::CopyHelper(const SmallPtrSetImplBase &RHS) { + // Copy over the new array size + CurArraySize = RHS.CurArraySize; + + // Copy over the contents from the other set + std::copy(RHS.CurArray, RHS.EndPointer(), CurArray); + + NumNonEmpty = RHS.NumNonEmpty; + NumTombstones = RHS.NumTombstones; +} + +void SmallPtrSetImplBase::MoveFrom(unsigned SmallSize, + SmallPtrSetImplBase &&RHS) { + if (!isSmall()) + free(CurArray); + MoveHelper(SmallSize, std::move(RHS)); +} + +void SmallPtrSetImplBase::MoveHelper(unsigned SmallSize, + SmallPtrSetImplBase &&RHS) { + assert(&RHS != this && "Self-move should be handled by the caller."); + + if (RHS.isSmall()) { + // Copy a small RHS rather than moving. + CurArray = SmallArray; + std::copy(RHS.CurArray, RHS.CurArray + RHS.NumNonEmpty, CurArray); + } else { + CurArray = RHS.CurArray; + RHS.CurArray = RHS.SmallArray; + } + + // Copy the rest of the trivial members. + CurArraySize = RHS.CurArraySize; + NumNonEmpty = RHS.NumNonEmpty; + NumTombstones = RHS.NumTombstones; + + // Make the RHS small and empty. + RHS.CurArraySize = SmallSize; + assert(RHS.CurArray == RHS.SmallArray); + RHS.NumNonEmpty = 0; + RHS.NumTombstones = 0; +} + +void SmallPtrSetImplBase::swap(SmallPtrSetImplBase &RHS) { + if (this == &RHS) return; + + // We can only avoid copying elements if neither set is small. + if (!this->isSmall() && !RHS.isSmall()) { + std::swap(this->CurArray, RHS.CurArray); + std::swap(this->CurArraySize, RHS.CurArraySize); + std::swap(this->NumNonEmpty, RHS.NumNonEmpty); + std::swap(this->NumTombstones, RHS.NumTombstones); + return; + } + + // FIXME: From here on we assume that both sets have the same small size. + + // If only RHS is small, copy the small elements into LHS and move the pointer + // from LHS to RHS. + if (!this->isSmall() && RHS.isSmall()) { + assert(RHS.CurArray == RHS.SmallArray); + std::copy(RHS.CurArray, RHS.CurArray + RHS.NumNonEmpty, this->SmallArray); + std::swap(RHS.CurArraySize, this->CurArraySize); + std::swap(this->NumNonEmpty, RHS.NumNonEmpty); + std::swap(this->NumTombstones, RHS.NumTombstones); + RHS.CurArray = this->CurArray; + this->CurArray = this->SmallArray; + return; + } + + // If only LHS is small, copy the small elements into RHS and move the pointer + // from RHS to LHS. + if (this->isSmall() && !RHS.isSmall()) { + assert(this->CurArray == this->SmallArray); + std::copy(this->CurArray, this->CurArray + this->NumNonEmpty, + RHS.SmallArray); + std::swap(RHS.CurArraySize, this->CurArraySize); + std::swap(RHS.NumNonEmpty, this->NumNonEmpty); + std::swap(RHS.NumTombstones, this->NumTombstones); + this->CurArray = RHS.CurArray; + RHS.CurArray = RHS.SmallArray; + return; + } + + // Both a small, just swap the small elements. + assert(this->isSmall() && RHS.isSmall()); + unsigned MinNonEmpty = std::min(this->NumNonEmpty, RHS.NumNonEmpty); + std::swap_ranges(this->SmallArray, this->SmallArray + MinNonEmpty, + RHS.SmallArray); + if (this->NumNonEmpty > MinNonEmpty) { + std::copy(this->SmallArray + MinNonEmpty, + this->SmallArray + this->NumNonEmpty, + RHS.SmallArray + MinNonEmpty); + } else { + std::copy(RHS.SmallArray + MinNonEmpty, RHS.SmallArray + RHS.NumNonEmpty, + this->SmallArray + MinNonEmpty); + } + assert(this->CurArraySize == RHS.CurArraySize); + std::swap(this->NumNonEmpty, RHS.NumNonEmpty); + std::swap(this->NumTombstones, RHS.NumTombstones); +}
diff --git a/third_party/llvm-subzero/lib/Support/SmallVector.cpp b/third_party/llvm-subzero/lib/Support/SmallVector.cpp new file mode 100644 index 0000000..b931505 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/SmallVector.cpp
@@ -0,0 +1,41 @@ +//===- llvm/ADT/SmallVector.cpp - 'Normally small' vectors ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SmallVector class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +using namespace llvm; + +/// grow_pod - This is an implementation of the grow() method which only works +/// on POD-like datatypes and is out of line to reduce code duplication. +void SmallVectorBase::grow_pod(void *FirstEl, size_t MinSizeInBytes, + size_t TSize) { + size_t CurSizeBytes = size_in_bytes(); + size_t NewCapacityInBytes = 2 * capacity_in_bytes() + TSize; // Always grow. + if (NewCapacityInBytes < MinSizeInBytes) + NewCapacityInBytes = MinSizeInBytes; + + void *NewElts; + if (BeginX == FirstEl) { + NewElts = malloc(NewCapacityInBytes); + + // Copy the elements over. No need to run dtors on PODs. + memcpy(NewElts, this->BeginX, CurSizeBytes); + } else { + // If this wasn't grown from the inline copy, grow the allocated space. + NewElts = realloc(this->BeginX, NewCapacityInBytes); + } + assert(NewElts && "Out of memory"); + + this->EndX = (char*)NewElts+CurSizeBytes; + this->BeginX = NewElts; + this->CapacityX = (char*)this->BeginX + NewCapacityInBytes; +}
diff --git a/third_party/llvm-subzero/lib/Support/StringExtras.cpp b/third_party/llvm-subzero/lib/Support/StringExtras.cpp new file mode 100644 index 0000000..3e2420f --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/StringExtras.cpp
@@ -0,0 +1,58 @@ +//===-- StringExtras.cpp - Implement the StringExtras header --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the StringExtras.h header +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +using namespace llvm; + +/// StrInStrNoCase - Portable version of strcasestr. Locates the first +/// occurrence of string 's1' in string 's2', ignoring case. Returns +/// the offset of s2 in s1 or npos if s2 cannot be found. +StringRef::size_type llvm::StrInStrNoCase(StringRef s1, StringRef s2) { + size_t N = s2.size(), M = s1.size(); + if (N > M) + return StringRef::npos; + for (size_t i = 0, e = M - N + 1; i != e; ++i) + if (s1.substr(i, N).equals_lower(s2)) + return i; + return StringRef::npos; +} + +/// getToken - This function extracts one token from source, ignoring any +/// leading characters that appear in the Delimiters string, and ending the +/// token at any of the characters that appear in the Delimiters string. If +/// there are no tokens in the source string, an empty string is returned. +/// The function returns a pair containing the extracted token and the +/// remaining tail string. +std::pair<StringRef, StringRef> llvm::getToken(StringRef Source, + StringRef Delimiters) { + // Figure out where the token starts. + StringRef::size_type Start = Source.find_first_not_of(Delimiters); + + // Find the next occurrence of the delimiter. + StringRef::size_type End = Source.find_first_of(Delimiters, Start); + + return std::make_pair(Source.slice(Start, End), Source.substr(End)); +} + +/// SplitString - Split up the specified string according to the specified +/// delimiters, appending the result fragments to the output list. +void llvm::SplitString(StringRef Source, + SmallVectorImpl<StringRef> &OutFragments, + StringRef Delimiters) { + std::pair<StringRef, StringRef> S = getToken(Source, Delimiters); + while (!S.first.empty()) { + OutFragments.push_back(S.first); + S = getToken(S.second, Delimiters); + } +}
diff --git a/third_party/llvm-subzero/lib/Support/StringMap.cpp b/third_party/llvm-subzero/lib/Support/StringMap.cpp new file mode 100644 index 0000000..d231596 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/StringMap.cpp
@@ -0,0 +1,257 @@ +//===--- StringMap.cpp - String Hash table map implementation -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the StringMap class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/MathExtras.h" +#include <cassert> + +using namespace llvm; + +/// Returns the number of buckets to allocate to ensure that the DenseMap can +/// accommodate \p NumEntries without need to grow(). +static unsigned getMinBucketToReserveForEntries(unsigned NumEntries) { + // Ensure that "NumEntries * 4 < NumBuckets * 3" + if (NumEntries == 0) + return 0; + // +1 is required because of the strict equality. + // For example if NumEntries is 48, we need to return 401. + return NextPowerOf2(NumEntries * 4 / 3 + 1); +} + +StringMapImpl::StringMapImpl(unsigned InitSize, unsigned itemSize) { + ItemSize = itemSize; + + // If a size is specified, initialize the table with that many buckets. + if (InitSize) { + // The table will grow when the number of entries reach 3/4 of the number of + // buckets. To guarantee that "InitSize" number of entries can be inserted + // in the table without growing, we allocate just what is needed here. + init(getMinBucketToReserveForEntries(InitSize)); + return; + } + + // Otherwise, initialize it with zero buckets to avoid the allocation. + TheTable = nullptr; + NumBuckets = 0; + NumItems = 0; + NumTombstones = 0; +} + +void StringMapImpl::init(unsigned InitSize) { + assert((InitSize & (InitSize-1)) == 0 && + "Init Size must be a power of 2 or zero!"); + NumBuckets = InitSize ? InitSize : 16; + NumItems = 0; + NumTombstones = 0; + + TheTable = (StringMapEntryBase **)calloc(NumBuckets+1, + sizeof(StringMapEntryBase **) + + sizeof(unsigned)); + + // Allocate one extra bucket, set it to look filled so the iterators stop at + // end. + TheTable[NumBuckets] = (StringMapEntryBase*)2; +} + +/// LookupBucketFor - Look up the bucket that the specified string should end +/// up in. If it already exists as a key in the map, the Item pointer for the +/// specified bucket will be non-null. Otherwise, it will be null. In either +/// case, the FullHashValue field of the bucket will be set to the hash value +/// of the string. +unsigned StringMapImpl::LookupBucketFor(StringRef Name) { + unsigned HTSize = NumBuckets; + if (HTSize == 0) { // Hash table unallocated so far? + init(16); + HTSize = NumBuckets; + } + unsigned FullHashValue = HashString(Name); + unsigned BucketNo = FullHashValue & (HTSize-1); + unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1); + + unsigned ProbeAmt = 1; + int FirstTombstone = -1; + while (true) { + StringMapEntryBase *BucketItem = TheTable[BucketNo]; + // If we found an empty bucket, this key isn't in the table yet, return it. + if (LLVM_LIKELY(!BucketItem)) { + // If we found a tombstone, we want to reuse the tombstone instead of an + // empty bucket. This reduces probing. + if (FirstTombstone != -1) { + HashTable[FirstTombstone] = FullHashValue; + return FirstTombstone; + } + + HashTable[BucketNo] = FullHashValue; + return BucketNo; + } + + if (BucketItem == getTombstoneVal()) { + // Skip over tombstones. However, remember the first one we see. + if (FirstTombstone == -1) FirstTombstone = BucketNo; + } else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) { + // If the full hash value matches, check deeply for a match. The common + // case here is that we are only looking at the buckets (for item info + // being non-null and for the full hash value) not at the items. This + // is important for cache locality. + + // Do the comparison like this because Name isn't necessarily + // null-terminated! + char *ItemStr = (char*)BucketItem+ItemSize; + if (Name == StringRef(ItemStr, BucketItem->getKeyLength())) { + // We found a match! + return BucketNo; + } + } + + // Okay, we didn't find the item. Probe to the next bucket. + BucketNo = (BucketNo+ProbeAmt) & (HTSize-1); + + // Use quadratic probing, it has fewer clumping artifacts than linear + // probing and has good cache behavior in the common case. + ++ProbeAmt; + } +} + +/// FindKey - Look up the bucket that contains the specified key. If it exists +/// in the map, return the bucket number of the key. Otherwise return -1. +/// This does not modify the map. +int StringMapImpl::FindKey(StringRef Key) const { + unsigned HTSize = NumBuckets; + if (HTSize == 0) return -1; // Really empty table? + unsigned FullHashValue = HashString(Key); + unsigned BucketNo = FullHashValue & (HTSize-1); + unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1); + + unsigned ProbeAmt = 1; + while (true) { + StringMapEntryBase *BucketItem = TheTable[BucketNo]; + // If we found an empty bucket, this key isn't in the table yet, return. + if (LLVM_LIKELY(!BucketItem)) + return -1; + + if (BucketItem == getTombstoneVal()) { + // Ignore tombstones. + } else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) { + // If the full hash value matches, check deeply for a match. The common + // case here is that we are only looking at the buckets (for item info + // being non-null and for the full hash value) not at the items. This + // is important for cache locality. + + // Do the comparison like this because NameStart isn't necessarily + // null-terminated! + char *ItemStr = (char*)BucketItem+ItemSize; + if (Key == StringRef(ItemStr, BucketItem->getKeyLength())) { + // We found a match! + return BucketNo; + } + } + + // Okay, we didn't find the item. Probe to the next bucket. + BucketNo = (BucketNo+ProbeAmt) & (HTSize-1); + + // Use quadratic probing, it has fewer clumping artifacts than linear + // probing and has good cache behavior in the common case. + ++ProbeAmt; + } +} + +/// RemoveKey - Remove the specified StringMapEntry from the table, but do not +/// delete it. This aborts if the value isn't in the table. +void StringMapImpl::RemoveKey(StringMapEntryBase *V) { + const char *VStr = (char*)V + ItemSize; + StringMapEntryBase *V2 = RemoveKey(StringRef(VStr, V->getKeyLength())); + (void)V2; + assert(V == V2 && "Didn't find key?"); +} + +/// RemoveKey - Remove the StringMapEntry for the specified key from the +/// table, returning it. If the key is not in the table, this returns null. +StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) { + int Bucket = FindKey(Key); + if (Bucket == -1) return nullptr; + + StringMapEntryBase *Result = TheTable[Bucket]; + TheTable[Bucket] = getTombstoneVal(); + --NumItems; + ++NumTombstones; + assert(NumItems + NumTombstones <= NumBuckets); + + return Result; +} + +/// RehashTable - Grow the table, redistributing values into the buckets with +/// the appropriate mod-of-hashtable-size. +unsigned StringMapImpl::RehashTable(unsigned BucketNo) { + unsigned NewSize; + unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1); + + // If the hash table is now more than 3/4 full, or if fewer than 1/8 of + // the buckets are empty (meaning that many are filled with tombstones), + // grow/rehash the table. + if (LLVM_UNLIKELY(NumItems * 4 > NumBuckets * 3)) { + NewSize = NumBuckets*2; + } else if (LLVM_UNLIKELY(NumBuckets - (NumItems + NumTombstones) <= + NumBuckets / 8)) { + NewSize = NumBuckets; + } else { + return BucketNo; + } + + unsigned NewBucketNo = BucketNo; + // Allocate one extra bucket which will always be non-empty. This allows the + // iterators to stop at end. + StringMapEntryBase **NewTableArray = + (StringMapEntryBase **)calloc(NewSize+1, sizeof(StringMapEntryBase *) + + sizeof(unsigned)); + unsigned *NewHashArray = (unsigned *)(NewTableArray + NewSize + 1); + NewTableArray[NewSize] = (StringMapEntryBase*)2; + + // Rehash all the items into their new buckets. Luckily :) we already have + // the hash values available, so we don't have to rehash any strings. + for (unsigned I = 0, E = NumBuckets; I != E; ++I) { + StringMapEntryBase *Bucket = TheTable[I]; + if (Bucket && Bucket != getTombstoneVal()) { + // Fast case, bucket available. + unsigned FullHash = HashTable[I]; + unsigned NewBucket = FullHash & (NewSize-1); + if (!NewTableArray[NewBucket]) { + NewTableArray[FullHash & (NewSize-1)] = Bucket; + NewHashArray[FullHash & (NewSize-1)] = FullHash; + if (I == BucketNo) + NewBucketNo = NewBucket; + continue; + } + + // Otherwise probe for a spot. + unsigned ProbeSize = 1; + do { + NewBucket = (NewBucket + ProbeSize++) & (NewSize-1); + } while (NewTableArray[NewBucket]); + + // Finally found a slot. Fill it in. + NewTableArray[NewBucket] = Bucket; + NewHashArray[NewBucket] = FullHash; + if (I == BucketNo) + NewBucketNo = NewBucket; + } + } + + free(TheTable); + + TheTable = NewTableArray; + NumBuckets = NewSize; + NumTombstones = 0; + return NewBucketNo; +}
diff --git a/third_party/llvm-subzero/lib/Support/StringRef.cpp b/third_party/llvm-subzero/lib/Support/StringRef.cpp new file mode 100644 index 0000000..8a9da5e --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/StringRef.cpp
@@ -0,0 +1,524 @@ +//===-- StringRef.cpp - Lightweight String References ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/ADT/edit_distance.h" +#include <bitset> + +using namespace llvm; + +// MSVC emits references to this into the translation units which reference it. +#ifndef _MSC_VER +const size_t StringRef::npos; +#endif + +static char ascii_tolower(char x) { + if (x >= 'A' && x <= 'Z') + return x - 'A' + 'a'; + return x; +} + +static char ascii_toupper(char x) { + if (x >= 'a' && x <= 'z') + return x - 'a' + 'A'; + return x; +} + +static bool ascii_isdigit(char x) { + return x >= '0' && x <= '9'; +} + +// strncasecmp() is not available on non-POSIX systems, so define an +// alternative function here. +static int ascii_strncasecmp(const char *LHS, const char *RHS, size_t Length) { + for (size_t I = 0; I < Length; ++I) { + unsigned char LHC = ascii_tolower(LHS[I]); + unsigned char RHC = ascii_tolower(RHS[I]); + if (LHC != RHC) + return LHC < RHC ? -1 : 1; + } + return 0; +} + +/// compare_lower - Compare strings, ignoring case. +int StringRef::compare_lower(StringRef RHS) const { + if (int Res = ascii_strncasecmp(Data, RHS.Data, std::min(Length, RHS.Length))) + return Res; + if (Length == RHS.Length) + return 0; + return Length < RHS.Length ? -1 : 1; +} + +/// Check if this string starts with the given \p Prefix, ignoring case. +bool StringRef::startswith_lower(StringRef Prefix) const { + return Length >= Prefix.Length && + ascii_strncasecmp(Data, Prefix.Data, Prefix.Length) == 0; +} + +/// Check if this string ends with the given \p Suffix, ignoring case. +bool StringRef::endswith_lower(StringRef Suffix) const { + return Length >= Suffix.Length && + ascii_strncasecmp(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0; +} + +/// compare_numeric - Compare strings, handle embedded numbers. +int StringRef::compare_numeric(StringRef RHS) const { + for (size_t I = 0, E = std::min(Length, RHS.Length); I != E; ++I) { + // Check for sequences of digits. + if (ascii_isdigit(Data[I]) && ascii_isdigit(RHS.Data[I])) { + // The longer sequence of numbers is considered larger. + // This doesn't really handle prefixed zeros well. + size_t J; + for (J = I + 1; J != E + 1; ++J) { + bool ld = J < Length && ascii_isdigit(Data[J]); + bool rd = J < RHS.Length && ascii_isdigit(RHS.Data[J]); + if (ld != rd) + return rd ? -1 : 1; + if (!rd) + break; + } + // The two number sequences have the same length (J-I), just memcmp them. + if (int Res = compareMemory(Data + I, RHS.Data + I, J - I)) + return Res < 0 ? -1 : 1; + // Identical number sequences, continue search after the numbers. + I = J - 1; + continue; + } + if (Data[I] != RHS.Data[I]) + return (unsigned char)Data[I] < (unsigned char)RHS.Data[I] ? -1 : 1; + } + if (Length == RHS.Length) + return 0; + return Length < RHS.Length ? -1 : 1; +} + +// Compute the edit distance between the two given strings. +unsigned StringRef::edit_distance(llvm::StringRef Other, + bool AllowReplacements, + unsigned MaxEditDistance) const { + return llvm::ComputeEditDistance( + makeArrayRef(data(), size()), + makeArrayRef(Other.data(), Other.size()), + AllowReplacements, MaxEditDistance); +} + +//===----------------------------------------------------------------------===// +// String Operations +//===----------------------------------------------------------------------===// + +std::string StringRef::lower() const { + std::string Result(size(), char()); + for (size_type i = 0, e = size(); i != e; ++i) { + Result[i] = ascii_tolower(Data[i]); + } + return Result; +} + +std::string StringRef::upper() const { + std::string Result(size(), char()); + for (size_type i = 0, e = size(); i != e; ++i) { + Result[i] = ascii_toupper(Data[i]); + } + return Result; +} + +//===----------------------------------------------------------------------===// +// String Searching +//===----------------------------------------------------------------------===// + + +/// find - Search for the first string \arg Str in the string. +/// +/// \return - The index of the first occurrence of \arg Str, or npos if not +/// found. +size_t StringRef::find(StringRef Str, size_t From) const { + if (From > Length) + return npos; + + const char *Needle = Str.data(); + size_t N = Str.size(); + if (N == 0) + return From; + + size_t Size = Length - From; + if (Size < N) + return npos; + + const char *Start = Data + From; + const char *Stop = Start + (Size - N + 1); + + // For short haystacks or unsupported needles fall back to the naive algorithm + if (Size < 16 || N > 255) { + do { + if (std::memcmp(Start, Needle, N) == 0) + return Start - Data; + ++Start; + } while (Start < Stop); + return npos; + } + + // Build the bad char heuristic table, with uint8_t to reduce cache thrashing. + uint8_t BadCharSkip[256]; + std::memset(BadCharSkip, N, 256); + for (unsigned i = 0; i != N-1; ++i) + BadCharSkip[(uint8_t)Str[i]] = N-1-i; + + do { + if (std::memcmp(Start, Needle, N) == 0) + return Start - Data; + + // Otherwise skip the appropriate number of bytes. + Start += BadCharSkip[(uint8_t)Start[N-1]]; + } while (Start < Stop); + + return npos; +} + +/// rfind - Search for the last string \arg Str in the string. +/// +/// \return - The index of the last occurrence of \arg Str, or npos if not +/// found. +size_t StringRef::rfind(StringRef Str) const { + size_t N = Str.size(); + if (N > Length) + return npos; + for (size_t i = Length - N + 1, e = 0; i != e;) { + --i; + if (substr(i, N).equals(Str)) + return i; + } + return npos; +} + +/// find_first_of - Find the first character in the string that is in \arg +/// Chars, or npos if not found. +/// +/// Note: O(size() + Chars.size()) +StringRef::size_type StringRef::find_first_of(StringRef Chars, + size_t From) const { + std::bitset<1 << CHAR_BIT> CharBits; + for (size_type i = 0; i != Chars.size(); ++i) + CharBits.set((unsigned char)Chars[i]); + + for (size_type i = std::min(From, Length), e = Length; i != e; ++i) + if (CharBits.test((unsigned char)Data[i])) + return i; + return npos; +} + +/// find_first_not_of - Find the first character in the string that is not +/// \arg C or npos if not found. +StringRef::size_type StringRef::find_first_not_of(char C, size_t From) const { + for (size_type i = std::min(From, Length), e = Length; i != e; ++i) + if (Data[i] != C) + return i; + return npos; +} + +/// find_first_not_of - Find the first character in the string that is not +/// in the string \arg Chars, or npos if not found. +/// +/// Note: O(size() + Chars.size()) +StringRef::size_type StringRef::find_first_not_of(StringRef Chars, + size_t From) const { + std::bitset<1 << CHAR_BIT> CharBits; + for (size_type i = 0; i != Chars.size(); ++i) + CharBits.set((unsigned char)Chars[i]); + + for (size_type i = std::min(From, Length), e = Length; i != e; ++i) + if (!CharBits.test((unsigned char)Data[i])) + return i; + return npos; +} + +/// find_last_of - Find the last character in the string that is in \arg C, +/// or npos if not found. +/// +/// Note: O(size() + Chars.size()) +StringRef::size_type StringRef::find_last_of(StringRef Chars, + size_t From) const { + std::bitset<1 << CHAR_BIT> CharBits; + for (size_type i = 0; i != Chars.size(); ++i) + CharBits.set((unsigned char)Chars[i]); + + for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i) + if (CharBits.test((unsigned char)Data[i])) + return i; + return npos; +} + +/// find_last_not_of - Find the last character in the string that is not +/// \arg C, or npos if not found. +StringRef::size_type StringRef::find_last_not_of(char C, size_t From) const { + for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i) + if (Data[i] != C) + return i; + return npos; +} + +/// find_last_not_of - Find the last character in the string that is not in +/// \arg Chars, or npos if not found. +/// +/// Note: O(size() + Chars.size()) +StringRef::size_type StringRef::find_last_not_of(StringRef Chars, + size_t From) const { + std::bitset<1 << CHAR_BIT> CharBits; + for (size_type i = 0, e = Chars.size(); i != e; ++i) + CharBits.set((unsigned char)Chars[i]); + + for (size_type i = std::min(From, Length) - 1, e = -1; i != e; --i) + if (!CharBits.test((unsigned char)Data[i])) + return i; + return npos; +} + +void StringRef::split(SmallVectorImpl<StringRef> &A, + StringRef Separator, int MaxSplit, + bool KeepEmpty) const { + StringRef S = *this; + + // Count down from MaxSplit. When MaxSplit is -1, this will just split + // "forever". This doesn't support splitting more than 2^31 times + // intentionally; if we ever want that we can make MaxSplit a 64-bit integer + // but that seems unlikely to be useful. + while (MaxSplit-- != 0) { + size_t Idx = S.find(Separator); + if (Idx == npos) + break; + + // Push this split. + if (KeepEmpty || Idx > 0) + A.push_back(S.slice(0, Idx)); + + // Jump forward. + S = S.slice(Idx + Separator.size(), npos); + } + + // Push the tail. + if (KeepEmpty || !S.empty()) + A.push_back(S); +} + +void StringRef::split(SmallVectorImpl<StringRef> &A, char Separator, + int MaxSplit, bool KeepEmpty) const { + StringRef S = *this; + + // Count down from MaxSplit. When MaxSplit is -1, this will just split + // "forever". This doesn't support splitting more than 2^31 times + // intentionally; if we ever want that we can make MaxSplit a 64-bit integer + // but that seems unlikely to be useful. + while (MaxSplit-- != 0) { + size_t Idx = S.find(Separator); + if (Idx == npos) + break; + + // Push this split. + if (KeepEmpty || Idx > 0) + A.push_back(S.slice(0, Idx)); + + // Jump forward. + S = S.slice(Idx + 1, npos); + } + + // Push the tail. + if (KeepEmpty || !S.empty()) + A.push_back(S); +} + +//===----------------------------------------------------------------------===// +// Helpful Algorithms +//===----------------------------------------------------------------------===// + +/// count - Return the number of non-overlapped occurrences of \arg Str in +/// the string. +size_t StringRef::count(StringRef Str) const { + size_t Count = 0; + size_t N = Str.size(); + if (N > Length) + return 0; + for (size_t i = 0, e = Length - N + 1; i != e; ++i) + if (substr(i, N).equals(Str)) + ++Count; + return Count; +} + +static unsigned GetAutoSenseRadix(StringRef &Str) { + if (Str.startswith("0x") || Str.startswith("0X")) { + Str = Str.substr(2); + return 16; + } + + if (Str.startswith("0b") || Str.startswith("0B")) { + Str = Str.substr(2); + return 2; + } + + if (Str.startswith("0o")) { + Str = Str.substr(2); + return 8; + } + + if (Str.startswith("0")) + return 8; + + return 10; +} + + +/// GetAsUnsignedInteger - Workhorse method that converts a integer character +/// sequence of radix up to 36 to an unsigned long long value. +bool llvm::getAsUnsignedInteger(StringRef Str, unsigned Radix, + unsigned long long &Result) { + // Autosense radix if not specified. + if (Radix == 0) + Radix = GetAutoSenseRadix(Str); + + // Empty strings (after the radix autosense) are invalid. + if (Str.empty()) return true; + + // Parse all the bytes of the string given this radix. Watch for overflow. + Result = 0; + while (!Str.empty()) { + unsigned CharVal; + if (Str[0] >= '0' && Str[0] <= '9') + CharVal = Str[0]-'0'; + else if (Str[0] >= 'a' && Str[0] <= 'z') + CharVal = Str[0]-'a'+10; + else if (Str[0] >= 'A' && Str[0] <= 'Z') + CharVal = Str[0]-'A'+10; + else + return true; + + // If the parsed value is larger than the integer radix, the string is + // invalid. + if (CharVal >= Radix) + return true; + + // Add in this character. + unsigned long long PrevResult = Result; + Result = Result*Radix+CharVal; + + // Check for overflow by shifting back and seeing if bits were lost. + if (Result/Radix < PrevResult) + return true; + + Str = Str.substr(1); + } + + return false; +} + +bool llvm::getAsSignedInteger(StringRef Str, unsigned Radix, + long long &Result) { + unsigned long long ULLVal; + + // Handle positive strings first. + if (Str.empty() || Str.front() != '-') { + if (getAsUnsignedInteger(Str, Radix, ULLVal) || + // Check for value so large it overflows a signed value. + (long long)ULLVal < 0) + return true; + Result = ULLVal; + return false; + } + + // Get the positive part of the value. + if (getAsUnsignedInteger(Str.substr(1), Radix, ULLVal) || + // Reject values so large they'd overflow as negative signed, but allow + // "-0". This negates the unsigned so that the negative isn't undefined + // on signed overflow. + (long long)-ULLVal > 0) + return true; + + Result = -ULLVal; + return false; +} + +bool StringRef::getAsInteger(unsigned Radix, APInt &Result) const { + StringRef Str = *this; + + // Autosense radix if not specified. + if (Radix == 0) + Radix = GetAutoSenseRadix(Str); + + assert(Radix > 1 && Radix <= 36); + + // Empty strings (after the radix autosense) are invalid. + if (Str.empty()) return true; + + // Skip leading zeroes. This can be a significant improvement if + // it means we don't need > 64 bits. + while (!Str.empty() && Str.front() == '0') + Str = Str.substr(1); + + // If it was nothing but zeroes.... + if (Str.empty()) { + Result = APInt(64, 0); + return false; + } + + // (Over-)estimate the required number of bits. + unsigned Log2Radix = 0; + while ((1U << Log2Radix) < Radix) Log2Radix++; + bool IsPowerOf2Radix = ((1U << Log2Radix) == Radix); + + unsigned BitWidth = Log2Radix * Str.size(); + if (BitWidth < Result.getBitWidth()) + BitWidth = Result.getBitWidth(); // don't shrink the result + else if (BitWidth > Result.getBitWidth()) + Result = Result.zext(BitWidth); + + APInt RadixAP, CharAP; // unused unless !IsPowerOf2Radix + if (!IsPowerOf2Radix) { + // These must have the same bit-width as Result. + RadixAP = APInt(BitWidth, Radix); + CharAP = APInt(BitWidth, 0); + } + + // Parse all the bytes of the string given this radix. + Result = 0; + while (!Str.empty()) { + unsigned CharVal; + if (Str[0] >= '0' && Str[0] <= '9') + CharVal = Str[0]-'0'; + else if (Str[0] >= 'a' && Str[0] <= 'z') + CharVal = Str[0]-'a'+10; + else if (Str[0] >= 'A' && Str[0] <= 'Z') + CharVal = Str[0]-'A'+10; + else + return true; + + // If the parsed value is larger than the integer radix, the string is + // invalid. + if (CharVal >= Radix) + return true; + + // Add in this character. + if (IsPowerOf2Radix) { + Result <<= Log2Radix; + Result |= CharVal; + } else { + Result *= RadixAP; + CharAP = CharVal; + Result += CharAP; + } + + Str = Str.substr(1); + } + + return false; +} + + +// Implementation of StringRef hashing. +hash_code llvm::hash_value(StringRef S) { + return hash_combine_range(S.begin(), S.end()); +}
diff --git a/third_party/llvm-subzero/lib/Support/StringSaver.cpp b/third_party/llvm-subzero/lib/Support/StringSaver.cpp new file mode 100644 index 0000000..bbc1fd2 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/StringSaver.cpp
@@ -0,0 +1,19 @@ +//===-- StringSaver.cpp ---------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/StringSaver.h" + +using namespace llvm; + +const char *StringSaver::save(StringRef S) { + char *P = Alloc.Allocate<char>(S.size() + 1); + memcpy(P, S.data(), S.size()); + P[S.size()] = '\0'; + return P; +}
diff --git a/third_party/llvm-subzero/lib/Support/TargetParser.cpp b/third_party/llvm-subzero/lib/Support/TargetParser.cpp new file mode 100644 index 0000000..8b00b34 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/TargetParser.cpp
@@ -0,0 +1,834 @@ +//===-- TargetParser - Parser for target features ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a target parser to recognise hardware features such as +// FPU/CPU/ARCH names as well as specific support such as HDIV, etc. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ARMBuildAttributes.h" +#include "llvm/Support/TargetParser.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include <cctype> + +using namespace llvm; +using namespace ARM; +using namespace AArch64; + +namespace { + +// List of canonical FPU names (use getFPUSynonym) and which architectural +// features they correspond to (use getFPUFeatures). +// FIXME: TableGen this. +// The entries must appear in the order listed in ARM::FPUKind for correct indexing +static const struct { + const char *NameCStr; + size_t NameLength; + ARM::FPUKind ID; + ARM::FPUVersion FPUVersion; + ARM::NeonSupportLevel NeonSupport; + ARM::FPURestriction Restriction; + + StringRef getName() const { return StringRef(NameCStr, NameLength); } +} FPUNames[] = { +#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \ + { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION }, +#include "llvm/Support/ARMTargetParser.def" +}; + +// List of canonical arch names (use getArchSynonym). +// This table also provides the build attribute fields for CPU arch +// and Arch ID, according to the Addenda to the ARM ABI, chapters +// 2.4 and 2.3.5.2 respectively. +// FIXME: SubArch values were simplified to fit into the expectations +// of the triples and are not conforming with their official names. +// Check to see if the expectation should be changed. +// FIXME: TableGen this. +template <typename T> struct ArchNames { + const char *NameCStr; + size_t NameLength; + const char *CPUAttrCStr; + size_t CPUAttrLength; + const char *SubArchCStr; + size_t SubArchLength; + unsigned DefaultFPU; + unsigned ArchBaseExtensions; + T ID; + ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes. + + StringRef getName() const { return StringRef(NameCStr, NameLength); } + + // CPU class in build attributes. + StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); } + + // Sub-Arch name. + StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); } +}; +ArchNames<ARM::ArchKind> ARCHNames[] = { +#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \ + {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \ + sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ID, ARCH_ATTR}, +#include "llvm/Support/ARMTargetParser.def" +}; + +ArchNames<AArch64::ArchKind> AArch64ARCHNames[] = { + #define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \ + {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \ + sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, AArch64::ArchKind::ID, ARCH_ATTR}, + #include "llvm/Support/AArch64TargetParser.def" + }; + + +// List of Arch Extension names. +// FIXME: TableGen this. +static const struct { + const char *NameCStr; + size_t NameLength; + unsigned ID; + const char *Feature; + const char *NegFeature; + + StringRef getName() const { return StringRef(NameCStr, NameLength); } +} ARCHExtNames[] = { +#define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \ + { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE }, +#include "llvm/Support/ARMTargetParser.def" +},AArch64ARCHExtNames[] = { +#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \ + { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE }, +#include "llvm/Support/AArch64TargetParser.def" +}; + +// List of HWDiv names (use getHWDivSynonym) and which architectural +// features they correspond to (use getHWDivFeatures). +// FIXME: TableGen this. +static const struct { + const char *NameCStr; + size_t NameLength; + unsigned ID; + + StringRef getName() const { return StringRef(NameCStr, NameLength); } +} HWDivNames[] = { +#define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID }, +#include "llvm/Support/ARMTargetParser.def" +}; + +// List of CPU names and their arches. +// The same CPU can have multiple arches and can be default on multiple arches. +// When finding the Arch for a CPU, first-found prevails. Sort them accordingly. +// When this becomes table-generated, we'd probably need two tables. +// FIXME: TableGen this. +template <typename T> struct CpuNames { + const char *NameCStr; + size_t NameLength; + T ArchID; + bool Default; // is $Name the default CPU for $ArchID ? + unsigned DefaultExtensions; + + StringRef getName() const { return StringRef(NameCStr, NameLength); } +}; +CpuNames<ARM::ArchKind> CPUNames[] = { +#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ + { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT }, +#include "llvm/Support/ARMTargetParser.def" +}; + +CpuNames<AArch64::ArchKind> AArch64CPUNames[] = { + #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ + { NAME, sizeof(NAME) - 1, AArch64::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT }, + #include "llvm/Support/AArch64TargetParser.def" + }; + +} // namespace + +// ======================================================= // +// Information by ID +// ======================================================= // + +StringRef llvm::ARM::getFPUName(unsigned FPUKind) { + if (FPUKind >= ARM::FK_LAST) + return StringRef(); + return FPUNames[FPUKind].getName(); +} + +unsigned llvm::ARM::getFPUVersion(unsigned FPUKind) { + if (FPUKind >= ARM::FK_LAST) + return 0; + return FPUNames[FPUKind].FPUVersion; +} + +unsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) { + if (FPUKind >= ARM::FK_LAST) + return 0; + return FPUNames[FPUKind].NeonSupport; +} + +unsigned llvm::ARM::getFPURestriction(unsigned FPUKind) { + if (FPUKind >= ARM::FK_LAST) + return 0; + return FPUNames[FPUKind].Restriction; +} + +unsigned llvm::ARM::getDefaultFPU(StringRef CPU, unsigned ArchKind) { + if (CPU == "generic") + return ARCHNames[ArchKind].DefaultFPU; + + return StringSwitch<unsigned>(CPU) +#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ + .Case(NAME, DEFAULT_FPU) +#include "llvm/Support/ARMTargetParser.def" + .Default(ARM::FK_INVALID); +} + +unsigned llvm::ARM::getDefaultExtensions(StringRef CPU, unsigned ArchKind) { + if (CPU == "generic") + return ARCHNames[ArchKind].ArchBaseExtensions; + + return StringSwitch<unsigned>(CPU) +#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ + .Case(NAME, ARCHNames[ID].ArchBaseExtensions | DEFAULT_EXT) +#include "llvm/Support/ARMTargetParser.def" + .Default(ARM::AEK_INVALID); +} + +bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind, + std::vector<const char *> &Features) { + + if (HWDivKind == ARM::AEK_INVALID) + return false; + + if (HWDivKind & ARM::AEK_HWDIVARM) + Features.push_back("+hwdiv-arm"); + else + Features.push_back("-hwdiv-arm"); + + if (HWDivKind & ARM::AEK_HWDIV) + Features.push_back("+hwdiv"); + else + Features.push_back("-hwdiv"); + + return true; +} + +bool llvm::ARM::getExtensionFeatures(unsigned Extensions, + std::vector<const char *> &Features) { + + if (Extensions == ARM::AEK_INVALID) + return false; + + if (Extensions & ARM::AEK_CRC) + Features.push_back("+crc"); + else + Features.push_back("-crc"); + + if (Extensions & ARM::AEK_DSP) + Features.push_back("+dsp"); + else + Features.push_back("-dsp"); + + return getHWDivFeatures(Extensions, Features); +} + +bool llvm::ARM::getFPUFeatures(unsigned FPUKind, + std::vector<const char *> &Features) { + + if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID) + return false; + + // fp-only-sp and d16 subtarget features are independent of each other, so we + // must enable/disable both. + switch (FPUNames[FPUKind].Restriction) { + case ARM::FR_SP_D16: + Features.push_back("+fp-only-sp"); + Features.push_back("+d16"); + break; + case ARM::FR_D16: + Features.push_back("-fp-only-sp"); + Features.push_back("+d16"); + break; + case ARM::FR_None: + Features.push_back("-fp-only-sp"); + Features.push_back("-d16"); + break; + } + + // FPU version subtarget features are inclusive of lower-numbered ones, so + // enable the one corresponding to this version and disable all that are + // higher. We also have to make sure to disable fp16 when vfp4 is disabled, + // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16. + switch (FPUNames[FPUKind].FPUVersion) { + case ARM::FV_VFPV5: + Features.push_back("+fp-armv8"); + break; + case ARM::FV_VFPV4: + Features.push_back("+vfp4"); + Features.push_back("-fp-armv8"); + break; + case ARM::FV_VFPV3_FP16: + Features.push_back("+vfp3"); + Features.push_back("+fp16"); + Features.push_back("-vfp4"); + Features.push_back("-fp-armv8"); + break; + case ARM::FV_VFPV3: + Features.push_back("+vfp3"); + Features.push_back("-fp16"); + Features.push_back("-vfp4"); + Features.push_back("-fp-armv8"); + break; + case ARM::FV_VFPV2: + Features.push_back("+vfp2"); + Features.push_back("-vfp3"); + Features.push_back("-fp16"); + Features.push_back("-vfp4"); + Features.push_back("-fp-armv8"); + break; + case ARM::FV_NONE: + Features.push_back("-vfp2"); + Features.push_back("-vfp3"); + Features.push_back("-fp16"); + Features.push_back("-vfp4"); + Features.push_back("-fp-armv8"); + break; + } + + // crypto includes neon, so we handle this similarly to FPU version. + switch (FPUNames[FPUKind].NeonSupport) { + case ARM::NS_Crypto: + Features.push_back("+neon"); + Features.push_back("+crypto"); + break; + case ARM::NS_Neon: + Features.push_back("+neon"); + Features.push_back("-crypto"); + break; + case ARM::NS_None: + Features.push_back("-neon"); + Features.push_back("-crypto"); + break; + } + + return true; +} + +StringRef llvm::ARM::getArchName(unsigned ArchKind) { + if (ArchKind >= ARM::AK_LAST) + return StringRef(); + return ARCHNames[ArchKind].getName(); +} + +StringRef llvm::ARM::getCPUAttr(unsigned ArchKind) { + if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST) + return StringRef(); + return ARCHNames[ArchKind].getCPUAttr(); +} + +StringRef llvm::ARM::getSubArch(unsigned ArchKind) { + if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST) + return StringRef(); + return ARCHNames[ArchKind].getSubArch(); +} + +unsigned llvm::ARM::getArchAttr(unsigned ArchKind) { + if (ArchKind >= ARM::AK_LAST) + return ARMBuildAttrs::CPUArch::Pre_v4; + return ARCHNames[ArchKind].ArchAttr; +} + +StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) { + for (const auto AE : ARCHExtNames) { + if (ArchExtKind == AE.ID) + return AE.getName(); + } + return StringRef(); +} + +const char *llvm::ARM::getArchExtFeature(StringRef ArchExt) { + if (ArchExt.startswith("no")) { + StringRef ArchExtBase(ArchExt.substr(2)); + for (const auto AE : ARCHExtNames) { + if (AE.NegFeature && ArchExtBase == AE.getName()) + return AE.NegFeature; + } + } + for (const auto AE : ARCHExtNames) { + if (AE.Feature && ArchExt == AE.getName()) + return AE.Feature; + } + + return nullptr; +} + +StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) { + for (const auto D : HWDivNames) { + if (HWDivKind == D.ID) + return D.getName(); + } + return StringRef(); +} + +StringRef llvm::ARM::getDefaultCPU(StringRef Arch) { + unsigned AK = parseArch(Arch); + if (AK == ARM::AK_INVALID) + return StringRef(); + + // Look for multiple AKs to find the default for pair AK+Name. + for (const auto CPU : CPUNames) { + if (CPU.ArchID == AK && CPU.Default) + return CPU.getName(); + } + + // If we can't find a default then target the architecture instead + return "generic"; +} + +StringRef llvm::AArch64::getFPUName(unsigned FPUKind) { + return ARM::getFPUName(FPUKind); +} + +unsigned llvm::AArch64::getFPUVersion(unsigned FPUKind) { + return ARM::getFPUVersion(FPUKind); +} + +unsigned llvm::AArch64::getFPUNeonSupportLevel(unsigned FPUKind) { + return ARM::getFPUNeonSupportLevel( FPUKind); +} + +unsigned llvm::AArch64::getFPURestriction(unsigned FPUKind) { + return ARM::getFPURestriction(FPUKind); +} + +unsigned llvm::AArch64::getDefaultFPU(StringRef CPU, unsigned ArchKind) { + if (CPU == "generic") + return AArch64ARCHNames[ArchKind].DefaultFPU; + + return StringSwitch<unsigned>(CPU) +#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ + .Case(NAME, DEFAULT_FPU) +#include "llvm/Support/AArch64TargetParser.def" + .Default(ARM::FK_INVALID); +} + +unsigned llvm::AArch64::getDefaultExtensions(StringRef CPU, unsigned ArchKind) { + if (CPU == "generic") + return AArch64ARCHNames[ArchKind].ArchBaseExtensions; + + return StringSwitch<unsigned>(CPU) +#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ + .Case(NAME, DEFAULT_EXT) +#include "llvm/Support/AArch64TargetParser.def" + .Default(AArch64::AEK_INVALID); +} + +bool llvm::AArch64::getExtensionFeatures(unsigned Extensions, + std::vector<const char *> &Features) { + + if (Extensions == AArch64::AEK_INVALID) + return false; + + if (Extensions & AArch64::AEK_FP) + Features.push_back("+fp-armv8"); + if (Extensions & AArch64::AEK_SIMD) + Features.push_back("+neon"); + if (Extensions & AArch64::AEK_CRC) + Features.push_back("+crc"); + if (Extensions & AArch64::AEK_CRYPTO) + Features.push_back("+crypto"); + if (Extensions & AArch64::AEK_FP16) + Features.push_back("+fullfp16"); + if (Extensions & AArch64::AEK_PROFILE) + Features.push_back("+spe"); + if (Extensions & AArch64::AEK_RAS) + Features.push_back("+ras"); + + return true; +} + +bool llvm::AArch64::getFPUFeatures(unsigned FPUKind, + std::vector<const char *> &Features) { + return ARM::getFPUFeatures(FPUKind, Features); +} + +bool llvm::AArch64::getArchFeatures(unsigned ArchKind, + std::vector<const char *> &Features) { + if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_ARMV8_1A)) + Features.push_back("+v8.1a"); + if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_ARMV8_2A)) + Features.push_back("+v8.2a"); + + return ArchKind > static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) && + ArchKind < static_cast<unsigned>(AArch64::ArchKind::AK_LAST); +} + +StringRef llvm::AArch64::getArchName(unsigned ArchKind) { + if (ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST)) + return StringRef(); + return AArch64ARCHNames[ArchKind].getName(); +} + +StringRef llvm::AArch64::getCPUAttr(unsigned ArchKind) { + if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) || + ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST)) + return StringRef(); + return AArch64ARCHNames[ArchKind].getCPUAttr(); +} + +StringRef llvm::AArch64::getSubArch(unsigned ArchKind) { + if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) || + ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST)) + return StringRef(); + return AArch64ARCHNames[ArchKind].getSubArch(); +} + +unsigned llvm::AArch64::getArchAttr(unsigned ArchKind) { + if (ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST)) + return ARMBuildAttrs::CPUArch::v8_A; + return AArch64ARCHNames[ArchKind].ArchAttr; +} + +StringRef llvm::AArch64::getArchExtName(unsigned ArchExtKind) { + for (const auto &AE : AArch64ARCHExtNames) + if (ArchExtKind == AE.ID) + return AE.getName(); + return StringRef(); +} + +const char *llvm::AArch64::getArchExtFeature(StringRef ArchExt) { + if (ArchExt.startswith("no")) { + StringRef ArchExtBase(ArchExt.substr(2)); + for (const auto &AE : AArch64ARCHExtNames) { + if (AE.NegFeature && ArchExtBase == AE.getName()) + return AE.NegFeature; + } + } + + for (const auto &AE : AArch64ARCHExtNames) + if (AE.Feature && ArchExt == AE.getName()) + return AE.Feature; + return nullptr; +} + +StringRef llvm::AArch64::getDefaultCPU(StringRef Arch) { + unsigned AK = parseArch(Arch); + if (AK == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID)) + return StringRef(); + + // Look for multiple AKs to find the default for pair AK+Name. + for (const auto &CPU : AArch64CPUNames) + if (static_cast<unsigned>(CPU.ArchID) == AK && CPU.Default) + return CPU.getName(); + + // If we can't find a default then target the architecture instead + return "generic"; +} + +unsigned llvm::AArch64::checkArchVersion(StringRef Arch) { + if (Arch[0] == 'v' && std::isdigit(Arch[1])) + return (Arch[1] - 48); + return 0; +} + +// ======================================================= // +// Parsers +// ======================================================= // + +static StringRef getHWDivSynonym(StringRef HWDiv) { + return StringSwitch<StringRef>(HWDiv) + .Case("thumb,arm", "arm,thumb") + .Default(HWDiv); +} + +static StringRef getFPUSynonym(StringRef FPU) { + return StringSwitch<StringRef>(FPU) + .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported + .Case("vfp2", "vfpv2") + .Case("vfp3", "vfpv3") + .Case("vfp4", "vfpv4") + .Case("vfp3-d16", "vfpv3-d16") + .Case("vfp4-d16", "vfpv4-d16") + .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16") + .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16") + .Case("fp5-sp-d16", "fpv5-sp-d16") + .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16") + // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3. + .Case("neon-vfpv3", "neon") + .Default(FPU); +} + +static StringRef getArchSynonym(StringRef Arch) { + return StringSwitch<StringRef>(Arch) + .Case("v5", "v5t") + .Case("v5e", "v5te") + .Case("v6j", "v6") + .Case("v6hl", "v6k") + .Cases("v6m", "v6sm", "v6s-m", "v6-m") + .Cases("v6z", "v6zk", "v6kz") + .Cases("v7", "v7a", "v7hl", "v7l", "v7-a") + .Case("v7r", "v7-r") + .Case("v7m", "v7-m") + .Case("v7em", "v7e-m") + .Cases("v8", "v8a", "aarch64", "arm64", "v8-a") + .Case("v8.1a", "v8.1-a") + .Case("v8.2a", "v8.2-a") + .Case("v8m.base", "v8-m.base") + .Case("v8m.main", "v8-m.main") + .Default(Arch); +} + +// MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but +// (iwmmxt|xscale)(eb)? is also permitted. If the former, return +// "v.+", if the latter, return unmodified string, minus 'eb'. +// If invalid, return empty string. +StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) { + size_t offset = StringRef::npos; + StringRef A = Arch; + StringRef Error = ""; + + // Begins with "arm" / "thumb", move past it. + if (A.startswith("arm64")) + offset = 5; + else if (A.startswith("arm")) + offset = 3; + else if (A.startswith("thumb")) + offset = 5; + else if (A.startswith("aarch64")) { + offset = 7; + // AArch64 uses "_be", not "eb" suffix. + if (A.find("eb") != StringRef::npos) + return Error; + if (A.substr(offset, 3) == "_be") + offset += 3; + } + + // Ex. "armebv7", move past the "eb". + if (offset != StringRef::npos && A.substr(offset, 2) == "eb") + offset += 2; + // Or, if it ends with eb ("armv7eb"), chop it off. + else if (A.endswith("eb")) + A = A.substr(0, A.size() - 2); + // Trim the head + if (offset != StringRef::npos) + A = A.substr(offset); + + // Empty string means offset reached the end, which means it's valid. + if (A.empty()) + return Arch; + + // Only match non-marketing names + if (offset != StringRef::npos) { + // Must start with 'vN'. + if (A[0] != 'v' || !std::isdigit(A[1])) + return Error; + // Can't have an extra 'eb'. + if (A.find("eb") != StringRef::npos) + return Error; + } + + // Arch will either be a 'v' name (v7a) or a marketing name (xscale). + return A; +} + +unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) { + StringRef Syn = getHWDivSynonym(HWDiv); + for (const auto D : HWDivNames) { + if (Syn == D.getName()) + return D.ID; + } + return ARM::AEK_INVALID; +} + +unsigned llvm::ARM::parseFPU(StringRef FPU) { + StringRef Syn = getFPUSynonym(FPU); + for (const auto F : FPUNames) { + if (Syn == F.getName()) + return F.ID; + } + return ARM::FK_INVALID; +} + +// Allows partial match, ex. "v7a" matches "armv7a". +unsigned llvm::ARM::parseArch(StringRef Arch) { + Arch = getCanonicalArchName(Arch); + StringRef Syn = getArchSynonym(Arch); + for (const auto A : ARCHNames) { + if (A.getName().endswith(Syn)) + return A.ID; + } + return ARM::AK_INVALID; +} + +unsigned llvm::ARM::parseArchExt(StringRef ArchExt) { + for (const auto A : ARCHExtNames) { + if (ArchExt == A.getName()) + return A.ID; + } + return ARM::AEK_INVALID; +} + +unsigned llvm::ARM::parseCPUArch(StringRef CPU) { + for (const auto C : CPUNames) { + if (CPU == C.getName()) + return C.ArchID; + } + return ARM::AK_INVALID; +} + +// ARM, Thumb, AArch64 +unsigned llvm::ARM::parseArchISA(StringRef Arch) { + return StringSwitch<unsigned>(Arch) + .StartsWith("aarch64", ARM::IK_AARCH64) + .StartsWith("arm64", ARM::IK_AARCH64) + .StartsWith("thumb", ARM::IK_THUMB) + .StartsWith("arm", ARM::IK_ARM) + .Default(ARM::IK_INVALID); +} + +// Little/Big endian +unsigned llvm::ARM::parseArchEndian(StringRef Arch) { + if (Arch.startswith("armeb") || Arch.startswith("thumbeb") || + Arch.startswith("aarch64_be")) + return ARM::EK_BIG; + + if (Arch.startswith("arm") || Arch.startswith("thumb")) { + if (Arch.endswith("eb")) + return ARM::EK_BIG; + else + return ARM::EK_LITTLE; + } + + if (Arch.startswith("aarch64")) + return ARM::EK_LITTLE; + + return ARM::EK_INVALID; +} + +// Profile A/R/M +unsigned llvm::ARM::parseArchProfile(StringRef Arch) { + Arch = getCanonicalArchName(Arch); + switch (parseArch(Arch)) { + case ARM::AK_ARMV6M: + case ARM::AK_ARMV7M: + case ARM::AK_ARMV7EM: + case ARM::AK_ARMV8MMainline: + case ARM::AK_ARMV8MBaseline: + return ARM::PK_M; + case ARM::AK_ARMV7R: + return ARM::PK_R; + case ARM::AK_ARMV7A: + case ARM::AK_ARMV7K: + case ARM::AK_ARMV8A: + case ARM::AK_ARMV8_1A: + case ARM::AK_ARMV8_2A: + return ARM::PK_A; + } + return ARM::PK_INVALID; +} + +// Version number (ex. v7 = 7). +unsigned llvm::ARM::parseArchVersion(StringRef Arch) { + Arch = getCanonicalArchName(Arch); + switch (parseArch(Arch)) { + case ARM::AK_ARMV2: + case ARM::AK_ARMV2A: + return 2; + case ARM::AK_ARMV3: + case ARM::AK_ARMV3M: + return 3; + case ARM::AK_ARMV4: + case ARM::AK_ARMV4T: + return 4; + case ARM::AK_ARMV5T: + case ARM::AK_ARMV5TE: + case ARM::AK_IWMMXT: + case ARM::AK_IWMMXT2: + case ARM::AK_XSCALE: + case ARM::AK_ARMV5TEJ: + return 5; + case ARM::AK_ARMV6: + case ARM::AK_ARMV6K: + case ARM::AK_ARMV6T2: + case ARM::AK_ARMV6KZ: + case ARM::AK_ARMV6M: + return 6; + case ARM::AK_ARMV7A: + case ARM::AK_ARMV7R: + case ARM::AK_ARMV7M: + case ARM::AK_ARMV7S: + case ARM::AK_ARMV7EM: + case ARM::AK_ARMV7K: + return 7; + case ARM::AK_ARMV8A: + case ARM::AK_ARMV8_1A: + case ARM::AK_ARMV8_2A: + case ARM::AK_ARMV8MBaseline: + case ARM::AK_ARMV8MMainline: + return 8; + } + return 0; +} + +StringRef llvm::AArch64::getCanonicalArchName(StringRef Arch) { + return ARM::getCanonicalArchName(Arch); +} + +unsigned llvm::AArch64::parseFPU(StringRef FPU) { + return ARM::parseFPU(FPU); +} + +// Allows partial match, ex. "v8a" matches "armv8a". +unsigned llvm::AArch64::parseArch(StringRef Arch) { + Arch = getCanonicalArchName(Arch); + if (checkArchVersion(Arch) < 8) + return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID); + + StringRef Syn = getArchSynonym(Arch); + for (const auto A : AArch64ARCHNames) { + if (A.getName().endswith(Syn)) + return static_cast<unsigned>(A.ID); + } + return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID); +} + +unsigned llvm::AArch64::parseArchExt(StringRef ArchExt) { + for (const auto A : AArch64ARCHExtNames) { + if (ArchExt == A.getName()) + return A.ID; + } + return AArch64::AEK_INVALID; +} + +unsigned llvm::AArch64::parseCPUArch(StringRef CPU) { + for (const auto C : AArch64CPUNames) { + if (CPU == C.getName()) + return static_cast<unsigned>(C.ArchID); + } + return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID); +} + +// ARM, Thumb, AArch64 +unsigned llvm::AArch64::parseArchISA(StringRef Arch) { + return ARM::parseArchISA(Arch); +} + +// Little/Big endian +unsigned llvm::AArch64::parseArchEndian(StringRef Arch) { + return ARM::parseArchEndian(Arch); +} + +// Profile A/R/M +unsigned llvm::AArch64::parseArchProfile(StringRef Arch) { + return ARM::parseArchProfile(Arch); +} + +// Version number (ex. v8 = 8). +unsigned llvm::AArch64::parseArchVersion(StringRef Arch) { + return ARM::parseArchVersion(Arch); +}
diff --git a/third_party/llvm-subzero/lib/Support/Threading.cpp b/third_party/llvm-subzero/lib/Support/Threading.cpp new file mode 100644 index 0000000..e8f5622 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Threading.cpp
@@ -0,0 +1,118 @@ +//===-- llvm/Support/Threading.cpp- Control multithreading mode --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines helper functions for running LLVM in a multi-threaded +// environment. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Threading.h" +#include "llvm/Config/config.h" +#include "llvm/Support/Atomic.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/thread.h" +#include <cassert> + +using namespace llvm; + +bool llvm::llvm_is_multithreaded() { +#if LLVM_ENABLE_THREADS != 0 + return true; +#else + return false; +#endif +} + +#if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H) +#include <pthread.h> + +struct ThreadInfo { + void (*UserFn)(void *); + void *UserData; +}; +static void *ExecuteOnThread_Dispatch(void *Arg) { + ThreadInfo *TI = reinterpret_cast<ThreadInfo*>(Arg); + TI->UserFn(TI->UserData); + return nullptr; +} + +void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, + unsigned RequestedStackSize) { + ThreadInfo Info = { Fn, UserData }; + pthread_attr_t Attr; + pthread_t Thread; + + // Construct the attributes object. + if (::pthread_attr_init(&Attr) != 0) + return; + + // Set the requested stack size, if given. + if (RequestedStackSize != 0) { + if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0) + goto error; + } + + // Construct and execute the thread. + if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0) + goto error; + + // Wait for the thread and clean up. + ::pthread_join(Thread, nullptr); + + error: + ::pthread_attr_destroy(&Attr); +} +#elif LLVM_ENABLE_THREADS!=0 && defined(LLVM_ON_WIN32) +#include "Windows/WindowsSupport.h" +#include <process.h> + +// Windows will at times define MemoryFence. +#ifdef MemoryFence +#undef MemoryFence +#endif + +struct ThreadInfo { + void (*func)(void*); + void *param; +}; + +static unsigned __stdcall ThreadCallback(void *param) { + struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param); + info->func(info->param); + + return 0; +} + +void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, + unsigned RequestedStackSize) { + struct ThreadInfo param = { Fn, UserData }; + + HANDLE hThread = (HANDLE)::_beginthreadex(NULL, + RequestedStackSize, ThreadCallback, + ¶m, 0, NULL); + + if (hThread) { + // We actually don't care whether the wait succeeds or fails, in + // the same way we don't care whether the pthread_join call succeeds + // or fails. There's not much we could do if this were to fail. But + // on success, this call will wait until the thread finishes executing + // before returning. + (void)::WaitForSingleObject(hThread, INFINITE); + ::CloseHandle(hThread); + } +} +#else +// Support for non-Win32, non-pthread implementation. +void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, + unsigned RequestedStackSize) { + (void) RequestedStackSize; + Fn(UserData); +} + +#endif
diff --git a/third_party/llvm-subzero/lib/Support/TimeValue.cpp b/third_party/llvm-subzero/lib/Support/TimeValue.cpp new file mode 100644 index 0000000..94a4c01 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/TimeValue.cpp
@@ -0,0 +1,56 @@ +//===-- TimeValue.cpp - Implement OS TimeValue Concept ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the operating system TimeValue concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/TimeValue.h" +#include "llvm/Config/config.h" + +namespace llvm { + +using namespace sys; + +const TimeValue::SecondsType + TimeValue::PosixZeroTimeSeconds = -946684800; +const TimeValue::SecondsType + TimeValue::Win32ZeroTimeSeconds = -12591158400ULL; + +void TimeValue::normalize() { + if ( nanos_ >= NANOSECONDS_PER_SECOND ) { + do { + seconds_++; + nanos_ -= NANOSECONDS_PER_SECOND; + } while ( nanos_ >= NANOSECONDS_PER_SECOND ); + } else if (nanos_ <= -NANOSECONDS_PER_SECOND ) { + do { + seconds_--; + nanos_ += NANOSECONDS_PER_SECOND; + } while (nanos_ <= -NANOSECONDS_PER_SECOND); + } + + if (seconds_ >= 1 && nanos_ < 0) { + seconds_--; + nanos_ += NANOSECONDS_PER_SECOND; + } else if (seconds_ < 0 && nanos_ > 0) { + seconds_++; + nanos_ -= NANOSECONDS_PER_SECOND; + } +} + +} // namespace llvm + +/// Include the platform-specific portion of TimeValue class +#ifdef LLVM_ON_UNIX +#include "Unix/TimeValue.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Windows/TimeValue.inc" +#endif
diff --git a/third_party/llvm-subzero/lib/Support/Timer.cpp b/third_party/llvm-subzero/lib/Support/Timer.cpp new file mode 100644 index 0000000..49bd39e --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Timer.cpp
@@ -0,0 +1,375 @@ +//===-- Timer.cpp - Interval Timing Support -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interval Timing implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Timer.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy +// of constructor/destructor ordering being unspecified by C++. Basically the +// problem is that a Statistic object gets destroyed, which ends up calling +// 'GetLibSupportInfoOutputFile()' (below), which calls this function. +// LibSupportInfoOutputFilename used to be a global variable, but sometimes it +// would get destroyed before the Statistic, causing havoc to ensue. We "fix" +// this by creating the string the first time it is needed and never destroying +// it. +static ManagedStatic<std::string> LibSupportInfoOutputFilename; +static std::string &getLibSupportInfoOutputFilename() { + return *LibSupportInfoOutputFilename; +} + +static ManagedStatic<sys::SmartMutex<true> > TimerLock; + +namespace { + static cl::opt<bool> + TrackSpace("track-memory", cl::desc("Enable -time-passes memory " + "tracking (this may be slow)"), + cl::Hidden); + + static cl::opt<std::string, true> + InfoOutputFilename("info-output-file", cl::value_desc("filename"), + cl::desc("File to append -stats and -timer output to"), + cl::Hidden, cl::location(getLibSupportInfoOutputFilename())); +} + +// Return a file stream to print our output on. +std::unique_ptr<raw_fd_ostream> llvm::CreateInfoOutputFile() { + const std::string &OutputFilename = getLibSupportInfoOutputFilename(); + if (OutputFilename.empty()) + return llvm::make_unique<raw_fd_ostream>(2, false); // stderr. + if (OutputFilename == "-") + return llvm::make_unique<raw_fd_ostream>(1, false); // stdout. + + // Append mode is used because the info output file is opened and closed + // each time -stats or -time-passes wants to print output to it. To + // compensate for this, the test-suite Makefiles have code to delete the + // info output file before running commands which write to it. + std::error_code EC; + auto Result = llvm::make_unique<raw_fd_ostream>( + OutputFilename, EC, sys::fs::F_Append | sys::fs::F_Text); + if (!EC) + return Result; + + errs() << "Error opening info-output-file '" + << OutputFilename << " for appending!\n"; + return llvm::make_unique<raw_fd_ostream>(2, false); // stderr. +} + + +static TimerGroup *DefaultTimerGroup = nullptr; +static TimerGroup *getDefaultTimerGroup() { + TimerGroup *tmp = DefaultTimerGroup; + sys::MemoryFence(); + if (tmp) return tmp; + + sys::SmartScopedLock<true> Lock(*TimerLock); + tmp = DefaultTimerGroup; + if (!tmp) { + tmp = new TimerGroup("Miscellaneous Ungrouped Timers"); + sys::MemoryFence(); + DefaultTimerGroup = tmp; + } + + return tmp; +} + +//===----------------------------------------------------------------------===// +// Timer Implementation +//===----------------------------------------------------------------------===// + +void Timer::init(StringRef N) { + init(N, *getDefaultTimerGroup()); +} + +void Timer::init(StringRef N, TimerGroup &tg) { + assert(!TG && "Timer already initialized"); + Name.assign(N.begin(), N.end()); + Running = Triggered = false; + TG = &tg; + TG->addTimer(*this); +} + +Timer::~Timer() { + if (!TG) return; // Never initialized, or already cleared. + TG->removeTimer(*this); +} + +static inline size_t getMemUsage() { + if (!TrackSpace) return 0; + return sys::Process::GetMallocUsage(); +} + +TimeRecord TimeRecord::getCurrentTime(bool Start) { + TimeRecord Result; + sys::TimeValue now(0,0), user(0,0), sys(0,0); + + if (Start) { + Result.MemUsed = getMemUsage(); + sys::Process::GetTimeUsage(now, user, sys); + } else { + sys::Process::GetTimeUsage(now, user, sys); + Result.MemUsed = getMemUsage(); + } + + Result.WallTime = now.seconds() + now.microseconds() / 1000000.0; + Result.UserTime = user.seconds() + user.microseconds() / 1000000.0; + Result.SystemTime = sys.seconds() + sys.microseconds() / 1000000.0; + return Result; +} + +void Timer::startTimer() { + assert(!Running && "Cannot start a running timer"); + Running = Triggered = true; + StartTime = TimeRecord::getCurrentTime(true); +} + +void Timer::stopTimer() { + assert(Running && "Cannot stop a paused timer"); + Running = false; + Time += TimeRecord::getCurrentTime(false); + Time -= StartTime; +} + +void Timer::clear() { + Running = Triggered = false; + Time = StartTime = TimeRecord(); +} + +static void printVal(double Val, double Total, raw_ostream &OS) { + if (Total < 1e-7) // Avoid dividing by zero. + OS << " ----- "; + else + OS << format(" %7.4f (%5.1f%%)", Val, Val*100/Total); +} + +void TimeRecord::print(const TimeRecord &Total, raw_ostream &OS) const { + if (Total.getUserTime()) + printVal(getUserTime(), Total.getUserTime(), OS); + if (Total.getSystemTime()) + printVal(getSystemTime(), Total.getSystemTime(), OS); + if (Total.getProcessTime()) + printVal(getProcessTime(), Total.getProcessTime(), OS); + printVal(getWallTime(), Total.getWallTime(), OS); + + OS << " "; + + if (Total.getMemUsed()) + OS << format("%9" PRId64 " ", (int64_t)getMemUsed()); +} + + +//===----------------------------------------------------------------------===// +// NamedRegionTimer Implementation +//===----------------------------------------------------------------------===// + +namespace { + +typedef StringMap<Timer> Name2TimerMap; + +class Name2PairMap { + StringMap<std::pair<TimerGroup*, Name2TimerMap> > Map; +public: + ~Name2PairMap() { + for (StringMap<std::pair<TimerGroup*, Name2TimerMap> >::iterator + I = Map.begin(), E = Map.end(); I != E; ++I) + delete I->second.first; + } + + Timer &get(StringRef Name, StringRef GroupName) { + sys::SmartScopedLock<true> L(*TimerLock); + + std::pair<TimerGroup*, Name2TimerMap> &GroupEntry = Map[GroupName]; + + if (!GroupEntry.first) + GroupEntry.first = new TimerGroup(GroupName); + + Timer &T = GroupEntry.second[Name]; + if (!T.isInitialized()) + T.init(Name, *GroupEntry.first); + return T; + } +}; + +} + +static ManagedStatic<Name2TimerMap> NamedTimers; +static ManagedStatic<Name2PairMap> NamedGroupedTimers; + +static Timer &getNamedRegionTimer(StringRef Name) { + sys::SmartScopedLock<true> L(*TimerLock); + + Timer &T = (*NamedTimers)[Name]; + if (!T.isInitialized()) + T.init(Name); + return T; +} + +NamedRegionTimer::NamedRegionTimer(StringRef Name, + bool Enabled) + : TimeRegion(!Enabled ? nullptr : &getNamedRegionTimer(Name)) {} + +NamedRegionTimer::NamedRegionTimer(StringRef Name, StringRef GroupName, + bool Enabled) + : TimeRegion(!Enabled ? nullptr : &NamedGroupedTimers->get(Name, GroupName)){} + +//===----------------------------------------------------------------------===// +// TimerGroup Implementation +//===----------------------------------------------------------------------===// + +/// TimerGroupList - This is the global list of TimerGroups, maintained by the +/// TimerGroup ctor/dtor and is protected by the TimerLock lock. +static TimerGroup *TimerGroupList = nullptr; + +TimerGroup::TimerGroup(StringRef name) + : Name(name.begin(), name.end()), FirstTimer(nullptr) { + + // Add the group to TimerGroupList. + sys::SmartScopedLock<true> L(*TimerLock); + if (TimerGroupList) + TimerGroupList->Prev = &Next; + Next = TimerGroupList; + Prev = &TimerGroupList; + TimerGroupList = this; +} + +TimerGroup::~TimerGroup() { + // If the timer group is destroyed before the timers it owns, accumulate and + // print the timing data. + while (FirstTimer) + removeTimer(*FirstTimer); + + // Remove the group from the TimerGroupList. + sys::SmartScopedLock<true> L(*TimerLock); + *Prev = Next; + if (Next) + Next->Prev = Prev; +} + + +void TimerGroup::removeTimer(Timer &T) { + sys::SmartScopedLock<true> L(*TimerLock); + + // If the timer was started, move its data to TimersToPrint. + if (T.hasTriggered()) + TimersToPrint.emplace_back(T.Time, T.Name); + + T.TG = nullptr; + + // Unlink the timer from our list. + *T.Prev = T.Next; + if (T.Next) + T.Next->Prev = T.Prev; + + // Print the report when all timers in this group are destroyed if some of + // them were started. + if (FirstTimer || TimersToPrint.empty()) + return; + + std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile(); + PrintQueuedTimers(*OutStream); +} + +void TimerGroup::addTimer(Timer &T) { + sys::SmartScopedLock<true> L(*TimerLock); + + // Add the timer to our list. + if (FirstTimer) + FirstTimer->Prev = &T.Next; + T.Next = FirstTimer; + T.Prev = &FirstTimer; + FirstTimer = &T; +} + +void TimerGroup::PrintQueuedTimers(raw_ostream &OS) { + // Sort the timers in descending order by amount of time taken. + std::sort(TimersToPrint.begin(), TimersToPrint.end()); + + TimeRecord Total; + for (auto &RecordNamePair : TimersToPrint) + Total += RecordNamePair.first; + + // Print out timing header. + OS << "===" << std::string(73, '-') << "===\n"; + // Figure out how many spaces to indent TimerGroup name. + unsigned Padding = (80-Name.length())/2; + if (Padding > 80) Padding = 0; // Don't allow "negative" numbers + OS.indent(Padding) << Name << '\n'; + OS << "===" << std::string(73, '-') << "===\n"; + + // If this is not an collection of ungrouped times, print the total time. + // Ungrouped timers don't really make sense to add up. We still print the + // TOTAL line to make the percentages make sense. + if (this != DefaultTimerGroup) + OS << format(" Total Execution Time: %5.4f seconds (%5.4f wall clock)\n", + Total.getProcessTime(), Total.getWallTime()); + OS << '\n'; + + if (Total.getUserTime()) + OS << " ---User Time---"; + if (Total.getSystemTime()) + OS << " --System Time--"; + if (Total.getProcessTime()) + OS << " --User+System--"; + OS << " ---Wall Time---"; + if (Total.getMemUsed()) + OS << " ---Mem---"; + OS << " --- Name ---\n"; + + // Loop through all of the timing data, printing it out. + for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) { + const std::pair<TimeRecord, std::string> &Entry = TimersToPrint[e-i-1]; + Entry.first.print(Total, OS); + OS << Entry.second << '\n'; + } + + Total.print(Total, OS); + OS << "Total\n\n"; + OS.flush(); + + TimersToPrint.clear(); +} + +/// print - Print any started timers in this group and zero them. +void TimerGroup::print(raw_ostream &OS) { + sys::SmartScopedLock<true> L(*TimerLock); + + // See if any of our timers were started, if so add them to TimersToPrint and + // reset them. + for (Timer *T = FirstTimer; T; T = T->Next) { + if (!T->hasTriggered()) continue; + TimersToPrint.emplace_back(T->Time, T->Name); + + // Clear out the time. + T->clear(); + } + + // If any timers were started, print the group. + if (!TimersToPrint.empty()) + PrintQueuedTimers(OS); +} + +/// printAll - This static method prints all timers and clears them all out. +void TimerGroup::printAll(raw_ostream &OS) { + sys::SmartScopedLock<true> L(*TimerLock); + + for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next) + TG->print(OS); +}
diff --git a/third_party/llvm-subzero/lib/Support/Triple.cpp b/third_party/llvm-subzero/lib/Support/Triple.cpp new file mode 100644 index 0000000..2bac2a3 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Triple.cpp
@@ -0,0 +1,1489 @@ +//===--- Triple.cpp - Target triple helper class --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetParser.h" +#include "llvm/Support/Host.h" +#include <cstring> +using namespace llvm; + +const char *Triple::getArchTypeName(ArchType Kind) { + switch (Kind) { + case UnknownArch: return "unknown"; + + case aarch64: return "aarch64"; + case aarch64_be: return "aarch64_be"; + case arm: return "arm"; + case armeb: return "armeb"; + case avr: return "avr"; + case bpfel: return "bpfel"; + case bpfeb: return "bpfeb"; + case hexagon: return "hexagon"; + case mips: return "mips"; + case mipsel: return "mipsel"; + case mips64: return "mips64"; + case mips64el: return "mips64el"; + case msp430: return "msp430"; + case ppc64: return "powerpc64"; + case ppc64le: return "powerpc64le"; + case ppc: return "powerpc"; + case r600: return "r600"; + case amdgcn: return "amdgcn"; + case sparc: return "sparc"; + case sparcv9: return "sparcv9"; + case sparcel: return "sparcel"; + case systemz: return "s390x"; + case tce: return "tce"; + case thumb: return "thumb"; + case thumbeb: return "thumbeb"; + case x86: return "i386"; + case x86_64: return "x86_64"; + case xcore: return "xcore"; + case nvptx: return "nvptx"; + case nvptx64: return "nvptx64"; + case le32: return "le32"; + case le64: return "le64"; + case amdil: return "amdil"; + case amdil64: return "amdil64"; + case hsail: return "hsail"; + case hsail64: return "hsail64"; + case spir: return "spir"; + case spir64: return "spir64"; + case kalimba: return "kalimba"; + case lanai: return "lanai"; + case shave: return "shave"; + case wasm32: return "wasm32"; + case wasm64: return "wasm64"; + case renderscript32: return "renderscript32"; + case renderscript64: return "renderscript64"; + } + + llvm_unreachable("Invalid ArchType!"); +} + +const char *Triple::getArchTypePrefix(ArchType Kind) { + switch (Kind) { + default: + return nullptr; + + case aarch64: + case aarch64_be: return "aarch64"; + + case arm: + case armeb: + case thumb: + case thumbeb: return "arm"; + + case avr: return "avr"; + + case ppc64: + case ppc64le: + case ppc: return "ppc"; + + case mips: + case mipsel: + case mips64: + case mips64el: return "mips"; + + case hexagon: return "hexagon"; + + case amdgcn: return "amdgcn"; + case r600: return "r600"; + + case bpfel: + case bpfeb: return "bpf"; + + case sparcv9: + case sparcel: + case sparc: return "sparc"; + + case systemz: return "s390"; + + case x86: + case x86_64: return "x86"; + + case xcore: return "xcore"; + + // NVPTX intrinsics are namespaced under nvvm. + case nvptx: return "nvvm"; + case nvptx64: return "nvvm"; + + case le32: return "le32"; + case le64: return "le64"; + + case amdil: + case amdil64: return "amdil"; + + case hsail: + case hsail64: return "hsail"; + + case spir: + case spir64: return "spir"; + case kalimba: return "kalimba"; + case lanai: return "lanai"; + case shave: return "shave"; + case wasm32: + case wasm64: return "wasm"; + } +} + +const char *Triple::getVendorTypeName(VendorType Kind) { + switch (Kind) { + case UnknownVendor: return "unknown"; + + case Apple: return "apple"; + case PC: return "pc"; + case SCEI: return "scei"; + case BGP: return "bgp"; + case BGQ: return "bgq"; + case Freescale: return "fsl"; + case IBM: return "ibm"; + case ImaginationTechnologies: return "img"; + case MipsTechnologies: return "mti"; + case NVIDIA: return "nvidia"; + case CSR: return "csr"; + case Myriad: return "myriad"; + case AMD: return "amd"; + case Mesa: return "mesa"; + } + + llvm_unreachable("Invalid VendorType!"); +} + +const char *Triple::getOSTypeName(OSType Kind) { + switch (Kind) { + case UnknownOS: return "unknown"; + + case CloudABI: return "cloudabi"; + case Darwin: return "darwin"; + case DragonFly: return "dragonfly"; + case FreeBSD: return "freebsd"; + case IOS: return "ios"; + case KFreeBSD: return "kfreebsd"; + case Linux: return "linux"; + case Lv2: return "lv2"; + case MacOSX: return "macosx"; + case NetBSD: return "netbsd"; + case OpenBSD: return "openbsd"; + case Solaris: return "solaris"; + case Win32: return "windows"; + case Haiku: return "haiku"; + case Minix: return "minix"; + case RTEMS: return "rtems"; + case NaCl: return "nacl"; + case CNK: return "cnk"; + case Bitrig: return "bitrig"; + case AIX: return "aix"; + case CUDA: return "cuda"; + case NVCL: return "nvcl"; + case AMDHSA: return "amdhsa"; + case PS4: return "ps4"; + case ELFIAMCU: return "elfiamcu"; + case TvOS: return "tvos"; + case WatchOS: return "watchos"; + case Mesa3D: return "mesa3d"; + } + + llvm_unreachable("Invalid OSType"); +} + +const char *Triple::getEnvironmentTypeName(EnvironmentType Kind) { + switch (Kind) { + case UnknownEnvironment: return "unknown"; + case GNU: return "gnu"; + case GNUABI64: return "gnuabi64"; + case GNUEABIHF: return "gnueabihf"; + case GNUEABI: return "gnueabi"; + case GNUX32: return "gnux32"; + case CODE16: return "code16"; + case EABI: return "eabi"; + case EABIHF: return "eabihf"; + case Android: return "android"; + case Musl: return "musl"; + case MuslEABI: return "musleabi"; + case MuslEABIHF: return "musleabihf"; + case MSVC: return "msvc"; + case Itanium: return "itanium"; + case Cygnus: return "cygnus"; + case AMDOpenCL: return "amdopencl"; + case CoreCLR: return "coreclr"; + } + + llvm_unreachable("Invalid EnvironmentType!"); +} + +static Triple::ArchType parseBPFArch(StringRef ArchName) { + if (ArchName.equals("bpf")) { + if (sys::IsLittleEndianHost) + return Triple::bpfel; + else + return Triple::bpfeb; + } else if (ArchName.equals("bpf_be") || ArchName.equals("bpfeb")) { + return Triple::bpfeb; + } else if (ArchName.equals("bpf_le") || ArchName.equals("bpfel")) { + return Triple::bpfel; + } else { + return Triple::UnknownArch; + } +} + +Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { + Triple::ArchType BPFArch(parseBPFArch(Name)); + return StringSwitch<Triple::ArchType>(Name) + .Case("aarch64", aarch64) + .Case("aarch64_be", aarch64_be) + .Case("arm64", aarch64) // "arm64" is an alias for "aarch64" + .Case("arm", arm) + .Case("armeb", armeb) + .Case("avr", avr) + .StartsWith("bpf", BPFArch) + .Case("mips", mips) + .Case("mipsel", mipsel) + .Case("mips64", mips64) + .Case("mips64el", mips64el) + .Case("msp430", msp430) + .Case("ppc64", ppc64) + .Case("ppc32", ppc) + .Case("ppc", ppc) + .Case("ppc64le", ppc64le) + .Case("r600", r600) + .Case("amdgcn", amdgcn) + .Case("hexagon", hexagon) + .Case("sparc", sparc) + .Case("sparcel", sparcel) + .Case("sparcv9", sparcv9) + .Case("systemz", systemz) + .Case("tce", tce) + .Case("thumb", thumb) + .Case("thumbeb", thumbeb) + .Case("x86", x86) + .Case("x86-64", x86_64) + .Case("xcore", xcore) + .Case("nvptx", nvptx) + .Case("nvptx64", nvptx64) + .Case("le32", le32) + .Case("le64", le64) + .Case("amdil", amdil) + .Case("amdil64", amdil64) + .Case("hsail", hsail) + .Case("hsail64", hsail64) + .Case("spir", spir) + .Case("spir64", spir64) + .Case("kalimba", kalimba) + .Case("lanai", lanai) + .Case("shave", shave) + .Case("wasm32", wasm32) + .Case("wasm64", wasm64) + .Case("renderscript32", renderscript32) + .Case("renderscript64", renderscript64) + .Default(UnknownArch); +} + +static Triple::ArchType parseARMArch(StringRef ArchName) { + unsigned ISA = ARM::parseArchISA(ArchName); + unsigned ENDIAN = ARM::parseArchEndian(ArchName); + + Triple::ArchType arch = Triple::UnknownArch; + switch (ENDIAN) { + case ARM::EK_LITTLE: { + switch (ISA) { + case ARM::IK_ARM: + arch = Triple::arm; + break; + case ARM::IK_THUMB: + arch = Triple::thumb; + break; + case ARM::IK_AARCH64: + arch = Triple::aarch64; + break; + } + break; + } + case ARM::EK_BIG: { + switch (ISA) { + case ARM::IK_ARM: + arch = Triple::armeb; + break; + case ARM::IK_THUMB: + arch = Triple::thumbeb; + break; + case ARM::IK_AARCH64: + arch = Triple::aarch64_be; + break; + } + break; + } + } + + ArchName = ARM::getCanonicalArchName(ArchName); + if (ArchName.empty()) + return Triple::UnknownArch; + + // Thumb only exists in v4+ + if (ISA == ARM::IK_THUMB && + (ArchName.startswith("v2") || ArchName.startswith("v3"))) + return Triple::UnknownArch; + + // Thumb only for v6m + unsigned Profile = ARM::parseArchProfile(ArchName); + unsigned Version = ARM::parseArchVersion(ArchName); + if (Profile == ARM::PK_M && Version == 6) { + if (ENDIAN == ARM::EK_BIG) + return Triple::thumbeb; + else + return Triple::thumb; + } + + return arch; +} + +static Triple::ArchType parseArch(StringRef ArchName) { + auto AT = StringSwitch<Triple::ArchType>(ArchName) + .Cases("i386", "i486", "i586", "i686", Triple::x86) + // FIXME: Do we need to support these? + .Cases("i786", "i886", "i986", Triple::x86) + .Cases("amd64", "x86_64", "x86_64h", Triple::x86_64) + .Cases("powerpc", "ppc32", Triple::ppc) + .Cases("powerpc64", "ppu", "ppc64", Triple::ppc64) + .Cases("powerpc64le", "ppc64le", Triple::ppc64le) + .Case("xscale", Triple::arm) + .Case("xscaleeb", Triple::armeb) + .Case("aarch64", Triple::aarch64) + .Case("aarch64_be", Triple::aarch64_be) + .Case("arm64", Triple::aarch64) + .Case("arm", Triple::arm) + .Case("armeb", Triple::armeb) + .Case("thumb", Triple::thumb) + .Case("thumbeb", Triple::thumbeb) + .Case("avr", Triple::avr) + .Case("msp430", Triple::msp430) + .Cases("mips", "mipseb", "mipsallegrex", Triple::mips) + .Cases("mipsel", "mipsallegrexel", Triple::mipsel) + .Cases("mips64", "mips64eb", Triple::mips64) + .Case("mips64el", Triple::mips64el) + .Case("r600", Triple::r600) + .Case("amdgcn", Triple::amdgcn) + .Case("hexagon", Triple::hexagon) + .Cases("s390x", "systemz", Triple::systemz) + .Case("sparc", Triple::sparc) + .Case("sparcel", Triple::sparcel) + .Cases("sparcv9", "sparc64", Triple::sparcv9) + .Case("tce", Triple::tce) + .Case("xcore", Triple::xcore) + .Case("nvptx", Triple::nvptx) + .Case("nvptx64", Triple::nvptx64) + .Case("le32", Triple::le32) + .Case("le64", Triple::le64) + .Case("amdil", Triple::amdil) + .Case("amdil64", Triple::amdil64) + .Case("hsail", Triple::hsail) + .Case("hsail64", Triple::hsail64) + .Case("spir", Triple::spir) + .Case("spir64", Triple::spir64) + .StartsWith("kalimba", Triple::kalimba) + .Case("lanai", Triple::lanai) + .Case("shave", Triple::shave) + .Case("wasm32", Triple::wasm32) + .Case("wasm64", Triple::wasm64) + .Case("renderscript32", Triple::renderscript32) + .Case("renderscript64", Triple::renderscript64) + .Default(Triple::UnknownArch); + + // Some architectures require special parsing logic just to compute the + // ArchType result. + if (AT == Triple::UnknownArch) { + if (ArchName.startswith("arm") || ArchName.startswith("thumb") || + ArchName.startswith("aarch64")) + return parseARMArch(ArchName); + if (ArchName.startswith("bpf")) + return parseBPFArch(ArchName); + } + + return AT; +} + +static Triple::VendorType parseVendor(StringRef VendorName) { + return StringSwitch<Triple::VendorType>(VendorName) + .Case("apple", Triple::Apple) + .Case("pc", Triple::PC) + .Case("scei", Triple::SCEI) + .Case("bgp", Triple::BGP) + .Case("bgq", Triple::BGQ) + .Case("fsl", Triple::Freescale) + .Case("ibm", Triple::IBM) + .Case("img", Triple::ImaginationTechnologies) + .Case("mti", Triple::MipsTechnologies) + .Case("nvidia", Triple::NVIDIA) + .Case("csr", Triple::CSR) + .Case("myriad", Triple::Myriad) + .Case("amd", Triple::AMD) + .Case("mesa", Triple::Mesa) + .Default(Triple::UnknownVendor); +} + +static Triple::OSType parseOS(StringRef OSName) { + return StringSwitch<Triple::OSType>(OSName) + .StartsWith("cloudabi", Triple::CloudABI) + .StartsWith("darwin", Triple::Darwin) + .StartsWith("dragonfly", Triple::DragonFly) + .StartsWith("freebsd", Triple::FreeBSD) + .StartsWith("ios", Triple::IOS) + .StartsWith("kfreebsd", Triple::KFreeBSD) + .StartsWith("linux", Triple::Linux) + .StartsWith("lv2", Triple::Lv2) + .StartsWith("macosx", Triple::MacOSX) + .StartsWith("netbsd", Triple::NetBSD) + .StartsWith("openbsd", Triple::OpenBSD) + .StartsWith("solaris", Triple::Solaris) + .StartsWith("win32", Triple::Win32) + .StartsWith("windows", Triple::Win32) + .StartsWith("haiku", Triple::Haiku) + .StartsWith("minix", Triple::Minix) + .StartsWith("rtems", Triple::RTEMS) + .StartsWith("nacl", Triple::NaCl) + .StartsWith("cnk", Triple::CNK) + .StartsWith("bitrig", Triple::Bitrig) + .StartsWith("aix", Triple::AIX) + .StartsWith("cuda", Triple::CUDA) + .StartsWith("nvcl", Triple::NVCL) + .StartsWith("amdhsa", Triple::AMDHSA) + .StartsWith("ps4", Triple::PS4) + .StartsWith("elfiamcu", Triple::ELFIAMCU) + .StartsWith("tvos", Triple::TvOS) + .StartsWith("watchos", Triple::WatchOS) + .StartsWith("mesa3d", Triple::Mesa3D) + .Default(Triple::UnknownOS); +} + +static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) { + return StringSwitch<Triple::EnvironmentType>(EnvironmentName) + .StartsWith("eabihf", Triple::EABIHF) + .StartsWith("eabi", Triple::EABI) + .StartsWith("gnuabi64", Triple::GNUABI64) + .StartsWith("gnueabihf", Triple::GNUEABIHF) + .StartsWith("gnueabi", Triple::GNUEABI) + .StartsWith("gnux32", Triple::GNUX32) + .StartsWith("code16", Triple::CODE16) + .StartsWith("gnu", Triple::GNU) + .StartsWith("android", Triple::Android) + .StartsWith("musleabihf", Triple::MuslEABIHF) + .StartsWith("musleabi", Triple::MuslEABI) + .StartsWith("musl", Triple::Musl) + .StartsWith("msvc", Triple::MSVC) + .StartsWith("itanium", Triple::Itanium) + .StartsWith("cygnus", Triple::Cygnus) + .StartsWith("amdopencl", Triple::AMDOpenCL) + .StartsWith("coreclr", Triple::CoreCLR) + .Default(Triple::UnknownEnvironment); +} + +static Triple::ObjectFormatType parseFormat(StringRef EnvironmentName) { + return StringSwitch<Triple::ObjectFormatType>(EnvironmentName) + .EndsWith("coff", Triple::COFF) + .EndsWith("elf", Triple::ELF) + .EndsWith("macho", Triple::MachO) + .Default(Triple::UnknownObjectFormat); +} + +static Triple::SubArchType parseSubArch(StringRef SubArchName) { + StringRef ARMSubArch = ARM::getCanonicalArchName(SubArchName); + + // For now, this is the small part. Early return. + if (ARMSubArch.empty()) + return StringSwitch<Triple::SubArchType>(SubArchName) + .EndsWith("kalimba3", Triple::KalimbaSubArch_v3) + .EndsWith("kalimba4", Triple::KalimbaSubArch_v4) + .EndsWith("kalimba5", Triple::KalimbaSubArch_v5) + .Default(Triple::NoSubArch); + + // ARM sub arch. + switch(ARM::parseArch(ARMSubArch)) { + case ARM::AK_ARMV4: + return Triple::NoSubArch; + case ARM::AK_ARMV4T: + return Triple::ARMSubArch_v4t; + case ARM::AK_ARMV5T: + return Triple::ARMSubArch_v5; + case ARM::AK_ARMV5TE: + case ARM::AK_IWMMXT: + case ARM::AK_IWMMXT2: + case ARM::AK_XSCALE: + case ARM::AK_ARMV5TEJ: + return Triple::ARMSubArch_v5te; + case ARM::AK_ARMV6: + return Triple::ARMSubArch_v6; + case ARM::AK_ARMV6K: + case ARM::AK_ARMV6KZ: + return Triple::ARMSubArch_v6k; + case ARM::AK_ARMV6T2: + return Triple::ARMSubArch_v6t2; + case ARM::AK_ARMV6M: + return Triple::ARMSubArch_v6m; + case ARM::AK_ARMV7A: + case ARM::AK_ARMV7R: + return Triple::ARMSubArch_v7; + case ARM::AK_ARMV7K: + return Triple::ARMSubArch_v7k; + case ARM::AK_ARMV7M: + return Triple::ARMSubArch_v7m; + case ARM::AK_ARMV7S: + return Triple::ARMSubArch_v7s; + case ARM::AK_ARMV7EM: + return Triple::ARMSubArch_v7em; + case ARM::AK_ARMV8A: + return Triple::ARMSubArch_v8; + case ARM::AK_ARMV8_1A: + return Triple::ARMSubArch_v8_1a; + case ARM::AK_ARMV8_2A: + return Triple::ARMSubArch_v8_2a; + case ARM::AK_ARMV8MBaseline: + return Triple::ARMSubArch_v8m_baseline; + case ARM::AK_ARMV8MMainline: + return Triple::ARMSubArch_v8m_mainline; + default: + return Triple::NoSubArch; + } +} + +static const char *getObjectFormatTypeName(Triple::ObjectFormatType Kind) { + switch (Kind) { + case Triple::UnknownObjectFormat: return ""; + case Triple::COFF: return "coff"; + case Triple::ELF: return "elf"; + case Triple::MachO: return "macho"; + } + llvm_unreachable("unknown object format type"); +} + +static Triple::ObjectFormatType getDefaultFormat(const Triple &T) { + switch (T.getArch()) { + case Triple::UnknownArch: + case Triple::aarch64: + case Triple::arm: + case Triple::thumb: + case Triple::x86: + case Triple::x86_64: + if (T.isOSDarwin()) + return Triple::MachO; + else if (T.isOSWindows()) + return Triple::COFF; + return Triple::ELF; + + case Triple::aarch64_be: + case Triple::amdgcn: + case Triple::amdil: + case Triple::amdil64: + case Triple::armeb: + case Triple::avr: + case Triple::bpfeb: + case Triple::bpfel: + case Triple::hexagon: + case Triple::lanai: + case Triple::hsail: + case Triple::hsail64: + case Triple::kalimba: + case Triple::le32: + case Triple::le64: + case Triple::mips: + case Triple::mips64: + case Triple::mips64el: + case Triple::mipsel: + case Triple::msp430: + case Triple::nvptx: + case Triple::nvptx64: + case Triple::ppc64le: + case Triple::r600: + case Triple::renderscript32: + case Triple::renderscript64: + case Triple::shave: + case Triple::sparc: + case Triple::sparcel: + case Triple::sparcv9: + case Triple::spir: + case Triple::spir64: + case Triple::systemz: + case Triple::tce: + case Triple::thumbeb: + case Triple::wasm32: + case Triple::wasm64: + case Triple::xcore: + return Triple::ELF; + + case Triple::ppc: + case Triple::ppc64: + if (T.isOSDarwin()) + return Triple::MachO; + return Triple::ELF; + } + llvm_unreachable("unknown architecture"); +} + +/// \brief Construct a triple from the string representation provided. +/// +/// This stores the string representation and parses the various pieces into +/// enum members. +Triple::Triple(const Twine &Str) + : Data(Str.str()), Arch(UnknownArch), SubArch(NoSubArch), + Vendor(UnknownVendor), OS(UnknownOS), Environment(UnknownEnvironment), + ObjectFormat(UnknownObjectFormat) { + // Do minimal parsing by hand here. + SmallVector<StringRef, 4> Components; + StringRef(Data).split(Components, '-', /*MaxSplit*/ 3); + if (Components.size() > 0) { + Arch = parseArch(Components[0]); + SubArch = parseSubArch(Components[0]); + if (Components.size() > 1) { + Vendor = parseVendor(Components[1]); + if (Components.size() > 2) { + OS = parseOS(Components[2]); + if (Components.size() > 3) { + Environment = parseEnvironment(Components[3]); + ObjectFormat = parseFormat(Components[3]); + } + } + } + } + if (ObjectFormat == UnknownObjectFormat) + ObjectFormat = getDefaultFormat(*this); +} + +/// \brief Construct a triple from string representations of the architecture, +/// vendor, and OS. +/// +/// This joins each argument into a canonical string representation and parses +/// them into enum members. It leaves the environment unknown and omits it from +/// the string representation. +Triple::Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr) + : Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr).str()), + Arch(parseArch(ArchStr.str())), + SubArch(parseSubArch(ArchStr.str())), + Vendor(parseVendor(VendorStr.str())), + OS(parseOS(OSStr.str())), + Environment(), ObjectFormat(Triple::UnknownObjectFormat) { + ObjectFormat = getDefaultFormat(*this); +} + +/// \brief Construct a triple from string representations of the architecture, +/// vendor, OS, and environment. +/// +/// This joins each argument into a canonical string representation and parses +/// them into enum members. +Triple::Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr, + const Twine &EnvironmentStr) + : Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr + Twine('-') + + EnvironmentStr).str()), + Arch(parseArch(ArchStr.str())), + SubArch(parseSubArch(ArchStr.str())), + Vendor(parseVendor(VendorStr.str())), + OS(parseOS(OSStr.str())), + Environment(parseEnvironment(EnvironmentStr.str())), + ObjectFormat(parseFormat(EnvironmentStr.str())) { + if (ObjectFormat == Triple::UnknownObjectFormat) + ObjectFormat = getDefaultFormat(*this); +} + +std::string Triple::normalize(StringRef Str) { + bool IsMinGW32 = false; + bool IsCygwin = false; + + // Parse into components. + SmallVector<StringRef, 4> Components; + Str.split(Components, '-'); + + // If the first component corresponds to a known architecture, preferentially + // use it for the architecture. If the second component corresponds to a + // known vendor, preferentially use it for the vendor, etc. This avoids silly + // component movement when a component parses as (eg) both a valid arch and a + // valid os. + ArchType Arch = UnknownArch; + if (Components.size() > 0) + Arch = parseArch(Components[0]); + VendorType Vendor = UnknownVendor; + if (Components.size() > 1) + Vendor = parseVendor(Components[1]); + OSType OS = UnknownOS; + if (Components.size() > 2) { + OS = parseOS(Components[2]); + IsCygwin = Components[2].startswith("cygwin"); + IsMinGW32 = Components[2].startswith("mingw"); + } + EnvironmentType Environment = UnknownEnvironment; + if (Components.size() > 3) + Environment = parseEnvironment(Components[3]); + ObjectFormatType ObjectFormat = UnknownObjectFormat; + if (Components.size() > 4) + ObjectFormat = parseFormat(Components[4]); + + // Note which components are already in their final position. These will not + // be moved. + bool Found[4]; + Found[0] = Arch != UnknownArch; + Found[1] = Vendor != UnknownVendor; + Found[2] = OS != UnknownOS; + Found[3] = Environment != UnknownEnvironment; + + // If they are not there already, permute the components into their canonical + // positions by seeing if they parse as a valid architecture, and if so moving + // the component to the architecture position etc. + for (unsigned Pos = 0; Pos != array_lengthof(Found); ++Pos) { + if (Found[Pos]) + continue; // Already in the canonical position. + + for (unsigned Idx = 0; Idx != Components.size(); ++Idx) { + // Do not reparse any components that already matched. + if (Idx < array_lengthof(Found) && Found[Idx]) + continue; + + // Does this component parse as valid for the target position? + bool Valid = false; + StringRef Comp = Components[Idx]; + switch (Pos) { + default: llvm_unreachable("unexpected component type!"); + case 0: + Arch = parseArch(Comp); + Valid = Arch != UnknownArch; + break; + case 1: + Vendor = parseVendor(Comp); + Valid = Vendor != UnknownVendor; + break; + case 2: + OS = parseOS(Comp); + IsCygwin = Comp.startswith("cygwin"); + IsMinGW32 = Comp.startswith("mingw"); + Valid = OS != UnknownOS || IsCygwin || IsMinGW32; + break; + case 3: + Environment = parseEnvironment(Comp); + Valid = Environment != UnknownEnvironment; + if (!Valid) { + ObjectFormat = parseFormat(Comp); + Valid = ObjectFormat != UnknownObjectFormat; + } + break; + } + if (!Valid) + continue; // Nope, try the next component. + + // Move the component to the target position, pushing any non-fixed + // components that are in the way to the right. This tends to give + // good results in the common cases of a forgotten vendor component + // or a wrongly positioned environment. + if (Pos < Idx) { + // Insert left, pushing the existing components to the right. For + // example, a-b-i386 -> i386-a-b when moving i386 to the front. + StringRef CurrentComponent(""); // The empty component. + // Replace the component we are moving with an empty component. + std::swap(CurrentComponent, Components[Idx]); + // Insert the component being moved at Pos, displacing any existing + // components to the right. + for (unsigned i = Pos; !CurrentComponent.empty(); ++i) { + // Skip over any fixed components. + while (i < array_lengthof(Found) && Found[i]) + ++i; + // Place the component at the new position, getting the component + // that was at this position - it will be moved right. + std::swap(CurrentComponent, Components[i]); + } + } else if (Pos > Idx) { + // Push right by inserting empty components until the component at Idx + // reaches the target position Pos. For example, pc-a -> -pc-a when + // moving pc to the second position. + do { + // Insert one empty component at Idx. + StringRef CurrentComponent(""); // The empty component. + for (unsigned i = Idx; i < Components.size();) { + // Place the component at the new position, getting the component + // that was at this position - it will be moved right. + std::swap(CurrentComponent, Components[i]); + // If it was placed on top of an empty component then we are done. + if (CurrentComponent.empty()) + break; + // Advance to the next component, skipping any fixed components. + while (++i < array_lengthof(Found) && Found[i]) + ; + } + // The last component was pushed off the end - append it. + if (!CurrentComponent.empty()) + Components.push_back(CurrentComponent); + + // Advance Idx to the component's new position. + while (++Idx < array_lengthof(Found) && Found[Idx]) + ; + } while (Idx < Pos); // Add more until the final position is reached. + } + assert(Pos < Components.size() && Components[Pos] == Comp && + "Component moved wrong!"); + Found[Pos] = true; + break; + } + } + + // Special case logic goes here. At this point Arch, Vendor and OS have the + // correct values for the computed components. + std::string NormalizedEnvironment; + if (Environment == Triple::Android && Components[3].startswith("androideabi")) { + StringRef AndroidVersion = Components[3].drop_front(strlen("androideabi")); + if (AndroidVersion.empty()) { + Components[3] = "android"; + } else { + NormalizedEnvironment = Twine("android", AndroidVersion).str(); + Components[3] = NormalizedEnvironment; + } + } + + if (OS == Triple::Win32) { + Components.resize(4); + Components[2] = "windows"; + if (Environment == UnknownEnvironment) { + if (ObjectFormat == UnknownObjectFormat || ObjectFormat == Triple::COFF) + Components[3] = "msvc"; + else + Components[3] = getObjectFormatTypeName(ObjectFormat); + } + } else if (IsMinGW32) { + Components.resize(4); + Components[2] = "windows"; + Components[3] = "gnu"; + } else if (IsCygwin) { + Components.resize(4); + Components[2] = "windows"; + Components[3] = "cygnus"; + } + if (IsMinGW32 || IsCygwin || + (OS == Triple::Win32 && Environment != UnknownEnvironment)) { + if (ObjectFormat != UnknownObjectFormat && ObjectFormat != Triple::COFF) { + Components.resize(5); + Components[4] = getObjectFormatTypeName(ObjectFormat); + } + } + + // Stick the corrected components back together to form the normalized string. + std::string Normalized; + for (unsigned i = 0, e = Components.size(); i != e; ++i) { + if (i) Normalized += '-'; + Normalized += Components[i]; + } + return Normalized; +} + +StringRef Triple::getArchName() const { + return StringRef(Data).split('-').first; // Isolate first component +} + +StringRef Triple::getVendorName() const { + StringRef Tmp = StringRef(Data).split('-').second; // Strip first component + return Tmp.split('-').first; // Isolate second component +} + +StringRef Triple::getOSName() const { + StringRef Tmp = StringRef(Data).split('-').second; // Strip first component + Tmp = Tmp.split('-').second; // Strip second component + return Tmp.split('-').first; // Isolate third component +} + +StringRef Triple::getEnvironmentName() const { + StringRef Tmp = StringRef(Data).split('-').second; // Strip first component + Tmp = Tmp.split('-').second; // Strip second component + return Tmp.split('-').second; // Strip third component +} + +StringRef Triple::getOSAndEnvironmentName() const { + StringRef Tmp = StringRef(Data).split('-').second; // Strip first component + return Tmp.split('-').second; // Strip second component +} + +static unsigned EatNumber(StringRef &Str) { + assert(!Str.empty() && Str[0] >= '0' && Str[0] <= '9' && "Not a number"); + unsigned Result = 0; + + do { + // Consume the leading digit. + Result = Result*10 + (Str[0] - '0'); + + // Eat the digit. + Str = Str.substr(1); + } while (!Str.empty() && Str[0] >= '0' && Str[0] <= '9'); + + return Result; +} + +static void parseVersionFromName(StringRef Name, unsigned &Major, + unsigned &Minor, unsigned &Micro) { + // Any unset version defaults to 0. + Major = Minor = Micro = 0; + + // Parse up to three components. + unsigned *Components[3] = {&Major, &Minor, &Micro}; + for (unsigned i = 0; i != 3; ++i) { + if (Name.empty() || Name[0] < '0' || Name[0] > '9') + break; + + // Consume the leading number. + *Components[i] = EatNumber(Name); + + // Consume the separator, if present. + if (Name.startswith(".")) + Name = Name.substr(1); + } +} + +void Triple::getEnvironmentVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const { + StringRef EnvironmentName = getEnvironmentName(); + StringRef EnvironmentTypeName = getEnvironmentTypeName(getEnvironment()); + if (EnvironmentName.startswith(EnvironmentTypeName)) + EnvironmentName = EnvironmentName.substr(EnvironmentTypeName.size()); + + parseVersionFromName(EnvironmentName, Major, Minor, Micro); +} + +void Triple::getOSVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const { + StringRef OSName = getOSName(); + // Assume that the OS portion of the triple starts with the canonical name. + StringRef OSTypeName = getOSTypeName(getOS()); + if (OSName.startswith(OSTypeName)) + OSName = OSName.substr(OSTypeName.size()); + + parseVersionFromName(OSName, Major, Minor, Micro); +} + +bool Triple::getMacOSXVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const { + getOSVersion(Major, Minor, Micro); + + switch (getOS()) { + default: llvm_unreachable("unexpected OS for Darwin triple"); + case Darwin: + // Default to darwin8, i.e., MacOSX 10.4. + if (Major == 0) + Major = 8; + // Darwin version numbers are skewed from OS X versions. + if (Major < 4) + return false; + Micro = 0; + Minor = Major - 4; + Major = 10; + break; + case MacOSX: + // Default to 10.4. + if (Major == 0) { + Major = 10; + Minor = 4; + } + if (Major != 10) + return false; + break; + case IOS: + case TvOS: + case WatchOS: + // Ignore the version from the triple. This is only handled because the + // the clang driver combines OS X and IOS support into a common Darwin + // toolchain that wants to know the OS X version number even when targeting + // IOS. + Major = 10; + Minor = 4; + Micro = 0; + break; + } + return true; +} + +void Triple::getiOSVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const { + switch (getOS()) { + default: llvm_unreachable("unexpected OS for Darwin triple"); + case Darwin: + case MacOSX: + // Ignore the version from the triple. This is only handled because the + // the clang driver combines OS X and IOS support into a common Darwin + // toolchain that wants to know the iOS version number even when targeting + // OS X. + Major = 5; + Minor = 0; + Micro = 0; + break; + case IOS: + case TvOS: + getOSVersion(Major, Minor, Micro); + // Default to 5.0 (or 7.0 for arm64). + if (Major == 0) + Major = (getArch() == aarch64) ? 7 : 5; + break; + case WatchOS: + llvm_unreachable("conflicting triple info"); + } +} + +void Triple::getWatchOSVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const { + switch (getOS()) { + default: llvm_unreachable("unexpected OS for Darwin triple"); + case Darwin: + case MacOSX: + // Ignore the version from the triple. This is only handled because the + // the clang driver combines OS X and IOS support into a common Darwin + // toolchain that wants to know the iOS version number even when targeting + // OS X. + Major = 2; + Minor = 0; + Micro = 0; + break; + case WatchOS: + getOSVersion(Major, Minor, Micro); + if (Major == 0) + Major = 2; + break; + case IOS: + llvm_unreachable("conflicting triple info"); + } +} + +void Triple::setTriple(const Twine &Str) { + *this = Triple(Str); +} + +void Triple::setArch(ArchType Kind) { + setArchName(getArchTypeName(Kind)); +} + +void Triple::setVendor(VendorType Kind) { + setVendorName(getVendorTypeName(Kind)); +} + +void Triple::setOS(OSType Kind) { + setOSName(getOSTypeName(Kind)); +} + +void Triple::setEnvironment(EnvironmentType Kind) { + if (ObjectFormat == getDefaultFormat(*this)) + return setEnvironmentName(getEnvironmentTypeName(Kind)); + + setEnvironmentName((getEnvironmentTypeName(Kind) + Twine("-") + + getObjectFormatTypeName(ObjectFormat)).str()); +} + +void Triple::setObjectFormat(ObjectFormatType Kind) { + if (Environment == UnknownEnvironment) + return setEnvironmentName(getObjectFormatTypeName(Kind)); + + setEnvironmentName((getEnvironmentTypeName(Environment) + Twine("-") + + getObjectFormatTypeName(Kind)).str()); +} + +void Triple::setArchName(StringRef Str) { + // Work around a miscompilation bug for Twines in gcc 4.0.3. + SmallString<64> Triple; + Triple += Str; + Triple += "-"; + Triple += getVendorName(); + Triple += "-"; + Triple += getOSAndEnvironmentName(); + setTriple(Triple); +} + +void Triple::setVendorName(StringRef Str) { + setTriple(getArchName() + "-" + Str + "-" + getOSAndEnvironmentName()); +} + +void Triple::setOSName(StringRef Str) { + if (hasEnvironment()) + setTriple(getArchName() + "-" + getVendorName() + "-" + Str + + "-" + getEnvironmentName()); + else + setTriple(getArchName() + "-" + getVendorName() + "-" + Str); +} + +void Triple::setEnvironmentName(StringRef Str) { + setTriple(getArchName() + "-" + getVendorName() + "-" + getOSName() + + "-" + Str); +} + +void Triple::setOSAndEnvironmentName(StringRef Str) { + setTriple(getArchName() + "-" + getVendorName() + "-" + Str); +} + +static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) { + switch (Arch) { + case llvm::Triple::UnknownArch: + return 0; + + case llvm::Triple::avr: + case llvm::Triple::msp430: + return 16; + + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::hexagon: + case llvm::Triple::le32: + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::nvptx: + case llvm::Triple::ppc: + case llvm::Triple::r600: + case llvm::Triple::sparc: + case llvm::Triple::sparcel: + case llvm::Triple::tce: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + case llvm::Triple::x86: + case llvm::Triple::xcore: + case llvm::Triple::amdil: + case llvm::Triple::hsail: + case llvm::Triple::spir: + case llvm::Triple::kalimba: + case llvm::Triple::lanai: + case llvm::Triple::shave: + case llvm::Triple::wasm32: + case llvm::Triple::renderscript32: + return 32; + + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: + case llvm::Triple::amdgcn: + case llvm::Triple::bpfel: + case llvm::Triple::bpfeb: + case llvm::Triple::le64: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + case llvm::Triple::nvptx64: + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: + case llvm::Triple::sparcv9: + case llvm::Triple::systemz: + case llvm::Triple::x86_64: + case llvm::Triple::amdil64: + case llvm::Triple::hsail64: + case llvm::Triple::spir64: + case llvm::Triple::wasm64: + case llvm::Triple::renderscript64: + return 64; + } + llvm_unreachable("Invalid architecture value"); +} + +bool Triple::isArch64Bit() const { + return getArchPointerBitWidth(getArch()) == 64; +} + +bool Triple::isArch32Bit() const { + return getArchPointerBitWidth(getArch()) == 32; +} + +bool Triple::isArch16Bit() const { + return getArchPointerBitWidth(getArch()) == 16; +} + +Triple Triple::get32BitArchVariant() const { + Triple T(*this); + switch (getArch()) { + case Triple::UnknownArch: + case Triple::amdgcn: + case Triple::avr: + case Triple::bpfel: + case Triple::bpfeb: + case Triple::msp430: + case Triple::systemz: + case Triple::ppc64le: + T.setArch(UnknownArch); + break; + + case Triple::amdil: + case Triple::hsail: + case Triple::spir: + case Triple::arm: + case Triple::armeb: + case Triple::hexagon: + case Triple::kalimba: + case Triple::le32: + case Triple::mips: + case Triple::mipsel: + case Triple::nvptx: + case Triple::ppc: + case Triple::r600: + case Triple::sparc: + case Triple::sparcel: + case Triple::tce: + case Triple::thumb: + case Triple::thumbeb: + case Triple::x86: + case Triple::xcore: + case Triple::lanai: + case Triple::shave: + case Triple::wasm32: + case Triple::renderscript32: + // Already 32-bit. + break; + + case Triple::aarch64: T.setArch(Triple::arm); break; + case Triple::aarch64_be: T.setArch(Triple::armeb); break; + case Triple::le64: T.setArch(Triple::le32); break; + case Triple::mips64: T.setArch(Triple::mips); break; + case Triple::mips64el: T.setArch(Triple::mipsel); break; + case Triple::nvptx64: T.setArch(Triple::nvptx); break; + case Triple::ppc64: T.setArch(Triple::ppc); break; + case Triple::sparcv9: T.setArch(Triple::sparc); break; + case Triple::x86_64: T.setArch(Triple::x86); break; + case Triple::amdil64: T.setArch(Triple::amdil); break; + case Triple::hsail64: T.setArch(Triple::hsail); break; + case Triple::spir64: T.setArch(Triple::spir); break; + case Triple::wasm64: T.setArch(Triple::wasm32); break; + case Triple::renderscript64: T.setArch(Triple::renderscript32); break; + } + return T; +} + +Triple Triple::get64BitArchVariant() const { + Triple T(*this); + switch (getArch()) { + case Triple::UnknownArch: + case Triple::avr: + case Triple::hexagon: + case Triple::kalimba: + case Triple::lanai: + case Triple::msp430: + case Triple::r600: + case Triple::tce: + case Triple::xcore: + case Triple::sparcel: + case Triple::shave: + T.setArch(UnknownArch); + break; + + case Triple::aarch64: + case Triple::aarch64_be: + case Triple::bpfel: + case Triple::bpfeb: + case Triple::le64: + case Triple::amdil64: + case Triple::amdgcn: + case Triple::hsail64: + case Triple::spir64: + case Triple::mips64: + case Triple::mips64el: + case Triple::nvptx64: + case Triple::ppc64: + case Triple::ppc64le: + case Triple::sparcv9: + case Triple::systemz: + case Triple::x86_64: + case Triple::wasm64: + case Triple::renderscript64: + // Already 64-bit. + break; + + case Triple::arm: T.setArch(Triple::aarch64); break; + case Triple::armeb: T.setArch(Triple::aarch64_be); break; + case Triple::le32: T.setArch(Triple::le64); break; + case Triple::mips: T.setArch(Triple::mips64); break; + case Triple::mipsel: T.setArch(Triple::mips64el); break; + case Triple::nvptx: T.setArch(Triple::nvptx64); break; + case Triple::ppc: T.setArch(Triple::ppc64); break; + case Triple::sparc: T.setArch(Triple::sparcv9); break; + case Triple::x86: T.setArch(Triple::x86_64); break; + case Triple::amdil: T.setArch(Triple::amdil64); break; + case Triple::hsail: T.setArch(Triple::hsail64); break; + case Triple::spir: T.setArch(Triple::spir64); break; + case Triple::thumb: T.setArch(Triple::aarch64); break; + case Triple::thumbeb: T.setArch(Triple::aarch64_be); break; + case Triple::wasm32: T.setArch(Triple::wasm64); break; + case Triple::renderscript32: T.setArch(Triple::renderscript64); break; + } + return T; +} + +Triple Triple::getBigEndianArchVariant() const { + Triple T(*this); + // Already big endian. + if (!isLittleEndian()) + return T; + switch (getArch()) { + case Triple::UnknownArch: + case Triple::amdgcn: + case Triple::amdil64: + case Triple::amdil: + case Triple::avr: + case Triple::hexagon: + case Triple::hsail64: + case Triple::hsail: + case Triple::kalimba: + case Triple::le32: + case Triple::le64: + case Triple::msp430: + case Triple::nvptx64: + case Triple::nvptx: + case Triple::r600: + case Triple::shave: + case Triple::spir64: + case Triple::spir: + case Triple::wasm32: + case Triple::wasm64: + case Triple::x86: + case Triple::x86_64: + case Triple::xcore: + case Triple::renderscript32: + case Triple::renderscript64: + + // ARM is intentionally unsupported here, changing the architecture would + // drop any arch suffixes. + case Triple::arm: + case Triple::thumb: + T.setArch(UnknownArch); + break; + + case Triple::aarch64: T.setArch(Triple::aarch64_be); break; + case Triple::bpfel: T.setArch(Triple::bpfeb); break; + case Triple::mips64el:T.setArch(Triple::mips64); break; + case Triple::mipsel: T.setArch(Triple::mips); break; + case Triple::ppc64le: T.setArch(Triple::ppc64); break; + case Triple::sparcel: T.setArch(Triple::sparc); break; + default: + llvm_unreachable("getBigEndianArchVariant: unknown triple."); + } + return T; +} + +Triple Triple::getLittleEndianArchVariant() const { + Triple T(*this); + if (isLittleEndian()) + return T; + + switch (getArch()) { + case Triple::UnknownArch: + case Triple::lanai: + case Triple::ppc: + case Triple::sparcv9: + case Triple::systemz: + case Triple::tce: + + // ARM is intentionally unsupported here, changing the architecture would + // drop any arch suffixes. + case Triple::armeb: + case Triple::thumbeb: + T.setArch(UnknownArch); + break; + + case Triple::aarch64_be: T.setArch(Triple::aarch64); break; + case Triple::bpfeb: T.setArch(Triple::bpfel); break; + case Triple::mips64: T.setArch(Triple::mips64el); break; + case Triple::mips: T.setArch(Triple::mipsel); break; + case Triple::ppc64: T.setArch(Triple::ppc64le); break; + case Triple::sparc: T.setArch(Triple::sparcel); break; + default: + llvm_unreachable("getLittleEndianArchVariant: unknown triple."); + } + return T; +} + +bool Triple::isLittleEndian() const { + switch (getArch()) { + case Triple::aarch64: + case Triple::amdgcn: + case Triple::amdil64: + case Triple::amdil: + case Triple::arm: + case Triple::avr: + case Triple::bpfel: + case Triple::hexagon: + case Triple::hsail64: + case Triple::hsail: + case Triple::kalimba: + case Triple::le32: + case Triple::le64: + case Triple::mips64el: + case Triple::mipsel: + case Triple::msp430: + case Triple::nvptx64: + case Triple::nvptx: + case Triple::ppc64le: + case Triple::r600: + case Triple::shave: + case Triple::sparcel: + case Triple::spir64: + case Triple::spir: + case Triple::thumb: + case Triple::wasm32: + case Triple::wasm64: + case Triple::x86: + case Triple::x86_64: + case Triple::xcore: + case Triple::renderscript32: + case Triple::renderscript64: + return true; + default: + return false; + } +} + +StringRef Triple::getARMCPUForArch(StringRef MArch) const { + if (MArch.empty()) + MArch = getArchName(); + MArch = ARM::getCanonicalArchName(MArch); + + // Some defaults are forced. + switch (getOS()) { + case llvm::Triple::FreeBSD: + case llvm::Triple::NetBSD: + if (!MArch.empty() && MArch == "v6") + return "arm1176jzf-s"; + break; + case llvm::Triple::Win32: + // FIXME: this is invalid for WindowsCE + return "cortex-a9"; + case llvm::Triple::MacOSX: + case llvm::Triple::IOS: + case llvm::Triple::WatchOS: + case llvm::Triple::TvOS: + if (MArch == "v7k") + return "cortex-a7"; + break; + default: + break; + } + + if (MArch.empty()) + return StringRef(); + + StringRef CPU = ARM::getDefaultCPU(MArch); + if (!CPU.empty()) + return CPU; + + // If no specific architecture version is requested, return the minimum CPU + // required by the OS and environment. + switch (getOS()) { + case llvm::Triple::NetBSD: + switch (getEnvironment()) { + case llvm::Triple::GNUEABIHF: + case llvm::Triple::GNUEABI: + case llvm::Triple::EABIHF: + case llvm::Triple::EABI: + return "arm926ej-s"; + default: + return "strongarm"; + } + case llvm::Triple::NaCl: + return "cortex-a8"; + default: + switch (getEnvironment()) { + case llvm::Triple::EABIHF: + case llvm::Triple::GNUEABIHF: + case llvm::Triple::MuslEABIHF: + return "arm1176jzf-s"; + default: + return "arm7tdmi"; + } + } + + llvm_unreachable("invalid arch name"); +}
diff --git a/third_party/llvm-subzero/lib/Support/Twine.cpp b/third_party/llvm-subzero/lib/Support/Twine.cpp new file mode 100644 index 0000000..5e989fb --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Twine.cpp
@@ -0,0 +1,170 @@ +//===-- Twine.cpp - Fast Temporary String Concatenation -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Twine.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +std::string Twine::str() const { + // If we're storing only a std::string, just return it. + if (LHSKind == StdStringKind && RHSKind == EmptyKind) + return *LHS.stdString; + + // Otherwise, flatten and copy the contents first. + SmallString<256> Vec; + return toStringRef(Vec).str(); +} + +void Twine::toVector(SmallVectorImpl<char> &Out) const { + raw_svector_ostream OS(Out); + print(OS); +} + +StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const { + if (isUnary()) { + switch (getLHSKind()) { + case CStringKind: + // Already null terminated, yay! + return StringRef(LHS.cString); + case StdStringKind: { + const std::string *str = LHS.stdString; + return StringRef(str->c_str(), str->size()); + } + default: + break; + } + } + toVector(Out); + Out.push_back(0); + Out.pop_back(); + return StringRef(Out.data(), Out.size()); +} + +void Twine::printOneChild(raw_ostream &OS, Child Ptr, + NodeKind Kind) const { + switch (Kind) { + case Twine::NullKind: break; + case Twine::EmptyKind: break; + case Twine::TwineKind: + Ptr.twine->print(OS); + break; + case Twine::CStringKind: + OS << Ptr.cString; + break; + case Twine::StdStringKind: + OS << *Ptr.stdString; + break; + case Twine::StringRefKind: + OS << *Ptr.stringRef; + break; + case Twine::SmallStringKind: + OS << *Ptr.smallString; + break; + case Twine::CharKind: + OS << Ptr.character; + break; + case Twine::DecUIKind: + OS << Ptr.decUI; + break; + case Twine::DecIKind: + OS << Ptr.decI; + break; + case Twine::DecULKind: + OS << *Ptr.decUL; + break; + case Twine::DecLKind: + OS << *Ptr.decL; + break; + case Twine::DecULLKind: + OS << *Ptr.decULL; + break; + case Twine::DecLLKind: + OS << *Ptr.decLL; + break; + case Twine::UHexKind: + OS.write_hex(*Ptr.uHex); + break; + } +} + +void Twine::printOneChildRepr(raw_ostream &OS, Child Ptr, + NodeKind Kind) const { + switch (Kind) { + case Twine::NullKind: + OS << "null"; break; + case Twine::EmptyKind: + OS << "empty"; break; + case Twine::TwineKind: + OS << "rope:"; + Ptr.twine->printRepr(OS); + break; + case Twine::CStringKind: + OS << "cstring:\"" + << Ptr.cString << "\""; + break; + case Twine::StdStringKind: + OS << "std::string:\"" + << Ptr.stdString << "\""; + break; + case Twine::StringRefKind: + OS << "stringref:\"" + << Ptr.stringRef << "\""; + break; + case Twine::SmallStringKind: + OS << "smallstring:\"" << *Ptr.smallString << "\""; + break; + case Twine::CharKind: + OS << "char:\"" << Ptr.character << "\""; + break; + case Twine::DecUIKind: + OS << "decUI:\"" << Ptr.decUI << "\""; + break; + case Twine::DecIKind: + OS << "decI:\"" << Ptr.decI << "\""; + break; + case Twine::DecULKind: + OS << "decUL:\"" << *Ptr.decUL << "\""; + break; + case Twine::DecLKind: + OS << "decL:\"" << *Ptr.decL << "\""; + break; + case Twine::DecULLKind: + OS << "decULL:\"" << *Ptr.decULL << "\""; + break; + case Twine::DecLLKind: + OS << "decLL:\"" << *Ptr.decLL << "\""; + break; + case Twine::UHexKind: + OS << "uhex:\"" << Ptr.uHex << "\""; + break; + } +} + +void Twine::print(raw_ostream &OS) const { + printOneChild(OS, LHS, getLHSKind()); + printOneChild(OS, RHS, getRHSKind()); +} + +void Twine::printRepr(raw_ostream &OS) const { + OS << "(Twine "; + printOneChildRepr(OS, LHS, getLHSKind()); + OS << " "; + printOneChildRepr(OS, RHS, getRHSKind()); + OS << ")"; +} + +LLVM_DUMP_METHOD void Twine::dump() const { + print(dbgs()); +} + +void Twine::dumpRepr() const { + printRepr(dbgs()); +}
diff --git a/third_party/llvm-subzero/lib/Support/Windows/Host.inc b/third_party/llvm-subzero/lib/Support/Windows/Host.inc new file mode 100644 index 0000000..fe89fe0 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Windows/Host.inc
@@ -0,0 +1,22 @@ +//===- llvm/Support/Win32/Host.inc ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Win32 Host support. +// +//===----------------------------------------------------------------------===// + +#include "WindowsSupport.h" +#include <cstdio> +#include <string> + +using namespace llvm; + +std::string sys::getDefaultTargetTriple() { + return Triple::normalize(LLVM_DEFAULT_TARGET_TRIPLE); +}
diff --git a/third_party/llvm-subzero/lib/Support/Windows/Mutex.inc b/third_party/llvm-subzero/lib/Support/Windows/Mutex.inc new file mode 100644 index 0000000..ab79d07 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Windows/Mutex.inc
@@ -0,0 +1,58 @@ +//===- llvm/Support/Win32/Mutex.inc - Win32 Mutex Implementation -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Win32 specific (non-pthread) Mutex class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Win32 code that +//=== is guaranteed to work on *all* Win32 variants. +//===----------------------------------------------------------------------===// + +#include "WindowsSupport.h" +#include "llvm/Support/Mutex.h" + +namespace llvm { +using namespace sys; + +MutexImpl::MutexImpl(bool /*recursive*/) +{ + data_ = new CRITICAL_SECTION; + InitializeCriticalSection((LPCRITICAL_SECTION)data_); +} + +MutexImpl::~MutexImpl() +{ + DeleteCriticalSection((LPCRITICAL_SECTION)data_); + delete (LPCRITICAL_SECTION)data_; + data_ = 0; +} + +bool +MutexImpl::acquire() +{ + EnterCriticalSection((LPCRITICAL_SECTION)data_); + return true; +} + +bool +MutexImpl::release() +{ + LeaveCriticalSection((LPCRITICAL_SECTION)data_); + return true; +} + +bool +MutexImpl::tryacquire() +{ + return TryEnterCriticalSection((LPCRITICAL_SECTION)data_); +} + +}
diff --git a/third_party/llvm-subzero/lib/Support/Windows/Path.inc b/third_party/llvm-subzero/lib/Support/Windows/Path.inc new file mode 100644 index 0000000..fab6aec --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Windows/Path.inc
@@ -0,0 +1,989 @@ +//===- llvm/Support/Windows/Path.inc - Windows Path Impl --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Windows specific implementation of the Path API. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Windows code that +//=== is guaranteed to work on *all* Windows variants. +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/WindowsError.h" +#include <fcntl.h> +#include <io.h> +#include <sys/stat.h> +#include <sys/types.h> + +// These two headers must be included last, and make sure shlobj is required +// after Windows.h to make sure it picks up our definition of _WIN32_WINNT +#include "WindowsSupport.h" +#include <shlobj.h> + +#undef max + +// MinGW doesn't define this. +#ifndef _ERRNO_T_DEFINED +#define _ERRNO_T_DEFINED +typedef int errno_t; +#endif + +#ifdef _MSC_VER +# pragma comment(lib, "advapi32.lib") // This provides CryptAcquireContextW. +# pragma comment(lib, "ole32.lib") // This provides CoTaskMemFree +#endif + +using namespace llvm; + +using llvm::sys::windows::UTF8ToUTF16; +using llvm::sys::windows::UTF16ToUTF8; +using llvm::sys::path::widenPath; + +static bool is_separator(const wchar_t value) { + switch (value) { + case L'\\': + case L'/': + return true; + default: + return false; + } +} + +namespace llvm { +namespace sys { +namespace path { + +// Convert a UTF-8 path to UTF-16. Also, if the absolute equivalent of the +// path is longer than CreateDirectory can tolerate, make it absolute and +// prefixed by '\\?\'. +std::error_code widenPath(const Twine &Path8, + SmallVectorImpl<wchar_t> &Path16) { + const size_t MaxDirLen = MAX_PATH - 12; // Must leave room for 8.3 filename. + + // Several operations would convert Path8 to SmallString; more efficient to + // do it once up front. + SmallString<128> Path8Str; + Path8.toVector(Path8Str); + + // If we made this path absolute, how much longer would it get? + size_t CurPathLen; + if (llvm::sys::path::is_absolute(Twine(Path8Str))) + CurPathLen = 0; // No contribution from current_path needed. + else { + CurPathLen = ::GetCurrentDirectoryW(0, NULL); + if (CurPathLen == 0) + return mapWindowsError(::GetLastError()); + } + + // Would the absolute path be longer than our limit? + if ((Path8Str.size() + CurPathLen) >= MaxDirLen && + !Path8Str.startswith("\\\\?\\")) { + SmallString<2*MAX_PATH> FullPath("\\\\?\\"); + if (CurPathLen) { + SmallString<80> CurPath; + if (std::error_code EC = llvm::sys::fs::current_path(CurPath)) + return EC; + FullPath.append(CurPath); + } + // Traverse the requested path, canonicalizing . and .. as we go (because + // the \\?\ prefix is documented to treat them as real components). + // The iterators don't report separators and append() always attaches + // preferred_separator so we don't need to call native() on the result. + for (llvm::sys::path::const_iterator I = llvm::sys::path::begin(Path8Str), + E = llvm::sys::path::end(Path8Str); + I != E; ++I) { + if (I->size() == 1 && *I == ".") + continue; + if (I->size() == 2 && *I == "..") + llvm::sys::path::remove_filename(FullPath); + else + llvm::sys::path::append(FullPath, *I); + } + return UTF8ToUTF16(FullPath, Path16); + } + + // Just use the caller's original path. + return UTF8ToUTF16(Path8Str, Path16); +} +} // end namespace path + +namespace fs { + +std::string getMainExecutable(const char *argv0, void *MainExecAddr) { + SmallVector<wchar_t, MAX_PATH> PathName; + DWORD Size = ::GetModuleFileNameW(NULL, PathName.data(), PathName.capacity()); + + // A zero return value indicates a failure other than insufficient space. + if (Size == 0) + return ""; + + // Insufficient space is determined by a return value equal to the size of + // the buffer passed in. + if (Size == PathName.capacity()) + return ""; + + // On success, GetModuleFileNameW returns the number of characters written to + // the buffer not including the NULL terminator. + PathName.set_size(Size); + + // Convert the result from UTF-16 to UTF-8. + SmallVector<char, MAX_PATH> PathNameUTF8; + if (UTF16ToUTF8(PathName.data(), PathName.size(), PathNameUTF8)) + return ""; + + return std::string(PathNameUTF8.data()); +} + +UniqueID file_status::getUniqueID() const { + // The file is uniquely identified by the volume serial number along + // with the 64-bit file identifier. + uint64_t FileID = (static_cast<uint64_t>(FileIndexHigh) << 32ULL) | + static_cast<uint64_t>(FileIndexLow); + + return UniqueID(VolumeSerialNumber, FileID); +} + +ErrorOr<space_info> disk_space(const Twine &Path) { + ULARGE_INTEGER Avail, Total, Free; + if (!::GetDiskFreeSpaceExA(Path.str().c_str(), &Avail, &Total, &Free)) + return mapWindowsError(::GetLastError()); + space_info SpaceInfo; + SpaceInfo.capacity = + (static_cast<uint64_t>(Total.HighPart) << 32) + Total.LowPart; + SpaceInfo.free = (static_cast<uint64_t>(Free.HighPart) << 32) + Free.LowPart; + SpaceInfo.available = + (static_cast<uint64_t>(Avail.HighPart) << 32) + Avail.LowPart; + return SpaceInfo; +} + +TimeValue file_status::getLastAccessedTime() const { + ULARGE_INTEGER UI; + UI.LowPart = LastAccessedTimeLow; + UI.HighPart = LastAccessedTimeHigh; + + TimeValue Ret; + Ret.fromWin32Time(UI.QuadPart); + return Ret; +} + +TimeValue file_status::getLastModificationTime() const { + ULARGE_INTEGER UI; + UI.LowPart = LastWriteTimeLow; + UI.HighPart = LastWriteTimeHigh; + + TimeValue Ret; + Ret.fromWin32Time(UI.QuadPart); + return Ret; +} + +std::error_code current_path(SmallVectorImpl<char> &result) { + SmallVector<wchar_t, MAX_PATH> cur_path; + DWORD len = MAX_PATH; + + do { + cur_path.reserve(len); + len = ::GetCurrentDirectoryW(cur_path.capacity(), cur_path.data()); + + // A zero return value indicates a failure other than insufficient space. + if (len == 0) + return mapWindowsError(::GetLastError()); + + // If there's insufficient space, the len returned is larger than the len + // given. + } while (len > cur_path.capacity()); + + // On success, GetCurrentDirectoryW returns the number of characters not + // including the null-terminator. + cur_path.set_size(len); + return UTF16ToUTF8(cur_path.begin(), cur_path.size(), result); +} + +std::error_code create_directory(const Twine &path, bool IgnoreExisting, + perms Perms) { + SmallVector<wchar_t, 128> path_utf16; + + if (std::error_code ec = widenPath(path, path_utf16)) + return ec; + + if (!::CreateDirectoryW(path_utf16.begin(), NULL)) { + DWORD LastError = ::GetLastError(); + if (LastError != ERROR_ALREADY_EXISTS || !IgnoreExisting) + return mapWindowsError(LastError); + } + + return std::error_code(); +} + +// We can't use symbolic links for windows. +std::error_code create_link(const Twine &to, const Twine &from) { + // Convert to utf-16. + SmallVector<wchar_t, 128> wide_from; + SmallVector<wchar_t, 128> wide_to; + if (std::error_code ec = widenPath(from, wide_from)) + return ec; + if (std::error_code ec = widenPath(to, wide_to)) + return ec; + + if (!::CreateHardLinkW(wide_from.begin(), wide_to.begin(), NULL)) + return mapWindowsError(::GetLastError()); + + return std::error_code(); +} + +std::error_code remove(const Twine &path, bool IgnoreNonExisting) { + SmallVector<wchar_t, 128> path_utf16; + + file_status ST; + if (std::error_code EC = status(path, ST)) { + if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting) + return EC; + return std::error_code(); + } + + if (std::error_code ec = widenPath(path, path_utf16)) + return ec; + + if (ST.type() == file_type::directory_file) { + if (!::RemoveDirectoryW(c_str(path_utf16))) { + std::error_code EC = mapWindowsError(::GetLastError()); + if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting) + return EC; + } + return std::error_code(); + } + if (!::DeleteFileW(c_str(path_utf16))) { + std::error_code EC = mapWindowsError(::GetLastError()); + if (EC != errc::no_such_file_or_directory || !IgnoreNonExisting) + return EC; + } + return std::error_code(); +} + +std::error_code rename(const Twine &from, const Twine &to) { + // Convert to utf-16. + SmallVector<wchar_t, 128> wide_from; + SmallVector<wchar_t, 128> wide_to; + if (std::error_code ec = widenPath(from, wide_from)) + return ec; + if (std::error_code ec = widenPath(to, wide_to)) + return ec; + + std::error_code ec = std::error_code(); + + // Retry while we see recoverable errors. + // System scanners (eg. indexer) might open the source file when it is written + // and closed. + + bool TryReplace = true; + + for (int i = 0; i < 2000; i++) { + if (i > 0) + ::Sleep(1); + + if (TryReplace) { + // Try ReplaceFile first, as it is able to associate a new data stream + // with the destination even if the destination file is currently open. + if (::ReplaceFileW(wide_to.data(), wide_from.data(), NULL, 0, NULL, NULL)) + return std::error_code(); + + DWORD ReplaceError = ::GetLastError(); + ec = mapWindowsError(ReplaceError); + + // If ReplaceFileW returned ERROR_UNABLE_TO_MOVE_REPLACEMENT or + // ERROR_UNABLE_TO_MOVE_REPLACEMENT_2, retry but only use MoveFileExW(). + if (ReplaceError == ERROR_UNABLE_TO_MOVE_REPLACEMENT || + ReplaceError == ERROR_UNABLE_TO_MOVE_REPLACEMENT_2) { + TryReplace = false; + continue; + } + // If ReplaceFileW returned ERROR_UNABLE_TO_REMOVE_REPLACED, retry + // using ReplaceFileW(). + if (ReplaceError == ERROR_UNABLE_TO_REMOVE_REPLACED) + continue; + // We get ERROR_FILE_NOT_FOUND if the destination file is missing. + // MoveFileEx can handle this case. + if (ReplaceError != ERROR_ACCESS_DENIED && + ReplaceError != ERROR_FILE_NOT_FOUND && + ReplaceError != ERROR_SHARING_VIOLATION) + break; + } + + if (::MoveFileExW(wide_from.begin(), wide_to.begin(), + MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)) + return std::error_code(); + + DWORD MoveError = ::GetLastError(); + ec = mapWindowsError(MoveError); + if (MoveError != ERROR_ACCESS_DENIED) break; + } + + return ec; +} + +std::error_code resize_file(int FD, uint64_t Size) { +#ifdef HAVE__CHSIZE_S + errno_t error = ::_chsize_s(FD, Size); +#else + errno_t error = ::_chsize(FD, Size); +#endif + return std::error_code(error, std::generic_category()); +} + +std::error_code access(const Twine &Path, AccessMode Mode) { + SmallVector<wchar_t, 128> PathUtf16; + + if (std::error_code EC = widenPath(Path, PathUtf16)) + return EC; + + DWORD Attributes = ::GetFileAttributesW(PathUtf16.begin()); + + if (Attributes == INVALID_FILE_ATTRIBUTES) { + // See if the file didn't actually exist. + DWORD LastError = ::GetLastError(); + if (LastError != ERROR_FILE_NOT_FOUND && + LastError != ERROR_PATH_NOT_FOUND) + return mapWindowsError(LastError); + return errc::no_such_file_or_directory; + } + + if (Mode == AccessMode::Write && (Attributes & FILE_ATTRIBUTE_READONLY)) + return errc::permission_denied; + + return std::error_code(); +} + +bool can_execute(const Twine &Path) { + return !access(Path, AccessMode::Execute) || + !access(Path + ".exe", AccessMode::Execute); +} + +bool equivalent(file_status A, file_status B) { + assert(status_known(A) && status_known(B)); + return A.FileIndexHigh == B.FileIndexHigh && + A.FileIndexLow == B.FileIndexLow && + A.FileSizeHigh == B.FileSizeHigh && + A.FileSizeLow == B.FileSizeLow && + A.LastAccessedTimeHigh == B.LastAccessedTimeHigh && + A.LastAccessedTimeLow == B.LastAccessedTimeLow && + A.LastWriteTimeHigh == B.LastWriteTimeHigh && + A.LastWriteTimeLow == B.LastWriteTimeLow && + A.VolumeSerialNumber == B.VolumeSerialNumber; +} + +std::error_code equivalent(const Twine &A, const Twine &B, bool &result) { + file_status fsA, fsB; + if (std::error_code ec = status(A, fsA)) + return ec; + if (std::error_code ec = status(B, fsB)) + return ec; + result = equivalent(fsA, fsB); + return std::error_code(); +} + +static bool isReservedName(StringRef path) { + // This list of reserved names comes from MSDN, at: + // http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx + static const char *const sReservedNames[] = { "nul", "con", "prn", "aux", + "com1", "com2", "com3", "com4", + "com5", "com6", "com7", "com8", + "com9", "lpt1", "lpt2", "lpt3", + "lpt4", "lpt5", "lpt6", "lpt7", + "lpt8", "lpt9" }; + + // First, check to see if this is a device namespace, which always + // starts with \\.\, since device namespaces are not legal file paths. + if (path.startswith("\\\\.\\")) + return true; + + // Then compare against the list of ancient reserved names. + for (size_t i = 0; i < array_lengthof(sReservedNames); ++i) { + if (path.equals_lower(sReservedNames[i])) + return true; + } + + // The path isn't what we consider reserved. + return false; +} + +static std::error_code getStatus(HANDLE FileHandle, file_status &Result) { + if (FileHandle == INVALID_HANDLE_VALUE) + goto handle_status_error; + + switch (::GetFileType(FileHandle)) { + default: + llvm_unreachable("Don't know anything about this file type"); + case FILE_TYPE_UNKNOWN: { + DWORD Err = ::GetLastError(); + if (Err != NO_ERROR) + return mapWindowsError(Err); + Result = file_status(file_type::type_unknown); + return std::error_code(); + } + case FILE_TYPE_DISK: + break; + case FILE_TYPE_CHAR: + Result = file_status(file_type::character_file); + return std::error_code(); + case FILE_TYPE_PIPE: + Result = file_status(file_type::fifo_file); + return std::error_code(); + } + + BY_HANDLE_FILE_INFORMATION Info; + if (!::GetFileInformationByHandle(FileHandle, &Info)) + goto handle_status_error; + + { + file_type Type = (Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + ? file_type::directory_file + : file_type::regular_file; + Result = + file_status(Type, Info.ftLastAccessTime.dwHighDateTime, + Info.ftLastAccessTime.dwLowDateTime, + Info.ftLastWriteTime.dwHighDateTime, + Info.ftLastWriteTime.dwLowDateTime, + Info.dwVolumeSerialNumber, Info.nFileSizeHigh, + Info.nFileSizeLow, Info.nFileIndexHigh, Info.nFileIndexLow); + return std::error_code(); + } + +handle_status_error: + DWORD LastError = ::GetLastError(); + if (LastError == ERROR_FILE_NOT_FOUND || + LastError == ERROR_PATH_NOT_FOUND) + Result = file_status(file_type::file_not_found); + else if (LastError == ERROR_SHARING_VIOLATION) + Result = file_status(file_type::type_unknown); + else + Result = file_status(file_type::status_error); + return mapWindowsError(LastError); +} + +std::error_code status(const Twine &path, file_status &result) { + SmallString<128> path_storage; + SmallVector<wchar_t, 128> path_utf16; + + StringRef path8 = path.toStringRef(path_storage); + if (isReservedName(path8)) { + result = file_status(file_type::character_file); + return std::error_code(); + } + + if (std::error_code ec = widenPath(path8, path_utf16)) + return ec; + + DWORD attr = ::GetFileAttributesW(path_utf16.begin()); + if (attr == INVALID_FILE_ATTRIBUTES) + return getStatus(INVALID_HANDLE_VALUE, result); + + // Handle reparse points. + if (attr & FILE_ATTRIBUTE_REPARSE_POINT) { + ScopedFileHandle h( + ::CreateFileW(path_utf16.begin(), + 0, // Attributes only. + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + 0)); + if (!h) + return getStatus(INVALID_HANDLE_VALUE, result); + } + + ScopedFileHandle h( + ::CreateFileW(path_utf16.begin(), 0, // Attributes only. + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); + if (!h) + return getStatus(INVALID_HANDLE_VALUE, result); + + return getStatus(h, result); +} + +std::error_code status(int FD, file_status &Result) { + HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD)); + return getStatus(FileHandle, Result); +} + +std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time) { + ULARGE_INTEGER UI; + UI.QuadPart = Time.toWin32Time(); + FILETIME FT; + FT.dwLowDateTime = UI.LowPart; + FT.dwHighDateTime = UI.HighPart; + HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD)); + if (!SetFileTime(FileHandle, NULL, &FT, &FT)) + return mapWindowsError(::GetLastError()); + return std::error_code(); +} + +std::error_code mapped_file_region::init(int FD, uint64_t Offset, + mapmode Mode) { + // Make sure that the requested size fits within SIZE_T. + if (Size > std::numeric_limits<SIZE_T>::max()) + return make_error_code(errc::invalid_argument); + + HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD)); + if (FileHandle == INVALID_HANDLE_VALUE) + return make_error_code(errc::bad_file_descriptor); + + DWORD flprotect; + switch (Mode) { + case readonly: flprotect = PAGE_READONLY; break; + case readwrite: flprotect = PAGE_READWRITE; break; + case priv: flprotect = PAGE_WRITECOPY; break; + } + + HANDLE FileMappingHandle = + ::CreateFileMappingW(FileHandle, 0, flprotect, + (Offset + Size) >> 32, + (Offset + Size) & 0xffffffff, + 0); + if (FileMappingHandle == NULL) { + std::error_code ec = mapWindowsError(GetLastError()); + return ec; + } + + DWORD dwDesiredAccess; + switch (Mode) { + case readonly: dwDesiredAccess = FILE_MAP_READ; break; + case readwrite: dwDesiredAccess = FILE_MAP_WRITE; break; + case priv: dwDesiredAccess = FILE_MAP_COPY; break; + } + Mapping = ::MapViewOfFile(FileMappingHandle, + dwDesiredAccess, + Offset >> 32, + Offset & 0xffffffff, + Size); + if (Mapping == NULL) { + std::error_code ec = mapWindowsError(GetLastError()); + ::CloseHandle(FileMappingHandle); + return ec; + } + + if (Size == 0) { + MEMORY_BASIC_INFORMATION mbi; + SIZE_T Result = VirtualQuery(Mapping, &mbi, sizeof(mbi)); + if (Result == 0) { + std::error_code ec = mapWindowsError(GetLastError()); + ::UnmapViewOfFile(Mapping); + ::CloseHandle(FileMappingHandle); + return ec; + } + Size = mbi.RegionSize; + } + + // Close all the handles except for the view. It will keep the other handles + // alive. + ::CloseHandle(FileMappingHandle); + return std::error_code(); +} + +mapped_file_region::mapped_file_region(int fd, mapmode mode, uint64_t length, + uint64_t offset, std::error_code &ec) + : Size(length), Mapping() { + ec = init(fd, offset, mode); + if (ec) + Mapping = 0; +} + +mapped_file_region::~mapped_file_region() { + if (Mapping) + ::UnmapViewOfFile(Mapping); +} + +uint64_t mapped_file_region::size() const { + assert(Mapping && "Mapping failed but used anyway!"); + return Size; +} + +char *mapped_file_region::data() const { + assert(Mapping && "Mapping failed but used anyway!"); + return reinterpret_cast<char*>(Mapping); +} + +const char *mapped_file_region::const_data() const { + assert(Mapping && "Mapping failed but used anyway!"); + return reinterpret_cast<const char*>(Mapping); +} + +int mapped_file_region::alignment() { + SYSTEM_INFO SysInfo; + ::GetSystemInfo(&SysInfo); + return SysInfo.dwAllocationGranularity; +} + +std::error_code detail::directory_iterator_construct(detail::DirIterState &it, + StringRef path){ + SmallVector<wchar_t, 128> path_utf16; + + if (std::error_code ec = widenPath(path, path_utf16)) + return ec; + + // Convert path to the format that Windows is happy with. + if (path_utf16.size() > 0 && + !is_separator(path_utf16[path.size() - 1]) && + path_utf16[path.size() - 1] != L':') { + path_utf16.push_back(L'\\'); + path_utf16.push_back(L'*'); + } else { + path_utf16.push_back(L'*'); + } + + // Get the first directory entry. + WIN32_FIND_DATAW FirstFind; + ScopedFindHandle FindHandle(::FindFirstFileW(c_str(path_utf16), &FirstFind)); + if (!FindHandle) + return mapWindowsError(::GetLastError()); + + size_t FilenameLen = ::wcslen(FirstFind.cFileName); + while ((FilenameLen == 1 && FirstFind.cFileName[0] == L'.') || + (FilenameLen == 2 && FirstFind.cFileName[0] == L'.' && + FirstFind.cFileName[1] == L'.')) + if (!::FindNextFileW(FindHandle, &FirstFind)) { + DWORD LastError = ::GetLastError(); + // Check for end. + if (LastError == ERROR_NO_MORE_FILES) + return detail::directory_iterator_destruct(it); + return mapWindowsError(LastError); + } else + FilenameLen = ::wcslen(FirstFind.cFileName); + + // Construct the current directory entry. + SmallString<128> directory_entry_name_utf8; + if (std::error_code ec = + UTF16ToUTF8(FirstFind.cFileName, ::wcslen(FirstFind.cFileName), + directory_entry_name_utf8)) + return ec; + + it.IterationHandle = intptr_t(FindHandle.take()); + SmallString<128> directory_entry_path(path); + path::append(directory_entry_path, directory_entry_name_utf8); + it.CurrentEntry = directory_entry(directory_entry_path); + + return std::error_code(); +} + +std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) { + if (it.IterationHandle != 0) + // Closes the handle if it's valid. + ScopedFindHandle close(HANDLE(it.IterationHandle)); + it.IterationHandle = 0; + it.CurrentEntry = directory_entry(); + return std::error_code(); +} + +std::error_code detail::directory_iterator_increment(detail::DirIterState &it) { + WIN32_FIND_DATAW FindData; + if (!::FindNextFileW(HANDLE(it.IterationHandle), &FindData)) { + DWORD LastError = ::GetLastError(); + // Check for end. + if (LastError == ERROR_NO_MORE_FILES) + return detail::directory_iterator_destruct(it); + return mapWindowsError(LastError); + } + + size_t FilenameLen = ::wcslen(FindData.cFileName); + if ((FilenameLen == 1 && FindData.cFileName[0] == L'.') || + (FilenameLen == 2 && FindData.cFileName[0] == L'.' && + FindData.cFileName[1] == L'.')) + return directory_iterator_increment(it); + + SmallString<128> directory_entry_path_utf8; + if (std::error_code ec = + UTF16ToUTF8(FindData.cFileName, ::wcslen(FindData.cFileName), + directory_entry_path_utf8)) + return ec; + + it.CurrentEntry.replace_filename(Twine(directory_entry_path_utf8)); + return std::error_code(); +} + +std::error_code openFileForRead(const Twine &Name, int &ResultFD, + SmallVectorImpl<char> *RealPath) { + SmallVector<wchar_t, 128> PathUTF16; + + if (std::error_code EC = widenPath(Name, PathUTF16)) + return EC; + + HANDLE H = + ::CreateFileW(PathUTF16.begin(), GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (H == INVALID_HANDLE_VALUE) { + DWORD LastError = ::GetLastError(); + std::error_code EC = mapWindowsError(LastError); + // Provide a better error message when trying to open directories. + // This only runs if we failed to open the file, so there is probably + // no performances issues. + if (LastError != ERROR_ACCESS_DENIED) + return EC; + if (is_directory(Name)) + return make_error_code(errc::is_a_directory); + return EC; + } + + int FD = ::_open_osfhandle(intptr_t(H), 0); + if (FD == -1) { + ::CloseHandle(H); + return mapWindowsError(ERROR_INVALID_HANDLE); + } + + // Fetch the real name of the file, if the user asked + if (RealPath) { + RealPath->clear(); + wchar_t RealPathUTF16[MAX_PATH]; + DWORD CountChars = + ::GetFinalPathNameByHandleW(H, RealPathUTF16, MAX_PATH, + FILE_NAME_NORMALIZED); + if (CountChars > 0 && CountChars < MAX_PATH) { + // Convert the result from UTF-16 to UTF-8. + SmallString<MAX_PATH> RealPathUTF8; + if (!UTF16ToUTF8(RealPathUTF16, CountChars, RealPathUTF8)) + RealPath->append(RealPathUTF8.data(), + RealPathUTF8.data() + strlen(RealPathUTF8.data())); + } + } + + ResultFD = FD; + return std::error_code(); +} + +std::error_code openFileForWrite(const Twine &Name, int &ResultFD, + sys::fs::OpenFlags Flags, unsigned Mode) { + // Verify that we don't have both "append" and "excl". + assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) && + "Cannot specify both 'excl' and 'append' file creation flags!"); + + SmallVector<wchar_t, 128> PathUTF16; + + if (std::error_code EC = widenPath(Name, PathUTF16)) + return EC; + + DWORD CreationDisposition; + if (Flags & F_Excl) + CreationDisposition = CREATE_NEW; + else if (Flags & F_Append) + CreationDisposition = OPEN_ALWAYS; + else + CreationDisposition = CREATE_ALWAYS; + + DWORD Access = GENERIC_WRITE; + if (Flags & F_RW) + Access |= GENERIC_READ; + + HANDLE H = ::CreateFileW(PathUTF16.begin(), Access, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + CreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL); + + if (H == INVALID_HANDLE_VALUE) { + DWORD LastError = ::GetLastError(); + std::error_code EC = mapWindowsError(LastError); + // Provide a better error message when trying to open directories. + // This only runs if we failed to open the file, so there is probably + // no performances issues. + if (LastError != ERROR_ACCESS_DENIED) + return EC; + if (is_directory(Name)) + return make_error_code(errc::is_a_directory); + return EC; + } + + int OpenFlags = 0; + if (Flags & F_Append) + OpenFlags |= _O_APPEND; + + if (Flags & F_Text) + OpenFlags |= _O_TEXT; + + int FD = ::_open_osfhandle(intptr_t(H), OpenFlags); + if (FD == -1) { + ::CloseHandle(H); + return mapWindowsError(ERROR_INVALID_HANDLE); + } + + ResultFD = FD; + return std::error_code(); +} + +std::error_code getPathFromOpenFD(int FD, SmallVectorImpl<char> &ResultPath) { + HANDLE FileHandle = reinterpret_cast<HANDLE>(::_get_osfhandle(FD)); + if (FileHandle == INVALID_HANDLE_VALUE) + return make_error_code(errc::bad_file_descriptor); + + DWORD CharCount; + SmallVector<wchar_t, 1024> TempPath; + do { + CharCount = ::GetFinalPathNameByHandleW(FileHandle, TempPath.begin(), + TempPath.capacity(), + FILE_NAME_NORMALIZED); + if (CharCount < TempPath.capacity()) + break; + + // Reserve sufficient space for the path as well as the null character. Even + // though the API does not document that it is required, if we reserve just + // CharCount space, the function call will not store the resulting path and + // still report success. + TempPath.reserve(CharCount + 1); + } while (true); + + if (CharCount == 0) + return mapWindowsError(::GetLastError()); + + TempPath.set_size(CharCount); + + // On earlier Windows releases, the character count includes the terminating + // null. + if (TempPath.back() == L'\0') { + --CharCount; + TempPath.pop_back(); + } + + return windows::UTF16ToUTF8(TempPath.data(), CharCount, ResultPath); +} +} // end namespace fs + +namespace path { +static bool getKnownFolderPath(KNOWNFOLDERID folderId, + SmallVectorImpl<char> &result) { + wchar_t *path = nullptr; + if (::SHGetKnownFolderPath(folderId, KF_FLAG_CREATE, nullptr, &path) != S_OK) + return false; + + bool ok = !UTF16ToUTF8(path, ::wcslen(path), result); + ::CoTaskMemFree(path); + return ok; +} + +bool getUserCacheDir(SmallVectorImpl<char> &Result) { + return getKnownFolderPath(FOLDERID_LocalAppData, Result); +} + +bool home_directory(SmallVectorImpl<char> &result) { + return getKnownFolderPath(FOLDERID_Profile, result); +} + +static bool getTempDirEnvVar(const wchar_t *Var, SmallVectorImpl<char> &Res) { + SmallVector<wchar_t, 1024> Buf; + size_t Size = 1024; + do { + Buf.reserve(Size); + Size = GetEnvironmentVariableW(Var, Buf.data(), Buf.capacity()); + if (Size == 0) + return false; + + // Try again with larger buffer. + } while (Size > Buf.capacity()); + Buf.set_size(Size); + + return !windows::UTF16ToUTF8(Buf.data(), Size, Res); +} + +static bool getTempDirEnvVar(SmallVectorImpl<char> &Res) { + const wchar_t *EnvironmentVariables[] = {L"TMP", L"TEMP", L"USERPROFILE"}; + for (auto *Env : EnvironmentVariables) { + if (getTempDirEnvVar(Env, Res)) + return true; + } + return false; +} + +void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) { + (void)ErasedOnReboot; + Result.clear(); + + // Check whether the temporary directory is specified by an environment var. + // This matches GetTempPath logic to some degree. GetTempPath is not used + // directly as it cannot handle evn var longer than 130 chars on Windows 7 + // (fixed on Windows 8). + if (getTempDirEnvVar(Result)) { + assert(!Result.empty() && "Unexpected empty path"); + native(Result); // Some Unix-like shells use Unix path separator in $TMP. + fs::make_absolute(Result); // Make it absolute if not already. + return; + } + + // Fall back to a system default. + const char *DefaultResult = "C:\\Temp"; + Result.append(DefaultResult, DefaultResult + strlen(DefaultResult)); +} +} // end namespace path + +namespace windows { +std::error_code UTF8ToUTF16(llvm::StringRef utf8, + llvm::SmallVectorImpl<wchar_t> &utf16) { + if (!utf8.empty()) { + int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8.begin(), + utf8.size(), utf16.begin(), 0); + + if (len == 0) + return mapWindowsError(::GetLastError()); + + utf16.reserve(len + 1); + utf16.set_size(len); + + len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8.begin(), + utf8.size(), utf16.begin(), utf16.size()); + + if (len == 0) + return mapWindowsError(::GetLastError()); + } + + // Make utf16 null terminated. + utf16.push_back(0); + utf16.pop_back(); + + return std::error_code(); +} + +static +std::error_code UTF16ToCodePage(unsigned codepage, const wchar_t *utf16, + size_t utf16_len, + llvm::SmallVectorImpl<char> &utf8) { + if (utf16_len) { + // Get length. + int len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, utf8.begin(), + 0, NULL, NULL); + + if (len == 0) + return mapWindowsError(::GetLastError()); + + utf8.reserve(len); + utf8.set_size(len); + + // Now do the actual conversion. + len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, utf8.data(), + utf8.size(), NULL, NULL); + + if (len == 0) + return mapWindowsError(::GetLastError()); + } + + // Make utf8 null terminated. + utf8.push_back(0); + utf8.pop_back(); + + return std::error_code(); +} + +std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, + llvm::SmallVectorImpl<char> &utf8) { + return UTF16ToCodePage(CP_UTF8, utf16, utf16_len, utf8); +} + +std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len, + llvm::SmallVectorImpl<char> &utf8) { + return UTF16ToCodePage(CP_ACP, utf16, utf16_len, utf8); +} + +} // end namespace windows +} // end namespace sys +} // end namespace llvm
diff --git a/third_party/llvm-subzero/lib/Support/Windows/Process.inc b/third_party/llvm-subzero/lib/Support/Windows/Process.inc new file mode 100644 index 0000000..b012991 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Windows/Process.inc
@@ -0,0 +1,473 @@ +//===- Win32/Process.cpp - Win32 Process Implementation ------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Win32 specific implementation of the Process class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Allocator.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/WindowsError.h" +#include <malloc.h> + +// The Windows.h header must be after LLVM and standard headers. +#include "WindowsSupport.h" + +#include <direct.h> +#include <io.h> +#include <psapi.h> +#include <shellapi.h> + +#ifdef __MINGW32__ + #if (HAVE_LIBPSAPI != 1) + #error "libpsapi.a should be present" + #endif + #if (HAVE_LIBSHELL32 != 1) + #error "libshell32.a should be present" + #endif +#else + #pragma comment(lib, "psapi.lib") + #pragma comment(lib, "shell32.lib") +#endif + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code +//=== and must not be UNIX code +//===----------------------------------------------------------------------===// + +#ifdef __MINGW32__ +// This ban should be lifted when MinGW 1.0+ has defined this value. +# define _HEAPOK (-2) +#endif + +using namespace llvm; +using namespace sys; + +static TimeValue getTimeValueFromFILETIME(FILETIME Time) { + ULARGE_INTEGER TimeInteger; + TimeInteger.LowPart = Time.dwLowDateTime; + TimeInteger.HighPart = Time.dwHighDateTime; + + // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond) + return TimeValue( + static_cast<TimeValue::SecondsType>(TimeInteger.QuadPart / 10000000), + static_cast<TimeValue::NanoSecondsType>( + (TimeInteger.QuadPart % 10000000) * 100)); +} + +// This function retrieves the page size using GetNativeSystemInfo() and is +// present solely so it can be called once to initialize the self_process member +// below. +static unsigned computePageSize() { + // GetNativeSystemInfo() provides the physical page size which may differ + // from GetSystemInfo() in 32-bit applications running under WOW64. + SYSTEM_INFO info; + GetNativeSystemInfo(&info); + // FIXME: FileOffset in MapViewOfFile() should be aligned to not dwPageSize, + // but dwAllocationGranularity. + return static_cast<unsigned>(info.dwPageSize); +} + +unsigned Process::getPageSize() { + static unsigned Ret = computePageSize(); + return Ret; +} + +size_t +Process::GetMallocUsage() +{ + _HEAPINFO hinfo; + hinfo._pentry = NULL; + + size_t size = 0; + + while (_heapwalk(&hinfo) == _HEAPOK) + size += hinfo._size; + + return size; +} + +void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, + TimeValue &sys_time) { + elapsed = TimeValue::now(); + + FILETIME ProcCreate, ProcExit, KernelTime, UserTime; + if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime, + &UserTime) == 0) + return; + + user_time = getTimeValueFromFILETIME(UserTime); + sys_time = getTimeValueFromFILETIME(KernelTime); +} + +// Some LLVM programs such as bugpoint produce core files as a normal part of +// their operation. To prevent the disk from filling up, this configuration +// item does what's necessary to prevent their generation. +void Process::PreventCoreFiles() { + // Windows does have the concept of core files, called minidumps. However, + // disabling minidumps for a particular application extends past the lifetime + // of that application, which is the incorrect behavior for this API. + // Additionally, the APIs require elevated privileges to disable and re- + // enable minidumps, which makes this untenable. For more information, see + // WerAddExcludedApplication and WerRemoveExcludedApplication (Vista and + // later). + // + // Windows also has modal pop-up message boxes. As this method is used by + // bugpoint, preventing these pop-ups is additionally important. + SetErrorMode(SEM_FAILCRITICALERRORS | + SEM_NOGPFAULTERRORBOX | + SEM_NOOPENFILEERRORBOX); + + coreFilesPrevented = true; +} + +/// Returns the environment variable \arg Name's value as a string encoded in +/// UTF-8. \arg Name is assumed to be in UTF-8 encoding. +Optional<std::string> Process::GetEnv(StringRef Name) { + // Convert the argument to UTF-16 to pass it to _wgetenv(). + SmallVector<wchar_t, 128> NameUTF16; + if (windows::UTF8ToUTF16(Name, NameUTF16)) + return None; + + // Environment variable can be encoded in non-UTF8 encoding, and there's no + // way to know what the encoding is. The only reliable way to look up + // multibyte environment variable is to use GetEnvironmentVariableW(). + SmallVector<wchar_t, MAX_PATH> Buf; + size_t Size = MAX_PATH; + do { + Buf.reserve(Size); + Size = + GetEnvironmentVariableW(NameUTF16.data(), Buf.data(), Buf.capacity()); + if (Size == 0) + return None; + + // Try again with larger buffer. + } while (Size > Buf.capacity()); + Buf.set_size(Size); + + // Convert the result from UTF-16 to UTF-8. + SmallVector<char, MAX_PATH> Res; + if (windows::UTF16ToUTF8(Buf.data(), Size, Res)) + return None; + return std::string(Res.data()); +} + +static void AllocateAndPush(const SmallVectorImpl<char> &S, + SmallVectorImpl<const char *> &Vector, + SpecificBumpPtrAllocator<char> &Allocator) { + char *Buffer = Allocator.Allocate(S.size() + 1); + ::memcpy(Buffer, S.data(), S.size()); + Buffer[S.size()] = '\0'; + Vector.push_back(Buffer); +} + +/// Convert Arg from UTF-16 to UTF-8 and push it onto Args. +static std::error_code +ConvertAndPushArg(const wchar_t *Arg, SmallVectorImpl<const char *> &Args, + SpecificBumpPtrAllocator<char> &Allocator) { + SmallVector<char, MAX_PATH> ArgString; + if (std::error_code ec = windows::UTF16ToUTF8(Arg, wcslen(Arg), ArgString)) + return ec; + AllocateAndPush(ArgString, Args, Allocator); + return std::error_code(); +} + +/// \brief Perform wildcard expansion of Arg, or just push it into Args if it +/// doesn't have wildcards or doesn't match any files. +static std::error_code +WildcardExpand(const wchar_t *Arg, SmallVectorImpl<const char *> &Args, + SpecificBumpPtrAllocator<char> &Allocator) { + if (!wcspbrk(Arg, L"*?")) { + // Arg does not contain any wildcard characters. This is the common case. + return ConvertAndPushArg(Arg, Args, Allocator); + } + + if (wcscmp(Arg, L"/?") == 0 || wcscmp(Arg, L"-?") == 0) { + // Don't wildcard expand /?. Always treat it as an option. + return ConvertAndPushArg(Arg, Args, Allocator); + } + + // Extract any directory part of the argument. + SmallVector<char, MAX_PATH> Dir; + if (std::error_code ec = windows::UTF16ToUTF8(Arg, wcslen(Arg), Dir)) + return ec; + sys::path::remove_filename(Dir); + const int DirSize = Dir.size(); + + // Search for matching files. + // FIXME: This assumes the wildcard is only in the file name and not in the + // directory portion of the file path. For example, it doesn't handle + // "*\foo.c" nor "s?c\bar.cpp". + WIN32_FIND_DATAW FileData; + HANDLE FindHandle = FindFirstFileW(Arg, &FileData); + if (FindHandle == INVALID_HANDLE_VALUE) { + return ConvertAndPushArg(Arg, Args, Allocator); + } + + std::error_code ec; + do { + SmallVector<char, MAX_PATH> FileName; + ec = windows::UTF16ToUTF8(FileData.cFileName, wcslen(FileData.cFileName), + FileName); + if (ec) + break; + + // Append FileName to Dir, and remove it afterwards. + llvm::sys::path::append(Dir, StringRef(FileName.data(), FileName.size())); + AllocateAndPush(Dir, Args, Allocator); + Dir.resize(DirSize); + } while (FindNextFileW(FindHandle, &FileData)); + + FindClose(FindHandle); + return ec; +} + +static std::error_code +ExpandShortFileName(const wchar_t *Arg, SmallVectorImpl<const char *> &Args, + SpecificBumpPtrAllocator<char> &Allocator) { + SmallVector<wchar_t, MAX_PATH> LongPath; + DWORD Length = GetLongPathNameW(Arg, LongPath.data(), LongPath.capacity()); + if (Length == 0) + return mapWindowsError(GetLastError()); + if (Length > LongPath.capacity()) { + // We're not going to try to deal with paths longer than MAX_PATH, so we'll + // treat this as an error. GetLastError() returns ERROR_SUCCESS, which + // isn't useful, so we'll hardcode an appropriate error value. + return mapWindowsError(ERROR_INSUFFICIENT_BUFFER); + } + LongPath.set_size(Length); + return ConvertAndPushArg(LongPath.data(), Args, Allocator); +} + +std::error_code +Process::GetArgumentVector(SmallVectorImpl<const char *> &Args, + ArrayRef<const char *>, + SpecificBumpPtrAllocator<char> &ArgAllocator) { + int ArgCount; + wchar_t **UnicodeCommandLine = + CommandLineToArgvW(GetCommandLineW(), &ArgCount); + if (!UnicodeCommandLine) + return mapWindowsError(::GetLastError()); + + Args.reserve(ArgCount); + std::error_code ec; + + // The first argument may contain just the name of the executable (e.g., + // "clang") rather than the full path, so swap it with the full path. + wchar_t ModuleName[MAX_PATH]; + int Length = ::GetModuleFileNameW(NULL, ModuleName, MAX_PATH); + if (0 < Length && Length < MAX_PATH) + UnicodeCommandLine[0] = ModuleName; + + // If the first argument is a shortened (8.3) name (which is possible even + // if we got the module name), the driver will have trouble distinguishing it + // (e.g., clang.exe v. clang++.exe), so expand it now. + ec = ExpandShortFileName(UnicodeCommandLine[0], Args, ArgAllocator); + + for (int i = 1; i < ArgCount && !ec; ++i) { + ec = WildcardExpand(UnicodeCommandLine[i], Args, ArgAllocator); + if (ec) + break; + } + + LocalFree(UnicodeCommandLine); + return ec; +} + +std::error_code Process::FixupStandardFileDescriptors() { + return std::error_code(); +} + +std::error_code Process::SafelyCloseFileDescriptor(int FD) { + if (::close(FD) < 0) + return std::error_code(errno, std::generic_category()); + return std::error_code(); +} + +bool Process::StandardInIsUserInput() { + return FileDescriptorIsDisplayed(0); +} + +bool Process::StandardOutIsDisplayed() { + return FileDescriptorIsDisplayed(1); +} + +bool Process::StandardErrIsDisplayed() { + return FileDescriptorIsDisplayed(2); +} + +bool Process::FileDescriptorIsDisplayed(int fd) { + DWORD Mode; // Unused + return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0); +} + +unsigned Process::StandardOutColumns() { + unsigned Columns = 0; + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) + Columns = csbi.dwSize.X; + return Columns; +} + +unsigned Process::StandardErrColumns() { + unsigned Columns = 0; + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi)) + Columns = csbi.dwSize.X; + return Columns; +} + +// The terminal always has colors. +bool Process::FileDescriptorHasColors(int fd) { + return FileDescriptorIsDisplayed(fd); +} + +bool Process::StandardOutHasColors() { + return FileDescriptorHasColors(1); +} + +bool Process::StandardErrHasColors() { + return FileDescriptorHasColors(2); +} + +static bool UseANSI = false; +void Process::UseANSIEscapeCodes(bool enable) { + UseANSI = enable; +} + +namespace { +class DefaultColors +{ + private: + WORD defaultColor; + public: + DefaultColors() + :defaultColor(GetCurrentColor()) {} + static unsigned GetCurrentColor() { + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) + return csbi.wAttributes; + return 0; + } + WORD operator()() const { return defaultColor; } +}; + +DefaultColors defaultColors; + +WORD fg_color(WORD color) { + return color & (FOREGROUND_BLUE | FOREGROUND_GREEN | + FOREGROUND_INTENSITY | FOREGROUND_RED); +} + +WORD bg_color(WORD color) { + return color & (BACKGROUND_BLUE | BACKGROUND_GREEN | + BACKGROUND_INTENSITY | BACKGROUND_RED); +} +} + +bool Process::ColorNeedsFlush() { + return !UseANSI; +} + +const char *Process::OutputBold(bool bg) { + if (UseANSI) return "\033[1m"; + + WORD colors = DefaultColors::GetCurrentColor(); + if (bg) + colors |= BACKGROUND_INTENSITY; + else + colors |= FOREGROUND_INTENSITY; + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors); + return 0; +} + +const char *Process::OutputColor(char code, bool bold, bool bg) { + if (UseANSI) return colorcodes[bg?1:0][bold?1:0][code&7]; + + WORD current = DefaultColors::GetCurrentColor(); + WORD colors; + if (bg) { + colors = ((code&1) ? BACKGROUND_RED : 0) | + ((code&2) ? BACKGROUND_GREEN : 0 ) | + ((code&4) ? BACKGROUND_BLUE : 0); + if (bold) + colors |= BACKGROUND_INTENSITY; + colors |= fg_color(current); + } else { + colors = ((code&1) ? FOREGROUND_RED : 0) | + ((code&2) ? FOREGROUND_GREEN : 0 ) | + ((code&4) ? FOREGROUND_BLUE : 0); + if (bold) + colors |= FOREGROUND_INTENSITY; + colors |= bg_color(current); + } + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors); + return 0; +} + +static WORD GetConsoleTextAttribute(HANDLE hConsoleOutput) { + CONSOLE_SCREEN_BUFFER_INFO info; + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info); + return info.wAttributes; +} + +const char *Process::OutputReverse() { + if (UseANSI) return "\033[7m"; + + const WORD attributes + = GetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE)); + + const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN | + FOREGROUND_RED | FOREGROUND_INTENSITY; + const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN | + BACKGROUND_RED | BACKGROUND_INTENSITY; + const WORD color_mask = foreground_mask | background_mask; + + WORD new_attributes = + ((attributes & FOREGROUND_BLUE )?BACKGROUND_BLUE :0) | + ((attributes & FOREGROUND_GREEN )?BACKGROUND_GREEN :0) | + ((attributes & FOREGROUND_RED )?BACKGROUND_RED :0) | + ((attributes & FOREGROUND_INTENSITY)?BACKGROUND_INTENSITY:0) | + ((attributes & BACKGROUND_BLUE )?FOREGROUND_BLUE :0) | + ((attributes & BACKGROUND_GREEN )?FOREGROUND_GREEN :0) | + ((attributes & BACKGROUND_RED )?FOREGROUND_RED :0) | + ((attributes & BACKGROUND_INTENSITY)?FOREGROUND_INTENSITY:0) | + 0; + new_attributes = (attributes & ~color_mask) | (new_attributes & color_mask); + + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), new_attributes); + return 0; +} + +const char *Process::ResetColor() { + if (UseANSI) return "\033[0m"; + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors()); + return 0; +} + +// Include GetLastError() in a fatal error message. +static void ReportLastErrorFatal(const char *Msg) { + std::string ErrMsg; + MakeErrMsg(&ErrMsg, Msg); + report_fatal_error(ErrMsg); +} + +unsigned Process::GetRandomNumber() { + HCRYPTPROV HCPC; + if (!::CryptAcquireContextW(&HCPC, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) + ReportLastErrorFatal("Could not acquire a cryptographic context"); + + ScopedCryptContext CryptoProvider(HCPC); + unsigned Ret; + if (!::CryptGenRandom(CryptoProvider, sizeof(Ret), + reinterpret_cast<BYTE *>(&Ret))) + ReportLastErrorFatal("Could not generate a random number"); + return Ret; +}
diff --git a/third_party/llvm-subzero/lib/Support/Windows/Program.inc b/third_party/llvm-subzero/lib/Support/Windows/Program.inc new file mode 100644 index 0000000..78fc538 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Windows/Program.inc
@@ -0,0 +1,554 @@ +//===- Win32/Program.cpp - Win32 Program Implementation ------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Win32 specific implementation of the Program class. +// +//===----------------------------------------------------------------------===// + +#include "WindowsSupport.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/WindowsError.h" +#include "llvm/Support/raw_ostream.h" +#include <cstdio> +#include <fcntl.h> +#include <io.h> +#include <malloc.h> + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code +//=== and must not be UNIX code +//===----------------------------------------------------------------------===// + +namespace llvm { +using namespace sys; + +ProcessInfo::ProcessInfo() : ProcessHandle(0), Pid(0), ReturnCode(0) {} + +ErrorOr<std::string> sys::findProgramByName(StringRef Name, + ArrayRef<StringRef> Paths) { + assert(!Name.empty() && "Must have a name!"); + + if (Name.find_first_of("/\\") != StringRef::npos) + return std::string(Name); + + const wchar_t *Path = nullptr; + std::wstring PathStorage; + if (!Paths.empty()) { + PathStorage.reserve(Paths.size() * MAX_PATH); + for (unsigned i = 0; i < Paths.size(); ++i) { + if (i) + PathStorage.push_back(L';'); + StringRef P = Paths[i]; + SmallVector<wchar_t, MAX_PATH> TmpPath; + if (std::error_code EC = windows::UTF8ToUTF16(P, TmpPath)) + return EC; + PathStorage.append(TmpPath.begin(), TmpPath.end()); + } + Path = PathStorage.c_str(); + } + + SmallVector<wchar_t, MAX_PATH> U16Name; + if (std::error_code EC = windows::UTF8ToUTF16(Name, U16Name)) + return EC; + + SmallVector<StringRef, 12> PathExts; + PathExts.push_back(""); + PathExts.push_back(".exe"); // FIXME: This must be in %PATHEXT%. + if (const char *PathExtEnv = std::getenv("PATHEXT")) + SplitString(PathExtEnv, PathExts, ";"); + + SmallVector<wchar_t, MAX_PATH> U16Result; + DWORD Len = MAX_PATH; + for (StringRef Ext : PathExts) { + SmallVector<wchar_t, MAX_PATH> U16Ext; + if (std::error_code EC = windows::UTF8ToUTF16(Ext, U16Ext)) + return EC; + + do { + U16Result.reserve(Len); + // Lets attach the extension manually. That is needed for files + // with a point in name like aaa.bbb. SearchPathW will not add extension + // from its argument to such files because it thinks they already had one. + SmallVector<wchar_t, MAX_PATH> U16NameExt; + if (std::error_code EC = + windows::UTF8ToUTF16(Twine(Name + Ext).str(), U16NameExt)) + return EC; + + Len = ::SearchPathW(Path, c_str(U16NameExt), nullptr, + U16Result.capacity(), U16Result.data(), nullptr); + } while (Len > U16Result.capacity()); + + if (Len != 0) + break; // Found it. + } + + if (Len == 0) + return mapWindowsError(::GetLastError()); + + U16Result.set_size(Len); + + SmallVector<char, MAX_PATH> U8Result; + if (std::error_code EC = + windows::UTF16ToUTF8(U16Result.data(), U16Result.size(), U8Result)) + return EC; + + return std::string(U8Result.begin(), U8Result.end()); +} + +static HANDLE RedirectIO(const StringRef *path, int fd, std::string* ErrMsg) { + HANDLE h; + if (path == 0) { + if (!DuplicateHandle(GetCurrentProcess(), (HANDLE)_get_osfhandle(fd), + GetCurrentProcess(), &h, + 0, TRUE, DUPLICATE_SAME_ACCESS)) + return INVALID_HANDLE_VALUE; + return h; + } + + std::string fname; + if (path->empty()) + fname = "NUL"; + else + fname = *path; + + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = 0; + sa.bInheritHandle = TRUE; + + SmallVector<wchar_t, 128> fnameUnicode; + if (path->empty()) { + // Don't play long-path tricks on "NUL". + if (windows::UTF8ToUTF16(fname, fnameUnicode)) + return INVALID_HANDLE_VALUE; + } else { + if (path::widenPath(fname, fnameUnicode)) + return INVALID_HANDLE_VALUE; + } + h = CreateFileW(fnameUnicode.data(), fd ? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ, &sa, fd == 0 ? OPEN_EXISTING : CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) { + MakeErrMsg(ErrMsg, fname + ": Can't open file for " + + (fd ? "input" : "output")); + } + + return h; +} + +/// ArgNeedsQuotes - Check whether argument needs to be quoted when calling +/// CreateProcess. +static bool ArgNeedsQuotes(const char *Str) { + return Str[0] == '\0' || strpbrk(Str, "\t \"&\'()*<>\\`^|") != 0; +} + +/// CountPrecedingBackslashes - Returns the number of backslashes preceding Cur +/// in the C string Start. +static unsigned int CountPrecedingBackslashes(const char *Start, + const char *Cur) { + unsigned int Count = 0; + --Cur; + while (Cur >= Start && *Cur == '\\') { + ++Count; + --Cur; + } + return Count; +} + +/// EscapePrecedingEscapes - Append a backslash to Dst for every backslash +/// preceding Cur in the Start string. Assumes Dst has enough space. +static char *EscapePrecedingEscapes(char *Dst, const char *Start, + const char *Cur) { + unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Cur); + while (PrecedingEscapes > 0) { + *Dst++ = '\\'; + --PrecedingEscapes; + } + return Dst; +} + +/// ArgLenWithQuotes - Check whether argument needs to be quoted when calling +/// CreateProcess and returns length of quoted arg with escaped quotes +static unsigned int ArgLenWithQuotes(const char *Str) { + const char *Start = Str; + bool Quoted = ArgNeedsQuotes(Str); + unsigned int len = Quoted ? 2 : 0; + + while (*Str != '\0') { + if (*Str == '\"') { + // We need to add a backslash, but ensure that it isn't escaped. + unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Str); + len += PrecedingEscapes + 1; + } + // Note that we *don't* need to escape runs of backslashes that don't + // precede a double quote! See MSDN: + // http://msdn.microsoft.com/en-us/library/17w5ykft%28v=vs.85%29.aspx + + ++len; + ++Str; + } + + if (Quoted) { + // Make sure the closing quote doesn't get escaped by a trailing backslash. + unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Str); + len += PrecedingEscapes + 1; + } + + return len; +} + +} + +static std::unique_ptr<char[]> flattenArgs(const char **args) { + // First, determine the length of the command line. + unsigned len = 0; + for (unsigned i = 0; args[i]; i++) { + len += ArgLenWithQuotes(args[i]) + 1; + } + + // Now build the command line. + std::unique_ptr<char[]> command(new char[len+1]); + char *p = command.get(); + + for (unsigned i = 0; args[i]; i++) { + const char *arg = args[i]; + const char *start = arg; + + bool needsQuoting = ArgNeedsQuotes(arg); + if (needsQuoting) + *p++ = '"'; + + while (*arg != '\0') { + if (*arg == '\"') { + // Escape all preceding escapes (if any), and then escape the quote. + p = EscapePrecedingEscapes(p, start, arg); + *p++ = '\\'; + } + + *p++ = *arg++; + } + + if (needsQuoting) { + // Make sure our quote doesn't get escaped by a trailing backslash. + p = EscapePrecedingEscapes(p, start, arg); + *p++ = '"'; + } + *p++ = ' '; + } + + *p = 0; + return command; +} + +static bool Execute(ProcessInfo &PI, StringRef Program, const char **args, + const char **envp, const StringRef **redirects, + unsigned memoryLimit, std::string *ErrMsg) { + if (!sys::fs::can_execute(Program)) { + if (ErrMsg) + *ErrMsg = "program not executable"; + return false; + } + + // can_execute may succeed by looking at Program + ".exe". CreateProcessW + // will implicitly add the .exe if we provide a command line without an + // executable path, but since we use an explicit executable, we have to add + // ".exe" ourselves. + SmallString<64> ProgramStorage; + if (!sys::fs::exists(Program)) + Program = Twine(Program + ".exe").toStringRef(ProgramStorage); + + // Windows wants a command line, not an array of args, to pass to the new + // process. We have to concatenate them all, while quoting the args that + // have embedded spaces (or are empty). + std::unique_ptr<char[]> command = flattenArgs(args); + + // The pointer to the environment block for the new process. + std::vector<wchar_t> EnvBlock; + + if (envp) { + // An environment block consists of a null-terminated block of + // null-terminated strings. Convert the array of environment variables to + // an environment block by concatenating them. + for (unsigned i = 0; envp[i]; ++i) { + SmallVector<wchar_t, MAX_PATH> EnvString; + if (std::error_code ec = windows::UTF8ToUTF16(envp[i], EnvString)) { + SetLastError(ec.value()); + MakeErrMsg(ErrMsg, "Unable to convert environment variable to UTF-16"); + return false; + } + + EnvBlock.insert(EnvBlock.end(), EnvString.begin(), EnvString.end()); + EnvBlock.push_back(0); + } + EnvBlock.push_back(0); + } + + // Create a child process. + STARTUPINFOW si; + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + si.hStdInput = INVALID_HANDLE_VALUE; + si.hStdOutput = INVALID_HANDLE_VALUE; + si.hStdError = INVALID_HANDLE_VALUE; + + if (redirects) { + si.dwFlags = STARTF_USESTDHANDLES; + + si.hStdInput = RedirectIO(redirects[0], 0, ErrMsg); + if (si.hStdInput == INVALID_HANDLE_VALUE) { + MakeErrMsg(ErrMsg, "can't redirect stdin"); + return false; + } + si.hStdOutput = RedirectIO(redirects[1], 1, ErrMsg); + if (si.hStdOutput == INVALID_HANDLE_VALUE) { + CloseHandle(si.hStdInput); + MakeErrMsg(ErrMsg, "can't redirect stdout"); + return false; + } + if (redirects[1] && redirects[2] && *(redirects[1]) == *(redirects[2])) { + // If stdout and stderr should go to the same place, redirect stderr + // to the handle already open for stdout. + if (!DuplicateHandle(GetCurrentProcess(), si.hStdOutput, + GetCurrentProcess(), &si.hStdError, + 0, TRUE, DUPLICATE_SAME_ACCESS)) { + CloseHandle(si.hStdInput); + CloseHandle(si.hStdOutput); + MakeErrMsg(ErrMsg, "can't dup stderr to stdout"); + return false; + } + } else { + // Just redirect stderr + si.hStdError = RedirectIO(redirects[2], 2, ErrMsg); + if (si.hStdError == INVALID_HANDLE_VALUE) { + CloseHandle(si.hStdInput); + CloseHandle(si.hStdOutput); + MakeErrMsg(ErrMsg, "can't redirect stderr"); + return false; + } + } + } + + PROCESS_INFORMATION pi; + memset(&pi, 0, sizeof(pi)); + + fflush(stdout); + fflush(stderr); + + SmallVector<wchar_t, MAX_PATH> ProgramUtf16; + if (std::error_code ec = path::widenPath(Program, ProgramUtf16)) { + SetLastError(ec.value()); + MakeErrMsg(ErrMsg, + std::string("Unable to convert application name to UTF-16")); + return false; + } + + SmallVector<wchar_t, MAX_PATH> CommandUtf16; + if (std::error_code ec = windows::UTF8ToUTF16(command.get(), CommandUtf16)) { + SetLastError(ec.value()); + MakeErrMsg(ErrMsg, + std::string("Unable to convert command-line to UTF-16")); + return false; + } + + BOOL rc = CreateProcessW(ProgramUtf16.data(), CommandUtf16.data(), 0, 0, + TRUE, CREATE_UNICODE_ENVIRONMENT, + EnvBlock.empty() ? 0 : EnvBlock.data(), 0, &si, + &pi); + DWORD err = GetLastError(); + + // Regardless of whether the process got created or not, we are done with + // the handles we created for it to inherit. + CloseHandle(si.hStdInput); + CloseHandle(si.hStdOutput); + CloseHandle(si.hStdError); + + // Now return an error if the process didn't get created. + if (!rc) { + SetLastError(err); + MakeErrMsg(ErrMsg, std::string("Couldn't execute program '") + + Program.str() + "'"); + return false; + } + + PI.Pid = pi.dwProcessId; + PI.ProcessHandle = pi.hProcess; + + // Make sure these get closed no matter what. + ScopedCommonHandle hThread(pi.hThread); + + // Assign the process to a job if a memory limit is defined. + ScopedJobHandle hJob; + if (memoryLimit != 0) { + hJob = CreateJobObjectW(0, 0); + bool success = false; + if (hJob) { + JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli; + memset(&jeli, 0, sizeof(jeli)); + jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY; + jeli.ProcessMemoryLimit = uintptr_t(memoryLimit) * 1048576; + if (SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, + &jeli, sizeof(jeli))) { + if (AssignProcessToJobObject(hJob, pi.hProcess)) + success = true; + } + } + if (!success) { + SetLastError(GetLastError()); + MakeErrMsg(ErrMsg, std::string("Unable to set memory limit")); + TerminateProcess(pi.hProcess, 1); + WaitForSingleObject(pi.hProcess, INFINITE); + return false; + } + } + + return true; +} + +namespace llvm { +ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, + bool WaitUntilChildTerminates, std::string *ErrMsg) { + assert(PI.Pid && "invalid pid to wait on, process not started?"); + assert(PI.ProcessHandle && + "invalid process handle to wait on, process not started?"); + DWORD milliSecondsToWait = 0; + if (WaitUntilChildTerminates) + milliSecondsToWait = INFINITE; + else if (SecondsToWait > 0) + milliSecondsToWait = SecondsToWait * 1000; + + ProcessInfo WaitResult = PI; + DWORD WaitStatus = WaitForSingleObject(PI.ProcessHandle, milliSecondsToWait); + if (WaitStatus == WAIT_TIMEOUT) { + if (SecondsToWait) { + if (!TerminateProcess(PI.ProcessHandle, 1)) { + if (ErrMsg) + MakeErrMsg(ErrMsg, "Failed to terminate timed-out program"); + + // -2 indicates a crash or timeout as opposed to failure to execute. + WaitResult.ReturnCode = -2; + CloseHandle(PI.ProcessHandle); + return WaitResult; + } + WaitForSingleObject(PI.ProcessHandle, INFINITE); + CloseHandle(PI.ProcessHandle); + } else { + // Non-blocking wait. + return ProcessInfo(); + } + } + + // Get its exit status. + DWORD status; + BOOL rc = GetExitCodeProcess(PI.ProcessHandle, &status); + DWORD err = GetLastError(); + if (err != ERROR_INVALID_HANDLE) + CloseHandle(PI.ProcessHandle); + + if (!rc) { + SetLastError(err); + if (ErrMsg) + MakeErrMsg(ErrMsg, "Failed getting status for program"); + + // -2 indicates a crash or timeout as opposed to failure to execute. + WaitResult.ReturnCode = -2; + return WaitResult; + } + + if (!status) + return WaitResult; + + // Pass 10(Warning) and 11(Error) to the callee as negative value. + if ((status & 0xBFFF0000U) == 0x80000000U) + WaitResult.ReturnCode = static_cast<int>(status); + else if (status & 0xFF) + WaitResult.ReturnCode = status & 0x7FFFFFFF; + else + WaitResult.ReturnCode = 1; + + return WaitResult; +} + +std::error_code sys::ChangeStdinToBinary() { + int result = _setmode(_fileno(stdin), _O_BINARY); + if (result == -1) + return std::error_code(errno, std::generic_category()); + return std::error_code(); +} + +std::error_code sys::ChangeStdoutToBinary() { + int result = _setmode(_fileno(stdout), _O_BINARY); + if (result == -1) + return std::error_code(errno, std::generic_category()); + return std::error_code(); +} + +std::error_code +llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents, + WindowsEncodingMethod Encoding) { + std::error_code EC; + llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text); + if (EC) + return EC; + + if (Encoding == WEM_UTF8) { + OS << Contents; + } else if (Encoding == WEM_CurrentCodePage) { + SmallVector<wchar_t, 1> ArgsUTF16; + SmallVector<char, 1> ArgsCurCP; + + if ((EC = windows::UTF8ToUTF16(Contents, ArgsUTF16))) + return EC; + + if ((EC = windows::UTF16ToCurCP( + ArgsUTF16.data(), ArgsUTF16.size(), ArgsCurCP))) + return EC; + + OS.write(ArgsCurCP.data(), ArgsCurCP.size()); + } else if (Encoding == WEM_UTF16) { + SmallVector<wchar_t, 1> ArgsUTF16; + + if ((EC = windows::UTF8ToUTF16(Contents, ArgsUTF16))) + return EC; + + // Endianness guessing + char BOM[2]; + uint16_t src = UNI_UTF16_BYTE_ORDER_MARK_NATIVE; + memcpy(BOM, &src, 2); + OS.write(BOM, 2); + OS.write((char *)ArgsUTF16.data(), ArgsUTF16.size() << 1); + } else { + llvm_unreachable("Unknown encoding"); + } + + if (OS.has_error()) + return make_error_code(errc::io_error); + + return EC; +} + +bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program, ArrayRef<const char*> Args) { + // The documented max length of the command line passed to CreateProcess. + static const size_t MaxCommandStringLength = 32768; + // Account for the trailing space for the program path and the + // trailing NULL of the last argument. + size_t ArgLength = ArgLenWithQuotes(Program.str().c_str()) + 2; + for (ArrayRef<const char*>::iterator I = Args.begin(), E = Args.end(); + I != E; ++I) { + // Account for the trailing space for every arg + ArgLength += ArgLenWithQuotes(*I) + 1; + if (ArgLength > MaxCommandStringLength) { + return false; + } + } + return true; +} +}
diff --git a/third_party/llvm-subzero/lib/Support/Windows/Signals.inc b/third_party/llvm-subzero/lib/Support/Windows/Signals.inc new file mode 100644 index 0000000..d3a70c3 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Windows/Signals.inc
@@ -0,0 +1,846 @@ +//===- Win32/Signals.cpp - Win32 Signals Implementation ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Win32 specific implementation of the Signals class. +// +//===----------------------------------------------------------------------===// +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/WindowsError.h" +#include <algorithm> +#include <io.h> +#include <signal.h> +#include <stdio.h> + +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" + +// The Windows.h header must be after LLVM and standard headers. +#include "WindowsSupport.h" + +#ifdef __MINGW32__ + #include <imagehlp.h> +#else + #include <dbghelp.h> +#endif +#include <psapi.h> + +#ifdef _MSC_VER + #pragma comment(lib, "psapi.lib") +#elif __MINGW32__ + #if (HAVE_LIBPSAPI != 1) + #error "libpsapi.a should be present" + #endif + // The version of g++ that comes with MinGW does *not* properly understand + // the ll format specifier for printf. However, MinGW passes the format + // specifiers on to the MSVCRT entirely, and the CRT understands the ll + // specifier. So these warnings are spurious in this case. Since we compile + // with -Wall, this will generate these warnings which should be ignored. So + // we will turn off the warnings for this just file. However, MinGW also does + // not support push and pop for diagnostics, so we have to manually turn it + // back on at the end of the file. + #pragma GCC diagnostic ignored "-Wformat" + #pragma GCC diagnostic ignored "-Wformat-extra-args" + + #if !defined(__MINGW64_VERSION_MAJOR) + // MinGW.org does not have updated support for the 64-bit versions of the + // DebugHlp APIs. So we will have to load them manually. The structures and + // method signatures were pulled from DbgHelp.h in the Windows Platform SDK, + // and adjusted for brevity. + typedef struct _IMAGEHLP_LINE64 { + DWORD SizeOfStruct; + PVOID Key; + DWORD LineNumber; + PCHAR FileName; + DWORD64 Address; + } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64; + + typedef struct _IMAGEHLP_SYMBOL64 { + DWORD SizeOfStruct; + DWORD64 Address; + DWORD Size; + DWORD Flags; + DWORD MaxNameLength; + CHAR Name[1]; + } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64; + + typedef struct _tagADDRESS64 { + DWORD64 Offset; + WORD Segment; + ADDRESS_MODE Mode; + } ADDRESS64, *LPADDRESS64; + + typedef struct _KDHELP64 { + DWORD64 Thread; + DWORD ThCallbackStack; + DWORD ThCallbackBStore; + DWORD NextCallback; + DWORD FramePointer; + DWORD64 KiCallUserMode; + DWORD64 KeUserCallbackDispatcher; + DWORD64 SystemRangeStart; + DWORD64 KiUserExceptionDispatcher; + DWORD64 StackBase; + DWORD64 StackLimit; + DWORD64 Reserved[5]; + } KDHELP64, *PKDHELP64; + + typedef struct _tagSTACKFRAME64 { + ADDRESS64 AddrPC; + ADDRESS64 AddrReturn; + ADDRESS64 AddrFrame; + ADDRESS64 AddrStack; + ADDRESS64 AddrBStore; + PVOID FuncTableEntry; + DWORD64 Params[4]; + BOOL Far; + BOOL Virtual; + DWORD64 Reserved[3]; + KDHELP64 KdHelp; + } STACKFRAME64, *LPSTACKFRAME64; + #endif // !defined(__MINGW64_VERSION_MAJOR) +#endif // __MINGW32__ + +typedef BOOL (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess, + DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, + LPDWORD lpNumberOfBytesRead); + +typedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( HANDLE ahProcess, + DWORD64 AddrBase); + +typedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess, + DWORD64 Address); + +typedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess, + HANDLE hThread, LPADDRESS64 lpaddr); + +typedef BOOL(WINAPI *fpMiniDumpWriteDump)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE, + PMINIDUMP_EXCEPTION_INFORMATION, + PMINIDUMP_USER_STREAM_INFORMATION, + PMINIDUMP_CALLBACK_INFORMATION); +static fpMiniDumpWriteDump fMiniDumpWriteDump; + +typedef BOOL (WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64, + PVOID, PREAD_PROCESS_MEMORY_ROUTINE64, + PFUNCTION_TABLE_ACCESS_ROUTINE64, + PGET_MODULE_BASE_ROUTINE64, + PTRANSLATE_ADDRESS_ROUTINE64); +static fpStackWalk64 fStackWalk64; + +typedef DWORD64 (WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64); +static fpSymGetModuleBase64 fSymGetModuleBase64; + +typedef BOOL (WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64, + PDWORD64, PIMAGEHLP_SYMBOL64); +static fpSymGetSymFromAddr64 fSymGetSymFromAddr64; + +typedef BOOL (WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64, + PDWORD, PIMAGEHLP_LINE64); +static fpSymGetLineFromAddr64 fSymGetLineFromAddr64; + +typedef BOOL(WINAPI *fpSymGetModuleInfo64)(HANDLE hProcess, DWORD64 dwAddr, + PIMAGEHLP_MODULE64 ModuleInfo); +static fpSymGetModuleInfo64 fSymGetModuleInfo64; + +typedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64); +static fpSymFunctionTableAccess64 fSymFunctionTableAccess64; + +typedef DWORD (WINAPI *fpSymSetOptions)(DWORD); +static fpSymSetOptions fSymSetOptions; + +typedef BOOL (WINAPI *fpSymInitialize)(HANDLE, PCSTR, BOOL); +static fpSymInitialize fSymInitialize; + +typedef BOOL (WINAPI *fpEnumerateLoadedModules)(HANDLE,PENUMLOADED_MODULES_CALLBACK64,PVOID); +static fpEnumerateLoadedModules fEnumerateLoadedModules; + +static bool load64BitDebugHelp(void) { + HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll"); + if (hLib) { + fMiniDumpWriteDump = (fpMiniDumpWriteDump) + ::GetProcAddress(hLib, "MiniDumpWriteDump"); + fStackWalk64 = (fpStackWalk64) + ::GetProcAddress(hLib, "StackWalk64"); + fSymGetModuleBase64 = (fpSymGetModuleBase64) + ::GetProcAddress(hLib, "SymGetModuleBase64"); + fSymGetSymFromAddr64 = (fpSymGetSymFromAddr64) + ::GetProcAddress(hLib, "SymGetSymFromAddr64"); + fSymGetLineFromAddr64 = (fpSymGetLineFromAddr64) + ::GetProcAddress(hLib, "SymGetLineFromAddr64"); + fSymGetModuleInfo64 = (fpSymGetModuleInfo64) + ::GetProcAddress(hLib, "SymGetModuleInfo64"); + fSymFunctionTableAccess64 = (fpSymFunctionTableAccess64) + ::GetProcAddress(hLib, "SymFunctionTableAccess64"); + fSymSetOptions = (fpSymSetOptions)::GetProcAddress(hLib, "SymSetOptions"); + fSymInitialize = (fpSymInitialize)::GetProcAddress(hLib, "SymInitialize"); + fEnumerateLoadedModules = (fpEnumerateLoadedModules) + ::GetProcAddress(hLib, "EnumerateLoadedModules64"); + } + return fStackWalk64 && fSymInitialize && fSymSetOptions && fMiniDumpWriteDump; +} + +using namespace llvm; + +// Forward declare. +static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep); +static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType); + +// InterruptFunction - The function to call if ctrl-c is pressed. +static void (*InterruptFunction)() = 0; + +static std::vector<std::string> *FilesToRemove = NULL; +static bool RegisteredUnhandledExceptionFilter = false; +static bool CleanupExecuted = false; +static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL; + +// Windows creates a new thread to execute the console handler when an event +// (such as CTRL/C) occurs. This causes concurrency issues with the above +// globals which this critical section addresses. +static CRITICAL_SECTION CriticalSection; +static bool CriticalSectionInitialized = false; + +static StringRef Argv0; + +enum { +#if defined(_M_X64) + NativeMachineType = IMAGE_FILE_MACHINE_AMD64 +#else + NativeMachineType = IMAGE_FILE_MACHINE_I386 +#endif +}; + +static bool printStackTraceWithLLVMSymbolizer(llvm::raw_ostream &OS, + HANDLE hProcess, HANDLE hThread, + STACKFRAME64 &StackFrameOrig, + CONTEXT *ContextOrig) { + // StackWalk64 modifies the incoming stack frame and context, so copy them. + STACKFRAME64 StackFrame = StackFrameOrig; + + // Copy the register context so that we don't modify it while we unwind. We + // could use InitializeContext + CopyContext, but that's only required to get + // at AVX registers, which typically aren't needed by StackWalk64. Reduce the + // flag set to indicate that there's less data. + CONTEXT Context = *ContextOrig; + Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; + + static void *StackTrace[256]; + size_t Depth = 0; + while (fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame, + &Context, 0, fSymFunctionTableAccess64, + fSymGetModuleBase64, 0)) { + if (StackFrame.AddrFrame.Offset == 0) + break; + StackTrace[Depth++] = (void *)(uintptr_t)StackFrame.AddrPC.Offset; + if (Depth >= array_lengthof(StackTrace)) + break; + } + + return printSymbolizedStackTrace(Argv0, &StackTrace[0], Depth, OS); +} + +namespace { +struct FindModuleData { + void **StackTrace; + int Depth; + const char **Modules; + intptr_t *Offsets; + StringSaver *StrPool; +}; +} + +static BOOL CALLBACK findModuleCallback(PCSTR ModuleName, + DWORD64 ModuleBase, ULONG ModuleSize, + void *VoidData) { + FindModuleData *Data = (FindModuleData*)VoidData; + intptr_t Beg = ModuleBase; + intptr_t End = Beg + ModuleSize; + for (int I = 0; I < Data->Depth; I++) { + if (Data->Modules[I]) + continue; + intptr_t Addr = (intptr_t)Data->StackTrace[I]; + if (Beg <= Addr && Addr < End) { + Data->Modules[I] = Data->StrPool->save(ModuleName); + Data->Offsets[I] = Addr - Beg; + } + } + return TRUE; +} + +static bool findModulesAndOffsets(void **StackTrace, int Depth, + const char **Modules, intptr_t *Offsets, + const char *MainExecutableName, + StringSaver &StrPool) { + if (!fEnumerateLoadedModules) + return false; + FindModuleData Data; + Data.StackTrace = StackTrace; + Data.Depth = Depth; + Data.Modules = Modules; + Data.Offsets = Offsets; + Data.StrPool = &StrPool; + fEnumerateLoadedModules(GetCurrentProcess(), findModuleCallback, &Data); + return true; +} + +static void PrintStackTraceForThread(llvm::raw_ostream &OS, HANDLE hProcess, + HANDLE hThread, STACKFRAME64 &StackFrame, + CONTEXT *Context) { + // Initialize the symbol handler. + fSymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES); + fSymInitialize(hProcess, NULL, TRUE); + + // Try llvm-symbolizer first. llvm-symbolizer knows how to deal with both PDBs + // and DWARF, so it should do a good job regardless of what debug info or + // linker is in use. + if (printStackTraceWithLLVMSymbolizer(OS, hProcess, hThread, StackFrame, + Context)) { + return; + } + + while (true) { + if (!fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame, + Context, 0, fSymFunctionTableAccess64, + fSymGetModuleBase64, 0)) { + break; + } + + if (StackFrame.AddrFrame.Offset == 0) + break; + + using namespace llvm; + // Print the PC in hexadecimal. + DWORD64 PC = StackFrame.AddrPC.Offset; +#if defined(_M_X64) + OS << format("0x%016llX", PC); +#elif defined(_M_IX86) + OS << format("0x%08lX", static_cast<DWORD>(PC)); +#endif + +// Print the parameters. Assume there are four. +#if defined(_M_X64) + OS << format(" (0x%016llX 0x%016llX 0x%016llX 0x%016llX)", + StackFrame.Params[0], StackFrame.Params[1], StackFrame.Params[2], + StackFrame.Params[3]); +#elif defined(_M_IX86) + OS << format(" (0x%08lX 0x%08lX 0x%08lX 0x%08lX)", + static_cast<DWORD>(StackFrame.Params[0]), + static_cast<DWORD>(StackFrame.Params[1]), + static_cast<DWORD>(StackFrame.Params[2]), + static_cast<DWORD>(StackFrame.Params[3])); +#endif + // Verify the PC belongs to a module in this process. + if (!fSymGetModuleBase64(hProcess, PC)) { + OS << " <unknown module>\n"; + continue; + } + + // Print the symbol name. + char buffer[512]; + IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer); + memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64)); + symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); + symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64); + + DWORD64 dwDisp; + if (!fSymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) { + OS << '\n'; + continue; + } + + buffer[511] = 0; + if (dwDisp > 0) + OS << format(", %s() + 0x%llX bytes(s)", (const char*)symbol->Name, + dwDisp); + else + OS << format(", %s", (const char*)symbol->Name); + + // Print the source file and line number information. + IMAGEHLP_LINE64 line = {}; + DWORD dwLineDisp; + line.SizeOfStruct = sizeof(line); + if (fSymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) { + OS << format(", %s, line %lu", line.FileName, line.LineNumber); + if (dwLineDisp > 0) + OS << format(" + 0x%lX byte(s)", dwLineDisp); + } + + OS << '\n'; + } +} + +namespace llvm { + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code +//=== and must not be UNIX code +//===----------------------------------------------------------------------===// + +#ifdef _MSC_VER +/// AvoidMessageBoxHook - Emulates hitting "retry" from an "abort, retry, +/// ignore" CRT debug report dialog. "retry" raises an exception which +/// ultimately triggers our stack dumper. +static LLVM_ATTRIBUTE_UNUSED int +AvoidMessageBoxHook(int ReportType, char *Message, int *Return) { + // Set *Return to the retry code for the return value of _CrtDbgReport: + // http://msdn.microsoft.com/en-us/library/8hyw4sy7(v=vs.71).aspx + // This may also trigger just-in-time debugging via DebugBreak(). + if (Return) + *Return = 1; + // Don't call _CrtDbgReport. + return TRUE; +} + +#endif + +extern "C" void HandleAbort(int Sig) { + if (Sig == SIGABRT) { + LLVM_BUILTIN_TRAP; + } +} + +static void InitializeThreading() { + if (CriticalSectionInitialized) + return; + + // Now's the time to create the critical section. This is the first time + // through here, and there's only one thread. + InitializeCriticalSection(&CriticalSection); + CriticalSectionInitialized = true; +} + +static void RegisterHandler() { + // If we cannot load up the APIs (which would be unexpected as they should + // exist on every version of Windows we support), we will bail out since + // there would be nothing to report. + if (!load64BitDebugHelp()) { + assert(false && "These APIs should always be available"); + return; + } + + if (RegisteredUnhandledExceptionFilter) { + EnterCriticalSection(&CriticalSection); + return; + } + + InitializeThreading(); + + // Enter it immediately. Now if someone hits CTRL/C, the console handler + // can't proceed until the globals are updated. + EnterCriticalSection(&CriticalSection); + + RegisteredUnhandledExceptionFilter = true; + OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter); + SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE); + + // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or + // else multi-threading problems will ensue. +} + +// RemoveFileOnSignal - The public API +bool sys::RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg) { + RegisterHandler(); + + if (CleanupExecuted) { + if (ErrMsg) + *ErrMsg = "Process terminating -- cannot register for removal"; + return true; + } + + if (FilesToRemove == NULL) + FilesToRemove = new std::vector<std::string>; + + FilesToRemove->push_back(Filename); + + LeaveCriticalSection(&CriticalSection); + return false; +} + +// DontRemoveFileOnSignal - The public API +void sys::DontRemoveFileOnSignal(StringRef Filename) { + if (FilesToRemove == NULL) + return; + + RegisterHandler(); + + std::vector<std::string>::reverse_iterator I = + find(reverse(*FilesToRemove), Filename); + if (I != FilesToRemove->rend()) + FilesToRemove->erase(I.base()-1); + + LeaveCriticalSection(&CriticalSection); +} + +void sys::DisableSystemDialogsOnCrash() { + // Crash to stack trace handler on abort. + signal(SIGABRT, HandleAbort); + + // The following functions are not reliably accessible on MinGW. +#ifdef _MSC_VER + // We're already handling writing a "something went wrong" message. + _set_abort_behavior(0, _WRITE_ABORT_MSG); + // Disable Dr. Watson. + _set_abort_behavior(0, _CALL_REPORTFAULT); + _CrtSetReportHook(AvoidMessageBoxHook); +#endif + + // Disable standard error dialog box. + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | + SEM_NOOPENFILEERRORBOX); + _set_error_mode(_OUT_TO_STDERR); +} + +/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or +/// SIGSEGV) is delivered to the process, print a stack trace and then exit. +void sys::PrintStackTraceOnErrorSignal(StringRef Argv0, + bool DisableCrashReporting) { + ::Argv0 = Argv0; + + if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT")) + Process::PreventCoreFiles(); + + DisableSystemDialogsOnCrash(); + RegisterHandler(); + LeaveCriticalSection(&CriticalSection); +} +} + +#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) +// Provide a prototype for RtlCaptureContext, mingw32 from mingw.org is +// missing it but mingw-w64 has it. +extern "C" VOID WINAPI RtlCaptureContext(PCONTEXT ContextRecord); +#endif + +void llvm::sys::PrintStackTrace(raw_ostream &OS) { + STACKFRAME64 StackFrame = {}; + CONTEXT Context = {}; + ::RtlCaptureContext(&Context); +#if defined(_M_X64) + StackFrame.AddrPC.Offset = Context.Rip; + StackFrame.AddrStack.Offset = Context.Rsp; + StackFrame.AddrFrame.Offset = Context.Rbp; +#else + StackFrame.AddrPC.Offset = Context.Eip; + StackFrame.AddrStack.Offset = Context.Esp; + StackFrame.AddrFrame.Offset = Context.Ebp; +#endif + StackFrame.AddrPC.Mode = AddrModeFlat; + StackFrame.AddrStack.Mode = AddrModeFlat; + StackFrame.AddrFrame.Mode = AddrModeFlat; + PrintStackTraceForThread(OS, GetCurrentProcess(), GetCurrentThread(), + StackFrame, &Context); +} + + +void llvm::sys::SetInterruptFunction(void (*IF)()) { + RegisterHandler(); + InterruptFunction = IF; + LeaveCriticalSection(&CriticalSection); +} + + +/// AddSignalHandler - Add a function to be called when a signal is delivered +/// to the process. The handler can have a cookie passed to it to identify +/// what instance of the handler it is. +void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { + CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie)); + RegisterHandler(); + LeaveCriticalSection(&CriticalSection); +} + +static void Cleanup() { + if (CleanupExecuted) + return; + + EnterCriticalSection(&CriticalSection); + + // Prevent other thread from registering new files and directories for + // removal, should we be executing because of the console handler callback. + CleanupExecuted = true; + + // FIXME: open files cannot be deleted. + if (FilesToRemove != NULL) + while (!FilesToRemove->empty()) { + llvm::sys::fs::remove(FilesToRemove->back()); + FilesToRemove->pop_back(); + } + llvm::sys::RunSignalHandlers(); + LeaveCriticalSection(&CriticalSection); +} + +void llvm::sys::RunInterruptHandlers() { + // The interrupt handler may be called from an interrupt, but it may also be + // called manually (such as the case of report_fatal_error with no registered + // error handler). We must ensure that the critical section is properly + // initialized. + InitializeThreading(); + Cleanup(); +} + +/// \brief Find the Windows Registry Key for a given location. +/// +/// \returns a valid HKEY if the location exists, else NULL. +static HKEY FindWERKey(const llvm::Twine &RegistryLocation) { + HKEY Key; + if (ERROR_SUCCESS != ::RegOpenKeyExA(HKEY_LOCAL_MACHINE, + RegistryLocation.str().c_str(), 0, + KEY_QUERY_VALUE | KEY_READ, &Key)) + return NULL; + + return Key; +} + +/// \brief Populate ResultDirectory with the value for "DumpFolder" for a given +/// Windows Registry key. +/// +/// \returns true if a valid value for DumpFolder exists, false otherwise. +static bool GetDumpFolder(HKEY Key, + llvm::SmallVectorImpl<char> &ResultDirectory) { + using llvm::sys::windows::UTF16ToUTF8; + + if (!Key) + return false; + + DWORD BufferLengthBytes = 0; + + if (ERROR_SUCCESS != ::RegGetValueW(Key, 0, L"DumpFolder", REG_EXPAND_SZ, + NULL, NULL, &BufferLengthBytes)) + return false; + + SmallVector<wchar_t, MAX_PATH> Buffer(BufferLengthBytes); + + if (ERROR_SUCCESS != ::RegGetValueW(Key, 0, L"DumpFolder", REG_EXPAND_SZ, + NULL, Buffer.data(), &BufferLengthBytes)) + return false; + + DWORD ExpandBufferSize = ::ExpandEnvironmentStringsW(Buffer.data(), NULL, 0); + + if (!ExpandBufferSize) + return false; + + SmallVector<wchar_t, MAX_PATH> ExpandBuffer(ExpandBufferSize); + + if (ExpandBufferSize != ::ExpandEnvironmentStringsW(Buffer.data(), + ExpandBuffer.data(), + ExpandBufferSize)) + return false; + + if (UTF16ToUTF8(ExpandBuffer.data(), ExpandBufferSize - 1, ResultDirectory)) + return false; + + return true; +} + +/// \brief Populate ResultType with a valid MINIDUMP_TYPE based on the value of +/// "DumpType" for a given Windows Registry key. +/// +/// According to +/// https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181(v=vs.85).aspx +/// valid values for DumpType are: +/// * 0: Custom dump +/// * 1: Mini dump +/// * 2: Full dump +/// If "Custom dump" is specified then the "CustomDumpFlags" field is read +/// containing a bitwise combination of MINIDUMP_TYPE values. +/// +/// \returns true if a valid value for ResultType can be set, false otherwise. +static bool GetDumpType(HKEY Key, MINIDUMP_TYPE &ResultType) { + if (!Key) + return false; + + DWORD DumpType; + DWORD TypeSize = sizeof(DumpType); + if (ERROR_SUCCESS != ::RegGetValueW(Key, NULL, L"DumpType", RRF_RT_REG_DWORD, + NULL, &DumpType, + &TypeSize)) + return false; + + switch (DumpType) { + case 0: { + DWORD Flags = 0; + if (ERROR_SUCCESS != ::RegGetValueW(Key, NULL, L"CustomDumpFlags", + RRF_RT_REG_DWORD, NULL, &Flags, + &TypeSize)) + return false; + + ResultType = static_cast<MINIDUMP_TYPE>(Flags); + break; + } + case 1: + ResultType = MiniDumpNormal; + break; + case 2: + ResultType = MiniDumpWithFullMemory; + break; + default: + return false; + } + return true; +} + +/// \brief Write a Windows dump file containing process information that can be +/// used for post-mortem debugging. +/// +/// \returns zero error code if a mini dump created, actual error code +/// otherwise. +static std::error_code WINAPI +WriteWindowsDumpFile(PMINIDUMP_EXCEPTION_INFORMATION ExceptionInfo) { + using namespace llvm; + using namespace llvm::sys; + + std::string MainExecutableName = fs::getMainExecutable(nullptr, nullptr); + StringRef ProgramName; + + if (MainExecutableName.empty()) { + // If we can't get the executable filename, + // things are in worse shape than we realize + // and we should just bail out. + return mapWindowsError(::GetLastError()); + } + + ProgramName = path::filename(MainExecutableName.c_str()); + + // The Windows Registry location as specified at + // https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181%28v=vs.85%29.aspx + // "Collecting User-Mode Dumps" that may optionally be set to collect crash + // dumps in a specified location. + StringRef LocalDumpsRegistryLocation = + "SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps"; + + // The key pointing to the Registry location that may contain global crash + // dump settings. This will be NULL if the location can not be found. + ScopedRegHandle DefaultLocalDumpsKey(FindWERKey(LocalDumpsRegistryLocation)); + + // The key pointing to the Registry location that may contain + // application-specific crash dump settings. This will be NULL if the + // location can not be found. + ScopedRegHandle AppSpecificKey( + FindWERKey(Twine(LocalDumpsRegistryLocation) + "\\" + ProgramName)); + + // Look to see if a dump type is specified in the registry; first with the + // app-specific key and failing that with the global key. If none are found + // default to a normal dump (GetDumpType will return false either if the key + // is NULL or if there is no valid DumpType value at its location). + MINIDUMP_TYPE DumpType; + if (!GetDumpType(AppSpecificKey, DumpType)) + if (!GetDumpType(DefaultLocalDumpsKey, DumpType)) + DumpType = MiniDumpNormal; + + // Look to see if a dump location is specified in the registry; first with the + // app-specific key and failing that with the global key. If none are found + // we'll just create the dump file in the default temporary file location + // (GetDumpFolder will return false either if the key is NULL or if there is + // no valid DumpFolder value at its location). + bool ExplicitDumpDirectorySet = true; + SmallString<MAX_PATH> DumpDirectory; + if (!GetDumpFolder(AppSpecificKey, DumpDirectory)) + if (!GetDumpFolder(DefaultLocalDumpsKey, DumpDirectory)) + ExplicitDumpDirectorySet = false; + + int FD; + SmallString<MAX_PATH> DumpPath; + + if (ExplicitDumpDirectorySet) { + if (std::error_code EC = fs::create_directories(DumpDirectory)) + return EC; + if (std::error_code EC = fs::createUniqueFile( + Twine(DumpDirectory) + "\\" + ProgramName + ".%%%%%%.dmp", FD, + DumpPath)) + return EC; + } else if (std::error_code EC = + fs::createTemporaryFile(ProgramName, "dmp", FD, DumpPath)) + return EC; + + // Our support functions return a file descriptor but Windows wants a handle. + ScopedCommonHandle FileHandle(reinterpret_cast<HANDLE>(_get_osfhandle(FD))); + + if (!fMiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), + FileHandle, DumpType, ExceptionInfo, NULL, NULL)) + return mapWindowsError(::GetLastError()); + + llvm::errs() << "Wrote crash dump file \"" << DumpPath << "\"\n"; + return std::error_code(); +} + +static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { + Cleanup(); + + // We'll automatically write a Minidump file here to help diagnose + // the nasty sorts of crashes that aren't 100% reproducible from a set of + // inputs (or in the event that the user is unable or unwilling to provide a + // reproducible case). + if (!llvm::Process::AreCoreFilesPrevented()) { + MINIDUMP_EXCEPTION_INFORMATION ExceptionInfo; + ExceptionInfo.ThreadId = ::GetCurrentThreadId(); + ExceptionInfo.ExceptionPointers = ep; + ExceptionInfo.ClientPointers = FALSE; + + if (std::error_code EC = WriteWindowsDumpFile(&ExceptionInfo)) + llvm::errs() << "Could not write crash dump file: " << EC.message() + << "\n"; + } + + // Initialize the STACKFRAME structure. + STACKFRAME64 StackFrame = {}; + +#if defined(_M_X64) + StackFrame.AddrPC.Offset = ep->ContextRecord->Rip; + StackFrame.AddrPC.Mode = AddrModeFlat; + StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp; + StackFrame.AddrStack.Mode = AddrModeFlat; + StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp; + StackFrame.AddrFrame.Mode = AddrModeFlat; +#elif defined(_M_IX86) + StackFrame.AddrPC.Offset = ep->ContextRecord->Eip; + StackFrame.AddrPC.Mode = AddrModeFlat; + StackFrame.AddrStack.Offset = ep->ContextRecord->Esp; + StackFrame.AddrStack.Mode = AddrModeFlat; + StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp; + StackFrame.AddrFrame.Mode = AddrModeFlat; +#endif + + HANDLE hProcess = GetCurrentProcess(); + HANDLE hThread = GetCurrentThread(); + PrintStackTraceForThread(llvm::errs(), hProcess, hThread, StackFrame, + ep->ContextRecord); + + _exit(ep->ExceptionRecord->ExceptionCode); +} + +static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) { + // We are running in our very own thread, courtesy of Windows. + EnterCriticalSection(&CriticalSection); + Cleanup(); + + // If an interrupt function has been set, go and run one it; otherwise, + // the process dies. + void (*IF)() = InterruptFunction; + InterruptFunction = 0; // Don't run it on another CTRL-C. + + if (IF) { + // Note: if the interrupt function throws an exception, there is nothing + // to catch it in this thread so it will kill the process. + IF(); // Run it now. + LeaveCriticalSection(&CriticalSection); + return TRUE; // Don't kill the process. + } + + // Allow normal processing to take place; i.e., the process dies. + LeaveCriticalSection(&CriticalSection); + return FALSE; +} + +#if __MINGW32__ + // We turned these warnings off for this file so that MinGW-g++ doesn't + // complain about the ll format specifiers used. Now we are turning the + // warnings back on. If MinGW starts to support diagnostic stacks, we can + // replace this with a pop. + #pragma GCC diagnostic warning "-Wformat" + #pragma GCC diagnostic warning "-Wformat-extra-args" +#endif
diff --git a/third_party/llvm-subzero/lib/Support/Windows/TimeValue.inc b/third_party/llvm-subzero/lib/Support/Windows/TimeValue.inc new file mode 100644 index 0000000..b90b4f1 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Windows/TimeValue.inc
@@ -0,0 +1,61 @@ +//===- Win32/TimeValue.cpp - Win32 TimeValue Implementation -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the Win32 implementation of the TimeValue class. +// +//===----------------------------------------------------------------------===// + +#include "WindowsSupport.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include <cctype> +#include <time.h> + +using namespace llvm; +using namespace llvm::sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code. +//===----------------------------------------------------------------------===// + +TimeValue TimeValue::now() { + uint64_t ft; + GetSystemTimeAsFileTime(reinterpret_cast<FILETIME *>(&ft)); + + TimeValue t(0, 0); + t.fromWin32Time(ft); + return t; +} + +std::string TimeValue::str() const { + std::string S; + struct tm *LT; +#ifdef __MINGW32__ + // Old versions of mingw don't have _localtime64_s. Remove this once we drop support + // for them. + time_t OurTime = time_t(this->toEpochTime()); + LT = ::localtime(&OurTime); + assert(LT); +#else + struct tm Storage; + __time64_t OurTime = this->toEpochTime(); + int Error = ::_localtime64_s(&Storage, &OurTime); + assert(!Error); + (void)Error; + LT = &Storage; +#endif + + char Buffer[sizeof("YYYY-MM-DD HH:MM:SS")]; + strftime(Buffer, sizeof(Buffer), "%Y-%m-%d %H:%M:%S", LT); + raw_string_ostream OS(S); + OS << format("%s.%.9u", static_cast<const char *>(Buffer), + this->nanoseconds()); + OS.flush(); + return S; +}
diff --git a/third_party/llvm-subzero/lib/Support/Windows/WindowsSupport.h b/third_party/llvm-subzero/lib/Support/Windows/WindowsSupport.h new file mode 100644 index 0000000..18ecdf4 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/Windows/WindowsSupport.h
@@ -0,0 +1,230 @@ +//===- WindowsSupport.h - Common Windows Include File -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines things specific to Windows implementations. In addition to +// providing some helpers for working with win32 APIs, this header wraps +// <windows.h> with some portability macros. Always include WindowsSupport.h +// instead of including <windows.h> directly. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Win32 code that +//=== is guaranteed to work on *all* Win32 variants. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_WINDOWSSUPPORT_H +#define LLVM_SUPPORT_WINDOWSSUPPORT_H + +// mingw-w64 tends to define it as 0x0502 in its headers. +#undef _WIN32_WINNT +#undef _WIN32_IE + +// Require at least Windows 7 API. +#define _WIN32_WINNT 0x0601 +#define _WIN32_IE 0x0800 // MinGW at it again. FIXME: verify if still needed. +#define WIN32_LEAN_AND_MEAN +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Config/config.h" // Get build system configuration settings +#include "llvm/Support/Compiler.h" +#include <system_error> +#include <windows.h> +#include <wincrypt.h> +#include <cassert> +#include <string> + +/// Determines if the program is running on Windows 8 or newer. This +/// reimplements one of the helpers in the Windows 8.1 SDK, which are intended +/// to supercede raw calls to GetVersionEx. Old SDKs, Cygwin, and MinGW don't +/// yet have VersionHelpers.h, so we have our own helper. +inline bool RunningWindows8OrGreater() { + // Windows 8 is version 6.2, service pack 0. + OSVERSIONINFOEXW osvi = {}; + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + osvi.dwMajorVersion = 6; + osvi.dwMinorVersion = 2; + osvi.wServicePackMajor = 0; + + DWORDLONG Mask = 0; + Mask = VerSetConditionMask(Mask, VER_MAJORVERSION, VER_GREATER_EQUAL); + Mask = VerSetConditionMask(Mask, VER_MINORVERSION, VER_GREATER_EQUAL); + Mask = VerSetConditionMask(Mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); + + return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | + VER_SERVICEPACKMAJOR, + Mask) != FALSE; +} + +inline bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix) { + if (!ErrMsg) + return true; + char *buffer = NULL; + DWORD LastError = GetLastError(); + DWORD R = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_MAX_WIDTH_MASK, + NULL, LastError, 0, (LPSTR)&buffer, 1, NULL); + if (R) + *ErrMsg = prefix + ": " + buffer; + else + *ErrMsg = prefix + ": Unknown error"; + *ErrMsg += " (0x" + llvm::utohexstr(LastError) + ")"; + + LocalFree(buffer); + return R != 0; +} + +template <typename HandleTraits> +class ScopedHandle { + typedef typename HandleTraits::handle_type handle_type; + handle_type Handle; + + ScopedHandle(const ScopedHandle &other); // = delete; + void operator=(const ScopedHandle &other); // = delete; +public: + ScopedHandle() + : Handle(HandleTraits::GetInvalid()) {} + + explicit ScopedHandle(handle_type h) + : Handle(h) {} + + ~ScopedHandle() { + if (HandleTraits::IsValid(Handle)) + HandleTraits::Close(Handle); + } + + handle_type take() { + handle_type t = Handle; + Handle = HandleTraits::GetInvalid(); + return t; + } + + ScopedHandle &operator=(handle_type h) { + if (HandleTraits::IsValid(Handle)) + HandleTraits::Close(Handle); + Handle = h; + return *this; + } + + // True if Handle is valid. + explicit operator bool() const { + return HandleTraits::IsValid(Handle) ? true : false; + } + + operator handle_type() const { + return Handle; + } +}; + +struct CommonHandleTraits { + typedef HANDLE handle_type; + + static handle_type GetInvalid() { + return INVALID_HANDLE_VALUE; + } + + static void Close(handle_type h) { + ::CloseHandle(h); + } + + static bool IsValid(handle_type h) { + return h != GetInvalid(); + } +}; + +struct JobHandleTraits : CommonHandleTraits { + static handle_type GetInvalid() { + return NULL; + } +}; + +struct CryptContextTraits : CommonHandleTraits { + typedef HCRYPTPROV handle_type; + + static handle_type GetInvalid() { + return 0; + } + + static void Close(handle_type h) { + ::CryptReleaseContext(h, 0); + } + + static bool IsValid(handle_type h) { + return h != GetInvalid(); + } +}; + +struct RegTraits : CommonHandleTraits { + typedef HKEY handle_type; + + static handle_type GetInvalid() { + return NULL; + } + + static void Close(handle_type h) { + ::RegCloseKey(h); + } + + static bool IsValid(handle_type h) { + return h != GetInvalid(); + } +}; + +struct FindHandleTraits : CommonHandleTraits { + static void Close(handle_type h) { + ::FindClose(h); + } +}; + +struct FileHandleTraits : CommonHandleTraits {}; + +typedef ScopedHandle<CommonHandleTraits> ScopedCommonHandle; +typedef ScopedHandle<FileHandleTraits> ScopedFileHandle; +typedef ScopedHandle<CryptContextTraits> ScopedCryptContext; +typedef ScopedHandle<RegTraits> ScopedRegHandle; +typedef ScopedHandle<FindHandleTraits> ScopedFindHandle; +typedef ScopedHandle<JobHandleTraits> ScopedJobHandle; + +namespace llvm { +template <class T> +class SmallVectorImpl; + +template <class T> +typename SmallVectorImpl<T>::const_pointer +c_str(SmallVectorImpl<T> &str) { + str.push_back(0); + str.pop_back(); + return str.data(); +} + +namespace sys { +namespace path { +std::error_code widenPath(const Twine &Path8, + SmallVectorImpl<wchar_t> &Path16); +} // end namespace path + +namespace windows { +std::error_code UTF8ToUTF16(StringRef utf8, SmallVectorImpl<wchar_t> &utf16); +std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, + SmallVectorImpl<char> &utf8); +/// Convert from UTF16 to the current code page used in the system +std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len, + SmallVectorImpl<char> &utf8); +} // end namespace windows +} // end namespace sys +} // end namespace llvm. + +#endif
diff --git a/third_party/llvm-subzero/lib/Support/circular_raw_ostream.cpp b/third_party/llvm-subzero/lib/Support/circular_raw_ostream.cpp new file mode 100644 index 0000000..ca0d30d --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/circular_raw_ostream.cpp
@@ -0,0 +1,45 @@ +//===- circular_raw_ostream.cpp - Implement circular_raw_ostream ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements support for circular buffered streams. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/circular_raw_ostream.h" +#include <algorithm> +using namespace llvm; + +void circular_raw_ostream::write_impl(const char *Ptr, size_t Size) { + if (BufferSize == 0) { + TheStream->write(Ptr, Size); + return; + } + + // Write into the buffer, wrapping if necessary. + while (Size != 0) { + unsigned Bytes = + std::min(unsigned(Size), unsigned(BufferSize - (Cur - BufferArray))); + memcpy(Cur, Ptr, Bytes); + Size -= Bytes; + Cur += Bytes; + if (Cur == BufferArray + BufferSize) { + // Reset the output pointer to the start of the buffer. + Cur = BufferArray; + Filled = true; + } + } +} + +void circular_raw_ostream::flushBufferWithBanner() { + if (BufferSize != 0) { + // Write out the buffer + TheStream->write(Banner, std::strlen(Banner)); + flushBuffer(); + } +}
diff --git a/third_party/llvm-subzero/lib/Support/raw_os_ostream.cpp b/third_party/llvm-subzero/lib/Support/raw_os_ostream.cpp new file mode 100644 index 0000000..44f2325 --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/raw_os_ostream.cpp
@@ -0,0 +1,30 @@ +//===--- raw_os_ostream.cpp - Implement the raw_os_ostream class ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements support adapting raw_ostream to std::ostream. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/raw_os_ostream.h" +#include <ostream> +using namespace llvm; + +//===----------------------------------------------------------------------===// +// raw_os_ostream +//===----------------------------------------------------------------------===// + +raw_os_ostream::~raw_os_ostream() { + flush(); +} + +void raw_os_ostream::write_impl(const char *Ptr, size_t Size) { + OS.write(Ptr, Size); +} + +uint64_t raw_os_ostream::current_pos() const { return OS.tellp(); }
diff --git a/third_party/llvm-subzero/lib/Support/raw_ostream.cpp b/third_party/llvm-subzero/lib/Support/raw_ostream.cpp new file mode 100644 index 0000000..df4c8dc --- /dev/null +++ b/third_party/llvm-subzero/lib/Support/raw_ostream.cpp
@@ -0,0 +1,789 @@ +//===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements support for bulk buffered stream output. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Config/config.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" +#include <algorithm> +#include <cctype> +#include <cerrno> +#include <cstdio> +#include <iterator> +#include <system_error> +#include <sys/stat.h> + +// <fcntl.h> may provide O_BINARY. +#if defined(HAVE_FCNTL_H) +# include <fcntl.h> +#endif + +#if defined(HAVE_UNISTD_H) +# include <unistd.h> +#endif +#if defined(HAVE_SYS_UIO_H) && defined(HAVE_WRITEV) +# include <sys/uio.h> +#endif + +#if defined(__CYGWIN__) +#include <io.h> +#endif + +#if defined(_MSC_VER) +#include <io.h> +#ifndef STDIN_FILENO +# define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +# define STDOUT_FILENO 1 +#endif +#ifndef STDERR_FILENO +# define STDERR_FILENO 2 +#endif +#endif + +#ifdef LLVM_ON_WIN32 +#include "Windows/WindowsSupport.h" +#endif + +using namespace llvm; + +raw_ostream::~raw_ostream() { + // raw_ostream's subclasses should take care to flush the buffer + // in their destructors. + assert(OutBufCur == OutBufStart && + "raw_ostream destructor called with non-empty buffer!"); + + if (BufferMode == InternalBuffer) + delete [] OutBufStart; +} + +// An out of line virtual method to provide a home for the class vtable. +void raw_ostream::handle() {} + +size_t raw_ostream::preferred_buffer_size() const { + // BUFSIZ is intended to be a reasonable default. + return BUFSIZ; +} + +void raw_ostream::SetBuffered() { + // Ask the subclass to determine an appropriate buffer size. + if (size_t Size = preferred_buffer_size()) + SetBufferSize(Size); + else + // It may return 0, meaning this stream should be unbuffered. + SetUnbuffered(); +} + +void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size, + BufferKind Mode) { + assert(((Mode == Unbuffered && !BufferStart && Size == 0) || + (Mode != Unbuffered && BufferStart && Size != 0)) && + "stream must be unbuffered or have at least one byte"); + // Make sure the current buffer is free of content (we can't flush here; the + // child buffer management logic will be in write_impl). + assert(GetNumBytesInBuffer() == 0 && "Current buffer is non-empty!"); + + if (BufferMode == InternalBuffer) + delete [] OutBufStart; + OutBufStart = BufferStart; + OutBufEnd = OutBufStart+Size; + OutBufCur = OutBufStart; + BufferMode = Mode; + + assert(OutBufStart <= OutBufEnd && "Invalid size!"); +} + +raw_ostream &raw_ostream::operator<<(unsigned long N) { + // Zero is a special case. + if (N == 0) + return *this << '0'; + + char NumberBuffer[20]; + char *EndPtr = NumberBuffer+sizeof(NumberBuffer); + char *CurPtr = EndPtr; + + while (N) { + *--CurPtr = '0' + char(N % 10); + N /= 10; + } + return write(CurPtr, EndPtr-CurPtr); +} + +raw_ostream &raw_ostream::operator<<(long N) { + if (N < 0) { + *this << '-'; + // Avoid undefined behavior on LONG_MIN with a cast. + N = -(unsigned long)N; + } + + return this->operator<<(static_cast<unsigned long>(N)); +} + +raw_ostream &raw_ostream::operator<<(unsigned long long N) { + // Output using 32-bit div/mod when possible. + if (N == static_cast<unsigned long>(N)) + return this->operator<<(static_cast<unsigned long>(N)); + + char NumberBuffer[20]; + char *EndPtr = std::end(NumberBuffer); + char *CurPtr = EndPtr; + + while (N) { + *--CurPtr = '0' + char(N % 10); + N /= 10; + } + return write(CurPtr, EndPtr-CurPtr); +} + +raw_ostream &raw_ostream::operator<<(long long N) { + if (N < 0) { + *this << '-'; + // Avoid undefined behavior on INT64_MIN with a cast. + N = -(unsigned long long)N; + } + + return this->operator<<(static_cast<unsigned long long>(N)); +} + +raw_ostream &raw_ostream::write_hex(unsigned long long N) { + // Zero is a special case. + if (N == 0) + return *this << '0'; + + char NumberBuffer[16]; + char *EndPtr = std::end(NumberBuffer); + char *CurPtr = EndPtr; + + while (N) { + unsigned char x = static_cast<unsigned char>(N) % 16; + *--CurPtr = hexdigit(x, /*LowerCase*/true); + N /= 16; + } + + return write(CurPtr, EndPtr-CurPtr); +} + +raw_ostream &raw_ostream::write_escaped(StringRef Str, + bool UseHexEscapes) { + for (unsigned char c : Str) { + switch (c) { + case '\\': + *this << '\\' << '\\'; + break; + case '\t': + *this << '\\' << 't'; + break; + case '\n': + *this << '\\' << 'n'; + break; + case '"': + *this << '\\' << '"'; + break; + default: + if (std::isprint(c)) { + *this << c; + break; + } + + // Write out the escaped representation. + if (UseHexEscapes) { + *this << '\\' << 'x'; + *this << hexdigit((c >> 4 & 0xF)); + *this << hexdigit((c >> 0) & 0xF); + } else { + // Always use a full 3-character octal escape. + *this << '\\'; + *this << char('0' + ((c >> 6) & 7)); + *this << char('0' + ((c >> 3) & 7)); + *this << char('0' + ((c >> 0) & 7)); + } + } + } + + return *this; +} + +raw_ostream &raw_ostream::operator<<(const void *P) { + *this << '0' << 'x'; + + return write_hex((uintptr_t) P); +} + +raw_ostream &raw_ostream::operator<<(double N) { +#ifdef _WIN32 + // On MSVCRT and compatible, output of %e is incompatible to Posix + // by default. Number of exponent digits should be at least 2. "%+03d" + // FIXME: Implement our formatter to here or Support/Format.h! +#if defined(__MINGW32__) + // FIXME: It should be generic to C++11. + if (N == 0.0 && std::signbit(N)) + return *this << "-0.000000e+00"; +#else + int fpcl = _fpclass(N); + + // negative zero + if (fpcl == _FPCLASS_NZ) + return *this << "-0.000000e+00"; +#endif + + char buf[16]; + unsigned len; + len = format("%e", N).snprint(buf, sizeof(buf)); + if (len <= sizeof(buf) - 2) { + if (len >= 5 && buf[len - 5] == 'e' && buf[len - 3] == '0') { + int cs = buf[len - 4]; + if (cs == '+' || cs == '-') { + int c1 = buf[len - 2]; + int c0 = buf[len - 1]; + if (isdigit(static_cast<unsigned char>(c1)) && + isdigit(static_cast<unsigned char>(c0))) { + // Trim leading '0': "...e+012" -> "...e+12\0" + buf[len - 3] = c1; + buf[len - 2] = c0; + buf[--len] = 0; + } + } + } + return this->operator<<(buf); + } +#endif + return this->operator<<(format("%e", N)); +} + +void raw_ostream::flush_nonempty() { + assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty."); + size_t Length = OutBufCur - OutBufStart; + OutBufCur = OutBufStart; + write_impl(OutBufStart, Length); +} + +raw_ostream &raw_ostream::write(unsigned char C) { + // Group exceptional cases into a single branch. + if (LLVM_UNLIKELY(OutBufCur >= OutBufEnd)) { + if (LLVM_UNLIKELY(!OutBufStart)) { + if (BufferMode == Unbuffered) { + write_impl(reinterpret_cast<char*>(&C), 1); + return *this; + } + // Set up a buffer and start over. + SetBuffered(); + return write(C); + } + + flush_nonempty(); + } + + *OutBufCur++ = C; + return *this; +} + +raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) { + // Group exceptional cases into a single branch. + if (LLVM_UNLIKELY(size_t(OutBufEnd - OutBufCur) < Size)) { + if (LLVM_UNLIKELY(!OutBufStart)) { + if (BufferMode == Unbuffered) { + write_impl(Ptr, Size); + return *this; + } + // Set up a buffer and start over. + SetBuffered(); + return write(Ptr, Size); + } + + size_t NumBytes = OutBufEnd - OutBufCur; + + // If the buffer is empty at this point we have a string that is larger + // than the buffer. Directly write the chunk that is a multiple of the + // preferred buffer size and put the remainder in the buffer. + if (LLVM_UNLIKELY(OutBufCur == OutBufStart)) { + assert(NumBytes != 0 && "undefined behavior"); + size_t BytesToWrite = Size - (Size % NumBytes); + write_impl(Ptr, BytesToWrite); + size_t BytesRemaining = Size - BytesToWrite; + if (BytesRemaining > size_t(OutBufEnd - OutBufCur)) { + // Too much left over to copy into our buffer. + return write(Ptr + BytesToWrite, BytesRemaining); + } + copy_to_buffer(Ptr + BytesToWrite, BytesRemaining); + return *this; + } + + // We don't have enough space in the buffer to fit the string in. Insert as + // much as possible, flush and start over with the remainder. + copy_to_buffer(Ptr, NumBytes); + flush_nonempty(); + return write(Ptr + NumBytes, Size - NumBytes); + } + + copy_to_buffer(Ptr, Size); + + return *this; +} + +void raw_ostream::copy_to_buffer(const char *Ptr, size_t Size) { + assert(Size <= size_t(OutBufEnd - OutBufCur) && "Buffer overrun!"); + + // Handle short strings specially, memcpy isn't very good at very short + // strings. + switch (Size) { + case 4: OutBufCur[3] = Ptr[3]; LLVM_FALLTHROUGH; + case 3: OutBufCur[2] = Ptr[2]; LLVM_FALLTHROUGH; + case 2: OutBufCur[1] = Ptr[1]; LLVM_FALLTHROUGH; + case 1: OutBufCur[0] = Ptr[0]; LLVM_FALLTHROUGH; + case 0: break; + default: + memcpy(OutBufCur, Ptr, Size); + break; + } + + OutBufCur += Size; +} + +// Formatted output. +raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) { + // If we have more than a few bytes left in our output buffer, try + // formatting directly onto its end. + size_t NextBufferSize = 127; + size_t BufferBytesLeft = OutBufEnd - OutBufCur; + if (BufferBytesLeft > 3) { + size_t BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft); + + // Common case is that we have plenty of space. + if (BytesUsed <= BufferBytesLeft) { + OutBufCur += BytesUsed; + return *this; + } + + // Otherwise, we overflowed and the return value tells us the size to try + // again with. + NextBufferSize = BytesUsed; + } + + // If we got here, we didn't have enough space in the output buffer for the + // string. Try printing into a SmallVector that is resized to have enough + // space. Iterate until we win. + SmallVector<char, 128> V; + + while (true) { + V.resize(NextBufferSize); + + // Try formatting into the SmallVector. + size_t BytesUsed = Fmt.print(V.data(), NextBufferSize); + + // If BytesUsed fit into the vector, we win. + if (BytesUsed <= NextBufferSize) + return write(V.data(), BytesUsed); + + // Otherwise, try again with a new size. + assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?"); + NextBufferSize = BytesUsed; + } +} + +raw_ostream &raw_ostream::operator<<(const FormattedString &FS) { + unsigned Len = FS.Str.size(); + int PadAmount = FS.Width - Len; + if (FS.RightJustify && (PadAmount > 0)) + this->indent(PadAmount); + this->operator<<(FS.Str); + if (!FS.RightJustify && (PadAmount > 0)) + this->indent(PadAmount); + return *this; +} + +raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) { + if (FN.Hex) { + unsigned Nibbles = (64 - countLeadingZeros(FN.HexValue)+3)/4; + unsigned PrefixChars = FN.HexPrefix ? 2 : 0; + unsigned Width = std::max(FN.Width, Nibbles + PrefixChars); + + char NumberBuffer[20] = "0x0000000000000000"; + if (!FN.HexPrefix) + NumberBuffer[1] = '0'; + char *EndPtr = NumberBuffer+Width; + char *CurPtr = EndPtr; + unsigned long long N = FN.HexValue; + while (N) { + unsigned char x = static_cast<unsigned char>(N) % 16; + *--CurPtr = hexdigit(x, !FN.Upper); + N /= 16; + } + + return write(NumberBuffer, Width); + } else { + // Zero is a special case. + if (FN.DecValue == 0) { + this->indent(FN.Width-1); + return *this << '0'; + } + char NumberBuffer[32]; + char *EndPtr = NumberBuffer+sizeof(NumberBuffer); + char *CurPtr = EndPtr; + bool Neg = (FN.DecValue < 0); + uint64_t N = Neg ? -static_cast<uint64_t>(FN.DecValue) : FN.DecValue; + while (N) { + *--CurPtr = '0' + char(N % 10); + N /= 10; + } + int Len = EndPtr - CurPtr; + int Pad = FN.Width - Len; + if (Neg) + --Pad; + if (Pad > 0) + this->indent(Pad); + if (Neg) + *this << '-'; + return write(CurPtr, Len); + } +} + +/// indent - Insert 'NumSpaces' spaces. +raw_ostream &raw_ostream::indent(unsigned NumSpaces) { + static const char Spaces[] = " " + " " + " "; + + // Usually the indentation is small, handle it with a fastpath. + if (NumSpaces < array_lengthof(Spaces)) + return write(Spaces, NumSpaces); + + while (NumSpaces) { + unsigned NumToWrite = std::min(NumSpaces, + (unsigned)array_lengthof(Spaces)-1); + write(Spaces, NumToWrite); + NumSpaces -= NumToWrite; + } + return *this; +} + +//===----------------------------------------------------------------------===// +// Formatted Output +//===----------------------------------------------------------------------===// + +// Out of line virtual method. +void format_object_base::home() { +} + +//===----------------------------------------------------------------------===// +// raw_fd_ostream +//===----------------------------------------------------------------------===// + +static int getFD(StringRef Filename, std::error_code &EC, + sys::fs::OpenFlags Flags) { + // Handle "-" as stdout. Note that when we do this, we consider ourself + // the owner of stdout. This means that we can do things like close the + // file descriptor when we're done and set the "binary" flag globally. + if (Filename == "-") { + EC = std::error_code(); + // If user requested binary then put stdout into binary mode if + // possible. + if (!(Flags & sys::fs::F_Text)) + sys::ChangeStdoutToBinary(); + return STDOUT_FILENO; + } + + int FD; + EC = sys::fs::openFileForWrite(Filename, FD, Flags); + if (EC) + return -1; + + return FD; +} + +raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC, + sys::fs::OpenFlags Flags) + : raw_fd_ostream(getFD(Filename, EC, Flags), true) {} + +/// FD is the file descriptor that this writes to. If ShouldClose is true, this +/// closes the file when the stream is destroyed. +raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered) + : raw_pwrite_stream(unbuffered), FD(fd), ShouldClose(shouldClose), + Error(false) { + if (FD < 0 ) { + ShouldClose = false; + return; + } + + // Get the starting position. + off_t loc = ::lseek(FD, 0, SEEK_CUR); +#ifdef LLVM_ON_WIN32 + // MSVCRT's _lseek(SEEK_CUR) doesn't return -1 for pipes. + sys::fs::file_status Status; + std::error_code EC = status(FD, Status); + SupportsSeeking = !EC && Status.type() == sys::fs::file_type::regular_file; +#else + SupportsSeeking = loc != (off_t)-1; +#endif + if (!SupportsSeeking) + pos = 0; + else + pos = static_cast<uint64_t>(loc); +} + +raw_fd_ostream::~raw_fd_ostream() { + if (FD >= 0) { + flush(); + if (ShouldClose && sys::Process::SafelyCloseFileDescriptor(FD)) + error_detected(); + } + +#ifdef __MINGW32__ + // On mingw, global dtors should not call exit(). + // report_fatal_error() invokes exit(). We know report_fatal_error() + // might not write messages to stderr when any errors were detected + // on FD == 2. + if (FD == 2) return; +#endif + + // If there are any pending errors, report them now. Clients wishing + // to avoid report_fatal_error calls should check for errors with + // has_error() and clear the error flag with clear_error() before + // destructing raw_ostream objects which may have errors. + if (has_error()) + report_fatal_error("IO failure on output stream.", /*GenCrashDiag=*/false); +} + +void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) { + assert(FD >= 0 && "File already closed."); + pos += Size; + +#ifndef LLVM_ON_WIN32 + bool ShouldWriteInChunks = false; +#else + // Writing a large size of output to Windows console returns ENOMEM. It seems + // that, prior to Windows 8, WriteFile() is redirecting to WriteConsole(), and + // the latter has a size limit (66000 bytes or less, depending on heap usage). + bool ShouldWriteInChunks = !!::_isatty(FD) && !RunningWindows8OrGreater(); +#endif + + do { + size_t ChunkSize = Size; + if (ChunkSize > 32767 && ShouldWriteInChunks) + ChunkSize = 32767; + + ssize_t ret = ::write(FD, Ptr, ChunkSize); + + if (ret < 0) { + // If it's a recoverable error, swallow it and retry the write. + // + // Ideally we wouldn't ever see EAGAIN or EWOULDBLOCK here, since + // raw_ostream isn't designed to do non-blocking I/O. However, some + // programs, such as old versions of bjam, have mistakenly used + // O_NONBLOCK. For compatibility, emulate blocking semantics by + // spinning until the write succeeds. If you don't want spinning, + // don't use O_NONBLOCK file descriptors with raw_ostream. + if (errno == EINTR || errno == EAGAIN +#ifdef EWOULDBLOCK + || errno == EWOULDBLOCK +#endif + ) + continue; + + // Otherwise it's a non-recoverable error. Note it and quit. + error_detected(); + break; + } + + // The write may have written some or all of the data. Update the + // size and buffer pointer to reflect the remainder that needs + // to be written. If there are no bytes left, we're done. + Ptr += ret; + Size -= ret; + } while (Size > 0); +} + +void raw_fd_ostream::close() { + assert(ShouldClose); + ShouldClose = false; + flush(); + if (sys::Process::SafelyCloseFileDescriptor(FD)) + error_detected(); + FD = -1; +} + +uint64_t raw_fd_ostream::seek(uint64_t off) { + assert(SupportsSeeking && "Stream does not support seeking!"); + flush(); + pos = ::lseek(FD, off, SEEK_SET); + if (pos == (uint64_t)-1) + error_detected(); + return pos; +} + +void raw_fd_ostream::pwrite_impl(const char *Ptr, size_t Size, + uint64_t Offset) { + uint64_t Pos = tell(); + seek(Offset); + write(Ptr, Size); + seek(Pos); +} + +size_t raw_fd_ostream::preferred_buffer_size() const { +#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__minix) + // Windows and Minix have no st_blksize. + assert(FD >= 0 && "File not yet open!"); + struct stat statbuf; + if (fstat(FD, &statbuf) != 0) + return 0; + + // If this is a terminal, don't use buffering. Line buffering + // would be a more traditional thing to do, but it's not worth + // the complexity. + if (S_ISCHR(statbuf.st_mode) && isatty(FD)) + return 0; + // Return the preferred block size. + return statbuf.st_blksize; +#else + return raw_ostream::preferred_buffer_size(); +#endif +} + +raw_ostream &raw_fd_ostream::changeColor(enum Colors colors, bool bold, + bool bg) { + if (sys::Process::ColorNeedsFlush()) + flush(); + const char *colorcode = + (colors == SAVEDCOLOR) ? sys::Process::OutputBold(bg) + : sys::Process::OutputColor(colors, bold, bg); + if (colorcode) { + size_t len = strlen(colorcode); + write(colorcode, len); + // don't account colors towards output characters + pos -= len; + } + return *this; +} + +raw_ostream &raw_fd_ostream::resetColor() { + if (sys::Process::ColorNeedsFlush()) + flush(); + const char *colorcode = sys::Process::ResetColor(); + if (colorcode) { + size_t len = strlen(colorcode); + write(colorcode, len); + // don't account colors towards output characters + pos -= len; + } + return *this; +} + +raw_ostream &raw_fd_ostream::reverseColor() { + if (sys::Process::ColorNeedsFlush()) + flush(); + const char *colorcode = sys::Process::OutputReverse(); + if (colorcode) { + size_t len = strlen(colorcode); + write(colorcode, len); + // don't account colors towards output characters + pos -= len; + } + return *this; +} + +bool raw_fd_ostream::is_displayed() const { + return sys::Process::FileDescriptorIsDisplayed(FD); +} + +bool raw_fd_ostream::has_colors() const { + return sys::Process::FileDescriptorHasColors(FD); +} + +//===----------------------------------------------------------------------===// +// outs(), errs(), nulls() +//===----------------------------------------------------------------------===// + +/// outs() - This returns a reference to a raw_ostream for standard output. +/// Use it like: outs() << "foo" << "bar"; +raw_ostream &llvm::outs() { + // Set buffer settings to model stdout behavior. Delete the file descriptor + // when the program exits, forcing error detection. This means that if you + // ever call outs(), you can't open another raw_fd_ostream on stdout, as we'll + // close stdout twice and print an error the second time. + std::error_code EC; + static raw_fd_ostream S("-", EC, sys::fs::F_None); + assert(!EC); + return S; +} + +/// errs() - This returns a reference to a raw_ostream for standard error. +/// Use it like: errs() << "foo" << "bar"; +raw_ostream &llvm::errs() { + // Set standard error to be unbuffered by default. + static raw_fd_ostream S(STDERR_FILENO, false, true); + return S; +} + +/// nulls() - This returns a reference to a raw_ostream which discards output. +raw_ostream &llvm::nulls() { + static raw_null_ostream S; + return S; +} + +//===----------------------------------------------------------------------===// +// raw_string_ostream +//===----------------------------------------------------------------------===// + +raw_string_ostream::~raw_string_ostream() { + flush(); +} + +void raw_string_ostream::write_impl(const char *Ptr, size_t Size) { + OS.append(Ptr, Size); +} + +//===----------------------------------------------------------------------===// +// raw_svector_ostream +//===----------------------------------------------------------------------===// + +uint64_t raw_svector_ostream::current_pos() const { return OS.size(); } + +void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) { + OS.append(Ptr, Ptr + Size); +} + +void raw_svector_ostream::pwrite_impl(const char *Ptr, size_t Size, + uint64_t Offset) { + memcpy(OS.data() + Offset, Ptr, Size); +} + +//===----------------------------------------------------------------------===// +// raw_null_ostream +//===----------------------------------------------------------------------===// + +raw_null_ostream::~raw_null_ostream() { +#ifndef NDEBUG + // ~raw_ostream asserts that the buffer is empty. This isn't necessary + // with raw_null_ostream, but it's better to have raw_null_ostream follow + // the rules than to change the rules just for raw_null_ostream. + flush(); +#endif +} + +void raw_null_ostream::write_impl(const char *Ptr, size_t Size) { +} + +uint64_t raw_null_ostream::current_pos() const { + return 0; +} + +void raw_null_ostream::pwrite_impl(const char *Ptr, size_t Size, + uint64_t Offset) {}