Index: vendor/clang/dist-release_70/include/clang/Basic/AttrDocs.td =================================================================== --- vendor/clang/dist-release_70/include/clang/Basic/AttrDocs.td (revision 341366) +++ vendor/clang/dist-release_70/include/clang/Basic/AttrDocs.td (revision 341367) @@ -1,3460 +1,3460 @@ //==--- AttrDocs.td - Attribute documentation ----------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===---------------------------------------------------------------------===// // To test that the documentation builds cleanly, you must run clang-tblgen to // convert the .td file into a .rst file, and then run sphinx to convert the // .rst file into an HTML file. After completing testing, you should revert the // generated .rst file so that the modified version does not get checked in to // version control. // // To run clang-tblgen to generate the .rst file: // clang-tblgen -gen-attr-docs -I /llvm/tools/clang/include // /llvm/tools/clang/include/clang/Basic/Attr.td -o // /llvm/tools/clang/docs/AttributeReference.rst // // To run sphinx to generate the .html files (note that sphinx-build must be // available on the PATH): // Windows (from within the clang\docs directory): // make.bat html // Non-Windows (from within the clang\docs directory): // make -f Makefile.sphinx html def GlobalDocumentation { code Intro =[{.. ------------------------------------------------------------------- NOTE: This file is automatically generated by running clang-tblgen -gen-attr-docs. Do not edit this file by hand!! ------------------------------------------------------------------- =================== Attributes in Clang =================== .. contents:: :local: Introduction ============ This page lists the attributes currently supported by Clang. }]; } def SectionDocs : Documentation { let Category = DocCatVariable; let Content = [{ The ``section`` attribute allows you to specify a specific section a global variable or function should be in after translation. }]; let Heading = "section (gnu::section, __declspec(allocate))"; } def InitSegDocs : Documentation { let Category = DocCatVariable; let Content = [{ The attribute applied by ``pragma init_seg()`` controls the section into which global initialization function pointers are emitted. It is only available with ``-fms-extensions``. Typically, this function pointer is emitted into ``.CRT$XCU`` on Windows. The user can change the order of initialization by using a different section name with the same ``.CRT$XC`` prefix and a suffix that sorts lexicographically before or after the standard ``.CRT$XCU`` sections. See the init_seg_ documentation on MSDN for more information. .. _init_seg: http://msdn.microsoft.com/en-us/library/7977wcck(v=vs.110).aspx }]; } def TLSModelDocs : Documentation { let Category = DocCatVariable; let Content = [{ The ``tls_model`` attribute allows you to specify which thread-local storage model to use. It accepts the following strings: * global-dynamic * local-dynamic * initial-exec * local-exec TLS models are mutually exclusive. }]; } def DLLExportDocs : Documentation { let Category = DocCatVariable; let Content = [{ The ``__declspec(dllexport)`` attribute declares a variable, function, or Objective-C interface to be exported from the module. It is available under the ``-fdeclspec`` flag for compatibility with various compilers. The primary use is for COFF object files which explicitly specify what interfaces are available for external use. See the dllexport_ documentation on MSDN for more information. .. _dllexport: https://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx }]; } def DLLImportDocs : Documentation { let Category = DocCatVariable; let Content = [{ The ``__declspec(dllimport)`` attribute declares a variable, function, or Objective-C interface to be imported from an external module. It is available under the ``-fdeclspec`` flag for compatibility with various compilers. The primary use is for COFF object files which explicitly specify what interfaces are imported from external modules. See the dllimport_ documentation on MSDN for more information. .. _dllimport: https://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx }]; } def ThreadDocs : Documentation { let Category = DocCatVariable; let Content = [{ The ``__declspec(thread)`` attribute declares a variable with thread local storage. It is available under the ``-fms-extensions`` flag for MSVC compatibility. See the documentation for `__declspec(thread)`_ on MSDN. .. _`__declspec(thread)`: http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx In Clang, ``__declspec(thread)`` is generally equivalent in functionality to the GNU ``__thread`` keyword. The variable must not have a destructor and must have a constant initializer, if any. The attribute only applies to variables declared with static storage duration, such as globals, class static data members, and static locals. }]; } def NoEscapeDocs : Documentation { let Category = DocCatVariable; let Content = [{ ``noescape`` placed on a function parameter of a pointer type is used to inform the compiler that the pointer cannot escape: that is, no reference to the object the pointer points to that is derived from the parameter value will survive after the function returns. Users are responsible for making sure parameters annotated with ``noescape`` do not actuallly escape. For example: .. code-block:: c int *gp; void nonescapingFunc(__attribute__((noescape)) int *p) { *p += 100; // OK. } void escapingFunc(__attribute__((noescape)) int *p) { gp = p; // Not OK. } Additionally, when the parameter is a `block pointer `, the same restriction applies to copies of the block. For example: .. code-block:: c typedef void (^BlockTy)(); BlockTy g0, g1; void nonescapingFunc(__attribute__((noescape)) BlockTy block) { block(); // OK. } void escapingFunc(__attribute__((noescape)) BlockTy block) { g0 = block; // Not OK. g1 = Block_copy(block); // Not OK either. } }]; } def CarriesDependencyDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``carries_dependency`` attribute specifies dependency propagation into and out of functions. When specified on a function or Objective-C method, the ``carries_dependency`` attribute means that the return value carries a dependency out of the function, so that the implementation need not constrain ordering upon return from that function. Implementations of the function and its caller may choose to preserve dependencies instead of emitting memory ordering instructions such as fences. Note, this attribute does not change the meaning of the program, but may result in generation of more efficient code. }]; } def CPUSpecificCPUDispatchDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``cpu_specific`` and ``cpu_dispatch`` attributes are used to define and resolve multiversioned functions. This form of multiversioning provides a mechanism for declaring versions across translation units and manually specifying the resolved function list. A specified CPU defines a set of minimum features that are required for the function to be called. The result of this is that future processors execute the most restrictive version of the function the new processor can execute. Function versions are defined with ``cpu_specific``, which takes one or more CPU names as a parameter. For example: .. code-block:: c // Declares and defines the ivybridge version of single_cpu. __attribute__((cpu_specific(ivybridge))) void single_cpu(void){} // Declares and defines the atom version of single_cpu. __attribute__((cpu_specific(atom))) void single_cpu(void){} // Declares and defines both the ivybridge and atom version of multi_cpu. __attribute__((cpu_specific(ivybridge, atom))) void multi_cpu(void){} A dispatching (or resolving) function can be declared anywhere in a project's source code with ``cpu_dispatch``. This attribute takes one or more CPU names as a parameter (like ``cpu_specific``). Functions marked with ``cpu_dispatch`` are not expected to be defined, only declared. If such a marked function has a definition, any side effects of the function are ignored; trivial function bodies are permissible for ICC compatibility. .. code-block:: c // Creates a resolver for single_cpu above. __attribute__((cpu_dispatch(ivybridge, atom))) void single_cpu(void){} // Creates a resolver for multi_cpu, but adds a 3rd version defined in another // translation unit. __attribute__((cpu_dispatch(ivybridge, atom, sandybridge))) void multi_cpu(void){} Note that it is possible to have a resolving function that dispatches based on more or fewer options than are present in the program. Specifying fewer will result in the omitted options not being considered during resolution. Specifying a version for resolution that isn't defined in the program will result in a linking failure. It is also possible to specify a CPU name of ``generic`` which will be resolved if the executing processor doesn't satisfy the features required in the CPU name. The behavior of a program executing on a processor that doesn't satisfy any option of a multiversioned function is undefined. }]; } def C11NoReturnDocs : Documentation { let Category = DocCatFunction; let Content = [{ A function declared as ``_Noreturn`` shall not return to its caller. The compiler will generate a diagnostic for a function declared as ``_Noreturn`` that appears to be capable of returning to its caller. }]; } def CXX11NoReturnDocs : Documentation { let Category = DocCatFunction; let Content = [{ A function declared as ``[[noreturn]]`` shall not return to its caller. The compiler will generate a diagnostic for a function declared as ``[[noreturn]]`` that appears to be capable of returning to its caller. }]; } def AssertCapabilityDocs : Documentation { let Category = DocCatFunction; let Heading = "assert_capability (assert_shared_capability, clang::assert_capability, clang::assert_shared_capability)"; let Content = [{ Marks a function that dynamically tests whether a capability is held, and halts the program if it is not held. }]; } def AcquireCapabilityDocs : Documentation { let Category = DocCatFunction; let Heading = "acquire_capability (acquire_shared_capability, clang::acquire_capability, clang::acquire_shared_capability)"; let Content = [{ Marks a function as acquiring a capability. }]; } def TryAcquireCapabilityDocs : Documentation { let Category = DocCatFunction; let Heading = "try_acquire_capability (try_acquire_shared_capability, clang::try_acquire_capability, clang::try_acquire_shared_capability)"; let Content = [{ Marks a function that attempts to acquire a capability. This function may fail to actually acquire the capability; they accept a Boolean value determining whether acquiring the capability means success (true), or failing to acquire the capability means success (false). }]; } def ReleaseCapabilityDocs : Documentation { let Category = DocCatFunction; let Heading = "release_capability (release_shared_capability, clang::release_capability, clang::release_shared_capability)"; let Content = [{ Marks a function as releasing a capability. }]; } def AssumeAlignedDocs : Documentation { let Category = DocCatFunction; let Content = [{ Use ``__attribute__((assume_aligned([,]))`` on a function declaration to specify that the return value of the function (which must be a pointer type) has the specified offset, in bytes, from an address with the specified alignment. The offset is taken to be zero if omitted. .. code-block:: c++ // The returned pointer value has 32-byte alignment. void *a() __attribute__((assume_aligned (32))); // The returned pointer value is 4 bytes greater than an address having // 32-byte alignment. void *b() __attribute__((assume_aligned (32, 4))); Note that this attribute provides information to the compiler regarding a condition that the code already ensures is true. It does not cause the compiler to enforce the provided alignment assumption. }]; } def AllocSizeDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``alloc_size`` attribute can be placed on functions that return pointers in order to hint to the compiler how many bytes of memory will be available at the returned pointer. ``alloc_size`` takes one or two arguments. - ``alloc_size(N)`` implies that argument number N equals the number of available bytes at the returned pointer. - ``alloc_size(N, M)`` implies that the product of argument number N and argument number M equals the number of available bytes at the returned pointer. Argument numbers are 1-based. An example of how to use ``alloc_size`` .. code-block:: c void *my_malloc(int a) __attribute__((alloc_size(1))); void *my_calloc(int a, int b) __attribute__((alloc_size(1, 2))); int main() { void *const p = my_malloc(100); assert(__builtin_object_size(p, 0) == 100); void *const a = my_calloc(20, 5); assert(__builtin_object_size(a, 0) == 100); } .. Note:: This attribute works differently in clang than it does in GCC. Specifically, clang will only trace ``const`` pointers (as above); we give up on pointers that are not marked as ``const``. In the vast majority of cases, this is unimportant, because LLVM has support for the ``alloc_size`` attribute. However, this may cause mildly unintuitive behavior when used with other attributes, such as ``enable_if``. }]; } def CodeSegDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``__declspec(code_seg)`` attribute enables the placement of code into separate named segments that can be paged or locked in memory individually. This attribute is used to control the placement of instantiated templates and compiler-generated code. See the documentation for `__declspec(code_seg)`_ on MSDN. .. _`__declspec(code_seg)`: http://msdn.microsoft.com/en-us/library/dn636922.aspx }]; } def AllocAlignDocs : Documentation { let Category = DocCatFunction; let Content = [{ Use ``__attribute__((alloc_align())`` on a function declaration to specify that the return value of the function (which must be a pointer type) is at least as aligned as the value of the indicated parameter. The parameter is given by its index in the list of formal parameters; the first parameter has index 1 unless the function is a C++ non-static member function, in which case the first parameter has index 2 to account for the implicit ``this`` parameter. .. code-block:: c++ // The returned pointer has the alignment specified by the first parameter. void *a(size_t align) __attribute__((alloc_align(1))); // The returned pointer has the alignment specified by the second parameter. void *b(void *v, size_t align) __attribute__((alloc_align(2))); // The returned pointer has the alignment specified by the second visible // parameter, however it must be adjusted for the implicit 'this' parameter. void *Foo::b(void *v, size_t align) __attribute__((alloc_align(3))); Note that this attribute merely informs the compiler that a function always returns a sufficiently aligned pointer. It does not cause the compiler to emit code to enforce that alignment. The behavior is undefined if the returned poitner is not sufficiently aligned. }]; } def EnableIfDocs : Documentation { let Category = DocCatFunction; let Content = [{ .. Note:: Some features of this attribute are experimental. The meaning of multiple enable_if attributes on a single declaration is subject to change in a future version of clang. Also, the ABI is not standardized and the name mangling may change in future versions. To avoid that, use asm labels. The ``enable_if`` attribute can be placed on function declarations to control which overload is selected based on the values of the function's arguments. When combined with the ``overloadable`` attribute, this feature is also available in C. .. code-block:: c++ int isdigit(int c); int isdigit(int c) __attribute__((enable_if(c <= -1 || c > 255, "chosen when 'c' is out of range"))) __attribute__((unavailable("'c' must have the value of an unsigned char or EOF"))); void foo(char c) { isdigit(c); isdigit(10); isdigit(-10); // results in a compile-time error. } The enable_if attribute takes two arguments, the first is an expression written in terms of the function parameters, the second is a string explaining why this overload candidate could not be selected to be displayed in diagnostics. The expression is part of the function signature for the purposes of determining whether it is a redeclaration (following the rules used when determining whether a C++ template specialization is ODR-equivalent), but is not part of the type. The enable_if expression is evaluated as if it were the body of a bool-returning constexpr function declared with the arguments of the function it is being applied to, then called with the parameters at the call site. If the result is false or could not be determined through constant expression evaluation, then this overload will not be chosen and the provided string may be used in a diagnostic if the compile fails as a result. Because the enable_if expression is an unevaluated context, there are no global state changes, nor the ability to pass information from the enable_if expression to the function body. For example, suppose we want calls to strnlen(strbuf, maxlen) to resolve to strnlen_chk(strbuf, maxlen, size of strbuf) only if the size of strbuf can be determined: .. code-block:: c++ __attribute__((always_inline)) static inline size_t strnlen(const char *s, size_t maxlen) __attribute__((overloadable)) __attribute__((enable_if(__builtin_object_size(s, 0) != -1))), "chosen when the buffer size is known but 'maxlen' is not"))) { return strnlen_chk(s, maxlen, __builtin_object_size(s, 0)); } Multiple enable_if attributes may be applied to a single declaration. In this case, the enable_if expressions are evaluated from left to right in the following manner. First, the candidates whose enable_if expressions evaluate to false or cannot be evaluated are discarded. If the remaining candidates do not share ODR-equivalent enable_if expressions, the overload resolution is ambiguous. Otherwise, enable_if overload resolution continues with the next enable_if attribute on the candidates that have not been discarded and have remaining enable_if attributes. In this way, we pick the most specific overload out of a number of viable overloads using enable_if. .. code-block:: c++ void f() __attribute__((enable_if(true, ""))); // #1 void f() __attribute__((enable_if(true, ""))) __attribute__((enable_if(true, ""))); // #2 void g(int i, int j) __attribute__((enable_if(i, ""))); // #1 void g(int i, int j) __attribute__((enable_if(j, ""))) __attribute__((enable_if(true))); // #2 In this example, a call to f() is always resolved to #2, as the first enable_if expression is ODR-equivalent for both declarations, but #1 does not have another enable_if expression to continue evaluating, so the next round of evaluation has only a single candidate. In a call to g(1, 1), the call is ambiguous even though #2 has more enable_if attributes, because the first enable_if expressions are not ODR-equivalent. Query for this feature with ``__has_attribute(enable_if)``. Note that functions with one or more ``enable_if`` attributes may not have their address taken, unless all of the conditions specified by said ``enable_if`` are constants that evaluate to ``true``. For example: .. code-block:: c const int TrueConstant = 1; const int FalseConstant = 0; int f(int a) __attribute__((enable_if(a > 0, ""))); int g(int a) __attribute__((enable_if(a == 0 || a != 0, ""))); int h(int a) __attribute__((enable_if(1, ""))); int i(int a) __attribute__((enable_if(TrueConstant, ""))); int j(int a) __attribute__((enable_if(FalseConstant, ""))); void fn() { int (*ptr)(int); ptr = &f; // error: 'a > 0' is not always true ptr = &g; // error: 'a == 0 || a != 0' is not a truthy constant ptr = &h; // OK: 1 is a truthy constant ptr = &i; // OK: 'TrueConstant' is a truthy constant ptr = &j; // error: 'FalseConstant' is a constant, but not truthy } Because ``enable_if`` evaluation happens during overload resolution, ``enable_if`` may give unintuitive results when used with templates, depending on when overloads are resolved. In the example below, clang will emit a diagnostic about no viable overloads for ``foo`` in ``bar``, but not in ``baz``: .. code-block:: c++ double foo(int i) __attribute__((enable_if(i > 0, ""))); void *foo(int i) __attribute__((enable_if(i <= 0, ""))); template auto bar() { return foo(I); } template auto baz() { return foo(T::number); } struct WithNumber { constexpr static int number = 1; }; void callThem() { bar(); baz(); } This is because, in ``bar``, ``foo`` is resolved prior to template instantiation, so the value for ``I`` isn't known (thus, both ``enable_if`` conditions for ``foo`` fail). However, in ``baz``, ``foo`` is resolved during template instantiation, so the value for ``T::number`` is known. }]; } def DiagnoseIfDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``diagnose_if`` attribute can be placed on function declarations to emit warnings or errors at compile-time if calls to the attributed function meet certain user-defined criteria. For example: .. code-block:: c void abs(int a) __attribute__((diagnose_if(a >= 0, "Redundant abs call", "warning"))); void must_abs(int a) __attribute__((diagnose_if(a >= 0, "Redundant abs call", "error"))); int val = abs(1); // warning: Redundant abs call int val2 = must_abs(1); // error: Redundant abs call int val3 = abs(val); int val4 = must_abs(val); // Because run-time checks are not emitted for // diagnose_if attributes, this executes without // issue. ``diagnose_if`` is closely related to ``enable_if``, with a few key differences: * Overload resolution is not aware of ``diagnose_if`` attributes: they're considered only after we select the best candidate from a given candidate set. * Function declarations that differ only in their ``diagnose_if`` attributes are considered to be redeclarations of the same function (not overloads). * If the condition provided to ``diagnose_if`` cannot be evaluated, no diagnostic will be emitted. Otherwise, ``diagnose_if`` is essentially the logical negation of ``enable_if``. As a result of bullet number two, ``diagnose_if`` attributes will stack on the same function. For example: .. code-block:: c int foo() __attribute__((diagnose_if(1, "diag1", "warning"))); int foo() __attribute__((diagnose_if(1, "diag2", "warning"))); int bar = foo(); // warning: diag1 // warning: diag2 int (*fooptr)(void) = foo; // warning: diag1 // warning: diag2 constexpr int supportsAPILevel(int N) { return N < 5; } int baz(int a) __attribute__((diagnose_if(!supportsAPILevel(10), "Upgrade to API level 10 to use baz", "error"))); int baz(int a) __attribute__((diagnose_if(!a, "0 is not recommended.", "warning"))); int (*bazptr)(int) = baz; // error: Upgrade to API level 10 to use baz int v = baz(0); // error: Upgrade to API level 10 to use baz Query for this feature with ``__has_attribute(diagnose_if)``. }]; } def PassObjectSizeDocs : Documentation { let Category = DocCatVariable; // Technically it's a parameter doc, but eh. let Content = [{ .. Note:: The mangling of functions with parameters that are annotated with ``pass_object_size`` is subject to change. You can get around this by using ``__asm__("foo")`` to explicitly name your functions, thus preserving your ABI; also, non-overloadable C functions with ``pass_object_size`` are not mangled. The ``pass_object_size(Type)`` attribute can be placed on function parameters to instruct clang to call ``__builtin_object_size(param, Type)`` at each callsite of said function, and implicitly pass the result of this call in as an invisible argument of type ``size_t`` directly after the parameter annotated with ``pass_object_size``. Clang will also replace any calls to ``__builtin_object_size(param, Type)`` in the function by said implicit parameter. Example usage: .. code-block:: c int bzero1(char *const p __attribute__((pass_object_size(0)))) __attribute__((noinline)) { int i = 0; for (/**/; i < (int)__builtin_object_size(p, 0); ++i) { p[i] = 0; } return i; } int main() { char chars[100]; int n = bzero1(&chars[0]); assert(n == sizeof(chars)); return 0; } If successfully evaluating ``__builtin_object_size(param, Type)`` at the callsite is not possible, then the "failed" value is passed in. So, using the definition of ``bzero1`` from above, the following code would exit cleanly: .. code-block:: c int main2(int argc, char *argv[]) { int n = bzero1(argv); assert(n == -1); return 0; } ``pass_object_size`` plays a part in overload resolution. If two overload candidates are otherwise equally good, then the overload with one or more parameters with ``pass_object_size`` is preferred. This implies that the choice between two identical overloads both with ``pass_object_size`` on one or more parameters will always be ambiguous; for this reason, having two such overloads is illegal. For example: .. code-block:: c++ #define PS(N) __attribute__((pass_object_size(N))) // OK void Foo(char *a, char *b); // Overload A // OK -- overload A has no parameters with pass_object_size. void Foo(char *a PS(0), char *b PS(0)); // Overload B // Error -- Same signature (sans pass_object_size) as overload B, and both // overloads have one or more parameters with the pass_object_size attribute. void Foo(void *a PS(0), void *b); // OK void Bar(void *a PS(0)); // Overload C // OK void Bar(char *c PS(1)); // Overload D void main() { char known[10], *unknown; Foo(unknown, unknown); // Calls overload B Foo(known, unknown); // Calls overload B Foo(unknown, known); // Calls overload B Foo(known, known); // Calls overload B Bar(known); // Calls overload D Bar(unknown); // Calls overload D } Currently, ``pass_object_size`` is a bit restricted in terms of its usage: * Only one use of ``pass_object_size`` is allowed per parameter. * It is an error to take the address of a function with ``pass_object_size`` on any of its parameters. If you wish to do this, you can create an overload without ``pass_object_size`` on any parameters. * It is an error to apply the ``pass_object_size`` attribute to parameters that are not pointers. Additionally, any parameter that ``pass_object_size`` is applied to must be marked ``const`` at its function's definition. }]; } def OverloadableDocs : Documentation { let Category = DocCatFunction; let Content = [{ Clang provides support for C++ function overloading in C. Function overloading in C is introduced using the ``overloadable`` attribute. For example, one might provide several overloaded versions of a ``tgsin`` function that invokes the appropriate standard function computing the sine of a value with ``float``, ``double``, or ``long double`` precision: .. code-block:: c #include float __attribute__((overloadable)) tgsin(float x) { return sinf(x); } double __attribute__((overloadable)) tgsin(double x) { return sin(x); } long double __attribute__((overloadable)) tgsin(long double x) { return sinl(x); } Given these declarations, one can call ``tgsin`` with a ``float`` value to receive a ``float`` result, with a ``double`` to receive a ``double`` result, etc. Function overloading in C follows the rules of C++ function overloading to pick the best overload given the call arguments, with a few C-specific semantics: * Conversion from ``float`` or ``double`` to ``long double`` is ranked as a floating-point promotion (per C99) rather than as a floating-point conversion (as in C++). * A conversion from a pointer of type ``T*`` to a pointer of type ``U*`` is considered a pointer conversion (with conversion rank) if ``T`` and ``U`` are compatible types. * A conversion from type ``T`` to a value of type ``U`` is permitted if ``T`` and ``U`` are compatible types. This conversion is given "conversion" rank. * If no viable candidates are otherwise available, we allow a conversion from a pointer of type ``T*`` to a pointer of type ``U*``, where ``T`` and ``U`` are incompatible. This conversion is ranked below all other types of conversions. Please note: ``U`` lacking qualifiers that are present on ``T`` is sufficient for ``T`` and ``U`` to be incompatible. The declaration of ``overloadable`` functions is restricted to function declarations and definitions. If a function is marked with the ``overloadable`` attribute, then all declarations and definitions of functions with that name, except for at most one (see the note below about unmarked overloads), must have the ``overloadable`` attribute. In addition, redeclarations of a function with the ``overloadable`` attribute must have the ``overloadable`` attribute, and redeclarations of a function without the ``overloadable`` attribute must *not* have the ``overloadable`` attribute. e.g., .. code-block:: c int f(int) __attribute__((overloadable)); float f(float); // error: declaration of "f" must have the "overloadable" attribute int f(int); // error: redeclaration of "f" must have the "overloadable" attribute int g(int) __attribute__((overloadable)); int g(int) { } // error: redeclaration of "g" must also have the "overloadable" attribute int h(int); int h(int) __attribute__((overloadable)); // error: declaration of "h" must not // have the "overloadable" attribute Functions marked ``overloadable`` must have prototypes. Therefore, the following code is ill-formed: .. code-block:: c int h() __attribute__((overloadable)); // error: h does not have a prototype However, ``overloadable`` functions are allowed to use a ellipsis even if there are no named parameters (as is permitted in C++). This feature is particularly useful when combined with the ``unavailable`` attribute: .. code-block:: c++ void honeypot(...) __attribute__((overloadable, unavailable)); // calling me is an error Functions declared with the ``overloadable`` attribute have their names mangled according to the same rules as C++ function names. For example, the three ``tgsin`` functions in our motivating example get the mangled names ``_Z5tgsinf``, ``_Z5tgsind``, and ``_Z5tgsine``, respectively. There are two caveats to this use of name mangling: * Future versions of Clang may change the name mangling of functions overloaded in C, so you should not depend on an specific mangling. To be completely safe, we strongly urge the use of ``static inline`` with ``overloadable`` functions. * The ``overloadable`` attribute has almost no meaning when used in C++, because names will already be mangled and functions are already overloadable. However, when an ``overloadable`` function occurs within an ``extern "C"`` linkage specification, it's name *will* be mangled in the same way as it would in C. For the purpose of backwards compatibility, at most one function with the same name as other ``overloadable`` functions may omit the ``overloadable`` attribute. In this case, the function without the ``overloadable`` attribute will not have its name mangled. For example: .. code-block:: c // Notes with mangled names assume Itanium mangling. int f(int); int f(double) __attribute__((overloadable)); void foo() { f(5); // Emits a call to f (not _Z1fi, as it would with an overload that // was marked with overloadable). f(1.0); // Emits a call to _Z1fd. } Support for unmarked overloads is not present in some versions of clang. You may query for it using ``__has_extension(overloadable_unmarked)``. Query for this attribute with ``__has_attribute(overloadable)``. }]; } def ObjCMethodFamilyDocs : Documentation { let Category = DocCatFunction; let Content = [{ Many methods in Objective-C have conventional meanings determined by their selectors. It is sometimes useful to be able to mark a method as having a particular conventional meaning despite not having the right selector, or as not having the conventional meaning that its selector would suggest. For these use cases, we provide an attribute to specifically describe the "method family" that a method belongs to. **Usage**: ``__attribute__((objc_method_family(X)))``, where ``X`` is one of ``none``, ``alloc``, ``copy``, ``init``, ``mutableCopy``, or ``new``. This attribute can only be placed at the end of a method declaration: .. code-block:: objc - (NSString *)initMyStringValue __attribute__((objc_method_family(none))); Users who do not wish to change the conventional meaning of a method, and who merely want to document its non-standard retain and release semantics, should use the retaining behavior attributes (``ns_returns_retained``, ``ns_returns_not_retained``, etc). Query for this feature with ``__has_attribute(objc_method_family)``. }]; } def NoDebugDocs : Documentation { let Category = DocCatVariable; let Content = [{ The ``nodebug`` attribute allows you to suppress debugging information for a function or method, or for a variable that is not a parameter or a non-static data member. }]; } def NoDuplicateDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``noduplicate`` attribute can be placed on function declarations to control whether function calls to this function can be duplicated or not as a result of optimizations. This is required for the implementation of functions with certain special requirements, like the OpenCL "barrier" function, that might need to be run concurrently by all the threads that are executing in lockstep on the hardware. For example this attribute applied on the function "nodupfunc" in the code below avoids that: .. code-block:: c void nodupfunc() __attribute__((noduplicate)); // Setting it as a C++11 attribute is also valid // void nodupfunc() [[clang::noduplicate]]; void foo(); void bar(); nodupfunc(); if (a > n) { foo(); } else { bar(); } gets possibly modified by some optimizations into code similar to this: .. code-block:: c if (a > n) { nodupfunc(); foo(); } else { nodupfunc(); bar(); } where the call to "nodupfunc" is duplicated and sunk into the two branches of the condition. }]; } def ConvergentDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``convergent`` attribute can be placed on a function declaration. It is translated into the LLVM ``convergent`` attribute, which indicates that the call instructions of a function with this attribute cannot be made control-dependent on any additional values. In languages designed for SPMD/SIMT programming model, e.g. OpenCL or CUDA, the call instructions of a function with this attribute must be executed by all work items or threads in a work group or sub group. This attribute is different from ``noduplicate`` because it allows duplicating function calls if it can be proved that the duplicated function calls are not made control-dependent on any additional values, e.g., unrolling a loop executed by all work items. Sample usage: .. code-block:: c void convfunc(void) __attribute__((convergent)); // Setting it as a C++11 attribute is also valid in a C++ program. // void convfunc(void) [[clang::convergent]]; }]; } def NoSplitStackDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``no_split_stack`` attribute disables the emission of the split stack preamble for a particular function. It has no effect if ``-fsplit-stack`` is not specified. }]; } def ObjCRequiresSuperDocs : Documentation { let Category = DocCatFunction; let Content = [{ Some Objective-C classes allow a subclass to override a particular method in a parent class but expect that the overriding method also calls the overridden method in the parent class. For these cases, we provide an attribute to designate that a method requires a "call to ``super``" in the overriding method in the subclass. **Usage**: ``__attribute__((objc_requires_super))``. This attribute can only be placed at the end of a method declaration: .. code-block:: objc - (void)foo __attribute__((objc_requires_super)); This attribute can only be applied the method declarations within a class, and not a protocol. Currently this attribute does not enforce any placement of where the call occurs in the overriding method (such as in the case of ``-dealloc`` where the call must appear at the end). It checks only that it exists. Note that on both OS X and iOS that the Foundation framework provides a convenience macro ``NS_REQUIRES_SUPER`` that provides syntactic sugar for this attribute: .. code-block:: objc - (void)foo NS_REQUIRES_SUPER; This macro is conditionally defined depending on the compiler's support for this attribute. If the compiler does not support the attribute the macro expands to nothing. Operationally, when a method has this annotation the compiler will warn if the implementation of an override in a subclass does not call super. For example: .. code-block:: objc warning: method possibly missing a [super AnnotMeth] call - (void) AnnotMeth{}; ^ }]; } def ObjCRuntimeNameDocs : Documentation { let Category = DocCatFunction; let Content = [{ By default, the Objective-C interface or protocol identifier is used in the metadata name for that object. The `objc_runtime_name` attribute allows annotated interfaces or protocols to use the specified string argument in the object's metadata name instead of the default name. **Usage**: ``__attribute__((objc_runtime_name("MyLocalName")))``. This attribute can only be placed before an @protocol or @interface declaration: .. code-block:: objc __attribute__((objc_runtime_name("MyLocalName"))) @interface Message @end }]; } def ObjCRuntimeVisibleDocs : Documentation { let Category = DocCatFunction; let Content = [{ This attribute specifies that the Objective-C class to which it applies is visible to the Objective-C runtime but not to the linker. Classes annotated with this attribute cannot be subclassed and cannot have categories defined for them. }]; } def ObjCBoxableDocs : Documentation { let Category = DocCatFunction; let Content = [{ Structs and unions marked with the ``objc_boxable`` attribute can be used with the Objective-C boxed expression syntax, ``@(...)``. **Usage**: ``__attribute__((objc_boxable))``. This attribute can only be placed on a declaration of a trivially-copyable struct or union: .. code-block:: objc struct __attribute__((objc_boxable)) some_struct { int i; }; union __attribute__((objc_boxable)) some_union { int i; float f; }; typedef struct __attribute__((objc_boxable)) _some_struct some_struct; // ... some_struct ss; NSValue *boxed = @(ss); }]; } def AvailabilityDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``availability`` attribute can be placed on declarations to describe the lifecycle of that declaration relative to operating system versions. Consider the function declaration for a hypothetical function ``f``: .. code-block:: c++ void f(void) __attribute__((availability(macos,introduced=10.4,deprecated=10.6,obsoleted=10.7))); The availability attribute states that ``f`` was introduced in macOS 10.4, deprecated in macOS 10.6, and obsoleted in macOS 10.7. This information is used by Clang to determine when it is safe to use ``f``: for example, if Clang is instructed to compile code for macOS 10.5, a call to ``f()`` succeeds. If Clang is instructed to compile code for macOS 10.6, the call succeeds but Clang emits a warning specifying that the function is deprecated. Finally, if Clang is instructed to compile code for macOS 10.7, the call fails because ``f()`` is no longer available. The availability attribute is a comma-separated list starting with the platform name and then including clauses specifying important milestones in the declaration's lifetime (in any order) along with additional information. Those clauses can be: introduced=\ *version* The first version in which this declaration was introduced. deprecated=\ *version* The first version in which this declaration was deprecated, meaning that users should migrate away from this API. obsoleted=\ *version* The first version in which this declaration was obsoleted, meaning that it was removed completely and can no longer be used. unavailable This declaration is never available on this platform. message=\ *string-literal* Additional message text that Clang will provide when emitting a warning or error about use of a deprecated or obsoleted declaration. Useful to direct users to replacement APIs. replacement=\ *string-literal* Additional message text that Clang will use to provide Fix-It when emitting a warning about use of a deprecated declaration. The Fix-It will replace the deprecated declaration with the new declaration specified. Multiple availability attributes can be placed on a declaration, which may correspond to different platforms. Only the availability attribute with the platform corresponding to the target platform will be used; any others will be ignored. If no availability attribute specifies availability for the current target platform, the availability attributes are ignored. Supported platforms are: ``ios`` Apple's iOS operating system. The minimum deployment target is specified by the ``-mios-version-min=*version*`` or ``-miphoneos-version-min=*version*`` command-line arguments. ``macos`` Apple's macOS operating system. The minimum deployment target is specified by the ``-mmacosx-version-min=*version*`` command-line argument. ``macosx`` is supported for backward-compatibility reasons, but it is deprecated. ``tvos`` Apple's tvOS operating system. The minimum deployment target is specified by the ``-mtvos-version-min=*version*`` command-line argument. ``watchos`` Apple's watchOS operating system. The minimum deployment target is specified by the ``-mwatchos-version-min=*version*`` command-line argument. A declaration can typically be used even when deploying back to a platform version prior to when the declaration was introduced. When this happens, the declaration is `weakly linked `_, as if the ``weak_import`` attribute were added to the declaration. A weakly-linked declaration may or may not be present a run-time, and a program can determine whether the declaration is present by checking whether the address of that declaration is non-NULL. The flag ``strict`` disallows using API when deploying back to a platform version prior to when the declaration was introduced. An attempt to use such API before its introduction causes a hard error. Weakly-linking is almost always a better API choice, since it allows users to query availability at runtime. If there are multiple declarations of the same entity, the availability attributes must either match on a per-platform basis or later declarations must not have availability attributes for that platform. For example: .. code-block:: c void g(void) __attribute__((availability(macos,introduced=10.4))); void g(void) __attribute__((availability(macos,introduced=10.4))); // okay, matches void g(void) __attribute__((availability(ios,introduced=4.0))); // okay, adds a new platform void g(void); // okay, inherits both macos and ios availability from above. void g(void) __attribute__((availability(macos,introduced=10.5))); // error: mismatch When one method overrides another, the overriding method can be more widely available than the overridden method, e.g.,: .. code-block:: objc @interface A - (id)method __attribute__((availability(macos,introduced=10.4))); - (id)method2 __attribute__((availability(macos,introduced=10.4))); @end @interface B : A - (id)method __attribute__((availability(macos,introduced=10.3))); // okay: method moved into base class later - (id)method __attribute__((availability(macos,introduced=10.5))); // error: this method was available via the base class in 10.4 @end Starting with the macOS 10.12 SDK, the ``API_AVAILABLE`` macro from ```` can simplify the spelling: .. code-block:: objc @interface A - (id)method API_AVAILABLE(macos(10.11))); - (id)otherMethod API_AVAILABLE(macos(10.11), ios(11.0)); @end Also see the documentation for `@available `_ }]; } def ExternalSourceSymbolDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``external_source_symbol`` attribute specifies that a declaration originates from an external source and describes the nature of that source. The fact that Clang is capable of recognizing declarations that were defined externally can be used to provide better tooling support for mixed-language projects or projects that rely on auto-generated code. For instance, an IDE that uses Clang and that supports mixed-language projects can use this attribute to provide a correct 'jump-to-definition' feature. For a concrete example, consider a protocol that's defined in a Swift file: .. code-block:: swift @objc public protocol SwiftProtocol { func method() } This protocol can be used from Objective-C code by including a header file that was generated by the Swift compiler. The declarations in that header can use the ``external_source_symbol`` attribute to make Clang aware of the fact that ``SwiftProtocol`` actually originates from a Swift module: .. code-block:: objc __attribute__((external_source_symbol(language="Swift",defined_in="module"))) @protocol SwiftProtocol @required - (void) method; @end Consequently, when 'jump-to-definition' is performed at a location that references ``SwiftProtocol``, the IDE can jump to the original definition in the Swift source file rather than jumping to the Objective-C declaration in the auto-generated header file. The ``external_source_symbol`` attribute is a comma-separated list that includes clauses that describe the origin and the nature of the particular declaration. Those clauses can be: language=\ *string-literal* The name of the source language in which this declaration was defined. defined_in=\ *string-literal* The name of the source container in which the declaration was defined. The exact definition of source container is language-specific, e.g. Swift's source containers are modules, so ``defined_in`` should specify the Swift module name. generated_declaration This declaration was automatically generated by some tool. The clauses can be specified in any order. The clauses that are listed above are all optional, but the attribute has to have at least one clause. }]; } def RequireConstantInitDocs : Documentation { let Category = DocCatVariable; let Content = [{ This attribute specifies that the variable to which it is attached is intended to have a `constant initializer `_ according to the rules of [basic.start.static]. The variable is required to have static or thread storage duration. If the initialization of the variable is not a constant initializer an error will be produced. This attribute may only be used in C++. Note that in C++03 strict constant expression checking is not done. Instead the attribute reports if Clang can emit the variable as a constant, even if it's not technically a 'constant initializer'. This behavior is non-portable. Static storage duration variables with constant initializers avoid hard-to-find bugs caused by the indeterminate order of dynamic initialization. They can also be safely used during dynamic initialization across translation units. This attribute acts as a compile time assertion that the requirements for constant initialization have been met. Since these requirements change between dialects and have subtle pitfalls it's important to fail fast instead of silently falling back on dynamic initialization. .. code-block:: c++ // -std=c++14 #define SAFE_STATIC [[clang::require_constant_initialization]] struct T { constexpr T(int) {} ~T(); // non-trivial }; SAFE_STATIC T x = {42}; // Initialization OK. Doesn't check destructor. SAFE_STATIC T y = 42; // error: variable does not have a constant initializer // copy initialization is not a constant expression on a non-literal type. }]; } def WarnMaybeUnusedDocs : Documentation { let Category = DocCatVariable; let Heading = "maybe_unused, unused, gnu::unused"; let Content = [{ When passing the ``-Wunused`` flag to Clang, entities that are unused by the program may be diagnosed. The ``[[maybe_unused]]`` (or ``__attribute__((unused))``) attribute can be used to silence such diagnostics when the entity cannot be removed. For instance, a local variable may exist solely for use in an ``assert()`` statement, which makes the local variable unused when ``NDEBUG`` is defined. The attribute may be applied to the declaration of a class, a typedef, a variable, a function or method, a function parameter, an enumeration, an enumerator, a non-static data member, or a label. .. code-block: c++ #include [[maybe_unused]] void f([[maybe_unused]] bool thing1, [[maybe_unused]] bool thing2) { [[maybe_unused]] bool b = thing1 && thing2; assert(b); } }]; } def WarnUnusedResultsDocs : Documentation { let Category = DocCatFunction; let Heading = "nodiscard, warn_unused_result, clang::warn_unused_result, gnu::warn_unused_result"; let Content = [{ Clang supports the ability to diagnose when the results of a function call expression are discarded under suspicious circumstances. A diagnostic is generated when a function or its return type is marked with ``[[nodiscard]]`` (or ``__attribute__((warn_unused_result))``) and the function call appears as a potentially-evaluated discarded-value expression that is not explicitly cast to `void`. .. code-block: c++ struct [[nodiscard]] error_info { /*...*/ }; error_info enable_missile_safety_mode(); void launch_missiles(); void test_missiles() { enable_missile_safety_mode(); // diagnoses launch_missiles(); } error_info &foo(); void f() { foo(); } // Does not diagnose, error_info is a reference. }]; } def FallthroughDocs : Documentation { let Category = DocCatStmt; let Heading = "fallthrough, clang::fallthrough"; let Content = [{ The ``fallthrough`` (or ``clang::fallthrough``) attribute is used to annotate intentional fall-through between switch labels. It can only be applied to a null statement placed at a point of execution between any statement and the next switch label. It is common to mark these places with a specific comment, but this attribute is meant to replace comments with a more strict annotation, which can be checked by the compiler. This attribute doesn't change semantics of the code and can be used wherever an intended fall-through occurs. It is designed to mimic control-flow statements like ``break;``, so it can be placed in most places where ``break;`` can, but only if there are no statements on the execution path between it and the next switch label. By default, Clang does not warn on unannotated fallthrough from one ``switch`` case to another. Diagnostics on fallthrough without a corresponding annotation can be enabled with the ``-Wimplicit-fallthrough`` argument. Here is an example: .. code-block:: c++ // compile with -Wimplicit-fallthrough switch (n) { case 22: case 33: // no warning: no statements between case labels f(); case 44: // warning: unannotated fall-through g(); [[clang::fallthrough]]; case 55: // no warning if (x) { h(); break; } else { i(); [[clang::fallthrough]]; } case 66: // no warning p(); [[clang::fallthrough]]; // warning: fallthrough annotation does not // directly precede case label q(); case 77: // warning: unannotated fall-through r(); } }]; } def ARMInterruptDocs : Documentation { let Category = DocCatFunction; let Heading = "interrupt (ARM)"; let Content = [{ Clang supports the GNU style ``__attribute__((interrupt("TYPE")))`` attribute on ARM targets. This attribute may be attached to a function definition and instructs the backend to generate appropriate function entry/exit code so that it can be used directly as an interrupt service routine. The parameter passed to the interrupt attribute is optional, but if provided it must be a string literal with one of the following values: "IRQ", "FIQ", "SWI", "ABORT", "UNDEF". The semantics are as follows: - If the function is AAPCS, Clang instructs the backend to realign the stack to 8 bytes on entry. This is a general requirement of the AAPCS at public interfaces, but may not hold when an exception is taken. Doing this allows other AAPCS functions to be called. - If the CPU is M-class this is all that needs to be done since the architecture itself is designed in such a way that functions obeying the normal AAPCS ABI constraints are valid exception handlers. - If the CPU is not M-class, the prologue and epilogue are modified to save all non-banked registers that are used, so that upon return the user-mode state will not be corrupted. Note that to avoid unnecessary overhead, only general-purpose (integer) registers are saved in this way. If VFP operations are needed, that state must be saved manually. Specifically, interrupt kinds other than "FIQ" will save all core registers except "lr" and "sp". "FIQ" interrupts will save r0-r7. - If the CPU is not M-class, the return instruction is changed to one of the canonical sequences permitted by the architecture for exception return. Where possible the function itself will make the necessary "lr" adjustments so that the "preferred return address" is selected. Unfortunately the compiler is unable to make this guarantee for an "UNDEF" handler, where the offset from "lr" to the preferred return address depends on the execution state of the code which generated the exception. In this case a sequence equivalent to "movs pc, lr" will be used. }]; } def MipsInterruptDocs : Documentation { let Category = DocCatFunction; let Heading = "interrupt (MIPS)"; let Content = [{ Clang supports the GNU style ``__attribute__((interrupt("ARGUMENT")))`` attribute on MIPS targets. This attribute may be attached to a function definition and instructs the backend to generate appropriate function entry/exit code so that it can be used directly as an interrupt service routine. By default, the compiler will produce a function prologue and epilogue suitable for an interrupt service routine that handles an External Interrupt Controller (eic) generated interrupt. This behaviour can be explicitly requested with the "eic" argument. Otherwise, for use with vectored interrupt mode, the argument passed should be of the form "vector=LEVEL" where LEVEL is one of the following values: "sw0", "sw1", "hw0", "hw1", "hw2", "hw3", "hw4", "hw5". The compiler will then set the interrupt mask to the corresponding level which will mask all interrupts up to and including the argument. The semantics are as follows: - The prologue is modified so that the Exception Program Counter (EPC) and Status coprocessor registers are saved to the stack. The interrupt mask is set so that the function can only be interrupted by a higher priority interrupt. The epilogue will restore the previous values of EPC and Status. - The prologue and epilogue are modified to save and restore all non-kernel registers as necessary. - The FPU is disabled in the prologue, as the floating pointer registers are not spilled to the stack. - The function return sequence is changed to use an exception return instruction. - The parameter sets the interrupt mask for the function corresponding to the interrupt level specified. If no mask is specified the interrupt mask defaults to "eic". }]; } def MicroMipsDocs : Documentation { let Category = DocCatFunction; let Content = [{ Clang supports the GNU style ``__attribute__((micromips))`` and ``__attribute__((nomicromips))`` attributes on MIPS targets. These attributes may be attached to a function definition and instructs the backend to generate or not to generate microMIPS code for that function. These attributes override the `-mmicromips` and `-mno-micromips` options on the command line. }]; } def MipsLongCallStyleDocs : Documentation { let Category = DocCatFunction; let Heading = "long_call (gnu::long_call, gnu::far)"; let Content = [{ Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``, and ``__attribute__((near))`` attributes on MIPS targets. These attributes may only be added to function declarations and change the code generated by the compiler when directly calling the function. The ``near`` attribute allows calls to the function to be made using the ``jal`` instruction, which requires the function to be located in the same naturally aligned 256MB segment as the caller. The ``long_call`` and ``far`` attributes are synonyms and require the use of a different call sequence that works regardless of the distance between the functions. These attributes have no effect for position-independent code. These attributes take priority over command line switches such as ``-mlong-calls`` and ``-mno-long-calls``. }]; } def MipsShortCallStyleDocs : Documentation { let Category = DocCatFunction; let Heading = "short_call (gnu::short_call, gnu::near)"; let Content = [{ Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``, ``__attribute__((short__call))``, and ``__attribute__((near))`` attributes on MIPS targets. These attributes may only be added to function declarations and change the code generated by the compiler when directly calling the function. The ``short_call`` and ``near`` attributes are synonyms and allow calls to the function to be made using the ``jal`` instruction, which requires the function to be located in the same naturally aligned 256MB segment as the caller. The ``long_call`` and ``far`` attributes are synonyms and require the use of a different call sequence that works regardless of the distance between the functions. These attributes have no effect for position-independent code. These attributes take priority over command line switches such as ``-mlong-calls`` and ``-mno-long-calls``. }]; } def RISCVInterruptDocs : Documentation { let Category = DocCatFunction; let Heading = "interrupt (RISCV)"; let Content = [{ Clang supports the GNU style ``__attribute__((interrupt))`` attribute on RISCV targets. This attribute may be attached to a function definition and instructs the backend to generate appropriate function entry/exit code so that it can be used directly as an interrupt service routine. Permissible values for this parameter are ``user``, ``supervisor``, and ``machine``. If there is no parameter, then it defaults to machine. Repeated interrupt attribute on the same declaration will cause a warning to be emitted. In case of repeated declarations, the last one prevails. Refer to: https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html https://riscv.org/specifications/privileged-isa/ The RISC-V Instruction Set Manual Volume II: Privileged Architecture Version 1.10. }]; } def AVRInterruptDocs : Documentation { let Category = DocCatFunction; let Heading = "interrupt (AVR)"; let Content = [{ Clang supports the GNU style ``__attribute__((interrupt))`` attribute on AVR targets. This attribute may be attached to a function definition and instructs the backend to generate appropriate function entry/exit code so that it can be used directly as an interrupt service routine. On the AVR, the hardware globally disables interrupts when an interrupt is executed. The first instruction of an interrupt handler declared with this attribute is a SEI instruction to re-enable interrupts. See also the signal attribute that does not insert a SEI instruction. }]; } def AVRSignalDocs : Documentation { let Category = DocCatFunction; let Content = [{ Clang supports the GNU style ``__attribute__((signal))`` attribute on AVR targets. This attribute may be attached to a function definition and instructs the backend to generate appropriate function entry/exit code so that it can be used directly as an interrupt service routine. Interrupt handler functions defined with the signal attribute do not re-enable interrupts. }]; } def TargetDocs : Documentation { let Category = DocCatFunction; let Content = [{ Clang supports the GNU style ``__attribute__((target("OPTIONS")))`` attribute. This attribute may be attached to a function definition and instructs the backend to use different code generation options than were passed on the command line. The current set of options correspond to the existing "subtarget features" for the target with or without a "-mno-" in front corresponding to the absence of the feature, as well as ``arch="CPU"`` which will change the default "CPU" for the function. Example "subtarget features" from the x86 backend include: "mmx", "sse", "sse4.2", "avx", "xop" and largely correspond to the machine specific options handled by the front end. Additionally, this attribute supports function multiversioning for ELF based x86/x86-64 targets, which can be used to create multiple implementations of the same function that will be resolved at runtime based on the priority of their ``target`` attribute strings. A function is considered a multiversioned function if either two declarations of the function have different ``target`` attribute strings, or if it has a ``target`` attribute string of ``default``. For example: .. code-block:: c++ __attribute__((target("arch=atom"))) void foo() {} // will be called on 'atom' processors. __attribute__((target("default"))) void foo() {} // will be called on any other processors. All multiversioned functions must contain a ``default`` (fallback) implementation, otherwise usages of the function are considered invalid. Additionally, a function may not become multiversioned after its first use. }]; } def MinVectorWidthDocs : Documentation { let Category = DocCatFunction; let Content = [{ Clang supports the ``__attribute__((min_vector_width(width)))`` attribute. This attribute may be attached to a function and informs the backend that this function desires vectors of at least this width to be generated. Target-specific maximum vector widths still apply. This means even if you ask for something larger than the target supports, you will only get what the target supports. This attribute is meant to be a hint to control target heuristics that may generate narrower vectors than what the target hardware supports. This is currently used by the X86 target to allow some CPUs that support 512-bit vectors to be limited to using 256-bit vectors to avoid frequency penalties. This is currently enabled with the ``-prefer-vector-width=256`` command line option. The ``min_vector_width`` attribute can be used to prevent the backend from trying to split vector operations to match the ``prefer-vector-width``. All X86 vector intrinsics from x86intrin.h already set this attribute. Additionally, use of any of the X86-specific vector builtins will implicitly set this attribute on the calling function. The intent is that explicitly writing vector code using the X86 intrinsics will prevent ``prefer-vector-width`` from affecting the code. }]; } def DocCatAMDGPUAttributes : DocumentationCategory<"AMD GPU Attributes">; def AMDGPUFlatWorkGroupSizeDocs : Documentation { let Category = DocCatAMDGPUAttributes; let Content = [{ The flat work-group size is the number of work-items in the work-group size specified when the kernel is dispatched. It is the product of the sizes of the x, y, and z dimension of the work-group. Clang supports the ``__attribute__((amdgpu_flat_work_group_size(, )))`` attribute for the AMDGPU target. This attribute may be attached to a kernel function definition and is an optimization hint. ```` parameter specifies the minimum flat work-group size, and ```` parameter specifies the maximum flat work-group size (must be greater than ````) to which all dispatches of the kernel will conform. Passing ``0, 0`` as ``, `` implies the default behavior (``128, 256``). If specified, the AMDGPU target backend might be able to produce better machine code for barriers and perform scratch promotion by estimating available group segment size. An error will be given if: - Specified values violate subtarget specifications; - Specified values are not compatible with values provided through other attributes. }]; } def AMDGPUWavesPerEUDocs : Documentation { let Category = DocCatAMDGPUAttributes; let Content = [{ A compute unit (CU) is responsible for executing the wavefronts of a work-group. It is composed of one or more execution units (EU), which are responsible for executing the wavefronts. An EU can have enough resources to maintain the state of more than one executing wavefront. This allows an EU to hide latency by switching between wavefronts in a similar way to symmetric multithreading on a CPU. In order to allow the state for multiple wavefronts to fit on an EU, the resources used by a single wavefront have to be limited. For example, the number of SGPRs and VGPRs. Limiting such resources can allow greater latency hiding, but can result in having to spill some register state to memory. Clang supports the ``__attribute__((amdgpu_waves_per_eu([, ])))`` attribute for the AMDGPU target. This attribute may be attached to a kernel function definition and is an optimization hint. ```` parameter specifies the requested minimum number of waves per EU, and *optional* ```` parameter specifies the requested maximum number of waves per EU (must be greater than ```` if specified). If ```` is omitted, then there is no restriction on the maximum number of waves per EU other than the one dictated by the hardware for which the kernel is compiled. Passing ``0, 0`` as ``, `` implies the default behavior (no limits). If specified, this attribute allows an advanced developer to tune the number of wavefronts that are capable of fitting within the resources of an EU. The AMDGPU target backend can use this information to limit resources, such as number of SGPRs, number of VGPRs, size of available group and private memory segments, in such a way that guarantees that at least ```` wavefronts and at most ```` wavefronts are able to fit within the resources of an EU. Requesting more wavefronts can hide memory latency but limits available registers which can result in spilling. Requesting fewer wavefronts can help reduce cache thrashing, but can reduce memory latency hiding. This attribute controls the machine code generated by the AMDGPU target backend to ensure it is capable of meeting the requested values. However, when the kernel is executed, there may be other reasons that prevent meeting the request, for example, there may be wavefronts from other kernels executing on the EU. An error will be given if: - Specified values violate subtarget specifications; - Specified values are not compatible with values provided through other attributes; - The AMDGPU target backend is unable to create machine code that can meet the request. }]; } def AMDGPUNumSGPRNumVGPRDocs : Documentation { let Category = DocCatAMDGPUAttributes; let Content = [{ Clang supports the ``__attribute__((amdgpu_num_sgpr()))`` and ``__attribute__((amdgpu_num_vgpr()))`` attributes for the AMDGPU target. These attributes may be attached to a kernel function definition and are an optimization hint. If these attributes are specified, then the AMDGPU target backend will attempt to limit the number of SGPRs and/or VGPRs used to the specified value(s). The number of used SGPRs and/or VGPRs may further be rounded up to satisfy the allocation requirements or constraints of the subtarget. Passing ``0`` as ``num_sgpr`` and/or ``num_vgpr`` implies the default behavior (no limits). These attributes can be used to test the AMDGPU target backend. It is recommended that the ``amdgpu_waves_per_eu`` attribute be used to control resources such as SGPRs and VGPRs since it is aware of the limits for different subtargets. An error will be given if: - Specified values violate subtarget specifications; - Specified values are not compatible with values provided through other attributes; - The AMDGPU target backend is unable to create machine code that can meet the request. }]; } def DocCatCallingConvs : DocumentationCategory<"Calling Conventions"> { let Content = [{ Clang supports several different calling conventions, depending on the target platform and architecture. The calling convention used for a function determines how parameters are passed, how results are returned to the caller, and other low-level details of calling a function. }]; } def PcsDocs : Documentation { let Category = DocCatCallingConvs; let Content = [{ On ARM targets, this attribute can be used to select calling conventions similar to ``stdcall`` on x86. Valid parameter values are "aapcs" and "aapcs-vfp". }]; } def RegparmDocs : Documentation { let Category = DocCatCallingConvs; let Content = [{ On 32-bit x86 targets, the regparm attribute causes the compiler to pass the first three integer parameters in EAX, EDX, and ECX instead of on the stack. This attribute has no effect on variadic functions, and all parameters are passed via the stack as normal. }]; } def SysVABIDocs : Documentation { let Category = DocCatCallingConvs; let Content = [{ On Windows x86_64 targets, this attribute changes the calling convention of a function to match the default convention used on Sys V targets such as Linux, Mac, and BSD. This attribute has no effect on other targets. }]; } def MSABIDocs : Documentation { let Category = DocCatCallingConvs; let Content = [{ On non-Windows x86_64 targets, this attribute changes the calling convention of a function to match the default convention used on Windows x86_64. This attribute has no effect on Windows targets or non-x86_64 targets. }]; } def StdCallDocs : Documentation { let Category = DocCatCallingConvs; let Content = [{ On 32-bit x86 targets, this attribute changes the calling convention of a function to clear parameters off of the stack on return. This convention does not support variadic calls or unprototyped functions in C, and has no effect on x86_64 targets. This calling convention is used widely by the Windows API and COM applications. See the documentation for `__stdcall`_ on MSDN. .. _`__stdcall`: http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx }]; } def FastCallDocs : Documentation { let Category = DocCatCallingConvs; let Content = [{ On 32-bit x86 targets, this attribute changes the calling convention of a function to use ECX and EDX as register parameters and clear parameters off of the stack on return. This convention does not support variadic calls or unprototyped functions in C, and has no effect on x86_64 targets. This calling convention is supported primarily for compatibility with existing code. Users seeking register parameters should use the ``regparm`` attribute, which does not require callee-cleanup. See the documentation for `__fastcall`_ on MSDN. .. _`__fastcall`: http://msdn.microsoft.com/en-us/library/6xa169sk.aspx }]; } def RegCallDocs : Documentation { let Category = DocCatCallingConvs; let Content = [{ On x86 targets, this attribute changes the calling convention to `__regcall`_ convention. This convention aims to pass as many arguments as possible in registers. It also tries to utilize registers for the return value whenever it is possible. .. _`__regcall`: https://software.intel.com/en-us/node/693069 }]; } def ThisCallDocs : Documentation { let Category = DocCatCallingConvs; let Content = [{ On 32-bit x86 targets, this attribute changes the calling convention of a function to use ECX for the first parameter (typically the implicit ``this`` parameter of C++ methods) and clear parameters off of the stack on return. This convention does not support variadic calls or unprototyped functions in C, and has no effect on x86_64 targets. See the documentation for `__thiscall`_ on MSDN. .. _`__thiscall`: http://msdn.microsoft.com/en-us/library/ek8tkfbw.aspx }]; } def VectorCallDocs : Documentation { let Category = DocCatCallingConvs; let Content = [{ On 32-bit x86 *and* x86_64 targets, this attribute changes the calling convention of a function to pass vector parameters in SSE registers. On 32-bit x86 targets, this calling convention is similar to ``__fastcall``. The first two integer parameters are passed in ECX and EDX. Subsequent integer parameters are passed in memory, and callee clears the stack. On x86_64 targets, the callee does *not* clear the stack, and integer parameters are passed in RCX, RDX, R8, and R9 as is done for the default Windows x64 calling convention. On both 32-bit x86 and x86_64 targets, vector and floating point arguments are passed in XMM0-XMM5. Homogeneous vector aggregates of up to four elements are passed in sequential SSE registers if enough are available. If AVX is enabled, 256 bit vectors are passed in YMM0-YMM5. Any vector or aggregate type that cannot be passed in registers for any reason is passed by reference, which allows the caller to align the parameter memory. See the documentation for `__vectorcall`_ on MSDN for more details. .. _`__vectorcall`: http://msdn.microsoft.com/en-us/library/dn375768.aspx }]; } def DocCatConsumed : DocumentationCategory<"Consumed Annotation Checking"> { let Content = [{ Clang supports additional attributes for checking basic resource management properties, specifically for unique objects that have a single owning reference. The following attributes are currently supported, although **the implementation for these annotations is currently in development and are subject to change.** }]; } def SetTypestateDocs : Documentation { let Category = DocCatConsumed; let Content = [{ Annotate methods that transition an object into a new state with ``__attribute__((set_typestate(new_state)))``. The new state must be unconsumed, consumed, or unknown. }]; } def CallableWhenDocs : Documentation { let Category = DocCatConsumed; let Content = [{ Use ``__attribute__((callable_when(...)))`` to indicate what states a method may be called in. Valid states are unconsumed, consumed, or unknown. Each argument to this attribute must be a quoted string. E.g.: ``__attribute__((callable_when("unconsumed", "unknown")))`` }]; } def TestTypestateDocs : Documentation { let Category = DocCatConsumed; let Content = [{ Use ``__attribute__((test_typestate(tested_state)))`` to indicate that a method returns true if the object is in the specified state.. }]; } def ParamTypestateDocs : Documentation { let Category = DocCatConsumed; let Content = [{ This attribute specifies expectations about function parameters. Calls to an function with annotated parameters will issue a warning if the corresponding argument isn't in the expected state. The attribute is also used to set the initial state of the parameter when analyzing the function's body. }]; } def ReturnTypestateDocs : Documentation { let Category = DocCatConsumed; let Content = [{ The ``return_typestate`` attribute can be applied to functions or parameters. When applied to a function the attribute specifies the state of the returned value. The function's body is checked to ensure that it always returns a value in the specified state. On the caller side, values returned by the annotated function are initialized to the given state. When applied to a function parameter it modifies the state of an argument after a call to the function returns. The function's body is checked to ensure that the parameter is in the expected state before returning. }]; } def ConsumableDocs : Documentation { let Category = DocCatConsumed; let Content = [{ Each ``class`` that uses any of the typestate annotations must first be marked using the ``consumable`` attribute. Failure to do so will result in a warning. This attribute accepts a single parameter that must be one of the following: ``unknown``, ``consumed``, or ``unconsumed``. }]; } def NoSanitizeDocs : Documentation { let Category = DocCatFunction; let Content = [{ Use the ``no_sanitize`` attribute on a function or a global variable declaration to specify that a particular instrumentation or set of instrumentations should not be applied. The attribute takes a list of string literals, which have the same meaning as values accepted by the ``-fno-sanitize=`` flag. For example, ``__attribute__((no_sanitize("address", "thread")))`` specifies that AddressSanitizer and ThreadSanitizer should not be applied to the function or variable. See :ref:`Controlling Code Generation ` for a full list of supported sanitizer flags. }]; } def NoSanitizeAddressDocs : Documentation { let Category = DocCatFunction; // This function has multiple distinct spellings, and so it requires a custom // heading to be specified. The most common spelling is sufficient. let Heading = "no_sanitize_address (no_address_safety_analysis, gnu::no_address_safety_analysis, gnu::no_sanitize_address)"; let Content = [{ .. _langext-address_sanitizer: Use ``__attribute__((no_sanitize_address))`` on a function or a global variable declaration to specify that address safety instrumentation (e.g. AddressSanitizer) should not be applied. }]; } def NoSanitizeThreadDocs : Documentation { let Category = DocCatFunction; let Heading = "no_sanitize_thread"; let Content = [{ .. _langext-thread_sanitizer: Use ``__attribute__((no_sanitize_thread))`` on a function declaration to specify that checks for data races on plain (non-atomic) memory accesses should not be inserted by ThreadSanitizer. The function is still instrumented by the tool to avoid false positives and provide meaningful stack traces. }]; } def NoSanitizeMemoryDocs : Documentation { let Category = DocCatFunction; let Heading = "no_sanitize_memory"; let Content = [{ .. _langext-memory_sanitizer: Use ``__attribute__((no_sanitize_memory))`` on a function declaration to specify that checks for uninitialized memory should not be inserted (e.g. by MemorySanitizer). The function may still be instrumented by the tool to avoid false positives in other places. }]; } def DocCatTypeSafety : DocumentationCategory<"Type Safety Checking"> { let Content = [{ Clang supports additional attributes to enable checking type safety properties that can't be enforced by the C type system. To see warnings produced by these checks, ensure that -Wtype-safety is enabled. Use cases include: * MPI library implementations, where these attributes enable checking that the buffer type matches the passed ``MPI_Datatype``; * for HDF5 library there is a similar use case to MPI; * checking types of variadic functions' arguments for functions like ``fcntl()`` and ``ioctl()``. You can detect support for these attributes with ``__has_attribute()``. For example: .. code-block:: c++ #if defined(__has_attribute) # if __has_attribute(argument_with_type_tag) && \ __has_attribute(pointer_with_type_tag) && \ __has_attribute(type_tag_for_datatype) # define ATTR_MPI_PWT(buffer_idx, type_idx) __attribute__((pointer_with_type_tag(mpi,buffer_idx,type_idx))) /* ... other macros ... */ # endif #endif #if !defined(ATTR_MPI_PWT) # define ATTR_MPI_PWT(buffer_idx, type_idx) #endif int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */) ATTR_MPI_PWT(1,3); }]; } def ArgumentWithTypeTagDocs : Documentation { let Category = DocCatTypeSafety; let Heading = "argument_with_type_tag"; let Content = [{ Use ``__attribute__((argument_with_type_tag(arg_kind, arg_idx, type_tag_idx)))`` on a function declaration to specify that the function accepts a type tag that determines the type of some other argument. This attribute is primarily useful for checking arguments of variadic functions (``pointer_with_type_tag`` can be used in most non-variadic cases). In the attribute prototype above: * ``arg_kind`` is an identifier that should be used when annotating all applicable type tags. * ``arg_idx`` provides the position of a function argument. The expected type of this function argument will be determined by the function argument specified by ``type_tag_idx``. In the code example below, "3" means that the type of the function's third argument will be determined by ``type_tag_idx``. * ``type_tag_idx`` provides the position of a function argument. This function argument will be a type tag. The type tag will determine the expected type of the argument specified by ``arg_idx``. In the code example below, "2" means that the type tag associated with the function's second argument should agree with the type of the argument specified by ``arg_idx``. For example: .. code-block:: c++ int fcntl(int fd, int cmd, ...) __attribute__(( argument_with_type_tag(fcntl,3,2) )); // The function's second argument will be a type tag; this type tag will // determine the expected type of the function's third argument. }]; } def PointerWithTypeTagDocs : Documentation { let Category = DocCatTypeSafety; let Heading = "pointer_with_type_tag"; let Content = [{ Use ``__attribute__((pointer_with_type_tag(ptr_kind, ptr_idx, type_tag_idx)))`` on a function declaration to specify that the function accepts a type tag that determines the pointee type of some other pointer argument. In the attribute prototype above: * ``ptr_kind`` is an identifier that should be used when annotating all applicable type tags. * ``ptr_idx`` provides the position of a function argument; this function argument will have a pointer type. The expected pointee type of this pointer type will be determined by the function argument specified by ``type_tag_idx``. In the code example below, "1" means that the pointee type of the function's first argument will be determined by ``type_tag_idx``. * ``type_tag_idx`` provides the position of a function argument; this function argument will be a type tag. The type tag will determine the expected pointee type of the pointer argument specified by ``ptr_idx``. In the code example below, "3" means that the type tag associated with the function's third argument should agree with the pointee type of the pointer argument specified by ``ptr_idx``. For example: .. code-block:: c++ typedef int MPI_Datatype; int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */) __attribute__(( pointer_with_type_tag(mpi,1,3) )); // The function's 3rd argument will be a type tag; this type tag will // determine the expected pointee type of the function's 1st argument. }]; } def TypeTagForDatatypeDocs : Documentation { let Category = DocCatTypeSafety; let Content = [{ When declaring a variable, use ``__attribute__((type_tag_for_datatype(kind, type)))`` to create a type tag that is tied to the ``type`` argument given to the attribute. In the attribute prototype above: * ``kind`` is an identifier that should be used when annotating all applicable type tags. * ``type`` indicates the name of the type. Clang supports annotating type tags of two forms. * **Type tag that is a reference to a declared identifier.** Use ``__attribute__((type_tag_for_datatype(kind, type)))`` when declaring that identifier: .. code-block:: c++ typedef int MPI_Datatype; extern struct mpi_datatype mpi_datatype_int __attribute__(( type_tag_for_datatype(mpi,int) )); #define MPI_INT ((MPI_Datatype) &mpi_datatype_int) // &mpi_datatype_int is a type tag. It is tied to type "int". * **Type tag that is an integral literal.** Declare a ``static const`` variable with an initializer value and attach ``__attribute__((type_tag_for_datatype(kind, type)))`` on that declaration: .. code-block:: c++ typedef int MPI_Datatype; static const MPI_Datatype mpi_datatype_int __attribute__(( type_tag_for_datatype(mpi,int) )) = 42; #define MPI_INT ((MPI_Datatype) 42) // The number 42 is a type tag. It is tied to type "int". The ``type_tag_for_datatype`` attribute also accepts an optional third argument that determines how the type of the function argument specified by either ``arg_idx`` or ``ptr_idx`` is compared against the type associated with the type tag. (Recall that for the ``argument_with_type_tag`` attribute, the type of the function argument specified by ``arg_idx`` is compared against the type associated with the type tag. Also recall that for the ``pointer_with_type_tag`` attribute, the pointee type of the function argument specified by ``ptr_idx`` is compared against the type associated with the type tag.) There are two supported values for this optional third argument: * ``layout_compatible`` will cause types to be compared according to layout-compatibility rules (In C++11 [class.mem] p 17, 18, see the layout-compatibility rules for two standard-layout struct types and for two standard-layout union types). This is useful when creating a type tag associated with a struct or union type. For example: .. code-block:: c++ /* In mpi.h */ typedef int MPI_Datatype; struct internal_mpi_double_int { double d; int i; }; extern struct mpi_datatype mpi_datatype_double_int __attribute__(( type_tag_for_datatype(mpi, struct internal_mpi_double_int, layout_compatible) )); #define MPI_DOUBLE_INT ((MPI_Datatype) &mpi_datatype_double_int) int MPI_Send(void *buf, int count, MPI_Datatype datatype, ...) __attribute__(( pointer_with_type_tag(mpi,1,3) )); /* In user code */ struct my_pair { double a; int b; }; struct my_pair *buffer; MPI_Send(buffer, 1, MPI_DOUBLE_INT /*, ... */); // no warning because the // layout of my_pair is // compatible with that of // internal_mpi_double_int struct my_int_pair { int a; int b; } struct my_int_pair *buffer2; MPI_Send(buffer2, 1, MPI_DOUBLE_INT /*, ... */); // warning because the // layout of my_int_pair // does not match that of // internal_mpi_double_int * ``must_be_null`` specifies that the function argument specified by either ``arg_idx`` (for the ``argument_with_type_tag`` attribute) or ``ptr_idx`` (for the ``pointer_with_type_tag`` attribute) should be a null pointer constant. The second argument to the ``type_tag_for_datatype`` attribute is ignored. For example: .. code-block:: c++ /* In mpi.h */ typedef int MPI_Datatype; extern struct mpi_datatype mpi_datatype_null __attribute__(( type_tag_for_datatype(mpi, void, must_be_null) )); #define MPI_DATATYPE_NULL ((MPI_Datatype) &mpi_datatype_null) int MPI_Send(void *buf, int count, MPI_Datatype datatype, ...) __attribute__(( pointer_with_type_tag(mpi,1,3) )); /* In user code */ struct my_pair { double a; int b; }; struct my_pair *buffer; MPI_Send(buffer, 1, MPI_DATATYPE_NULL /*, ... */); // warning: MPI_DATATYPE_NULL // was specified but buffer // is not a null pointer }]; } def FlattenDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``flatten`` attribute causes calls within the attributed function to be inlined unless it is impossible to do so, for example if the body of the callee is unavailable or if the callee has the ``noinline`` attribute. }]; } def FormatDocs : Documentation { let Category = DocCatFunction; let Content = [{ Clang supports the ``format`` attribute, which indicates that the function accepts a ``printf`` or ``scanf``-like format string and corresponding arguments or a ``va_list`` that contains these arguments. Please see `GCC documentation about format attribute `_ to find details about attribute syntax. Clang implements two kinds of checks with this attribute. #. Clang checks that the function with the ``format`` attribute is called with a format string that uses format specifiers that are allowed, and that arguments match the format string. This is the ``-Wformat`` warning, it is on by default. #. Clang checks that the format string argument is a literal string. This is the ``-Wformat-nonliteral`` warning, it is off by default. Clang implements this mostly the same way as GCC, but there is a difference for functions that accept a ``va_list`` argument (for example, ``vprintf``). GCC does not emit ``-Wformat-nonliteral`` warning for calls to such functions. Clang does not warn if the format string comes from a function parameter, where the function is annotated with a compatible attribute, otherwise it warns. For example: .. code-block:: c __attribute__((__format__ (__scanf__, 1, 3))) void foo(const char* s, char *buf, ...) { va_list ap; va_start(ap, buf); vprintf(s, ap); // warning: format string is not a string literal } In this case we warn because ``s`` contains a format string for a ``scanf``-like function, but it is passed to a ``printf``-like function. If the attribute is removed, clang still warns, because the format string is not a string literal. Another example: .. code-block:: c __attribute__((__format__ (__printf__, 1, 3))) void foo(const char* s, char *buf, ...) { va_list ap; va_start(ap, buf); vprintf(s, ap); // warning } In this case Clang does not warn because the format string ``s`` and the corresponding arguments are annotated. If the arguments are incorrect, the caller of ``foo`` will receive a warning. }]; } def AlignValueDocs : Documentation { let Category = DocCatType; let Content = [{ The align_value attribute can be added to the typedef of a pointer type or the declaration of a variable of pointer or reference type. It specifies that the pointer will point to, or the reference will bind to, only objects with at least the provided alignment. This alignment value must be some positive power of 2. .. code-block:: c typedef double * aligned_double_ptr __attribute__((align_value(64))); void foo(double & x __attribute__((align_value(128)), aligned_double_ptr y) { ... } If the pointer value does not have the specified alignment at runtime, the behavior of the program is undefined. }]; } def FlagEnumDocs : Documentation { let Category = DocCatType; let Content = [{ This attribute can be added to an enumerator to signal to the compiler that it is intended to be used as a flag type. This will cause the compiler to assume that the range of the type includes all of the values that you can get by manipulating bits of the enumerator when issuing warnings. }]; } def EnumExtensibilityDocs : Documentation { let Category = DocCatType; let Content = [{ Attribute ``enum_extensibility`` is used to distinguish between enum definitions that are extensible and those that are not. The attribute can take either ``closed`` or ``open`` as an argument. ``closed`` indicates a variable of the enum type takes a value that corresponds to one of the enumerators listed in the enum definition or, when the enum is annotated with ``flag_enum``, a value that can be constructed using values corresponding to the enumerators. ``open`` indicates a variable of the enum type can take any values allowed by the standard and instructs clang to be more lenient when issuing warnings. .. code-block:: c enum __attribute__((enum_extensibility(closed))) ClosedEnum { A0, A1 }; enum __attribute__((enum_extensibility(open))) OpenEnum { B0, B1 }; enum __attribute__((enum_extensibility(closed),flag_enum)) ClosedFlagEnum { C0 = 1 << 0, C1 = 1 << 1 }; enum __attribute__((enum_extensibility(open),flag_enum)) OpenFlagEnum { D0 = 1 << 0, D1 = 1 << 1 }; void foo1() { enum ClosedEnum ce; enum OpenEnum oe; enum ClosedFlagEnum cfe; enum OpenFlagEnum ofe; ce = A1; // no warnings ce = 100; // warning issued oe = B1; // no warnings oe = 100; // no warnings cfe = C0 | C1; // no warnings cfe = C0 | C1 | 4; // warning issued ofe = D0 | D1; // no warnings ofe = D0 | D1 | 4; // no warnings } }]; } def EmptyBasesDocs : Documentation { let Category = DocCatType; let Content = [{ The empty_bases attribute permits the compiler to utilize the empty-base-optimization more frequently. This attribute only applies to struct, class, and union types. It is only supported when using the Microsoft C++ ABI. }]; } def LayoutVersionDocs : Documentation { let Category = DocCatType; let Content = [{ The layout_version attribute requests that the compiler utilize the class layout rules of a particular compiler version. This attribute only applies to struct, class, and union types. It is only supported when using the Microsoft C++ ABI. }]; } def LifetimeBoundDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``lifetimebound`` attribute indicates that a resource owned by a function parameter or implicit object parameter is retained by the return value of the annotated function (or, for a parameter of a constructor, in the value of the constructed object). It is only supported in C++. This attribute provides an experimental implementation of the facility described in the C++ committee paper [http://wg21.link/p0936r0](P0936R0), and is subject to change as the design of the corresponding functionality changes. }]; } def TrivialABIDocs : Documentation { let Category = DocCatVariable; let Content = [{ The ``trivial_abi`` attribute can be applied to a C++ class, struct, or union. It instructs the compiler to pass and return the type using the C ABI for the underlying type when the type would otherwise be considered non-trivial for the purpose of calls. A class annotated with `trivial_abi` can have non-trivial destructors or copy/move constructors without automatically becoming non-trivial for the purposes of calls. For example: .. code-block:: c++ // A is trivial for the purposes of calls because `trivial_abi` makes the // user-provided special functions trivial. struct __attribute__((trivial_abi)) A { ~A(); A(const A &); A(A &&); int x; }; // B's destructor and copy/move constructor are considered trivial for the // purpose of calls because A is trivial. struct B { A a; }; If a type is trivial for the purposes of calls, has a non-trivial destructor, and is passed as an argument by value, the convention is that the callee will destroy the object before returning. Attribute ``trivial_abi`` has no effect in the following cases: - The class directly declares a virtual base or virtual methods. - The class has a base class that is non-trivial for the purposes of calls. - The class has a non-static data member whose type is non-trivial for the purposes of calls, which includes: - classes that are non-trivial for the purposes of calls - __weak-qualified types in Objective-C++ - arrays of any of the above }]; } def MSInheritanceDocs : Documentation { let Category = DocCatType; let Heading = "__single_inhertiance, __multiple_inheritance, __virtual_inheritance"; let Content = [{ This collection of keywords is enabled under ``-fms-extensions`` and controls the pointer-to-member representation used on ``*-*-win32`` targets. The ``*-*-win32`` targets utilize a pointer-to-member representation which varies in size and alignment depending on the definition of the underlying class. However, this is problematic when a forward declaration is only available and no definition has been made yet. In such cases, Clang is forced to utilize the most general representation that is available to it. These keywords make it possible to use a pointer-to-member representation other than the most general one regardless of whether or not the definition will ever be present in the current translation unit. This family of keywords belong between the ``class-key`` and ``class-name``: .. code-block:: c++ struct __single_inheritance S; int S::*i; struct S {}; This keyword can be applied to class templates but only has an effect when used on full specializations: .. code-block:: c++ template struct __single_inheritance A; // warning: inheritance model ignored on primary template template struct __multiple_inheritance A; // warning: inheritance model ignored on partial specialization template <> struct __single_inheritance A; Note that choosing an inheritance model less general than strictly necessary is an error: .. code-block:: c++ struct __multiple_inheritance S; // error: inheritance model does not match definition int S::*i; struct S {}; }]; } def MSNoVTableDocs : Documentation { let Category = DocCatType; let Content = [{ This attribute can be added to a class declaration or definition to signal to the compiler that constructors and destructors will not reference the virtual function table. It is only supported when using the Microsoft C++ ABI. }]; } def OptnoneDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``optnone`` attribute suppresses essentially all optimizations on a function or method, regardless of the optimization level applied to the compilation unit as a whole. This is particularly useful when you need to debug a particular function, but it is infeasible to build the entire application without optimization. Avoiding optimization on the specified function can improve the quality of the debugging information for that function. This attribute is incompatible with the ``always_inline`` and ``minsize`` attributes. }]; } def LoopHintDocs : Documentation { let Category = DocCatStmt; let Heading = "#pragma clang loop"; let Content = [{ The ``#pragma clang loop`` directive allows loop optimization hints to be specified for the subsequent loop. The directive allows vectorization, interleaving, and unrolling to be enabled or disabled. Vector width as well as interleave and unrolling count can be manually specified. See `language extensions `_ for details. }]; } def UnrollHintDocs : Documentation { let Category = DocCatStmt; let Heading = "#pragma unroll, #pragma nounroll"; let Content = [{ Loop unrolling optimization hints can be specified with ``#pragma unroll`` and ``#pragma nounroll``. The pragma is placed immediately before a for, while, do-while, or c++11 range-based for loop. Specifying ``#pragma unroll`` without a parameter directs the loop unroller to attempt to fully unroll the loop if the trip count is known at compile time and attempt to partially unroll the loop if the trip count is not known at compile time: .. code-block:: c++ #pragma unroll for (...) { ... } Specifying the optional parameter, ``#pragma unroll _value_``, directs the unroller to unroll the loop ``_value_`` times. The parameter may optionally be enclosed in parentheses: .. code-block:: c++ #pragma unroll 16 for (...) { ... } #pragma unroll(16) for (...) { ... } Specifying ``#pragma nounroll`` indicates that the loop should not be unrolled: .. code-block:: c++ #pragma nounroll for (...) { ... } ``#pragma unroll`` and ``#pragma unroll _value_`` have identical semantics to ``#pragma clang loop unroll(full)`` and ``#pragma clang loop unroll_count(_value_)`` respectively. ``#pragma nounroll`` is equivalent to ``#pragma clang loop unroll(disable)``. See `language extensions `_ for further details including limitations of the unroll hints. }]; } def OpenCLUnrollHintDocs : Documentation { let Category = DocCatStmt; let Heading = "__attribute__((opencl_unroll_hint))"; let Content = [{ The opencl_unroll_hint attribute qualifier can be used to specify that a loop (for, while and do loops) can be unrolled. This attribute qualifier can be used to specify full unrolling or partial unrolling by a specified amount. This is a compiler hint and the compiler may ignore this directive. See `OpenCL v2.0 `_ s6.11.5 for details. }]; } def OpenCLIntelReqdSubGroupSizeDocs : Documentation { let Category = DocCatStmt; let Heading = "__attribute__((intel_reqd_sub_group_size))"; let Content = [{ The optional attribute intel_reqd_sub_group_size can be used to indicate that the kernel must be compiled and executed with the specified subgroup size. When this attribute is present, get_max_sub_group_size() is guaranteed to return the specified integer value. This is important for the correctness of many subgroup algorithms, and in some cases may be used by the compiler to generate more optimal code. See `cl_intel_required_subgroup_size ` for details. }]; } def OpenCLAccessDocs : Documentation { let Category = DocCatStmt; let Heading = "__read_only, __write_only, __read_write (read_only, write_only, read_write)"; let Content = [{ The access qualifiers must be used with image object arguments or pipe arguments to declare if they are being read or written by a kernel or function. The read_only/__read_only, write_only/__write_only and read_write/__read_write names are reserved for use as access qualifiers and shall not be used otherwise. .. code-block:: c kernel void foo (read_only image2d_t imageA, write_only image2d_t imageB) { ... } In the above example imageA is a read-only 2D image object, and imageB is a write-only 2D image object. The read_write (or __read_write) qualifier can not be used with pipe. More details can be found in the OpenCL C language Spec v2.0, Section 6.6. }]; } def DocOpenCLAddressSpaces : DocumentationCategory<"OpenCL Address Spaces"> { let Content = [{ The address space qualifier may be used to specify the region of memory that is used to allocate the object. OpenCL supports the following address spaces: __generic(generic), __global(global), __local(local), __private(private), __constant(constant). .. code-block:: c __constant int c = ...; __generic int* foo(global int* g) { __local int* l; private int p; ... return l; } More details can be found in the OpenCL C language Spec v2.0, Section 6.5. }]; } def OpenCLAddressSpaceGenericDocs : Documentation { let Category = DocOpenCLAddressSpaces; let Content = [{ The generic address space attribute is only available with OpenCL v2.0 and later. It can be used with pointer types. Variables in global and local scope and function parameters in non-kernel functions can have the generic address space type attribute. It is intended to be a placeholder for any other address space except for '__constant' in OpenCL code which can be used with multiple address spaces. }]; } def OpenCLAddressSpaceConstantDocs : Documentation { let Category = DocOpenCLAddressSpaces; let Content = [{ The constant address space attribute signals that an object is located in a constant (non-modifiable) memory region. It is available to all work items. Any type can be annotated with the constant address space attribute. Objects with the constant address space qualifier can be declared in any scope and must have an initializer. }]; } def OpenCLAddressSpaceGlobalDocs : Documentation { let Category = DocOpenCLAddressSpaces; let Content = [{ The global address space attribute specifies that an object is allocated in global memory, which is accessible by all work items. The content stored in this memory area persists between kernel executions. Pointer types to the global address space are allowed as function parameters or local variables. Starting with OpenCL v2.0, the global address space can be used with global (program scope) variables and static local variable as well. }]; } def OpenCLAddressSpaceLocalDocs : Documentation { let Category = DocOpenCLAddressSpaces; let Content = [{ The local address space specifies that an object is allocated in the local (work group) memory area, which is accessible to all work items in the same work group. The content stored in this memory region is not accessible after the kernel execution ends. In a kernel function scope, any variable can be in the local address space. In other scopes, only pointer types to the local address space are allowed. Local address space variables cannot have an initializer. }]; } def OpenCLAddressSpacePrivateDocs : Documentation { let Category = DocOpenCLAddressSpaces; let Content = [{ The private address space specifies that an object is allocated in the private (work item) memory. Other work items cannot access the same memory area and its content is destroyed after work item execution ends. Local variables can be declared in the private address space. Function arguments are always in the private address space. Kernel function arguments of a pointer or an array type cannot point to the private address space. }]; } def OpenCLNoSVMDocs : Documentation { let Category = DocCatVariable; let Content = [{ OpenCL 2.0 supports the optional ``__attribute__((nosvm))`` qualifier for pointer variable. It informs the compiler that the pointer does not refer to a shared virtual memory region. See OpenCL v2.0 s6.7.2 for details. Since it is not widely used and has been removed from OpenCL 2.1, it is ignored by Clang. }]; } def NullabilityDocs : DocumentationCategory<"Nullability Attributes"> { let Content = [{ Whether a particular pointer may be "null" is an important concern when working with pointers in the C family of languages. The various nullability attributes indicate whether a particular pointer can be null or not, which makes APIs more expressive and can help static analysis tools identify bugs involving null pointers. Clang supports several kinds of nullability attributes: the ``nonnull`` and ``returns_nonnull`` attributes indicate which function or method parameters and result types can never be null, while nullability type qualifiers indicate which pointer types can be null (``_Nullable``) or cannot be null (``_Nonnull``). The nullability (type) qualifiers express whether a value of a given pointer type can be null (the ``_Nullable`` qualifier), doesn't have a defined meaning for null (the ``_Nonnull`` qualifier), or for which the purpose of null is unclear (the ``_Null_unspecified`` qualifier). Because nullability qualifiers are expressed within the type system, they are more general than the ``nonnull`` and ``returns_nonnull`` attributes, allowing one to express (for example) a nullable pointer to an array of nonnull pointers. Nullability qualifiers are written to the right of the pointer to which they apply. For example: .. code-block:: c // No meaningful result when 'ptr' is null (here, it happens to be undefined behavior). int fetch(int * _Nonnull ptr) { return *ptr; } // 'ptr' may be null. int fetch_or_zero(int * _Nullable ptr) { return ptr ? *ptr : 0; } // A nullable pointer to non-null pointers to const characters. const char *join_strings(const char * _Nonnull * _Nullable strings, unsigned n); In Objective-C, there is an alternate spelling for the nullability qualifiers that can be used in Objective-C methods and properties using context-sensitive, non-underscored keywords. For example: .. code-block:: objective-c @interface NSView : NSResponder - (nullable NSView *)ancestorSharedWithView:(nonnull NSView *)aView; @property (assign, nullable) NSView *superview; @property (readonly, nonnull) NSArray *subviews; @end }]; } def TypeNonNullDocs : Documentation { let Category = NullabilityDocs; let Content = [{ The ``_Nonnull`` nullability qualifier indicates that null is not a meaningful value for a value of the ``_Nonnull`` pointer type. For example, given a declaration such as: .. code-block:: c int fetch(int * _Nonnull ptr); a caller of ``fetch`` should not provide a null value, and the compiler will produce a warning if it sees a literal null value passed to ``fetch``. Note that, unlike the declaration attribute ``nonnull``, the presence of ``_Nonnull`` does not imply that passing null is undefined behavior: ``fetch`` is free to consider null undefined behavior or (perhaps for backward-compatibility reasons) defensively handle null. }]; } def TypeNullableDocs : Documentation { let Category = NullabilityDocs; let Content = [{ The ``_Nullable`` nullability qualifier indicates that a value of the ``_Nullable`` pointer type can be null. For example, given: .. code-block:: c int fetch_or_zero(int * _Nullable ptr); a caller of ``fetch_or_zero`` can provide null. }]; } def TypeNullUnspecifiedDocs : Documentation { let Category = NullabilityDocs; let Content = [{ The ``_Null_unspecified`` nullability qualifier indicates that neither the ``_Nonnull`` nor ``_Nullable`` qualifiers make sense for a particular pointer type. It is used primarily to indicate that the role of null with specific pointers in a nullability-annotated header is unclear, e.g., due to overly-complex implementations or historical factors with a long-lived API. }]; } def NonNullDocs : Documentation { let Category = NullabilityDocs; let Content = [{ The ``nonnull`` attribute indicates that some function parameters must not be null, and can be used in several different ways. It's original usage (`from GCC `_) is as a function (or Objective-C method) attribute that specifies which parameters of the function are nonnull in a comma-separated list. For example: .. code-block:: c extern void * my_memcpy (void *dest, const void *src, size_t len) __attribute__((nonnull (1, 2))); Here, the ``nonnull`` attribute indicates that parameters 1 and 2 cannot have a null value. Omitting the parenthesized list of parameter indices means that all parameters of pointer type cannot be null: .. code-block:: c extern void * my_memcpy (void *dest, const void *src, size_t len) __attribute__((nonnull)); Clang also allows the ``nonnull`` attribute to be placed directly on a function (or Objective-C method) parameter, eliminating the need to specify the parameter index ahead of type. For example: .. code-block:: c extern void * my_memcpy (void *dest __attribute__((nonnull)), const void *src __attribute__((nonnull)), size_t len); Note that the ``nonnull`` attribute indicates that passing null to a non-null parameter is undefined behavior, which the optimizer may take advantage of to, e.g., remove null checks. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable. }]; } def ReturnsNonNullDocs : Documentation { let Category = NullabilityDocs; let Content = [{ The ``returns_nonnull`` attribute indicates that a particular function (or Objective-C method) always returns a non-null pointer. For example, a particular system ``malloc`` might be defined to terminate a process when memory is not available rather than returning a null pointer: .. code-block:: c extern void * malloc (size_t size) __attribute__((returns_nonnull)); The ``returns_nonnull`` attribute implies that returning a null pointer is undefined behavior, which the optimizer may take advantage of. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable }]; } def NoAliasDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``noalias`` attribute indicates that the only memory accesses inside function are loads and stores from objects pointed to by its pointer-typed arguments, with arbitrary offsets. }]; } def OMPDeclareSimdDocs : Documentation { let Category = DocCatFunction; let Heading = "#pragma omp declare simd"; let Content = [{ The `declare simd` construct can be applied to a function to enable the creation of one or more versions that can process multiple arguments using SIMD instructions from a single invocation in a SIMD loop. The `declare simd` directive is a declarative directive. There may be multiple `declare simd` directives for a function. The use of a `declare simd` construct on a function enables the creation of SIMD versions of the associated function that can be used to process multiple arguments from a single invocation from a SIMD loop concurrently. The syntax of the `declare simd` construct is as follows: .. code-block:: none #pragma omp declare simd [clause[[,] clause] ...] new-line [#pragma omp declare simd [clause[[,] clause] ...] new-line] [...] function definition or declaration where clause is one of the following: .. code-block:: none simdlen(length) linear(argument-list[:constant-linear-step]) aligned(argument-list[:alignment]) uniform(argument-list) inbranch notinbranch }]; } def OMPDeclareTargetDocs : Documentation { let Category = DocCatFunction; let Heading = "#pragma omp declare target"; let Content = [{ The `declare target` directive specifies that variables and functions are mapped to a device for OpenMP offload mechanism. The syntax of the declare target directive is as follows: .. code-block:: c #pragma omp declare target new-line declarations-definition-seq #pragma omp end declare target new-line }]; } def NoStackProtectorDocs : Documentation { let Category = DocCatFunction; let Content = [{ Clang supports the ``__attribute__((no_stack_protector))`` attribute which disables the stack protector on the specified function. This attribute is useful for selectively disabling the stack protector on some functions when building with ``-fstack-protector`` compiler option. For example, it disables the stack protector for the function ``foo`` but function ``bar`` will still be built with the stack protector with the ``-fstack-protector`` option. .. code-block:: c int __attribute__((no_stack_protector)) foo (int x); // stack protection will be disabled for foo. int bar(int y); // bar can be built with the stack protector. }]; } def NotTailCalledDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``not_tail_called`` attribute prevents tail-call optimization on statically bound calls. It has no effect on indirect calls. Virtual functions, objective-c methods, and functions marked as ``always_inline`` cannot be marked as ``not_tail_called``. For example, it prevents tail-call optimization in the following case: .. code-block:: c int __attribute__((not_tail_called)) foo1(int); int foo2(int a) { return foo1(a); // No tail-call optimization on direct calls. } However, it doesn't prevent tail-call optimization in this case: .. code-block:: c int __attribute__((not_tail_called)) foo1(int); int foo2(int a) { int (*fn)(int) = &foo1; // not_tail_called has no effect on an indirect call even if the call can be // resolved at compile time. return (*fn)(a); } Marking virtual functions as ``not_tail_called`` is an error: .. code-block:: c++ class Base { public: // not_tail_called on a virtual function is an error. [[clang::not_tail_called]] virtual int foo1(); virtual int foo2(); // Non-virtual functions can be marked ``not_tail_called``. [[clang::not_tail_called]] int foo3(); }; class Derived1 : public Base { public: int foo1() override; // not_tail_called on a virtual function is an error. [[clang::not_tail_called]] int foo2() override; }; }]; } def NoThrowDocs : Documentation { let Category = DocCatFunction; let Content = [{ Clang supports the GNU style ``__attribute__((nothrow))`` and Microsoft style ``__declspec(nothrow)`` attribute as an equivalent of `noexcept` on function declarations. This attribute informs the compiler that the annotated function does not throw an exception. This prevents exception-unwinding. This attribute is particularly useful on functions in the C Standard Library that are guaranteed to not throw an exception. }]; } def InternalLinkageDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``internal_linkage`` attribute changes the linkage type of the declaration to internal. This is similar to C-style ``static``, but can be used on classes and class methods. When applied to a class definition, this attribute affects all methods and static data members of that class. This can be used to contain the ABI of a C++ library by excluding unwanted class methods from the export tables. }]; } def DisableTailCallsDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``disable_tail_calls`` attribute instructs the backend to not perform tail call optimization inside the marked function. For example: .. code-block:: c int callee(int); int foo(int a) __attribute__((disable_tail_calls)) { return callee(a); // This call is not tail-call optimized. } Marking virtual functions as ``disable_tail_calls`` is legal. .. code-block:: c++ int callee(int); class Base { public: [[clang::disable_tail_calls]] virtual int foo1() { return callee(); // This call is not tail-call optimized. } }; class Derived1 : public Base { public: int foo1() override { return callee(); // This call is tail-call optimized. } }; }]; } def AnyX86NoCallerSavedRegistersDocs : Documentation { let Category = DocCatFunction; let Content = [{ Use this attribute to indicate that the specified function has no caller-saved registers. That is, all registers are callee-saved except for registers used for passing parameters to the function or returning parameters from the function. The compiler saves and restores any modified registers that were not used for passing or returning arguments to the function. The user can call functions specified with the 'no_caller_saved_registers' attribute from an interrupt handler without saving and restoring all call-clobbered registers. Note that 'no_caller_saved_registers' attribute is not a calling convention. In fact, it only overrides the decision of which registers should be saved by the caller, but not how the parameters are passed from the caller to the callee. For example: .. code-block:: c __attribute__ ((no_caller_saved_registers, fastcall)) void f (int arg1, int arg2) { ... } In this case parameters 'arg1' and 'arg2' will be passed in registers. In this case, on 32-bit x86 targets, the function 'f' will use ECX and EDX as register parameters. However, it will not assume any scratch registers and should save and restore any modified registers except for ECX and EDX. }]; } def X86ForceAlignArgPointerDocs : Documentation { let Category = DocCatFunction; let Content = [{ Use this attribute to force stack alignment. Legacy x86 code uses 4-byte stack alignment. Newer aligned SSE instructions (like 'movaps') that work with the stack require operands to be 16-byte aligned. This attribute realigns the stack in the function prologue to make sure the stack can be used with SSE instructions. Note that the x86_64 ABI forces 16-byte stack alignment at the call site. Because of this, 'force_align_arg_pointer' is not needed on x86_64, except in rare cases where the caller does not align the stack properly (e.g. flow jumps from i386 arch code). .. code-block:: c __attribute__ ((force_align_arg_pointer)) void f () { ... } }]; } def AnyX86NoCfCheckDocs : Documentation{ let Category = DocCatFunction; let Content = [{ Jump Oriented Programming attacks rely on tampering with addresses used by indirect call / jmp, e.g. redirect control-flow to non-programmer intended bytes in the binary. X86 Supports Indirect Branch Tracking (IBT) as part of Control-Flow Enforcement Technology (CET). IBT instruments ENDBR instructions used to specify valid targets of indirect call / jmp. The ``nocf_check`` attribute has two roles: 1. Appertains to a function - do not add ENDBR instruction at the beginning of the function. 2. Appertains to a function pointer - do not track the target function of this pointer (by adding nocf_check prefix to the indirect-call instruction). }]; } def SwiftCallDocs : Documentation { let Category = DocCatVariable; let Content = [{ The ``swiftcall`` attribute indicates that a function should be called using the Swift calling convention for a function or function pointer. The lowering for the Swift calling convention, as described by the Swift ABI documentation, occurs in multiple phases. The first, "high-level" phase breaks down the formal parameters and results into innately direct and indirect components, adds implicit paraameters for the generic signature, and assigns the context and error ABI treatments to parameters where applicable. The second phase breaks down the direct parameters and results from the first phase and assigns them to registers or the stack. The ``swiftcall`` convention only handles this second phase of lowering; the C function type must accurately reflect the results of the first phase, as follows: - Results classified as indirect by high-level lowering should be represented as parameters with the ``swift_indirect_result`` attribute. - Results classified as direct by high-level lowering should be represented as follows: - First, remove any empty direct results. - If there are no direct results, the C result type should be ``void``. - If there is one direct result, the C result type should be a type with the exact layout of that result type. - If there are a multiple direct results, the C result type should be a struct type with the exact layout of a tuple of those results. - Parameters classified as indirect by high-level lowering should be represented as parameters of pointer type. - Parameters classified as direct by high-level lowering should be omitted if they are empty types; otherwise, they should be represented as a parameter type with a layout exactly matching the layout of the Swift parameter type. - The context parameter, if present, should be represented as a trailing parameter with the ``swift_context`` attribute. - The error result parameter, if present, should be represented as a trailing parameter (always following a context parameter) with the ``swift_error_result`` attribute. ``swiftcall`` does not support variadic arguments or unprototyped functions. The parameter ABI treatment attributes are aspects of the function type. A function type which which applies an ABI treatment attribute to a parameter is a different type from an otherwise-identical function type that does not. A single parameter may not have multiple ABI treatment attributes. Support for this feature is target-dependent, although it should be supported on every target that Swift supports. Query for this support with ``__has_attribute(swiftcall)``. This implies support for the ``swift_context``, ``swift_error_result``, and ``swift_indirect_result`` attributes. }]; } def SwiftContextDocs : Documentation { let Category = DocCatVariable; let Content = [{ The ``swift_context`` attribute marks a parameter of a ``swiftcall`` function as having the special context-parameter ABI treatment. This treatment generally passes the context value in a special register which is normally callee-preserved. A ``swift_context`` parameter must either be the last parameter or must be followed by a ``swift_error_result`` parameter (which itself must always be the last parameter). A context parameter must have pointer or reference type. }]; } def SwiftErrorResultDocs : Documentation { let Category = DocCatVariable; let Content = [{ The ``swift_error_result`` attribute marks a parameter of a ``swiftcall`` function as having the special error-result ABI treatment. This treatment generally passes the underlying error value in and out of the function through a special register which is normally callee-preserved. This is modeled in C by pretending that the register is addressable memory: - The caller appears to pass the address of a variable of pointer type. The current value of this variable is copied into the register before the call; if the call returns normally, the value is copied back into the variable. - The callee appears to receive the address of a variable. This address is actually a hidden location in its own stack, initialized with the value of the register upon entry. When the function returns normally, the value in that hidden location is written back to the register. A ``swift_error_result`` parameter must be the last parameter, and it must be preceded by a ``swift_context`` parameter. A ``swift_error_result`` parameter must have type ``T**`` or ``T*&`` for some type T. Note that no qualifiers are permitted on the intermediate level. It is undefined behavior if the caller does not pass a pointer or reference to a valid object. The standard convention is that the error value itself (that is, the value stored in the apparent argument) will be null upon function entry, but this is not enforced by the ABI. }]; } def SwiftIndirectResultDocs : Documentation { let Category = DocCatVariable; let Content = [{ The ``swift_indirect_result`` attribute marks a parameter of a ``swiftcall`` function as having the special indirect-result ABI treatment. This treatment gives the parameter the target's normal indirect-result ABI treatment, which may involve passing it differently from an ordinary parameter. However, only the first indirect result will receive this treatment. Furthermore, low-level lowering may decide that a direct result must be returned indirectly; if so, this will take priority over the ``swift_indirect_result`` parameters. A ``swift_indirect_result`` parameter must either be the first parameter or follow another ``swift_indirect_result`` parameter. A ``swift_indirect_result`` parameter must have type ``T*`` or ``T&`` for some object type ``T``. If ``T`` is a complete type at the point of definition of a function, it is undefined behavior if the argument value does not point to storage of adequate size and alignment for a value of type ``T``. Making indirect results explicit in the signature allows C functions to directly construct objects into them without relying on language optimizations like C++'s named return value optimization (NRVO). }]; } def SuppressDocs : Documentation { let Category = DocCatStmt; let Content = [{ The ``[[gsl::suppress]]`` attribute suppresses specific clang-tidy diagnostics for rules of the `C++ Core Guidelines`_ in a portable way. The attribute can be attached to declarations, statements, and at namespace scope. .. code-block:: c++ [[gsl::suppress("Rh-public")]] void f_() { int *p; [[gsl::suppress("type")]] { p = reinterpret_cast(7); } } namespace N { [[clang::suppress("type", "bounds")]]; ... } .. _`C++ Core Guidelines`: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#inforce-enforcement }]; } def AbiTagsDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``abi_tag`` attribute can be applied to a function, variable, class or inline namespace declaration to modify the mangled name of the entity. It gives the ability to distinguish between different versions of the same entity but with different ABI versions supported. For example, a newer version of a class could have a different set of data members and thus have a different size. Using the ``abi_tag`` attribute, it is possible to have different mangled names for a global variable of the class type. Therefore, the old code could keep using the old manged name and the new code will use the new mangled name with tags. }]; } def PreserveMostDocs : Documentation { let Category = DocCatCallingConvs; let Content = [{ On X86-64 and AArch64 targets, this attribute changes the calling convention of a function. The ``preserve_most`` calling convention attempts to make the code in the caller as unintrusive as possible. This convention behaves identically to the ``C`` calling convention on how arguments and return values are passed, but it uses a different set of caller/callee-saved registers. This alleviates the burden of saving and recovering a large register set before and after the call in the caller. If the arguments are passed in callee-saved registers, then they will be preserved by the callee across the call. This doesn't apply for values returned in callee-saved registers. - On X86-64 the callee preserves all general purpose registers, except for R11. R11 can be used as a scratch register. Floating-point registers (XMMs/YMMs) are not preserved and need to be saved by the caller. The idea behind this convention is to support calls to runtime functions that have a hot path and a cold path. The hot path is usually a small piece of code that doesn't use many registers. The cold path might need to call out to another function and therefore only needs to preserve the caller-saved registers, which haven't already been saved by the caller. The `preserve_most` calling convention is very similar to the ``cold`` calling convention in terms of caller/callee-saved registers, but they are used for different types of function calls. ``coldcc`` is for function calls that are rarely executed, whereas `preserve_most` function calls are intended to be on the hot path and definitely executed a lot. Furthermore ``preserve_most`` doesn't prevent the inliner from inlining the function call. This calling convention will be used by a future version of the Objective-C runtime and should therefore still be considered experimental at this time. Although this convention was created to optimize certain runtime calls to the Objective-C runtime, it is not limited to this runtime and might be used by other runtimes in the future too. The current implementation only supports X86-64 and AArch64, but the intention is to support more architectures in the future. }]; } def PreserveAllDocs : Documentation { let Category = DocCatCallingConvs; let Content = [{ On X86-64 and AArch64 targets, this attribute changes the calling convention of a function. The ``preserve_all`` calling convention attempts to make the code in the caller even less intrusive than the ``preserve_most`` calling convention. This calling convention also behaves identical to the ``C`` calling convention on how arguments and return values are passed, but it uses a different set of caller/callee-saved registers. This removes the burden of saving and recovering a large register set before and after the call in the caller. If the arguments are passed in callee-saved registers, then they will be preserved by the callee across the call. This doesn't apply for values returned in callee-saved registers. - On X86-64 the callee preserves all general purpose registers, except for R11. R11 can be used as a scratch register. Furthermore it also preserves all floating-point registers (XMMs/YMMs). The idea behind this convention is to support calls to runtime functions that don't need to call out to any other functions. This calling convention, like the ``preserve_most`` calling convention, will be used by a future version of the Objective-C runtime and should be considered experimental at this time. }]; } def DeprecatedDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``deprecated`` attribute can be applied to a function, a variable, or a type. This is useful when identifying functions, variables, or types that are expected to be removed in a future version of a program. Consider the function declaration for a hypothetical function ``f``: .. code-block:: c++ void f(void) __attribute__((deprecated("message", "replacement"))); When spelled as `__attribute__((deprecated))`, the deprecated attribute can have two optional string arguments. The first one is the message to display when emitting the warning; the second one enables the compiler to provide a Fix-It to replace the deprecated name with a new name. Otherwise, when spelled as `[[gnu::deprecated]] or [[deprecated]]`, the attribute can have one optional string argument which is the message to display when emitting the warning. }]; } def IFuncDocs : Documentation { let Category = DocCatFunction; let Content = [{ ``__attribute__((ifunc("resolver")))`` is used to mark that the address of a declaration should be resolved at runtime by calling a resolver function. -The symbol name of the resolver function is given in quotes. A function with this name (after mangling) must be defined in the current translation unit; it may be ``static``. The resolver function should take no arguments and return a pointer. +The symbol name of the resolver function is given in quotes. A function with this name (after mangling) must be defined in the current translation unit; it may be ``static``. The resolver function should return a pointer. The ``ifunc`` attribute may only be used on a function declaration. A function declaration with an ``ifunc`` attribute is considered to be a definition of the declared entity. The entity must not have weak linkage; for example, in C++, it cannot be applied to a declaration if a definition at that location would be considered inline. Not all targets support this attribute. ELF targets support this attribute when using binutils v2.20.1 or higher and glibc v2.11.1 or higher. Non-ELF targets currently do not support this attribute. }]; } def LTOVisibilityDocs : Documentation { let Category = DocCatType; let Content = [{ See :doc:`LTOVisibility`. }]; } def RenderScriptKernelAttributeDocs : Documentation { let Category = DocCatFunction; let Content = [{ ``__attribute__((kernel))`` is used to mark a ``kernel`` function in RenderScript. In RenderScript, ``kernel`` functions are used to express data-parallel computations. The RenderScript runtime efficiently parallelizes ``kernel`` functions to run on computational resources such as multi-core CPUs and GPUs. See the RenderScript_ documentation for more information. .. _RenderScript: https://developer.android.com/guide/topics/renderscript/compute.html }]; } def XRayDocs : Documentation { let Category = DocCatFunction; let Heading = "xray_always_instrument (clang::xray_always_instrument), xray_never_instrument (clang::xray_never_instrument), xray_log_args (clang::xray_log_args)"; let Content = [{ ``__attribute__((xray_always_instrument))`` or ``[[clang::xray_always_instrument]]`` is used to mark member functions (in C++), methods (in Objective C), and free functions (in C, C++, and Objective C) to be instrumented with XRay. This will cause the function to always have space at the beginning and exit points to allow for runtime patching. Conversely, ``__attribute__((xray_never_instrument))`` or ``[[clang::xray_never_instrument]]`` will inhibit the insertion of these instrumentation points. If a function has neither of these attributes, they become subject to the XRay heuristics used to determine whether a function should be instrumented or otherwise. ``__attribute__((xray_log_args(N)))`` or ``[[clang::xray_log_args(N)]]`` is used to preserve N function arguments for the logging function. Currently, only N==1 is supported. }]; } def TransparentUnionDocs : Documentation { let Category = DocCatType; let Content = [{ This attribute can be applied to a union to change the behaviour of calls to functions that have an argument with a transparent union type. The compiler behaviour is changed in the following manner: - A value whose type is any member of the transparent union can be passed as an argument without the need to cast that value. - The argument is passed to the function using the calling convention of the first member of the transparent union. Consequently, all the members of the transparent union should have the same calling convention as its first member. Transparent unions are not supported in C++. }]; } def ObjCSubclassingRestrictedDocs : Documentation { let Category = DocCatType; let Content = [{ This attribute can be added to an Objective-C ``@interface`` declaration to ensure that this class cannot be subclassed. }]; } def SelectAnyDocs : Documentation { let Category = DocCatType; let Content = [{ This attribute appertains to a global symbol, causing it to have a weak definition ( `linkonce `_ ), allowing the linker to select any definition. For more information see `gcc documentation `_ or `msvc documentation `_. }]; } def ArtificialDocs : Documentation { let Category = DocCatFunction; let Content = [{ The ``artificial`` attribute can be applied to an inline function. If such a function is inlined, the attribute indicates that debuggers should associate the resulting instructions with the call site, rather than with the corresponding line within the inlined callee. }]; } Index: vendor/clang/dist-release_70/include/clang/Basic/DiagnosticFrontendKinds.td =================================================================== --- vendor/clang/dist-release_70/include/clang/Basic/DiagnosticFrontendKinds.td (revision 341366) +++ vendor/clang/dist-release_70/include/clang/Basic/DiagnosticFrontendKinds.td (revision 341367) @@ -1,244 +1,244 @@ //==--- DiagnosticFrontendKinds.td - frontend diagnostics -----------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// class BackendInfo : CatBackend, ShowInSystemHeader; let Component = "Frontend" in { def err_fe_error_opening : Error<"error opening '%0': %1">; def err_fe_error_reading : Error<"error reading '%0'">; def err_fe_error_reading_stdin : Error<"error reading stdin: %0">; def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal; def err_fe_inline_asm : Error<"%0">, CatInlineAsm; def warn_fe_inline_asm : Warning<"%0">, CatInlineAsm, InGroup; def note_fe_inline_asm : Note<"%0">, CatInlineAsm; def note_fe_inline_asm_here : Note<"instantiated into assembly here">; def err_fe_cannot_link_module : Error<"cannot link module '%0': %1">, DefaultFatal; def warn_fe_frame_larger_than : Warning<"stack frame size of %0 bytes in %q1">, BackendInfo, InGroup; def warn_fe_backend_frame_larger_than: Warning<"%0">, BackendInfo, InGroup; def err_fe_backend_frame_larger_than: Error<"%0">, BackendInfo; def note_fe_backend_frame_larger_than: Note<"%0">, BackendInfo; def warn_fe_backend_plugin: Warning<"%0">, BackendInfo, InGroup; def err_fe_backend_plugin: Error<"%0">, BackendInfo; def remark_fe_backend_plugin: Remark<"%0">, BackendInfo, InGroup; def note_fe_backend_plugin: Note<"%0">, BackendInfo; def warn_fe_override_module : Warning< "overriding the module target triple with %0">, InGroup>; def remark_fe_backend_optimization_remark : Remark<"%0">, BackendInfo, InGroup; def remark_fe_backend_optimization_remark_missed : Remark<"%0">, BackendInfo, InGroup; def remark_fe_backend_optimization_remark_analysis : Remark<"%0">, BackendInfo, InGroup; def remark_fe_backend_optimization_remark_analysis_fpcommute : Remark<"%0; " "allow reordering by specifying '#pragma clang loop vectorize(enable)' " "before the loop or by providing the compiler option '-ffast-math'.">, BackendInfo, InGroup; def remark_fe_backend_optimization_remark_analysis_aliasing : Remark<"%0; " "allow reordering by specifying '#pragma clang loop vectorize(enable)' " "before the loop. If the arrays will always be independent specify " "'#pragma clang loop vectorize(assume_safety)' before the loop or provide " "the '__restrict__' qualifier with the independent array arguments. " "Erroneous results will occur if these options are incorrectly applied!">, BackendInfo, InGroup; def warn_fe_backend_optimization_failure : Warning<"%0">, BackendInfo, InGroup, DefaultWarn; def note_fe_backend_invalid_loc : Note<"could " "not determine the original source location for %0:%1:%2">, BackendInfo; def err_fe_backend_unsupported : Error<"%0">, BackendInfo; def remark_sanitize_address_insert_extra_padding_accepted : Remark< "-fsanitize-address-field-padding applied to %0">, ShowInSystemHeader, InGroup; def remark_sanitize_address_insert_extra_padding_rejected : Remark< "-fsanitize-address-field-padding ignored for %0 because it " "%select{is not C++|is packed|is a union|is trivially copyable|" "has trivial destructor|is standard layout|is in a blacklisted file|" "is blacklisted}1">, ShowInSystemHeader, InGroup; def err_fe_invalid_code_complete_file : Error< "cannot locate code-completion file %0">, DefaultFatal; def err_fe_stdout_binary : Error<"unable to change standard output to binary">, DefaultFatal; def err_fe_dependency_file_requires_MT : Error< "-dependency-file requires at least one -MT or -MQ option">; def err_fe_invalid_plugin_name : Error< "unable to find plugin '%0'">; def err_fe_expected_compiler_job : Error< "unable to handle compilation, expected exactly one compiler job in '%0'">; def err_fe_expected_clang_command : Error< "expected a clang compiler command">; def err_fe_remap_missing_to_file : Error< "could not remap file '%0' to the contents of file '%1'">, DefaultFatal; def err_fe_remap_missing_from_file : Error< "could not remap from missing file '%0'">, DefaultFatal; def err_fe_unable_to_load_pch : Error< "unable to load PCH file">; def err_fe_unable_to_load_plugin : Error< "unable to load plugin '%0': '%1'">; def err_fe_unable_to_create_target : Error< "unable to create target: '%0'">; def err_fe_unable_to_interface_with_target : Error< "unable to interface with target machine">; def err_fe_unable_to_open_output : Error< "unable to open output file '%0': '%1'">; def err_fe_pth_file_has_no_source_header : Error< "PTH file '%0' does not designate an original source header file for -include-pth">; def warn_fe_macro_contains_embedded_newline : Warning< "macro '%0' contains embedded newline; text after the newline is ignored">; def warn_fe_cc_print_header_failure : Warning< "unable to open CC_PRINT_HEADERS file: %0 (using stderr)">; def warn_fe_cc_log_diagnostics_failure : Warning< "unable to open CC_LOG_DIAGNOSTICS file: %0 (using stderr)">; def warn_fe_unable_to_open_stats_file : Warning< "unable to open statistics output file '%0': '%1'">, InGroup>; def err_fe_no_pch_in_dir : Error< "no suitable precompiled header file found in directory '%0'">; def err_fe_action_not_available : Error< "action %0 not compiled in">; def err_fe_invalid_alignment : Error< "invalid value '%1' in '%0'; alignment must be a power of 2">; def err_fe_invalid_wchar_type : Error<"invalid wchar_t type '%0'; must be one of 'char', 'short', 'int'">; def err_fe_invalid_exception_model : Error<"invalid exception model '%0' for target '%1'">; def warn_fe_serialized_diag_merge_failure : Warning< "unable to merge a subprocess's serialized diagnostics">, InGroup; def warn_fe_serialized_diag_failure : Warning< "unable to open file %0 for serializing diagnostics (%1)">, InGroup; def err_verify_missing_line : Error< "missing or invalid line number following '@' in expected %0">; def err_verify_missing_file : Error< "file '%0' could not be located in expected %1">; def err_verify_invalid_range : Error< "invalid range following '-' in expected %0">; def err_verify_missing_start : Error< "cannot find start ('{{') of expected %0">; def err_verify_missing_end : Error< "cannot find end ('}}') of expected %0">; def err_verify_invalid_content : Error< "invalid expected %0: %1">; def err_verify_missing_regex : Error< "cannot find start of regex ('{{') in %0">; def err_verify_inconsistent_diags : Error< "'%0' diagnostics %select{expected|seen}1 but not %select{seen|expected}1: " "%2">; def err_verify_invalid_no_diags : Error< "%select{expected|'expected-no-diagnostics'}0 directive cannot follow " "%select{'expected-no-diagnostics' directive|other expected directives}0">; def err_verify_no_directives : Error< "no expected directives found: consider use of 'expected-no-diagnostics'">; def note_fixit_applied : Note<"FIX-IT applied suggested code changes">; def note_fixit_in_macro : Note< "FIX-IT unable to apply suggested code changes in a macro">; def note_fixit_failed : Note< "FIX-IT unable to apply suggested code changes">; def note_fixit_unfixed_error : Note<"FIX-IT detected an error it cannot fix">; def warn_fixit_no_changes : Note< "FIX-IT detected errors it could not fix; no output will be generated">; // PCH reader def err_relocatable_without_isysroot : Error< "must specify system root with -isysroot when building a relocatable " "PCH file">; def warn_unknown_diag_option : Warning< "unknown %select{warning|remark}0 option '%1'%select{|; did you mean '%3'?}2">, InGroup; def warn_unknown_warning_specifier : Warning< "unknown %0 warning specifier: '%1'">, InGroup; def err_unknown_analyzer_checker : Error< "no analyzer checkers are associated with '%0'">; def note_suggest_disabling_all_checkers : Note< "use -analyzer-disable-all-checks to disable all static analyzer checkers">; def warn_incompatible_analyzer_plugin_api : Warning< "checker plugin '%0' is not compatible with this version of the analyzer">, InGroup >; def note_incompatible_analyzer_plugin_api : Note< "current API version is '%0', but plugin was compiled with version '%1'">; def err_module_build_requires_fmodules : Error< "module compilation requires '-fmodules'">; def err_module_interface_requires_modules_ts : Error< "module interface compilation requires '-fmodules-ts'">; def warn_module_config_mismatch : Warning< "module file %0 cannot be loaded due to a configuration mismatch with the current " "compilation">, InGroup>, DefaultError; def err_module_map_not_found : Error<"module map file '%0' not found">, DefaultFatal; def err_missing_module_name : Error< "no module name provided; specify one with -fmodule-name=">, DefaultFatal; def err_missing_module : Error< "no module named '%0' declared in module map file '%1'">, DefaultFatal; def err_no_submodule : Error<"no submodule named %0 in module '%1'">; def err_no_submodule_suggest : Error< "no submodule named %0 in module '%1'; did you mean '%2'?">; def warn_no_priv_submodule_use_toplevel : Warning< "no submodule named %0 in module '%1'; using top level '%2'">, InGroup; def note_private_top_level_defined : Note< "module defined here">; def warn_missing_submodule : Warning<"missing submodule '%0'">, InGroup; def note_module_import_here : Note<"module imported here">; def err_module_cannot_create_includes : Error< "cannot create includes file for module %0: %1">; def warn_module_config_macro_undef : Warning< "%select{definition|#undef}0 of configuration macro '%1' has no effect on " "the import of '%2'; pass '%select{-D%1=...|-U%1}0' on the command line " "to configure the module">, InGroup; def note_module_def_undef_here : Note< "macro was %select{defined|#undef'd}0 here">; def remark_module_build : Remark<"building module '%0' as '%1'">, InGroup; def remark_module_build_done : Remark<"finished building module '%0'">, InGroup; def err_modules_embed_file_not_found : Error<"file '%0' specified by '-fmodules-embed-file=' not found">, DefaultFatal; def err_test_module_file_extension_version : Error< "test module file extension '%0' has different version (%1.%2) than expected " "(%3.%4)">; def err_missing_vfs_overlay_file : Error< "virtual filesystem overlay file '%0' not found">, DefaultFatal; def err_invalid_vfs_overlay : Error< "invalid virtual filesystem overlay file '%0'">, DefaultFatal; def warn_option_invalid_ocl_version : Warning< "OpenCL version %0 does not support the option '%1'">, InGroup; def warn_stdlibcxx_not_found : Warning< - "include path for stdlibc++ headers not found; pass '-std=libc++' on the " + "include path for stdlibc++ headers not found; pass '-stdlib=libc++' on the " "command line to use the libc++ standard library instead">, InGroup>; } Index: vendor/clang/dist-release_70/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- vendor/clang/dist-release_70/include/clang/Basic/DiagnosticSemaKinds.td (revision 341366) +++ vendor/clang/dist-release_70/include/clang/Basic/DiagnosticSemaKinds.td (revision 341367) @@ -1,9443 +1,9441 @@ //==--- DiagnosticSemaKinds.td - libsema diagnostics ----------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // Semantic Analysis //===----------------------------------------------------------------------===// let Component = "Sema" in { let CategoryName = "Semantic Issue" in { def note_previous_decl : Note<"%0 declared here">; def note_entity_declared_at : Note<"%0 declared here">; def note_callee_decl : Note<"%0 declared here">; def note_defined_here : Note<"%0 defined here">; // For loop analysis def warn_variables_not_in_loop_body : Warning< "variable%select{s| %1|s %1 and %2|s %1, %2, and %3|s %1, %2, %3, and %4}0 " "used in loop condition not modified in loop body">, InGroup, DefaultIgnore; def warn_redundant_loop_iteration : Warning< "variable %0 is %select{decremented|incremented}1 both in the loop header " "and in the loop body">, InGroup, DefaultIgnore; def note_loop_iteration_here : Note<"%select{decremented|incremented}0 here">; def warn_duplicate_enum_values : Warning< "element %0 has been implicitly assigned %1 which another element has " "been assigned">, InGroup>, DefaultIgnore; def note_duplicate_element : Note<"element %0 also has value %1">; // Absolute value functions def warn_unsigned_abs : Warning< "taking the absolute value of unsigned type %0 has no effect">, InGroup; def note_remove_abs : Note< "remove the call to '%0' since unsigned values cannot be negative">; def warn_abs_too_small : Warning< "absolute value function %0 given an argument of type %1 but has parameter " "of type %2 which may cause truncation of value">, InGroup; def warn_wrong_absolute_value_type : Warning< "using %select{integer|floating point|complex}1 absolute value function %0 " "when argument is of %select{integer|floating point|complex}2 type">, InGroup; def note_replace_abs_function : Note<"use function '%0' instead">; def warn_pointer_abs : Warning< "taking the absolute value of %select{pointer|function|array}0 type %1 is suspicious">, InGroup; def warn_max_unsigned_zero : Warning< "taking the max of " "%select{a value and unsigned zero|unsigned zero and a value}0 " "is always equal to the other value">, InGroup; def note_remove_max_call : Note< "remove call to max function and unsigned zero argument">; def warn_infinite_recursive_function : Warning< "all paths through this function will call itself">, InGroup, DefaultIgnore; def warn_comma_operator : Warning<"possible misuse of comma operator here">, InGroup>, DefaultIgnore; def note_cast_to_void : Note<"cast expression to void to silence warning">; // Constant expressions def err_expr_not_ice : Error< "expression is not an %select{integer|integral}0 constant expression">; def ext_expr_not_ice : Extension< "expression is not an %select{integer|integral}0 constant expression; " "folding it to a constant is a GNU extension">, InGroup; def err_typecheck_converted_constant_expression : Error< "value of type %0 is not implicitly convertible to %1">; def err_typecheck_converted_constant_expression_disallowed : Error< "conversion from %0 to %1 is not allowed in a converted constant expression">; def err_typecheck_converted_constant_expression_indirect : Error< "conversion from %0 to %1 in converted constant expression would " "bind reference to a temporary">; def err_expr_not_cce : Error< "%select{case value|enumerator value|non-type template argument|" "array size|constexpr if condition}0 " "is not a constant expression">; def ext_cce_narrowing : ExtWarn< "%select{case value|enumerator value|non-type template argument|" "array size|constexpr if condition}0 " "%select{cannot be narrowed from type %2 to %3|" "evaluates to %2, which cannot be narrowed to type %3}1">, InGroup, DefaultError, SFINAEFailure; def err_ice_not_integral : Error< "integral constant expression must have integral or unscoped enumeration " "type, not %0">; def err_ice_incomplete_type : Error< "integral constant expression has incomplete class type %0">; def err_ice_explicit_conversion : Error< "integral constant expression requires explicit conversion from %0 to %1">; def note_ice_conversion_here : Note< "conversion to %select{integral|enumeration}0 type %1 declared here">; def err_ice_ambiguous_conversion : Error< "ambiguous conversion from type %0 to an integral or unscoped " "enumeration type">; def err_ice_too_large : Error< "integer constant expression evaluates to value %0 that cannot be " "represented in a %1-bit %select{signed|unsigned}2 integer type">; def err_expr_not_string_literal : Error<"expression is not a string literal">; // Semantic analysis of constant literals. def ext_predef_outside_function : Warning< "predefined identifier is only valid inside function">, InGroup>; def warn_float_overflow : Warning< "magnitude of floating-point constant too large for type %0; maximum is %1">, InGroup; def warn_float_underflow : Warning< "magnitude of floating-point constant too small for type %0; minimum is %1">, InGroup; def warn_double_const_requires_fp64 : Warning< "double precision constant requires cl_khr_fp64, casting to single precision">; def err_half_const_requires_fp16 : Error< "half precision constant requires cl_khr_fp16">; // C99 variable-length arrays def ext_vla : Extension<"variable length arrays are a C99 feature">, InGroup; def warn_vla_used : Warning<"variable length array used">, InGroup, DefaultIgnore; def err_vla_in_sfinae : Error< "variable length array cannot be formed during template argument deduction">; def err_array_star_in_function_definition : Error< "variable length array must be bound in function definition">; def err_vla_decl_in_file_scope : Error< "variable length array declaration not allowed at file scope">; def err_vla_decl_has_static_storage : Error< "variable length array declaration cannot have 'static' storage duration">; def err_vla_decl_has_extern_linkage : Error< "variable length array declaration cannot have 'extern' linkage">; def ext_vla_folded_to_constant : Extension< "variable length array folded to constant array as an extension">, InGroup; def err_vla_unsupported : Error< "variable length arrays are not supported for the current target">; def note_vla_unsupported : Note< "variable length arrays are not supported for the current target">; // C99 variably modified types def err_variably_modified_template_arg : Error< "variably modified type %0 cannot be used as a template argument">; def err_variably_modified_nontype_template_param : Error< "non-type template parameter of variably modified type %0">; def err_variably_modified_new_type : Error< "'new' cannot allocate object of variably modified type %0">; // C99 Designated Initializers def ext_designated_init : Extension< "designated initializers are a C99 feature">, InGroup; def err_array_designator_negative : Error< "array designator value '%0' is negative">; def err_array_designator_empty_range : Error< "array designator range [%0, %1] is empty">; def err_array_designator_non_array : Error< "array designator cannot initialize non-array type %0">; def err_array_designator_too_large : Error< "array designator index (%0) exceeds array bounds (%1)">; def err_field_designator_non_aggr : Error< "field designator cannot initialize a " "%select{non-struct, non-union|non-class}0 type %1">; def err_field_designator_unknown : Error< "field designator %0 does not refer to any field in type %1">; def err_field_designator_nonfield : Error< "field designator %0 does not refer to a non-static data member">; def note_field_designator_found : Note<"field designator refers here">; def err_designator_for_scalar_init : Error< "designator in initializer for scalar type %0">; def warn_subobject_initializer_overrides : Warning< "subobject initialization overrides initialization of other fields " "within its enclosing subobject">, InGroup; def warn_initializer_overrides : Warning< "initializer overrides prior initialization of this subobject">, InGroup; def note_previous_initializer : Note< "previous initialization %select{|with side effects }0is here" "%select{| (side effects may not occur at run time)}0">; def err_designator_into_flexible_array_member : Error< "designator into flexible array member subobject">; def note_flexible_array_member : Note< "initialized flexible array member %0 is here">; def ext_flexible_array_init : Extension< "flexible array initialization is a GNU extension">, InGroup; // Declarations. def ext_duplicate_declspec : ExtWarn<"duplicate '%0' declaration specifier">, InGroup; def warn_duplicate_declspec : Warning<"duplicate '%0' declaration specifier">, InGroup; def ext_plain_complex : ExtWarn< "plain '_Complex' requires a type specifier; assuming '_Complex double'">; def ext_imaginary_constant : Extension< "imaginary constants are a GNU extension">, InGroup; def ext_integer_complex : Extension< "complex integer types are a GNU extension">, InGroup; def err_invalid_saturation_spec : Error<"'_Sat' specifier is only valid on " "'_Fract' or '_Accum', not '%0'">; def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">; def err_invalid_width_spec : Error< "'%select{|short|long|long long}0 %1' is invalid">; def err_invalid_complex_spec : Error<"'_Complex %0' is invalid">; def err_friend_decl_spec : Error<"'%0' is invalid in friend declarations">; def ext_auto_type_specifier : ExtWarn< "'auto' type specifier is a C++11 extension">, InGroup; def warn_auto_storage_class : Warning< "'auto' storage class specifier is redundant and incompatible with C++11">, InGroup, DefaultIgnore; def warn_deprecated_register : Warning< "'register' storage class specifier is deprecated " "and incompatible with C++17">, InGroup; def ext_register_storage_class : ExtWarn< "ISO C++17 does not allow 'register' storage class specifier">, DefaultError, InGroup; def err_invalid_decl_spec_combination : Error< "cannot combine with previous '%0' declaration specifier">; def err_invalid_vector_decl_spec_combination : Error< "cannot combine with previous '%0' declaration specifier. " "'__vector' must be first">; def err_invalid_pixel_decl_spec_combination : Error< "'__pixel' must be preceded by '__vector'. " "'%0' declaration specifier not allowed here">; def err_invalid_vector_bool_decl_spec : Error< "cannot use '%0' with '__vector bool'">; def err_invalid_vector_long_decl_spec : Error< "cannot use 'long' with '__vector'">; def err_invalid_vector_float_decl_spec : Error< "cannot use 'float' with '__vector'">; def err_invalid_vector_double_decl_spec : Error < "use of 'double' with '__vector' requires VSX support to be enabled " "(available on POWER7 or later)">; def err_invalid_vector_long_long_decl_spec : Error < "use of 'long long' with '__vector bool' requires VSX support (available on " "POWER7 or later) or extended Altivec support (available on POWER8 or later) " "to be enabled">; def err_invalid_vector_long_double_decl_spec : Error< "cannot use 'long double' with '__vector'">; def warn_vector_long_decl_spec_combination : Warning< "Use of 'long' with '__vector' is deprecated">, InGroup; def err_use_of_tag_name_without_tag : Error< "must use '%1' tag to refer to type %0%select{| in this scope}2">; def err_redeclaration_different_type : Error< "redeclaration of %0 with a different type%diff{: $ vs $|}1,2">; def err_bad_variable_name : Error< "%0 cannot be the name of a variable or data member">; def err_bad_parameter_name : Error< "%0 cannot be the name of a parameter">; def err_parameter_name_omitted : Error<"parameter name omitted">; def err_anyx86_interrupt_attribute : Error< "%select{x86|x86-64}0 'interrupt' attribute only applies to functions that " "have %select{a 'void' return type|" "only a pointer parameter optionally followed by an integer parameter|" "a pointer as the first parameter|a %2 type as the second parameter}1">; def err_anyx86_interrupt_called : Error< "interrupt service routine cannot be called directly">; def warn_arm_interrupt_calling_convention : Warning< "call to function without interrupt attribute could clobber interruptee's VFP registers">, InGroup; def warn_mips_interrupt_attribute : Warning< "MIPS 'interrupt' attribute only applies to functions that have " "%select{no parameters|a 'void' return type}0">, InGroup; def warn_riscv_repeated_interrupt_attribute : Warning< "repeated RISC-V 'interrupt' attribute">, InGroup; def note_riscv_repeated_interrupt_attribute : Note< "repeated RISC-V 'interrupt' attribute is here">; def warn_riscv_interrupt_attribute : Warning< "RISC-V 'interrupt' attribute only applies to functions that have " "%select{no parameters|a 'void' return type}0">, InGroup; def warn_unused_parameter : Warning<"unused parameter %0">, InGroup, DefaultIgnore; def warn_unused_variable : Warning<"unused variable %0">, InGroup, DefaultIgnore; def warn_unused_local_typedef : Warning< "unused %select{typedef|type alias}0 %1">, InGroup, DefaultIgnore; def warn_unused_property_backing_ivar : Warning<"ivar %0 which backs the property is not " "referenced in this property's accessor">, InGroup, DefaultIgnore; def warn_unused_const_variable : Warning<"unused variable %0">, InGroup, DefaultIgnore; def warn_unused_exception_param : Warning<"unused exception parameter %0">, InGroup, DefaultIgnore; def warn_decl_in_param_list : Warning< "declaration of %0 will not be visible outside of this function">, InGroup; def warn_redefinition_in_param_list : Warning< "redefinition of %0 will not be visible outside of this function">, InGroup; def warn_empty_parens_are_function_decl : Warning< "empty parentheses interpreted as a function declaration">, InGroup; def warn_parens_disambiguated_as_function_declaration : Warning< "parentheses were disambiguated as a function declaration">, InGroup; def warn_parens_disambiguated_as_variable_declaration : Warning< "parentheses were disambiguated as redundant parentheses around declaration " "of variable named %0">, InGroup; def warn_redundant_parens_around_declarator : Warning< "redundant parentheses surrounding declarator">, InGroup>, DefaultIgnore; def note_additional_parens_for_variable_declaration : Note< "add a pair of parentheses to declare a variable">; def note_raii_guard_add_name : Note< "add a variable name to declare a %0 initialized with %1">; def note_function_style_cast_add_parentheses : Note< "add enclosing parentheses to perform a function-style cast">; def note_remove_parens_for_variable_declaration : Note< "remove parentheses to silence this warning">; def note_empty_parens_function_call : Note< "change this ',' to a ';' to call %0">; def note_empty_parens_default_ctor : Note< "remove parentheses to declare a variable">; def note_empty_parens_zero_initialize : Note< "replace parentheses with an initializer to declare a variable">; def warn_unused_function : Warning<"unused function %0">, InGroup, DefaultIgnore; def warn_unused_template : Warning<"unused %select{function|variable}0 template %1">, InGroup, DefaultIgnore; def warn_unused_member_function : Warning<"unused member function %0">, InGroup, DefaultIgnore; def warn_used_but_marked_unused: Warning<"%0 was marked unused but was used">, InGroup, DefaultIgnore; def warn_unneeded_internal_decl : Warning< "%select{function|variable}0 %1 is not needed and will not be emitted">, InGroup, DefaultIgnore; def warn_unneeded_static_internal_decl : Warning< "'static' function %0 declared in header file " "should be declared 'static inline'">, InGroup, DefaultIgnore; def warn_unneeded_member_function : Warning< "member function %0 is not needed and will not be emitted">, InGroup, DefaultIgnore; def warn_unused_private_field: Warning<"private field %0 is not used">, InGroup, DefaultIgnore; def warn_unused_lambda_capture: Warning<"lambda capture %0 is not " "%select{used|required to be captured for this use}1">, InGroup, DefaultIgnore; def warn_parameter_size: Warning< "%0 is a large (%1 bytes) pass-by-value argument; " "pass it by reference instead ?">, InGroup; def warn_return_value_size: Warning< "return value of %0 is a large (%1 bytes) pass-by-value object; " "pass it by reference instead ?">, InGroup; def warn_return_value_udt: Warning< "%0 has C-linkage specified, but returns user-defined type %1 which is " "incompatible with C">, InGroup; def warn_return_value_udt_incomplete: Warning< "%0 has C-linkage specified, but returns incomplete type %1 which could be " "incompatible with C">, InGroup; def warn_implicit_function_decl : Warning< "implicit declaration of function %0">, InGroup, DefaultIgnore; def ext_implicit_function_decl : ExtWarn< "implicit declaration of function %0 is invalid in %select{C99|OpenCL}1">, InGroup; def note_function_suggestion : Note<"did you mean %0?">; def err_ellipsis_first_param : Error< "ISO C requires a named parameter before '...'">; def err_declarator_need_ident : Error<"declarator requires an identifier">; def err_language_linkage_spec_unknown : Error<"unknown linkage language">; def err_language_linkage_spec_not_ascii : Error< "string literal in language linkage specifier cannot have an " "encoding-prefix">; def ext_use_out_of_scope_declaration : ExtWarn< "use of out-of-scope declaration of %0%select{| whose type is not " "compatible with that of an implicit declaration}1">, InGroup>; def err_inline_non_function : Error< "'inline' can only appear on functions%select{| and non-local variables}0">; def err_noreturn_non_function : Error< "'_Noreturn' can only appear on functions">; def warn_qual_return_type : Warning< "'%0' type qualifier%s1 on return type %plural{1:has|:have}1 no effect">, InGroup, DefaultIgnore; def warn_deprecated_redundant_constexpr_static_def : Warning< "out-of-line definition of constexpr static data member is redundant " "in C++17 and is deprecated">, InGroup, DefaultIgnore; def warn_decl_shadow : Warning<"declaration shadows a %select{" "local variable|" "variable in %2|" "static data member of %2|" "field of %2|" "typedef in %2|" "type alias in %2}1">, InGroup, DefaultIgnore; def warn_decl_shadow_uncaptured_local : Warning, InGroup, DefaultIgnore; def warn_ctor_parm_shadows_field: Warning<"constructor parameter %0 shadows the field %1 of %2">, InGroup, DefaultIgnore; def warn_modifying_shadowing_decl : Warning<"modifying constructor parameter %0 that shadows a " "field of %1">, InGroup, DefaultIgnore; // C++ decomposition declarations def err_decomp_decl_context : Error< "decomposition declaration not permitted in this context">; def warn_cxx14_compat_decomp_decl : Warning< "decomposition declarations are incompatible with " "C++ standards before C++17">, DefaultIgnore, InGroup; def ext_decomp_decl : ExtWarn< "decomposition declarations are a C++17 extension">, InGroup; def ext_decomp_decl_cond : ExtWarn< "ISO C++17 does not permit structured binding declaration in a condition">, InGroup>; def err_decomp_decl_spec : Error< "decomposition declaration cannot be declared " "%plural{1:'%1'|:with '%1' specifiers}0">; def err_decomp_decl_type : Error< "decomposition declaration cannot be declared with type %0; " "declared type must be 'auto' or reference to 'auto'">; def err_decomp_decl_parens : Error< "decomposition declaration cannot be declared with parentheses">; def err_decomp_decl_template : Error< "decomposition declaration template not supported">; def err_decomp_decl_not_alone : Error< "decomposition declaration must be the only declaration in its group">; def err_decomp_decl_requires_init : Error< "decomposition declaration %0 requires an initializer">; def err_decomp_decl_wrong_number_bindings : Error< "type %0 decomposes into %2 elements, but %select{only |}3%1 " "names were provided">; def err_decomp_decl_unbindable_type : Error< "cannot decompose %select{union|non-class, non-array}1 type %2">; def err_decomp_decl_multiple_bases_with_members : Error< "cannot decompose class type %1: " "%select{its base classes %2 and|both it and its base class}0 %3 " "have non-static data members">; def err_decomp_decl_ambiguous_base : Error< "cannot decompose members of ambiguous base class %1 of %0:%2">; def err_decomp_decl_non_public_base : Error< "cannot decompose members of non-public base class %1 of %0">; def err_decomp_decl_non_public_member : Error< "cannot decompose non-public member %0 of %1">; def err_decomp_decl_anon_union_member : Error< "cannot decompose class type %0 because it has an anonymous " "%select{struct|union}1 member">; def err_decomp_decl_std_tuple_element_not_specialized : Error< "cannot decompose this type; 'std::tuple_element<%0>::type' " "does not name a type">; def err_decomp_decl_std_tuple_size_not_constant : Error< "cannot decompose this type; 'std::tuple_size<%0>::value' " "is not a valid integral constant expression">; def note_in_binding_decl_init : Note< "in implicit initialization of binding declaration %0">; def err_std_type_trait_not_class_template : Error< "unsupported standard library implementation: " "'std::%0' is not a class template">; // C++ using declarations def err_using_requires_qualname : Error< "using declaration requires a qualified name">; def err_using_typename_non_type : Error< "'typename' keyword used on a non-type">; def err_using_dependent_value_is_type : Error< "dependent using declaration resolved to type without 'typename'">; def err_using_decl_nested_name_specifier_is_not_class : Error< "using declaration in class refers into '%0', which is not a class">; def err_using_decl_nested_name_specifier_is_current_class : Error< "using declaration refers to its own class">; def err_using_decl_nested_name_specifier_is_not_base_class : Error< "using declaration refers into '%0', which is not a base class of %1">; def err_using_decl_constructor_not_in_direct_base : Error< "%0 is not a direct base of %1, cannot inherit constructors">; def err_using_decl_can_not_refer_to_class_member : Error< "using declaration cannot refer to class member">; def err_ambiguous_inherited_constructor : Error< "constructor of %0 inherited from multiple base class subobjects">; def note_ambiguous_inherited_constructor_using : Note< "inherited from base class %0 here">; def note_using_decl_class_member_workaround : Note< "use %select{an alias declaration|a typedef declaration|a reference|" "a const variable|a constexpr variable}0 instead">; def err_using_decl_can_not_refer_to_namespace : Error< "using declaration cannot refer to a namespace">; def err_using_decl_can_not_refer_to_scoped_enum : Error< "using declaration cannot refer to a scoped enumerator">; def err_using_decl_constructor : Error< "using declaration cannot refer to a constructor">; def warn_cxx98_compat_using_decl_constructor : Warning< "inheriting constructors are incompatible with C++98">, InGroup, DefaultIgnore; def err_using_decl_destructor : Error< "using declaration cannot refer to a destructor">; def err_using_decl_template_id : Error< "using declaration cannot refer to a template specialization">; def note_using_decl_target : Note<"target of using declaration">; def note_using_decl_conflict : Note<"conflicting declaration">; def err_using_decl_redeclaration : Error<"redeclaration of using declaration">; def err_using_decl_conflict : Error< "target of using declaration conflicts with declaration already in scope">; def err_using_decl_conflict_reverse : Error< "declaration conflicts with target of using declaration already in scope">; def note_using_decl : Note<"%select{|previous }0using declaration">; def err_using_decl_redeclaration_expansion : Error< "using declaration pack expansion at block scope produces multiple values">; def warn_access_decl_deprecated : Warning< "access declarations are deprecated; use using declarations instead">, InGroup; def err_access_decl : Error< "ISO C++11 does not allow access declarations; " "use using declarations instead">; def ext_dynamic_exception_spec : ExtWarn< "ISO C++17 does not allow dynamic exception specifications">, InGroup, DefaultError; def warn_exception_spec_deprecated : Warning< "dynamic exception specifications are deprecated">, InGroup, DefaultIgnore; def note_exception_spec_deprecated : Note<"use '%0' instead">; def warn_deprecated_copy_operation : Warning< "definition of implicit copy %select{constructor|assignment operator}1 " "for %0 is deprecated because it has a user-declared " "%select{copy %select{assignment operator|constructor}1|destructor}2">, InGroup, DefaultIgnore; def warn_cxx17_compat_exception_spec_in_signature : Warning< "mangled name of %0 will change in C++17 due to non-throwing exception " "specification in function signature">, InGroup; def warn_global_constructor : Warning< "declaration requires a global constructor">, InGroup, DefaultIgnore; def warn_global_destructor : Warning< "declaration requires a global destructor">, InGroup, DefaultIgnore; def warn_exit_time_destructor : Warning< "declaration requires an exit-time destructor">, InGroup, DefaultIgnore; def err_invalid_thread : Error< "'%0' is only allowed on variable declarations">; def err_thread_non_global : Error< "'%0' variables must have global storage">; def err_thread_unsupported : Error< "thread-local storage is not supported for the current target">; def warn_maybe_falloff_nonvoid_function : Warning< "control may reach end of non-void function">, InGroup; def warn_falloff_nonvoid_function : Warning< "control reaches end of non-void function">, InGroup; def err_maybe_falloff_nonvoid_block : Error< "control may reach end of non-void block">; def err_falloff_nonvoid_block : Error< "control reaches end of non-void block">; def warn_maybe_falloff_nonvoid_coroutine : Warning< "control may reach end of coroutine; which is undefined behavior because the promise type %0 does not declare 'return_void()'">, InGroup; def warn_falloff_nonvoid_coroutine : Warning< "control reaches end of coroutine; which is undefined behavior because the promise type %0 does not declare 'return_void()'">, InGroup; def warn_suggest_noreturn_function : Warning< "%select{function|method}0 %1 could be declared with attribute 'noreturn'">, InGroup, DefaultIgnore; def warn_suggest_noreturn_block : Warning< "block could be declared with attribute 'noreturn'">, InGroup, DefaultIgnore; // Unreachable code. def warn_unreachable : Warning< "code will never be executed">, InGroup, DefaultIgnore; def warn_unreachable_break : Warning< "'break' will never be executed">, InGroup, DefaultIgnore; def warn_unreachable_return : Warning< "'return' will never be executed">, InGroup, DefaultIgnore; def warn_unreachable_loop_increment : Warning< "loop will run at most once (loop increment never executed)">, InGroup, DefaultIgnore; def note_unreachable_silence : Note< "silence by adding parentheses to mark code as explicitly dead">; /// Built-in functions. def ext_implicit_lib_function_decl : ExtWarn< "implicitly declaring library function '%0' with type %1">, InGroup; def note_include_header_or_declare : Note< "include the header <%0> or explicitly provide a declaration for '%1'">; def note_previous_builtin_declaration : Note<"%0 is a builtin with type %1">; def warn_implicit_decl_requires_sysheader : Warning< "declaration of built-in function '%1' requires inclusion of the header <%0>">, InGroup; def warn_redecl_library_builtin : Warning< "incompatible redeclaration of library function %0">, InGroup>; def err_builtin_definition : Error<"definition of builtin function %0">; def err_builtin_redeclare : Error<"cannot redeclare builtin function %0">; def err_arm_invalid_specialreg : Error<"invalid special register for builtin">; def err_invalid_cpu_supports : Error<"invalid cpu feature string for builtin">; def err_invalid_cpu_is : Error<"invalid cpu name for builtin">; def err_invalid_cpu_specific_dispatch_value : Error< "invalid option '%0' for %select{cpu_specific|cpu_dispatch}1">; def err_builtin_needs_feature : Error<"%0 needs target feature %1">; def err_function_needs_feature : Error<"always_inline function %1 requires target feature '%2', but would " "be inlined into function %0 that is compiled without support for " "'%2'">; def warn_builtin_unknown : Warning<"use of unknown builtin %0">, InGroup, DefaultError; def warn_cstruct_memaccess : Warning< "%select{destination for|source of|first operand of|second operand of}0 this " "%1 call is a pointer to record %2 that is not trivial to " "%select{primitive-default-initialize|primitive-copy}3">, InGroup; def note_nontrivial_field : Note< "field is non-trivial to %select{copy|default-initialize}0">; def warn_dyn_class_memaccess : Warning< "%select{destination for|source of|first operand of|second operand of}0 this " "%1 call is a pointer to %select{|class containing a }2dynamic class %3; " "vtable pointer will be %select{overwritten|copied|moved|compared}4">, InGroup; def note_bad_memaccess_silence : Note< "explicitly cast the pointer to silence this warning">; def warn_sizeof_pointer_expr_memaccess : Warning< "'%0' call operates on objects of type %1 while the size is based on a " "different type %2">, InGroup; def warn_sizeof_pointer_expr_memaccess_note : Note< "did you mean to %select{dereference the argument to 'sizeof' (and multiply " "it by the number of elements)|remove the addressof in the argument to " "'sizeof' (and multiply it by the number of elements)|provide an explicit " "length}0?">; def warn_sizeof_pointer_type_memaccess : Warning< "argument to 'sizeof' in %0 call is the same pointer type %1 as the " "%select{destination|source}2; expected %3 or an explicit length">, InGroup; def warn_strlcpycat_wrong_size : Warning< "size argument in %0 call appears to be size of the source; " "expected the size of the destination">, InGroup>; def note_strlcpycat_wrong_size : Note< "change size argument to be the size of the destination">; def warn_memsize_comparison : Warning< "size argument in %0 call is a comparison">, InGroup>; def note_memsize_comparison_paren : Note< "did you mean to compare the result of %0 instead?">; def note_memsize_comparison_cast_silence : Note< "explicitly cast the argument to size_t to silence this warning">; def warn_suspicious_sizeof_memset : Warning< "%select{'size' argument to memset is '0'|" "setting buffer to a 'sizeof' expression}0" "; did you mean to transpose the last two arguments?">, InGroup; def note_suspicious_sizeof_memset_silence : Note< "%select{parenthesize the third argument|" "cast the second argument to 'int'}0 to silence">; def warn_suspicious_bzero_size : Warning<"'size' argument to bzero is '0'">, InGroup; def note_suspicious_bzero_size_silence : Note< "parenthesize the second argument to silence">; def warn_strncat_large_size : Warning< "the value of the size argument in 'strncat' is too large, might lead to a " "buffer overflow">, InGroup; def warn_strncat_src_size : Warning<"size argument in 'strncat' call appears " "to be size of the source">, InGroup; def warn_strncat_wrong_size : Warning< "the value of the size argument to 'strncat' is wrong">, InGroup; def note_strncat_wrong_size : Note< "change the argument to be the free space in the destination buffer minus " "the terminating null byte">; def warn_assume_side_effects : Warning< "the argument to %0 has side effects that will be discarded">, InGroup>; def warn_memcpy_chk_overflow : Warning< "%0 will always overflow destination buffer">, InGroup>; /// main() // static main() is not an error in C, just in C++. def warn_static_main : Warning<"'main' should not be declared static">, InGroup
; def err_static_main : Error<"'main' is not allowed to be declared static">; def err_inline_main : Error<"'main' is not allowed to be declared inline">; def ext_variadic_main : ExtWarn< "'main' is not allowed to be declared variadic">, InGroup
; def ext_noreturn_main : ExtWarn< "'main' is not allowed to be declared _Noreturn">, InGroup
; def note_main_remove_noreturn : Note<"remove '_Noreturn'">; def err_constexpr_main : Error< "'main' is not allowed to be declared constexpr">; def err_deleted_main : Error<"'main' is not allowed to be deleted">; def err_mainlike_template_decl : Error<"%0 cannot be a template">; def err_main_returns_nonint : Error<"'main' must return 'int'">; def ext_main_returns_nonint : ExtWarn<"return type of 'main' is not 'int'">, InGroup; def note_main_change_return_type : Note<"change return type to 'int'">; def err_main_surplus_args : Error<"too many parameters (%0) for 'main': " "must be 0, 2, or 3">; def warn_main_one_arg : Warning<"only one parameter on 'main' declaration">, InGroup
; def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 " "parameter of 'main' (%select{argument count|argument array|environment|" "platform-specific data}0) must be of type %1">; def warn_main_returns_bool_literal : Warning<"bool literal returned from " "'main'">, InGroup
; def err_main_global_variable : Error<"main cannot be declared as global variable">; def warn_main_redefined : Warning<"variable named 'main' with external linkage " "has undefined behavior">, InGroup
; def ext_main_used : Extension< "ISO C++ does not allow 'main' to be used by a program">, InGroup
; /// parser diagnostics def ext_no_declarators : ExtWarn<"declaration does not declare anything">, InGroup; def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">, InGroup; def err_typedef_not_identifier : Error<"typedef name must be an identifier">; def err_typedef_changes_linkage : Error<"unsupported: typedef changes linkage" " of anonymous type, but linkage was already computed">; def note_typedef_changes_linkage : Note<"use a tag name here to establish " "linkage prior to definition">; def err_statically_allocated_object : Error< "interface type cannot be statically allocated">; def err_object_cannot_be_passed_returned_by_value : Error< "interface type %1 cannot be %select{returned|passed}0 by value" "; did you forget * in %1?">; def err_parameters_retval_cannot_have_fp16_type : Error< "%select{parameters|function return value}0 cannot have __fp16 type; did you forget * ?">; def err_opencl_half_load_store : Error< "%select{loading directly from|assigning directly to}0 pointer to type %1 requires " "cl_khr_fp16. Use vector data %select{load|store}0 builtin functions instead">; def err_opencl_cast_to_half : Error<"casting to type %0 is not allowed">; def err_opencl_half_declaration : Error< "declaring variable of type %0 is not allowed">; def err_opencl_half_param : Error< "declaring function parameter of type %0 is not allowed; did you forget * ?">; def err_opencl_invalid_return : Error< "declaring function return value of type %0 is not allowed %select{; did you forget * ?|}1">; def warn_enum_value_overflow : Warning<"overflow in enumeration value">; def warn_pragma_options_align_reset_failed : Warning< "#pragma options align=reset failed: %0">, InGroup; def err_pragma_options_align_mac68k_target_unsupported : Error< "mac68k alignment pragma is not supported on this target">; def warn_pragma_pack_invalid_alignment : Warning< "expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">, InGroup; def warn_pragma_pack_non_default_at_include : Warning< "non-default #pragma pack value changes the alignment of struct or union " "members in the included file">, InGroup, DefaultIgnore; def warn_pragma_pack_modified_after_include : Warning< "the current #pragma pack aligment value is modified in the included " "file">, InGroup; def warn_pragma_pack_no_pop_eof : Warning<"unterminated " "'#pragma pack (push, ...)' at end of file">, InGroup; def note_pragma_pack_here : Note< "previous '#pragma pack' directive that modifies alignment is here">; def note_pragma_pack_pop_instead_reset : Note< "did you intend to use '#pragma pack (pop)' instead of '#pragma pack()'?">; // Follow the Microsoft implementation. def warn_pragma_pack_show : Warning<"value of #pragma pack(show) == %0">; def warn_pragma_pack_pop_identifier_and_alignment : Warning< "specifying both a name and alignment to 'pop' is undefined">; def warn_pragma_pop_failed : Warning<"#pragma %0(pop, ...) failed: %1">, InGroup; def warn_cxx_ms_struct : Warning<"ms_struct may not produce Microsoft-compatible layouts for classes " "with base classes or virtual functions">, DefaultError, InGroup; def warn_npot_ms_struct : Warning<"ms_struct may not produce Microsoft-compatible layouts with fundamental " "data types with sizes that aren't a power of two">, DefaultError, InGroup; def err_section_conflict : Error<"%0 causes a section type conflict with %1">; def err_no_base_classes : Error<"invalid use of '__super', %0 has no base classes">; def err_invalid_super_scope : Error<"invalid use of '__super', " "this keyword can only be used inside class or member function scope">; def err_super_in_lambda_unsupported : Error< "use of '__super' inside a lambda is unsupported">; def warn_pragma_unused_undeclared_var : Warning< "undeclared variable %0 used as an argument for '#pragma unused'">, InGroup; def warn_atl_uuid_deprecated : Warning< "specifying 'uuid' as an ATL attribute is deprecated; use __declspec instead">, InGroup; def warn_pragma_unused_expected_var_arg : Warning< "only variables can be arguments to '#pragma unused'">, InGroup; def err_pragma_push_visibility_mismatch : Error< "#pragma visibility push with no matching #pragma visibility pop">; def note_surrounding_namespace_ends_here : Note< "surrounding namespace with visibility attribute ends here">; def err_pragma_pop_visibility_mismatch : Error< "#pragma visibility pop with no matching #pragma visibility push">; def note_surrounding_namespace_starts_here : Note< "surrounding namespace with visibility attribute starts here">; def err_pragma_loop_invalid_argument_type : Error< "invalid argument of type %0; expected an integer type">; def err_pragma_loop_invalid_argument_value : Error< "%select{invalid value '%0'; must be positive|value '%0' is too large}1">; def err_pragma_loop_compatibility : Error< "%select{incompatible|duplicate}0 directives '%1' and '%2'">; def err_pragma_loop_precedes_nonloop : Error< "expected a for, while, or do-while loop to follow '%0'">; def err_pragma_attribute_matcher_subrule_contradicts_rule : Error< "redundant attribute subject matcher sub-rule '%0'; '%1' already matches " "those declarations">; def err_pragma_attribute_matcher_negated_subrule_contradicts_subrule : Error< "negated attribute subject matcher sub-rule '%0' contradicts sub-rule '%1'">; def err_pragma_attribute_invalid_matchers : Error< "attribute %0 can't be applied to %1">; def err_pragma_attribute_stack_mismatch : Error< "'#pragma clang attribute pop' with no matching '#pragma clang attribute push'">; def warn_pragma_attribute_unused : Warning< "unused attribute %0 in '#pragma clang attribute push' region">, InGroup; def note_pragma_attribute_region_ends_here : Note< "'#pragma clang attribute push' regions ends here">; def err_pragma_attribute_no_pop_eof : Error<"unterminated " "'#pragma clang attribute push' at end of file">; def note_pragma_attribute_applied_decl_here : Note< "when applied to this declaration">; /// Objective-C parser diagnostics def err_duplicate_class_def : Error< "duplicate interface definition for class %0">; def err_undef_superclass : Error< "cannot find interface declaration for %0, superclass of %1">; def err_forward_superclass : Error< "attempting to use the forward class %0 as superclass of %1">; def err_no_nsconstant_string_class : Error< "cannot find interface declaration for %0">; def err_recursive_superclass : Error< "trying to recursively use %0 as superclass of %1">; def err_conflicting_aliasing_type : Error<"conflicting types for alias %0">; def warn_undef_interface : Warning<"cannot find interface declaration for %0">; def warn_duplicate_protocol_def : Warning< "duplicate protocol definition of %0 is ignored">, InGroup>; def err_protocol_has_circular_dependency : Error< "protocol has circular dependency">; def err_undeclared_protocol : Error<"cannot find protocol declaration for %0">; def warn_undef_protocolref : Warning<"cannot find protocol definition for %0">; def warn_atprotocol_protocol : Warning< "@protocol is using a forward protocol declaration of %0">, InGroup; def warn_readonly_property : Warning< "attribute 'readonly' of property %0 restricts attribute " "'readwrite' of property inherited from %1">, InGroup; def warn_property_attribute : Warning< "'%1' attribute on property %0 does not match the property inherited from %2">, InGroup; def warn_property_types_are_incompatible : Warning< "property type %0 is incompatible with type %1 inherited from %2">, InGroup>; def warn_protocol_property_mismatch : Warning< "property %select{of type %1|with attribute '%1'|without attribute '%1'|with " "getter %1|with setter %1}0 was selected for synthesis">, InGroup>; def err_protocol_property_mismatch: Error; def err_undef_interface : Error<"cannot find interface declaration for %0">; def err_category_forward_interface : Error< "cannot define %select{category|class extension}0 for undefined class %1">; def err_class_extension_after_impl : Error< "cannot declare class extension for %0 after class implementation">; def note_implementation_declared : Note< "class implementation is declared here">; def note_while_in_implementation : Note< "detected while default synthesizing properties in class implementation">; def note_class_declared : Note< "class is declared here">; def note_receiver_class_declared : Note< "receiver is instance of class declared here">; def note_receiver_expr_here : Note< "receiver expression is here">; def note_receiver_is_id : Note< "receiver is treated with 'id' type for purpose of method lookup">; def note_suppressed_class_declare : Note< "class with specified objc_requires_property_definitions attribute is declared here">; def err_objc_root_class_subclass : Error< "objc_root_class attribute may only be specified on a root class declaration">; def err_restricted_superclass_mismatch : Error< "cannot subclass a class that was declared with the " "'objc_subclassing_restricted' attribute">; def warn_objc_root_class_missing : Warning< "class %0 defined without specifying a base class">, InGroup; def err_objc_runtime_visible_category : Error< "cannot implement a category for class %0 that is only visible via the " "Objective-C runtime">; def err_objc_runtime_visible_subclass : Error< "cannot implement subclass %0 of a superclass %1 that is only visible via the " "Objective-C runtime">; def note_objc_needs_superclass : Note< "add a super class to fix this problem">; def warn_dup_category_def : Warning< "duplicate definition of category %1 on interface %0">; def err_conflicting_super_class : Error<"conflicting super class name %0">; def err_dup_implementation_class : Error<"reimplementation of class %0">; def err_dup_implementation_category : Error< "reimplementation of category %1 for class %0">; def err_conflicting_ivar_type : Error< "instance variable %0 has conflicting type%diff{: $ vs $|}1,2">; def err_duplicate_ivar_declaration : Error< "instance variable is already declared">; def warn_on_superclass_use : Warning< "class implementation may not have super class">; def err_conflicting_ivar_bitwidth : Error< "instance variable %0 has conflicting bit-field width">; def err_conflicting_ivar_name : Error< "conflicting instance variable names: %0 vs %1">; def err_inconsistent_ivar_count : Error< "inconsistent number of instance variables specified">; def warn_undef_method_impl : Warning<"method definition for %0 not found">, InGroup>; def warn_conflicting_overriding_ret_types : Warning< "conflicting return type in " "declaration of %0%diff{: $ vs $|}1,2">, InGroup, DefaultIgnore; def warn_conflicting_ret_types : Warning< "conflicting return type in " "implementation of %0%diff{: $ vs $|}1,2">, InGroup; def warn_conflicting_overriding_ret_type_modifiers : Warning< "conflicting distributed object modifiers on return type " "in declaration of %0">, InGroup, DefaultIgnore; def warn_conflicting_ret_type_modifiers : Warning< "conflicting distributed object modifiers on return type " "in implementation of %0">, InGroup; def warn_non_covariant_overriding_ret_types : Warning< "conflicting return type in " "declaration of %0: %1 vs %2">, InGroup, DefaultIgnore; def warn_non_covariant_ret_types : Warning< "conflicting return type in " "implementation of %0: %1 vs %2">, InGroup, DefaultIgnore; def warn_conflicting_overriding_param_types : Warning< "conflicting parameter types in " "declaration of %0%diff{: $ vs $|}1,2">, InGroup, DefaultIgnore; def warn_conflicting_param_types : Warning< "conflicting parameter types in " "implementation of %0%diff{: $ vs $|}1,2">, InGroup; def warn_conflicting_param_modifiers : Warning< "conflicting distributed object modifiers on parameter type " "in implementation of %0">, InGroup; def warn_conflicting_overriding_param_modifiers : Warning< "conflicting distributed object modifiers on parameter type " "in declaration of %0">, InGroup, DefaultIgnore; def warn_non_contravariant_overriding_param_types : Warning< "conflicting parameter types in " "declaration of %0: %1 vs %2">, InGroup, DefaultIgnore; def warn_non_contravariant_param_types : Warning< "conflicting parameter types in " "implementation of %0: %1 vs %2">, InGroup, DefaultIgnore; def warn_conflicting_overriding_variadic :Warning< "conflicting variadic declaration of method and its " "implementation">, InGroup, DefaultIgnore; def warn_conflicting_variadic :Warning< "conflicting variadic declaration of method and its " "implementation">; def warn_category_method_impl_match:Warning< "category is implementing a method which will also be implemented" " by its primary class">, InGroup; def warn_implements_nscopying : Warning< "default assign attribute on property %0 which implements " "NSCopying protocol is not appropriate with -fobjc-gc[-only]">; def warn_multiple_method_decl : Warning<"multiple methods named %0 found">, InGroup; def warn_strict_multiple_method_decl : Warning< "multiple methods named %0 found">, InGroup, DefaultIgnore; def warn_accessor_property_type_mismatch : Warning< "type of property %0 does not match type of accessor %1">; def note_conv_function_declared_at : Note<"type conversion function declared here">; def note_method_declared_at : Note<"method %0 declared here">; def note_property_attribute : Note<"property %0 is declared " "%select{deprecated|unavailable|partial}1 here">; def err_setter_type_void : Error<"type of setter must be void">; def err_duplicate_method_decl : Error<"duplicate declaration of method %0">; def warn_duplicate_method_decl : Warning<"multiple declarations of method %0 found and ignored">, InGroup, DefaultIgnore; def warn_objc_cdirective_format_string : Warning<"using %0 directive in %select{NSString|CFString}1 " "which is being passed as a formatting argument to the formatting " "%select{method|CFfunction}2">, InGroup, DefaultIgnore; def err_objc_var_decl_inclass : Error<"cannot declare variable inside @interface or @protocol">; def err_missing_method_context : Error< "missing context for method declaration">; def err_objc_property_attr_mutually_exclusive : Error< "property attributes '%0' and '%1' are mutually exclusive">; def err_objc_property_requires_object : Error< "property with '%0' attribute must be of object type">; def warn_objc_property_no_assignment_attribute : Warning< "no 'assign', 'retain', or 'copy' attribute is specified - " "'assign' is assumed">, InGroup; def warn_objc_isa_use : Warning< "direct access to Objective-C's isa is deprecated in favor of " "object_getClass()">, InGroup; def warn_objc_isa_assign : Warning< "assignment to Objective-C's isa is deprecated in favor of " "object_setClass()">, InGroup; def warn_objc_pointer_masking : Warning< "bitmasking for introspection of Objective-C object pointers is strongly " "discouraged">, InGroup; def warn_objc_pointer_masking_performSelector : Warning, InGroup; def warn_objc_property_default_assign_on_object : Warning< "default property attribute 'assign' not appropriate for object">, InGroup; def warn_property_attr_mismatch : Warning< "property attribute in class extension does not match the primary class">, InGroup; def warn_property_implicitly_mismatched : Warning < "primary property declaration is implicitly strong while redeclaration " "in class extension is weak">, InGroup>; def warn_objc_property_copy_missing_on_block : Warning< "'copy' attribute must be specified for the block property " "when -fobjc-gc-only is specified">; def warn_objc_property_retain_of_block : Warning< "retain'ed block property does not copy the block " "- use copy attribute instead">, InGroup; def warn_objc_readonly_property_has_setter : Warning< "setter cannot be specified for a readonly property">, InGroup; def warn_atomic_property_rule : Warning< "writable atomic property %0 cannot pair a synthesized %select{getter|setter}1 " "with a user defined %select{getter|setter}2">, InGroup>; def note_atomic_property_fixup_suggest : Note<"setter and getter must both be " "synthesized, or both be user defined,or the property must be nonatomic">; def err_atomic_property_nontrivial_assign_op : Error< "atomic property of reference type %0 cannot have non-trivial assignment" " operator">; def warn_cocoa_naming_owned_rule : Warning< "property follows Cocoa naming" " convention for returning 'owned' objects">, InGroup>; def err_cocoa_naming_owned_rule : Error< "property follows Cocoa naming" " convention for returning 'owned' objects">; def note_cocoa_naming_declare_family : Note< "explicitly declare getter %objcinstance0 with '%1' to return an 'unowned' " "object">; def warn_auto_synthesizing_protocol_property :Warning< "auto property synthesis will not synthesize property %0" " declared in protocol %1">, InGroup>; def note_add_synthesize_directive : Note< "add a '@synthesize' directive">; def warn_no_autosynthesis_shared_ivar_property : Warning < "auto property synthesis will not synthesize property " "%0 because it cannot share an ivar with another synthesized property">, InGroup; def warn_no_autosynthesis_property : Warning< "auto property synthesis will not synthesize property " "%0 because it is 'readwrite' but it will be synthesized 'readonly' " "via another property">, InGroup; def warn_autosynthesis_property_in_superclass : Warning< "auto property synthesis will not synthesize property " "%0; it will be implemented by its superclass, use @dynamic to " "acknowledge intention">, InGroup; def warn_autosynthesis_property_ivar_match :Warning< "autosynthesized property %0 will use %select{|synthesized}1 instance variable " "%2, not existing instance variable %3">, InGroup>; def warn_missing_explicit_synthesis : Warning < "auto property synthesis is synthesizing property not explicitly synthesized">, InGroup>, DefaultIgnore; def warn_property_getter_owning_mismatch : Warning< "property declared as returning non-retained objects" "; getter returning retained objects">; def warn_property_redecl_getter_mismatch : Warning< "getter name mismatch between property redeclaration (%1) and its original " "declaration (%0)">, InGroup; def err_property_setter_ambiguous_use : Error< "synthesized properties %0 and %1 both claim setter %2 -" " use of this setter will cause unexpected behavior">; def warn_default_atomic_custom_getter_setter : Warning< "atomic by default property %0 has a user defined %select{getter|setter}1 " "(property should be marked 'atomic' if this is intended)">, InGroup, DefaultIgnore; def err_use_continuation_class : Error< "illegal redeclaration of property in class extension %0" " (attribute must be 'readwrite', while its primary must be 'readonly')">; def err_type_mismatch_continuation_class : Error< "type of property %0 in class extension does not match " "property type in primary class">; def err_use_continuation_class_redeclaration_readwrite : Error< "illegal redeclaration of 'readwrite' property in class extension %0" " (perhaps you intended this to be a 'readwrite' redeclaration of a " "'readonly' public property?)">; def err_continuation_class : Error<"class extension has no primary class">; def err_property_type : Error<"property cannot have array or function type %0">; def err_missing_property_context : Error< "missing context for property implementation declaration">; def err_bad_property_decl : Error< "property implementation must have its declaration in interface %0 or one of " "its extensions">; def err_category_property : Error< "property declared in category %0 cannot be implemented in " "class implementation">; def note_property_declare : Note< "property declared here">; def note_protocol_property_declare : Note< "it could also be property " "%select{of type %1|without attribute '%1'|with attribute '%1'|with getter " "%1|with setter %1}0 declared here">; def note_property_synthesize : Note< "property synthesized here">; def err_synthesize_category_decl : Error< "@synthesize not allowed in a category's implementation">; def err_synthesize_on_class_property : Error< "@synthesize not allowed on a class property %0">; def err_missing_property_interface : Error< "property implementation in a category with no category declaration">; def err_bad_category_property_decl : Error< "property implementation must have its declaration in the category %0">; def err_bad_property_context : Error< "property implementation must be in a class or category implementation">; def err_missing_property_ivar_decl : Error< "synthesized property %0 must either be named the same as a compatible" " instance variable or must explicitly name an instance variable">; def err_arc_perform_selector_retains : Error< "performSelector names a selector which retains the object">; def warn_arc_perform_selector_leaks : Warning< "performSelector may cause a leak because its selector is unknown">, InGroup>; def warn_dealloc_in_category : Warning< "-dealloc is being overridden in a category">, InGroup; def err_gc_weak_property_strong_type : Error< "weak attribute declared on a __strong type property in GC mode">; def warn_arc_repeated_use_of_weak : Warning < "weak %select{variable|property|implicit property|instance variable}0 %1 is " "accessed multiple times in this %select{function|method|block|lambda}2 " "but may be unpredictably set to nil; assign to a strong variable to keep " "the object alive">, InGroup, DefaultIgnore; def warn_implicitly_retains_self : Warning < "block implicitly retains 'self'; explicitly mention 'self' to indicate " "this is intended behavior">, InGroup>, DefaultIgnore; def warn_arc_possible_repeated_use_of_weak : Warning < "weak %select{variable|property|implicit property|instance variable}0 %1 may " "be accessed multiple times in this %select{function|method|block|lambda}2 " "and may be unpredictably set to nil; assign to a strong variable to keep " "the object alive">, InGroup, DefaultIgnore; def note_arc_weak_also_accessed_here : Note< "also accessed here">; def err_incomplete_synthesized_property : Error< "cannot synthesize property %0 with incomplete type %1">; def err_property_ivar_type : Error< "type of property %0 (%1) does not match type of instance variable %2 (%3)">; def err_property_accessor_type : Error< "type of property %0 (%1) does not match type of accessor %2 (%3)">; def err_ivar_in_superclass_use : Error< "property %0 attempting to use instance variable %1 declared in super class %2">; def err_weak_property : Error< "existing instance variable %1 for __weak property %0 must be __weak">; def err_strong_property : Error< "existing instance variable %1 for strong property %0 may not be __weak">; def err_dynamic_property_ivar_decl : Error< "dynamic property cannot have instance variable specification">; def err_duplicate_ivar_use : Error< "synthesized properties %0 and %1 both claim instance variable %2">; def err_property_implemented : Error<"property %0 is already implemented">; def warn_objc_missing_super_call : Warning< "method possibly missing a [super %0] call">, InGroup; def err_dealloc_bad_result_type : Error< "dealloc return type must be correctly specified as 'void' under ARC, " "instead of %0">; def warn_undeclared_selector : Warning< "undeclared selector %0">, InGroup, DefaultIgnore; def warn_undeclared_selector_with_typo : Warning< "undeclared selector %0; did you mean %1?">, InGroup, DefaultIgnore; def warn_implicit_atomic_property : Warning< "property is assumed atomic by default">, InGroup, DefaultIgnore; def note_auto_readonly_iboutlet_fixup_suggest : Note< "property should be changed to be readwrite">; def warn_auto_readonly_iboutlet_property : Warning< "readonly IBOutlet property %0 when auto-synthesized may " "not work correctly with 'nib' loader">, InGroup>; def warn_auto_implicit_atomic_property : Warning< "property is assumed atomic when auto-synthesizing the property">, InGroup, DefaultIgnore; def warn_unimplemented_selector: Warning< "no method with selector %0 is implemented in this translation unit">, InGroup, DefaultIgnore; def warn_unimplemented_protocol_method : Warning< "method %0 in protocol %1 not implemented">, InGroup; def warn_multiple_selectors: Warning< "several methods with selector %0 of mismatched types are found " "for the @selector expression">, InGroup, DefaultIgnore; def err_objc_kindof_nonobject : Error< "'__kindof' specifier cannot be applied to non-object type %0">; def err_objc_kindof_wrong_position : Error< "'__kindof' type specifier must precede the declarator">; def err_objc_method_unsupported_param_ret_type : Error< "%0 %select{parameter|return}1 type is unsupported; " "support for vector types for this target is introduced in %2">; def warn_messaging_unqualified_id : Warning< "messaging unqualified id">, DefaultIgnore, InGroup>; // C++ declarations def err_static_assert_expression_is_not_constant : Error< "static_assert expression is not an integral constant expression">; def err_static_assert_failed : Error<"static_assert failed%select{ %1|}0">; def err_static_assert_requirement_failed : Error< "static_assert failed due to requirement '%0'%select{ %2|}1">; def ext_static_assert_no_message : ExtWarn< "static_assert with no message is a C++17 extension">, InGroup; def warn_cxx14_compat_static_assert_no_message : Warning< "static_assert with no message is incompatible with C++ standards before C++17">, DefaultIgnore, InGroup; def ext_inline_variable : ExtWarn< "inline variables are a C++17 extension">, InGroup; def warn_cxx14_compat_inline_variable : Warning< "inline variables are incompatible with C++ standards before C++17">, DefaultIgnore, InGroup; def warn_inline_namespace_reopened_noninline : Warning< "inline namespace reopened as a non-inline namespace">; def err_inline_namespace_mismatch : Error< "non-inline namespace cannot be reopened as inline">; def err_unexpected_friend : Error< "friends can only be classes or functions">; def ext_enum_friend : ExtWarn< "befriending enumeration type %0 is a C++11 extension">, InGroup; def warn_cxx98_compat_enum_friend : Warning< "befriending enumeration type %0 is incompatible with C++98">, InGroup, DefaultIgnore; def ext_nonclass_type_friend : ExtWarn< "non-class friend type %0 is a C++11 extension">, InGroup; def warn_cxx98_compat_nonclass_type_friend : Warning< "non-class friend type %0 is incompatible with C++98">, InGroup, DefaultIgnore; def err_friend_is_member : Error< "friends cannot be members of the declaring class">; def warn_cxx98_compat_friend_is_member : Warning< "friend declaration naming a member of the declaring class is incompatible " "with C++98">, InGroup, DefaultIgnore; def ext_unelaborated_friend_type : ExtWarn< "unelaborated friend declaration is a C++11 extension; specify " "'%select{struct|interface|union|class|enum}0' to befriend %1">, InGroup; def warn_cxx98_compat_unelaborated_friend_type : Warning< "befriending %1 without '%select{struct|interface|union|class|enum}0' " "keyword is incompatible with C++98">, InGroup, DefaultIgnore; def err_qualified_friend_not_found : Error< "no function named %0 with type %1 was found in the specified scope">; def err_introducing_special_friend : Error< "%plural{[0,2]:must use a qualified name when declaring|3:cannot declare}0" " a %select{constructor|destructor|conversion operator|deduction guide}0 " "as a friend">; def err_tagless_friend_type_template : Error< "friend type templates must use an elaborated type">; def err_no_matching_local_friend : Error< "no matching function found in local scope">; def err_no_matching_local_friend_suggest : Error< "no matching function %0 found in local scope; did you mean %3?">; def err_partial_specialization_friend : Error< "partial specialization cannot be declared as a friend">; def err_qualified_friend_def : Error< "friend function definition cannot be qualified with '%0'">; def err_friend_def_in_local_class : Error< "friend function cannot be defined in a local class">; def err_friend_not_first_in_declaration : Error< "'friend' must appear first in a non-function declaration">; def err_using_decl_friend : Error< "cannot befriend target of using declaration">; def warn_template_qualified_friend_unsupported : Warning< "dependent nested name specifier '%0' for friend class declaration is " "not supported; turning off access control for %1">, InGroup; def warn_template_qualified_friend_ignored : Warning< "dependent nested name specifier '%0' for friend template declaration is " "not supported; ignoring this friend declaration">, InGroup; def ext_friend_tag_redecl_outside_namespace : ExtWarn< "unqualified friend declaration referring to type outside of the nearest " "enclosing namespace is a Microsoft extension; add a nested name specifier">, InGroup; def err_pure_friend : Error<"friend declaration cannot have a pure-specifier">; def err_invalid_member_in_interface : Error< "%select{data member |non-public member function |static member function |" "user-declared constructor|user-declared destructor|operator |" "nested class }0%1 is not permitted within an interface type">; def err_invalid_base_in_interface : Error< "interface type cannot inherit from " "%select{struct|non-public interface|class}0 %1">; def err_abstract_type_in_decl : Error< "%select{return|parameter|variable|field|instance variable|" "synthesized instance variable}0 type %1 is an abstract class">; def err_allocation_of_abstract_type : Error< "allocating an object of abstract class type %0">; def err_throw_abstract_type : Error< "cannot throw an object of abstract type %0">; def err_array_of_abstract_type : Error<"array of abstract class type %0">; def err_capture_of_abstract_type : Error< "by-copy capture of value of abstract type %0">; def err_capture_of_incomplete_type : Error< "by-copy capture of variable %0 with incomplete type %1">; def err_capture_default_non_local : Error< "non-local lambda expression cannot have a capture-default">; def err_multiple_final_overriders : Error< "virtual function %q0 has more than one final overrider in %1">; def note_final_overrider : Note<"final overrider of %q0 in %1">; def err_type_defined_in_type_specifier : Error< "%0 cannot be defined in a type specifier">; def err_type_defined_in_result_type : Error< "%0 cannot be defined in the result type of a function">; def err_type_defined_in_param_type : Error< "%0 cannot be defined in a parameter type">; def err_type_defined_in_alias_template : Error< "%0 cannot be defined in a type alias template">; def err_type_defined_in_condition : Error< "%0 cannot be defined in a condition">; def err_type_defined_in_enum : Error< "%0 cannot be defined in an enumeration">; def note_pure_virtual_function : Note< "unimplemented pure virtual method %0 in %1">; def note_pure_qualified_call_kext : Note< "qualified call to %0::%1 is treated as a virtual call to %1 due to -fapple-kext">; def err_deleted_decl_not_first : Error< "deleted definition must be first declaration">; def err_deleted_override : Error< "deleted function %0 cannot override a non-deleted function">; def err_non_deleted_override : Error< "non-deleted function %0 cannot override a deleted function">; def warn_weak_vtable : Warning< "%0 has no out-of-line virtual method definitions; its vtable will be " "emitted in every translation unit">, InGroup>, DefaultIgnore; def warn_weak_template_vtable : Warning< "explicit template instantiation %0 will emit a vtable in every " "translation unit">, InGroup>, DefaultIgnore; def ext_using_undefined_std : ExtWarn< "using directive refers to implicitly-defined namespace 'std'">; // C++ exception specifications def err_exception_spec_in_typedef : Error< "exception specifications are not allowed in %select{typedefs|type aliases}0">; def err_distant_exception_spec : Error< "exception specifications are not allowed beyond a single level " "of indirection">; def err_incomplete_in_exception_spec : Error< "%select{|pointer to |reference to }0incomplete type %1 is not allowed " "in exception specification">; def ext_incomplete_in_exception_spec : ExtWarn, InGroup; def err_rref_in_exception_spec : Error< "rvalue reference type %0 is not allowed in exception specification">; def err_mismatched_exception_spec : Error< "exception specification in declaration does not match previous declaration">; def ext_mismatched_exception_spec : ExtWarn, InGroup; def err_override_exception_spec : Error< "exception specification of overriding function is more lax than " "base version">; def ext_override_exception_spec : ExtWarn, InGroup; def err_incompatible_exception_specs : Error< "target exception specification is not superset of source">; def warn_incompatible_exception_specs : Warning< err_incompatible_exception_specs.Text>, InGroup; def err_deep_exception_specs_differ : Error< "exception specifications of %select{return|argument}0 types differ">; def warn_deep_exception_specs_differ : Warning< err_deep_exception_specs_differ.Text>, InGroup; def err_missing_exception_specification : Error< "%0 is missing exception specification '%1'">; def ext_missing_exception_specification : ExtWarn< err_missing_exception_specification.Text>, InGroup>; def ext_ms_missing_exception_specification : ExtWarn< err_missing_exception_specification.Text>, InGroup; def err_noexcept_needs_constant_expression : Error< "argument to noexcept specifier must be a constant expression">; def err_exception_spec_not_parsed : Error< "exception specification is not available until end of class definition">; // C++ access checking def err_class_redeclared_with_different_access : Error< "%0 redeclared with '%1' access">; def err_access : Error< "%1 is a %select{private|protected}0 member of %3">, AccessControl; def ext_ms_using_declaration_inaccessible : ExtWarn< "using declaration referring to inaccessible member '%0' (which refers " "to accessible member '%1') is a Microsoft compatibility extension">, AccessControl, InGroup; def err_access_ctor : Error< "calling a %select{private|protected}0 constructor of class %2">, AccessControl; def ext_rvalue_to_reference_access_ctor : Extension< "C++98 requires an accessible copy constructor for class %2 when binding " "a reference to a temporary; was %select{private|protected}0">, AccessControl, InGroup; def err_access_base_ctor : Error< // The ERRORs represent other special members that aren't constructors, in // hopes that someone will bother noticing and reporting if they appear "%select{base class|inherited virtual base class}0 %1 has %select{private|" "protected}3 %select{default |copy |move |*ERROR* |*ERROR* " "|*ERROR*|}2constructor">, AccessControl; def err_access_field_ctor : Error< // The ERRORs represent other special members that aren't constructors, in // hopes that someone will bother noticing and reporting if they appear "field of type %0 has %select{private|protected}2 " "%select{default |copy |move |*ERROR* |*ERROR* |*ERROR* |}1constructor">, AccessControl; def err_access_friend_function : Error< "friend function %1 is a %select{private|protected}0 member of %3">, AccessControl; def err_access_dtor : Error< "calling a %select{private|protected}1 destructor of class %0">, AccessControl; def err_access_dtor_base : Error<"base class %0 has %select{private|protected}1 destructor">, AccessControl; def err_access_dtor_vbase : Error<"inherited virtual base class %1 has " "%select{private|protected}2 destructor">, AccessControl; def err_access_dtor_temp : Error<"temporary of type %0 has %select{private|protected}1 destructor">, AccessControl; def err_access_dtor_exception : Error<"exception object of type %0 has %select{private|protected}1 " "destructor">, AccessControl; def err_access_dtor_field : Error<"field of type %1 has %select{private|protected}2 destructor">, AccessControl; def err_access_dtor_var : Error<"variable of type %1 has %select{private|protected}2 destructor">, AccessControl; def err_access_dtor_ivar : Error<"instance variable of type %0 has %select{private|protected}1 " "destructor">, AccessControl; def note_previous_access_declaration : Note< "previously declared '%1' here">; def note_access_natural : Note< "%select{|implicitly }1declared %select{private|protected}0 here">; def note_access_constrained_by_path : Note< "constrained by %select{|implicitly }1%select{private|protected}0" " inheritance here">; def note_access_protected_restricted_noobject : Note< "must name member using the type of the current context %0">; def note_access_protected_restricted_ctordtor : Note< "protected %select{constructor|destructor}0 can only be used to " "%select{construct|destroy}0 a base class subobject">; def note_access_protected_restricted_object : Note< "can only access this member on an object of type %0">; def warn_cxx98_compat_sfinae_access_control : Warning< "substitution failure due to access control is incompatible with C++98">, InGroup, DefaultIgnore, NoSFINAE; // C++ name lookup def err_incomplete_nested_name_spec : Error< "incomplete type %0 named in nested name specifier">; def err_dependent_nested_name_spec : Error< "nested name specifier for a declaration cannot depend on a template " "parameter">; def err_nested_name_member_ref_lookup_ambiguous : Error< "lookup of %0 in member access expression is ambiguous">; def ext_nested_name_member_ref_lookup_ambiguous : ExtWarn< "lookup of %0 in member access expression is ambiguous; using member of %1">, InGroup; def note_ambig_member_ref_object_type : Note< "lookup in the object type %0 refers here">; def note_ambig_member_ref_scope : Note< "lookup from the current scope refers here">; def err_qualified_member_nonclass : Error< "qualified member access refers to a member in %0">; def err_incomplete_member_access : Error< "member access into incomplete type %0">; def err_incomplete_type : Error< "incomplete type %0 where a complete type is required">; def warn_cxx98_compat_enum_nested_name_spec : Warning< "enumeration type in nested name specifier is incompatible with C++98">, InGroup, DefaultIgnore; def err_nested_name_spec_is_not_class : Error< "%0 cannot appear before '::' because it is not a class" "%select{ or namespace|, namespace, or enumeration}1; did you mean ':'?">; def ext_nested_name_spec_is_enum : ExtWarn< "use of enumeration in a nested name specifier is a C++11 extension">, InGroup; def err_out_of_line_qualified_id_type_names_constructor : Error< "qualified reference to %0 is a constructor name rather than a " "%select{template name|type}1 in this context">; def ext_out_of_line_qualified_id_type_names_constructor : ExtWarn< "ISO C++ specifies that " "qualified reference to %0 is a constructor name rather than a " "%select{template name|type}1 in this context, despite preceding " "%select{'typename'|'template'}2 keyword">, SFINAEFailure, InGroup>; // C++ class members def err_storageclass_invalid_for_member : Error< "storage class specified for a member declaration">; def err_mutable_function : Error<"'mutable' cannot be applied to functions">; def err_mutable_reference : Error<"'mutable' cannot be applied to references">; def ext_mutable_reference : ExtWarn< "'mutable' on a reference type is a Microsoft extension">, InGroup; def err_mutable_const : Error<"'mutable' and 'const' cannot be mixed">; def err_mutable_nonmember : Error< "'mutable' can only be applied to member variables">; def err_virtual_in_union : Error< "unions cannot have virtual functions">; def err_virtual_non_function : Error< "'virtual' can only appear on non-static member functions">; def err_virtual_out_of_class : Error< "'virtual' can only be specified inside the class definition">; def err_virtual_member_function_template : Error< "'virtual' cannot be specified on member function templates">; def err_static_overrides_virtual : Error< "'static' member function %0 overrides a virtual function in a base class">; def err_explicit_non_function : Error< "'explicit' can only appear on non-static member functions">; def err_explicit_out_of_class : Error< "'explicit' can only be specified inside the class definition">; def err_explicit_non_ctor_or_conv_function : Error< "'explicit' can only be applied to a constructor or conversion function">; def err_static_not_bitfield : Error<"static member %0 cannot be a bit-field">; def err_static_out_of_line : Error< "'static' can only be specified inside the class definition">; def err_storage_class_for_static_member : Error< "static data member definition cannot specify a storage class">; def err_typedef_not_bitfield : Error<"typedef member %0 cannot be a bit-field">; def err_not_integral_type_bitfield : Error< "bit-field %0 has non-integral type %1">; def err_not_integral_type_anon_bitfield : Error< "anonymous bit-field has non-integral type %0">; def err_anon_bitfield_qualifiers : Error< "anonymous bit-field cannot have qualifiers">; def err_member_function_initialization : Error< "initializer on function does not look like a pure-specifier">; def err_non_virtual_pure : Error< "%0 is not virtual and cannot be declared pure">; def ext_pure_function_definition : ExtWarn< "function definition with pure-specifier is a Microsoft extension">, InGroup; def err_qualified_member_of_unrelated : Error< "%q0 is not a member of class %1">; def err_member_function_call_bad_cvr : Error< "'this' argument to member function %0 has type %1, but function is not marked " "%select{const|restrict|const or restrict|volatile|const or volatile|" "volatile or restrict|const, volatile, or restrict}2">; def err_member_function_call_bad_ref : Error< "'this' argument to member function %0 is an %select{lvalue|rvalue}1, " "but function has %select{non-const lvalue|rvalue}2 ref-qualifier">; def err_member_function_call_bad_type : Error< "cannot initialize object parameter of type %0 with an expression " "of type %1">; def warn_call_to_pure_virtual_member_function_from_ctor_dtor : Warning< "call to pure virtual member function %0 has undefined behavior; " "overrides of %0 in subclasses are not available in the " "%select{constructor|destructor}1 of %2">; def select_special_member_kind : TextSubstitution< "%select{default constructor|copy constructor|move constructor|" "copy assignment operator|move assignment operator|destructor}0">; def note_member_declared_at : Note<"member is declared here">; def note_ivar_decl : Note<"instance variable is declared here">; def note_bitfield_decl : Note<"bit-field is declared here">; def note_implicit_param_decl : Note<"%0 is an implicit parameter">; def note_member_synthesized_at : Note< "in implicit %sub{select_special_member_kind}0 for %1 " "first required here">; def err_missing_default_ctor : Error< "%select{constructor for %1 must explicitly initialize the|" "implicit default constructor for %1 must explicitly initialize the|" "cannot use constructor inherited from base class %4;}0 " "%select{base class|member}2 %3 %select{which|which|of %1}0 " "does not have a default constructor">; def note_due_to_dllexported_class : Note< "due to %0 being dllexported%select{|; try compiling in C++11 mode}1">; def err_illegal_union_or_anon_struct_member : Error< "%select{anonymous struct|union}0 member %1 has a non-trivial " "%sub{select_special_member_kind}2">; def warn_cxx98_compat_nontrivial_union_or_anon_struct_member : Warning< "%select{anonymous struct|union}0 member %1 with a non-trivial " "%sub{select_special_member_kind}2 is incompatible with C++98">, InGroup, DefaultIgnore; def note_nontrivial_virtual_dtor : Note< "destructor for %0 is not trivial because it is virtual">; def note_nontrivial_has_virtual : Note< "because type %0 has a virtual %select{member function|base class}1">; def note_nontrivial_no_def_ctor : Note< "because %select{base class of |field of |}0type %1 has no " "default constructor">; def note_user_declared_ctor : Note< "implicit default constructor suppressed by user-declared constructor">; def note_nontrivial_no_copy : Note< "because no %select{<>|constructor|constructor|assignment operator|" "assignment operator|<>}2 can be used to " "%select{<>|copy|move|copy|move|<>}2 " "%select{base class|field|an object}0 of type %3">; def note_nontrivial_user_provided : Note< "because %select{base class of |field of |}0type %1 has a user-provided " "%sub{select_special_member_kind}2">; def note_nontrivial_in_class_init : Note< "because field %0 has an initializer">; def note_nontrivial_param_type : Note< "because its parameter is %diff{of type $, not $|of the wrong type}2,3">; def note_nontrivial_default_arg : Note<"because it has a default argument">; def note_nontrivial_variadic : Note<"because it is a variadic function">; def note_nontrivial_subobject : Note< "because the function selected to %select{construct|copy|move|copy|move|" "destroy}2 %select{base class|field}0 of type %1 is not trivial">; def note_nontrivial_objc_ownership : Note< "because type %0 has a member with %select{no|no|__strong|__weak|" "__autoreleasing}1 ownership">; def err_static_data_member_not_allowed_in_anon_struct : Error< "static data member %0 not allowed in anonymous struct">; def ext_static_data_member_in_union : ExtWarn< "static data member %0 in union is a C++11 extension">, InGroup; def warn_cxx98_compat_static_data_member_in_union : Warning< "static data member %0 in union is incompatible with C++98">, InGroup, DefaultIgnore; def ext_union_member_of_reference_type : ExtWarn< "union member %0 has reference type %1, which is a Microsoft extension">, InGroup; def err_union_member_of_reference_type : Error< "union member %0 has reference type %1">; def ext_anonymous_struct_union_qualified : Extension< "anonymous %select{struct|union}0 cannot be '%1'">; def err_different_return_type_for_overriding_virtual_function : Error< "virtual function %0 has a different return type " "%diff{($) than the function it overrides (which has return type $)|" "than the function it overrides}1,2">; def note_overridden_virtual_function : Note< "overridden virtual function is here">; def err_conflicting_overriding_cc_attributes : Error< "virtual function %0 has different calling convention attributes " "%diff{($) than the function it overrides (which has calling convention $)|" "than the function it overrides}1,2">; def warn_overriding_method_missing_noescape : Warning< "parameter of overriding method should be annotated with " "__attribute__((noescape))">, InGroup; def note_overridden_marked_noescape : Note< "parameter of overridden method is annotated with __attribute__((noescape))">; def note_cat_conform_to_noescape_prot : Note< "%select{category|class extension}0 conforms to protocol %1 which defines method %2">; def err_covariant_return_inaccessible_base : Error< "invalid covariant return for virtual function: %1 is a " "%select{private|protected}2 base class of %0">, AccessControl; def err_covariant_return_ambiguous_derived_to_base_conv : Error< "return type of virtual function %3 is not covariant with the return type of " "the function it overrides (ambiguous conversion from derived class " "%0 to base class %1:%2)">; def err_covariant_return_not_derived : Error< "return type of virtual function %0 is not covariant with the return type of " "the function it overrides (%1 is not derived from %2)">; def err_covariant_return_incomplete : Error< "return type of virtual function %0 is not covariant with the return type of " "the function it overrides (%1 is incomplete)">; def err_covariant_return_type_different_qualifications : Error< "return type of virtual function %0 is not covariant with the return type of " "the function it overrides (%1 has different qualifiers than %2)">; def err_covariant_return_type_class_type_more_qualified : Error< "return type of virtual function %0 is not covariant with the return type of " "the function it overrides (class type %1 is more qualified than class " "type %2">; // C++ implicit special member functions def note_in_declaration_of_implicit_special_member : Note< "while declaring the implicit %sub{select_special_member_kind}1" " for %0">; // C++ constructors def err_constructor_cannot_be : Error<"constructor cannot be declared '%0'">; def err_invalid_qualified_constructor : Error< "'%0' qualifier is not allowed on a constructor">; def err_ref_qualifier_constructor : Error< "ref-qualifier '%select{&&|&}0' is not allowed on a constructor">; def err_constructor_return_type : Error< "constructor cannot have a return type">; def err_constructor_redeclared : Error<"constructor cannot be redeclared">; def err_constructor_byvalue_arg : Error< "copy constructor must pass its first argument by reference">; def warn_no_constructor_for_refconst : Warning< "%select{struct|interface|union|class|enum}0 %1 does not declare any " "constructor to initialize its non-modifiable members">; def note_refconst_member_not_initialized : Note< "%select{const|reference}0 member %1 will never be initialized">; def ext_ms_explicit_constructor_call : ExtWarn< "explicit constructor calls are a Microsoft extension">, InGroup; // C++ destructors def err_destructor_not_member : Error< "destructor must be a non-static member function">; def err_destructor_cannot_be : Error<"destructor cannot be declared '%0'">; def err_invalid_qualified_destructor : Error< "'%0' qualifier is not allowed on a destructor">; def err_ref_qualifier_destructor : Error< "ref-qualifier '%select{&&|&}0' is not allowed on a destructor">; def err_destructor_return_type : Error<"destructor cannot have a return type">; def err_destructor_redeclared : Error<"destructor cannot be redeclared">; def err_destructor_with_params : Error<"destructor cannot have any parameters">; def err_destructor_variadic : Error<"destructor cannot be variadic">; def err_destructor_typedef_name : Error< "destructor cannot be declared using a %select{typedef|type alias}1 %0 of the class name">; def err_destructor_name : Error< "expected the class name after '~' to name the enclosing class">; def err_destructor_class_name : Error< "expected the class name after '~' to name a destructor">; def err_ident_in_dtor_not_a_type : Error< "identifier %0 in object destruction expression does not name a type">; def err_destructor_expr_type_mismatch : Error< "destructor type %0 in object destruction expression does not match the " "type %1 of the object being destroyed">; def note_destructor_type_here : Note< "type %0 is declared here">; def err_destructor_template : Error< "destructor cannot be declared as a template">; // C++ initialization def err_init_conversion_failed : Error< "cannot initialize %select{a variable|a parameter|return object|" "statement expression result|an " "exception object|a member subobject|an array element|a new value|a value|a " "base class|a constructor delegation|a vector element|a block element|a " "block element|a complex element|a lambda capture|a compound literal " "initializer|a related result|a parameter of CF audited function}0 " "%diff{of type $ with an %select{rvalue|lvalue}2 of type $|" "with an %select{rvalue|lvalue}2 of incompatible type}1,3" "%select{|: different classes%diff{ ($ vs $)|}5,6" "|: different number of parameters (%5 vs %6)" "|: type mismatch at %ordinal5 parameter%diff{ ($ vs $)|}6,7" "|: different return type%diff{ ($ vs $)|}5,6" "|: different qualifiers (" "%select{none|const|restrict|const and restrict|volatile|const and volatile|" "volatile and restrict|const, volatile, and restrict}5 vs " "%select{none|const|restrict|const and restrict|volatile|const and volatile|" "volatile and restrict|const, volatile, and restrict}6)" "|: different exception specifications}4">; def err_lvalue_to_rvalue_ref : Error<"rvalue reference %diff{to type $ cannot " "bind to lvalue of type $|cannot bind to incompatible lvalue}0,1">; def err_lvalue_reference_bind_to_initlist : Error< "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to an " "initializer list temporary">; def err_lvalue_reference_bind_to_temporary : Error< "%select{non-const|volatile}0 lvalue reference %diff{to type $ cannot bind " "to a temporary of type $|cannot bind to incompatible temporary}1,2">; def err_lvalue_reference_bind_to_unrelated : Error< "%select{non-const|volatile}0 lvalue reference " "%diff{to type $ cannot bind to a value of unrelated type $|" "cannot bind to a value of unrelated type}1,2">; def err_reference_bind_drops_quals : Error< "binding value %diff{of type $ to reference to type $|to reference}0,1 " "drops %select{<>|'const'|'restrict'|'const' and 'restrict'|" "'volatile'|'const' and 'volatile'|'restrict' and 'volatile'|" "'const', 'restrict', and 'volatile'}2 qualifier%plural{1:|2:|4:|:s}2">; def err_reference_bind_failed : Error< "reference %diff{to type $ could not bind to an %select{rvalue|lvalue}1 of " "type $|could not bind to %select{rvalue|lvalue}1 of incompatible type}0,2">; def err_reference_bind_init_list : Error< "reference to type %0 cannot bind to an initializer list">; def err_init_list_bad_dest_type : Error< "%select{|non-aggregate }0type %1 cannot be initialized with an initializer " "list">; def err_reference_bind_to_bitfield : Error< "%select{non-const|volatile}0 reference cannot bind to " "bit-field%select{| %1}2">; def err_reference_bind_to_vector_element : Error< "%select{non-const|volatile}0 reference cannot bind to vector element">; def err_reference_var_requires_init : Error< "declaration of reference variable %0 requires an initializer">; def err_reference_without_init : Error< "reference to type %0 requires an initializer">; def note_value_initialization_here : Note< "in value-initialization of type %0 here">; def err_reference_has_multiple_inits : Error< "reference cannot be initialized with multiple values">; def err_init_non_aggr_init_list : Error< "initialization of non-aggregate type %0 with an initializer list">; def err_init_reference_member_uninitialized : Error< "reference member of type %0 uninitialized">; def note_uninit_reference_member : Note< "uninitialized reference member is here">; def warn_field_is_uninit : Warning<"field %0 is uninitialized when used here">, InGroup; def warn_base_class_is_uninit : Warning< "base class %0 is uninitialized when used here to access %q1">, InGroup; def warn_reference_field_is_uninit : Warning< "reference %0 is not yet bound to a value when used here">, InGroup; def note_uninit_in_this_constructor : Note< "during field initialization in %select{this|the implicit default}0 " "constructor">; def warn_static_self_reference_in_init : Warning< "static variable %0 is suspiciously used within its own initialization">, InGroup; def warn_uninit_self_reference_in_init : Warning< "variable %0 is uninitialized when used within its own initialization">, InGroup; def warn_uninit_self_reference_in_reference_init : Warning< "reference %0 is not yet bound to a value when used within its own" " initialization">, InGroup; def warn_uninit_var : Warning< "variable %0 is uninitialized when %select{used here|captured by block}1">, InGroup, DefaultIgnore; def warn_sometimes_uninit_var : Warning< "variable %0 is %select{used|captured}1 uninitialized whenever " "%select{'%3' condition is %select{true|false}4|" "'%3' loop %select{is entered|exits because its condition is false}4|" "'%3' loop %select{condition is true|exits because its condition is false}4|" "switch %3 is taken|" "its declaration is reached|" "%3 is called}2">, InGroup, DefaultIgnore; def warn_maybe_uninit_var : Warning< "variable %0 may be uninitialized when " "%select{used here|captured by block}1">, InGroup, DefaultIgnore; def note_var_declared_here : Note<"variable %0 is declared here">; def note_uninit_var_use : Note< "%select{uninitialized use occurs|variable is captured by block}0 here">; def warn_uninit_byref_blockvar_captured_by_block : Warning< "block pointer variable %0 is uninitialized when captured by block">, InGroup, DefaultIgnore; def note_block_var_fixit_add_initialization : Note< "did you mean to use __block %0?">; def note_in_omitted_aggregate_initializer : Note< "in implicit initialization of %select{" "array element %1 with omitted initializer|" "field %1 with omitted initializer|" "trailing array elements in runtime-sized array new}0">; def note_in_reference_temporary_list_initializer : Note< "in initialization of temporary of type %0 created to " "list-initialize this reference">; def note_var_fixit_add_initialization : Note< "initialize the variable %0 to silence this warning">; def note_uninit_fixit_remove_cond : Note< "remove the %select{'%1' if its condition|condition if it}0 " "is always %select{false|true}2">; def err_init_incomplete_type : Error<"initialization of incomplete type %0">; def err_list_init_in_parens : Error< "cannot initialize %select{non-class|reference}0 type %1 with a " "parenthesized initializer list">; def warn_unsequenced_mod_mod : Warning< "multiple unsequenced modifications to %0">, InGroup; def warn_unsequenced_mod_use : Warning< "unsequenced modification and access to %0">, InGroup; def select_initialized_entity_kind : TextSubstitution< "%select{copying variable|copying parameter|" "returning object|initializing statement expression result|" "throwing object|copying member subobject|copying array element|" "allocating object|copying temporary|initializing base subobject|" "initializing vector element|capturing value}0">; def err_temp_copy_no_viable : Error< "no viable constructor %sub{select_initialized_entity_kind}0 of type %1">; def ext_rvalue_to_reference_temp_copy_no_viable : Extension< "no viable constructor %sub{select_initialized_entity_kind}0 of type %1; " "C++98 requires a copy constructor when binding a reference to a temporary">, InGroup; def err_temp_copy_ambiguous : Error< "ambiguous constructor call when %sub{select_initialized_entity_kind}0 " "of type %1">; def err_temp_copy_deleted : Error< "%sub{select_initialized_entity_kind}0 of type %1 " "invokes deleted constructor">; def err_temp_copy_incomplete : Error< "copying a temporary object of incomplete type %0">; def warn_cxx98_compat_temp_copy : Warning< "%sub{select_initialized_entity_kind}1 " "of type %2 when binding a reference to a temporary would %select{invoke " "an inaccessible constructor|find no viable constructor|find ambiguous " "constructors|invoke a deleted constructor}0 in C++98">, InGroup, DefaultIgnore; def err_selected_explicit_constructor : Error< "chosen constructor is explicit in copy-initialization">; def note_explicit_ctor_deduction_guide_here : Note< "explicit %select{constructor|deduction guide}0 declared here">; // C++11 decltype def err_decltype_in_declarator : Error< "'decltype' cannot be used to name a declaration">; // C++11 auto def warn_cxx98_compat_auto_type_specifier : Warning< "'auto' type specifier is incompatible with C++98">, InGroup, DefaultIgnore; def err_auto_variable_cannot_appear_in_own_initializer : Error< "variable %0 declared with deduced type %1 " "cannot appear in its own initializer">; def err_binding_cannot_appear_in_own_initializer : Error< "binding %0 cannot appear in the initializer of its own " "decomposition declaration">; def err_illegal_decl_array_of_auto : Error< "'%0' declared as array of %1">; def err_new_array_of_auto : Error< "cannot allocate array of 'auto'">; def err_auto_not_allowed : Error< "%select{'auto'|'decltype(auto)'|'__auto_type'|" "use of " "%select{class template|function template|variable template|alias template|" "template template parameter|template}2 %3 requires template arguments; " "argument deduction}0 not allowed " "%select{in function prototype" "|in non-static struct member|in struct member" "|in non-static union member|in union member" "|in non-static class member|in interface member" "|in exception declaration|in template parameter until C++17|in block literal" "|in template argument|in typedef|in type alias|in function return type" "|in conversion function type|here|in lambda parameter" "|in type allocated by 'new'|in K&R-style function parameter" "|in template parameter|in friend declaration}1">; def err_dependent_deduced_tst : Error< "typename specifier refers to " "%select{class template|function template|variable template|alias template|" "template template parameter|template}0 member in %1; " "argument deduction not allowed here">; def err_auto_not_allowed_var_inst : Error< "'auto' variable template instantiation is not allowed">; def err_auto_var_requires_init : Error< "declaration of variable %0 with deduced type %1 requires an initializer">; def err_auto_new_requires_ctor_arg : Error< "new expression for type %0 requires a constructor argument">; def ext_auto_new_list_init : Extension< "ISO C++ standards before C++17 do not allow new expression for " "type %0 to use list-initialization">, InGroup; def err_auto_var_init_no_expression : Error< "initializer for variable %0 with type %1 is empty">; def err_auto_var_init_multiple_expressions : Error< "initializer for variable %0 with type %1 contains multiple expressions">; def err_auto_var_init_paren_braces : Error< "cannot deduce type for variable %1 with type %2 from " "%select{parenthesized|nested}0 initializer list">; def err_auto_new_ctor_multiple_expressions : Error< "new expression for type %0 contains multiple constructor arguments">; def err_auto_missing_trailing_return : Error< "'auto' return without trailing return type; deduced return types are a " "C++14 extension">; def err_deduced_return_type : Error< "deduced return types are a C++14 extension">; def err_trailing_return_without_auto : Error< "function with trailing return type must specify return type 'auto', not %0">; def err_trailing_return_in_parens : Error< "trailing return type may not be nested within parentheses">; def err_auto_var_deduction_failure : Error< "variable %0 with type %1 has incompatible initializer of type %2">; def err_auto_var_deduction_failure_from_init_list : Error< "cannot deduce actual type for variable %0 with type %1 from initializer list">; def err_auto_new_deduction_failure : Error< "new expression for type %0 has incompatible constructor argument of type %1">; def err_auto_inconsistent_deduction : Error< "deduced conflicting types %diff{($ vs $) |}0,1" "for initializer list element type">; def err_auto_different_deductions : Error< "%select{'auto'|'decltype(auto)'|'__auto_type'|template arguments}0 " "deduced as %1 in declaration of %2 and " "deduced as %3 in declaration of %4">; def err_auto_non_deduced_not_alone : Error< "%select{function with deduced return type|" "declaration with trailing return type}0 " "must be the only declaration in its group">; def err_implied_std_initializer_list_not_found : Error< "cannot deduce type of initializer list because std::initializer_list was " "not found; include ">; def err_malformed_std_initializer_list : Error< "std::initializer_list must be a class template with a single type parameter">; def err_auto_init_list_from_c : Error< "cannot use __auto_type with initializer list in C">; def err_auto_bitfield : Error< "cannot pass bit-field as __auto_type initializer in C">; // C++1y decltype(auto) type def err_decltype_auto_invalid : Error< "'decltype(auto)' not allowed here">; def err_decltype_auto_cannot_be_combined : Error< "'decltype(auto)' cannot be combined with other type specifiers">; def err_decltype_auto_function_declarator_not_declaration : Error< "'decltype(auto)' can only be used as a return type " "in a function declaration">; def err_decltype_auto_compound_type : Error< "cannot form %select{pointer to|reference to|array of}0 'decltype(auto)'">; def err_decltype_auto_initializer_list : Error< "cannot deduce 'decltype(auto)' from initializer list">; // C++17 deduced class template specialization types def err_deduced_class_template_compound_type : Error< "cannot %select{form pointer to|form reference to|form array of|" "form function returning|use parentheses when declaring variable with}0 " "deduced class template specialization type">; def err_deduced_non_class_template_specialization_type : Error< "%select{|function template|variable template|alias template|" "template template parameter|template}0 %1 requires template arguments; " "argument deduction only allowed for class templates">; def err_deduced_class_template_ctor_ambiguous : Error< "ambiguous deduction for template arguments of %0">; def err_deduced_class_template_ctor_no_viable : Error< "no viable constructor or deduction guide for deduction of " "template arguments of %0">; def err_deduced_class_template_incomplete : Error< "template %0 has no definition and no %select{|viable }1deduction guides " "for deduction of template arguments">; def err_deduced_class_template_deleted : Error< "class template argument deduction for %0 selected a deleted constructor">; def err_deduced_class_template_explicit : Error< "class template argument deduction for %0 selected an explicit " "%select{constructor|deduction guide}1 for copy-list-initialization">; def err_deduction_guide_no_trailing_return_type : Error< "deduction guide declaration without trailing return type">; def err_deduction_guide_bad_trailing_return_type : Error< "deduced type %1 of deduction guide is not %select{|written as }2" "a specialization of template %0">; def err_deduction_guide_with_complex_decl : Error< "cannot specify any part of a return type in the " "declaration of a deduction guide">; def err_deduction_guide_invalid_specifier : Error< "deduction guide cannot be declared '%0'">; def err_deduction_guide_name_not_class_template : Error< "cannot specify deduction guide for " "%select{|function template|variable template|alias template|" "template template parameter|dependent template name}0 %1">; def err_deduction_guide_wrong_scope : Error< "deduction guide must be declared in the same scope as template %q0">; def err_deduction_guide_defines_function : Error< "deduction guide cannot have a function definition">; def err_deduction_guide_explicit_mismatch : Error< "deduction guide is %select{not |}0declared 'explicit' but " "previous declaration was%select{ not|}0">; def err_deduction_guide_specialized : Error<"deduction guide cannot be " "%select{explicitly instantiated|explicitly specialized}0">; def err_deduction_guide_template_not_deducible : Error< "deduction guide template contains " "%select{a template parameter|template parameters}0 that cannot be " "deduced">; def err_deduction_guide_wrong_access : Error< "deduction guide has different access from the corresponding " "member template">; def note_deduction_guide_template_access : Note< "member template declared %0 here">; def note_deduction_guide_access : Note< "deduction guide declared %0 by intervening access specifier">; // C++1y deduced return types def err_auto_fn_deduction_failure : Error< "cannot deduce return type %0 from returned value of type %1">; def err_auto_fn_different_deductions : Error< "'%select{auto|decltype(auto)}0' in return type deduced as %1 here but " "deduced as %2 in earlier return statement">; def err_auto_fn_used_before_defined : Error< "function %0 with deduced return type cannot be used before it is defined">; def err_auto_fn_no_return_but_not_auto : Error< "cannot deduce return type %0 for function with no return statements">; def err_auto_fn_return_void_but_not_auto : Error< "cannot deduce return type %0 from omitted return expression">; def err_auto_fn_return_init_list : Error< "cannot deduce return type from initializer list">; def err_auto_fn_virtual : Error< "function with deduced return type cannot be virtual">; // C++11 override control def override_keyword_only_allowed_on_virtual_member_functions : Error< "only virtual member functions can be marked '%0'">; def override_keyword_hides_virtual_member_function : Error< "non-virtual member function marked '%0' hides virtual member " "%select{function|functions}1">; def err_function_marked_override_not_overriding : Error< "%0 marked 'override' but does not override any member functions">; def warn_destructor_marked_not_override_overriding : Warning < "%0 overrides a destructor but is not marked 'override'">, InGroup, DefaultIgnore; def warn_function_marked_not_override_overriding : Warning < "%0 overrides a member function but is not marked 'override'">, InGroup; def err_class_marked_final_used_as_base : Error< "base %0 is marked '%select{final|sealed}1'">; def warn_abstract_final_class : Warning< "abstract class is marked '%select{final|sealed}0'">, InGroup; // C++11 attributes def err_repeat_attribute : Error<"%0 attribute cannot be repeated">; // C++11 final def err_final_function_overridden : Error< "declaration of %0 overrides a '%select{final|sealed}1' function">; // C++11 scoped enumerations def err_enum_invalid_underlying : Error< "non-integral type %0 is an invalid underlying type">; def err_enumerator_too_large : Error< "enumerator value is not representable in the underlying type %0">; def ext_enumerator_too_large : Extension< "enumerator value is not representable in the underlying type %0">, InGroup; def err_enumerator_wrapped : Error< "enumerator value %0 is not representable in the underlying type %1">; def err_enum_redeclare_type_mismatch : Error< "enumeration redeclared with different underlying type %0 (was %1)">; def err_enum_redeclare_fixed_mismatch : Error< "enumeration previously declared with %select{non|}0fixed underlying type">; def err_enum_redeclare_scoped_mismatch : Error< "enumeration previously declared as %select{un|}0scoped">; def err_enum_class_reference : Error< "reference to %select{|scoped }0enumeration must use 'enum' " "not 'enum class'">; def err_only_enums_have_underlying_types : Error< "only enumeration types have underlying types">; def err_underlying_type_of_incomplete_enum : Error< "cannot determine underlying type of incomplete enumeration type %0">; // C++11 delegating constructors def err_delegating_ctor : Error< "delegating constructors are permitted only in C++11">; def warn_cxx98_compat_delegating_ctor : Warning< "delegating constructors are incompatible with C++98">, InGroup, DefaultIgnore; def err_delegating_initializer_alone : Error< "an initializer for a delegating constructor must appear alone">; def warn_delegating_ctor_cycle : Warning< "constructor for %0 creates a delegation cycle">, DefaultError, InGroup; def note_it_delegates_to : Note<"it delegates to">; def note_which_delegates_to : Note<"which delegates to">; // C++11 range-based for loop def err_for_range_decl_must_be_var : Error< "for range declaration must declare a variable">; def err_for_range_storage_class : Error< "loop variable %0 may not be declared %select{'extern'|'static'|" "'__private_extern__'|'auto'|'register'|'constexpr'}1">; def err_type_defined_in_for_range : Error< "types may not be defined in a for range declaration">; def err_for_range_deduction_failure : Error< "cannot use type %0 as a range">; def err_for_range_incomplete_type : Error< "cannot use incomplete type %0 as a range">; def err_for_range_iter_deduction_failure : Error< "cannot use type %0 as an iterator">; def err_for_range_member_begin_end_mismatch : Error< "range type %0 has '%select{begin|end}1' member but no '%select{end|begin}1' member">; def ext_for_range_begin_end_types_differ : ExtWarn< "'begin' and 'end' returning different types (%0 and %1) is a C++17 extension">, InGroup; def warn_for_range_begin_end_types_differ : Warning< "'begin' and 'end' returning different types (%0 and %1) is incompatible " "with C++ standards before C++17">, InGroup, DefaultIgnore; def note_in_for_range: Note< "when looking up '%select{begin|end}0' function for range expression " "of type %1">; def err_for_range_invalid: Error< "invalid range expression of type %0; no viable '%select{begin|end}1' " "function available">; def err_range_on_array_parameter : Error< "cannot build range expression with array function parameter %0 since " "parameter with array type %1 is treated as pointer type %2">; def err_for_range_dereference : Error< "invalid range expression of type %0; did you mean to dereference it " "with '*'?">; def note_for_range_invalid_iterator : Note < "in implicit call to 'operator%select{!=|*|++}0' for iterator of type %1">; def note_for_range_begin_end : Note< "selected '%select{begin|end}0' %select{function|template }1%2 with iterator type %3">; def warn_for_range_const_reference_copy : Warning< "loop variable %0 " "%diff{has type $ but is initialized with type $" "| is initialized with a value of a different type}1,2 resulting in a copy">, InGroup, DefaultIgnore; def note_use_type_or_non_reference : Note< "use non-reference type %0 to keep the copy or type %1 to prevent copying">; def warn_for_range_variable_always_copy : Warning< "loop variable %0 is always a copy because the range of type %1 does not " "return a reference">, InGroup, DefaultIgnore; def note_use_non_reference_type : Note<"use non-reference type %0">; def warn_for_range_copy : Warning< "loop variable %0 of type %1 creates a copy from type %2">, InGroup, DefaultIgnore; def note_use_reference_type : Note<"use reference type %0 to prevent copying">; // C++11 constexpr def warn_cxx98_compat_constexpr : Warning< "'constexpr' specifier is incompatible with C++98">, InGroup, DefaultIgnore; // FIXME: Maybe this should also go in -Wc++14-compat? def warn_cxx14_compat_constexpr_not_const : Warning< "'constexpr' non-static member function will not be implicitly 'const' " "in C++14; add 'const' to avoid a change in behavior">, InGroup>; def err_invalid_constexpr : Error< "%select{function parameter|typedef|non-static data member}0 " "cannot be constexpr">; def err_invalid_constexpr_member : Error<"non-static data member cannot be " "constexpr%select{; did you intend to make it %select{const|static}0?|}1">; def err_constexpr_tag : Error< "%select{class|struct|interface|union|enum}0 cannot be marked constexpr">; def err_constexpr_dtor : Error<"destructor cannot be marked constexpr">; def err_constexpr_no_declarators : Error< "constexpr can only be used in variable and function declarations">; def err_invalid_constexpr_var_decl : Error< "constexpr variable declaration must be a definition">; def err_constexpr_static_mem_var_requires_init : Error< "declaration of constexpr static data member %0 requires an initializer">; def err_constexpr_var_non_literal : Error< "constexpr variable cannot have non-literal type %0">; def err_constexpr_var_requires_const_init : Error< "constexpr variable %0 must be initialized by a constant expression">; def err_constexpr_redecl_mismatch : Error< "%select{non-constexpr declaration of %0 follows constexpr declaration" "|constexpr declaration of %0 follows non-constexpr declaration}1">; def err_constexpr_virtual : Error<"virtual function cannot be constexpr">; def err_constexpr_virtual_base : Error< "constexpr %select{member function|constructor}0 not allowed in " "%select{struct|interface|class}1 with virtual base " "%plural{1:class|:classes}2">; def note_non_literal_incomplete : Note< "incomplete type %0 is not a literal type">; def note_non_literal_virtual_base : Note<"%select{struct|interface|class}0 " "with virtual base %plural{1:class|:classes}1 is not a literal type">; def note_constexpr_virtual_base_here : Note<"virtual base class declared here">; def err_constexpr_non_literal_return : Error< "constexpr function's return type %0 is not a literal type">; def err_constexpr_non_literal_param : Error< "constexpr %select{function|constructor}1's %ordinal0 parameter type %2 is " "not a literal type">; def err_constexpr_body_invalid_stmt : Error< "statement not allowed in constexpr %select{function|constructor}0">; def ext_constexpr_body_invalid_stmt : ExtWarn< "use of this statement in a constexpr %select{function|constructor}0 " "is a C++14 extension">, InGroup; def warn_cxx11_compat_constexpr_body_invalid_stmt : Warning< "use of this statement in a constexpr %select{function|constructor}0 " "is incompatible with C++ standards before C++14">, InGroup, DefaultIgnore; def ext_constexpr_type_definition : ExtWarn< "type definition in a constexpr %select{function|constructor}0 " "is a C++14 extension">, InGroup; def warn_cxx11_compat_constexpr_type_definition : Warning< "type definition in a constexpr %select{function|constructor}0 " "is incompatible with C++ standards before C++14">, InGroup, DefaultIgnore; def err_constexpr_vla : Error< "variably-modified type %0 cannot be used in a constexpr " "%select{function|constructor}1">; def ext_constexpr_local_var : ExtWarn< "variable declaration in a constexpr %select{function|constructor}0 " "is a C++14 extension">, InGroup; def warn_cxx11_compat_constexpr_local_var : Warning< "variable declaration in a constexpr %select{function|constructor}0 " "is incompatible with C++ standards before C++14">, InGroup, DefaultIgnore; def err_constexpr_local_var_static : Error< "%select{static|thread_local}1 variable not permitted in a constexpr " "%select{function|constructor}0">; def err_constexpr_local_var_non_literal_type : Error< "variable of non-literal type %1 cannot be defined in a constexpr " "%select{function|constructor}0">; def err_constexpr_local_var_no_init : Error< "variables defined in a constexpr %select{function|constructor}0 must be " "initialized">; def ext_constexpr_function_never_constant_expr : ExtWarn< "constexpr %select{function|constructor}0 never produces a " "constant expression">, InGroup>, DefaultError; def err_attr_cond_never_constant_expr : Error< "%0 attribute expression never produces a constant expression">; def err_diagnose_if_invalid_diagnostic_type : Error< "invalid diagnostic type for 'diagnose_if'; use \"error\" or \"warning\" " "instead">; def err_constexpr_body_no_return : Error< "no return statement in constexpr function">; def err_constexpr_return_missing_expr : Error< "non-void constexpr function %0 should return a value">; def warn_cxx11_compat_constexpr_body_no_return : Warning< "constexpr function with no return statements is incompatible with C++ " "standards before C++14">, InGroup, DefaultIgnore; def ext_constexpr_body_multiple_return : ExtWarn< "multiple return statements in constexpr function is a C++14 extension">, InGroup; def warn_cxx11_compat_constexpr_body_multiple_return : Warning< "multiple return statements in constexpr function " "is incompatible with C++ standards before C++14">, InGroup, DefaultIgnore; def note_constexpr_body_previous_return : Note< "previous return statement is here">; def err_constexpr_function_try_block : Error< "function try block not allowed in constexpr %select{function|constructor}0">; def err_constexpr_union_ctor_no_init : Error< "constexpr union constructor does not initialize any member">; def err_constexpr_ctor_missing_init : Error< "constexpr constructor must initialize all members">; def note_constexpr_ctor_missing_init : Note< "member not initialized by constructor">; def note_non_literal_no_constexpr_ctors : Note< "%0 is not literal because it is not an aggregate and has no constexpr " "constructors other than copy or move constructors">; def note_non_literal_base_class : Note< "%0 is not literal because it has base class %1 of non-literal type">; def note_non_literal_field : Note< "%0 is not literal because it has data member %1 of " "%select{non-literal|volatile}3 type %2">; def note_non_literal_user_provided_dtor : Note< "%0 is not literal because it has a user-provided destructor">; def note_non_literal_nontrivial_dtor : Note< "%0 is not literal because it has a non-trivial destructor">; def note_non_literal_lambda : Note< "lambda closure types are non-literal types before C++17">; def warn_private_extern : Warning< "use of __private_extern__ on a declaration may not produce external symbol " "private to the linkage unit and is deprecated">, InGroup; def note_private_extern : Note< "use __attribute__((visibility(\"hidden\"))) attribute instead">; // C++ Concepts TS def err_concept_wrong_decl_kind : Error< "'concept' can only appear on the definition of a function template or variable template">; def err_concept_decls_may_only_appear_in_namespace_scope : Error< "concept declarations may only appear in namespace scope">; def err_function_concept_not_defined : Error< "function concept declaration must be a definition">; def err_var_concept_not_initialized : Error< "variable concept declaration must be initialized">; def err_function_concept_exception_spec : Error< "function concept cannot have exception specification">; def err_concept_decl_invalid_specifiers : Error< "%select{variable|function}0 concept cannot be declared " "'%select{thread_local|inline|friend|constexpr}1'">; def err_function_concept_with_params : Error< "function concept cannot have any parameters">; def err_function_concept_bool_ret : Error< "declared return type of function concept must be 'bool'">; def err_variable_concept_bool_decl : Error< "declared type of variable concept must be 'bool'">; def err_concept_specified_specialization : Error< "'concept' cannot be applied on an " "%select{explicit instantiation|explicit specialization|partial specialization}0">; def err_concept_specialized : Error< "%select{function|variable}0 concept cannot be " "%select{explicitly instantiated|explicitly specialized|partially specialized}1">; def err_template_different_associated_constraints : Error< "associated constraints differ in template redeclaration">; // C++11 char16_t/char32_t def warn_cxx98_compat_unicode_type : Warning< "'%0' type specifier is incompatible with C++98">, InGroup, DefaultIgnore; def warn_cxx17_compat_unicode_type : Warning< "'char8_t' type specifier is incompatible with C++ standards before C++20">, InGroup, DefaultIgnore; // __make_integer_seq def err_integer_sequence_negative_length : Error< "integer sequences must have non-negative sequence length">; def err_integer_sequence_integral_element_type : Error< "integer sequences must have integral element type">; // __type_pack_element def err_type_pack_element_out_of_bounds : Error< "a parameter pack may not be accessed at an out of bounds index">; // Objective-C++ def err_objc_decls_may_only_appear_in_global_scope : Error< "Objective-C declarations may only appear in global scope">; def warn_auto_var_is_id : Warning< "'auto' deduced as 'id' in declaration of %0">, InGroup>; // Attributes def err_nsobject_attribute : Error< "'NSObject' attribute is for pointer types only">; def err_attributes_are_not_compatible : Error< "%0 and %1 attributes are not compatible">; def err_attribute_wrong_number_arguments : Error< "%0 attribute %plural{0:takes no arguments|1:takes one argument|" ":requires exactly %1 arguments}1">; def err_attribute_too_many_arguments : Error< "%0 attribute takes no more than %1 argument%s1">; def err_attribute_too_few_arguments : Error< "%0 attribute takes at least %1 argument%s1">; def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">; def err_attribute_bad_neon_vector_size : Error< "Neon vector size must be 64 or 128 bits">; def err_attribute_requires_positive_integer : Error< "%0 attribute requires a positive integral compile time constant expression">; def err_attribute_requires_opencl_version : Error< "%0 attribute requires OpenCL version %1%select{| or above}2">; def warn_unsupported_target_attribute : Warning<"%select{unsupported|duplicate}0%select{| architecture}1 '%2' in" " the 'target' attribute string; 'target' attribute ignored">, InGroup; def err_attribute_unsupported : Error<"%0 attribute is not supported for this target">; // The err_*_attribute_argument_not_int are separate because they're used by // VerifyIntegerConstantExpression. def err_aligned_attribute_argument_not_int : Error< "'aligned' attribute requires integer constant">; def err_align_value_attribute_argument_not_int : Error< "'align_value' attribute requires integer constant">; def err_alignas_attribute_wrong_decl_type : Error< "%0 attribute cannot be applied to a %select{function parameter|" "variable with 'register' storage class|'catch' variable|bit-field}1">; def err_alignas_missing_on_definition : Error< "%0 must be specified on definition if it is specified on any declaration">; def note_alignas_on_declaration : Note<"declared with %0 attribute here">; def err_alignas_mismatch : Error< "redeclaration has different alignment requirement (%1 vs %0)">; def err_alignas_underaligned : Error< "requested alignment is less than minimum alignment of %1 for type %0">; def err_attribute_argument_n_type : Error< "%0 attribute requires parameter %1 to be %select{int or bool|an integer " "constant|a string|an identifier}2">; def err_attribute_argument_type : Error< "%0 attribute requires %select{int or bool|an integer " "constant|a string|an identifier}1">; def err_attribute_argument_outof_range : Error< "%0 attribute requires integer constant between %1 and %2 inclusive">; def err_init_priority_object_attr : Error< "can only use 'init_priority' attribute on file-scope definitions " "of objects of class type">; def err_attribute_argument_vec_type_hint : Error< "invalid attribute argument %0 - expecting a vector or vectorizable scalar type">; def err_attribute_argument_out_of_bounds : Error< "%0 attribute parameter %1 is out of bounds">; def err_attribute_only_once_per_parameter : Error< "%0 attribute can only be applied once per parameter">; def err_attribute_uuid_malformed_guid : Error< "uuid attribute contains a malformed GUID">; def err_mismatched_uuid : Error<"uuid does not match previous declaration">; def note_previous_uuid : Note<"previous uuid specified here">; def warn_attribute_pointers_only : Warning< "%0 attribute only applies to%select{| constant}1 pointer arguments">, InGroup; def err_attribute_pointers_only : Error; def err_attribute_integers_only : Error< "%0 attribute argument may only refer to a function parameter of integer " "type">; def warn_attribute_return_pointers_only : Warning< "%0 attribute only applies to return values that are pointers">, InGroup; def warn_attribute_return_pointers_refs_only : Warning< "%0 attribute only applies to return values that are pointers or references">, InGroup; def warn_attribute_pointer_or_reference_only : Warning< "%0 attribute only applies to a pointer or reference (%1 is invalid)">, InGroup; def err_attribute_no_member_pointers : Error< "%0 attribute cannot be used with pointers to members">; def err_attribute_invalid_implicit_this_argument : Error< "%0 attribute is invalid for the implicit this argument">; def err_ownership_type : Error< "%0 attribute only applies to %select{pointer|integer}1 arguments">; def err_ownership_returns_index_mismatch : Error< "'ownership_returns' attribute index does not match; here it is %0">; def note_ownership_returns_index_mismatch : Note< "declared with index %0 here">; def err_format_strftime_third_parameter : Error< "strftime format attribute requires 3rd parameter to be 0">; def err_format_attribute_requires_variadic : Error< "format attribute requires variadic function">; def err_format_attribute_not : Error<"format argument not %0">; def err_format_attribute_result_not : Error<"function does not return %0">; def err_format_attribute_implicit_this_format_string : Error< "format attribute cannot specify the implicit this argument as the format " "string">; def err_init_method_bad_return_type : Error< "init methods must return an object pointer type, not %0">; def err_attribute_invalid_size : Error< "vector size not an integral multiple of component size">; def err_attribute_zero_size : Error<"zero vector size">; def err_attribute_size_too_large : Error<"vector size too large">; def err_typecheck_vector_not_convertable_implict_truncation : Error< "cannot convert between %select{scalar|vector}0 type %1 and vector type" " %2 as implicit conversion would cause truncation">; def err_typecheck_vector_not_convertable : Error< "cannot convert between vector values of different size (%0 and %1)">; def err_typecheck_vector_not_convertable_non_scalar : Error< "cannot convert between vector and non-scalar values (%0 and %1)">; def err_typecheck_vector_lengths_not_equal : Error< "vector operands do not have the same number of elements (%0 and %1)">; def warn_typecheck_vector_element_sizes_not_equal : Warning< "vector operands do not have the same elements sizes (%0 and %1)">, InGroup>, DefaultError; def err_ext_vector_component_exceeds_length : Error< "vector component access exceeds type %0">; def err_ext_vector_component_name_illegal : Error< "illegal vector component name '%0'">; def err_attribute_address_space_negative : Error< "address space is negative">; def err_attribute_address_space_too_high : Error< "address space is larger than the maximum supported (%0)">; def err_attribute_address_multiple_qualifiers : Error< "multiple address spaces specified for type">; def warn_attribute_address_multiple_identical_qualifiers : Warning< "multiple identical address spaces specified for type">, InGroup; def err_attribute_address_function_type : Error< "function type may not be qualified with an address space">; def err_as_qualified_auto_decl : Error< "automatic variable qualified with an%select{| invalid}0 address space">; def err_arg_with_address_space : Error< "parameter may not be qualified with an address space">; def err_field_with_address_space : Error< "field may not be qualified with an address space">; def err_attr_objc_ownership_redundant : Error< "the type %0 is already explicitly ownership-qualified">; def err_invalid_nsnumber_type : Error< "%0 is not a valid literal type for NSNumber">; def err_objc_illegal_boxed_expression_type : Error< "illegal type %0 used in a boxed expression">; def err_objc_non_trivially_copyable_boxed_expression_type : Error< "non-trivially copyable type %0 cannot be used in a boxed expression">; def err_objc_incomplete_boxed_expression_type : Error< "incomplete type %0 used in a boxed expression">; def err_undeclared_objc_literal_class : Error< "definition of class %0 must be available to use Objective-C " "%select{array literals|dictionary literals|numeric literals|boxed expressions|" "string literals}1">; def err_undeclared_boxing_method : Error< "declaration of %0 is missing in %1 class">; def err_objc_literal_method_sig : Error< "literal construction method %0 has incompatible signature">; def note_objc_literal_method_param : Note< "%select{first|second|third}0 parameter has unexpected type %1 " "(should be %2)">; def note_objc_literal_method_return : Note< "method returns unexpected type %0 (should be an object type)">; def err_invalid_collection_element : Error< "collection element of type %0 is not an Objective-C object">; def err_box_literal_collection : Error< "%select{string|character|boolean|numeric}0 literal must be prefixed by '@' " "in a collection">; def warn_objc_literal_comparison : Warning< "direct comparison of %select{an array literal|a dictionary literal|" "a numeric literal|a boxed expression|}0 has undefined behavior">, InGroup; def err_missing_atsign_prefix : Error< "string literal must be prefixed by '@' ">; def warn_objc_string_literal_comparison : Warning< "direct comparison of a string literal has undefined behavior">, InGroup; def warn_concatenated_nsarray_literal : Warning< "concatenated NSString literal for an NSArray expression - " "possibly missing a comma">, InGroup; def note_objc_literal_comparison_isequal : Note< "use 'isEqual:' instead">; def warn_objc_collection_literal_element : Warning< "object of type %0 is not compatible with " "%select{array element type|dictionary key type|dictionary value type}1 %2">, InGroup; def err_swift_param_attr_not_swiftcall : Error< "'%0' parameter can only be used with swiftcall calling convention">; def err_swift_indirect_result_not_first : Error< "'swift_indirect_result' parameters must be first parameters of function">; def err_swift_error_result_not_after_swift_context : Error< "'swift_error_result' parameter must follow 'swift_context' parameter">; def err_swift_abi_parameter_wrong_type : Error< "'%0' parameter must have pointer%select{| to unqualified pointer}1 type; " "type here is %2">; def err_attribute_argument_invalid : Error< "%0 attribute argument is invalid: %select{max must be 0 since min is 0|" "min must not be greater than max}1">; def err_attribute_argument_is_zero : Error< "%0 attribute must be greater than 0">; def warn_attribute_argument_n_negative : Warning< "%0 attribute parameter %1 is negative and will be ignored">, InGroup; def err_property_function_in_objc_container : Error< "use of Objective-C property in function nested in Objective-C " "container not supported, move function outside its container">; let CategoryName = "Cocoa API Issue" in { def warn_objc_redundant_literal_use : Warning< "using %0 with a literal is redundant">, InGroup; } def err_attr_tlsmodel_arg : Error<"tls_model must be \"global-dynamic\", " "\"local-dynamic\", \"initial-exec\" or \"local-exec\"">; def err_tls_var_aligned_over_maximum : Error< "alignment (%0) of thread-local variable %1 is greater than the maximum supported " "alignment (%2) for a thread-local variable on this target">; def err_only_annotate_after_access_spec : Error< "access specifier can only have annotation attributes">; def err_attribute_section_invalid_for_target : Error< "argument to %select{'code_seg'|'section'}1 attribute is not valid for this target: %0">; def warn_mismatched_section : Warning< "%select{codeseg|section}0 does not match previous declaration">, InGroup
; def warn_attribute_section_on_redeclaration : Warning< "section attribute is specified on redeclared variable">, InGroup
; def err_mismatched_code_seg_base : Error< "derived class must specify the same code segment as its base classes">; def err_mismatched_code_seg_override : Error< "overriding virtual function must specify the same code segment as its overridden function">; def err_conflicting_codeseg_attribute : Error< "conflicting code segment specifiers">; def warn_duplicate_codeseg_attribute : Warning< "duplicate code segment specifiers">, InGroup
; def err_anonymous_property: Error< "anonymous property is not supported">; def err_property_is_variably_modified : Error< "property %0 has a variably modified type">; def err_no_accessor_for_property : Error< "no %select{getter|setter}0 defined for property %1">; def err_cannot_find_suitable_accessor : Error< "cannot find suitable %select{getter|setter}0 for property %1">; def warn_alloca_align_alignof : Warning< "second argument to __builtin_alloca_with_align is supposed to be in bits">, InGroup>; def err_alignment_too_small : Error< "requested alignment must be %0 or greater">; def err_alignment_too_big : Error< "requested alignment must be %0 or smaller">; def err_alignment_not_power_of_two : Error< "requested alignment is not a power of 2">; def err_alignment_dependent_typedef_name : Error< "requested alignment is dependent but declaration is not dependent">; def err_attribute_aligned_too_great : Error< "requested alignment must be %0 bytes or smaller">; def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< "%q0 redeclared without %1 attribute: previous %1 ignored">, InGroup; def warn_redeclaration_without_import_attribute : Warning< "%q0 redeclared without 'dllimport' attribute: 'dllexport' attribute added">, InGroup; def warn_dllimport_dropped_from_inline_function : Warning< "%q0 redeclared inline; %1 attribute ignored">, InGroup; def warn_attribute_ignored : Warning<"%0 attribute ignored">, InGroup; def warn_attribute_ignored_on_inline : Warning<"%0 attribute ignored on inline function">, InGroup; def warn_nocf_check_attribute_ignored : Warning<"'nocf_check' attribute ignored; use -fcf-protection to enable the attribute">, InGroup; def warn_attribute_after_definition_ignored : Warning< "attribute %0 after definition is ignored">, InGroup; def warn_unknown_attribute_ignored : Warning< "unknown attribute %0 ignored">, InGroup; def warn_cxx11_gnu_attribute_on_type : Warning< "attribute %0 ignored, because it cannot be applied to a type">, InGroup; def warn_unhandled_ms_attribute_ignored : Warning< "__declspec attribute %0 is not supported">, InGroup; def err_decl_attribute_invalid_on_stmt : Error< "%0 attribute cannot be applied to a statement">; def err_stmt_attribute_invalid_on_decl : Error< "%0 attribute cannot be applied to a declaration">; def warn_declspec_attribute_ignored : Warning< "attribute %0 is ignored, place it after " "\"%select{class|struct|interface|union|enum}1\" to apply attribute to " "type declaration">, InGroup; def warn_attribute_precede_definition : Warning< "attribute declaration must precede definition">, InGroup; def warn_attribute_void_function_method : Warning< "attribute %0 cannot be applied to " "%select{functions|Objective-C method}1 without return value">, InGroup; def warn_attribute_weak_on_field : Warning< "__weak attribute cannot be specified on a field declaration">, InGroup; def warn_gc_attribute_weak_on_local : Warning< "Objective-C GC does not allow weak variables on the stack">, InGroup; def warn_nsobject_attribute : Warning< "'NSObject' attribute may be put on a typedef only; attribute is ignored">, InGroup; def warn_independentclass_attribute : Warning< "'objc_independent_class' attribute may be put on a typedef only; " "attribute is ignored">, InGroup; def warn_ptr_independentclass_attribute : Warning< "'objc_independent_class' attribute may be put on Objective-C object " "pointer type only; attribute is ignored">, InGroup; def warn_attribute_weak_on_local : Warning< "__weak attribute cannot be specified on an automatic variable when ARC " "is not enabled">, InGroup; def warn_weak_identifier_undeclared : Warning< "weak identifier %0 never declared">; def err_attribute_weak_static : Error< "weak declaration cannot have internal linkage">; def err_attribute_selectany_non_extern_data : Error< "'selectany' can only be applied to data items with external linkage">; def err_declspec_thread_on_thread_variable : Error< "'__declspec(thread)' applied to variable that already has a " "thread-local storage specifier">; def err_attribute_dll_not_extern : Error< "%q0 must have external linkage when declared %q1">; def err_attribute_dll_thread_local : Error< "%q0 cannot be thread local when declared %q1">; def err_attribute_dll_lambda : Error< "lambda cannot be declared %0">; def warn_attribute_invalid_on_definition : Warning< "'%0' attribute cannot be specified on a definition">, InGroup; def err_attribute_dll_redeclaration : Error< "redeclaration of %q0 cannot add %q1 attribute">; def warn_attribute_dll_redeclaration : Warning< "redeclaration of %q0 should not add %q1 attribute">, InGroup>; def err_attribute_dllimport_function_definition : Error< "dllimport cannot be applied to non-inline function definition">; def err_attribute_dll_deleted : Error< "attribute %q0 cannot be applied to a deleted function">; def err_attribute_dllimport_data_definition : Error< "definition of dllimport data">; def err_attribute_dllimport_static_field_definition : Error< "definition of dllimport static field not allowed">; def warn_attribute_dllimport_static_field_definition : Warning< "definition of dllimport static field">, InGroup>; def warn_attribute_dllexport_explicit_instantiation_decl : Warning< "explicit instantiation declaration should not be 'dllexport'">, InGroup>; def warn_invalid_initializer_from_system_header : Warning< "invalid constructor form class in system header, should not be explicit">, InGroup>; def note_used_in_initialization_here : Note<"used in initialization here">; def err_attribute_dll_member_of_dll_class : Error< "attribute %q0 cannot be applied to member of %q1 class">; def warn_attribute_dll_instantiated_base_class : Warning< "propagating dll attribute to %select{already instantiated|explicitly specialized}0 " "base class template without dll attribute is not supported">, InGroup>, DefaultIgnore; def err_attribute_dll_ambiguous_default_ctor : Error< "'__declspec(dllexport)' cannot be applied to more than one default constructor in %0">; def err_attribute_weakref_not_static : Error< "weakref declaration must have internal linkage">; def err_attribute_weakref_not_global_context : Error< "weakref declaration of %0 must be in a global context">; def err_attribute_weakref_without_alias : Error< "weakref declaration of %0 must also have an alias attribute">; def err_alias_not_supported_on_darwin : Error < "aliases are not supported on darwin">; def err_alias_to_undefined : Error< "%select{alias|ifunc}0 must point to a defined %select{variable or |}1function">; def warn_alias_to_weak_alias : Warning< "%select{alias|ifunc}2 will always resolve to %0 even if weak definition of %1 is overridden">, InGroup; def warn_alias_with_section : Warning< "%select{alias|ifunc}1 will not be in section '%0' but in the same section as the %select{aliasee|resolver}2">, InGroup; def err_duplicate_mangled_name : Error< "definition with same mangled name '%0' as another definition">; def err_cyclic_alias : Error< "%select{alias|ifunc}0 definition is part of a cycle">; def err_ifunc_resolver_return : Error< "ifunc resolver function must return a pointer">; -def err_ifunc_resolver_params : Error< - "ifunc resolver function must have no parameters">; def warn_attribute_wrong_decl_type_str : Warning< "%0 attribute only applies to %1">, InGroup; def err_attribute_wrong_decl_type_str : Error< warn_attribute_wrong_decl_type_str.Text>; def warn_attribute_wrong_decl_type : Warning< "%0 attribute only applies to %select{" "functions" "|unions" "|variables and functions" "|functions and methods" "|functions, methods and blocks" "|functions, methods, and parameters" "|variables" "|variables and fields" "|variables, data members and tag types" "|types and namespaces" "|variables, functions and classes" "|kernel functions" "|non-K&R-style functions}1">, InGroup; def err_attribute_wrong_decl_type : Error; def warn_type_attribute_wrong_type : Warning< "'%0' only applies to %select{function|pointer|" "Objective-C object or block pointer}1 types; type here is %2">, InGroup; def warn_incomplete_encoded_type : Warning< "encoding of %0 type is incomplete because %1 component has unknown encoding">, InGroup>; def warn_gnu_inline_attribute_requires_inline : Warning< "'gnu_inline' attribute requires function to be marked 'inline'," " attribute ignored">, InGroup; def err_attribute_vecreturn_only_vector_member : Error< "the vecreturn attribute can only be used on a class or structure with one member, which must be a vector">; def err_attribute_vecreturn_only_pod_record : Error< "the vecreturn attribute can only be used on a POD (plain old data) class or structure (i.e. no virtual functions)">; def err_cconv_change : Error< "function declared '%0' here was previously declared " "%select{'%2'|without calling convention}1">; def warn_cconv_ignored : Warning< "calling convention %0 ignored for this target">, InGroup; def err_cconv_knr : Error< "function with no prototype cannot use the %0 calling convention">; def warn_cconv_knr : Warning< err_cconv_knr.Text>, InGroup>; def err_cconv_varargs : Error< "variadic function cannot use %0 calling convention">; def warn_cconv_varargs : Warning< "%0 calling convention ignored on variadic function">, InGroup; def warn_cconv_structors : Warning< "%0 calling convention ignored on constructor/destructor">, InGroup; def err_regparm_mismatch : Error<"function declared with regparm(%0) " "attribute was previously declared " "%plural{0:without the regparm|:with the regparm(%1)}1 attribute">; def err_function_attribute_mismatch : Error< "function declared with %0 attribute " "was previously declared without the %0 attribute">; def err_objc_precise_lifetime_bad_type : Error< "objc_precise_lifetime only applies to retainable types; type here is %0">; def warn_objc_precise_lifetime_meaningless : Error< "objc_precise_lifetime is not meaningful for " "%select{__unsafe_unretained|__autoreleasing}0 objects">; def err_invalid_pcs : Error<"invalid PCS type">; def warn_attribute_not_on_decl : Warning< "%0 attribute ignored when parsing type">, InGroup; def err_base_specifier_attribute : Error< "%0 attribute cannot be applied to a base specifier">; def err_invalid_attribute_on_virtual_function : Error< "%0 attribute cannot be applied to virtual functions">; def ext_cannot_use_trivial_abi : ExtWarn< "'trivial_abi' cannot be applied to %0">, InGroup; // Availability attribute def warn_availability_unknown_platform : Warning< "unknown platform %0 in availability macro">, InGroup; def warn_availability_version_ordering : Warning< "feature cannot be %select{introduced|deprecated|obsoleted}0 in %1 version " "%2 before it was %select{introduced|deprecated|obsoleted}3 in version %4; " "attribute ignored">, InGroup; def warn_mismatched_availability: Warning< "availability does not match previous declaration">, InGroup; def warn_mismatched_availability_override : Warning< "%select{|overriding }4method %select{introduced after|" "deprecated before|obsoleted before}0 " "%select{the protocol method it implements|overridden method}4 " "on %1 (%2 vs. %3)">, InGroup; def warn_mismatched_availability_override_unavail : Warning< "%select{|overriding }1method cannot be unavailable on %0 when " "%select{the protocol method it implements|its overridden method}1 is " "available">, InGroup; def warn_availability_on_static_initializer : Warning< "ignoring availability attribute %select{on '+load' method|" "with constructor attribute|with destructor attribute}0">, InGroup; def note_overridden_method : Note< "overridden method is here">; def note_protocol_method : Note< "protocol method is here">; def warn_unguarded_availability : Warning<"%0 is only available on %1 %2 or newer">, InGroup, DefaultIgnore; def warn_unguarded_availability_new : Warning, InGroup; def note_decl_unguarded_availability_silence : Note< "annotate %select{%1|anonymous %1}0 with an availability attribute to silence this warning">; def note_unguarded_available_silence : Note< "enclose %0 in %select{an @available|a __builtin_available}1 check to silence" " this warning">; def warn_at_available_unchecked_use : Warning< "%select{@available|__builtin_available}0 does not guard availability here; " "use if (%select{@available|__builtin_available}0) instead">, InGroup>; // Thread Safety Attributes def warn_invalid_capability_name : Warning< "invalid capability name '%0'; capability name must be 'mutex' or 'role'">, InGroup, DefaultIgnore; def warn_thread_attribute_ignored : Warning< "ignoring %0 attribute because its argument is invalid">, InGroup, DefaultIgnore; def warn_thread_attribute_argument_not_lockable : Warning< "%0 attribute requires arguments whose type is annotated " "with 'capability' attribute; type here is %1">, InGroup, DefaultIgnore; def warn_thread_attribute_decl_not_lockable : Warning< "%0 attribute can only be applied in a context annotated " "with 'capability(\"mutex\")' attribute">, InGroup, DefaultIgnore; def warn_thread_attribute_decl_not_pointer : Warning< "%0 only applies to pointer types; type here is %1">, InGroup, DefaultIgnore; def err_attribute_argument_out_of_range : Error< "%0 attribute parameter %1 is out of bounds: " "%plural{0:no parameters to index into|" "1:can only be 1, since there is one parameter|" ":must be between 1 and %2}2">; // Thread Safety Analysis def warn_unlock_but_no_lock : Warning<"releasing %0 '%1' that was not held">, InGroup, DefaultIgnore; def warn_unlock_kind_mismatch : Warning< "releasing %0 '%1' using %select{shared|exclusive}2 access, expected " "%select{shared|exclusive}3 access">, InGroup, DefaultIgnore; def warn_double_lock : Warning<"acquiring %0 '%1' that is already held">, InGroup, DefaultIgnore; def warn_no_unlock : Warning< "%0 '%1' is still held at the end of function">, InGroup, DefaultIgnore; def warn_expecting_locked : Warning< "expecting %0 '%1' to be held at the end of function">, InGroup, DefaultIgnore; // FIXME: improve the error message about locks not in scope def warn_lock_some_predecessors : Warning< "%0 '%1' is not held on every path through here">, InGroup, DefaultIgnore; def warn_expecting_lock_held_on_loop : Warning< "expecting %0 '%1' to be held at start of each loop">, InGroup, DefaultIgnore; def note_locked_here : Note<"%0 acquired here">; def warn_lock_exclusive_and_shared : Warning< "%0 '%1' is acquired exclusively and shared in the same scope">, InGroup, DefaultIgnore; def note_lock_exclusive_and_shared : Note< "the other acquisition of %0 '%1' is here">; def warn_variable_requires_any_lock : Warning< "%select{reading|writing}1 variable %0 requires holding " "%select{any mutex|any mutex exclusively}1">, InGroup, DefaultIgnore; def warn_var_deref_requires_any_lock : Warning< "%select{reading|writing}1 the value pointed to by %0 requires holding " "%select{any mutex|any mutex exclusively}1">, InGroup, DefaultIgnore; def warn_fun_excludes_mutex : Warning< "cannot call function '%1' while %0 '%2' is held">, InGroup, DefaultIgnore; def warn_cannot_resolve_lock : Warning< "cannot resolve lock expression">, InGroup, DefaultIgnore; def warn_acquired_before : Warning< "%0 '%1' must be acquired before '%2'">, InGroup, DefaultIgnore; def warn_acquired_before_after_cycle : Warning< "Cycle in acquired_before/after dependencies, starting with '%0'">, InGroup, DefaultIgnore; // Thread safety warnings negative capabilities def warn_acquire_requires_negative_cap : Warning< "acquiring %0 '%1' requires negative capability '%2'">, InGroup, DefaultIgnore; // Thread safety warnings on pass by reference def warn_guarded_pass_by_reference : Warning< "passing variable %1 by reference requires holding %0 " "%select{'%2'|'%2' exclusively}3">, InGroup, DefaultIgnore; def warn_pt_guarded_pass_by_reference : Warning< "passing the value that %1 points to by reference requires holding %0 " "%select{'%2'|'%2' exclusively}3">, InGroup, DefaultIgnore; // Imprecise thread safety warnings def warn_variable_requires_lock : Warning< "%select{reading|writing}3 variable %1 requires holding %0 " "%select{'%2'|'%2' exclusively}3">, InGroup, DefaultIgnore; def warn_var_deref_requires_lock : Warning< "%select{reading|writing}3 the value pointed to by %1 requires " "holding %0 %select{'%2'|'%2' exclusively}3">, InGroup, DefaultIgnore; def warn_fun_requires_lock : Warning< "calling function %1 requires holding %0 %select{'%2'|'%2' exclusively}3">, InGroup, DefaultIgnore; // Precise thread safety warnings def warn_variable_requires_lock_precise : Warning, InGroup, DefaultIgnore; def warn_var_deref_requires_lock_precise : Warning, InGroup, DefaultIgnore; def warn_fun_requires_lock_precise : Warning, InGroup, DefaultIgnore; def note_found_mutex_near_match : Note<"found near match '%0'">; // Verbose thread safety warnings def warn_thread_safety_verbose : Warning<"Thread safety verbose warning.">, InGroup, DefaultIgnore; def note_thread_warning_in_fun : Note<"Thread warning in function %0">; def note_guarded_by_declared_here : Note<"Guarded_by declared here.">; // Dummy warning that will trigger "beta" warnings from the analysis if enabled. def warn_thread_safety_beta : Warning<"Thread safety beta warning.">, InGroup, DefaultIgnore; // Consumed warnings def warn_use_in_invalid_state : Warning< "invalid invocation of method '%0' on object '%1' while it is in the '%2' " "state">, InGroup, DefaultIgnore; def warn_use_of_temp_in_invalid_state : Warning< "invalid invocation of method '%0' on a temporary object while it is in the " "'%1' state">, InGroup, DefaultIgnore; def warn_attr_on_unconsumable_class : Warning< "consumed analysis attribute is attached to member of class '%0' which isn't " "marked as consumable">, InGroup, DefaultIgnore; def warn_return_typestate_for_unconsumable_type : Warning< "return state set for an unconsumable type '%0'">, InGroup, DefaultIgnore; def warn_return_typestate_mismatch : Warning< "return value not in expected state; expected '%0', observed '%1'">, InGroup, DefaultIgnore; def warn_loop_state_mismatch : Warning< "state of variable '%0' must match at the entry and exit of loop">, InGroup, DefaultIgnore; def warn_param_return_typestate_mismatch : Warning< "parameter '%0' not in expected state when the function returns: expected " "'%1', observed '%2'">, InGroup, DefaultIgnore; def warn_param_typestate_mismatch : Warning< "argument not in expected state; expected '%0', observed '%1'">, InGroup, DefaultIgnore; // no_sanitize attribute def warn_unknown_sanitizer_ignored : Warning< "unknown sanitizer '%0' ignored">, InGroup; def warn_impcast_vector_scalar : Warning< "implicit conversion turns vector to scalar: %0 to %1">, InGroup, DefaultIgnore; def warn_impcast_complex_scalar : Warning< "implicit conversion discards imaginary component: %0 to %1">, InGroup, DefaultIgnore; def err_impcast_complex_scalar : Error< "implicit conversion from %0 to %1 is not permitted in C++">; def warn_impcast_float_precision : Warning< "implicit conversion loses floating-point precision: %0 to %1">, InGroup, DefaultIgnore; def warn_impcast_float_result_precision : Warning< "implicit conversion when assigning computation result loses floating-point precision: %0 to %1">, InGroup, DefaultIgnore; def warn_impcast_double_promotion : Warning< "implicit conversion increases floating-point precision: %0 to %1">, InGroup, DefaultIgnore; def warn_impcast_integer_sign : Warning< "implicit conversion changes signedness: %0 to %1">, InGroup, DefaultIgnore; def warn_impcast_integer_sign_conditional : Warning< "operand of ? changes signedness: %0 to %1">, InGroup, DefaultIgnore; def warn_impcast_integer_precision : Warning< "implicit conversion loses integer precision: %0 to %1">, InGroup, DefaultIgnore; def warn_impcast_integer_64_32 : Warning< "implicit conversion loses integer precision: %0 to %1">, InGroup, DefaultIgnore; def warn_impcast_integer_precision_constant : Warning< "implicit conversion from %2 to %3 changes value from %0 to %1">, InGroup; def warn_impcast_bitfield_precision_constant : Warning< "implicit truncation from %2 to bit-field changes value from %0 to %1">, InGroup; def warn_impcast_literal_float_to_integer : Warning< "implicit conversion from %0 to %1 changes value from %2 to %3">, InGroup; def warn_impcast_literal_float_to_integer_out_of_range : Warning< "implicit conversion of out of range value from %0 to %1 is undefined">, InGroup; def warn_impcast_float_integer : Warning< "implicit conversion turns floating-point number into integer: %0 to %1">, InGroup, DefaultIgnore; def warn_impcast_float_to_integer : Warning< "implicit conversion from %0 to %1 changes value from %2 to %3">, InGroup, DefaultIgnore; def warn_impcast_float_to_integer_out_of_range : Warning< "implicit conversion of out of range value from %0 to %1 is undefined">, InGroup, DefaultIgnore; def warn_impcast_float_to_integer_zero : Warning< "implicit conversion from %0 to %1 changes non-zero value from %2 to %3">, InGroup, DefaultIgnore; def warn_impcast_string_literal_to_bool : Warning< "implicit conversion turns string literal into bool: %0 to %1">, InGroup, DefaultIgnore; def warn_impcast_different_enum_types : Warning< "implicit conversion from enumeration type %0 to different enumeration type " "%1">, InGroup; def warn_impcast_bool_to_null_pointer : Warning< "initialization of pointer of type %0 to null from a constant boolean " "expression">, InGroup; def warn_non_literal_null_pointer : Warning< "expression which evaluates to zero treated as a null pointer constant of " "type %0">, InGroup; def warn_impcast_null_pointer_to_integer : Warning< "implicit conversion of %select{NULL|nullptr}0 constant to %1">, InGroup; def warn_impcast_floating_point_to_bool : Warning< "implicit conversion turns floating-point number into bool: %0 to %1">, InGroup; def ext_ms_impcast_fn_obj : ExtWarn< "implicit conversion between pointer-to-function and pointer-to-object is a " "Microsoft extension">, InGroup; def warn_impcast_pointer_to_bool : Warning< "address of%select{| function| array}0 '%1' will always evaluate to " "'true'">, InGroup; def warn_cast_nonnull_to_bool : Warning< "nonnull %select{function call|parameter}0 '%1' will evaluate to " "'true' on first encounter">, InGroup; def warn_this_bool_conversion : Warning< "'this' pointer cannot be null in well-defined C++ code; pointer may be " "assumed to always convert to true">, InGroup; def warn_address_of_reference_bool_conversion : Warning< "reference cannot be bound to dereferenced null pointer in well-defined C++ " "code; pointer may be assumed to always convert to true">, InGroup; def warn_null_pointer_compare : Warning< "comparison of %select{address of|function|array}0 '%1' %select{not |}2" "equal to a null pointer is always %select{true|false}2">, InGroup; def warn_nonnull_expr_compare : Warning< "comparison of nonnull %select{function call|parameter}0 '%1' " "%select{not |}2equal to a null pointer is '%select{true|false}2' on first " "encounter">, InGroup; def warn_this_null_compare : Warning< "'this' pointer cannot be null in well-defined C++ code; comparison may be " "assumed to always evaluate to %select{true|false}0">, InGroup; def warn_address_of_reference_null_compare : Warning< "reference cannot be bound to dereferenced null pointer in well-defined C++ " "code; comparison may be assumed to always evaluate to " "%select{true|false}0">, InGroup; def note_reference_is_return_value : Note<"%0 returns a reference">; def note_function_warning_silence : Note< "prefix with the address-of operator to silence this warning">; def note_function_to_function_call : Note< "suffix with parentheses to turn this into a function call">; def warn_impcast_objective_c_literal_to_bool : Warning< "implicit boolean conversion of Objective-C object literal always " "evaluates to true">, InGroup; def warn_cast_align : Warning< "cast from %0 to %1 increases required alignment from %2 to %3">, InGroup, DefaultIgnore; def warn_old_style_cast : Warning< "use of old-style cast">, InGroup, DefaultIgnore; // Separate between casts to void* and non-void* pointers. // Some APIs use (abuse) void* for something like a user context, // and often that value is an integer even if it isn't a pointer itself. // Having a separate warning flag allows users to control the warning // for their workflow. def warn_int_to_pointer_cast : Warning< "cast to %1 from smaller integer type %0">, InGroup; def warn_int_to_void_pointer_cast : Warning< "cast to %1 from smaller integer type %0">, InGroup; def warn_attribute_ignored_for_field_of_type : Warning< "%0 attribute ignored for field of type %1">, InGroup; def warn_no_underlying_type_specified_for_enum_bitfield : Warning< "enums in the Microsoft ABI are signed integers by default; consider giving " "the enum %0 an unsigned underlying type to make this code portable">, InGroup, DefaultIgnore; def warn_attribute_packed_for_bitfield : Warning< "'packed' attribute was ignored on bit-fields with single-byte alignment " "in older versions of GCC and Clang">, InGroup>; def warn_transparent_union_attribute_field_size_align : Warning< "%select{alignment|size}0 of field %1 (%2 bits) does not match the " "%select{alignment|size}0 of the first field in transparent union; " "transparent_union attribute ignored">, InGroup; def note_transparent_union_first_field_size_align : Note< "%select{alignment|size}0 of first field is %1 bits">; def warn_transparent_union_attribute_not_definition : Warning< "transparent_union attribute can only be applied to a union definition; " "attribute ignored">, InGroup; def warn_transparent_union_attribute_floating : Warning< "first field of a transparent union cannot have %select{floating point|" "vector}0 type %1; transparent_union attribute ignored">, InGroup; def warn_transparent_union_attribute_zero_fields : Warning< "transparent union definition must contain at least one field; " "transparent_union attribute ignored">, InGroup; def warn_attribute_type_not_supported : Warning< "%0 attribute argument not supported: %1">, InGroup; def warn_attribute_unknown_visibility : Warning<"unknown visibility %0">, InGroup; def warn_attribute_protected_visibility : Warning<"target does not support 'protected' visibility; using 'default'">, InGroup>; def err_mismatched_visibility: Error<"visibility does not match previous declaration">; def note_previous_attribute : Note<"previous attribute is here">; def note_conflicting_attribute : Note<"conflicting attribute is here">; def note_attribute : Note<"attribute is here">; def err_mismatched_ms_inheritance : Error< "inheritance model does not match %select{definition|previous declaration}0">; def warn_ignored_ms_inheritance : Warning< "inheritance model ignored on %select{primary template|partial specialization}0">, InGroup; def note_previous_ms_inheritance : Note< "previous inheritance model specified here">; def err_machine_mode : Error<"%select{unknown|unsupported}0 machine mode %1">; def err_mode_not_primitive : Error< "mode attribute only supported for integer and floating-point types">; def err_mode_wrong_type : Error< "type of machine mode does not match type of base type">; def warn_vector_mode_deprecated : Warning< "specifying vector types with the 'mode' attribute is deprecated; " "use the 'vector_size' attribute instead">, InGroup; def err_complex_mode_vector_type : Error< "type of machine mode does not support base vector types">; def err_enum_mode_vector_type : Error< "mode %0 is not supported for enumeration types">; def warn_attribute_nonnull_no_pointers : Warning< "'nonnull' attribute applied to function with no pointer arguments">, InGroup; def warn_attribute_nonnull_parm_no_args : Warning< "'nonnull' attribute when used on parameters takes no arguments">, InGroup; def note_declared_nonnull : Note< "declared %select{'returns_nonnull'|'nonnull'}0 here">; def warn_attribute_sentinel_named_arguments : Warning< "'sentinel' attribute requires named arguments">, InGroup; def warn_attribute_sentinel_not_variadic : Warning< "'sentinel' attribute only supported for variadic %select{functions|blocks}0">, InGroup; def err_attribute_sentinel_less_than_zero : Error< "'sentinel' parameter 1 less than zero">; def err_attribute_sentinel_not_zero_or_one : Error< "'sentinel' parameter 2 not 0 or 1">; def warn_cleanup_ext : Warning< "GCC does not allow the 'cleanup' attribute argument to be anything other " "than a simple identifier">, InGroup; def err_attribute_cleanup_arg_not_function : Error< "'cleanup' argument %select{|%1 |%1 }0is not a %select{||single }0function">; def err_attribute_cleanup_func_must_take_one_arg : Error< "'cleanup' function %0 must take 1 parameter">; def err_attribute_cleanup_func_arg_incompatible_type : Error< "'cleanup' function %0 parameter has " "%diff{type $ which is incompatible with type $|incompatible type}1,2">; def err_attribute_regparm_wrong_platform : Error< "'regparm' is not valid on this platform">; def err_attribute_regparm_invalid_number : Error< "'regparm' parameter must be between 0 and %0 inclusive">; def err_attribute_not_supported_in_lang : Error< "%0 attribute is not supported in %select{C|C++|Objective-C}1">; def err_attribute_not_supported_on_arch : Error<"%0 attribute is not supported on '%1'">; def warn_gcc_ignores_type_attr : Warning< "GCC does not allow the %0 attribute to be written on a type">, InGroup; // Clang-Specific Attributes def warn_attribute_iboutlet : Warning< "%0 attribute can only be applied to instance variables or properties">, InGroup; def err_iboutletcollection_type : Error< "invalid type %0 as argument of iboutletcollection attribute">; def err_iboutletcollection_builtintype : Error< "type argument of iboutletcollection attribute cannot be a builtin type">; def warn_iboutlet_object_type : Warning< "%select{instance variable|property}2 with %0 attribute must " "be an object type (invalid %1)">, InGroup; def warn_iboutletcollection_property_assign : Warning< "IBOutletCollection properties should be copy/strong and not assign">, InGroup; def err_attribute_overloadable_mismatch : Error< "redeclaration of %0 must %select{not |}1have the 'overloadable' attribute">; def note_attribute_overloadable_prev_overload : Note< "previous %select{unmarked |}0overload of function is here">; def err_attribute_overloadable_no_prototype : Error< "'overloadable' function %0 must have a prototype">; def err_attribute_overloadable_multiple_unmarked_overloads : Error< "at most one overload for a given name may lack the 'overloadable' " "attribute">; def warn_ns_attribute_wrong_return_type : Warning< "%0 attribute only applies to %select{functions|methods|properties}1 that " "return %select{an Objective-C object|a pointer|a non-retainable pointer}2">, InGroup; def err_ns_attribute_wrong_parameter_type : Error< "%0 attribute only applies to " "%select{Objective-C object|pointer|pointer-to-CF-pointer}1 parameters">; def warn_ns_attribute_wrong_parameter_type : Warning< "%0 attribute only applies to " "%select{Objective-C object|pointer|pointer-to-CF-pointer}1 parameters">, InGroup; def warn_objc_requires_super_protocol : Warning< "%0 attribute cannot be applied to %select{methods in protocols|dealloc}1">, InGroup>; def note_protocol_decl : Note< "protocol is declared here">; def note_protocol_decl_undefined : Note< "protocol %0 has no definition">; // objc_designated_initializer attribute diagnostics. def warn_objc_designated_init_missing_super_call : Warning< "designated initializer missing a 'super' call to a designated initializer of the super class">, InGroup; def note_objc_designated_init_marked_here : Note< "method marked as designated initializer of the class here">; def warn_objc_designated_init_non_super_designated_init_call : Warning< "designated initializer should only invoke a designated initializer on 'super'">, InGroup; def warn_objc_designated_init_non_designated_init_call : Warning< "designated initializer invoked a non-designated initializer">, InGroup; def warn_objc_secondary_init_super_init_call : Warning< "convenience initializer should not invoke an initializer on 'super'">, InGroup; def warn_objc_secondary_init_missing_init_call : Warning< "convenience initializer missing a 'self' call to another initializer">, InGroup; def warn_objc_implementation_missing_designated_init_override : Warning< "method override for the designated initializer of the superclass %objcinstance0 not found">, InGroup; // objc_bridge attribute diagnostics. def err_objc_attr_not_id : Error< "parameter of %0 attribute must be a single name of an Objective-C %select{class|protocol}1">; def err_objc_attr_typedef_not_id : Error< "parameter of %0 attribute must be 'id' when used on a typedef">; def err_objc_attr_typedef_not_void_pointer : Error< "'objc_bridge(id)' is only allowed on structs and typedefs of void pointers">; def err_objc_cf_bridged_not_interface : Error< "CF object of type %0 is bridged to %1, which is not an Objective-C class">; def err_objc_ns_bridged_invalid_cfobject : Error< "ObjectiveC object of type %0 is bridged to %1, which is not valid CF object">; def warn_objc_invalid_bridge : Warning< "%0 bridges to %1, not %2">, InGroup; def warn_objc_invalid_bridge_to_cf : Warning< "%0 cannot bridge to %1">, InGroup; // objc_bridge_related attribute diagnostics. def err_objc_bridged_related_invalid_class : Error< "could not find Objective-C class %0 to convert %1 to %2">; def err_objc_bridged_related_invalid_class_name : Error< "%0 must be name of an Objective-C class to be able to convert %1 to %2">; def err_objc_bridged_related_known_method : Error< "%0 must be explicitly converted to %1; use %select{%objcclass2|%objcinstance2}3 " "method for this conversion">; def err_objc_attr_protocol_requires_definition : Error< "attribute %0 can only be applied to @protocol definitions, not forward declarations">; // Function Parameter Semantic Analysis. def err_param_with_void_type : Error<"argument may not have 'void' type">; def err_void_only_param : Error< "'void' must be the first and only parameter if specified">; def err_void_param_qualified : Error< "'void' as parameter must not have type qualifiers">; def err_ident_list_in_fn_declaration : Error< "a parameter list without types is only allowed in a function definition">; def ext_param_not_declared : Extension< "parameter %0 was not declared, defaulting to type 'int'">; def err_param_default_argument : Error< "C does not support default arguments">; def err_param_default_argument_redefinition : Error< "redefinition of default argument">; def ext_param_default_argument_redefinition : ExtWarn< err_param_default_argument_redefinition.Text>, InGroup; def err_param_default_argument_missing : Error< "missing default argument on parameter">; def err_param_default_argument_missing_name : Error< "missing default argument on parameter %0">; def err_param_default_argument_references_param : Error< "default argument references parameter %0">; def err_param_default_argument_references_local : Error< "default argument references local variable %0 of enclosing function">; def err_param_default_argument_references_this : Error< "default argument references 'this'">; def err_param_default_argument_nonfunc : Error< "default arguments can only be specified for parameters in a function " "declaration">; def err_param_default_argument_template_redecl : Error< "default arguments cannot be added to a function template that has already " "been declared">; def err_param_default_argument_member_template_redecl : Error< "default arguments cannot be added to an out-of-line definition of a member " "of a %select{class template|class template partial specialization|nested " "class in a template}0">; def err_param_default_argument_on_parameter_pack : Error< "parameter pack cannot have a default argument">; def err_uninitialized_member_for_assign : Error< "cannot define the implicit copy assignment operator for %0, because " "non-static %select{reference|const}1 member %2 cannot use copy " "assignment operator">; def err_uninitialized_member_in_ctor : Error< "%select{constructor for %1|" "implicit default constructor for %1|" "cannot use constructor inherited from %1:}0 must explicitly " "initialize the %select{reference|const}2 member %3">; def err_default_arg_makes_ctor_special : Error< "addition of default argument on redeclaration makes this constructor a " "%select{default|copy|move}0 constructor">; def err_use_of_default_argument_to_function_declared_later : Error< "use of default argument to function %0 that is declared later in class %1">; def note_default_argument_declared_here : Note< "default argument declared here">; def err_recursive_default_argument : Error<"recursive evaluation of default argument">; def ext_param_promoted_not_compatible_with_prototype : ExtWarn< "%diff{promoted type $ of K&R function parameter is not compatible with the " "parameter type $|promoted type of K&R function parameter is not compatible " "with parameter type}0,1 declared in a previous prototype">, InGroup; // C++ Overloading Semantic Analysis. def err_ovl_diff_return_type : Error< "functions that differ only in their return type cannot be overloaded">; def err_ovl_static_nonstatic_member : Error< "static and non-static member functions with the same parameter types " "cannot be overloaded">; def err_ovl_no_viable_function_in_call : Error< "no matching function for call to %0">; def err_ovl_no_viable_member_function_in_call : Error< "no matching member function for call to %0">; def err_ovl_ambiguous_call : Error< "call to %0 is ambiguous">; def err_ovl_deleted_call : Error< "call to %select{unavailable|deleted}0 function %1%2">; def err_ovl_ambiguous_member_call : Error< "call to member function %0 is ambiguous">; def err_ovl_deleted_member_call : Error< "call to %select{unavailable|deleted}0 member function %1%2">; def note_ovl_too_many_candidates : Note< "remaining %0 candidate%s0 omitted; " "pass -fshow-overloads=all to show them">; def select_ovl_candidate_kind : TextSubstitution< "%select{function|function|constructor|" "constructor (the implicit default constructor)|" "constructor (the implicit copy constructor)|" "constructor (the implicit move constructor)|" "function (the implicit copy assignment operator)|" "function (the implicit move assignment operator)|" "inherited constructor}0%select{| template| %2}1">; def note_ovl_candidate : Note< "candidate %sub{select_ovl_candidate_kind}0,1,3" "%select{| has different class%diff{ (expected $ but has $)|}5,6" "| has different number of parameters (expected %5 but has %6)" "| has type mismatch at %ordinal5 parameter" "%diff{ (expected $ but has $)|}6,7" "| has different return type%diff{ ($ expected but has $)|}5,6" "| has different qualifiers (expected " "%select{none|const|restrict|const and restrict|volatile|const and volatile" "|volatile and restrict|const, volatile, and restrict}5 but found " "%select{none|const|restrict|const and restrict|volatile|const and volatile" "|volatile and restrict|const, volatile, and restrict}6)" "| has different exception specification}4">; def note_ovl_candidate_inherited_constructor : Note< "constructor from base class %0 inherited here">; def note_ovl_candidate_inherited_constructor_slice : Note< "candidate %select{constructor|template}0 ignored: " "inherited constructor cannot be used to %select{copy|move}1 object">; def note_ovl_candidate_illegal_constructor : Note< "candidate %select{constructor|template}0 ignored: " "instantiation %select{takes|would take}0 its own class type by value">; def note_ovl_candidate_bad_deduction : Note< "candidate template ignored: failed template argument deduction">; def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: " "couldn't infer template argument %0">; def note_ovl_candidate_incomplete_deduction_pack : Note<"candidate template ignored: " "deduced too few arguments for expanded pack %0; no argument for %ordinal1 " "expanded parameter in deduced argument pack %2">; def note_ovl_candidate_inconsistent_deduction : Note< "candidate template ignored: deduced conflicting %select{types|values|" "templates}0 for parameter %1%diff{ ($ vs. $)|}2,3">; def note_ovl_candidate_inconsistent_deduction_types : Note< "candidate template ignored: deduced values %diff{" "of conflicting types for parameter %0 (%1 of type $ vs. %3 of type $)|" "%1 and %3 of conflicting types for parameter %0}2,4">; def note_ovl_candidate_explicit_arg_mismatch_named : Note< "candidate template ignored: invalid explicitly-specified argument " "for template parameter %0">; def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note< "candidate template ignored: invalid explicitly-specified argument " "for %ordinal0 template parameter">; def note_ovl_candidate_instantiation_depth : Note< "candidate template ignored: substitution exceeded maximum template " "instantiation depth">; def note_ovl_candidate_underqualified : Note< "candidate template ignored: cannot deduce a type for %0 that would " "make %2 equal %1">; def note_ovl_candidate_substitution_failure : Note< "candidate template ignored: substitution failure%0%1">; def note_ovl_candidate_disabled_by_enable_if : Note< "candidate template ignored: disabled by %0%1">; def note_ovl_candidate_disabled_by_requirement : Note< "candidate template ignored: requirement '%0' was not satisfied%1">; def note_ovl_candidate_has_pass_object_size_params: Note< "candidate address cannot be taken because parameter %0 has " "pass_object_size attribute">; def err_diagnose_if_succeeded : Error<"%0">; def warn_diagnose_if_succeeded : Warning<"%0">, InGroup, ShowInSystemHeader; def note_ovl_candidate_disabled_by_function_cond_attr : Note< "candidate disabled: %0">; def note_ovl_candidate_disabled_by_extension : Note< "candidate disabled due to OpenCL extension">; def err_addrof_function_disabled_by_enable_if_attr : Error< "cannot take address of function %0 because it has one or more " "non-tautological enable_if conditions">; def note_addrof_ovl_candidate_disabled_by_enable_if_attr : Note< "candidate function made ineligible by enable_if">; def note_ovl_candidate_deduced_mismatch : Note< "candidate template ignored: deduced type " "%diff{$ of %select{|element of }4%ordinal0 parameter does not match " "adjusted type $ of %select{|element of }4argument" "|of %select{|element of }4%ordinal0 parameter does not match " "adjusted type of %select{|element of }4argument}1,2%3">; def note_ovl_candidate_non_deduced_mismatch : Note< "candidate template ignored: could not match %diff{$ against $|types}0,1">; // This note is needed because the above note would sometimes print two // different types with the same name. Remove this note when the above note // can handle that case properly. def note_ovl_candidate_non_deduced_mismatch_qualified : Note< "candidate template ignored: could not match %q0 against %q1">; // Note that we don't treat templates differently for this diagnostic. def note_ovl_candidate_arity : Note<"candidate " "%sub{select_ovl_candidate_kind}0,1,2 not viable: " "requires%select{ at least| at most|}3 %4 argument%s4, but %5 " "%plural{1:was|:were}5 provided">; def note_ovl_candidate_arity_one : Note<"candidate " "%sub{select_ovl_candidate_kind}0,1,2 not viable: " "%select{requires at least|allows at most single|requires single}3 " "argument %4, but %plural{0:no|:%5}5 arguments were provided">; def note_ovl_candidate_deleted : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 has been " "%select{explicitly made unavailable|explicitly deleted|" "implicitly deleted}3">; // Giving the index of the bad argument really clutters this message, and // it's relatively unimportant because 1) it's generally obvious which // argument(s) are of the given object type and 2) the fix is usually // to complete the type, which doesn't involve changes to the call line // anyway. If people complain, we can change it. def note_ovl_candidate_bad_conv_incomplete : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "cannot convert argument of incomplete type " "%diff{$ to $|to parameter type}3,4 for " "%select{%ordinal6 argument|object argument}5" "%select{|; dereference the argument with *|" "; take the address of the argument with &|" "; remove *|" "; remove &}7">; def note_ovl_candidate_bad_list_argument : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "cannot convert initializer list argument to %4">; def note_ovl_candidate_bad_overload : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "no overload of %4 matching %3 for %ordinal5 argument">; def note_ovl_candidate_bad_conv : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "no known conversion " "%diff{from $ to $|from argument type to parameter type}3,4 for " "%select{%ordinal6 argument|object argument}5" "%select{|; dereference the argument with *|" "; take the address of the argument with &|" "; remove *|" "; remove &}7">; def note_ovl_candidate_bad_arc_conv : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "cannot implicitly convert argument " "%diff{of type $ to $|type to parameter type}3,4 for " "%select{%ordinal6 argument|object argument}5 under ARC">; def note_ovl_candidate_bad_lvalue : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "expects an l-value for " "%select{%ordinal4 argument|object argument}3">; def note_ovl_candidate_bad_addrspace : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "address space mismatch in %select{%ordinal6|'this'}5 argument (%3), " "parameter type must be %4">; def note_ovl_candidate_bad_gc : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "%select{%ordinal7|'this'}6 argument (%3) has %select{no|__weak|__strong}4 " "ownership, but parameter has %select{no|__weak|__strong}5 ownership">; def note_ovl_candidate_bad_ownership : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "%select{%ordinal7|'this'}6 argument (%3) has " "%select{no|__unsafe_unretained|__strong|__weak|__autoreleasing}4 ownership," " but parameter has %select{no|__unsafe_unretained|__strong|__weak|" "__autoreleasing}5 ownership">; def note_ovl_candidate_bad_cvr_this : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "'this' argument has type %3, but method is not marked " "%select{const|restrict|const or restrict|volatile|const or volatile|" "volatile or restrict|const, volatile, or restrict}4">; def note_ovl_candidate_bad_cvr : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "%ordinal5 argument (%3) would lose " "%select{const|restrict|const and restrict|volatile|const and volatile|" "volatile and restrict|const, volatile, and restrict}4 qualifier" "%select{||s||s|s|s}4">; def note_ovl_candidate_bad_unaligned : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "%ordinal5 argument (%3) would lose __unaligned qualifier">; def note_ovl_candidate_bad_base_to_derived_conv : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "cannot %select{convert from|convert from|bind}3 " "%select{base class pointer|superclass|base class object of type}3 %4 to " "%select{derived class pointer|subclass|derived class reference}3 %5 for " "%ordinal6 argument">; def note_ovl_candidate_bad_target : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "call to " "%select{__device__|__global__|__host__|__host__ __device__|invalid}3 function from" " %select{__device__|__global__|__host__|__host__ __device__|invalid}4 function">; def note_implicit_member_target_infer_collision : Note< "implicit %sub{select_special_member_kind}0 inferred target collision: call to both " "%select{__device__|__global__|__host__|__host__ __device__}1 and " "%select{__device__|__global__|__host__|__host__ __device__}2 members">; def note_ambiguous_type_conversion: Note< "because of ambiguity in conversion %diff{of $ to $|between types}0,1">; def note_ovl_builtin_binary_candidate : Note< "built-in candidate %0">; def note_ovl_builtin_unary_candidate : Note< "built-in candidate %0">; def err_ovl_no_viable_function_in_init : Error< "no matching constructor for initialization of %0">; def err_ovl_no_conversion_in_cast : Error< "cannot convert %1 to %2 without a conversion operator">; def err_ovl_no_viable_conversion_in_cast : Error< "no matching conversion for %select{|static_cast|reinterpret_cast|" "dynamic_cast|C-style cast|functional-style cast}0 from %1 to %2">; def err_ovl_ambiguous_conversion_in_cast : Error< "ambiguous conversion for %select{|static_cast|reinterpret_cast|" "dynamic_cast|C-style cast|functional-style cast}0 from %1 to %2">; def err_ovl_deleted_conversion_in_cast : Error< "%select{|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" "functional-style cast}0 from %1 to %2 uses deleted function">; def err_ovl_ambiguous_init : Error<"call to constructor of %0 is ambiguous">; def err_ref_init_ambiguous : Error< "reference initialization of type %0 with initializer of type %1 is ambiguous">; def err_ovl_deleted_init : Error< "call to %select{unavailable|deleted}0 constructor of %1">; def err_ovl_deleted_special_init : Error< "call to implicitly-deleted %select{default constructor|copy constructor|" "move constructor|copy assignment operator|move assignment operator|" "destructor|function}0 of %1">; def err_ovl_ambiguous_oper_unary : Error< "use of overloaded operator '%0' is ambiguous (operand type %1)">; def err_ovl_ambiguous_oper_binary : Error< "use of overloaded operator '%0' is ambiguous (with operand types %1 and %2)">; def err_ovl_no_viable_oper : Error<"no viable overloaded '%0'">; def note_assign_lhs_incomplete : Note<"type %0 is incomplete">; def err_ovl_deleted_oper : Error< "overload resolution selected %select{unavailable|deleted}0 operator '%1'%2">; def err_ovl_deleted_special_oper : Error< "object of type %0 cannot be %select{constructed|copied|moved|assigned|" "assigned|destroyed}1 because its %sub{select_special_member_kind}1 is implicitly deleted">; def err_ovl_no_viable_subscript : Error<"no viable overloaded operator[] for type %0">; def err_ovl_no_oper : Error<"type %0 does not provide a %select{subscript|call}1 operator">; def err_ovl_unresolvable : Error< "reference to %select{overloaded|multiversioned}1 function could not be " "resolved; did you mean to call it%select{| with no arguments}0?">; def err_bound_member_function : Error< "reference to non-static member function must be called" "%select{|; did you mean to call it with no arguments?}0">; def note_possible_target_of_call : Note<"possible target for call">; def err_ovl_no_viable_object_call : Error< "no matching function for call to object of type %0">; def err_ovl_ambiguous_object_call : Error< "call to object of type %0 is ambiguous">; def err_ovl_deleted_object_call : Error< "call to %select{unavailable|deleted}0 function call operator in type %1%2">; def note_ovl_surrogate_cand : Note<"conversion candidate of type %0">; def err_member_call_without_object : Error< "call to non-static member function without an object argument">; // C++ Address of Overloaded Function def err_addr_ovl_no_viable : Error< "address of overloaded function %0 does not match required type %1">; def err_addr_ovl_ambiguous : Error< "address of overloaded function %0 is ambiguous">; def err_addr_ovl_not_func_ptrref : Error< "address of overloaded function %0 cannot be converted to type %1">; def err_addr_ovl_no_qualifier : Error< "cannot form member pointer of type %0 without '&' and class name">; // C++11 Literal Operators def err_ovl_no_viable_literal_operator : Error< "no matching literal operator for call to %0" "%select{| with argument of type %2| with arguments of types %2 and %3}1" "%select{| or 'const char *'}4" "%select{|, and no matching literal operator template}5">; // C++ Template Declarations def err_template_param_shadow : Error< "declaration of %0 shadows template parameter">; def note_template_param_here : Note<"template parameter is declared here">; def warn_template_export_unsupported : Warning< "exported templates are unsupported">; def err_template_outside_namespace_or_class_scope : Error< "templates can only be declared in namespace or class scope">; def err_template_inside_local_class : Error< "templates cannot be declared inside of a local class">; def err_template_linkage : Error<"templates must have C++ linkage">; def err_template_typedef : Error<"a typedef cannot be a template">; def err_template_unnamed_class : Error< "cannot declare a class template with no name">; def err_template_param_list_different_arity : Error< "%select{too few|too many}0 template parameters in template " "%select{|template parameter }1redeclaration">; def note_template_param_list_different_arity : Note< "%select{too few|too many}0 template parameters in template template " "argument">; def note_template_prev_declaration : Note< "previous template %select{declaration|template parameter}0 is here">; def err_template_param_different_kind : Error< "template parameter has a different kind in template " "%select{|template parameter }0redeclaration">; def note_template_param_different_kind : Note< "template parameter has a different kind in template argument">; def err_invalid_decl_specifier_in_nontype_parm : Error< "invalid declaration specifier in template non-type parameter">; def err_template_nontype_parm_different_type : Error< "template non-type parameter has a different type %0 in template " "%select{|template parameter }1redeclaration">; def note_template_nontype_parm_different_type : Note< "template non-type parameter has a different type %0 in template argument">; def note_template_nontype_parm_prev_declaration : Note< "previous non-type template parameter with type %0 is here">; def err_template_nontype_parm_bad_type : Error< "a non-type template parameter cannot have type %0">; def warn_cxx14_compat_template_nontype_parm_auto_type : Warning< "non-type template parameters declared with %0 are incompatible with C++ " "standards before C++17">, DefaultIgnore, InGroup; def err_template_param_default_arg_redefinition : Error< "template parameter redefines default argument">; def note_template_param_prev_default_arg : Note< "previous default template argument defined here">; def err_template_param_default_arg_missing : Error< "template parameter missing a default argument">; def ext_template_parameter_default_in_function_template : ExtWarn< "default template arguments for a function template are a C++11 extension">, InGroup; def warn_cxx98_compat_template_parameter_default_in_function_template : Warning< "default template arguments for a function template are incompatible with C++98">, InGroup, DefaultIgnore; def err_template_parameter_default_template_member : Error< "cannot add a default template argument to the definition of a member of a " "class template">; def err_template_parameter_default_friend_template : Error< "default template argument not permitted on a friend template">; def err_template_template_parm_no_parms : Error< "template template parameter must have its own template parameters">; def ext_variable_template : ExtWarn<"variable templates are a C++14 extension">, InGroup; def warn_cxx11_compat_variable_template : Warning< "variable templates are incompatible with C++ standards before C++14">, InGroup, DefaultIgnore; def err_template_variable_noparams : Error< "extraneous 'template<>' in declaration of variable %0">; def err_template_member : Error<"member %0 declared as a template">; def err_template_member_noparams : Error< "extraneous 'template<>' in declaration of member %0">; def err_template_tag_noparams : Error< "extraneous 'template<>' in declaration of %0 %1">; // C++ Template Argument Lists def err_template_missing_args : Error< "use of " "%select{class template|function template|variable template|alias template|" "template template parameter|template}0 %1 requires template arguments">; def err_template_arg_list_different_arity : Error< "%select{too few|too many}0 template arguments for " "%select{class template|function template|variable template|alias template|" "template template parameter|template}1 %2">; def note_template_decl_here : Note<"template is declared here">; def err_template_arg_must_be_type : Error< "template argument for template type parameter must be a type">; def err_template_arg_must_be_type_suggest : Error< "template argument for template type parameter must be a type; " "did you forget 'typename'?">; def ext_ms_template_type_arg_missing_typename : ExtWarn< "template argument for template type parameter must be a type; " "omitted 'typename' is a Microsoft extension">, InGroup; def err_template_arg_must_be_expr : Error< "template argument for non-type template parameter must be an expression">; def err_template_arg_nontype_ambig : Error< "template argument for non-type template parameter is treated as function type %0">; def err_template_arg_must_be_template : Error< "template argument for template template parameter must be a class template%select{| or type alias template}0">; def ext_template_arg_local_type : ExtWarn< "template argument uses local type %0">, InGroup; def ext_template_arg_unnamed_type : ExtWarn< "template argument uses unnamed type">, InGroup; def warn_cxx98_compat_template_arg_local_type : Warning< "local type %0 as template argument is incompatible with C++98">, InGroup, DefaultIgnore; def warn_cxx98_compat_template_arg_unnamed_type : Warning< "unnamed type as template argument is incompatible with C++98">, InGroup, DefaultIgnore; def note_template_unnamed_type_here : Note< "unnamed type used in template argument was declared here">; def err_template_arg_overload_type : Error< "template argument is the type of an unresolved overloaded function">; def err_template_arg_not_valid_template : Error< "template argument does not refer to a class or alias template, or template " "template parameter">; def note_template_arg_refers_here_func : Note< "template argument refers to function template %0, here">; def err_template_arg_template_params_mismatch : Error< "template template argument has different template parameters than its " "corresponding template template parameter">; def err_template_arg_not_integral_or_enumeral : Error< "non-type template argument of type %0 must have an integral or enumeration" " type">; def err_template_arg_not_ice : Error< "non-type template argument of type %0 is not an integral constant " "expression">; def err_template_arg_not_address_constant : Error< "non-type template argument of type %0 is not a constant expression">; def warn_cxx98_compat_template_arg_null : Warning< "use of null pointer as non-type template argument is incompatible with " "C++98">, InGroup, DefaultIgnore; def err_template_arg_untyped_null_constant : Error< "null non-type template argument must be cast to template parameter type %0">; def err_template_arg_wrongtype_null_constant : Error< "null non-type template argument of type %0 does not match template parameter " "of type %1">; def err_non_type_template_parm_type_deduction_failure : Error< "non-type template parameter %0 with type %1 has incompatible initializer of type %2">; def err_deduced_non_type_template_arg_type_mismatch : Error< "deduced non-type template argument does not have the same type as the " "corresponding template parameter%diff{ ($ vs $)|}0,1">; def err_non_type_template_arg_subobject : Error< "non-type template argument refers to subobject '%0'">; def err_non_type_template_arg_addr_label_diff : Error< "template argument / label address difference / what did you expect?">; def err_template_arg_not_convertible : Error< "non-type template argument of type %0 cannot be converted to a value " "of type %1">; def warn_template_arg_negative : Warning< "non-type template argument with value '%0' converted to '%1' for unsigned " "template parameter of type %2">, InGroup, DefaultIgnore; def warn_template_arg_too_large : Warning< "non-type template argument value '%0' truncated to '%1' for " "template parameter of type %2">, InGroup, DefaultIgnore; def err_template_arg_no_ref_bind : Error< "non-type template parameter of reference type " "%diff{$ cannot bind to template argument of type $" "|cannot bind to template of incompatible argument type}0,1">; def err_template_arg_ref_bind_ignores_quals : Error< "reference binding of non-type template parameter " "%diff{of type $ to template argument of type $|to template argument}0,1 " "ignores qualifiers">; def err_template_arg_not_decl_ref : Error< "non-type template argument does not refer to any declaration">; def err_template_arg_not_address_of : Error< "non-type template argument for template parameter of pointer type %0 must " "have its address taken">; def err_template_arg_address_of_non_pointer : Error< "address taken in non-type template argument for template parameter of " "reference type %0">; def err_template_arg_reference_var : Error< "non-type template argument of reference type %0 is not an object">; def err_template_arg_field : Error< "non-type template argument refers to non-static data member %0">; def err_template_arg_method : Error< "non-type template argument refers to non-static member function %0">; def err_template_arg_object_no_linkage : Error< "non-type template argument refers to %select{function|object}0 %1 that " "does not have linkage">; def warn_cxx98_compat_template_arg_object_internal : Warning< "non-type template argument referring to %select{function|object}0 %1 with " "internal linkage is incompatible with C++98">, InGroup, DefaultIgnore; def ext_template_arg_object_internal : ExtWarn< "non-type template argument referring to %select{function|object}0 %1 with " "internal linkage is a C++11 extension">, InGroup; def err_template_arg_thread_local : Error< "non-type template argument refers to thread-local object">; def note_template_arg_internal_object : Note< "non-type template argument refers to %select{function|object}0 here">; def note_template_arg_refers_here : Note< "non-type template argument refers here">; def err_template_arg_not_object_or_func : Error< "non-type template argument does not refer to an object or function">; def err_template_arg_not_pointer_to_member_form : Error< "non-type template argument is not a pointer to member constant">; def err_template_arg_member_ptr_base_derived_not_supported : Error< "sorry, non-type template argument of pointer-to-member type %1 that refers " "to member %q0 of a different class is not supported yet">; def ext_template_arg_extra_parens : ExtWarn< "address non-type template argument cannot be surrounded by parentheses">; def warn_cxx98_compat_template_arg_extra_parens : Warning< "redundant parentheses surrounding address non-type template argument are " "incompatible with C++98">, InGroup, DefaultIgnore; def err_pointer_to_member_type : Error< "invalid use of pointer to member type after %select{.*|->*}0">; def err_pointer_to_member_call_drops_quals : Error< "call to pointer to member function of type %0 drops '%1' qualifier%s2">; def err_pointer_to_member_oper_value_classify: Error< "pointer-to-member function type %0 can only be called on an " "%select{rvalue|lvalue}1">; def ext_pointer_to_const_ref_member_on_rvalue : Extension< "invoking a pointer to a 'const &' member function on an rvalue is a C++2a extension">, InGroup, SFINAEFailure; def warn_cxx17_compat_pointer_to_const_ref_member_on_rvalue : Warning< "invoking a pointer to a 'const &' member function on an rvalue is " "incompatible with C++ standards before C++2a">, InGroup, DefaultIgnore; def ext_ms_deref_template_argument: ExtWarn< "non-type template argument containing a dereference operation is a " "Microsoft extension">, InGroup; def ext_ms_delayed_template_argument: ExtWarn< "using the undeclared type %0 as a default template argument is a " "Microsoft extension">, InGroup; def err_template_arg_deduced_incomplete_pack : Error< "deduced incomplete pack %0 for template parameter %1">; // C++ template specialization def err_template_spec_unknown_kind : Error< "can only provide an explicit specialization for a class template, function " "template, variable template, or a member function, static data member, " "%select{or member class|member class, or member enumeration}0 of a " "class template">; def note_specialized_entity : Note< "explicitly specialized declaration is here">; def note_explicit_specialization_declared_here : Note< "explicit specialization declared here">; def err_template_spec_decl_function_scope : Error< "explicit specialization of %0 in function scope">; def err_template_spec_decl_friend : Error< "cannot declare an explicit specialization in a friend">; def err_template_spec_redecl_out_of_scope : Error< "%select{class template|class template partial|variable template|" "variable template partial|function template|member " "function|static data member|member class|member enumeration}0 " "specialization of %1 not in %select{a namespace enclosing %2|" "class %2 or an enclosing namespace}3">; def ext_ms_template_spec_redecl_out_of_scope: ExtWarn< "%select{class template|class template partial|variable template|" "variable template partial|function template|member " "function|static data member|member class|member enumeration}0 " "specialization of %1 not in %select{a namespace enclosing %2|" "class %2 or an enclosing namespace}3 " "is a Microsoft extension">, InGroup; def err_template_spec_redecl_global_scope : Error< "%select{class template|class template partial|variable template|" "variable template partial|function template|member " "function|static data member|member class|member enumeration}0 " "specialization of %1 must occur at global scope">; def err_spec_member_not_instantiated : Error< "specialization of member %q0 does not specialize an instantiated member">; def note_specialized_decl : Note<"attempt to specialize declaration here">; def err_specialization_after_instantiation : Error< "explicit specialization of %0 after instantiation">; def note_instantiation_required_here : Note< "%select{implicit|explicit}0 instantiation first required here">; def err_template_spec_friend : Error< "template specialization declaration cannot be a friend">; def err_template_spec_default_arg : Error< "default argument not permitted on an explicit " "%select{instantiation|specialization}0 of function %1">; def err_not_class_template_specialization : Error< "cannot specialize a %select{dependent template|template template " "parameter}0">; def ext_explicit_specialization_storage_class : ExtWarn< "explicit specialization cannot have a storage class">; def err_explicit_specialization_inconsistent_storage_class : Error< "explicit specialization has extraneous, inconsistent storage class " "'%select{none|extern|static|__private_extern__|auto|register}0'">; def err_dependent_function_template_spec_no_match : Error< "no candidate function template was found for dependent" " friend function template specialization">; def note_dependent_function_template_spec_discard_reason : Note< "candidate ignored: %select{not a function template" "|not a member of the enclosing namespace;" " did you mean to explicitly qualify the specialization?}0">; // C++ class template specializations and out-of-line definitions def err_template_spec_needs_header : Error< "template specialization requires 'template<>'">; def err_template_spec_needs_template_parameters : Error< "template specialization or definition requires a template parameter list " "corresponding to the nested type %0">; def err_template_param_list_matches_nontemplate : Error< "template parameter list matching the non-templated nested type %0 should " "be empty ('template<>')">; def err_alias_template_extra_headers : Error< "extraneous template parameter list in alias template declaration">; def err_template_spec_extra_headers : Error< "extraneous template parameter list in template specialization or " "out-of-line template definition">; def warn_template_spec_extra_headers : Warning< "extraneous template parameter list in template specialization">; def note_explicit_template_spec_does_not_need_header : Note< "'template<>' header not required for explicitly-specialized class %0 " "declared here">; def err_template_qualified_declarator_no_match : Error< "nested name specifier '%0' for declaration does not refer into a class, " "class template or class template partial specialization">; def err_specialize_member_of_template : Error< "cannot specialize %select{|(with 'template<>') }0a member of an " "unspecialized template">; // C++ Class Template Partial Specialization def err_default_arg_in_partial_spec : Error< "default template argument in a class template partial specialization">; def err_dependent_non_type_arg_in_partial_spec : Error< "type of specialized non-type template argument depends on a template " "parameter of the partial specialization">; def note_dependent_non_type_default_arg_in_partial_spec : Note< "template parameter is used in default argument declared here">; def err_dependent_typed_non_type_arg_in_partial_spec : Error< "non-type template argument specializes a template parameter with " "dependent type %0">; def err_partial_spec_args_match_primary_template : Error< "%select{class|variable}0 template partial specialization does not " "specialize any template argument; to %select{declare|define}1 the " "primary template, remove the template argument list">; def ext_partial_spec_not_more_specialized_than_primary : ExtWarn< "%select{class|variable}0 template partial specialization is not " "more specialized than the primary template">, DefaultError, InGroup>; def note_partial_spec_not_more_specialized_than_primary : Note<"%0">; def ext_partial_specs_not_deducible : ExtWarn< "%select{class|variable}0 template partial specialization contains " "%select{a template parameter|template parameters}1 that cannot be " "deduced; this partial specialization will never be used">, DefaultError, InGroup>; def note_non_deducible_parameter : Note< "non-deducible template parameter %0">; def err_partial_spec_ordering_ambiguous : Error< "ambiguous partial specializations of %0">; def note_partial_spec_match : Note<"partial specialization matches %0">; def err_partial_spec_redeclared : Error< "class template partial specialization %0 cannot be redeclared">; def note_partial_specialization_declared_here : Note< "explicit specialization declared here">; def note_prev_partial_spec_here : Note< "previous declaration of class template partial specialization %0 is here">; def err_partial_spec_fully_specialized : Error< "partial specialization of %0 does not use any of its template parameters">; // C++ Variable Template Partial Specialization def err_var_partial_spec_redeclared : Error< "variable template partial specialization %0 cannot be redefined">; def note_var_prev_partial_spec_here : Note< "previous declaration of variable template partial specialization is here">; def err_var_spec_no_template : Error< "no variable template matches%select{| partial}0 specialization">; def err_var_spec_no_template_but_method : Error< "no variable template matches specialization; " "did you mean to use %0 as function template instead?">; // C++ Function template specializations def err_function_template_spec_no_match : Error< "no function template matches function template specialization %0">; def err_function_template_spec_ambiguous : Error< "function template specialization %0 ambiguously refers to more than one " "function template; explicitly specify%select{| additional}1 template " "arguments to identify a particular function template">; def note_function_template_spec_matched : Note< "function template %q0 matches specialization %1">; def err_function_template_partial_spec : Error< "function template partial specialization is not allowed">; // C++ Template Instantiation def err_template_recursion_depth_exceeded : Error< "recursive template instantiation exceeded maximum depth of %0">, DefaultFatal, NoSFINAE; def note_template_recursion_depth : Note< "use -ftemplate-depth=N to increase recursive template instantiation depth">; def err_template_instantiate_within_definition : Error< "%select{implicit|explicit}0 instantiation of template %1 within its" " own definition">; def err_template_instantiate_undefined : Error< "%select{implicit|explicit}0 instantiation of undefined template %1">; def err_implicit_instantiate_member_undefined : Error< "implicit instantiation of undefined member %0">; def note_template_class_instantiation_was_here : Note< "class template %0 was instantiated here">; def note_template_class_explicit_specialization_was_here : Note< "class template %0 was explicitly specialized here">; def note_template_class_instantiation_here : Note< "in instantiation of template class %q0 requested here">; def note_template_member_class_here : Note< "in instantiation of member class %q0 requested here">; def note_template_member_function_here : Note< "in instantiation of member function %q0 requested here">; def note_function_template_spec_here : Note< "in instantiation of function template specialization %q0 requested here">; def note_template_static_data_member_def_here : Note< "in instantiation of static data member %q0 requested here">; def note_template_variable_def_here : Note< "in instantiation of variable template specialization %q0 requested here">; def note_template_enum_def_here : Note< "in instantiation of enumeration %q0 requested here">; def note_template_nsdmi_here : Note< "in instantiation of default member initializer %q0 requested here">; def note_template_type_alias_instantiation_here : Note< "in instantiation of template type alias %0 requested here">; def note_template_exception_spec_instantiation_here : Note< "in instantiation of exception specification for %0 requested here">; def warn_var_template_missing : Warning<"instantiation of variable %q0 " "required here, but no definition is available">, InGroup; def warn_func_template_missing : Warning<"instantiation of function %q0 " "required here, but no definition is available">, InGroup, DefaultIgnore; def note_forward_template_decl : Note< "forward declaration of template entity is here">; def note_inst_declaration_hint : Note<"add an explicit instantiation " "declaration to suppress this warning if %q0 is explicitly instantiated in " "another translation unit">; def note_default_arg_instantiation_here : Note< "in instantiation of default argument for '%0' required here">; def note_default_function_arg_instantiation_here : Note< "in instantiation of default function argument expression " "for '%0' required here">; def note_explicit_template_arg_substitution_here : Note< "while substituting explicitly-specified template arguments into function " "template %0 %1">; def note_function_template_deduction_instantiation_here : Note< "while substituting deduced template arguments into function template %0 " "%1">; def note_deduced_template_arg_substitution_here : Note< "during template argument deduction for %select{class|variable}0 template " "%select{partial specialization |}1%2 %3">; def note_prior_template_arg_substitution : Note< "while substituting prior template arguments into %select{non-type|template}0" " template parameter%1 %2">; def note_template_default_arg_checking : Note< "while checking a default template argument used here">; def note_instantiation_contexts_suppressed : Note< "(skipping %0 context%s0 in backtrace; use -ftemplate-backtrace-limit=0 to " "see all)">; def err_field_instantiates_to_function : Error< "data member instantiated with function type %0">; def err_variable_instantiates_to_function : Error< "%select{variable|static data member}0 instantiated with function type %1">; def err_nested_name_spec_non_tag : Error< "type %0 cannot be used prior to '::' because it has no members">; def err_using_pack_expansion_empty : Error< "%select{|member}0 using declaration %1 instantiates to an empty pack">; // C++ Explicit Instantiation def err_explicit_instantiation_duplicate : Error< "duplicate explicit instantiation of %0">; def ext_explicit_instantiation_duplicate : ExtWarn< "duplicate explicit instantiation of %0 ignored as a Microsoft extension">, InGroup; def note_previous_explicit_instantiation : Note< "previous explicit instantiation is here">; def warn_explicit_instantiation_after_specialization : Warning< "explicit instantiation of %0 that occurs after an explicit " "specialization has no effect">, InGroup>; def note_previous_template_specialization : Note< "previous template specialization is here">; def err_explicit_instantiation_nontemplate_type : Error< "explicit instantiation of non-templated type %0">; def note_nontemplate_decl_here : Note< "non-templated declaration is here">; def err_explicit_instantiation_in_class : Error< "explicit instantiation of %0 in class scope">; def err_explicit_instantiation_out_of_scope : Error< "explicit instantiation of %0 not in a namespace enclosing %1">; def err_explicit_instantiation_must_be_global : Error< "explicit instantiation of %0 must occur at global scope">; def warn_explicit_instantiation_out_of_scope_0x : Warning< "explicit instantiation of %0 not in a namespace enclosing %1">, InGroup, DefaultIgnore; def warn_explicit_instantiation_must_be_global_0x : Warning< "explicit instantiation of %0 must occur at global scope">, InGroup, DefaultIgnore; def err_explicit_instantiation_requires_name : Error< "explicit instantiation declaration requires a name">; def err_explicit_instantiation_of_typedef : Error< "explicit instantiation of typedef %0">; def err_explicit_instantiation_storage_class : Error< "explicit instantiation cannot have a storage class">; def err_explicit_instantiation_not_known : Error< "explicit instantiation of %0 does not refer to a function template, " "variable template, member function, member class, or static data member">; def note_explicit_instantiation_here : Note< "explicit instantiation refers here">; def err_explicit_instantiation_data_member_not_instantiated : Error< "explicit instantiation refers to static data member %q0 that is not an " "instantiation">; def err_explicit_instantiation_member_function_not_instantiated : Error< "explicit instantiation refers to member function %q0 that is not an " "instantiation">; def err_explicit_instantiation_ambiguous : Error< "partial ordering for explicit instantiation of %0 is ambiguous">; def note_explicit_instantiation_candidate : Note< "explicit instantiation candidate function %q0 template here %1">; def err_explicit_instantiation_inline : Error< "explicit instantiation cannot be 'inline'">; def warn_explicit_instantiation_inline_0x : Warning< "explicit instantiation cannot be 'inline'">, InGroup, DefaultIgnore; def err_explicit_instantiation_constexpr : Error< "explicit instantiation cannot be 'constexpr'">; def ext_explicit_instantiation_without_qualified_id : Extension< "qualifier in explicit instantiation of %q0 requires a template-id " "(a typedef is not permitted)">; def err_explicit_instantiation_without_template_id : Error< "explicit instantiation of %q0 must specify a template argument list">; def err_explicit_instantiation_unqualified_wrong_namespace : Error< "explicit instantiation of %q0 must occur in namespace %1">; def warn_explicit_instantiation_unqualified_wrong_namespace_0x : Warning< "explicit instantiation of %q0 must occur in namespace %1">, InGroup, DefaultIgnore; def err_explicit_instantiation_undefined_member : Error< "explicit instantiation of undefined %select{member class|member function|" "static data member}0 %1 of class template %2">; def err_explicit_instantiation_undefined_func_template : Error< "explicit instantiation of undefined function template %0">; def err_explicit_instantiation_undefined_var_template : Error< "explicit instantiation of undefined variable template %q0">; def err_explicit_instantiation_declaration_after_definition : Error< "explicit instantiation declaration (with 'extern') follows explicit " "instantiation definition (without 'extern')">; def note_explicit_instantiation_definition_here : Note< "explicit instantiation definition is here">; def err_invalid_var_template_spec_type : Error<"type %2 " "of %select{explicit instantiation|explicit specialization|" "partial specialization|redeclaration}0 of %1 does not match" " expected type %3">; def err_mismatched_exception_spec_explicit_instantiation : Error< "exception specification in explicit instantiation does not match " "instantiated one">; def ext_mismatched_exception_spec_explicit_instantiation : ExtWarn< err_mismatched_exception_spec_explicit_instantiation.Text>, InGroup; // C++ typename-specifiers def err_typename_nested_not_found : Error<"no type named %0 in %1">; def err_typename_nested_not_found_enable_if : Error< "no type named 'type' in %0; 'enable_if' cannot be used to disable " "this declaration">; def err_typename_nested_not_found_requirement : Error< "failed requirement '%0'; 'enable_if' cannot be used to disable this " "declaration">; def err_typename_nested_not_type : Error< "typename specifier refers to non-type member %0 in %1">; def note_typename_refers_here : Note< "referenced member %0 is declared here">; def err_typename_missing : Error< "missing 'typename' prior to dependent type name '%0%1'">; def err_typename_missing_template : Error< "missing 'typename' prior to dependent type template name '%0%1'">; def ext_typename_missing : ExtWarn< "missing 'typename' prior to dependent type name '%0%1'">, InGroup>; def ext_typename_outside_of_template : ExtWarn< "'typename' occurs outside of a template">, InGroup; def warn_cxx98_compat_typename_outside_of_template : Warning< "use of 'typename' outside of a template is incompatible with C++98">, InGroup, DefaultIgnore; def err_typename_refers_to_using_value_decl : Error< "typename specifier refers to a dependent using declaration for a value " "%0 in %1">; def note_using_value_decl_missing_typename : Note< "add 'typename' to treat this using declaration as a type">; def err_template_kw_refers_to_non_template : Error< "%0 following the 'template' keyword does not refer to a template">; def note_template_kw_refers_to_non_template : Note< "declared as a non-template here">; def err_template_kw_refers_to_class_template : Error< "'%0%1' instantiated to a class template, not a function template">; def note_referenced_class_template : Note< "class template declared here">; def err_template_kw_missing : Error< "missing 'template' keyword prior to dependent template name '%0%1'">; def ext_template_outside_of_template : ExtWarn< "'template' keyword outside of a template">, InGroup; def warn_cxx98_compat_template_outside_of_template : Warning< "use of 'template' keyword outside of a template is incompatible with C++98">, InGroup, DefaultIgnore; def err_non_type_template_in_nested_name_specifier : Error< "qualified name refers into a specialization of %select{function|variable}0 " "template %1">; def err_template_id_not_a_type : Error< "template name refers to non-type template %0">; def note_template_declared_here : Note< "%select{function template|class template|variable template" "|type alias template|template template parameter}0 " "%1 declared here">; def err_alias_template_expansion_into_fixed_list : Error< "pack expansion used as argument for non-pack parameter of alias template">; def note_parameter_type : Note< "parameter of type %0 is declared here">; // C++11 Variadic Templates def err_template_param_pack_default_arg : Error< "template parameter pack cannot have a default argument">; def err_template_param_pack_must_be_last_template_parameter : Error< "template parameter pack must be the last template parameter">; def err_template_parameter_pack_non_pack : Error< "%select{template type|non-type template|template template}0 parameter" "%select{| pack}1 conflicts with previous %select{template type|" "non-type template|template template}0 parameter%select{ pack|}1">; def note_template_parameter_pack_non_pack : Note< "%select{template type|non-type template|template template}0 parameter" "%select{| pack}1 does not match %select{template type|non-type template" "|template template}0 parameter%select{ pack|}1 in template argument">; def note_template_parameter_pack_here : Note< "previous %select{template type|non-type template|template template}0 " "parameter%select{| pack}1 declared here">; def err_unexpanded_parameter_pack : Error< "%select{expression|base type|declaration type|data member type|bit-field " "size|static assertion|fixed underlying type|enumerator value|" "using declaration|friend declaration|qualifier|initializer|default argument|" "non-type template parameter type|exception type|partial specialization|" "__if_exists name|__if_not_exists name|lambda|block}0 contains" "%plural{0: an|:}1 unexpanded parameter pack" "%plural{0:|1: %2|2:s %2 and %3|:s %2, %3, ...}1">; def err_pack_expansion_without_parameter_packs : Error< "pack expansion does not contain any unexpanded parameter packs">; def err_pack_expansion_length_conflict : Error< "pack expansion contains parameter packs %0 and %1 that have different " "lengths (%2 vs. %3)">; def err_pack_expansion_length_conflict_multilevel : Error< "pack expansion contains parameter pack %0 that has a different " "length (%1 vs. %2) from outer parameter packs">; def err_pack_expansion_length_conflict_partial : Error< "pack expansion contains parameter pack %0 that has a different " "length (at least %1 vs. %2) from outer parameter packs">; def err_pack_expansion_member_init : Error< "pack expansion for initialization of member %0">; def err_function_parameter_pack_without_parameter_packs : Error< "type %0 of function parameter pack does not contain any unexpanded " "parameter packs">; def err_ellipsis_in_declarator_not_parameter : Error< "only function and template parameters can be parameter packs">; def err_sizeof_pack_no_pack_name : Error< "%0 does not refer to the name of a parameter pack">; def err_fold_expression_packs_both_sides : Error< "binary fold expression has unexpanded parameter packs in both operands">; def err_fold_expression_empty : Error< "unary fold expression has empty expansion for operator '%0' " "with no fallback value">; def err_fold_expression_bad_operand : Error< "expression not permitted as operand of fold expression">; def err_unexpected_typedef : Error< "unexpected type name %0: expected expression">; def err_unexpected_namespace : Error< "unexpected namespace name %0: expected expression">; def err_undeclared_var_use : Error<"use of undeclared identifier %0">; def ext_undeclared_unqual_id_with_dependent_base : ExtWarn< "use of undeclared identifier %0; " "unqualified lookup into dependent bases of class template %1 is a Microsoft extension">, InGroup; def ext_found_via_dependent_bases_lookup : ExtWarn<"use of identifier %0 " "found via unqualified lookup into dependent bases of class templates is a " "Microsoft extension">, InGroup; def note_dependent_var_use : Note<"must qualify identifier to find this " "declaration in dependent base class">; def err_not_found_by_two_phase_lookup : Error<"call to function %0 that is neither " "visible in the template definition nor found by argument-dependent lookup">; def note_not_found_by_two_phase_lookup : Note<"%0 should be declared prior to the " "call site%select{| or in %2| or in an associated namespace of one of its arguments}1">; def err_undeclared_use : Error<"use of undeclared %0">; def warn_deprecated : Warning<"%0 is deprecated">, InGroup; def note_from_diagnose_if : Note<"from 'diagnose_if' attribute on %0:">; def warn_property_method_deprecated : Warning<"property access is using %0 method which is deprecated">, InGroup; def warn_deprecated_message : Warning<"%0 is deprecated: %1">, InGroup; def warn_deprecated_anonymous_namespace : Warning< "'deprecated' attribute on anonymous namespace ignored">, InGroup; def warn_deprecated_fwdclass_message : Warning< "%0 may be deprecated because the receiver type is unknown">, InGroup; def warn_deprecated_def : Warning< "implementing deprecated %select{method|class|category}0">, InGroup, DefaultIgnore; def warn_unavailable_def : Warning< "implementing unavailable method">, InGroup, DefaultIgnore; def err_unavailable : Error<"%0 is unavailable">; def err_property_method_unavailable : Error<"property access is using %0 method which is unavailable">; def err_unavailable_message : Error<"%0 is unavailable: %1">; def warn_unavailable_fwdclass_message : Warning< "%0 may be unavailable because the receiver type is unknown">, InGroup; def note_availability_specified_here : Note< "%0 has been explicitly marked " "%select{unavailable|deleted|deprecated|partial}1 here">; def note_implicitly_deleted : Note< "explicitly defaulted function was implicitly deleted here">; def warn_not_enough_argument : Warning< "not enough variable arguments in %0 declaration to fit a sentinel">, InGroup; def warn_missing_sentinel : Warning < "missing sentinel in %select{function call|method dispatch|block call}0">, InGroup; def note_sentinel_here : Note< "%select{function|method|block}0 has been explicitly marked sentinel here">; def warn_missing_prototype : Warning< "no previous prototype for function %0">, InGroup>, DefaultIgnore; def note_declaration_not_a_prototype : Note< "this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function">; def warn_strict_prototypes : Warning< "this %select{function declaration is not|block declaration is not|" "old-style function definition is not preceded by}0 a prototype">, InGroup>, DefaultIgnore; def warn_missing_variable_declarations : Warning< "no previous extern declaration for non-static variable %0">, InGroup>, DefaultIgnore; def err_static_data_member_reinitialization : Error<"static data member %0 already has an initializer">; def err_redefinition : Error<"redefinition of %0">; def err_alias_after_tentative : Error<"alias definition of %0 after tentative definition">; def err_alias_is_definition : Error<"definition %0 cannot also be an %select{alias|ifunc}1">; def err_definition_of_implicitly_declared_member : Error< "definition of implicitly declared %select{default constructor|copy " "constructor|move constructor|copy assignment operator|move assignment " "operator|destructor|function}1">; def err_definition_of_explicitly_defaulted_member : Error< "definition of explicitly defaulted %select{default constructor|copy " "constructor|move constructor|copy assignment operator|move assignment " "operator|destructor|function}0">; def err_redefinition_extern_inline : Error< "redefinition of a 'extern inline' function %0 is not supported in " "%select{C99 mode|C++}1">; def warn_attr_abi_tag_namespace : Warning< "'abi_tag' attribute on %select{non-inline|anonymous}0 namespace ignored">, InGroup; def err_abi_tag_on_redeclaration : Error< "cannot add 'abi_tag' attribute in a redeclaration">; def err_new_abi_tag_on_redeclaration : Error< "'abi_tag' %0 missing in original declaration">; def note_use_ifdef_guards : Note< "unguarded header; consider using #ifdef guards or #pragma once">; def note_deleted_dtor_no_operator_delete : Note< "virtual destructor requires an unambiguous, accessible 'operator delete'">; def note_deleted_special_member_class_subobject : Note< "%select{default constructor of|copy constructor of|move constructor of|" "copy assignment operator of|move assignment operator of|destructor of|" "constructor inherited by}0 " "%1 is implicitly deleted because " "%select{base class %3|%select{||||variant }4field %3}2 has " "%select{no|a deleted|multiple|an inaccessible|a non-trivial}4 " "%select{%select{default constructor|copy constructor|move constructor|copy " "assignment operator|move assignment operator|destructor|" "%select{default|corresponding|default|default|default}4 constructor}0|" "destructor}5" "%select{||s||}4">; def note_deleted_default_ctor_uninit_field : Note< "%select{default constructor of|constructor inherited by}0 " "%1 is implicitly deleted because field %2 of " "%select{reference|const-qualified}4 type %3 would not be initialized">; def note_deleted_default_ctor_all_const : Note< "%select{default constructor of|constructor inherited by}0 " "%1 is implicitly deleted because all " "%select{data members|data members of an anonymous union member}2" " are const-qualified">; def note_deleted_copy_ctor_rvalue_reference : Note< "copy constructor of %0 is implicitly deleted because field %1 is of " "rvalue reference type %2">; def note_deleted_copy_user_declared_move : Note< "copy %select{constructor|assignment operator}0 is implicitly deleted because" " %1 has a user-declared move %select{constructor|assignment operator}2">; def note_deleted_assign_field : Note< "%select{copy|move}0 assignment operator of %1 is implicitly deleted " "because field %2 is of %select{reference|const-qualified}4 type %3">; // These should be errors. def warn_undefined_internal : Warning< "%select{function|variable}0 %q1 has internal linkage but is not defined">, InGroup>; def err_undefined_internal_type : Error< "%select{function|variable}0 %q1 is used but not defined in this " "translation unit, and cannot be defined in any other translation unit " "because its type does not have linkage">; def ext_undefined_internal_type : Extension< "ISO C++ requires a definition in this translation unit for " "%select{function|variable}0 %q1 because its type does not have linkage">, InGroup>; def warn_undefined_inline : Warning<"inline function %q0 is not defined">, InGroup>; def err_undefined_inline_var : Error<"inline variable %q0 is not defined">; def note_used_here : Note<"used here">; def err_internal_linkage_redeclaration : Error< "'internal_linkage' attribute does not appear on the first declaration of %0">; def warn_internal_linkage_local_storage : Warning< "'internal_linkage' attribute on a non-static local variable is ignored">, InGroup; def ext_internal_in_extern_inline : ExtWarn< "static %select{function|variable}0 %1 is used in an inline function with " "external linkage">, InGroup; def ext_internal_in_extern_inline_quiet : Extension< "static %select{function|variable}0 %1 is used in an inline function with " "external linkage">, InGroup; def warn_static_local_in_extern_inline : Warning< "non-constant static local variable in inline function may be different " "in different files">, InGroup; def note_convert_inline_to_static : Note< "use 'static' to give inline function %0 internal linkage">; def ext_redefinition_of_typedef : ExtWarn< "redefinition of typedef %0 is a C11 feature">, InGroup >; def err_redefinition_variably_modified_typedef : Error< "redefinition of %select{typedef|type alias}0 for variably-modified type %1">; def err_inline_decl_follows_def : Error< "inline declaration of %0 follows non-inline definition">; def err_inline_declaration_block_scope : Error< "inline declaration of %0 not allowed in block scope">; def err_static_non_static : Error< "static declaration of %0 follows non-static declaration">; def err_different_language_linkage : Error< "declaration of %0 has a different language linkage">; def ext_retained_language_linkage : Extension< "friend function %0 retaining previous language linkage is an extension">, InGroup>; def err_extern_c_global_conflict : Error< "declaration of %1 %select{with C language linkage|in global scope}0 " "conflicts with declaration %select{in global scope|with C language linkage}0">; def note_extern_c_global_conflict : Note< "declared %select{in global scope|with C language linkage}0 here">; def note_extern_c_begins_here : Note< "extern \"C\" language linkage specification begins here">; def warn_weak_import : Warning < "an already-declared variable is made a weak_import declaration %0">; def ext_static_non_static : Extension< "redeclaring non-static %0 as static is a Microsoft extension">, InGroup; def err_non_static_static : Error< "non-static declaration of %0 follows static declaration">; def err_extern_non_extern : Error< "extern declaration of %0 follows non-extern declaration">; def err_non_extern_extern : Error< "non-extern declaration of %0 follows extern declaration">; def err_non_thread_thread : Error< "non-thread-local declaration of %0 follows thread-local declaration">; def err_thread_non_thread : Error< "thread-local declaration of %0 follows non-thread-local declaration">; def err_thread_thread_different_kind : Error< "thread-local declaration of %0 with %select{static|dynamic}1 initialization " "follows declaration with %select{dynamic|static}1 initialization">; def err_mismatched_owning_module : Error< "declaration of %0 in %select{the global module|module %2}1 follows " "declaration in %select{the global module|module %4}3">; def err_redefinition_different_type : Error< "redefinition of %0 with a different type%diff{: $ vs $|}1,2">; def err_redefinition_different_kind : Error< "redefinition of %0 as different kind of symbol">; def err_redefinition_different_namespace_alias : Error< "redefinition of %0 as an alias for a different namespace">; def note_previous_namespace_alias : Note< "previously defined as an alias for %0">; def warn_forward_class_redefinition : Warning< "redefinition of forward class %0 of a typedef name of an object type is ignored">, InGroup>; def err_redefinition_different_typedef : Error< "%select{typedef|type alias|type alias template}0 " "redefinition with different types%diff{ ($ vs $)|}1,2">; def err_tag_reference_non_tag : Error< "%select{non-struct type|non-class type|non-union type|non-enum " "type|typedef|type alias|template|type alias template|template " "template argument}1 %0 cannot be referenced with a " "%select{struct|interface|union|class|enum}2 specifier">; def err_tag_reference_conflict : Error< "implicit declaration introduced by elaborated type conflicts with a " "%select{non-struct type|non-class type|non-union type|non-enum " "type|typedef|type alias|template|type alias template|template " "template argument}0 of the same name">; def err_dependent_tag_decl : Error< "%select{declaration|definition}0 of " "%select{struct|interface|union|class|enum}1 in a dependent scope">; def err_tag_definition_of_typedef : Error< "definition of type %0 conflicts with %select{typedef|type alias}1 of the same name">; def err_conflicting_types : Error<"conflicting types for %0">; def err_different_pass_object_size_params : Error< "conflicting pass_object_size attributes on parameters">; def err_late_asm_label_name : Error< "cannot apply asm label to %select{variable|function}0 after its first use">; def err_different_asm_label : Error<"conflicting asm label">; def err_nested_redefinition : Error<"nested redefinition of %0">; def err_use_with_wrong_tag : Error< "use of %0 with tag type that does not match previous declaration">; def warn_struct_class_tag_mismatch : Warning< "%select{struct|interface|class}0%select{| template}1 %2 was previously " "declared as a %select{struct|interface|class}3%select{| template}1">, InGroup, DefaultIgnore; def warn_struct_class_previous_tag_mismatch : Warning< "%2 defined as %select{a struct|an interface|a class}0%select{| template}1 " "here but previously declared as " "%select{a struct|an interface|a class}3%select{| template}1">, InGroup, DefaultIgnore; def note_struct_class_suggestion : Note< "did you mean %select{struct|interface|class}0 here?">; def ext_forward_ref_enum : Extension< "ISO C forbids forward references to 'enum' types">; def err_forward_ref_enum : Error< "ISO C++ forbids forward references to 'enum' types">; def ext_ms_forward_ref_enum : ExtWarn< "forward references to 'enum' types are a Microsoft extension">, InGroup; def ext_forward_ref_enum_def : Extension< "redeclaration of already-defined enum %0 is a GNU extension">, InGroup; def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">; def err_duplicate_member : Error<"duplicate member %0">; def err_misplaced_ivar : Error< "instance variables may not be placed in %select{categories|class extension}0">; def warn_ivars_in_interface : Warning< "declaration of instance variables in the interface is deprecated">, InGroup>, DefaultIgnore; def ext_enum_value_not_int : Extension< "ISO C restricts enumerator values to range of 'int' (%0 is too " "%select{small|large}1)">; def ext_enum_too_large : ExtWarn< "enumeration values exceed range of largest integer">, InGroup; def ext_enumerator_increment_too_large : ExtWarn< "incremented enumerator value %0 is not representable in the " "largest integer type">, InGroup; def warn_flag_enum_constant_out_of_range : Warning< "enumeration value %0 is out of range of flags in enumeration type %1">, InGroup; def warn_illegal_constant_array_size : Extension< "size of static array must be an integer constant expression">; def err_vm_decl_in_file_scope : Error< "variably modified type declaration not allowed at file scope">; def err_vm_decl_has_extern_linkage : Error< "variably modified type declaration cannot have 'extern' linkage">; def err_typecheck_field_variable_size : Error< "fields must have a constant size: 'variable length array in structure' " "extension will never be supported">; def err_vm_func_decl : Error< "function declaration cannot have variably modified type">; def err_array_too_large : Error< "array is too large (%0 elements)">; // -Wpadded, -Wpacked def warn_padded_struct_field : Warning< "padding %select{struct|interface|class}0 %1 with %2 " "%select{byte|bit}3%s2 to align %4">, InGroup, DefaultIgnore; def warn_padded_struct_anon_field : Warning< "padding %select{struct|interface|class}0 %1 with %2 " "%select{byte|bit}3%s2 to align anonymous bit-field">, InGroup, DefaultIgnore; def warn_padded_struct_size : Warning< "padding size of %0 with %1 %select{byte|bit}2%s1 to alignment boundary">, InGroup, DefaultIgnore; def warn_unnecessary_packed : Warning< "packed attribute is unnecessary for %0">, InGroup, DefaultIgnore; def err_typecheck_negative_array_size : Error<"array size is negative">; def warn_typecheck_function_qualifiers_ignored : Warning< "'%0' qualifier on function type %1 has no effect">, InGroup; def warn_typecheck_function_qualifiers_unspecified : Warning< "'%0' qualifier on function type %1 has unspecified behavior">; def warn_typecheck_reference_qualifiers : Warning< "'%0' qualifier on reference type %1 has no effect">, InGroup; def err_typecheck_invalid_restrict_not_pointer : Error< "restrict requires a pointer or reference (%0 is invalid)">; def err_typecheck_invalid_restrict_not_pointer_noarg : Error< "restrict requires a pointer or reference">; def err_typecheck_invalid_restrict_invalid_pointee : Error< "pointer to function type %0 may not be 'restrict' qualified">; def ext_typecheck_zero_array_size : Extension< "zero size arrays are an extension">, InGroup; def err_typecheck_zero_array_size : Error< "zero-length arrays are not permitted in C++">; def warn_typecheck_zero_static_array_size : Warning< "'static' has no effect on zero-length arrays">, InGroup; def err_array_size_non_int : Error<"size of array has non-integer type %0">; def err_init_element_not_constant : Error< "initializer element is not a compile-time constant">; def ext_aggregate_init_not_constant : Extension< "initializer for aggregate is not a compile-time constant">, InGroup; def err_local_cant_init : Error< "'__local' variable cannot have an initializer">; def err_block_extern_cant_init : Error< "'extern' variable cannot have an initializer">; def warn_extern_init : Warning<"'extern' variable has an initializer">, InGroup>; def err_variable_object_no_init : Error< "variable-sized object may not be initialized">; def err_excess_initializers : Error< "excess elements in %select{array|vector|scalar|union|struct}0 initializer">; def ext_excess_initializers : ExtWarn< "excess elements in %select{array|vector|scalar|union|struct}0 initializer">; def err_excess_initializers_in_char_array_initializer : Error< "excess elements in char array initializer">; def ext_excess_initializers_in_char_array_initializer : ExtWarn< "excess elements in char array initializer">; def err_initializer_string_for_char_array_too_long : Error< "initializer-string for char array is too long">; def ext_initializer_string_for_char_array_too_long : ExtWarn< "initializer-string for char array is too long">; def warn_missing_field_initializers : Warning< "missing field %0 initializer">, InGroup, DefaultIgnore; def warn_braces_around_scalar_init : Warning< "braces around scalar initializer">, InGroup>; def ext_many_braces_around_scalar_init : ExtWarn< "too many braces around scalar initializer">, InGroup>; def ext_complex_component_init : Extension< "complex initialization specifying real and imaginary components " "is an extension">, InGroup>; def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">; def warn_cxx98_compat_empty_scalar_initializer : Warning< "scalar initialized from empty initializer list is incompatible with C++98">, InGroup, DefaultIgnore; def warn_cxx98_compat_reference_list_init : Warning< "reference initialized from initializer list is incompatible with C++98">, InGroup, DefaultIgnore; def warn_cxx98_compat_initializer_list_init : Warning< "initialization of initializer_list object is incompatible with C++98">, InGroup, DefaultIgnore; def warn_cxx98_compat_ctor_list_init : Warning< "constructor call from initializer list is incompatible with C++98">, InGroup, DefaultIgnore; def err_illegal_initializer : Error< "illegal initializer (only variables can be initialized)">; def err_illegal_initializer_type : Error<"illegal initializer type %0">; def ext_init_list_type_narrowing : ExtWarn< "type %0 cannot be narrowed to %1 in initializer list">, InGroup, DefaultError, SFINAEFailure; def ext_init_list_variable_narrowing : ExtWarn< "non-constant-expression cannot be narrowed from type %0 to %1 in " "initializer list">, InGroup, DefaultError, SFINAEFailure; def ext_init_list_constant_narrowing : ExtWarn< "constant expression evaluates to %0 which cannot be narrowed to type %1">, InGroup, DefaultError, SFINAEFailure; def warn_init_list_type_narrowing : Warning< "type %0 cannot be narrowed to %1 in initializer list in C++11">, InGroup, DefaultIgnore; def warn_init_list_variable_narrowing : Warning< "non-constant-expression cannot be narrowed from type %0 to %1 in " "initializer list in C++11">, InGroup, DefaultIgnore; def warn_init_list_constant_narrowing : Warning< "constant expression evaluates to %0 which cannot be narrowed to type %1 in " "C++11">, InGroup, DefaultIgnore; def note_init_list_narrowing_silence : Note< "insert an explicit cast to silence this issue">; def err_init_objc_class : Error< "cannot initialize Objective-C class type %0">; def err_implicit_empty_initializer : Error< "initializer for aggregate with no elements requires explicit braces">; def err_bitfield_has_negative_width : Error< "bit-field %0 has negative width (%1)">; def err_anon_bitfield_has_negative_width : Error< "anonymous bit-field has negative width (%0)">; def err_bitfield_has_zero_width : Error<"named bit-field %0 has zero width">; def err_bitfield_width_exceeds_type_width : Error< "width of bit-field %0 (%1 bits) exceeds %select{width|size}2 " "of its type (%3 bit%s3)">; def err_anon_bitfield_width_exceeds_type_width : Error< "width of anonymous bit-field (%0 bits) exceeds %select{width|size}1 " "of its type (%2 bit%s2)">; def err_incorrect_number_of_vector_initializers : Error< "number of elements must be either one or match the size of the vector">; // Used by C++ which allows bit-fields that are wider than the type. def warn_bitfield_width_exceeds_type_width: Warning< "width of bit-field %0 (%1 bits) exceeds the width of its type; value will " "be truncated to %2 bit%s2">, InGroup; def warn_anon_bitfield_width_exceeds_type_width : Warning< "width of anonymous bit-field (%0 bits) exceeds width of its type; value " "will be truncated to %1 bit%s1">, InGroup; def warn_bitfield_too_small_for_enum : Warning< "bit-field %0 is not wide enough to store all enumerators of %1">, InGroup, DefaultIgnore; def note_widen_bitfield : Note< "widen this field to %0 bits to store all values of %1">; def warn_unsigned_bitfield_assigned_signed_enum : Warning< "assigning value of signed enum type %1 to unsigned bit-field %0; " "negative enumerators of enum %1 will be converted to positive values">, InGroup, DefaultIgnore; def warn_signed_bitfield_enum_conversion : Warning< "signed bit-field %0 needs an extra bit to represent the largest positive " "enumerators of %1">, InGroup, DefaultIgnore; def note_change_bitfield_sign : Note< "consider making the bitfield type %select{unsigned|signed}0">; def warn_missing_braces : Warning< "suggest braces around initialization of subobject">, InGroup, DefaultIgnore; def err_redefinition_of_label : Error<"redefinition of label %0">; def err_undeclared_label_use : Error<"use of undeclared label %0">; def err_goto_ms_asm_label : Error< "cannot jump from this goto statement to label %0 inside an inline assembly block">; def note_goto_ms_asm_label : Note< "inline assembly label %0 declared here">; def warn_unused_label : Warning<"unused label %0">, InGroup, DefaultIgnore; def err_goto_into_protected_scope : Error< "cannot jump from this goto statement to its label">; def ext_goto_into_protected_scope : ExtWarn< "jump from this goto statement to its label is a Microsoft extension">, InGroup; def warn_cxx98_compat_goto_into_protected_scope : Warning< "jump from this goto statement to its label is incompatible with C++98">, InGroup, DefaultIgnore; def err_switch_into_protected_scope : Error< "cannot jump from switch statement to this case label">; def warn_cxx98_compat_switch_into_protected_scope : Warning< "jump from switch statement to this case label is incompatible with C++98">, InGroup, DefaultIgnore; def err_indirect_goto_without_addrlabel : Error< "indirect goto in function with no address-of-label expressions">; def err_indirect_goto_in_protected_scope : Error< "cannot jump from this indirect goto statement to one of its possible targets">; def warn_cxx98_compat_indirect_goto_in_protected_scope : Warning< "jump from this indirect goto statement to one of its possible targets " "is incompatible with C++98">, InGroup, DefaultIgnore; def note_indirect_goto_target : Note< "possible target of indirect goto statement">; def note_protected_by_variable_init : Note< "jump bypasses variable initialization">; def note_protected_by_variable_nontriv_destructor : Note< "jump bypasses variable with a non-trivial destructor">; def note_protected_by_variable_non_pod : Note< "jump bypasses initialization of non-POD variable">; def note_protected_by_cleanup : Note< "jump bypasses initialization of variable with __attribute__((cleanup))">; def note_protected_by_vla_typedef : Note< "jump bypasses initialization of VLA typedef">; def note_protected_by_vla_type_alias : Note< "jump bypasses initialization of VLA type alias">; def note_protected_by_constexpr_if : Note< "jump enters controlled statement of constexpr if">; def note_protected_by_if_available : Note< "jump enters controlled statement of if available">; def note_protected_by_vla : Note< "jump bypasses initialization of variable length array">; def note_protected_by_objc_fast_enumeration : Note< "jump enters Objective-C fast enumeration loop">; def note_protected_by_objc_try : Note< "jump bypasses initialization of @try block">; def note_protected_by_objc_catch : Note< "jump bypasses initialization of @catch block">; def note_protected_by_objc_finally : Note< "jump bypasses initialization of @finally block">; def note_protected_by_objc_synchronized : Note< "jump bypasses initialization of @synchronized block">; def note_protected_by_objc_autoreleasepool : Note< "jump bypasses auto release push of @autoreleasepool block">; def note_protected_by_cxx_try : Note< "jump bypasses initialization of try block">; def note_protected_by_cxx_catch : Note< "jump bypasses initialization of catch block">; def note_protected_by_seh_try : Note< "jump bypasses initialization of __try block">; def note_protected_by_seh_except : Note< "jump bypasses initialization of __except block">; def note_protected_by_seh_finally : Note< "jump bypasses initialization of __finally block">; def note_protected_by___block : Note< "jump bypasses setup of __block variable">; def note_protected_by_objc_strong_init : Note< "jump bypasses initialization of __strong variable">; def note_protected_by_objc_weak_init : Note< "jump bypasses initialization of __weak variable">; def note_protected_by_non_trivial_c_struct_init : Note< "jump bypasses initialization of variable of non-trivial C struct type">; def note_enters_block_captures_cxx_obj : Note< "jump enters lifetime of block which captures a destructible C++ object">; def note_enters_block_captures_strong : Note< "jump enters lifetime of block which strongly captures a variable">; def note_enters_block_captures_weak : Note< "jump enters lifetime of block which weakly captures a variable">; def note_enters_block_captures_non_trivial_c_struct : Note< "jump enters lifetime of block which captures a C struct that is non-trivial " "to destroy">; def note_exits_cleanup : Note< "jump exits scope of variable with __attribute__((cleanup))">; def note_exits_dtor : Note< "jump exits scope of variable with non-trivial destructor">; def note_exits_temporary_dtor : Note< "jump exits scope of lifetime-extended temporary with non-trivial " "destructor">; def note_exits___block : Note< "jump exits scope of __block variable">; def note_exits_objc_try : Note< "jump exits @try block">; def note_exits_objc_catch : Note< "jump exits @catch block">; def note_exits_objc_finally : Note< "jump exits @finally block">; def note_exits_objc_synchronized : Note< "jump exits @synchronized block">; def note_exits_cxx_try : Note< "jump exits try block">; def note_exits_cxx_catch : Note< "jump exits catch block">; def note_exits_seh_try : Note< "jump exits __try block">; def note_exits_seh_except : Note< "jump exits __except block">; def note_exits_seh_finally : Note< "jump exits __finally block">; def note_exits_objc_autoreleasepool : Note< "jump exits autoreleasepool block">; def note_exits_objc_strong : Note< "jump exits scope of __strong variable">; def note_exits_objc_weak : Note< "jump exits scope of __weak variable">; def note_exits_block_captures_cxx_obj : Note< "jump exits lifetime of block which captures a destructible C++ object">; def note_exits_block_captures_strong : Note< "jump exits lifetime of block which strongly captures a variable">; def note_exits_block_captures_weak : Note< "jump exits lifetime of block which weakly captures a variable">; def note_exits_block_captures_non_trivial_c_struct : Note< "jump exits lifetime of block which captures a C struct that is non-trivial " "to destroy">; def err_func_returning_qualified_void : ExtWarn< "function cannot return qualified void type %0">, InGroup>; def err_func_returning_array_function : Error< "function cannot return %select{array|function}0 type %1">; def err_field_declared_as_function : Error<"field %0 declared as a function">; def err_field_incomplete : Error<"field has incomplete type %0">; def ext_variable_sized_type_in_struct : ExtWarn< "field %0 with variable sized type %1 not at the end of a struct or class is" " a GNU extension">, InGroup; def ext_c99_flexible_array_member : Extension< "flexible array members are a C99 feature">, InGroup; def err_flexible_array_virtual_base : Error< "flexible array member %0 not allowed in " "%select{struct|interface|union|class|enum}1 which has a virtual base class">; def err_flexible_array_empty_aggregate : Error< "flexible array member %0 not allowed in otherwise empty " "%select{struct|interface|union|class|enum}1">; def err_flexible_array_has_nontrivial_dtor : Error< "flexible array member %0 of type %1 with non-trivial destruction">; def ext_flexible_array_in_struct : Extension< "%0 may not be nested in a struct due to flexible array member">, InGroup; def ext_flexible_array_in_array : Extension< "%0 may not be used as an array element due to flexible array member">, InGroup; def err_flexible_array_init : Error< "initialization of flexible array member is not allowed">; def ext_flexible_array_empty_aggregate_ms : Extension< "flexible array member %0 in otherwise empty " "%select{struct|interface|union|class|enum}1 is a Microsoft extension">, InGroup; def err_flexible_array_union : Error< "flexible array member %0 in a union is not allowed">; def ext_flexible_array_union_ms : Extension< "flexible array member %0 in a union is a Microsoft extension">, InGroup; def ext_flexible_array_empty_aggregate_gnu : Extension< "flexible array member %0 in otherwise empty " "%select{struct|interface|union|class|enum}1 is a GNU extension">, InGroup; def ext_flexible_array_union_gnu : Extension< "flexible array member %0 in a union is a GNU extension">, InGroup; def err_flexible_array_not_at_end : Error< "flexible array member %0 with type %1 is not at the end of" " %select{struct|interface|union|class|enum}2">; def err_objc_variable_sized_type_not_at_end : Error< "field %0 with variable sized type %1 is not at the end of class">; def note_next_field_declaration : Note< "next field declaration is here">; def note_next_ivar_declaration : Note< "next %select{instance variable declaration|synthesized instance variable}0" " is here">; def err_synthesize_variable_sized_ivar : Error< "synthesized property with variable size type %0" " requires an existing instance variable">; def err_flexible_array_arc_retainable : Error< "ARC forbids flexible array members with retainable object type">; def warn_variable_sized_ivar_visibility : Warning< "field %0 with variable sized type %1 is not visible to subclasses and" " can conflict with their instance variables">, InGroup; def warn_superclass_variable_sized_type_not_at_end : Warning< "field %0 can overwrite instance variable %1 with variable sized type %2" " in superclass %3">, InGroup; let CategoryName = "ARC Semantic Issue" in { // ARC-mode diagnostics. let CategoryName = "ARC Weak References" in { def err_arc_weak_no_runtime : Error< "cannot create __weak reference because the current deployment target " "does not support weak references">; def err_arc_weak_disabled : Error< "cannot create __weak reference in file using manual reference counting">; def err_synthesizing_arc_weak_property_disabled : Error< "cannot synthesize weak property in file using manual reference counting">; def err_synthesizing_arc_weak_property_no_runtime : Error< "cannot synthesize weak property because the current deployment target " "does not support weak references">; def err_arc_unsupported_weak_class : Error< "class is incompatible with __weak references">; def err_arc_weak_unavailable_assign : Error< "assignment of a weak-unavailable object to a __weak object">; def err_arc_weak_unavailable_property : Error< "synthesizing __weak instance variable of type %0, which does not " "support weak references">; def note_implemented_by_class : Note< "when implemented by class %0">; def err_arc_convesion_of_weak_unavailable : Error< "%select{implicit conversion|cast}0 of weak-unavailable object of type %1 to" " a __weak object of type %2">; } // end "ARC Weak References" category let CategoryName = "ARC Restrictions" in { def err_unavailable_in_arc : Error< "%0 is unavailable in ARC">; def note_arc_forbidden_type : Note< "declaration uses type that is ill-formed in ARC">; def note_performs_forbidden_arc_conversion : Note< "inline function performs a conversion which is forbidden in ARC">; def note_arc_init_returns_unrelated : Note< "init method must return a type related to its receiver type">; def note_arc_weak_disabled : Note< "declaration uses __weak, but ARC is disabled">; def note_arc_weak_no_runtime : Note<"declaration uses __weak, which " "the current deployment target does not support">; def note_arc_field_with_ownership : Note< "field has non-trivial ownership qualification">; def err_arc_illegal_explicit_message : Error< "ARC forbids explicit message send of %0">; def err_arc_unused_init_message : Error< "the result of a delegate init call must be immediately returned " "or assigned to 'self'">; def err_arc_mismatched_cast : Error< "%select{implicit conversion|cast}0 of " "%select{%2|a non-Objective-C pointer type %2|a block pointer|" "an Objective-C pointer|an indirect pointer to an Objective-C pointer}1" " to %3 is disallowed with ARC">; def err_arc_nolifetime_behavior : Error< "explicit ownership qualifier on cast result has no effect">; def err_arc_objc_object_in_tag : Error< "ARC forbids %select{Objective-C objects|blocks}0 in " "%select{struct|interface|union|<>|enum}1">; def err_arc_objc_property_default_assign_on_object : Error< "ARC forbids synthesizing a property of an Objective-C object " "with unspecified ownership or storage attribute">; def err_arc_illegal_selector : Error< "ARC forbids use of %0 in a @selector">; def err_arc_illegal_method_def : Error< "ARC forbids %select{implementation|synthesis}0 of %1">; def warn_arc_strong_pointer_objc_pointer : Warning< "method parameter of type %0 with no explicit ownership">, InGroup>, DefaultIgnore; } // end "ARC Restrictions" category def err_arc_lost_method_convention : Error< "method was declared as %select{an 'alloc'|a 'copy'|an 'init'|a 'new'}0 " "method, but its implementation doesn't match because %select{" "its result type is not an object pointer|" "its result type is unrelated to its receiver type}1">; def note_arc_lost_method_convention : Note<"declaration in interface">; def err_arc_gained_method_convention : Error< "method implementation does not match its declaration">; def note_arc_gained_method_convention : Note< "declaration in interface is not in the '%select{alloc|copy|init|new}0' " "family because %select{its result type is not an object pointer|" "its result type is unrelated to its receiver type}1">; def err_typecheck_arc_assign_self : Error< "cannot assign to 'self' outside of a method in the init family">; def err_typecheck_arc_assign_self_class_method : Error< "cannot assign to 'self' in a class method">; def err_typecheck_arr_assign_enumeration : Error< "fast enumeration variables cannot be modified in ARC by default; " "declare the variable __strong to allow this">; def warn_arc_retained_assign : Warning< "assigning retained object to %select{weak|unsafe_unretained}0 " "%select{property|variable}1" "; object will be released after assignment">, InGroup; def warn_arc_retained_property_assign : Warning< "assigning retained object to unsafe property" "; object will be released after assignment">, InGroup; def warn_arc_literal_assign : Warning< "assigning %select{array literal|dictionary literal|numeric literal|boxed expression||block literal}0" " to a weak %select{property|variable}1" "; object will be released after assignment">, InGroup; def err_arc_new_array_without_ownership : Error< "'new' cannot allocate an array of %0 with no explicit ownership">; def err_arc_autoreleasing_var : Error< "%select{__block variables|global variables|fields|instance variables}0 cannot have " "__autoreleasing ownership">; def err_arc_autoreleasing_capture : Error< "cannot capture __autoreleasing variable in a " "%select{block|lambda by copy}0">; def err_arc_thread_ownership : Error< "thread-local variable has non-trivial ownership: type is %0">; def err_arc_indirect_no_ownership : Error< "%select{pointer|reference}1 to non-const type %0 with no explicit ownership">; def err_arc_array_param_no_ownership : Error< "must explicitly describe intended ownership of an object array parameter">; def err_arc_pseudo_dtor_inconstant_quals : Error< "pseudo-destructor destroys object of type %0 with inconsistently-qualified " "type %1">; def err_arc_init_method_unrelated_result_type : Error< "init methods must return a type related to the receiver type">; def err_arc_nonlocal_writeback : Error< "passing address of %select{non-local|non-scalar}0 object to " "__autoreleasing parameter for write-back">; def err_arc_method_not_found : Error< "no known %select{instance|class}1 method for selector %0">; def err_arc_receiver_forward_class : Error< "receiver %0 for class message is a forward declaration">; def err_arc_may_not_respond : Error< "no visible @interface for %0 declares the selector %1">; def err_arc_receiver_forward_instance : Error< "receiver type %0 for instance message is a forward declaration">; def warn_receiver_forward_instance : Warning< "receiver type %0 for instance message is a forward declaration">, InGroup, DefaultIgnore; def err_arc_collection_forward : Error< "collection expression type %0 is a forward declaration">; def err_arc_multiple_method_decl : Error< "multiple methods named %0 found with mismatched result, " "parameter type or attributes">; def warn_arc_lifetime_result_type : Warning< "ARC %select{unused|__unsafe_unretained|__strong|__weak|__autoreleasing}0 " "lifetime qualifier on return type is ignored">, InGroup; let CategoryName = "ARC Retain Cycle" in { def warn_arc_retain_cycle : Warning< "capturing %0 strongly in this block is likely to lead to a retain cycle">, InGroup; def note_arc_retain_cycle_owner : Note< "block will be retained by %select{the captured object|an object strongly " "retained by the captured object}0">; } // end "ARC Retain Cycle" category def warn_arc_object_memaccess : Warning< "%select{destination for|source of}0 this %1 call is a pointer to " "ownership-qualified type %2">, InGroup; let CategoryName = "ARC and @properties" in { def err_arc_strong_property_ownership : Error< "existing instance variable %1 for strong property %0 may not be " "%select{|__unsafe_unretained||__weak}2">; def err_arc_assign_property_ownership : Error< "existing instance variable %1 for property %0 with %select{unsafe_unretained|assign}2 " "attribute must be __unsafe_unretained">; def err_arc_inconsistent_property_ownership : Error< "%select{|unsafe_unretained|strong|weak}1 property %0 may not also be " "declared %select{|__unsafe_unretained|__strong|__weak|__autoreleasing}2">; } // end "ARC and @properties" category def warn_block_capture_autoreleasing : Warning< "block captures an autoreleasing out-parameter, which may result in " "use-after-free bugs">, InGroup; def note_declare_parameter_strong : Note< "declare the parameter __strong or capture a __block __strong variable to " "keep values alive across autorelease pools">; def err_arc_atomic_ownership : Error< "cannot perform atomic operation on a pointer to type %0: type has " "non-trivial ownership">; let CategoryName = "ARC Casting Rules" in { def err_arc_bridge_cast_incompatible : Error< "incompatible types casting %0 to %1 with a %select{__bridge|" "__bridge_transfer|__bridge_retained}2 cast">; def err_arc_bridge_cast_wrong_kind : Error< "cast of %select{Objective-C|block|C}0 pointer type %1 to " "%select{Objective-C|block|C}2 pointer type %3 cannot use %select{__bridge|" "__bridge_transfer|__bridge_retained}4">; def err_arc_cast_requires_bridge : Error< "%select{cast|implicit conversion}0 of %select{Objective-C|block|C}1 " "pointer type %2 to %select{Objective-C|block|C}3 pointer type %4 " "requires a bridged cast">; def note_arc_bridge : Note< "use __bridge to convert directly (no change in ownership)">; def note_arc_cstyle_bridge : Note< "use __bridge with C-style cast to convert directly (no change in ownership)">; def note_arc_bridge_transfer : Note< "use %select{__bridge_transfer|CFBridgingRelease call}1 to transfer " "ownership of a +1 %0 into ARC">; def note_arc_cstyle_bridge_transfer : Note< "use __bridge_transfer with C-style cast to transfer " "ownership of a +1 %0 into ARC">; def note_arc_bridge_retained : Note< "use %select{__bridge_retained|CFBridgingRetain call}1 to make an " "ARC object available as a +1 %0">; def note_arc_cstyle_bridge_retained : Note< "use __bridge_retained with C-style cast to make an " "ARC object available as a +1 %0">; } // ARC Casting category } // ARC category name def err_flexible_array_init_needs_braces : Error< "flexible array requires brace-enclosed initializer">; def err_illegal_decl_array_of_functions : Error< "'%0' declared as array of functions of type %1">; def err_illegal_decl_array_incomplete_type : Error< "array has incomplete element type %0">; def err_illegal_message_expr_incomplete_type : Error< "Objective-C message has incomplete result type %0">; def err_illegal_decl_array_of_references : Error< "'%0' declared as array of references of type %1">; def err_decl_negative_array_size : Error< "'%0' declared as an array with a negative size">; def err_array_static_outside_prototype : Error< "%0 used in array declarator outside of function prototype">; def err_array_static_not_outermost : Error< "%0 used in non-outermost array type derivation">; def err_array_star_outside_prototype : Error< "star modifier used outside of function prototype">; def err_illegal_decl_pointer_to_reference : Error< "'%0' declared as a pointer to a reference of type %1">; def err_illegal_decl_mempointer_to_reference : Error< "'%0' declared as a member pointer to a reference of type %1">; def err_illegal_decl_mempointer_to_void : Error< "'%0' declared as a member pointer to void">; def err_illegal_decl_mempointer_in_nonclass : Error< "'%0' does not point into a class">; def err_mempointer_in_nonclass_type : Error< "member pointer refers into non-class type %0">; def err_reference_to_void : Error<"cannot form a reference to 'void'">; def err_nonfunction_block_type : Error< "block pointer to non-function type is invalid">; def err_return_block_has_expr : Error<"void block should not return a value">; def err_block_return_missing_expr : Error< "non-void block should return a value">; def err_func_def_incomplete_result : Error< "incomplete result type %0 in function definition">; def err_atomic_specifier_bad_type : Error< "_Atomic cannot be applied to " "%select{incomplete |array |function |reference |atomic |qualified |}0type " "%1 %select{||||||which is not trivially copyable}0">; // Expressions. def ext_sizeof_alignof_function_type : Extension< "invalid application of '%select{sizeof|alignof|vec_step}0' to a " "function type">, InGroup; def ext_sizeof_alignof_void_type : Extension< "invalid application of '%select{sizeof|alignof|vec_step}0' to a void " "type">, InGroup; def err_opencl_sizeof_alignof_type : Error< "invalid application of '%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align}0' to a void type">; def err_sizeof_alignof_incomplete_type : Error< "invalid application of '%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align}0' to an " "incomplete type %1">; def err_sizeof_alignof_function_type : Error< "invalid application of '%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align}0' to a " "function type">; def err_openmp_default_simd_align_expr : Error< "invalid application of '__builtin_omp_required_simd_align' to an expression, only type is allowed">; def err_sizeof_alignof_typeof_bitfield : Error< "invalid application of '%select{sizeof|alignof|typeof}0' to bit-field">; def err_alignof_member_of_incomplete_type : Error< "invalid application of 'alignof' to a field of a class still being defined">; def err_vecstep_non_scalar_vector_type : Error< "'vec_step' requires built-in scalar or vector type, %0 invalid">; def err_offsetof_incomplete_type : Error< "offsetof of incomplete type %0">; def err_offsetof_record_type : Error< "offsetof requires struct, union, or class type, %0 invalid">; def err_offsetof_array_type : Error<"offsetof requires array type, %0 invalid">; def ext_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">, InGroup; def ext_offsetof_non_standardlayout_type : ExtWarn< "offset of on non-standard-layout type %0">, InGroup; def err_offsetof_bitfield : Error<"cannot compute offset of bit-field %0">; def err_offsetof_field_of_virtual_base : Error< "invalid application of 'offsetof' to a field of a virtual base">; def warn_sub_ptr_zero_size_types : Warning< "subtraction of pointers to type %0 of zero size has undefined behavior">, InGroup; def warn_pointer_arith_null_ptr : Warning< "performing pointer arithmetic on a null pointer has undefined behavior%select{| if the offset is nonzero}0">, InGroup, DefaultIgnore; def warn_gnu_null_ptr_arith : Warning< "arithmetic on a null pointer treated as a cast from integer to pointer is a GNU extension">, InGroup, DefaultIgnore; def warn_floatingpoint_eq : Warning< "comparing floating point with == or != is unsafe">, InGroup>, DefaultIgnore; def warn_remainder_division_by_zero : Warning< "%select{remainder|division}0 by zero is undefined">, InGroup; def warn_shift_lhs_negative : Warning<"shifting a negative signed value is undefined">, InGroup>; def warn_shift_negative : Warning<"shift count is negative">, InGroup>; def warn_shift_gt_typewidth : Warning<"shift count >= width of type">, InGroup>; def warn_shift_result_gt_typewidth : Warning< "signed shift result (%0) requires %1 bits to represent, but %2 only has " "%3 bits">, InGroup>; def warn_shift_result_sets_sign_bit : Warning< "signed shift result (%0) sets the sign bit of the shift expression's " "type (%1) and becomes negative">, InGroup>, DefaultIgnore; def warn_precedence_bitwise_rel : Warning< "%0 has lower precedence than %1; %1 will be evaluated first">, InGroup; def note_precedence_bitwise_first : Note< "place parentheses around the %0 expression to evaluate it first">; def note_precedence_silence : Note< "place parentheses around the '%0' expression to silence this warning">; def warn_precedence_conditional : Warning< "operator '?:' has lower precedence than '%0'; '%0' will be evaluated first">, InGroup; def note_precedence_conditional_first : Note< "place parentheses around the '?:' expression to evaluate it first">; def warn_logical_instead_of_bitwise : Warning< "use of logical '%0' with constant operand">, InGroup>; def note_logical_instead_of_bitwise_change_operator : Note< "use '%0' for a bitwise operation">; def note_logical_instead_of_bitwise_remove_constant : Note< "remove constant to silence this warning">; def warn_bitwise_op_in_bitwise_op : Warning< "'%0' within '%1'">, InGroup; def warn_logical_and_in_logical_or : Warning< "'&&' within '||'">, InGroup; def warn_overloaded_shift_in_comparison :Warning< "overloaded operator %select{>>|<<}0 has higher precedence than " "comparison operator">, InGroup; def note_evaluate_comparison_first :Note< "place parentheses around comparison expression to evaluate it first">; def warn_addition_in_bitshift : Warning< "operator '%0' has lower precedence than '%1'; " "'%1' will be evaluated first">, InGroup; def warn_self_assignment_builtin : Warning< "explicitly assigning value of variable of type %0 to itself">, InGroup, DefaultIgnore; def warn_self_assignment_overloaded : Warning< "explicitly assigning value of variable of type %0 to itself">, InGroup, DefaultIgnore; def warn_self_move : Warning< "explicitly moving variable of type %0 to itself">, InGroup, DefaultIgnore; def warn_redundant_move_on_return : Warning< "redundant move in return statement">, InGroup, DefaultIgnore; def warn_pessimizing_move_on_return : Warning< "moving a local object in a return statement prevents copy elision">, InGroup, DefaultIgnore; def warn_pessimizing_move_on_initialization : Warning< "moving a temporary object prevents copy elision">, InGroup, DefaultIgnore; def note_remove_move : Note<"remove std::move call here">; def warn_return_std_move : Warning< "local variable %0 will be copied despite being %select{returned|thrown}1 by name">, InGroup, DefaultIgnore; def note_add_std_move : Note< "call 'std::move' explicitly to avoid copying">; def warn_return_std_move_in_cxx11 : Warning< "prior to the resolution of a defect report against ISO C++11, " "local variable %0 would have been copied despite being returned by name, " "due to its not matching the function return type%diff{ ($ vs $)|}1,2">, InGroup, DefaultIgnore; def note_add_std_move_in_cxx11 : Note< "call 'std::move' explicitly to avoid copying on older compilers">; def warn_string_plus_int : Warning< "adding %0 to a string does not append to the string">, InGroup; def warn_string_plus_char : Warning< "adding %0 to a string pointer does not append to the string">, InGroup; def note_string_plus_scalar_silence : Note< "use array indexing to silence this warning">; def warn_sizeof_array_param : Warning< "sizeof on array function parameter will return size of %0 instead of %1">, InGroup; def warn_sizeof_array_decay : Warning< "sizeof on pointer operation will return size of %0 instead of %1">, InGroup; def err_sizeof_nonfragile_interface : Error< "application of '%select{alignof|sizeof}1' to interface %0 is " "not supported on this architecture and platform">; def err_atdef_nonfragile_interface : Error< "use of @defs is not supported on this architecture and platform">; def err_subscript_nonfragile_interface : Error< "subscript requires size of interface %0, which is not constant for " "this architecture and platform">; def err_arithmetic_nonfragile_interface : Error< "arithmetic on pointer to interface %0, which is not a constant size for " "this architecture and platform">; def ext_subscript_non_lvalue : Extension< "ISO C90 does not allow subscripting non-lvalue array">; def err_typecheck_subscript_value : Error< "subscripted value is not an array, pointer, or vector">; def err_typecheck_subscript_not_integer : Error< "array subscript is not an integer">; def err_subscript_function_type : Error< "subscript of pointer to function type %0">; def err_subscript_incomplete_type : Error< "subscript of pointer to incomplete type %0">; def err_dereference_incomplete_type : Error< "dereference of pointer to incomplete type %0">; def ext_gnu_subscript_void_type : Extension< "subscript of a pointer to void is a GNU extension">, InGroup; def err_typecheck_member_reference_struct_union : Error< "member reference base type %0 is not a structure or union">; def err_typecheck_member_reference_ivar : Error< "%0 does not have a member named %1">; def err_arc_weak_ivar_access : Error< "dereferencing a __weak pointer is not allowed due to possible " "null value caused by race condition, assign it to strong variable first">; def err_typecheck_member_reference_arrow : Error< "member reference type %0 is not a pointer">; def err_typecheck_member_reference_suggestion : Error< "member reference type %0 is %select{a|not a}1 pointer; did you mean to use '%select{->|.}1'?">; def note_typecheck_member_reference_suggestion : Note< "did you mean to use '.' instead?">; def note_member_reference_arrow_from_operator_arrow : Note< "'->' applied to return value of the operator->() declared here">; def err_typecheck_member_reference_type : Error< "cannot refer to type member %0 in %1 with '%select{.|->}2'">; def err_typecheck_member_reference_unknown : Error< "cannot refer to member %0 in %1 with '%select{.|->}2'">; def err_member_reference_needs_call : Error< "base of member reference is a function; perhaps you meant to call " "it%select{| with no arguments}0?">; def warn_subscript_is_char : Warning<"array subscript is of type 'char'">, InGroup, DefaultIgnore; def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">; def err_no_member : Error<"no member named %0 in %1">; def err_no_member_overloaded_arrow : Error< "no member named %0 in %1; did you mean to use '->' instead of '.'?">; def err_member_not_yet_instantiated : Error< "no member %0 in %1; it has not yet been instantiated">; def note_non_instantiated_member_here : Note< "not-yet-instantiated member is declared here">; def err_enumerator_does_not_exist : Error< "enumerator %0 does not exist in instantiation of %1">; def note_enum_specialized_here : Note< "enum %0 was explicitly specialized here">; def err_specialization_not_primary_template : Error< "cannot reference member of primary template because deduced class " "template specialization %0 is %select{instantiated from a partial|" "an explicit}1 specialization">; def err_member_redeclared : Error<"class member cannot be redeclared">; def ext_member_redeclared : ExtWarn<"class member cannot be redeclared">, InGroup; def err_member_redeclared_in_instantiation : Error< "multiple overloads of %0 instantiate to the same signature %1">; def err_member_name_of_class : Error<"member %0 has the same name as its class">; def err_member_def_undefined_record : Error< "out-of-line definition of %0 from class %1 without definition">; def err_member_decl_does_not_match : Error< "out-of-line %select{declaration|definition}2 of %0 " "does not match any declaration in %1">; def err_friend_decl_with_def_arg_must_be_def : Error< "friend declaration specifying a default argument must be a definition">; def err_friend_decl_with_def_arg_redeclared : Error< "friend declaration specifying a default argument must be the only declaration">; def err_friend_decl_does_not_match : Error< "friend declaration of %0 does not match any declaration in %1">; def err_member_decl_does_not_match_suggest : Error< "out-of-line %select{declaration|definition}2 of %0 " "does not match any declaration in %1; did you mean %3?">; def err_member_def_does_not_match_ret_type : Error< "return type of out-of-line definition of %q0 differs from " "that in the declaration">; def err_nonstatic_member_out_of_line : Error< "non-static data member defined out-of-line">; def err_qualified_typedef_declarator : Error< "typedef declarator cannot be qualified">; def err_qualified_param_declarator : Error< "parameter declarator cannot be qualified">; def ext_out_of_line_declaration : ExtWarn< "out-of-line declaration of a member must be a definition">, InGroup, DefaultError; def err_member_extra_qualification : Error< "extra qualification on member %0">; def warn_member_extra_qualification : Warning< err_member_extra_qualification.Text>, InGroup; def warn_namespace_member_extra_qualification : Warning< "extra qualification on member %0">, InGroup>; def err_member_qualification : Error< "non-friend class member %0 cannot have a qualified name">; def note_member_def_close_match : Note<"member declaration nearly matches">; def note_member_def_close_const_match : Note< "member declaration does not match because " "it %select{is|is not}0 const qualified">; def note_member_def_close_param_match : Note< "type of %ordinal0 parameter of member declaration does not match definition" "%diff{ ($ vs $)|}1,2">; def note_local_decl_close_match : Note<"local declaration nearly matches">; def note_local_decl_close_param_match : Note< "type of %ordinal0 parameter of local declaration does not match definition" "%diff{ ($ vs $)|}1,2">; def err_typecheck_ivar_variable_size : Error< "instance variables must have a constant size">; def err_ivar_reference_type : Error< "instance variables cannot be of reference type">; def err_typecheck_illegal_increment_decrement : Error< "cannot %select{decrement|increment}1 value of type %0">; def err_typecheck_expect_int : Error< "used type %0 where integer is required">; def err_typecheck_arithmetic_incomplete_type : Error< "arithmetic on a pointer to an incomplete type %0">; def err_typecheck_pointer_arith_function_type : Error< "arithmetic on%select{ a|}0 pointer%select{|s}0 to%select{ the|}2 " "function type%select{|s}2 %1%select{| and %3}2">; def err_typecheck_pointer_arith_void_type : Error< "arithmetic on%select{ a|}0 pointer%select{|s}0 to void">; def err_typecheck_decl_incomplete_type : Error< "variable has incomplete type %0">; def ext_typecheck_decl_incomplete_type : ExtWarn< "tentative definition of variable with internal linkage has incomplete non-array type %0">, InGroup>; def err_tentative_def_incomplete_type : Error< "tentative definition has type %0 that is never completed">; def warn_tentative_incomplete_array : Warning< "tentative array definition assumed to have one element">; def err_typecheck_incomplete_array_needs_initializer : Error< "definition of variable with array type needs an explicit size " "or an initializer">; def err_array_init_not_init_list : Error< "array initializer must be an initializer " "list%select{| or string literal| or wide string literal}0">; def err_array_init_narrow_string_into_wchar : Error< "initializing wide char array with non-wide string literal">; def err_array_init_wide_string_into_char : Error< "initializing char array with wide string literal">; def err_array_init_incompat_wide_string_into_wchar : Error< "initializing wide char array with incompatible wide string literal">; def err_array_init_plain_string_into_char8_t : Error< "initializing 'char8_t' array with plain string literal">; def note_array_init_plain_string_into_char8_t : Note< "add 'u8' prefix to form a 'char8_t' string literal">; def err_array_init_utf8_string_into_char : Error< "initialization of char array with UTF-8 string literal is not permitted " "by '-fchar8_t'">; def err_array_init_different_type : Error< "cannot initialize array %diff{of type $ with array of type $|" "with different type of array}0,1">; def err_array_init_non_constant_array : Error< "cannot initialize array %diff{of type $ with non-constant array of type $|" "with different type of array}0,1">; def ext_array_init_copy : Extension< "initialization of an array " "%diff{of type $ from a compound literal of type $|" "from a compound literal}0,1 is a GNU extension">, InGroup; // This is intentionally not disabled by -Wno-gnu. def ext_array_init_parens : ExtWarn< "parenthesized initialization of a member array is a GNU extension">, InGroup>, DefaultError; def warn_deprecated_string_literal_conversion : Warning< "conversion from string literal to %0 is deprecated">, InGroup; def ext_deprecated_string_literal_conversion : ExtWarn< "ISO C++11 does not allow conversion from string literal to %0">, InGroup, SFINAEFailure; def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">; def err_typecheck_sclass_fscope : Error< "illegal storage class on file-scoped variable">; def warn_standalone_specifier : Warning<"'%0' ignored on this declaration">, InGroup; def ext_standalone_specifier : ExtWarn<"'%0' is not permitted on a declaration " "of a type">, InGroup; def err_standalone_class_nested_name_specifier : Error< "forward declaration of %select{class|struct|interface|union|enum}0 cannot " "have a nested name specifier">; def err_typecheck_sclass_func : Error<"illegal storage class on function">; def err_static_block_func : Error< "function declared in block scope cannot have 'static' storage class">; def err_typecheck_address_of : Error<"address of %select{bit-field" "|vector element|property expression|register variable}0 requested">; def ext_typecheck_addrof_void : Extension< "ISO C forbids taking the address of an expression of type 'void'">; def err_unqualified_pointer_member_function : Error< "must explicitly qualify name of member function when taking its address">; def err_invalid_form_pointer_member_function : Error< "cannot create a non-constant pointer to member function">; def err_address_of_function_with_pass_object_size_params: Error< "cannot take address of function %0 because parameter %1 has " "pass_object_size attribute">; def err_parens_pointer_member_function : Error< "cannot parenthesize the name of a method when forming a member pointer">; def err_typecheck_invalid_lvalue_addrof_addrof_function : Error< "extra '&' taking address of overloaded function">; def err_typecheck_invalid_lvalue_addrof : Error< "cannot take the address of an rvalue of type %0">; def ext_typecheck_addrof_temporary : ExtWarn< "taking the address of a temporary object of type %0">, InGroup, DefaultError; def err_typecheck_addrof_temporary : Error< "taking the address of a temporary object of type %0">; def err_typecheck_addrof_dtor : Error< "taking the address of a destructor">; def err_typecheck_unary_expr : Error< "invalid argument type %0 to unary expression">; def err_typecheck_indirection_requires_pointer : Error< "indirection requires pointer operand (%0 invalid)">; def ext_typecheck_indirection_through_void_pointer : ExtWarn< "ISO C++ does not allow indirection on operand of type %0">, InGroup>; def warn_indirection_through_null : Warning< "indirection of non-volatile null pointer will be deleted, not trap">, InGroup; def warn_binding_null_to_reference : Warning< "binding dereferenced null pointer to reference has undefined behavior">, InGroup; def note_indirection_through_null : Note< "consider using __builtin_trap() or qualifying pointer with 'volatile'">; def warn_pointer_indirection_from_incompatible_type : Warning< "dereference of type %1 that was reinterpret_cast from type %0 has undefined " "behavior">, InGroup, DefaultIgnore; def warn_taking_address_of_packed_member : Warning< "taking address of packed member %0 of class or structure %q1 may result in an unaligned pointer value">, InGroup>; def err_objc_object_assignment : Error< "cannot assign to class object (%0 invalid)">; def err_typecheck_invalid_operands : Error< "invalid operands to binary expression (%0 and %1)">; def note_typecheck_invalid_operands_converted : Note< "%select{first|second}0 operand was implicitly converted to type %1">; def err_typecheck_logical_vector_expr_gnu_cpp_restrict : Error< "logical expression with vector %select{type %1 and non-vector type %2|types" " %1 and %2}0 is only supported in C++">; def err_typecheck_sub_ptr_compatible : Error< "%diff{$ and $ are not pointers to compatible types|" "pointers to incompatible types}0,1">; def ext_typecheck_ordered_comparison_of_pointer_integer : ExtWarn< "ordered comparison between pointer and integer (%0 and %1)">; def ext_typecheck_ordered_comparison_of_pointer_and_zero : Extension< "ordered comparison between pointer and zero (%0 and %1) is an extension">; def err_typecheck_ordered_comparison_of_pointer_and_zero : Error< "ordered comparison between pointer and zero (%0 and %1)">; def ext_typecheck_ordered_comparison_of_function_pointers : ExtWarn< "ordered comparison of function pointers (%0 and %1)">, InGroup>; def ext_typecheck_comparison_of_fptr_to_void : Extension< "equality comparison between function pointer and void pointer (%0 and %1)">; def err_typecheck_comparison_of_fptr_to_void : Error< "equality comparison between function pointer and void pointer (%0 and %1)">; def ext_typecheck_comparison_of_pointer_integer : ExtWarn< "comparison between pointer and integer (%0 and %1)">; def err_typecheck_comparison_of_pointer_integer : Error< "comparison between pointer and integer (%0 and %1)">; def ext_typecheck_comparison_of_distinct_pointers : ExtWarn< "comparison of distinct pointer types%diff{ ($ and $)|}0,1">, InGroup; def ext_typecheck_cond_incompatible_operands : ExtWarn< "incompatible operand types (%0 and %1)">; def err_cond_voidptr_arc : Error < "operands to conditional of types%diff{ $ and $|}0,1 are incompatible " "in ARC mode">; def err_typecheck_comparison_of_distinct_pointers : Error< "comparison of distinct pointer types%diff{ ($ and $)|}0,1">; def err_typecheck_op_on_nonoverlapping_address_space_pointers : Error< "%select{comparison between %diff{ ($ and $)|}0,1" "|arithmetic operation with operands of type %diff{ ($ and $)|}0,1" "|conditional operator with the second and third operands of type " "%diff{ ($ and $)|}0,1}2" " which are pointers to non-overlapping address spaces">; def err_typecheck_assign_const : Error< "%select{" "cannot assign to return value because function %1 returns a const value|" "cannot assign to variable %1 with const-qualified type %2|" "cannot assign to %select{non-|}1static data member %2 " "with const-qualified type %3|" "cannot assign to non-static data member within const member function %1|" "cannot assign to %select{variable %2|non-static data member %2|lvalue}1 " "with %select{|nested }3const-qualified data member %4|" "read-only variable is not assignable}0">; def note_typecheck_assign_const : Note< "%select{" "function %1 which returns const-qualified type %2 declared here|" "variable %1 declared const here|" "%select{non-|}1static data member %2 declared const here|" "member function %q1 is declared const here|" "%select{|nested }1data member %2 declared const here}0">; def warn_unsigned_always_true_comparison : Warning< "result of comparison of %select{%3|unsigned expression}0 %2 " "%select{unsigned expression|%3}0 is always %4">, InGroup, DefaultIgnore; def warn_unsigned_enum_always_true_comparison : Warning< "result of comparison of %select{%3|unsigned enum expression}0 %2 " "%select{unsigned enum expression|%3}0 is always %4">, InGroup, DefaultIgnore; def warn_tautological_constant_compare : Warning< "result of comparison %select{%3|%1}0 %2 " "%select{%1|%3}0 is always %4">, InGroup, DefaultIgnore; def warn_mixed_sign_comparison : Warning< "comparison of integers of different signs: %0 and %1">, InGroup, DefaultIgnore; def warn_out_of_range_compare : Warning< "result of comparison of %select{constant %0|true|false}1 with " "%select{expression of type %2|boolean expression}3 is always %4">, InGroup; def warn_tautological_bool_compare : Warning, InGroup; def warn_comparison_of_mixed_enum_types : Warning< "comparison of two values with different enumeration types" "%diff{ ($ and $)|}0,1">, InGroup; def warn_comparison_of_mixed_enum_types_switch : Warning< "comparison of two values with different enumeration types in switch statement" "%diff{ ($ and $)|}0,1">, InGroup; def warn_null_in_arithmetic_operation : Warning< "use of NULL in arithmetic operation">, InGroup; def warn_null_in_comparison_operation : Warning< "comparison between NULL and non-pointer " "%select{(%1 and NULL)|(NULL and %1)}0">, InGroup; def err_shift_rhs_only_vector : Error< "requested shift is a vector of type %0 but the first operand is not a " "vector (%1)">; def warn_logical_not_on_lhs_of_check : Warning< "logical not is only applied to the left hand side of this " "%select{comparison|bitwise operator}0">, InGroup; def note_logical_not_fix : Note< "add parentheses after the '!' to evaluate the " "%select{comparison|bitwise operator}0 first">; def note_logical_not_silence_with_parens : Note< "add parentheses around left hand side expression to silence this warning">; def err_invalid_this_use : Error< "invalid use of 'this' outside of a non-static member function">; def err_this_static_member_func : Error< "'this' cannot be%select{| implicitly}0 used in a static member function " "declaration">; def err_invalid_member_use_in_static_method : Error< "invalid use of member %0 in static member function">; def err_invalid_qualified_function_type : Error< "%select{non-member function|static member function|deduction guide}0 " "%select{of type %2 |}1cannot have '%3' qualifier">; def err_compound_qualified_function_type : Error< "%select{block pointer|pointer|reference}0 to function type %select{%2 |}1" "cannot have '%3' qualifier">; def err_ref_qualifier_overload : Error< "cannot overload a member function %select{without a ref-qualifier|with " "ref-qualifier '&'|with ref-qualifier '&&'}0 with a member function %select{" "without a ref-qualifier|with ref-qualifier '&'|with ref-qualifier '&&'}1">; def err_invalid_non_static_member_use : Error< "invalid use of non-static data member %0">; def err_nested_non_static_member_use : Error< "%select{call to non-static member function|use of non-static data member}0 " "%2 of %1 from nested type %3">; def warn_cxx98_compat_non_static_member_use : Warning< "use of non-static data member %0 in an unevaluated context is " "incompatible with C++98">, InGroup, DefaultIgnore; def err_invalid_incomplete_type_use : Error< "invalid use of incomplete type %0">; def err_builtin_func_cast_more_than_one_arg : Error< "function-style cast to a builtin type can only take one argument">; def err_value_init_for_array_type : Error< "array types cannot be value-initialized">; def err_init_for_function_type : Error< "cannot create object of function type %0">; def warn_format_nonliteral_noargs : Warning< "format string is not a string literal (potentially insecure)">, InGroup; def warn_format_nonliteral : Warning< "format string is not a string literal">, InGroup, DefaultIgnore; def err_unexpected_interface : Error< "unexpected interface name %0: expected expression">; def err_ref_non_value : Error<"%0 does not refer to a value">; def err_ref_vm_type : Error< "cannot refer to declaration with a variably modified type inside block">; def err_ref_flexarray_type : Error< "cannot refer to declaration of structure variable with flexible array member " "inside block">; def err_ref_array_type : Error< "cannot refer to declaration with an array type inside block">; def err_property_not_found : Error< "property %0 not found on object of type %1">; def err_invalid_property_name : Error< "%0 is not a valid property name (accessing an object of type %1)">; def err_getter_not_found : Error< "no getter method for read from property">; def err_objc_subscript_method_not_found : Error< "expected method to %select{read|write}1 %select{dictionary|array}2 element not " "found on object of type %0">; def err_objc_subscript_index_type : Error< "method index parameter type %0 is not integral type">; def err_objc_subscript_key_type : Error< "method key parameter type %0 is not object type">; def err_objc_subscript_dic_object_type : Error< "method object parameter type %0 is not object type">; def err_objc_subscript_object_type : Error< "cannot assign to this %select{dictionary|array}1 because assigning method's " "2nd parameter of type %0 is not an Objective-C pointer type">; def err_objc_subscript_base_type : Error< "%select{dictionary|array}1 subscript base type %0 is not an Objective-C object">; def err_objc_multiple_subscript_type_conversion : Error< "indexing expression is invalid because subscript type %0 has " "multiple type conversion functions">; def err_objc_subscript_type_conversion : Error< "indexing expression is invalid because subscript type %0 is not an integral" " or Objective-C pointer type">; def err_objc_subscript_pointer : Error< "indexing expression is invalid because subscript type %0 is not an" " Objective-C pointer">; def err_objc_indexing_method_result_type : Error< "method for accessing %select{dictionary|array}1 element must have Objective-C" " object return type instead of %0">; def err_objc_index_incomplete_class_type : Error< "Objective-C index expression has incomplete class type %0">; def err_illegal_container_subscripting_op : Error< "illegal operation on Objective-C container subscripting">; def err_property_not_found_forward_class : Error< "property %0 cannot be found in forward class object %1">; def err_property_not_as_forward_class : Error< "property %0 refers to an incomplete Objective-C class %1 " "(with no @interface available)">; def note_forward_class : Note< "forward declaration of class here">; def err_duplicate_property : Error< "property has a previous declaration">; def ext_gnu_void_ptr : Extension< "arithmetic on%select{ a|}0 pointer%select{|s}0 to void is a GNU extension">, InGroup; def ext_gnu_ptr_func_arith : Extension< "arithmetic on%select{ a|}0 pointer%select{|s}0 to%select{ the|}2 function " "type%select{|s}2 %1%select{| and %3}2 is a GNU extension">, InGroup; def err_readonly_message_assignment : Error< "assigning to 'readonly' return result of an Objective-C message not allowed">; def ext_integer_increment_complex : Extension< "ISO C does not support '++'/'--' on complex integer type %0">; def ext_integer_complement_complex : Extension< "ISO C does not support '~' for complex conjugation of %0">; def err_nosetter_property_assignment : Error< "%select{assignment to readonly property|" "no setter method %1 for assignment to property}0">; def err_nosetter_property_incdec : Error< "%select{%select{increment|decrement}1 of readonly property|" "no setter method %2 for %select{increment|decrement}1 of property}0">; def err_nogetter_property_compound_assignment : Error< "a getter method is needed to perform a compound assignment on a property">; def err_nogetter_property_incdec : Error< "no getter method %1 for %select{increment|decrement}0 of property">; def err_no_subobject_property_setting : Error< "expression is not assignable">; def err_qualified_objc_access : Error< "%select{property|instance variable}0 access cannot be qualified with '%1'">; def ext_freestanding_complex : Extension< "complex numbers are an extension in a freestanding C99 implementation">; // FIXME: Remove when we support imaginary. def err_imaginary_not_supported : Error<"imaginary types are not supported">; // Obj-c expressions def warn_root_inst_method_not_found : Warning< "instance method %0 is being used on 'Class' which is not in the root class">, InGroup; def warn_class_method_not_found : Warning< "class method %objcclass0 not found (return type defaults to 'id')">, InGroup; def warn_instance_method_on_class_found : Warning< "instance method %0 found instead of class method %1">, InGroup; def warn_inst_method_not_found : Warning< "instance method %objcinstance0 not found (return type defaults to 'id')">, InGroup; def warn_instance_method_not_found_with_typo : Warning< "instance method %objcinstance0 not found (return type defaults to 'id')" "; did you mean %objcinstance2?">, InGroup; def warn_class_method_not_found_with_typo : Warning< "class method %objcclass0 not found (return type defaults to 'id')" "; did you mean %objcclass2?">, InGroup; def err_method_not_found_with_typo : Error< "%select{instance|class}1 method %0 not found " "; did you mean %2?">; def err_no_super_class_message : Error< "no @interface declaration found in class messaging of %0">; def err_root_class_cannot_use_super : Error< "%0 cannot use 'super' because it is a root class">; def err_invalid_receiver_to_message_super : Error< "'super' is only valid in a method body">; def err_invalid_receiver_class_message : Error< "receiver type %0 is not an Objective-C class">; def err_missing_open_square_message_send : Error< "missing '[' at start of message send expression">; def warn_bad_receiver_type : Warning< "receiver type %0 is not 'id' or interface pointer, consider " "casting it to 'id'">,InGroup; def err_bad_receiver_type : Error<"bad receiver type %0">; def err_incomplete_receiver_type : Error<"incomplete receiver type %0">; def err_unknown_receiver_suggest : Error< "unknown receiver %0; did you mean %1?">; def err_objc_throw_expects_object : Error< "@throw requires an Objective-C object type (%0 invalid)">; def err_objc_synchronized_expects_object : Error< "@synchronized requires an Objective-C object type (%0 invalid)">; def err_rethrow_used_outside_catch : Error< "@throw (rethrow) used outside of a @catch block">; def err_attribute_multiple_objc_gc : Error< "multiple garbage collection attributes specified for type">; def err_catch_param_not_objc_type : Error< "@catch parameter is not a pointer to an interface type">; def err_illegal_qualifiers_on_catch_parm : Error< "illegal qualifiers on @catch parameter">; def err_storage_spec_on_catch_parm : Error< "@catch parameter cannot have storage specifier '%0'">; def warn_register_objc_catch_parm : Warning< "'register' storage specifier on @catch parameter will be ignored">; def err_qualified_objc_catch_parm : Error< "@catch parameter declarator cannot be qualified">; def warn_objc_pointer_cxx_catch_fragile : Warning< "cannot catch an exception thrown with @throw in C++ in the non-unified " "exception model">, InGroup; def err_objc_object_catch : Error< "cannot catch an Objective-C object by value">; def err_incomplete_type_objc_at_encode : Error< "'@encode' of incomplete type %0">; def warn_objc_circular_container : Warning< "adding %0 to %1 might cause circular dependency in container">, InGroup>; def note_objc_circular_container_declared_here : Note<"%0 declared here">; def warn_objc_unsafe_perform_selector : Warning< "%0 is incompatible with selectors that return a " "%select{struct|union|vector}1 type">, InGroup>; def note_objc_unsafe_perform_selector_method_declared_here : Note< "method %0 that returns %1 declared here">; def warn_setter_getter_impl_required : Warning< "property %0 requires method %1 to be defined - " "use @synthesize, @dynamic or provide a method implementation " "in this class implementation">, InGroup; def warn_setter_getter_impl_required_in_category : Warning< "property %0 requires method %1 to be defined - " "use @dynamic or provide a method implementation in this category">, InGroup; def note_parameter_named_here : Note< "passing argument to parameter %0 here">; def note_parameter_here : Note< "passing argument to parameter here">; def note_method_return_type_change : Note< "compiler has implicitly changed method %0 return type">; def warn_impl_required_for_class_property : Warning< "class property %0 requires method %1 to be defined - " "use @dynamic or provide a method implementation " "in this class implementation">, InGroup; def warn_impl_required_in_category_for_class_property : Warning< "class property %0 requires method %1 to be defined - " "use @dynamic or provide a method implementation in this category">, InGroup; // C++ casts // These messages adhere to the TryCast pattern: %0 is an int specifying the // cast type, %1 is the source type, %2 is the destination type. def err_bad_reinterpret_cast_overload : Error< "reinterpret_cast cannot resolve overloaded function %0 to type %1">; def warn_reinterpret_different_from_static : Warning< "'reinterpret_cast' %select{from|to}3 class %0 %select{to|from}3 its " "%select{virtual base|base at non-zero offset}2 %1 behaves differently from " "'static_cast'">, InGroup; def note_reinterpret_updowncast_use_static: Note< "use 'static_cast' to adjust the pointer correctly while " "%select{upcasting|downcasting}0">; def err_bad_static_cast_overload : Error< "address of overloaded function %0 cannot be static_cast to type %1">; def err_bad_cstyle_cast_overload : Error< "address of overloaded function %0 cannot be cast to type %1">; def err_bad_cxx_cast_generic : Error< "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" "functional-style cast}0 from %1 to %2 is not allowed">; def err_bad_cxx_cast_unrelated_class : Error< "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" "functional-style cast}0 from %1 to %2, which are not related by " "inheritance, is not allowed">; def note_type_incomplete : Note<"%0 is incomplete">; def err_bad_cxx_cast_rvalue : Error< "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" "functional-style cast}0 from rvalue to reference type %2">; def err_bad_cxx_cast_bitfield : Error< "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" "functional-style cast}0 from bit-field lvalue to reference type %2">; def err_bad_cxx_cast_qualifiers_away : Error< "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" "functional-style cast}0 from %1 to %2 casts away qualifiers">; def ext_bad_cxx_cast_qualifiers_away_incoherent : ExtWarn< "ISO C++ does not allow " "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" "functional-style cast}0 from %1 to %2 because it casts away qualifiers, " "even though the source and destination types are unrelated">, SFINAEFailure, InGroup>; def err_bad_const_cast_dest : Error< "%select{const_cast||||C-style cast|functional-style cast}0 to %2, " "which is not a reference, pointer-to-object, or pointer-to-data-member">; def ext_cast_fn_obj : Extension< "cast between pointer-to-function and pointer-to-object is an extension">; def ext_ms_cast_fn_obj : ExtWarn< "static_cast between pointer-to-function and pointer-to-object is a " "Microsoft extension">, InGroup; def warn_cxx98_compat_cast_fn_obj : Warning< "cast between pointer-to-function and pointer-to-object is incompatible with C++98">, InGroup, DefaultIgnore; def err_bad_reinterpret_cast_small_int : Error< "cast from pointer to smaller type %2 loses information">; def err_bad_cxx_cast_vector_to_scalar_different_size : Error< "%select{||reinterpret_cast||C-style cast|}0 from vector %1 " "to scalar %2 of different size">; def err_bad_cxx_cast_scalar_to_vector_different_size : Error< "%select{||reinterpret_cast||C-style cast|}0 from scalar %1 " "to vector %2 of different size">; def err_bad_cxx_cast_vector_to_vector_different_size : Error< "%select{||reinterpret_cast||C-style cast|}0 from vector %1 " "to vector %2 of different size">; def err_bad_lvalue_to_rvalue_cast : Error< "cannot cast from lvalue of type %1 to rvalue reference type %2; types are " "not compatible">; def err_bad_rvalue_to_rvalue_cast : Error< "cannot cast from rvalue of type %1 to rvalue reference type %2; types are " "not compatible">; def err_bad_static_cast_pointer_nonpointer : Error< "cannot cast from type %1 to pointer type %2">; def err_bad_static_cast_member_pointer_nonmp : Error< "cannot cast from type %1 to member pointer type %2">; def err_bad_cxx_cast_member_pointer_size : Error< "cannot %select{||reinterpret_cast||C-style cast|}0 from member pointer " "type %1 to member pointer type %2 of different size">; def err_bad_reinterpret_cast_reference : Error< "reinterpret_cast of a %0 to %1 needs its address, which is not allowed">; def warn_undefined_reinterpret_cast : Warning< "reinterpret_cast from %0 to %1 has undefined behavior">, InGroup, DefaultIgnore; // These messages don't adhere to the pattern. // FIXME: Display the path somehow better. def err_ambiguous_base_to_derived_cast : Error< "ambiguous cast from base %0 to derived %1:%2">; def err_static_downcast_via_virtual : Error< "cannot cast %0 to %1 via virtual base %2">; def err_downcast_from_inaccessible_base : Error< "cannot cast %select{private|protected}2 base class %1 to %0">; def err_upcast_to_inaccessible_base : Error< "cannot cast %0 to its %select{private|protected}2 base class %1">; def err_bad_dynamic_cast_not_ref_or_ptr : Error< "%0 is not a reference or pointer">; def err_bad_dynamic_cast_not_class : Error<"%0 is not a class">; def err_bad_dynamic_cast_incomplete : Error<"%0 is an incomplete type">; def err_bad_dynamic_cast_not_ptr : Error<"%0 is not a pointer">; def err_bad_dynamic_cast_not_polymorphic : Error<"%0 is not polymorphic">; // Other C++ expressions def err_need_header_before_typeid : Error< "you need to include before using the 'typeid' operator">; def err_need_header_before_ms_uuidof : Error< "you need to include before using the '__uuidof' operator">; def err_ms___leave_not_in___try : Error< "'__leave' statement not in __try block">; def err_uuidof_without_guid : Error< "cannot call operator __uuidof on a type with no GUID">; def err_uuidof_with_multiple_guids : Error< "cannot call operator __uuidof on a type with multiple GUIDs">; def err_incomplete_typeid : Error<"'typeid' of incomplete type %0">; def err_variably_modified_typeid : Error<"'typeid' of variably modified type %0">; def err_static_illegal_in_new : Error< "the 'static' modifier for the array size is not legal in new expressions">; def err_array_new_needs_size : Error< "array size must be specified in new expressions">; def err_bad_new_type : Error< "cannot allocate %select{function|reference}1 type %0 with new">; def err_new_incomplete_type : Error< "allocation of incomplete type %0">; def err_new_array_nonconst : Error< "only the first dimension of an allocated array may have dynamic size">; def err_new_array_init_args : Error< "array 'new' cannot have initialization arguments">; def ext_new_paren_array_nonconst : ExtWarn< "when type is in parentheses, array cannot have dynamic size">; def err_placement_new_non_placement_delete : Error< "'new' expression with placement arguments refers to non-placement " "'operator delete'">; def err_array_size_not_integral : Error< "array size expression must have integral or %select{|unscoped }0" "enumeration type, not %1">; def err_array_size_incomplete_type : Error< "array size expression has incomplete class type %0">; def err_array_size_explicit_conversion : Error< "array size expression of type %0 requires explicit conversion to type %1">; def note_array_size_conversion : Note< "conversion to %select{integral|enumeration}0 type %1 declared here">; def err_array_size_ambiguous_conversion : Error< "ambiguous conversion of array size expression of type %0 to an integral or " "enumeration type">; def ext_array_size_conversion : Extension< "implicit conversion from array size expression of type %0 to " "%select{integral|enumeration}1 type %2 is a C++11 extension">, InGroup; def warn_cxx98_compat_array_size_conversion : Warning< "implicit conversion from array size expression of type %0 to " "%select{integral|enumeration}1 type %2 is incompatible with C++98">, InGroup, DefaultIgnore; def err_address_space_qualified_new : Error< "'new' cannot allocate objects of type %0 in address space '%1'">; def err_address_space_qualified_delete : Error< "'delete' cannot delete objects of type %0 in address space '%1'">; def err_default_init_const : Error< "default initialization of an object of const type %0" "%select{| without a user-provided default constructor}1">; def ext_default_init_const : ExtWarn< "default initialization of an object of const type %0" "%select{| without a user-provided default constructor}1 " "is a Microsoft extension">, InGroup; def err_delete_operand : Error<"cannot delete expression of type %0">; def ext_delete_void_ptr_operand : ExtWarn< "cannot delete expression with pointer-to-'void' type %0">, InGroup; def err_ambiguous_delete_operand : Error< "ambiguous conversion of delete expression of type %0 to a pointer">; def warn_delete_incomplete : Warning< "deleting pointer to incomplete type %0 may cause undefined behavior">, InGroup; def err_delete_incomplete_class_type : Error< "deleting incomplete class type %0; no conversions to pointer type">; def err_delete_explicit_conversion : Error< "converting delete expression from type %0 to type %1 invokes an explicit " "conversion function">; def note_delete_conversion : Note<"conversion to pointer type %0">; def warn_delete_array_type : Warning< "'delete' applied to a pointer-to-array type %0 treated as 'delete[]'">; def warn_mismatched_delete_new : Warning< "'delete%select{|[]}0' applied to a pointer that was allocated with " "'new%select{[]|}0'; did you mean 'delete%select{[]|}0'?">, InGroup>; def note_allocated_here : Note<"allocated with 'new%select{[]|}0' here">; def err_no_suitable_delete_member_function_found : Error< "no suitable member %0 in %1">; def err_ambiguous_suitable_delete_member_function_found : Error< "multiple suitable %0 functions in %1">; def warn_ambiguous_suitable_delete_function_found : Warning< "multiple suitable %0 functions for %1; no 'operator delete' function " "will be invoked if initialization throws an exception">, InGroup>; def note_member_declared_here : Note< "member %0 declared here">; def note_member_first_declared_here : Note< "member %0 first declared here">; def err_decrement_bool : Error<"cannot decrement expression of type bool">; def warn_increment_bool : Warning< "incrementing expression of type bool is deprecated and " "incompatible with C++17">, InGroup; def ext_increment_bool : ExtWarn< "ISO C++17 does not allow incrementing expression of type bool">, DefaultError, InGroup; def err_increment_decrement_enum : Error< "cannot %select{decrement|increment}0 expression of enum type %1">; def err_catch_incomplete_ptr : Error< "cannot catch pointer to incomplete type %0">; def err_catch_incomplete_ref : Error< "cannot catch reference to incomplete type %0">; def err_catch_incomplete : Error<"cannot catch incomplete type %0">; def err_catch_rvalue_ref : Error<"cannot catch exceptions by rvalue reference">; def err_catch_variably_modified : Error< "cannot catch variably modified type %0">; def err_qualified_catch_declarator : Error< "exception declarator cannot be qualified">; def err_early_catch_all : Error<"catch-all handler must come last">; def err_bad_memptr_rhs : Error< "right hand operand to %0 has non-pointer-to-member type %1">; def err_bad_memptr_lhs : Error< "left hand operand to %0 must be a %select{|pointer to }1class " "compatible with the right hand operand, but is %2">; def err_memptr_incomplete : Error< "member pointer has incomplete base type %0">; def warn_exception_caught_by_earlier_handler : Warning< "exception of type %0 will be caught by earlier handler">, InGroup; def note_previous_exception_handler : Note<"for type %0">; def err_exceptions_disabled : Error< "cannot use '%0' with exceptions disabled">; def err_objc_exceptions_disabled : Error< "cannot use '%0' with Objective-C exceptions disabled">; def warn_throw_in_noexcept_func : Warning< "%0 has a non-throwing exception specification but can still throw">, InGroup; def note_throw_in_dtor : Note< "%select{destructor|deallocator}0 has a %select{non-throwing|implicit " "non-throwing}1 exception specification">; def note_throw_in_function : Note<"function declared non-throwing here">; def err_seh_try_outside_functions : Error< "cannot use SEH '__try' in blocks, captured regions, or Obj-C method decls">; def err_mixing_cxx_try_seh_try : Error< "cannot use C++ 'try' in the same function as SEH '__try'">; def err_seh_try_unsupported : Error< "SEH '__try' is not supported on this target">; def note_conflicting_try_here : Note< "conflicting %0 here">; def warn_jump_out_of_seh_finally : Warning< "jump out of __finally block has undefined behavior">, InGroup>; def warn_non_virtual_dtor : Warning< "%0 has virtual functions but non-virtual destructor">, InGroup, DefaultIgnore; def warn_delete_non_virtual_dtor : Warning< "%select{delete|destructor}0 called on non-final %1 that has " "virtual functions but non-virtual destructor">, InGroup, DefaultIgnore, ShowInSystemHeader; def note_delete_non_virtual : Note< "qualify call to silence this warning">; def warn_delete_abstract_non_virtual_dtor : Warning< "%select{delete|destructor}0 called on %1 that is abstract but has " "non-virtual destructor">, InGroup, ShowInSystemHeader; def warn_overloaded_virtual : Warning< "%q0 hides overloaded virtual %select{function|functions}1">, InGroup, DefaultIgnore; def note_hidden_overloaded_virtual_declared_here : Note< "hidden overloaded virtual function %q0 declared here" "%select{|: different classes%diff{ ($ vs $)|}2,3" "|: different number of parameters (%2 vs %3)" "|: type mismatch at %ordinal2 parameter%diff{ ($ vs $)|}3,4" "|: different return type%diff{ ($ vs $)|}2,3" "|: different qualifiers (" "%select{none|const|restrict|const and restrict|volatile|const and volatile|" "volatile and restrict|const, volatile, and restrict}2 vs " "%select{none|const|restrict|const and restrict|volatile|const and volatile|" "volatile and restrict|const, volatile, and restrict}3)" "|: different exception specifications}1">; def warn_using_directive_in_header : Warning< "using namespace directive in global context in header">, InGroup, DefaultIgnore; def warn_overaligned_type : Warning< "type %0 requires %1 bytes of alignment and the default allocator only " "guarantees %2 bytes">, InGroup, DefaultIgnore; def err_aligned_allocation_unavailable : Error< "aligned %select{allocation|deallocation}0 function of type '%1' is only " "available on %2 %3 or newer">; def note_silence_unligned_allocation_unavailable : Note< "if you supply your own aligned allocation functions, use " "-faligned-allocation to silence this diagnostic">; def err_conditional_void_nonvoid : Error< "%select{left|right}1 operand to ? is void, but %select{right|left}1 operand " "is of type %0">; def err_conditional_ambiguous : Error< "conditional expression is ambiguous; " "%diff{$ can be converted to $ and vice versa|" "types can be convert to each other}0,1">; def err_conditional_ambiguous_ovl : Error< "conditional expression is ambiguous; %diff{$ and $|types}0,1 " "can be converted to several common types">; def err_conditional_vector_size : Error< "vector condition type %0 and result type %1 do not have the same number " "of elements">; def err_conditional_vector_element_size : Error< "vector condition type %0 and result type %1 do not have elements of the " "same size">; def err_throw_incomplete : Error< "cannot throw object of incomplete type %0">; def err_throw_incomplete_ptr : Error< "cannot throw pointer to object of incomplete type %0">; def err_return_in_constructor_handler : Error< "return in the catch of a function try block of a constructor is illegal">; def warn_cdtor_function_try_handler_mem_expr : Warning< "cannot refer to a non-static member from the handler of a " "%select{constructor|destructor}0 function try block">, InGroup; let CategoryName = "Lambda Issue" in { def err_capture_more_than_once : Error< "%0 can appear only once in a capture list">; def err_reference_capture_with_reference_default : Error< "'&' cannot precede a capture when the capture default is '&'">; def err_copy_capture_with_copy_default : Error< "'&' must precede a capture when the capture default is '='">; def err_capture_does_not_name_variable : Error< "%0 in capture list does not name a variable">; def err_capture_non_automatic_variable : Error< "%0 cannot be captured because it does not have automatic storage " "duration">; def err_this_capture : Error< "'this' cannot be %select{implicitly |}0captured in this context">; def err_lambda_capture_anonymous_var : Error< "unnamed variable cannot be implicitly captured in a lambda expression">; def err_lambda_capture_flexarray_type : Error< "variable %0 with flexible array member cannot be captured in " "a lambda expression">; def err_lambda_impcap : Error< "variable %0 cannot be implicitly captured in a lambda with no " "capture-default specified">; def note_lambda_decl : Note<"lambda expression begins here">; def err_lambda_unevaluated_operand : Error< "lambda expression in an unevaluated operand">; def err_lambda_in_constant_expression : Error< "a lambda expression may not appear inside of a constant expression">; def err_lambda_in_invalid_context : Error< "a lambda expression cannot appear in this context">; def err_lambda_return_init_list : Error< "cannot deduce lambda return type from initializer list">; def err_lambda_capture_default_arg : Error< "lambda expression in default argument cannot capture any entity">; def err_lambda_incomplete_result : Error< "incomplete result type %0 in lambda expression">; def err_noreturn_lambda_has_return_expr : Error< "lambda declared 'noreturn' should not return">; def warn_maybe_falloff_nonvoid_lambda : Warning< "control may reach end of non-void lambda">, InGroup; def warn_falloff_nonvoid_lambda : Warning< "control reaches end of non-void lambda">, InGroup; def err_access_lambda_capture : Error< // The ERRORs represent other special members that aren't constructors, in // hopes that someone will bother noticing and reporting if they appear "capture of variable '%0' as type %1 calls %select{private|protected}3 " "%select{default |copy |move |*ERROR* |*ERROR* |*ERROR* |}2constructor">, AccessControl; def note_lambda_to_block_conv : Note< "implicit capture of lambda object due to conversion to block pointer " "here">; def note_var_explicitly_captured_here : Note<"variable %0 is" "%select{| explicitly}1 captured here">; // C++14 lambda init-captures. def warn_cxx11_compat_init_capture : Warning< "initialized lambda captures are incompatible with C++ standards " "before C++14">, InGroup, DefaultIgnore; def ext_init_capture : ExtWarn< "initialized lambda captures are a C++14 extension">, InGroup; def err_init_capture_no_expression : Error< "initializer missing for lambda capture %0">; def err_init_capture_multiple_expressions : Error< "initializer for lambda capture %0 contains multiple expressions">; def err_init_capture_paren_braces : Error< "cannot deduce type for lambda capture %1 from " "%select{parenthesized|nested}0 initializer list">; def err_init_capture_deduction_failure : Error< "cannot deduce type for lambda capture %0 from initializer of type %2">; def err_init_capture_deduction_failure_from_init_list : Error< "cannot deduce type for lambda capture %0 from initializer list">; // C++17 '*this' captures. def warn_cxx14_compat_star_this_lambda_capture : Warning< "by value capture of '*this' is incompatible with C++ standards before C++17">, InGroup, DefaultIgnore; def ext_star_this_lambda_capture_cxx17 : ExtWarn< "capture of '*this' by copy is a C++17 extension">, InGroup; // C++2a [=, this] captures. def warn_cxx17_compat_equals_this_lambda_capture : Warning< "explicit capture of 'this' with a capture default of '=' is incompatible " "with C++ standards before C++2a">, InGroup, DefaultIgnore; def ext_equals_this_lambda_capture_cxx2a : ExtWarn< "explicit capture of 'this' with a capture default of '=' " "is a C++2a extension">, InGroup; def warn_deprecated_this_capture : Warning< "implicit capture of 'this' with a capture default of '=' is deprecated">, InGroup, DefaultIgnore; def note_deprecated_this_capture : Note< "add an explicit capture of 'this' to capture '*this' by reference">; } def err_return_in_captured_stmt : Error< "cannot return from %0">; def err_capture_block_variable : Error< "__block variable %0 cannot be captured in a " "%select{lambda expression|captured statement}1">; def err_operator_arrow_circular : Error< "circular pointer delegation detected">; def err_operator_arrow_depth_exceeded : Error< "use of 'operator->' on type %0 would invoke a sequence of more than %1 " "'operator->' calls">; def note_operator_arrow_here : Note< "'operator->' declared here produces an object of type %0">; def note_operator_arrows_suppressed : Note< "(skipping %0 'operator->'%s0 in backtrace)">; def note_operator_arrow_depth : Note< "use -foperator-arrow-depth=N to increase 'operator->' limit">; def err_pseudo_dtor_base_not_scalar : Error< "object expression of non-scalar type %0 cannot be used in a " "pseudo-destructor expression">; def ext_pseudo_dtor_on_void : ExtWarn< "pseudo-destructors on type void are a Microsoft extension">, InGroup; def err_pseudo_dtor_type_mismatch : Error< "the type of object expression " "%diff{($) does not match the type being destroyed ($)|" "does not match the type being destroyed}0,1 " "in pseudo-destructor expression">; def err_pseudo_dtor_call_with_args : Error< "call to pseudo-destructor cannot have any arguments">; def err_dtor_expr_without_call : Error< "reference to %select{destructor|pseudo-destructor}0 must be called" "%select{|; did you mean to call it with no arguments?}1">; def err_pseudo_dtor_destructor_non_type : Error< "%0 does not refer to a type name in pseudo-destructor expression; expected " "the name of type %1">; def err_invalid_use_of_function_type : Error< "a function type is not allowed here">; def err_invalid_use_of_array_type : Error<"an array type is not allowed here">; def err_typecheck_bool_condition : Error< "value of type %0 is not contextually convertible to 'bool'">; def err_typecheck_ambiguous_condition : Error< "conversion %diff{from $ to $|between types}0,1 is ambiguous">; def err_typecheck_nonviable_condition : Error< "no viable conversion%select{%diff{ from $ to $|}1,2|" "%diff{ from returned value of type $ to function return type $|}1,2}0">; def err_typecheck_nonviable_condition_incomplete : Error< "no viable conversion%diff{ from $ to incomplete type $|}0,1">; def err_typecheck_deleted_function : Error< "conversion function %diff{from $ to $|between types}0,1 " "invokes a deleted function">; def err_expected_class_or_namespace : Error<"%0 is not a class" "%select{ or namespace|, namespace, or enumeration}1">; def err_invalid_declarator_scope : Error<"cannot define or redeclare %0 here " "because namespace %1 does not enclose namespace %2">; def err_invalid_declarator_global_scope : Error< "definition or redeclaration of %0 cannot name the global scope">; def err_invalid_declarator_in_function : Error< "definition or redeclaration of %0 not allowed inside a function">; def err_invalid_declarator_in_block : Error< "definition or redeclaration of %0 not allowed inside a block">; def err_not_tag_in_scope : Error< "no %select{struct|interface|union|class|enum}0 named %1 in %2">; def err_no_typeid_with_fno_rtti : Error< "use of typeid requires -frtti">; def err_no_dynamic_cast_with_fno_rtti : Error< "use of dynamic_cast requires -frtti">; def err_cannot_form_pointer_to_member_of_reference_type : Error< "cannot form a pointer-to-member to member %0 of reference type %1">; def err_incomplete_object_call : Error< "incomplete type in call to object of type %0">; def warn_condition_is_assignment : Warning<"using the result of an " "assignment as a condition without parentheses">, InGroup; // Completely identical except off by default. def warn_condition_is_idiomatic_assignment : Warning<"using the result " "of an assignment as a condition without parentheses">, InGroup>, DefaultIgnore; def note_condition_assign_to_comparison : Note< "use '==' to turn this assignment into an equality comparison">; def note_condition_or_assign_to_comparison : Note< "use '!=' to turn this compound assignment into an inequality comparison">; def note_condition_assign_silence : Note< "place parentheses around the assignment to silence this warning">; def warn_equality_with_extra_parens : Warning<"equality comparison with " "extraneous parentheses">, InGroup; def note_equality_comparison_to_assign : Note< "use '=' to turn this equality comparison into an assignment">; def note_equality_comparison_silence : Note< "remove extraneous parentheses around the comparison to silence this warning">; // assignment related diagnostics (also for argument passing, returning, etc). // In most of these diagnostics the %2 is a value from the // Sema::AssignmentAction enumeration def err_typecheck_convert_incompatible : Error< "%select{%diff{assigning to $ from incompatible type $|" "assigning to type from incompatible type}0,1" "|%diff{passing $ to parameter of incompatible type $|" "passing type to parameter of incompatible type}0,1" "|%diff{returning $ from a function with incompatible result type $|" "returning type from a function with incompatible result type}0,1" "|%diff{converting $ to incompatible type $|" "converting type to incompatible type}0,1" "|%diff{initializing $ with an expression of incompatible type $|" "initializing type with an expression of incompatible type}0,1" "|%diff{sending $ to parameter of incompatible type $|" "sending type to parameter of incompatible type}0,1" "|%diff{casting $ to incompatible type $|" "casting type to incompatible type}0,1}2" "%select{|; dereference with *|" "; take the address with &|" "; remove *|" "; remove &}3" "%select{|: different classes%diff{ ($ vs $)|}5,6" "|: different number of parameters (%5 vs %6)" "|: type mismatch at %ordinal5 parameter%diff{ ($ vs $)|}6,7" "|: different return type%diff{ ($ vs $)|}5,6" "|: different qualifiers (" "%select{none|const|restrict|const and restrict|volatile|const and volatile|" "volatile and restrict|const, volatile, and restrict}5 vs " "%select{none|const|restrict|const and restrict|volatile|const and volatile|" "volatile and restrict|const, volatile, and restrict}6)" "|: different exception specifications}4">; def err_typecheck_missing_return_type_incompatible : Error< "%diff{return type $ must match previous return type $|" "return type must match previous return type}0,1 when %select{block " "literal|lambda expression}2 has unspecified explicit return type">; def note_incomplete_class_and_qualified_id : Note< "conformance of forward class %0 to protocol %1 can not be confirmed">; def warn_incompatible_qualified_id : Warning< "%select{%diff{assigning to $ from incompatible type $|" "assigning to type from incompatible type}0,1" "|%diff{passing $ to parameter of incompatible type $|" "passing type to parameter of incompatible type}0,1" "|%diff{returning $ from a function with incompatible result type $|" "returning type from a function with incompatible result type}0,1" "|%diff{converting $ to incompatible type $|" "converting type to incompatible type}0,1" "|%diff{initializing $ with an expression of incompatible type $|" "initializing type with an expression of incompatible type}0,1" "|%diff{sending $ to parameter of incompatible type $|" "sending type to parameter of incompatible type}0,1" "|%diff{casting $ to incompatible type $|" "casting type to incompatible type}0,1}2">; def ext_typecheck_convert_pointer_int : ExtWarn< "incompatible pointer to integer conversion " "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" "passing to parameter of different type}0,1" "|%diff{returning $ from a function with result type $|" "returning from function with different return type}0,1" "|%diff{converting $ to type $|converting between types}0,1" "|%diff{initializing $ with an expression of type $|" "initializing with expression of different type}0,1" "|%diff{sending $ to parameter of type $|" "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2" "%select{|; dereference with *|" "; take the address with &|" "; remove *|" "; remove &}3">, InGroup; def ext_typecheck_convert_int_pointer : ExtWarn< "incompatible integer to pointer conversion " "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" "passing to parameter of different type}0,1" "|%diff{returning $ from a function with result type $|" "returning from function with different return type}0,1" "|%diff{converting $ to type $|converting between types}0,1" "|%diff{initializing $ with an expression of type $|" "initializing with expression of different type}0,1" "|%diff{sending $ to parameter of type $|" "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2" "%select{|; dereference with *|" "; take the address with &|" "; remove *|" "; remove &}3">, InGroup; def ext_typecheck_convert_pointer_void_func : Extension< "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" "passing to parameter of different type}0,1" "|%diff{returning $ from a function with result type $|" "returning from function with different return type}0,1" "|%diff{converting $ to type $|converting between types}0,1" "|%diff{initializing $ with an expression of type $|" "initializing with expression of different type}0,1" "|%diff{sending $ to parameter of type $|" "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2" " converts between void pointer and function pointer">; def ext_typecheck_convert_incompatible_pointer_sign : ExtWarn< "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" "passing to parameter of different type}0,1" "|%diff{returning $ from a function with result type $|" "returning from function with different return type}0,1" "|%diff{converting $ to type $|converting between types}0,1" "|%diff{initializing $ with an expression of type $|" "initializing with expression of different type}0,1" "|%diff{sending $ to parameter of type $|" "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2" " converts between pointers to integer types with different sign">, InGroup>; def ext_typecheck_convert_incompatible_pointer : ExtWarn< "incompatible pointer types " "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" "passing to parameter of different type}0,1" "|%diff{returning $ from a function with result type $|" "returning from function with different return type}0,1" "|%diff{converting $ to type $|converting between types}0,1" "|%diff{initializing $ with an expression of type $|" "initializing with expression of different type}0,1" "|%diff{sending $ to parameter of type $|" "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2" "%select{|; dereference with *|" "; take the address with &|" "; remove *|" "; remove &}3">, InGroup; def ext_typecheck_convert_incompatible_function_pointer : ExtWarn< "incompatible function pointer types " "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" "passing to parameter of different type}0,1" "|%diff{returning $ from a function with result type $|" "returning from function with different return type}0,1" "|%diff{converting $ to type $|converting between types}0,1" "|%diff{initializing $ with an expression of type $|" "initializing with expression of different type}0,1" "|%diff{sending $ to parameter of type $|" "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2" "%select{|; dereference with *|" "; take the address with &|" "; remove *|" "; remove &}3">, InGroup; def ext_typecheck_convert_discards_qualifiers : ExtWarn< "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" "passing to parameter of different type}0,1" "|%diff{returning $ from a function with result type $|" "returning from function with different return type}0,1" "|%diff{converting $ to type $|converting between types}0,1" "|%diff{initializing $ with an expression of type $|" "initializing with expression of different type}0,1" "|%diff{sending $ to parameter of type $|" "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2" " discards qualifiers">, InGroup; def ext_nested_pointer_qualifier_mismatch : ExtWarn< "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" "passing to parameter of different type}0,1" "|%diff{returning $ from a function with result type $|" "returning from function with different return type}0,1" "|%diff{converting $ to type $|converting between types}0,1" "|%diff{initializing $ with an expression of type $|" "initializing with expression of different type}0,1" "|%diff{sending $ to parameter of type $|" "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2" " discards qualifiers in nested pointer types">, InGroup; def warn_incompatible_vectors : Warning< "incompatible vector types " "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" "passing to parameter of different type}0,1" "|%diff{returning $ from a function with result type $|" "returning from function with different return type}0,1" "|%diff{converting $ to type $|converting between types}0,1" "|%diff{initializing $ with an expression of type $|" "initializing with expression of different type}0,1" "|%diff{sending $ to parameter of type $|" "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2">, InGroup, DefaultIgnore; def err_int_to_block_pointer : Error< "invalid block pointer conversion " "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" "passing to parameter of different type}0,1" "|%diff{returning $ from a function with result type $|" "returning from function with different return type}0,1" "|%diff{converting $ to type $|converting between types}0,1" "|%diff{initializing $ with an expression of type $|" "initializing with expression of different type}0,1" "|%diff{sending $ to parameter of type $|" "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2">; def err_typecheck_convert_incompatible_block_pointer : Error< "incompatible block pointer types " "%select{%diff{assigning to $ from $|assigning to different types}0,1" "|%diff{passing $ to parameter of type $|" "passing to parameter of different type}0,1" "|%diff{returning $ from a function with result type $|" "returning from function with different return type}0,1" "|%diff{converting $ to type $|converting between types}0,1" "|%diff{initializing $ with an expression of type $|" "initializing with expression of different type}0,1" "|%diff{sending $ to parameter of type $|" "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2">; def err_typecheck_incompatible_address_space : Error< "%select{%diff{assigning $ to $|assigning to different types}1,0" "|%diff{passing $ to parameter of type $|" "passing to parameter of different type}0,1" "|%diff{returning $ from a function with result type $|" "returning from function with different return type}0,1" "|%diff{converting $ to type $|converting between types}0,1" "|%diff{initializing $ with an expression of type $|" "initializing with expression of different type}0,1" "|%diff{sending $ to parameter of type $|" "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2" " changes address space of pointer">; def err_typecheck_incompatible_ownership : Error< "%select{%diff{assigning $ to $|assigning to different types}1,0" "|%diff{passing $ to parameter of type $|" "passing to parameter of different type}0,1" "|%diff{returning $ from a function with result type $|" "returning from function with different return type}0,1" "|%diff{converting $ to type $|converting between types}0,1" "|%diff{initializing $ with an expression of type $|" "initializing with expression of different type}0,1" "|%diff{sending $ to parameter of type $|" "sending to parameter of different type}0,1" "|%diff{casting $ to type $|casting between types}0,1}2" " changes retain/release properties of pointer">; def err_typecheck_comparison_of_distinct_blocks : Error< "comparison of distinct block types%diff{ ($ and $)|}0,1">; def err_typecheck_array_not_modifiable_lvalue : Error< "array type %0 is not assignable">; def err_typecheck_non_object_not_modifiable_lvalue : Error< "non-object type %0 is not assignable">; def err_typecheck_expression_not_modifiable_lvalue : Error< "expression is not assignable">; def err_typecheck_incomplete_type_not_modifiable_lvalue : Error< "incomplete type %0 is not assignable">; def err_typecheck_lvalue_casts_not_supported : Error< "assignment to cast is illegal, lvalue casts are not supported">; def err_typecheck_duplicate_vector_components_not_mlvalue : Error< "vector is not assignable (contains duplicate components)">; def err_block_decl_ref_not_modifiable_lvalue : Error< "variable is not assignable (missing __block type specifier)">; def err_lambda_decl_ref_not_modifiable_lvalue : Error< "cannot assign to a variable captured by copy in a non-mutable lambda">; def err_typecheck_call_not_function : Error< "called object type %0 is not a function or function pointer">; def err_call_incomplete_return : Error< "calling function with incomplete return type %0">; def err_call_function_incomplete_return : Error< "calling %0 with incomplete return type %1">; def err_call_incomplete_argument : Error< "argument type %0 is incomplete">; def err_typecheck_call_too_few_args : Error< "too few %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "expected %1, have %2">; def err_typecheck_call_too_few_args_one : Error< "too few %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "single argument %1 was not specified">; def err_typecheck_call_too_few_args_at_least : Error< "too few %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "expected at least %1, have %2">; def err_typecheck_call_too_few_args_at_least_one : Error< "too few %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "at least argument %1 must be specified">; def err_typecheck_call_too_few_args_suggest : Error< "too few %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "expected %1, have %2; did you mean %3?">; def err_typecheck_call_too_few_args_at_least_suggest : Error< "too few %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "expected at least %1, have %2; did you mean %3?">; def err_typecheck_call_too_many_args : Error< "too many %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "expected %1, have %2">; def err_typecheck_call_too_many_args_one : Error< "too many %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "expected single argument %1, have %2 arguments">; def err_typecheck_call_too_many_args_at_most : Error< "too many %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "expected at most %1, have %2">; def err_typecheck_call_too_many_args_at_most_one : Error< "too many %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "expected at most single argument %1, have %2 arguments">; def err_typecheck_call_too_many_args_suggest : Error< "too many %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "expected %1, have %2; did you mean %3?">; def err_typecheck_call_too_many_args_at_most_suggest : Error< "too many %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "expected at most %1, have %2; did you mean %3?">; def err_arc_typecheck_convert_incompatible_pointer : Error< "incompatible pointer types passing retainable parameter of type %0" "to a CF function expecting %1 type">; def err_builtin_fn_use : Error<"builtin functions must be directly called">; def warn_call_wrong_number_of_arguments : Warning< "too %select{few|many}0 arguments in call to %1">; def err_atomic_builtin_must_be_pointer : Error< "address argument to atomic builtin must be a pointer (%0 invalid)">; def err_atomic_builtin_must_be_pointer_intptr : Error< "address argument to atomic builtin must be a pointer to integer or pointer" " (%0 invalid)">; def err_atomic_builtin_cannot_be_const : Error< "address argument to atomic builtin cannot be const-qualified (%0 invalid)">; def err_atomic_builtin_must_be_pointer_intfltptr : Error< "address argument to atomic builtin must be a pointer to integer," " floating-point or pointer (%0 invalid)">; def err_atomic_builtin_pointer_size : Error< "address argument to atomic builtin must be a pointer to 1,2,4,8 or 16 byte " "type (%0 invalid)">; def err_atomic_exclusive_builtin_pointer_size : Error< "address argument to load or store exclusive builtin must be a pointer to" " 1,2,4 or 8 byte type (%0 invalid)">; def err_atomic_op_needs_atomic : Error< "address argument to atomic operation must be a pointer to _Atomic " "type (%0 invalid)">; def err_atomic_op_needs_non_const_atomic : Error< "address argument to atomic operation must be a pointer to non-%select{const|constant}0 _Atomic " "type (%1 invalid)">; def err_atomic_op_needs_non_const_pointer : Error< "address argument to atomic operation must be a pointer to non-const " "type (%0 invalid)">; def err_atomic_op_needs_trivial_copy : Error< "address argument to atomic operation must be a pointer to a " "trivially-copyable type (%0 invalid)">; def err_atomic_op_needs_atomic_int_or_ptr : Error< "address argument to atomic operation must be a pointer to %select{|atomic }0" "integer or pointer (%1 invalid)">; def err_atomic_op_needs_int32_or_ptr : Error< "address argument to atomic operation must be a pointer to signed or unsigned 32-bit integer">; def err_atomic_op_bitwise_needs_atomic_int : Error< "address argument to bitwise atomic operation must be a pointer to " "%select{|atomic }0integer (%1 invalid)">; def warn_atomic_op_has_invalid_memory_order : Warning< "memory order argument to atomic operation is invalid">, InGroup>; def err_atomic_op_has_invalid_synch_scope : Error< "synchronization scope argument to atomic operation is invalid">; def warn_atomic_op_misaligned : Warning< "misaligned or large atomic operation may incur significant performance penalty">, InGroup>; def err_overflow_builtin_must_be_int : Error< "operand argument to overflow builtin must be an integer (%0 invalid)">; def err_overflow_builtin_must_be_ptr_int : Error< "result argument to overflow builtin must be a pointer " "to a non-const integer (%0 invalid)">; def err_atomic_load_store_uses_lib : Error< "atomic %select{load|store}0 requires runtime support that is not " "available for this target">; def err_nontemporal_builtin_must_be_pointer : Error< "address argument to nontemporal builtin must be a pointer (%0 invalid)">; def err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector : Error< "address argument to nontemporal builtin must be a pointer to integer, float, " "pointer, or a vector of such types (%0 invalid)">; def err_deleted_function_use : Error<"attempt to use a deleted function">; def err_deleted_inherited_ctor_use : Error< "constructor inherited by %0 from base class %1 is implicitly deleted">; def note_called_by : Note<"called by %0">; def err_kern_type_not_void_return : Error< "kernel function type %0 must have void return type">; def err_kern_is_nonstatic_method : Error< "kernel function %0 must be a free function or static member function">; def err_config_scalar_return : Error< "CUDA special function 'cudaConfigureCall' must have scalar return type">; def err_kern_call_not_global_function : Error< "kernel call to non-global function %0">; def err_global_call_not_config : Error< "call to global function %0 not configured">; def err_ref_bad_target : Error< "reference to %select{__device__|__global__|__host__|__host__ __device__}0 " "function %1 in %select{__device__|__global__|__host__|__host__ __device__}2 function">; def err_ref_bad_target_global_initializer : Error< "reference to %select{__device__|__global__|__host__|__host__ __device__}0 " "function %1 in global initializer">; def warn_kern_is_method : Extension< "kernel function %0 is a member function; this may not be accepted by nvcc">, InGroup; def warn_kern_is_inline : Warning< "ignored 'inline' attribute on kernel function %0">, InGroup; def err_variadic_device_fn : Error< "CUDA device code does not support variadic functions">; def err_va_arg_in_device : Error< "CUDA device code does not support va_arg">; def err_alias_not_supported_on_nvptx : Error<"CUDA does not support aliases">; def err_cuda_unattributed_constexpr_cannot_overload_device : Error< "constexpr function %0 without __host__ or __device__ attributes cannot " "overload __device__ function with same signature. Add a __host__ " "attribute, or build with -fno-cuda-host-device-constexpr.">; def note_cuda_conflicting_device_function_declared_here : Note< "conflicting __device__ function declared here">; def err_cuda_device_exceptions : Error< "cannot use '%0' in " "%select{__device__|__global__|__host__|__host__ __device__}1 function">; def err_dynamic_var_init : Error< "dynamic initialization is not supported for " "__device__, __constant__, and __shared__ variables.">; def err_shared_var_init : Error< "initialization is not supported for __shared__ variables.">; def err_device_static_local_var : Error< "within a %select{__device__|__global__|__host__|__host__ __device__}0 " "function, only __shared__ variables or const variables without device " "memory qualifier may be marked 'static'">; def err_cuda_vla : Error< "cannot use variable-length arrays in " "%select{__device__|__global__|__host__|__host__ __device__}0 functions">; def err_cuda_extern_shared : Error<"__shared__ variable %0 cannot be 'extern'">; def err_cuda_host_shared : Error< "__shared__ local variables not allowed in " "%select{__device__|__global__|__host__|__host__ __device__}0 functions">; def err_cuda_nonglobal_constant : Error<"__constant__ variables must be global">; def err_cuda_ovl_target : Error< "%select{__device__|__global__|__host__|__host__ __device__}0 function %1 " "cannot overload %select{__device__|__global__|__host__|__host__ __device__}2 function %3">; def note_cuda_ovl_candidate_target_mismatch : Note< "candidate template ignored: target attributes do not match">; def warn_non_pod_vararg_with_format_string : Warning< "cannot pass %select{non-POD|non-trivial}0 object of type %1 to variadic " "%select{function|block|method|constructor}2; expected type from format " "string was %3">, InGroup, DefaultError; // The arguments to this diagnostic should match the warning above. def err_cannot_pass_objc_interface_to_vararg_format : Error< "cannot pass object with interface type %1 by value to variadic " "%select{function|block|method|constructor}2; expected type from format " "string was %3">; def err_cannot_pass_non_trivial_c_struct_to_vararg : Error< "cannot pass non-trivial C object of type %0 by value to variadic " "%select{function|block|method|constructor}1">; def err_cannot_pass_objc_interface_to_vararg : Error< "cannot pass object with interface type %0 by value through variadic " "%select{function|block|method|constructor}1">; def warn_cannot_pass_non_pod_arg_to_vararg : Warning< "cannot pass object of %select{non-POD|non-trivial}0 type %1 through variadic" " %select{function|block|method|constructor}2; call will abort at runtime">, InGroup, DefaultError; def warn_cxx98_compat_pass_non_pod_arg_to_vararg : Warning< "passing object of trivial but non-POD type %0 through variadic" " %select{function|block|method|constructor}1 is incompatible with C++98">, InGroup, DefaultIgnore; def warn_pass_class_arg_to_vararg : Warning< "passing object of class type %0 through variadic " "%select{function|block|method|constructor}1" "%select{|; did you mean to call '%3'?}2">, InGroup, DefaultIgnore; def err_cannot_pass_to_vararg : Error< "cannot pass %select{expression of type %1|initializer list}0 to variadic " "%select{function|block|method|constructor}2">; def err_cannot_pass_to_vararg_format : Error< "cannot pass %select{expression of type %1|initializer list}0 to variadic " "%select{function|block|method|constructor}2; expected type from format " "string was %3">; def err_typecheck_call_invalid_ordered_compare : Error< "ordered compare requires two args of floating point type" "%diff{ ($ and $)|}0,1">; def err_typecheck_call_invalid_unary_fp : Error< "floating point classification requires argument of floating point type " "(passed in %0)">; def err_typecheck_cond_expect_int_float : Error< "used type %0 where integer or floating point type is required">; def err_typecheck_cond_expect_scalar : Error< "used type %0 where arithmetic or pointer type is required">; def err_typecheck_cond_expect_nonfloat : Error< "used type %0 where floating point type is not allowed">; def ext_typecheck_cond_one_void : Extension< "C99 forbids conditional expressions with only one void side">; def err_typecheck_cast_to_incomplete : Error< "cast to incomplete type %0">; def ext_typecheck_cast_nonscalar : Extension< "C99 forbids casting nonscalar type %0 to the same type">; def ext_typecheck_cast_to_union : Extension< "cast to union type is a GNU extension">, InGroup; def err_typecheck_cast_to_union_no_type : Error< "cast to union type from type %0 not present in union">; def err_cast_pointer_from_non_pointer_int : Error< "operand of type %0 cannot be cast to a pointer type">; def warn_cast_pointer_from_sel : Warning< "cast of type %0 to %1 is deprecated; use sel_getName instead">, InGroup; def warn_function_def_in_objc_container : Warning< "function definition inside an Objective-C container is deprecated">, InGroup; def warn_cast_calling_conv : Warning< "cast between incompatible calling conventions '%0' and '%1'; " "calls through this pointer may abort at runtime">, InGroup>; def note_change_calling_conv_fixit : Note< "consider defining %0 with the '%1' calling convention">; def warn_bad_function_cast : Warning< "cast from function call of type %0 to non-matching type %1">, InGroup, DefaultIgnore; def err_cast_pointer_to_non_pointer_int : Error< "pointer cannot be cast to type %0">; def err_typecheck_expect_scalar_operand : Error< "operand of type %0 where arithmetic or pointer type is required">; def err_typecheck_cond_incompatible_operands : Error< "incompatible operand types%diff{ ($ and $)|}0,1">; def err_cast_selector_expr : Error< "cannot type cast @selector expression">; def ext_typecheck_cond_incompatible_pointers : ExtWarn< "pointer type mismatch%diff{ ($ and $)|}0,1">, InGroup>; def ext_typecheck_cond_pointer_integer_mismatch : ExtWarn< "pointer/integer type mismatch in conditional expression" "%diff{ ($ and $)|}0,1">, InGroup>; def err_typecheck_choose_expr_requires_constant : Error< "'__builtin_choose_expr' requires a constant expression">; def warn_unused_expr : Warning<"expression result unused">, InGroup; def warn_unused_voidptr : Warning< "expression result unused; should this cast be to 'void'?">, InGroup; def warn_unused_property_expr : Warning< "property access result unused - getters should not be used for side effects">, InGroup; def warn_unused_container_subscript_expr : Warning< "container access result unused - container access should not be used for side effects">, InGroup; def warn_unused_call : Warning< "ignoring return value of function declared with %0 attribute">, InGroup; def warn_side_effects_unevaluated_context : Warning< "expression with side effects has no effect in an unevaluated context">, InGroup; def warn_side_effects_typeid : Warning< "expression with side effects will be evaluated despite being used as an " "operand to 'typeid'">, InGroup; def warn_unused_result : Warning< "ignoring return value of function declared with %0 attribute">, InGroup; def warn_unused_volatile : Warning< "expression result unused; assign into a variable to force a volatile load">, InGroup>; def ext_cxx14_attr : Extension< "use of the %0 attribute is a C++14 extension">, InGroup; def ext_cxx17_attr : Extension< "use of the %0 attribute is a C++17 extension">, InGroup; def warn_unused_comparison : Warning< "%select{equality|inequality|relational|three-way}0 comparison result unused">, InGroup; def note_inequality_comparison_to_or_assign : Note< "use '|=' to turn this inequality comparison into an or-assignment">; def err_incomplete_type_used_in_type_trait_expr : Error< "incomplete type %0 used in type trait expression">; def err_require_constant_init_failed : Error< "variable does not have a constant initializer">; def note_declared_required_constant_init_here : Note< "required by 'require_constant_initialization' attribute here">; def err_dimension_expr_not_constant_integer : Error< "dimension expression does not evaluate to a constant unsigned int">; def err_typecheck_cond_incompatible_operands_null : Error< "non-pointer operand type %0 incompatible with %select{NULL|nullptr}1">; def ext_empty_struct_union : Extension< "empty %select{struct|union}0 is a GNU extension">, InGroup; def ext_no_named_members_in_struct_union : Extension< "%select{struct|union}0 without named members is a GNU extension">, InGroup; def warn_zero_size_struct_union_compat : Warning<"%select{|empty }0" "%select{struct|union}1 has size 0 in C, %select{size 1|non-zero size}2 in C++">, InGroup, DefaultIgnore; def warn_zero_size_struct_union_in_extern_c : Warning<"%select{|empty }0" "%select{struct|union}1 has size 0 in C, %select{size 1|non-zero size}2 in C++">, InGroup; def warn_cast_qual : Warning<"cast from %0 to %1 drops %select{const and " "volatile qualifiers|const qualifier|volatile qualifier}2">, InGroup, DefaultIgnore; def warn_cast_qual2 : Warning<"cast from %0 to %1 must have all intermediate " "pointers const qualified to be safe">, InGroup, DefaultIgnore; def warn_redefine_extname_not_applied : Warning< "#pragma redefine_extname is applicable to external C declarations only; " "not applied to %select{function|variable}0 %1">, InGroup; } // End of general sema category. // inline asm. let CategoryName = "Inline Assembly Issue" in { def err_asm_invalid_lvalue_in_output : Error<"invalid lvalue in asm output">; def err_asm_invalid_output_constraint : Error< "invalid output constraint '%0' in asm">; def err_asm_invalid_lvalue_in_input : Error< "invalid lvalue in asm input for constraint '%0'">; def err_asm_invalid_input_constraint : Error< "invalid input constraint '%0' in asm">; def err_asm_immediate_expected : Error<"constraint '%0' expects " "an integer constant expression">; def err_asm_invalid_type_in_input : Error< "invalid type %0 in asm input for constraint '%1'">; def err_asm_tying_incompatible_types : Error< "unsupported inline asm: input with type " "%diff{$ matching output with type $|}0,1">; def err_asm_unexpected_constraint_alternatives : Error< "asm constraint has an unexpected number of alternatives: %0 vs %1">; def err_asm_incomplete_type : Error<"asm operand has incomplete type %0">; def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">; def err_asm_invalid_global_var_reg : Error<"register '%0' unsuitable for " "global register variables on this target">; def err_asm_register_size_mismatch : Error<"size of register '%0' does not " "match variable size">; def err_asm_bad_register_type : Error<"bad type for named register variable">; def err_asm_invalid_input_size : Error< "invalid input size for constraint '%0'">; def err_asm_invalid_output_size : Error< "invalid output size for constraint '%0'">; def err_invalid_asm_cast_lvalue : Error< "invalid use of a cast in a inline asm context requiring an l-value: " "remove the cast or build with -fheinous-gnu-extensions">; def err_invalid_asm_value_for_constraint : Error <"value '%0' out of range for constraint '%1'">; def err_asm_non_addr_value_in_memory_constraint : Error < "reference to a %select{bit-field|vector element|global register variable}0" " in asm %select{input|output}1 with a memory constraint '%2'">; def err_asm_input_duplicate_match : Error< "more than one input constraint matches the same output '%0'">; def warn_asm_label_on_auto_decl : Warning< "ignored asm label '%0' on automatic variable">; def warn_invalid_asm_cast_lvalue : Warning< "invalid use of a cast in an inline asm context requiring an l-value: " "accepted due to -fheinous-gnu-extensions, but clang may remove support " "for this in the future">; def warn_asm_mismatched_size_modifier : Warning< "value size does not match register size specified by the constraint " "and modifier">, InGroup; def note_asm_missing_constraint_modifier : Note< "use constraint modifier \"%0\"">; def note_asm_input_duplicate_first : Note< "constraint '%0' is already present here">; } def error_inoutput_conflict_with_clobber : Error< "asm-specifier for input or output variable conflicts with asm" " clobber list">; let CategoryName = "Semantic Issue" in { def err_invalid_conversion_between_vectors : Error< "invalid conversion between vector type%diff{ $ and $|}0,1 of different " "size">; def err_invalid_conversion_between_vector_and_integer : Error< "invalid conversion between vector type %0 and integer type %1 " "of different size">; def err_opencl_function_pointer : Error< "pointers to functions are not allowed">; def err_opencl_taking_address_capture : Error< "taking address of a capture is not allowed">; def err_invalid_conversion_between_vector_and_scalar : Error< "invalid conversion between vector type %0 and scalar type %1">; // C++ member initializers. def err_only_constructors_take_base_inits : Error< "only constructors take base initializers">; def err_multiple_mem_initialization : Error < "multiple initializations given for non-static member %0">; def err_multiple_mem_union_initialization : Error < "initializing multiple members of union">; def err_multiple_base_initialization : Error < "multiple initializations given for base %0">; def err_mem_init_not_member_or_class : Error< "member initializer %0 does not name a non-static data member or base " "class">; def warn_initializer_out_of_order : Warning< "%select{field|base class}0 %1 will be initialized after " "%select{field|base}2 %3">, InGroup, DefaultIgnore; def warn_abstract_vbase_init_ignored : Warning< "initializer for virtual base class %0 of abstract class %1 " "will never be used">, InGroup>, DefaultIgnore; def err_base_init_does_not_name_class : Error< "constructor initializer %0 does not name a class">; def err_base_init_direct_and_virtual : Error< "base class initializer %0 names both a direct base class and an " "inherited virtual base class">; def err_not_direct_base_or_virtual : Error< "type %0 is not a direct or virtual base of %1">; def err_in_class_initializer_non_const : Error< "non-const static data member must be initialized out of line">; def err_in_class_initializer_volatile : Error< "static const volatile data member must be initialized out of line">; def err_in_class_initializer_bad_type : Error< "static data member of type %0 must be initialized out of line">; def ext_in_class_initializer_float_type : ExtWarn< "in-class initializer for static data member of type %0 is a GNU extension">, InGroup; def ext_in_class_initializer_float_type_cxx11 : ExtWarn< "in-class initializer for static data member of type %0 requires " "'constexpr' specifier">, InGroup, DefaultError; def note_in_class_initializer_float_type_cxx11 : Note<"add 'constexpr'">; def err_in_class_initializer_literal_type : Error< "in-class initializer for static data member of type %0 requires " "'constexpr' specifier">; def err_in_class_initializer_non_constant : Error< "in-class initializer for static data member is not a constant expression">; def err_in_class_initializer_not_yet_parsed : Error< "default member initializer for %1 needed within definition of enclosing " "class %0 outside of member functions">; def note_in_class_initializer_not_yet_parsed : Note< "default member initializer declared here">; def err_in_class_initializer_cycle : Error<"default member initializer for %0 uses itself">; def err_exception_spec_cycle : Error<"exception specification of %0 uses itself">; def ext_in_class_initializer_non_constant : Extension< "in-class initializer for static data member is not a constant expression; " "folding it to a constant is a GNU extension">, InGroup; def err_thread_dynamic_init : Error< "initializer for thread-local variable must be a constant expression">; def err_thread_nontrivial_dtor : Error< "type of thread-local variable has non-trivial destruction">; def note_use_thread_local : Note< "use 'thread_local' to allow this">; // C++ anonymous unions and GNU anonymous structs/unions def ext_anonymous_union : Extension< "anonymous unions are a C11 extension">, InGroup; def ext_gnu_anonymous_struct : Extension< "anonymous structs are a GNU extension">, InGroup; def ext_c11_anonymous_struct : Extension< "anonymous structs are a C11 extension">, InGroup; def err_anonymous_union_not_static : Error< "anonymous unions at namespace or global scope must be declared 'static'">; def err_anonymous_union_with_storage_spec : Error< "anonymous union at class scope must not have a storage specifier">; def err_anonymous_struct_not_member : Error< "anonymous %select{structs|structs and classes}0 must be " "%select{struct or union|class}0 members">; def err_anonymous_record_member_redecl : Error< "member of anonymous %select{struct|union}0 redeclares %1">; def err_anonymous_record_with_type : Error< "types cannot be declared in an anonymous %select{struct|union}0">; def ext_anonymous_record_with_type : Extension< "types declared in an anonymous %select{struct|union}0 are a Microsoft " "extension">, InGroup; def ext_anonymous_record_with_anonymous_type : Extension< "anonymous types declared in an anonymous %select{struct|union}0 " "are an extension">, InGroup>; def err_anonymous_record_with_function : Error< "functions cannot be declared in an anonymous %select{struct|union}0">; def err_anonymous_record_with_static : Error< "static members cannot be declared in an anonymous %select{struct|union}0">; def err_anonymous_record_bad_member : Error< "anonymous %select{struct|union}0 can only contain non-static data members">; def err_anonymous_record_nonpublic_member : Error< "anonymous %select{struct|union}0 cannot contain a " "%select{private|protected}1 data member">; def ext_ms_anonymous_record : ExtWarn< "anonymous %select{structs|unions}0 are a Microsoft extension">, InGroup; // C++ local classes def err_reference_to_local_in_enclosing_context : Error< "reference to local %select{variable|binding}1 %0 declared in enclosing " "%select{%3|block literal|lambda expression|context}2">; def err_static_data_member_not_allowed_in_local_class : Error< "static data member %0 not allowed in local class %1">; // C++ derived classes def err_base_clause_on_union : Error<"unions cannot have base classes">; def err_base_must_be_class : Error<"base specifier must name a class">; def err_union_as_base_class : Error<"unions cannot be base classes">; def err_circular_inheritance : Error< "circular inheritance between %0 and %1">; def err_base_class_has_flexible_array_member : Error< "base class %0 has a flexible array member">; def err_incomplete_base_class : Error<"base class has incomplete type">; def err_duplicate_base_class : Error< "base class %0 specified more than once as a direct base class">; def warn_inaccessible_base_class : Warning< "direct base %0 is inaccessible due to ambiguity:%1">, InGroup>; // FIXME: better way to display derivation? Pass entire thing into diagclient? def err_ambiguous_derived_to_base_conv : Error< "ambiguous conversion from derived class %0 to base class %1:%2">; def err_ambiguous_memptr_conv : Error< "ambiguous conversion from pointer to member of %select{base|derived}0 " "class %1 to pointer to member of %select{derived|base}0 class %2:%3">; def ext_ms_ambiguous_direct_base : ExtWarn< "accessing inaccessible direct base %0 of %1 is a Microsoft extension">, InGroup; def err_memptr_conv_via_virtual : Error< "conversion from pointer to member of class %0 to pointer to member " "of class %1 via virtual base %2 is not allowed">; // C++ member name lookup def err_ambiguous_member_multiple_subobjects : Error< "non-static member %0 found in multiple base-class subobjects of type %1:%2">; def err_ambiguous_member_multiple_subobject_types : Error< "member %0 found in multiple base classes of different types">; def note_ambiguous_member_found : Note<"member found by ambiguous name lookup">; def err_ambiguous_reference : Error<"reference to %0 is ambiguous">; def note_ambiguous_candidate : Note<"candidate found by name lookup is %q0">; def err_ambiguous_tag_hiding : Error<"a type named %0 is hidden by a " "declaration in a different namespace">; def note_hidden_tag : Note<"type declaration hidden">; def note_hiding_object : Note<"declaration hides type">; // C++ operator overloading def err_operator_overload_needs_class_or_enum : Error< "overloaded %0 must have at least one parameter of class " "or enumeration type">; def err_operator_overload_variadic : Error<"overloaded %0 cannot be variadic">; def err_operator_overload_static : Error< "overloaded %0 cannot be a static member function">; def err_operator_overload_default_arg : Error< "parameter of overloaded %0 cannot have a default argument">; def err_operator_overload_must_be : Error< "overloaded %0 must be a %select{unary|binary|unary or binary}2 operator " "(has %1 parameter%s1)">; def err_operator_overload_must_be_member : Error< "overloaded %0 must be a non-static member function">; def err_operator_overload_post_incdec_must_be_int : Error< "parameter of overloaded post-%select{increment|decrement}1 operator must " "have type 'int' (not %0)">; // C++ allocation and deallocation functions. def err_operator_new_delete_declared_in_namespace : Error< "%0 cannot be declared inside a namespace">; def err_operator_new_delete_declared_static : Error< "%0 cannot be declared static in global scope">; def ext_operator_new_delete_declared_inline : ExtWarn< "replacement function %0 cannot be declared 'inline'">, InGroup>; def err_operator_new_delete_invalid_result_type : Error< "%0 must return type %1">; def err_operator_new_delete_dependent_result_type : Error< "%0 cannot have a dependent return type; use %1 instead">; def err_operator_new_delete_too_few_parameters : Error< "%0 must have at least one parameter">; def err_operator_new_delete_template_too_few_parameters : Error< "%0 template must have at least two parameters">; def warn_operator_new_returns_null : Warning< "%0 should not return a null pointer unless it is declared 'throw()'" "%select{| or 'noexcept'}1">, InGroup; def err_operator_new_dependent_param_type : Error< "%0 cannot take a dependent type as first parameter; " "use size_t (%1) instead">; def err_operator_new_param_type : Error< "%0 takes type size_t (%1) as first parameter">; def err_operator_new_default_arg: Error< "parameter of %0 cannot have a default argument">; def err_operator_delete_dependent_param_type : Error< "%0 cannot take a dependent type as first parameter; use %1 instead">; def err_operator_delete_param_type : Error< "first parameter of %0 must have type %1">; def err_destroying_operator_delete_not_usual : Error< "destroying operator delete can have only an optional size and optional " "alignment parameter">; def note_implicit_delete_this_in_destructor_here : Note< "while checking implicit 'delete this' for virtual destructor">; def err_builtin_operator_new_delete_not_usual : Error< "call to '%select{__builtin_operator_new|__builtin_operator_delete}0' " "selects non-usual %select{allocation|deallocation}0 function">; def note_non_usual_function_declared_here : Note< "non-usual %0 declared here">; // C++ literal operators def err_literal_operator_outside_namespace : Error< "literal operator %0 must be in a namespace or global scope">; def err_literal_operator_id_outside_namespace : Error< "non-namespace scope '%0' cannot have a literal operator member">; def err_literal_operator_default_argument : Error< "literal operator cannot have a default argument">; def err_literal_operator_bad_param_count : Error< "non-template literal operator must have one or two parameters">; def err_literal_operator_invalid_param : Error< "parameter of literal operator must have type 'unsigned long long', 'long double', 'char', 'wchar_t', 'char16_t', 'char32_t', or 'const char *'">; def err_literal_operator_param : Error< "invalid literal operator parameter type %0, did you mean %1?">; def err_literal_operator_template_with_params : Error< "literal operator template cannot have any parameters">; def err_literal_operator_template : Error< "template parameter list for literal operator must be either 'char...' or 'typename T, T...'">; def err_literal_operator_extern_c : Error< "literal operator must have C++ linkage">; def ext_string_literal_operator_template : ExtWarn< "string literal operator templates are a GNU extension">, InGroup; def warn_user_literal_reserved : Warning< "user-defined literal suffixes not starting with '_' are reserved" "%select{; no literal will invoke this operator|}0">, InGroup; // C++ conversion functions def err_conv_function_not_member : Error< "conversion function must be a non-static member function">; def err_conv_function_return_type : Error< "conversion function cannot have a return type">; def err_conv_function_with_params : Error< "conversion function cannot have any parameters">; def err_conv_function_variadic : Error< "conversion function cannot be variadic">; def err_conv_function_to_array : Error< "conversion function cannot convert to an array type">; def err_conv_function_to_function : Error< "conversion function cannot convert to a function type">; def err_conv_function_with_complex_decl : Error< "cannot specify any part of a return type in the " "declaration of a conversion function" "%select{" "; put the complete type after 'operator'|" "; use a typedef to declare a conversion to %1|" "; use an alias template to declare a conversion to %1|" "}0">; def err_conv_function_redeclared : Error< "conversion function cannot be redeclared">; def warn_conv_to_self_not_used : Warning< "conversion function converting %0 to itself will never be used">; def warn_conv_to_base_not_used : Warning< "conversion function converting %0 to its base class %1 will never be used">; def warn_conv_to_void_not_used : Warning< "conversion function converting %0 to %1 will never be used">; def warn_not_compound_assign : Warning< "use of unary operator that may be intended as compound assignment (%0=)">; // C++11 explicit conversion operators def ext_explicit_conversion_functions : ExtWarn< "explicit conversion functions are a C++11 extension">, InGroup; def warn_cxx98_compat_explicit_conversion_functions : Warning< "explicit conversion functions are incompatible with C++98">, InGroup, DefaultIgnore; // C++11 defaulted functions def err_defaulted_special_member_params : Error< "an explicitly-defaulted %select{|copy |move }0constructor cannot " "have default arguments">; def err_defaulted_special_member_variadic : Error< "an explicitly-defaulted %select{|copy |move }0constructor cannot " "be variadic">; def err_defaulted_special_member_return_type : Error< "explicitly-defaulted %select{copy|move}0 assignment operator must " "return %1">; def err_defaulted_special_member_quals : Error< "an explicitly-defaulted %select{copy|move}0 assignment operator may not " "have 'const'%select{, 'constexpr'|}1 or 'volatile' qualifiers">; def err_defaulted_special_member_volatile_param : Error< "the parameter for an explicitly-defaulted %sub{select_special_member_kind}0 " "may not be volatile">; def err_defaulted_special_member_move_const_param : Error< "the parameter for an explicitly-defaulted move " "%select{constructor|assignment operator}0 may not be const">; def err_defaulted_special_member_copy_const_param : Error< "the parameter for this explicitly-defaulted copy " "%select{constructor|assignment operator}0 is const, but a member or base " "requires it to be non-const">; def err_defaulted_copy_assign_not_ref : Error< "the parameter for an explicitly-defaulted copy assignment operator must be an " "lvalue reference type">; def err_incorrect_defaulted_exception_spec : Error< "exception specification of explicitly defaulted " "%sub{select_special_member_kind}0 does not match the calculated one">; def err_incorrect_defaulted_constexpr : Error< "defaulted definition of %sub{select_special_member_kind}0 " "is not constexpr">; def err_out_of_line_default_deletes : Error< "defaulting this %sub{select_special_member_kind}0 " "would delete it after its first declaration">; def warn_vbase_moved_multiple_times : Warning< "defaulted move assignment operator of %0 will move assign virtual base " "class %1 multiple times">, InGroup>; def note_vbase_moved_here : Note< "%select{%1 is a virtual base class of base class %2 declared here|" "virtual base class %1 declared here}0">; def ext_implicit_exception_spec_mismatch : ExtWarn< "function previously declared with an %select{explicit|implicit}0 exception " "specification redeclared with an %select{implicit|explicit}0 exception " "specification">, InGroup>; def warn_ptr_arith_precedes_bounds : Warning< "the pointer decremented by %0 refers before the beginning of the array">, InGroup, DefaultIgnore; def warn_ptr_arith_exceeds_bounds : Warning< "the pointer incremented by %0 refers past the end of the array (that " "contains %1 element%s2)">, InGroup, DefaultIgnore; def warn_array_index_precedes_bounds : Warning< "array index %0 is before the beginning of the array">, InGroup; def warn_array_index_exceeds_bounds : Warning< "array index %0 is past the end of the array (which contains %1 " "element%s2)">, InGroup; def note_array_index_out_of_bounds : Note< "array %0 declared here">; def warn_printf_insufficient_data_args : Warning< "more '%%' conversions than data arguments">, InGroup; def warn_printf_data_arg_not_used : Warning< "data argument not used by format string">, InGroup; def warn_format_invalid_conversion : Warning< "invalid conversion specifier '%0'">, InGroup; def warn_printf_incomplete_specifier : Warning< "incomplete format specifier">, InGroup; def warn_missing_format_string : Warning< "format string missing">, InGroup; def warn_scanf_nonzero_width : Warning< "zero field width in scanf format string is unused">, InGroup; def warn_format_conversion_argument_type_mismatch : Warning< "format specifies type %0 but the argument has " "%select{type|underlying type}2 %1">, InGroup; def warn_format_conversion_argument_type_mismatch_pedantic : Extension< "format specifies type %0 but the argument has " "%select{type|underlying type}2 %1">, InGroup; def warn_format_argument_needs_cast : Warning< "%select{values of type|enum values with underlying type}2 '%0' should not " "be used as format arguments; add an explicit cast to %1 instead">, InGroup; def warn_format_argument_needs_cast_pedantic : Warning< "%select{values of type|enum values with underlying type}2 '%0' should not " "be used as format arguments; add an explicit cast to %1 instead">, InGroup, DefaultIgnore; def warn_printf_positional_arg_exceeds_data_args : Warning < "data argument position '%0' exceeds the number of data arguments (%1)">, InGroup; def warn_format_zero_positional_specifier : Warning< "position arguments in format strings start counting at 1 (not 0)">, InGroup; def warn_format_invalid_positional_specifier : Warning< "invalid position specified for %select{field width|field precision}0">, InGroup; def warn_format_mix_positional_nonpositional_args : Warning< "cannot mix positional and non-positional arguments in format string">, InGroup; def warn_static_array_too_small : Warning< "array argument is too small; contains %0 elements, callee requires at least %1">, InGroup; def note_callee_static_array : Note< "callee declares array parameter as static here">; def warn_empty_format_string : Warning< "format string is empty">, InGroup; def warn_format_string_is_wide_literal : Warning< "format string should not be a wide string">, InGroup; def warn_printf_format_string_contains_null_char : Warning< "format string contains '\\0' within the string body">, InGroup; def warn_printf_format_string_not_null_terminated : Warning< "format string is not null-terminated">, InGroup; def warn_printf_asterisk_missing_arg : Warning< "'%select{*|.*}0' specified field %select{width|precision}0 is missing a matching 'int' argument">, InGroup; def warn_printf_asterisk_wrong_type : Warning< "field %select{width|precision}0 should have type %1, but argument has type %2">, InGroup; def warn_printf_nonsensical_optional_amount: Warning< "%select{field width|precision}0 used with '%1' conversion specifier, resulting in undefined behavior">, InGroup; def warn_printf_nonsensical_flag: Warning< "flag '%0' results in undefined behavior with '%1' conversion specifier">, InGroup; def warn_format_nonsensical_length: Warning< "length modifier '%0' results in undefined behavior or no effect with '%1' conversion specifier">, InGroup; def warn_format_non_standard_positional_arg: Warning< "positional arguments are not supported by ISO C">, InGroup, DefaultIgnore; def warn_format_non_standard: Warning< "'%0' %select{length modifier|conversion specifier}1 is not supported by ISO C">, InGroup, DefaultIgnore; def warn_format_non_standard_conversion_spec: Warning< "using length modifier '%0' with conversion specifier '%1' is not supported by ISO C">, InGroup, DefaultIgnore; def warn_format_invalid_annotation : Warning< "using '%0' format specifier annotation outside of os_log()/os_trace()">, InGroup; def warn_format_P_no_precision : Warning< "using '%%P' format specifier without precision">, InGroup; def warn_printf_ignored_flag: Warning< "flag '%0' is ignored when flag '%1' is present">, InGroup; def warn_printf_empty_objc_flag: Warning< "missing object format flag">, InGroup; def warn_printf_ObjCflags_without_ObjCConversion: Warning< "object format flags cannot be used with '%0' conversion specifier">, InGroup; def warn_printf_invalid_objc_flag: Warning< "'%0' is not a valid object format flag">, InGroup; def warn_scanf_scanlist_incomplete : Warning< "no closing ']' for '%%[' in scanf format string">, InGroup; def note_format_string_defined : Note<"format string is defined here">; def note_format_fix_specifier : Note<"did you mean to use '%0'?">; def note_printf_c_str: Note<"did you mean to call the %0 method?">; def note_format_security_fixit: Note< "treat the string as an argument to avoid this">; def warn_null_arg : Warning< "null passed to a callee that requires a non-null argument">, InGroup; def warn_null_ret : Warning< "null returned from %select{function|method}0 that requires a non-null return value">, InGroup; def err_lifetimebound_no_object_param : Error< "'lifetimebound' attribute cannot be applied; %select{static |non-}0member " "function has no implicit object parameter">; def err_lifetimebound_ctor_dtor : Error< "'lifetimebound' attribute cannot be applied to a " "%select{constructor|destructor}0">; // CHECK: returning address/reference of stack memory def warn_ret_stack_addr_ref : Warning< "%select{address of|reference to}0 stack memory associated with " "%select{local variable|parameter}2 %1 returned">, InGroup; def warn_ret_local_temp_addr_ref : Warning< "returning %select{address of|reference to}0 local temporary object">, InGroup; def warn_ret_addr_label : Warning< "returning address of label, which is local">, InGroup; def err_ret_local_block : Error< "returning block that lives on the local stack">; def note_local_var_initializer : Note< "%select{via initialization of|binding reference}0 variable " "%select{%2 |}1here">; def note_init_with_default_member_initalizer : Note< "initializing field %0 with default member initializer">; // Check for initializing a member variable with the address or a reference to // a constructor parameter. def warn_bind_ref_member_to_parameter : Warning< "binding reference member %0 to stack allocated " "%select{variable|parameter}2 %1">, InGroup; def warn_init_ptr_member_to_parameter_addr : Warning< "initializing pointer member %0 with the stack address of " "%select{variable|parameter}2 %1">, InGroup; def note_ref_or_ptr_member_declared_here : Note< "%select{reference|pointer}0 member declared here">; def err_dangling_member : Error< "%select{reference|backing array for 'std::initializer_list'}2 " "%select{|subobject of }1member %0 " "%select{binds to|is}2 a temporary object " "whose lifetime would be shorter than the lifetime of " "the constructed object">; def warn_dangling_member : Warning< "%select{reference|backing array for 'std::initializer_list'}2 " "%select{|subobject of }1member %0 " "%select{binds to|is}2 a temporary object " "whose lifetime is shorter than the lifetime of the constructed object">, InGroup; def note_lifetime_extending_member_declared_here : Note< "%select{%select{reference|'std::initializer_list'}0 member|" "member with %select{reference|'std::initializer_list'}0 subobject}1 " "declared here">; def warn_dangling_variable : Warning< "%select{temporary %select{whose address is used as value of|" "%select{|implicitly }2bound to}4 " "%select{%select{|reference }4member of local variable|" "local %select{variable|reference}4}1|" "array backing " "%select{initializer list subobject of local variable|" "local initializer list}1}0 " "%select{%3 |}2will be destroyed at the end of the full-expression">, InGroup; def warn_new_dangling_reference : Warning< "temporary bound to reference member of allocated object " "will be destroyed at the end of the full-expression">, InGroup; def warn_new_dangling_initializer_list : Warning< "array backing " "%select{initializer list subobject of the allocated object|" "the allocated initializer list}0 " "will be destroyed at the end of the full-expression">, InGroup; def warn_unsupported_lifetime_extension : Warning< "sorry, lifetime extension of " "%select{temporary|backing array of initializer list}0 created " "by aggregate initialization using default member initializer " "is not supported; lifetime of %select{temporary|backing array}0 " "will end at the end of the full-expression">, InGroup; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. // Array comparisons have similar warnings def warn_comparison_always : Warning< "%select{self-|array }0comparison always evaluates to %select{a constant|%2}1">, InGroup; def warn_comparison_bitwise_always : Warning< "bitwise comparison always evaluates to %select{false|true}0">, InGroup; def warn_tautological_overlap_comparison : Warning< "overlapping comparisons always evaluate to %select{false|true}0">, InGroup, DefaultIgnore; def warn_stringcompare : Warning< "result of comparison against %select{a string literal|@encode}0 is " "unspecified (use strncmp instead)">, InGroup; def warn_identity_field_assign : Warning< "assigning %select{field|instance variable}0 to itself">, InGroup; // Type safety attributes def err_type_tag_for_datatype_not_ice : Error< "'type_tag_for_datatype' attribute requires the initializer to be " "an %select{integer|integral}0 constant expression">; def err_type_tag_for_datatype_too_large : Error< "'type_tag_for_datatype' attribute requires the initializer to be " "an %select{integer|integral}0 constant expression " "that can be represented by a 64 bit integer">; def err_tag_index_out_of_range : Error< "%select{type tag|argument}0 index %1 is greater than the number of arguments specified">; def warn_type_tag_for_datatype_wrong_kind : Warning< "this type tag was not designed to be used with this function">, InGroup; def warn_type_safety_type_mismatch : Warning< "argument type %0 doesn't match specified %1 type tag " "%select{that requires %3|}2">, InGroup; def warn_type_safety_null_pointer_required : Warning< "specified %0 type tag requires a null pointer">, InGroup; // Generic selections. def err_assoc_type_incomplete : Error< "type %0 in generic association incomplete">; def err_assoc_type_nonobject : Error< "type %0 in generic association not an object type">; def err_assoc_type_variably_modified : Error< "type %0 in generic association is a variably modified type">; def err_assoc_compatible_types : Error< "type %0 in generic association compatible with previously specified type %1">; def note_compat_assoc : Note< "compatible type %0 specified here">; def err_generic_sel_no_match : Error< "controlling expression type %0 not compatible with any generic association type">; def err_generic_sel_multi_match : Error< "controlling expression type %0 compatible with %1 generic association types">; // Blocks def err_blocks_disable : Error<"blocks support disabled - compile with -fblocks" " or %select{pick a deployment target that supports them|for OpenCL 2.0}0">; def err_block_returning_array_function : Error< "block cannot return %select{array|function}0 type %1">; // Builtin annotation def err_builtin_annotation_first_arg : Error< "first argument to __builtin_annotation must be an integer">; def err_builtin_annotation_second_arg : Error< "second argument to __builtin_annotation must be a non-wide string constant">; def err_msvc_annotation_wide_str : Error< "arguments to __annotation must be wide string constants">; // CFString checking def err_cfstring_literal_not_string_constant : Error< "CFString literal is not a string constant">; def warn_cfstring_truncated : Warning< "input conversion stopped due to an input byte that does not " "belong to the input codeset UTF-8">, InGroup>; // os_log checking // TODO: separate diagnostic for os_trace() def err_os_log_format_not_string_constant : Error< "os_log() format argument is not a string constant">; def err_os_log_argument_too_big : Error< "os_log() argument %0 is too big (%1 bytes, max %2)">; def warn_os_log_format_narg : Error< "os_log() '%%n' format specifier is not allowed">, DefaultError; // Statements. def err_continue_not_in_loop : Error< "'continue' statement not in loop statement">; def err_break_not_in_loop_or_switch : Error< "'break' statement not in loop or switch statement">; def warn_loop_ctrl_binds_to_inner : Warning< "'%0' is bound to current loop, GCC binds it to the enclosing loop">, InGroup; def warn_break_binds_to_switch : Warning< "'break' is bound to loop, GCC binds it to switch">, InGroup; def err_default_not_in_switch : Error< "'default' statement not in switch statement">; def err_case_not_in_switch : Error<"'case' statement not in switch statement">; def warn_bool_switch_condition : Warning< "switch condition has boolean value">, InGroup; def warn_case_value_overflow : Warning< "overflow converting case value to switch condition type (%0 to %1)">, InGroup; def err_duplicate_case : Error<"duplicate case value '%0'">; def err_duplicate_case_differing_expr : Error< "duplicate case value: '%0' and '%1' both equal '%2'">; def warn_case_empty_range : Warning<"empty case range specified">; def warn_missing_case_for_condition : Warning<"no case matching constant switch condition '%0'">; def warn_def_missing_case : Warning<"%plural{" "1:enumeration value %1 not explicitly handled in switch|" "2:enumeration values %1 and %2 not explicitly handled in switch|" "3:enumeration values %1, %2, and %3 not explicitly handled in switch|" ":%0 enumeration values not explicitly handled in switch: %1, %2, %3...}0">, InGroup, DefaultIgnore; def warn_missing_case : Warning<"%plural{" "1:enumeration value %1 not handled in switch|" "2:enumeration values %1 and %2 not handled in switch|" "3:enumeration values %1, %2, and %3 not handled in switch|" ":%0 enumeration values not handled in switch: %1, %2, %3...}0">, InGroup; def warn_unannotated_fallthrough : Warning< "unannotated fall-through between switch labels">, InGroup, DefaultIgnore; def warn_unannotated_fallthrough_per_function : Warning< "unannotated fall-through between switch labels in partly-annotated " "function">, InGroup, DefaultIgnore; def note_insert_fallthrough_fixit : Note< "insert '%0;' to silence this warning">; def note_insert_break_fixit : Note< "insert 'break;' to avoid fall-through">; def err_fallthrough_attr_wrong_target : Error< "%0 attribute is only allowed on empty statements">; def note_fallthrough_insert_semi_fixit : Note<"did you forget ';'?">; def err_fallthrough_attr_outside_switch : Error< "fallthrough annotation is outside switch statement">; def err_fallthrough_attr_invalid_placement : Error< "fallthrough annotation does not directly precede switch label">; def warn_fallthrough_attr_unreachable : Warning< "fallthrough annotation in unreachable code">, InGroup, DefaultIgnore; def warn_unreachable_default : Warning< "default label in switch which covers all enumeration values">, InGroup, DefaultIgnore; def warn_not_in_enum : Warning<"case value not in enumerated type %0">, InGroup; def warn_not_in_enum_assignment : Warning<"integer constant not in range " "of enumerated type %0">, InGroup>, DefaultIgnore; def err_typecheck_statement_requires_scalar : Error< "statement requires expression of scalar type (%0 invalid)">; def err_typecheck_statement_requires_integer : Error< "statement requires expression of integer type (%0 invalid)">; def err_multiple_default_labels_defined : Error< "multiple default labels in one switch">; def err_switch_multiple_conversions : Error< "multiple conversions from switch condition type %0 to an integral or " "enumeration type">; def note_switch_conversion : Note< "conversion to %select{integral|enumeration}0 type %1">; def err_switch_explicit_conversion : Error< "switch condition type %0 requires explicit conversion to %1">; def err_switch_incomplete_class_type : Error< "switch condition has incomplete class type %0">; def warn_empty_if_body : Warning< "if statement has empty body">, InGroup; def warn_empty_for_body : Warning< "for loop has empty body">, InGroup; def warn_empty_range_based_for_body : Warning< "range-based for loop has empty body">, InGroup; def warn_empty_while_body : Warning< "while loop has empty body">, InGroup; def warn_empty_switch_body : Warning< "switch statement has empty body">, InGroup; def note_empty_body_on_separate_line : Note< "put the semicolon on a separate line to silence this warning">; def err_va_start_captured_stmt : Error< "'va_start' cannot be used in a captured statement">; def err_va_start_outside_function : Error< "'va_start' cannot be used outside a function">; def err_va_start_fixed_function : Error< "'va_start' used in function with fixed args">; def err_va_start_used_in_wrong_abi_function : Error< "'va_start' used in %select{System V|Win64}0 ABI function">; def err_ms_va_start_used_in_sysv_function : Error< "'__builtin_ms_va_start' used in System V ABI function">; def warn_second_arg_of_va_start_not_last_named_param : Warning< "second argument to 'va_start' is not the last named parameter">, InGroup; def warn_va_start_type_is_undefined : Warning< "passing %select{an object that undergoes default argument promotion|" "an object of reference type|a parameter declared with the 'register' " "keyword}0 to 'va_start' has undefined behavior">, InGroup; def err_first_argument_to_va_arg_not_of_type_va_list : Error< "first argument to 'va_arg' is of type %0 and not 'va_list'">; def err_second_parameter_to_va_arg_incomplete: Error< "second argument to 'va_arg' is of incomplete type %0">; def err_second_parameter_to_va_arg_abstract: Error< "second argument to 'va_arg' is of abstract type %0">; def warn_second_parameter_to_va_arg_not_pod : Warning< "second argument to 'va_arg' is of non-POD type %0">, InGroup, DefaultError; def warn_second_parameter_to_va_arg_ownership_qualified : Warning< "second argument to 'va_arg' is of ARC ownership-qualified type %0">, InGroup, DefaultError; def warn_second_parameter_to_va_arg_never_compatible : Warning< "second argument to 'va_arg' is of promotable type %0; this va_arg has " "undefined behavior because arguments will be promoted to %1">, InGroup; def warn_return_missing_expr : Warning< "non-void %select{function|method}1 %0 should return a value">, DefaultError, InGroup; def ext_return_missing_expr : ExtWarn< "non-void %select{function|method}1 %0 should return a value">, DefaultError, InGroup; def ext_return_has_expr : ExtWarn< "%select{void function|void method|constructor|destructor}1 %0 " "should not return a value">, DefaultError, InGroup; def ext_return_has_void_expr : Extension< "void %select{function|method|block}1 %0 should not return void expression">; def err_return_init_list : Error< "%select{void function|void method|constructor|destructor}1 %0 " "must not return a value">; def err_ctor_dtor_returns_void : Error< "%select{constructor|destructor}1 %0 must not return void expression">; def warn_noreturn_function_has_return_expr : Warning< "function %0 declared 'noreturn' should not return">, InGroup; def warn_falloff_noreturn_function : Warning< "function declared 'noreturn' should not return">, InGroup; def err_noreturn_block_has_return_expr : Error< "block declared 'noreturn' should not return">; def err_noreturn_missing_on_first_decl : Error< "function declared '[[noreturn]]' after its first declaration">; def note_noreturn_missing_first_decl : Note< "declaration missing '[[noreturn]]' attribute is here">; def err_carries_dependency_missing_on_first_decl : Error< "%select{function|parameter}0 declared '[[carries_dependency]]' " "after its first declaration">; def note_carries_dependency_missing_first_decl : Note< "declaration missing '[[carries_dependency]]' attribute is here">; def err_carries_dependency_param_not_function_decl : Error< "'[[carries_dependency]]' attribute only allowed on parameter in a function " "declaration or lambda">; def err_block_on_nonlocal : Error< "__block attribute not allowed, only allowed on local variables">; def err_block_on_vm : Error< "__block attribute not allowed on declaration with a variably modified type">; def err_vec_builtin_non_vector : Error< "first two arguments to %0 must be vectors">; def err_vec_builtin_incompatible_vector : Error< "first two arguments to %0 must have the same type">; def err_vsx_builtin_nonconstant_argument : Error< "argument %0 to %1 must be a 2-bit unsigned literal (i.e. 0, 1, 2 or 3)">; def err_shufflevector_nonconstant_argument : Error< "index for __builtin_shufflevector must be a constant integer">; def err_shufflevector_argument_too_large : Error< "index for __builtin_shufflevector must be less than the total number " "of vector elements">; def err_convertvector_non_vector : Error< "first argument to __builtin_convertvector must be a vector">; def err_convertvector_non_vector_type : Error< "second argument to __builtin_convertvector must be a vector type">; def err_convertvector_incompatible_vector : Error< "first two arguments to __builtin_convertvector must have the same number of elements">; def err_first_argument_to_cwsc_not_call : Error< "first argument to __builtin_call_with_static_chain must be a non-member call expression">; def err_first_argument_to_cwsc_block_call : Error< "first argument to __builtin_call_with_static_chain must not be a block call">; def err_first_argument_to_cwsc_builtin_call : Error< "first argument to __builtin_call_with_static_chain must not be a builtin call">; def err_first_argument_to_cwsc_pdtor_call : Error< "first argument to __builtin_call_with_static_chain must not be a pseudo-destructor call">; def err_second_argument_to_cwsc_not_pointer : Error< "second argument to __builtin_call_with_static_chain must be of pointer type">; def err_vector_incorrect_num_initializers : Error< "%select{too many|too few}0 elements in vector initialization (expected %1 elements, have %2)">; def err_altivec_empty_initializer : Error<"expected initializer">; def err_invalid_neon_type_code : Error< "incompatible constant for this __builtin_neon function">; def err_argument_invalid_range : Error< "argument value %0 is outside the valid range [%1, %2]">; def warn_argument_invalid_range : Warning< "argument value %0 is outside the valid range [%1, %2]">, DefaultError, InGroup>; def err_argument_not_multiple : Error< "argument should be a multiple of %0">; def warn_neon_vector_initializer_non_portable : Warning< "vector initializers are not compatible with NEON intrinsics in big endian " "mode">, InGroup>; def note_neon_vector_initializer_non_portable : Note< "consider using vld1_%0%1() to initialize a vector from memory, or " "vcreate_%0%1() to initialize from an integer constant">; def note_neon_vector_initializer_non_portable_q : Note< "consider using vld1q_%0%1() to initialize a vector from memory, or " "vcombine_%0%1(vcreate_%0%1(), vcreate_%0%1()) to initialize from integer " "constants">; def err_systemz_invalid_tabort_code : Error< "invalid transaction abort code">; def err_64_bit_builtin_32_bit_tgt : Error< "this builtin is only available on 64-bit targets">; def err_32_bit_builtin_64_bit_tgt : Error< "this builtin is only available on 32-bit targets">; def err_builtin_x64_aarch64_only : Error< "this builtin is only available on x86-64 and aarch64 targets">; def err_ppc_builtin_only_on_pwr7 : Error< "this builtin is only valid on POWER7 or later CPUs">; def err_x86_builtin_invalid_rounding : Error< "invalid rounding argument">; def err_x86_builtin_invalid_scale : Error< "scale argument must be 1, 2, 4, or 8">; def err_hexagon_builtin_unsupported_cpu : Error< "builtin is not supported on this CPU">; def err_hexagon_builtin_requires_hvx : Error< "builtin requires HVX">; def err_hexagon_builtin_unsupported_hvx : Error< "builtin is not supported on this version of HVX">; def err_builtin_target_unsupported : Error< "builtin is not supported on this target">; def err_builtin_longjmp_unsupported : Error< "__builtin_longjmp is not supported for the current target">; def err_builtin_setjmp_unsupported : Error< "__builtin_setjmp is not supported for the current target">; def err_builtin_longjmp_invalid_val : Error< "argument to __builtin_longjmp must be a constant 1">; def err_builtin_requires_language : Error<"'%0' is only available in %1">; def err_constant_integer_arg_type : Error< "argument to %0 must be a constant integer">; def ext_mixed_decls_code : Extension< "ISO C90 forbids mixing declarations and code">, InGroup>; def err_non_local_variable_decl_in_for : Error< "declaration of non-local variable in 'for' loop">; def err_non_variable_decl_in_for : Error< "non-variable declaration in 'for' loop">; def err_toomany_element_decls : Error< "only one element declaration is allowed">; def err_selector_element_not_lvalue : Error< "selector element is not a valid lvalue">; def err_selector_element_type : Error< "selector element type %0 is not a valid object">; def err_selector_element_const_type : Error< "selector element of type %0 cannot be a constant l-value expression">; def err_collection_expr_type : Error< "the type %0 is not a pointer to a fast-enumerable object">; def warn_collection_expr_type : Warning< "collection expression type %0 may not respond to %1">; def err_invalid_conversion_between_ext_vectors : Error< "invalid conversion between ext-vector type %0 and %1">; def warn_duplicate_attribute_exact : Warning< "attribute %0 is already applied">, InGroup; def warn_duplicate_attribute : Warning< "attribute %0 is already applied with different parameters">, InGroup; def warn_sync_fetch_and_nand_semantics_change : Warning< "the semantics of this intrinsic changed with GCC " "version 4.4 - the newer semantics are provided here">, InGroup>; // Type def ext_invalid_sign_spec : Extension<"'%0' cannot be signed or unsigned">; def warn_receiver_forward_class : Warning< "receiver %0 is a forward class and corresponding @interface may not exist">, InGroup; def note_method_sent_forward_class : Note<"method %0 is used for the forward class">; def ext_missing_declspec : ExtWarn< "declaration specifier missing, defaulting to 'int'">; def ext_missing_type_specifier : ExtWarn< "type specifier missing, defaults to 'int'">, InGroup; def err_decimal_unsupported : Error< "GNU decimal type extension not supported">; def err_missing_type_specifier : Error< "C++ requires a type specifier for all declarations">; def err_objc_array_of_interfaces : Error< "array of interface %0 is invalid (probably should be an array of pointers)">; def ext_c99_array_usage : Extension< "%select{qualifier in |static |}0array size %select{||'[*] '}0is a C99 " "feature">, InGroup; def err_c99_array_usage_cxx : Error< "%select{qualifier in |static |}0array size %select{||'[*] '}0is a C99 " "feature, not permitted in C++">; def err_type_unsupported : Error< "%0 is not supported on this target">; def err_nsconsumed_attribute_mismatch : Error< "overriding method has mismatched ns_consumed attribute on its" " parameter">; def err_nsreturns_retained_attribute_mismatch : Error< "overriding method has mismatched ns_returns_%select{not_retained|retained}0" " attributes">; def warn_nsconsumed_attribute_mismatch : Warning< err_nsconsumed_attribute_mismatch.Text>, InGroup; def warn_nsreturns_retained_attribute_mismatch : Warning< err_nsreturns_retained_attribute_mismatch.Text>, InGroup; def note_getter_unavailable : Note< "or because setter is declared here, but no getter method %0 is found">; def err_invalid_protocol_qualifiers : Error< "invalid protocol qualifiers on non-ObjC type">; def warn_ivar_use_hidden : Warning< "local declaration of %0 hides instance variable">, InGroup; def warn_direct_initialize_call : Warning< "explicit call to +initialize results in duplicate call to +initialize">, InGroup; def warn_direct_super_initialize_call : Warning< "explicit call to [super initialize] should only be in implementation " "of +initialize">, InGroup; def err_ivar_use_in_class_method : Error< "instance variable %0 accessed in class method">; def err_private_ivar_access : Error<"instance variable %0 is private">, AccessControl; def err_protected_ivar_access : Error<"instance variable %0 is protected">, AccessControl; def warn_maynot_respond : Warning<"%0 may not respond to %1">; def ext_typecheck_base_super : Warning< "method parameter type " "%diff{$ does not match super class method parameter type $|" "does not match super class method parameter type}0,1">, InGroup, DefaultIgnore; def warn_missing_method_return_type : Warning< "method has no return type specified; defaults to 'id'">, InGroup, DefaultIgnore; def warn_direct_ivar_access : Warning<"instance variable %0 is being " "directly accessed">, InGroup>, DefaultIgnore; // Spell-checking diagnostics def err_unknown_typename : Error< "unknown type name %0">; def err_unknown_type_or_class_name_suggest : Error< "unknown %select{type|class}1 name %0; did you mean %2?">; def err_unknown_typename_suggest : Error< "unknown type name %0; did you mean %1?">; def err_unknown_nested_typename_suggest : Error< "no type named %0 in %1; did you mean %select{|simply }2%3?">; def err_no_member_suggest : Error<"no member named %0 in %1; did you mean %select{|simply }2%3?">; def err_undeclared_use_suggest : Error< "use of undeclared %0; did you mean %1?">; def err_undeclared_var_use_suggest : Error< "use of undeclared identifier %0; did you mean %1?">; def err_no_template : Error<"no template named %0">; def err_no_template_suggest : Error<"no template named %0; did you mean %1?">; def err_no_member_template : Error<"no template named %0 in %1">; def err_no_member_template_suggest : Error< "no template named %0 in %1; did you mean %select{|simply }2%3?">; def err_non_template_in_template_id : Error< "%0 does not name a template but is followed by template arguments">; def err_non_template_in_template_id_suggest : Error< "%0 does not name a template but is followed by template arguments; " "did you mean %1?">; def err_non_template_in_member_template_id_suggest : Error< "member %0 of %1 is not a template; did you mean %select{|simply }2%3?">; def note_non_template_in_template_id_found : Note< "non-template declaration found by name lookup">; def err_mem_init_not_member_or_class_suggest : Error< "initializer %0 does not name a non-static data member or base " "class; did you mean the %select{base class|member}1 %2?">; def err_field_designator_unknown_suggest : Error< "field designator %0 does not refer to any field in type %1; did you mean " "%2?">; def err_typecheck_member_reference_ivar_suggest : Error< "%0 does not have a member named %1; did you mean %2?">; def err_property_not_found_suggest : Error< "property %0 not found on object of type %1; did you mean %2?">; def err_class_property_found : Error< "property %0 is a class property; did you mean to access it with class '%1'?">; def err_ivar_access_using_property_syntax_suggest : Error< "property %0 not found on object of type %1; did you mean to access instance variable %2?">; def warn_property_access_suggest : Warning< "property %0 not found on object of type %1; did you mean to access property %2?">, InGroup; def err_property_found_suggest : Error< "property %0 found on object of type %1; did you mean to access " "it with the \".\" operator?">; def err_undef_interface_suggest : Error< "cannot find interface declaration for %0; did you mean %1?">; def warn_undef_interface_suggest : Warning< "cannot find interface declaration for %0; did you mean %1?">; def err_undef_superclass_suggest : Error< "cannot find interface declaration for %0, superclass of %1; did you mean " "%2?">; def err_undeclared_protocol_suggest : Error< "cannot find protocol declaration for %0; did you mean %1?">; def note_base_class_specified_here : Note< "base class %0 specified here">; def err_using_directive_suggest : Error< "no namespace named %0; did you mean %1?">; def err_using_directive_member_suggest : Error< "no namespace named %0 in %1; did you mean %select{|simply }2%3?">; def note_namespace_defined_here : Note<"namespace %0 defined here">; def err_sizeof_pack_no_pack_name_suggest : Error< "%0 does not refer to the name of a parameter pack; did you mean %1?">; def note_parameter_pack_here : Note<"parameter pack %0 declared here">; def err_uncasted_use_of_unknown_any : Error< "%0 has unknown type; cast it to its declared type to use it">; def err_uncasted_call_of_unknown_any : Error< "%0 has unknown return type; cast the call to its declared return type">; def err_uncasted_send_to_unknown_any_method : Error< "no known method %select{%objcinstance1|%objcclass1}0; cast the " "message send to the method's return type">; def err_unsupported_unknown_any_decl : Error< "%0 has unknown type, which is not supported for this kind of declaration">; def err_unsupported_unknown_any_expr : Error< "unsupported expression with unknown type">; def err_unsupported_unknown_any_call : Error< "call to unsupported expression with unknown type">; def err_unknown_any_addrof : Error< "the address of a declaration with unknown type " "can only be cast to a pointer type">; def err_unknown_any_addrof_call : Error< "address-of operator cannot be applied to a call to a function with " "unknown return type">; def err_unknown_any_var_function_type : Error< "variable %0 with unknown type cannot be given a function type">; def err_unknown_any_function : Error< "function %0 with unknown type must be given a function type">; def err_filter_expression_integral : Error< "filter expression type should be an integral value not %0">; def err_non_asm_stmt_in_naked_function : Error< "non-ASM statement in naked function is not supported">; def err_asm_naked_this_ref : Error< "'this' pointer references not allowed in naked functions">; def err_asm_naked_parm_ref : Error< "parameter references not allowed in naked functions">; // OpenCL warnings and errors. def err_invalid_astype_of_different_size : Error< "invalid reinterpretation: sizes of %0 and %1 must match">; def err_static_kernel : Error< "kernel functions cannot be declared static">; def err_opencl_ptrptr_kernel_param : Error< "kernel parameter cannot be declared as a pointer to a pointer">; def err_kernel_arg_address_space : Error< "pointer arguments to kernel functions must reside in '__global', " "'__constant' or '__local' address space">; def err_opencl_ext_vector_component_invalid_length : Error< "vector component access has invalid length %0. Supported: 1,2,3,4,8,16.">; def err_opencl_function_variable : Error< "%select{non-kernel function|function scope}0 variable cannot be declared in %1 address space">; def err_opencl_addrspace_scope : Error< "variables in the %0 address space can only be declared in the outermost " "scope of a kernel function">; def err_static_function_scope : Error< "variables in function scope cannot be declared static">; def err_opencl_bitfields : Error< "bit-fields are not supported in OpenCL">; def err_opencl_vla : Error< "variable length arrays are not supported in OpenCL">; def err_opencl_scalar_type_rank_greater_than_vector_type : Error< "scalar operand type has greater rank than the type of the vector " "element. (%0 and %1)">; def err_bad_kernel_param_type : Error< "%0 cannot be used as the type of a kernel parameter">; def err_record_with_pointers_kernel_param : Error< "%select{struct|union}0 kernel parameters may not contain pointers">; def note_within_field_of_type : Note< "within field of type %0 declared here">; def note_illegal_field_declared_here : Note< "field of illegal %select{type|pointer type}0 %1 declared here">; def err_opencl_type_struct_or_union_field : Error< "the %0 type cannot be used to declare a structure or union field">; def err_event_t_addr_space_qual : Error< "the event_t type can only be used with __private address space qualifier">; def err_expected_kernel_void_return_type : Error< "kernel must have void return type">; def err_sampler_initializer_not_integer : Error< "sampler_t initialization requires 32-bit integer, not %0">; def warn_sampler_initializer_invalid_bits : Warning< "sampler initializer has invalid %0 bits">, InGroup, DefaultIgnore; def err_sampler_argument_required : Error< "sampler_t variable required - got %0">; def err_wrong_sampler_addressspace: Error< "sampler type cannot be used with the __local and __global address space qualifiers">; def err_opencl_nonconst_global_sampler : Error< "global sampler requires a const or constant address space qualifier">; def err_opencl_cast_non_zero_to_event_t : Error< "cannot cast non-zero value '%0' to 'event_t'">; def err_opencl_global_invalid_addr_space : Error< "%select{program scope|static local|extern}0 variable must reside in %1 address space">; def err_missing_actual_pipe_type : Error< "missing actual type specifier for pipe">; def err_reference_pipe_type : Error < "pipes packet types cannot be of reference type">; def err_opencl_no_main : Error<"%select{function|kernel}0 cannot be called 'main'">; def err_opencl_kernel_attr : Error<"attribute %0 can only be applied to an OpenCL kernel function">; def err_opencl_return_value_with_address_space : Error< "return value cannot be qualified with address space">; def err_opencl_constant_no_init : Error< "variable in constant address space must be initialized">; def err_opencl_atomic_init: Error< "atomic variable can be %select{assigned|initialized}0 to a variable only " "in global address space">; def err_opencl_implicit_vector_conversion : Error< "implicit conversions between vector types (%0 and %1) are not permitted">; def err_opencl_invalid_type_array : Error< "array of %0 type is invalid in OpenCL">; def err_opencl_ternary_with_block : Error< "block type cannot be used as expression in ternary expression in OpenCL">; def err_opencl_pointer_to_type : Error< "pointer to type %0 is invalid in OpenCL">; def err_opencl_type_can_only_be_used_as_function_parameter : Error < "type %0 can only be used as a function parameter in OpenCL">; def warn_opencl_attr_deprecated_ignored : Warning < "%0 attribute is deprecated and ignored in OpenCL version %1">, InGroup; def err_opencl_variadic_function : Error< "invalid prototype, variadic arguments are not allowed in OpenCL">; def err_opencl_requires_extension : Error< "use of %select{type|declaration}0 %1 requires %2 extension to be enabled">; // OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions def err_opencl_builtin_pipe_first_arg : Error< "first argument to %0 must be a pipe type">; def err_opencl_builtin_pipe_arg_num : Error< "invalid number of arguments to function: %0">; def err_opencl_builtin_pipe_invalid_arg : Error< "invalid argument type to function %0 (expecting %1 having %2)">; def err_opencl_builtin_pipe_invalid_access_modifier : Error< "invalid pipe access modifier (expecting %0)">; // OpenCL access qualifier def err_opencl_invalid_access_qualifier : Error< "access qualifier can only be used for pipe and image type">; def err_opencl_invalid_read_write : Error< "access qualifier %0 can not be used for %1 %select{|prior to OpenCL version 2.0}2">; def err_opencl_multiple_access_qualifiers : Error< "multiple access qualifiers">; def note_opencl_typedef_access_qualifier : Note< "previously declared '%0' here">; // OpenCL Section 6.8.g def err_opencl_unknown_type_specifier : Error< "OpenCL %select{C|C++}0 version %1 does not support the '%2' " "%select{type qualifier|storage class specifier}3">; // OpenCL v2.0 s6.12.5 Blocks restrictions def err_opencl_block_storage_type : Error< "the __block storage type is not permitted">; def err_opencl_invalid_block_declaration : Error< "invalid block variable declaration - must be %select{const qualified|initialized}0">; def err_opencl_extern_block_declaration : Error< "invalid block variable declaration - using 'extern' storage class is disallowed">; def err_opencl_block_ref_block : Error< "cannot refer to a block inside block">; // OpenCL v2.0 s6.13.9 - Address space qualifier functions. def err_opencl_builtin_to_addr_arg_num : Error< "invalid number of arguments to function: %0">; def err_opencl_builtin_to_addr_invalid_arg : Error< "invalid argument %0 to function: %1, expecting a generic pointer argument">; // OpenCL v2.0 s6.13.17 Enqueue kernel restrictions. def err_opencl_enqueue_kernel_incorrect_args : Error< "illegal call to enqueue_kernel, incorrect argument types">; def err_opencl_enqueue_kernel_local_size_args : Error< "mismatch in number of block parameters and local size arguments passed">; def err_opencl_enqueue_kernel_invalid_local_size_type : Error< "illegal call to enqueue_kernel, parameter needs to be specified as integer type">; def err_opencl_enqueue_kernel_blocks_non_local_void_args : Error< "blocks used in enqueue_kernel call are expected to have parameters of type 'local void*'">; def err_opencl_enqueue_kernel_blocks_no_args : Error< "blocks with parameters are not accepted in this prototype of enqueue_kernel call">; def err_opencl_builtin_expected_type : Error< "illegal call to %0, expected %1 argument type">; // OpenCL v2.2 s2.1.2.3 - Vector Component Access def ext_opencl_ext_vector_type_rgba_selector: ExtWarn< "vector component name '%0' is an OpenCL version 2.2 feature">, InGroup; } // end of sema category let CategoryName = "OpenMP Issue" in { // OpenMP support. def err_omp_expected_var_arg : Error< "%0 is not a global variable, static local variable or static data member">; def err_omp_expected_var_arg_suggest : Error< "%0 is not a global variable, static local variable or static data member; " "did you mean %1">; def err_omp_global_var_arg : Error< "arguments of '#pragma omp %0' must have %select{global storage|static storage duration}1">; def err_omp_ref_type_arg : Error< "arguments of '#pragma omp %0' cannot be of reference type %1">; def err_omp_region_not_file_context : Error< "directive must be at file or namespace scope">; def err_omp_var_scope : Error< "'#pragma omp %0' must appear in the scope of the %q1 variable declaration">; def err_omp_var_used : Error< "'#pragma omp %0' must precede all references to variable %q1">; def err_omp_var_thread_local : Error< "variable %0 cannot be threadprivate because it is %select{thread-local|a global named register variable}1">; def err_omp_private_incomplete_type : Error< "a private variable with incomplete type %0">; def err_omp_firstprivate_incomplete_type : Error< "a firstprivate variable with incomplete type %0">; def err_omp_lastprivate_incomplete_type : Error< "a lastprivate variable with incomplete type %0">; def err_omp_reduction_incomplete_type : Error< "a reduction list item with incomplete type %0">; def err_omp_unexpected_clause_value : Error< "expected %0 in OpenMP clause '%1'">; def err_omp_expected_var_name_member_expr : Error< "expected variable name%select{| or data member of current class}0">; def err_omp_expected_var_name_member_expr_or_array_item : Error< "expected variable name%select{|, data member of current class}0, array element or array section">; def err_omp_expected_addressable_lvalue_or_array_item : Error< "expected addressable lvalue expression, array element or array section">; def err_omp_expected_named_var_member_or_array_expression: Error< "expected expression containing only member accesses and/or array sections based on named variables">; def err_omp_bit_fields_forbidden_in_clause : Error< "bit fields cannot be used to specify storage in a '%0' clause">; def err_array_section_does_not_specify_contiguous_storage : Error< "array section does not specify contiguous storage">; def err_omp_union_type_not_allowed : Error< "mapping of union members is not allowed">; def err_omp_expected_access_to_data_field : Error< "expected access to data field">; def err_omp_multiple_array_items_in_map_clause : Error< "multiple array elements associated with the same variable are not allowed in map clauses of the same construct">; def err_omp_pointer_mapped_along_with_derived_section : Error< "pointer cannot be mapped along with a section derived from itself">; def err_omp_original_storage_is_shared_and_does_not_contain : Error< "original storage of expression in data environment is shared but data environment do not fully contain mapped expression storage">; def err_omp_same_pointer_dereferenced : Error< "same pointer dereferenced in multiple different ways in map clause expressions">; def note_omp_task_predetermined_firstprivate_here : Note< "predetermined as a firstprivate in a task construct here">; def err_omp_threadprivate_incomplete_type : Error< "threadprivate variable with incomplete type %0">; def err_omp_no_dsa_for_variable : Error< "variable %0 must have explicitly specified data sharing attributes">; def err_omp_wrong_dsa : Error< "%0 variable cannot be %1">; def err_omp_variably_modified_type_not_supported : Error< "arguments of OpenMP clause '%0' in '#pragma omp %2' directive cannot be of variably-modified type %1">; def note_omp_explicit_dsa : Note< "defined as %0">; def note_omp_predetermined_dsa : Note< "%select{static data member is predetermined as shared|" "variable with static storage duration is predetermined as shared|" "loop iteration variable is predetermined as private|" "loop iteration variable is predetermined as linear|" "loop iteration variable is predetermined as lastprivate|" "constant variable is predetermined as shared|" "global variable is predetermined as shared|" "non-shared variable in a task construct is predetermined as firstprivate|" "variable with automatic storage duration is predetermined as private}0" "%select{|; perhaps you forget to enclose 'omp %2' directive into a parallel or another task region?}1">; def note_omp_implicit_dsa : Note< "implicitly determined as %0">; def err_omp_loop_var_dsa : Error< "loop iteration variable in the associated loop of 'omp %1' directive may not be %0, predetermined as %2">; def err_omp_not_for : Error< "%select{statement after '#pragma omp %1' must be a for loop|" "expected %2 for loops after '#pragma omp %1'%select{|, but found only %4}3}0">; def note_omp_collapse_ordered_expr : Note< "as specified in %select{'collapse'|'ordered'|'collapse' and 'ordered'}0 clause%select{||s}0">; def err_omp_negative_expression_in_clause : Error< "argument to '%0' clause must be a %select{non-negative|strictly positive}1 integer value">; def err_omp_not_integral : Error< "expression must have integral or unscoped enumeration " "type, not %0">; def err_omp_threadprivate_in_target : Error< "threadprivate variables cannot be used in target constructs">; def err_omp_incomplete_type : Error< "expression has incomplete class type %0">; def err_omp_explicit_conversion : Error< "expression requires explicit conversion from %0 to %1">; def note_omp_conversion_here : Note< "conversion to %select{integral|enumeration}0 type %1 declared here">; def err_omp_ambiguous_conversion : Error< "ambiguous conversion from type %0 to an integral or unscoped " "enumeration type">; def err_omp_required_access : Error< "%0 variable must be %1">; def err_omp_const_variable : Error< "const-qualified variable cannot be %0">; def err_omp_const_reduction_list_item : Error< "const-qualified list item cannot be reduction">; def err_omp_linear_incomplete_type : Error< "a linear variable with incomplete type %0">; def err_omp_linear_expected_int_or_ptr : Error< "argument of a linear clause should be of integral or pointer " "type, not %0">; def warn_omp_linear_step_zero : Warning< "zero linear step (%0 %select{|and other variables in clause }1should probably be const)">, InGroup; def warn_omp_alignment_not_power_of_two : Warning< "aligned clause will be ignored because the requested alignment is not a power of 2">, InGroup; def err_omp_enclosed_declare_target : Error< "declare target region may not be enclosed within another declare target region">; def err_omp_invalid_target_decl : Error< "%0 used in declare target directive is not a variable or a function name">; def err_omp_declare_target_multiple : Error< "%0 appears multiple times in clauses on the same declare target directive">; def err_omp_declare_target_to_and_link : Error< "%0 must not appear in both clauses 'to' and 'link'">; def warn_omp_not_in_target_context : Warning< "declaration is not declared in any declare target region">, InGroup; def err_omp_function_in_link_clause : Error< "function name is not allowed in 'link' clause">; def err_omp_aligned_expected_array_or_ptr : Error< "argument of aligned clause should be array" "%select{ or pointer|, pointer, reference to array or reference to pointer}1" ", not %0">; def err_omp_aligned_twice : Error< "%select{a variable|a parameter|'this'}0 cannot appear in more than one aligned clause">; def err_omp_local_var_in_threadprivate_init : Error< "variable with local storage in initial value of threadprivate variable">; def err_omp_loop_not_canonical_init : Error< "initialization clause of OpenMP for loop is not in canonical form " "('var = init' or 'T var = init')">; def ext_omp_loop_not_canonical_init : ExtWarn< "initialization clause of OpenMP for loop is not in canonical form " "('var = init' or 'T var = init')">, InGroup; def err_omp_loop_not_canonical_cond : Error< "condition of OpenMP for loop must be a relational comparison " "('<', '<=', '>', or '>=') of loop variable %0">; def err_omp_loop_not_canonical_incr : Error< "increment clause of OpenMP for loop must perform simple addition " "or subtraction on loop variable %0">; def err_omp_loop_variable_type : Error< "variable must be of integer or %select{pointer|random access iterator}0 type">; def err_omp_loop_incr_not_compatible : Error< "increment expression must cause %0 to %select{decrease|increase}1 " "on each iteration of OpenMP for loop">; def note_omp_loop_cond_requres_compatible_incr : Note< "loop step is expected to be %select{negative|positive}0 due to this condition">; def err_omp_loop_diff_cxx : Error< "could not calculate number of iterations calling 'operator-' with " "upper and lower loop bounds">; def err_omp_loop_cannot_use_stmt : Error< "'%0' statement cannot be used in OpenMP for loop">; def err_omp_simd_region_cannot_use_stmt : Error< "'%0' statement cannot be used in OpenMP simd region">; def warn_omp_loop_64_bit_var : Warning< "OpenMP loop iteration variable cannot have more than 64 bits size and will be narrowed">, InGroup; def err_omp_unknown_reduction_identifier : Error< "incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', " "'&&', '||', 'min' or 'max' or declare reduction for type %0">; def err_omp_not_resolved_reduction_identifier : Error< "unable to resolve declare reduction construct for type %0">; def err_omp_reduction_ref_type_arg : Error< "argument of OpenMP clause '%0' must reference the same object in all threads">; def err_omp_clause_not_arithmetic_type_arg : Error< "arguments of OpenMP clause '%0' for 'min' or 'max' must be of %select{scalar|arithmetic}1 type">; def err_omp_clause_floating_type_arg : Error< "arguments of OpenMP clause '%0' with bitwise operators cannot be of floating type">; def err_omp_once_referenced : Error< "variable can appear only once in OpenMP '%0' clause">; def err_omp_once_referenced_in_target_update : Error< "variable can appear only once in OpenMP 'target update' construct">; def note_omp_referenced : Note< "previously referenced here">; def err_omp_reduction_in_task : Error< "reduction variables may not be accessed in an explicit task">; def err_omp_reduction_id_not_compatible : Error< "list item of type %0 is not valid for specified reduction operation: unable to provide default initialization value">; def err_omp_in_reduction_not_task_reduction : Error< "in_reduction variable must appear in a task_reduction clause">; def err_omp_reduction_identifier_mismatch : Error< "in_reduction variable must have the same reduction operation as in a task_reduction clause">; def note_omp_previous_reduction_identifier : Note< "previously marked as task_reduction with different reduction operation">; def err_omp_prohibited_region : Error< "region cannot be%select{| closely}0 nested inside '%1' region" "%select{|; perhaps you forget to enclose 'omp %3' directive into a parallel region?|" "; perhaps you forget to enclose 'omp %3' directive into a for or a parallel for region with 'ordered' clause?|" "; perhaps you forget to enclose 'omp %3' directive into a target region?|" "; perhaps you forget to enclose 'omp %3' directive into a teams region?}2">; def err_omp_prohibited_region_simd : Error< "OpenMP constructs may not be nested inside a simd region">; def err_omp_prohibited_region_atomic : Error< "OpenMP constructs may not be nested inside an atomic region">; def err_omp_prohibited_region_critical_same_name : Error< "cannot nest 'critical' regions having the same name %0">; def note_omp_previous_critical_region : Note< "previous 'critical' region starts here">; def err_omp_sections_not_compound_stmt : Error< "the statement for '#pragma omp sections' must be a compound statement">; def err_omp_parallel_sections_not_compound_stmt : Error< "the statement for '#pragma omp parallel sections' must be a compound statement">; def err_omp_orphaned_section_directive : Error< "%select{orphaned 'omp section' directives are prohibited, it|'omp section' directive}0" " must be closely nested to a sections region%select{|, not a %1 region}0">; def err_omp_sections_substmt_not_section : Error< "statement in 'omp sections' directive must be enclosed into a section region">; def err_omp_parallel_sections_substmt_not_section : Error< "statement in 'omp parallel sections' directive must be enclosed into a section region">; def err_omp_parallel_reduction_in_task_firstprivate : Error< "argument of a reduction clause of a %0 construct must not appear in a firstprivate clause on a task construct">; def err_omp_atomic_read_not_expression_statement : Error< "the statement for 'atomic read' must be an expression statement of form 'v = x;'," " where v and x are both lvalue expressions with scalar type">; def note_omp_atomic_read_write: Note< "%select{expected an expression statement|expected built-in assignment operator|expected expression of scalar type|expected lvalue expression}0">; def err_omp_atomic_write_not_expression_statement : Error< "the statement for 'atomic write' must be an expression statement of form 'x = expr;'," " where x is a lvalue expression with scalar type">; def err_omp_atomic_update_not_expression_statement : Error< "the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x'," " where x is an l-value expression with scalar type">; def err_omp_atomic_not_expression_statement : Error< "the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x'," " where x is an l-value expression with scalar type">; def note_omp_atomic_update: Note< "%select{expected an expression statement|expected built-in binary or unary operator|expected unary decrement/increment operation|" "expected expression of scalar type|expected assignment expression|expected built-in binary operator|" "expected one of '+', '*', '-', '/', '&', '^', '%|', '<<', or '>>' built-in operations|expected in right hand side of expression}0">; def err_omp_atomic_capture_not_expression_statement : Error< "the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x'," " where x and v are both l-value expressions with scalar type">; def err_omp_atomic_capture_not_compound_statement : Error< "the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}'," " '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}'," " '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}'" " where x is an l-value expression with scalar type">; def note_omp_atomic_capture: Note< "%select{expected assignment expression|expected compound statement|expected exactly two expression statements|expected in right hand side of the first expression}0">; def err_omp_atomic_several_clauses : Error< "directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause">; def note_omp_atomic_previous_clause : Note< "'%0' clause used here">; def err_omp_target_contains_not_only_teams : Error< "target construct with nested teams region contains statements outside of the teams construct">; def note_omp_nested_teams_construct_here : Note< "nested teams construct here">; def note_omp_nested_statement_here : Note< "%select{statement|directive}0 outside teams construct here">; def err_omp_single_copyprivate_with_nowait : Error< "the 'copyprivate' clause must not be used with the 'nowait' clause">; def note_omp_nowait_clause_here : Note< "'nowait' clause is here">; def err_omp_single_decl_in_declare_simd : Error< "single declaration is expected after 'declare simd' directive">; def err_omp_function_expected : Error< "'#pragma omp declare simd' can only be applied to functions">; def err_omp_wrong_cancel_region : Error< "one of 'for', 'parallel', 'sections' or 'taskgroup' is expected">; def err_omp_parent_cancel_region_nowait : Error< "parent region for 'omp %select{cancellation point|cancel}0' construct cannot be nowait">; def err_omp_parent_cancel_region_ordered : Error< "parent region for 'omp %select{cancellation point|cancel}0' construct cannot be ordered">; def err_omp_reduction_wrong_type : Error<"reduction type cannot be %select{qualified with 'const', 'volatile' or 'restrict'|a function|a reference|an array}0 type">; def err_omp_wrong_var_in_declare_reduction : Error<"only %select{'omp_priv' or 'omp_orig'|'omp_in' or 'omp_out'}0 variables are allowed in %select{initializer|combiner}0 expression">; def err_omp_declare_reduction_redefinition : Error<"redefinition of user-defined reduction for type %0">; def err_omp_array_section_use : Error<"OpenMP array section is not allowed here">; def err_omp_typecheck_section_value : Error< "subscripted value is not an array or pointer">; def err_omp_typecheck_section_not_integer : Error< "array section %select{lower bound|length}0 is not an integer">; def err_omp_section_function_type : Error< "section of pointer to function type %0">; def warn_omp_section_is_char : Warning<"array section %select{lower bound|length}0 is of type 'char'">, InGroup, DefaultIgnore; def err_omp_section_incomplete_type : Error< "section of pointer to incomplete type %0">; def err_omp_section_not_subset_of_array : Error< "array section must be a subset of the original array">; def err_omp_section_length_negative : Error< "section length is evaluated to a negative value %0">; def err_omp_section_length_undefined : Error< "section length is unspecified and cannot be inferred because subscripted value is %select{not an array|an array of unknown bound}0">; def err_omp_wrong_linear_modifier : Error< "expected %select{'val' modifier|one of 'ref', val' or 'uval' modifiers}0">; def err_omp_wrong_linear_modifier_non_reference : Error< "variable of non-reference type %0 can be used only with 'val' modifier, but used with '%1'">; def err_omp_wrong_simdlen_safelen_values : Error< "the value of 'simdlen' parameter must be less than or equal to the value of the 'safelen' parameter">; def err_omp_wrong_if_directive_name_modifier : Error< "directive name modifier '%0' is not allowed for '#pragma omp %1'">; def err_omp_no_more_if_clause : Error< "no more 'if' clause is allowed">; def err_omp_unnamed_if_clause : Error< "expected %select{|one of}0 %1 directive name modifier%select{|s}0">; def note_omp_previous_named_if_clause : Note< "previous clause with directive name modifier specified here">; def err_omp_ordered_directive_with_param : Error< "'ordered' directive %select{without any clauses|with 'threads' clause}0 cannot be closely nested inside ordered region with specified parameter">; def err_omp_ordered_directive_without_param : Error< "'ordered' directive with 'depend' clause cannot be closely nested inside ordered region without specified parameter">; def note_omp_ordered_param : Note< "'ordered' clause with specified parameter">; def err_omp_expected_base_var_name : Error< "expected variable name as a base of the array %select{subscript|section}0">; def err_omp_map_shared_storage : Error< "variable already marked as mapped in current construct">; def err_omp_invalid_map_type_for_directive : Error< "%select{map type '%1' is not allowed|map type must be specified}0 for '#pragma omp %2'">; def err_omp_no_clause_for_directive : Error< "expected at least one %0 clause for '#pragma omp %1'">; def err_omp_threadprivate_in_clause : Error< "threadprivate variables are not allowed in '%0' clause">; def err_omp_wrong_ordered_loop_count : Error< "the parameter of the 'ordered' clause must be greater than or equal to the parameter of the 'collapse' clause">; def note_collapse_loop_count : Note< "parameter of the 'collapse' clause">; def err_omp_grainsize_num_tasks_mutually_exclusive : Error< "'%0' and '%1' clause are mutually exclusive and may not appear on the same directive">; def note_omp_previous_grainsize_num_tasks : Note< "'%0' clause is specified here">; def err_omp_hint_clause_no_name : Error< "the name of the construct must be specified in presence of 'hint' clause">; def err_omp_critical_with_hint : Error< "constructs with the same name must have a 'hint' clause with the same value">; def note_omp_critical_hint_here : Note< "%select{|previous }0'hint' clause with value '%1'">; def note_omp_critical_no_hint : Note< "%select{|previous }0directive with no 'hint' clause specified">; def err_omp_depend_clause_thread_simd : Error< "'depend' clauses cannot be mixed with '%0' clause">; def err_omp_depend_sink_expected_loop_iteration : Error< "expected%select{| %1}0 loop iteration variable">; def err_omp_depend_sink_unexpected_expr : Error< "unexpected expression: number of expressions is larger than the number of associated loops">; def err_omp_depend_sink_expected_plus_minus : Error< "expected '+' or '-' operation">; def err_omp_depend_sink_source_not_allowed : Error< "'depend(%select{source|sink:vec}0)' clause%select{|s}0 cannot be mixed with 'depend(%select{sink:vec|source}0)' clause%select{s|}0">; def err_omp_linear_ordered : Error< "'linear' clause cannot be specified along with 'ordered' clause with a parameter">; def err_omp_unexpected_schedule_modifier : Error< "modifier '%0' cannot be used along with modifier '%1'">; def err_omp_schedule_nonmonotonic_static : Error< "'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind">; def err_omp_schedule_nonmonotonic_ordered : Error< "'schedule' clause with 'nonmonotonic' modifier cannot be specified if an 'ordered' clause is specified">; def err_omp_ordered_simd : Error< "'ordered' clause with a parameter can not be specified in '#pragma omp %0' directive">; def err_omp_variable_in_given_clause_and_dsa : Error< "%0 variable cannot be in a %1 clause in '#pragma omp %2' directive">; def err_omp_param_or_this_in_clause : Error< "expected reference to one of the parameters of function %0%select{| or 'this'}1">; def err_omp_expected_uniform_param : Error< "expected a reference to a parameter specified in a 'uniform' clause">; def err_omp_expected_int_param : Error< "expected a reference to an integer-typed parameter">; def err_omp_at_least_one_motion_clause_required : Error< "expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'">; def err_omp_usedeviceptr_not_a_pointer : Error< "expected pointer or reference to pointer in 'use_device_ptr' clause">; def err_omp_argument_type_isdeviceptr : Error < "expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'">; def warn_omp_nesting_simd : Warning< "OpenMP only allows an ordered construct with the simd clause nested in a simd construct">, InGroup; def err_omp_orphaned_device_directive : Error< "orphaned 'omp %0' directives are prohibited" "; perhaps you forget to enclose the directive into a %select{|||target |teams }1region?">; def err_omp_reduction_non_addressable_expression : Error< "expected addressable reduction item for the task-based directives">; def err_omp_reduction_with_nogroup : Error< "'reduction' clause cannot be used with 'nogroup' clause">; def err_omp_reduction_vla_unsupported : Error< "cannot generate code for reduction on %select{|array section, which requires a }0variable length array">; def err_omp_linear_distribute_var_non_loop_iteration : Error< "only loop iteration variables are allowed in 'linear' clause in distribute directives">; def warn_omp_non_trivial_type_mapped : Warning< "Non-trivial type %0 is mapped, only trivial types are guaranteed to be mapped correctly">, InGroup; } // end of OpenMP category let CategoryName = "Related Result Type Issue" in { // Objective-C related result type compatibility def warn_related_result_type_compatibility_class : Warning< "method is expected to return an instance of its class type " "%diff{$, but is declared to return $|" ", but is declared to return different type}0,1">; def warn_related_result_type_compatibility_protocol : Warning< "protocol method is expected to return an instance of the implementing " "class, but is declared to return %0">; def note_related_result_type_family : Note< "%select{overridden|current}0 method is part of the '%select{|alloc|copy|init|" "mutableCopy|new|autorelease|dealloc|finalize|release|retain|retainCount|" "self}1' method family%select{| and is expected to return an instance of its " "class type}0">; def note_related_result_type_overridden : Note< "overridden method returns an instance of its class type">; def note_related_result_type_inferred : Note< "%select{class|instance}0 method %1 is assumed to return an instance of " "its receiver type (%2)">; def note_related_result_type_explicit : Note< "%select{overridden|current}0 method is explicitly declared 'instancetype'" "%select{| and is expected to return an instance of its class type}0">; def err_invalid_type_for_program_scope_var : Error< "the %0 type cannot be used to declare a program scope variable">; } let CategoryName = "Modules Issue" in { def err_module_decl_in_module_map_module : Error< "'module' declaration found while building module from module map">; def err_module_interface_implementation_mismatch : Error< "missing 'export' specifier in module declaration while " "building module interface">; def err_current_module_name_mismatch : Error< "module name '%0' specified on command line does not match name of module">; def err_module_redefinition : Error< "redefinition of module '%0'">; def note_prev_module_definition : Note<"previously defined here">; def note_prev_module_definition_from_ast_file : Note<"module loaded from '%0'">; def err_module_not_defined : Error< "definition of module '%0' is not available; use -fmodule-file= to specify " "path to precompiled module interface">; def err_module_redeclaration : Error< "translation unit contains multiple module declarations">; def note_prev_module_declaration : Note<"previous module declaration is here">; def err_module_declaration_missing : Error< "missing 'export module' declaration in module interface unit">; def err_module_private_specialization : Error< "%select{template|partial|member}0 specialization cannot be " "declared __module_private__">; def err_module_private_local : Error< "%select{local variable|parameter|typedef}0 %1 cannot be declared " "__module_private__">; def err_module_private_local_class : Error< "local %select{struct|interface|union|class|enum}0 cannot be declared " "__module_private__">; def err_module_unimported_use : Error< "%select{declaration|definition|default argument|" "explicit specialization|partial specialization}0 of %1 must be imported " "from module '%2' before it is required">; def err_module_unimported_use_header : Error< "missing '#include %3'; " "%select{declaration|definition|default argument|" "explicit specialization|partial specialization}0 of %1 must be imported " "from module '%2' before it is required">; def err_module_unimported_use_multiple : Error< "%select{declaration|definition|default argument|" "explicit specialization|partial specialization}0 of %1 must be imported " "from one of the following modules before it is required:%2">; def ext_module_import_in_extern_c : ExtWarn< "import of C++ module '%0' appears within extern \"C\" language linkage " "specification">, DefaultError, InGroup>; def err_module_import_not_at_top_level_fatal : Error< "import of module '%0' appears within %1">, DefaultFatal; def ext_module_import_not_at_top_level_noop : ExtWarn< "redundant #include of module '%0' appears within %1">, DefaultError, InGroup>; def note_module_import_not_at_top_level : Note<"%0 begins here">; def err_module_self_import : Error< "import of module '%0' appears within same top-level module '%1'">; def err_module_import_in_implementation : Error< "@import of module '%0' in implementation of '%1'; use #import">; // C++ Modules TS def err_export_within_export : Error< "export declaration appears within another export declaration">; def err_export_not_in_module_interface : Error< "export declaration can only be used within a module interface unit after " "the module declaration">; def ext_equivalent_internal_linkage_decl_in_modules : ExtWarn< "ambiguous use of internal linkage declaration %0 defined in multiple modules">, InGroup>; def note_equivalent_internal_linkage_decl : Note< "declared here%select{ in module '%1'|}0">; def note_redefinition_modules_same_file : Note< "'%0' included multiple times, additional include site in header from module '%1'">; def note_redefinition_include_same_file : Note< "'%0' included multiple times, additional include site here">; } let CategoryName = "Coroutines Issue" in { def err_return_in_coroutine : Error< "return statement not allowed in coroutine; did you mean 'co_return'?">; def note_declared_coroutine_here : Note< "function is a coroutine due to use of '%0' here">; def err_coroutine_objc_method : Error< "Objective-C methods as coroutines are not yet supported">; def err_coroutine_unevaluated_context : Error< "'%0' cannot be used in an unevaluated context">; def err_coroutine_outside_function : Error< "'%0' cannot be used outside a function">; def err_coroutine_invalid_func_context : Error< "'%1' cannot be used in %select{a constructor|a destructor" "|a copy assignment operator|a move assignment operator|the 'main' function" "|a constexpr function|a function with a deduced return type" "|a varargs function}0">; def err_implied_coroutine_type_not_found : Error< "%0 type was not found; include before defining " "a coroutine">; def err_implicit_coroutine_std_nothrow_type_not_found : Error< "std::nothrow was not found; include before defining a coroutine which " "uses get_return_object_on_allocation_failure()">; def err_malformed_std_nothrow : Error< "std::nothrow must be a valid variable declaration">; def err_malformed_std_coroutine_handle : Error< "std::experimental::coroutine_handle must be a class template">; def err_coroutine_handle_missing_member : Error< "std::experimental::coroutine_handle missing a member named '%0'">; def err_malformed_std_coroutine_traits : Error< "'std::experimental::coroutine_traits' must be a class template">; def err_implied_std_coroutine_traits_promise_type_not_found : Error< "this function cannot be a coroutine: %q0 has no member named 'promise_type'">; def err_implied_std_coroutine_traits_promise_type_not_class : Error< "this function cannot be a coroutine: %0 is not a class">; def err_coroutine_promise_type_incomplete : Error< "this function cannot be a coroutine: %0 is an incomplete type">; def err_coroutine_type_missing_specialization : Error< "this function cannot be a coroutine: missing definition of " "specialization %0">; def err_coroutine_promise_incompatible_return_functions : Error< "the coroutine promise type %0 declares both 'return_value' and 'return_void'">; def err_coroutine_promise_requires_return_function : Error< "the coroutine promise type %0 must declare either 'return_value' or 'return_void'">; def note_coroutine_promise_implicit_await_transform_required_here : Note< "call to 'await_transform' implicitly required by 'co_await' here">; def note_coroutine_promise_suspend_implicitly_required : Note< "call to '%select{initial_suspend|final_suspend}0' implicitly " "required by the %select{initial suspend point|final suspend point}0">; def err_coroutine_promise_unhandled_exception_required : Error< "%0 is required to declare the member 'unhandled_exception()'">; def warn_coroutine_promise_unhandled_exception_required_with_exceptions : Warning< "%0 is required to declare the member 'unhandled_exception()' when exceptions are enabled">, InGroup; def err_coroutine_promise_get_return_object_on_allocation_failure : Error< "%0: 'get_return_object_on_allocation_failure()' must be a static member function">; def err_seh_in_a_coroutine_with_cxx_exceptions : Error< "cannot use SEH '__try' in a coroutine when C++ exceptions are enabled">; def err_coroutine_promise_new_requires_nothrow : Error< "%0 is required to have a non-throwing noexcept specification when the promise " "type declares 'get_return_object_on_allocation_failure()'">; def note_coroutine_promise_call_implicitly_required : Note< "call to %0 implicitly required by coroutine function here">; def err_await_suspend_invalid_return_type : Error< "return type of 'await_suspend' is required to be 'void' or 'bool' (have %0)" >; def note_await_ready_no_bool_conversion : Note< "return type of 'await_ready' is required to be contextually convertible to 'bool'" >; } let CategoryName = "Documentation Issue" in { def warn_not_a_doxygen_trailing_member_comment : Warning< "not a Doxygen trailing comment">, InGroup, DefaultIgnore; } // end of documentation issue category let CategoryName = "Instrumentation Issue" in { def warn_profile_data_out_of_date : Warning< "profile data may be out of date: of %0 function%s0, %1 %plural{1:has|:have}1" " mismatched data that will be ignored">, InGroup; def warn_profile_data_missing : Warning< "profile data may be incomplete: of %0 function%s0, %1 %plural{1:has|:have}1" " no data">, InGroup, DefaultIgnore; def warn_profile_data_unprofiled : Warning< "no profile data available for file \"%0\"">, InGroup; } // end of instrumentation issue category let CategoryName = "Nullability Issue" in { def warn_mismatched_nullability_attr : Warning< "nullability specifier %0 conflicts with existing specifier %1">, InGroup; def warn_nullability_declspec : Warning< "nullability specifier %0 cannot be applied " "to non-pointer type %1; did you mean to apply the specifier to the " "%select{pointer|block pointer|member pointer|function pointer|" "member function pointer}2?">, InGroup, DefaultError; def note_nullability_here : Note<"%0 specified here">; def err_nullability_nonpointer : Error< "nullability specifier %0 cannot be applied to non-pointer type %1">; def warn_nullability_lost : Warning< "implicit conversion from nullable pointer %0 to non-nullable pointer " "type %1">, InGroup, DefaultIgnore; def warn_zero_as_null_pointer_constant : Warning< "zero as null pointer constant">, InGroup>, DefaultIgnore; def err_nullability_cs_multilevel : Error< "nullability keyword %0 cannot be applied to multi-level pointer type %1">; def note_nullability_type_specifier : Note< "use nullability type specifier %0 to affect the innermost " "pointer type of %1">; def warn_null_resettable_setter : Warning< "synthesized setter %0 for null_resettable property %1 does not handle nil">, InGroup; def warn_nullability_missing : Warning< "%select{pointer|block pointer|member pointer}0 is missing a nullability " "type specifier (_Nonnull, _Nullable, or _Null_unspecified)">, InGroup; def warn_nullability_missing_array : Warning< "array parameter is missing a nullability type specifier (_Nonnull, " "_Nullable, or _Null_unspecified)">, InGroup; def note_nullability_fix_it : Note< "insert '%select{_Nonnull|_Nullable|_Null_unspecified}0' if the " "%select{pointer|block pointer|member pointer|array parameter}1 " "%select{should never be null|may be null|should not declare nullability}0">; def warn_nullability_inferred_on_nested_type : Warning< "inferring '_Nonnull' for pointer type within %select{array|reference}0 is " "deprecated">, InGroup; def err_objc_type_arg_explicit_nullability : Error< "type argument %0 cannot explicitly specify nullability">; def err_objc_type_param_bound_explicit_nullability : Error< "type parameter %0 bound %1 cannot explicitly specify nullability">; } let CategoryName = "Generics Issue" in { def err_objc_type_param_bound_nonobject : Error< "type bound %0 for type parameter %1 is not an Objective-C pointer type">; def err_objc_type_param_bound_missing_pointer : Error< "missing '*' in type bound %0 for type parameter %1">; def err_objc_type_param_bound_qualified : Error< "type bound %1 for type parameter %0 cannot be qualified with '%2'">; def err_objc_type_param_redecl : Error< "redeclaration of type parameter %0">; def err_objc_type_param_arity_mismatch : Error< "%select{forward class declaration|class definition|category|extension}0 has " "too %select{few|many}1 type parameters (expected %2, have %3)">; def err_objc_type_param_bound_conflict : Error< "type bound %0 for type parameter %1 conflicts with " "%select{implicit|previous}2 bound %3%select{for type parameter %5|}4">; def err_objc_type_param_variance_conflict : Error< "%select{in|co|contra}0variant type parameter %1 conflicts with previous " "%select{in|co|contra}2variant type parameter %3">; def note_objc_type_param_here : Note<"type parameter %0 declared here">; def err_objc_type_param_bound_missing : Error< "missing type bound %0 for type parameter %1 in %select{@interface|@class}2">; def err_objc_parameterized_category_nonclass : Error< "%select{extension|category}0 of non-parameterized class %1 cannot have type " "parameters">; def err_objc_parameterized_forward_class : Error< "forward declaration of non-parameterized class %0 cannot have type " "parameters">; def err_objc_parameterized_forward_class_first : Error< "class %0 previously declared with type parameters">; def err_objc_type_arg_missing_star : Error< "type argument %0 must be a pointer (requires a '*')">; def err_objc_type_arg_qualified : Error< "type argument %0 cannot be qualified with '%1'">; def err_objc_type_arg_missing : Error< "no type or protocol named %0">; def err_objc_type_args_and_protocols : Error< "angle brackets contain both a %select{type|protocol}0 (%1) and a " "%select{protocol|type}0 (%2)">; def err_objc_type_args_non_class : Error< "type arguments cannot be applied to non-class type %0">; def err_objc_type_args_non_parameterized_class : Error< "type arguments cannot be applied to non-parameterized class %0">; def err_objc_type_args_specialized_class : Error< "type arguments cannot be applied to already-specialized class type %0">; def err_objc_type_args_wrong_arity : Error< "too %select{many|few}0 type arguments for class %1 (have %2, expected %3)">; } def err_objc_type_arg_not_id_compatible : Error< "type argument %0 is neither an Objective-C object nor a block type">; def err_objc_type_arg_does_not_match_bound : Error< "type argument %0 does not satisfy the bound (%1) of type parameter %2">; def warn_objc_redundant_qualified_class_type : Warning< "parameterized class %0 already conforms to the protocols listed; did you " "forget a '*'?">, InGroup; def warn_block_literal_attributes_on_omitted_return_type : Warning< "attribute %0 ignored, because it cannot be applied to omitted return type">, InGroup; def warn_block_literal_qualifiers_on_omitted_return_type : Warning< "'%0' qualifier on omitted return type %1 has no effect">, InGroup; def ext_warn_gnu_final : ExtWarn< "__final is a GNU extension, consider using C++11 final">, InGroup; def warn_shadow_field : Warning<"non-static data member %0 of %1 shadows member inherited from " "type %2">, InGroup, DefaultIgnore; def note_shadow_field : Note<"declared here">; def err_multiversion_required_in_redecl : Error< "function declaration is missing %select{'target'|'cpu_specific' or " "'cpu_dispatch'}0 attribute in a multiversioned function">; def note_multiversioning_caused_here : Note< "function multiversioning caused by this declaration">; def err_multiversion_after_used : Error< "function declaration cannot become a multiversioned function after first " "usage">; def err_bad_multiversion_option : Error< "function multiversioning doesn't support %select{feature|architecture}0 " "'%1'">; def err_multiversion_duplicate : Error< "multiversioned function redeclarations require identical target attributes">; def err_multiversion_noproto : Error< "multiversioned function must have a prototype">; def err_multiversion_no_other_attrs : Error< "attribute '%select{target|cpu_specific|cpu_dispatch}0' multiversioning cannot be combined" " with other attributes">; def err_multiversion_diff : Error< "multiversioned function declaration has a different %select{calling convention" "|return type|constexpr specification|inline specification|storage class|" "linkage}0">; def err_multiversion_doesnt_support : Error< "attribute '%select{target|cpu_specific|cpu_dispatch}0' multiversioned functions do not " "yet support %select{function templates|virtual functions|" "deduced return types|constructors|destructors|deleted functions|" "defaulted functions|constexpr functions}1">; def err_multiversion_not_allowed_on_main : Error< "'main' cannot be a multiversioned function">; def err_multiversion_not_supported : Error< "function multiversioning is not supported on the current target">; def err_multiversion_types_mixed : Error< "multiversioning attributes cannot be combined">; def err_cpu_dispatch_mismatch : Error< "'cpu_dispatch' function redeclared with different CPUs">; def err_cpu_specific_multiple_defs : Error< "multiple 'cpu_specific' functions cannot specify the same CPU: %0">; def warn_multiversion_duplicate_entries : Warning< "CPU list contains duplicate entries; attribute ignored">, InGroup; def warn_dispatch_body_ignored : Warning< "body of cpu_dispatch function will be ignored">, InGroup; // three-way comparison operator diagnostics def err_implied_comparison_category_type_not_found : Error< "cannot deduce return type of 'operator<=>' because type '%0' was not found; " "include ">; def err_spaceship_argument_narrowing : Error< "argument to 'operator<=>' " "%select{cannot be narrowed from type %1 to %2|" "evaluates to %1, which cannot be narrowed to type %2}0">; def err_std_compare_type_not_supported : Error< "standard library implementation of %0 is not supported; " "%select{member '%2' does not have expected form|" "member '%2' is missing|" "the type is not trivially copyable|" "the type does not have the expected form}1">; } // end of sema component. Index: vendor/clang/dist-release_70/lib/CodeGen/CodeGenModule.cpp =================================================================== --- vendor/clang/dist-release_70/lib/CodeGen/CodeGenModule.cpp (revision 341366) +++ vendor/clang/dist-release_70/lib/CodeGen/CodeGenModule.cpp (revision 341367) @@ -1,5249 +1,5247 @@ //===--- CodeGenModule.cpp - Emit LLVM Code from ASTs for a Module --------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This coordinates the per-module state used while generating code. // //===----------------------------------------------------------------------===// #include "CodeGenModule.h" #include "CGBlocks.h" #include "CGCUDARuntime.h" #include "CGCXXABI.h" #include "CGCall.h" #include "CGDebugInfo.h" #include "CGObjCRuntime.h" #include "CGOpenCLRuntime.h" #include "CGOpenMPRuntime.h" #include "CGOpenMPRuntimeNVPTX.h" #include "CodeGenFunction.h" #include "CodeGenPGO.h" #include "ConstantEmitter.h" #include "CoverageMappingGen.h" #include "TargetInfo.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Mangle.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" #include "clang/CodeGen/ConstantInitBuilder.h" #include "clang/Frontend/CodeGenOptions.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/Triple.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MD5.h" using namespace clang; using namespace CodeGen; static llvm::cl::opt LimitedCoverage( "limited-coverage-experimental", llvm::cl::ZeroOrMore, llvm::cl::Hidden, llvm::cl::desc("Emit limited coverage mapping information (experimental)"), llvm::cl::init(false)); static const char AnnotationSection[] = "llvm.metadata"; static CGCXXABI *createCXXABI(CodeGenModule &CGM) { switch (CGM.getTarget().getCXXABI().getKind()) { case TargetCXXABI::GenericAArch64: case TargetCXXABI::GenericARM: case TargetCXXABI::iOS: case TargetCXXABI::iOS64: case TargetCXXABI::WatchOS: case TargetCXXABI::GenericMIPS: case TargetCXXABI::GenericItanium: case TargetCXXABI::WebAssembly: return CreateItaniumCXXABI(CGM); case TargetCXXABI::Microsoft: return CreateMicrosoftCXXABI(CGM); } llvm_unreachable("invalid C++ ABI kind"); } CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO, const PreprocessorOptions &PPO, const CodeGenOptions &CGO, llvm::Module &M, DiagnosticsEngine &diags, CoverageSourceInfo *CoverageInfo) : Context(C), LangOpts(C.getLangOpts()), HeaderSearchOpts(HSO), PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags), Target(C.getTargetInfo()), ABI(createCXXABI(*this)), VMContext(M.getContext()), Types(*this), VTables(*this), SanitizerMD(new SanitizerMetadata(*this)) { // Initialize the type cache. llvm::LLVMContext &LLVMContext = M.getContext(); VoidTy = llvm::Type::getVoidTy(LLVMContext); Int8Ty = llvm::Type::getInt8Ty(LLVMContext); Int16Ty = llvm::Type::getInt16Ty(LLVMContext); Int32Ty = llvm::Type::getInt32Ty(LLVMContext); Int64Ty = llvm::Type::getInt64Ty(LLVMContext); HalfTy = llvm::Type::getHalfTy(LLVMContext); FloatTy = llvm::Type::getFloatTy(LLVMContext); DoubleTy = llvm::Type::getDoubleTy(LLVMContext); PointerWidthInBits = C.getTargetInfo().getPointerWidth(0); PointerAlignInBytes = C.toCharUnitsFromBits(C.getTargetInfo().getPointerAlign(0)).getQuantity(); SizeSizeInBytes = C.toCharUnitsFromBits(C.getTargetInfo().getMaxPointerWidth()).getQuantity(); IntAlignInBytes = C.toCharUnitsFromBits(C.getTargetInfo().getIntAlign()).getQuantity(); IntTy = llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getIntWidth()); IntPtrTy = llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getMaxPointerWidth()); Int8PtrTy = Int8Ty->getPointerTo(0); Int8PtrPtrTy = Int8PtrTy->getPointerTo(0); AllocaInt8PtrTy = Int8Ty->getPointerTo( M.getDataLayout().getAllocaAddrSpace()); ASTAllocaAddressSpace = getTargetCodeGenInfo().getASTAllocaAddressSpace(); RuntimeCC = getTargetCodeGenInfo().getABIInfo().getRuntimeCC(); if (LangOpts.ObjC1) createObjCRuntime(); if (LangOpts.OpenCL) createOpenCLRuntime(); if (LangOpts.OpenMP) createOpenMPRuntime(); if (LangOpts.CUDA) createCUDARuntime(); // Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0. if (LangOpts.Sanitize.has(SanitizerKind::Thread) || (!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0)) TBAA.reset(new CodeGenTBAA(Context, TheModule, CodeGenOpts, getLangOpts(), getCXXABI().getMangleContext())); // If debug info or coverage generation is enabled, create the CGDebugInfo // object. if (CodeGenOpts.getDebugInfo() != codegenoptions::NoDebugInfo || CodeGenOpts.EmitGcovArcs || CodeGenOpts.EmitGcovNotes) DebugInfo.reset(new CGDebugInfo(*this)); Block.GlobalUniqueCount = 0; if (C.getLangOpts().ObjC1) ObjCData.reset(new ObjCEntrypoints()); if (CodeGenOpts.hasProfileClangUse()) { auto ReaderOrErr = llvm::IndexedInstrProfReader::create( CodeGenOpts.ProfileInstrumentUsePath); if (auto E = ReaderOrErr.takeError()) { unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "Could not read profile %0: %1"); llvm::handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EI) { getDiags().Report(DiagID) << CodeGenOpts.ProfileInstrumentUsePath << EI.message(); }); } else PGOReader = std::move(ReaderOrErr.get()); } // If coverage mapping generation is enabled, create the // CoverageMappingModuleGen object. if (CodeGenOpts.CoverageMapping) CoverageMapping.reset(new CoverageMappingModuleGen(*this, *CoverageInfo)); } CodeGenModule::~CodeGenModule() {} void CodeGenModule::createObjCRuntime() { // This is just isGNUFamily(), but we want to force implementors of // new ABIs to decide how best to do this. switch (LangOpts.ObjCRuntime.getKind()) { case ObjCRuntime::GNUstep: case ObjCRuntime::GCC: case ObjCRuntime::ObjFW: ObjCRuntime.reset(CreateGNUObjCRuntime(*this)); return; case ObjCRuntime::FragileMacOSX: case ObjCRuntime::MacOSX: case ObjCRuntime::iOS: case ObjCRuntime::WatchOS: ObjCRuntime.reset(CreateMacObjCRuntime(*this)); return; } llvm_unreachable("bad runtime kind"); } void CodeGenModule::createOpenCLRuntime() { OpenCLRuntime.reset(new CGOpenCLRuntime(*this)); } void CodeGenModule::createOpenMPRuntime() { // Select a specialized code generation class based on the target, if any. // If it does not exist use the default implementation. switch (getTriple().getArch()) { case llvm::Triple::nvptx: case llvm::Triple::nvptx64: assert(getLangOpts().OpenMPIsDevice && "OpenMP NVPTX is only prepared to deal with device code."); OpenMPRuntime.reset(new CGOpenMPRuntimeNVPTX(*this)); break; default: if (LangOpts.OpenMPSimd) OpenMPRuntime.reset(new CGOpenMPSIMDRuntime(*this)); else OpenMPRuntime.reset(new CGOpenMPRuntime(*this)); break; } } void CodeGenModule::createCUDARuntime() { CUDARuntime.reset(CreateNVCUDARuntime(*this)); } void CodeGenModule::addReplacement(StringRef Name, llvm::Constant *C) { Replacements[Name] = C; } void CodeGenModule::applyReplacements() { for (auto &I : Replacements) { StringRef MangledName = I.first(); llvm::Constant *Replacement = I.second; llvm::GlobalValue *Entry = GetGlobalValue(MangledName); if (!Entry) continue; auto *OldF = cast(Entry); auto *NewF = dyn_cast(Replacement); if (!NewF) { if (auto *Alias = dyn_cast(Replacement)) { NewF = dyn_cast(Alias->getAliasee()); } else { auto *CE = cast(Replacement); assert(CE->getOpcode() == llvm::Instruction::BitCast || CE->getOpcode() == llvm::Instruction::GetElementPtr); NewF = dyn_cast(CE->getOperand(0)); } } // Replace old with new, but keep the old order. OldF->replaceAllUsesWith(Replacement); if (NewF) { NewF->removeFromParent(); OldF->getParent()->getFunctionList().insertAfter(OldF->getIterator(), NewF); } OldF->eraseFromParent(); } } void CodeGenModule::addGlobalValReplacement(llvm::GlobalValue *GV, llvm::Constant *C) { GlobalValReplacements.push_back(std::make_pair(GV, C)); } void CodeGenModule::applyGlobalValReplacements() { for (auto &I : GlobalValReplacements) { llvm::GlobalValue *GV = I.first; llvm::Constant *C = I.second; GV->replaceAllUsesWith(C); GV->eraseFromParent(); } } // This is only used in aliases that we created and we know they have a // linear structure. static const llvm::GlobalObject *getAliasedGlobal( const llvm::GlobalIndirectSymbol &GIS) { llvm::SmallPtrSet Visited; const llvm::Constant *C = &GIS; for (;;) { C = C->stripPointerCasts(); if (auto *GO = dyn_cast(C)) return GO; // stripPointerCasts will not walk over weak aliases. auto *GIS2 = dyn_cast(C); if (!GIS2) return nullptr; if (!Visited.insert(GIS2).second) return nullptr; C = GIS2->getIndirectSymbol(); } } void CodeGenModule::checkAliases() { // Check if the constructed aliases are well formed. It is really unfortunate // that we have to do this in CodeGen, but we only construct mangled names // and aliases during codegen. bool Error = false; DiagnosticsEngine &Diags = getDiags(); for (const GlobalDecl &GD : Aliases) { const auto *D = cast(GD.getDecl()); SourceLocation Location; bool IsIFunc = D->hasAttr(); if (const Attr *A = D->getDefiningAttr()) Location = A->getLocation(); else llvm_unreachable("Not an alias or ifunc?"); StringRef MangledName = getMangledName(GD); llvm::GlobalValue *Entry = GetGlobalValue(MangledName); auto *Alias = cast(Entry); const llvm::GlobalValue *GV = getAliasedGlobal(*Alias); if (!GV) { Error = true; Diags.Report(Location, diag::err_cyclic_alias) << IsIFunc; } else if (GV->isDeclaration()) { Error = true; Diags.Report(Location, diag::err_alias_to_undefined) << IsIFunc << IsIFunc; } else if (IsIFunc) { // Check resolver function type. llvm::FunctionType *FTy = dyn_cast( GV->getType()->getPointerElementType()); assert(FTy); if (!FTy->getReturnType()->isPointerTy()) Diags.Report(Location, diag::err_ifunc_resolver_return); - if (FTy->getNumParams()) - Diags.Report(Location, diag::err_ifunc_resolver_params); } llvm::Constant *Aliasee = Alias->getIndirectSymbol(); llvm::GlobalValue *AliaseeGV; if (auto CE = dyn_cast(Aliasee)) AliaseeGV = cast(CE->getOperand(0)); else AliaseeGV = cast(Aliasee); if (const SectionAttr *SA = D->getAttr()) { StringRef AliasSection = SA->getName(); if (AliasSection != AliaseeGV->getSection()) Diags.Report(SA->getLocation(), diag::warn_alias_with_section) << AliasSection << IsIFunc << IsIFunc; } // We have to handle alias to weak aliases in here. LLVM itself disallows // this since the object semantics would not match the IL one. For // compatibility with gcc we implement it by just pointing the alias // to its aliasee's aliasee. We also warn, since the user is probably // expecting the link to be weak. if (auto GA = dyn_cast(AliaseeGV)) { if (GA->isInterposable()) { Diags.Report(Location, diag::warn_alias_to_weak_alias) << GV->getName() << GA->getName() << IsIFunc; Aliasee = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast( GA->getIndirectSymbol(), Alias->getType()); Alias->setIndirectSymbol(Aliasee); } } } if (!Error) return; for (const GlobalDecl &GD : Aliases) { StringRef MangledName = getMangledName(GD); llvm::GlobalValue *Entry = GetGlobalValue(MangledName); auto *Alias = dyn_cast(Entry); Alias->replaceAllUsesWith(llvm::UndefValue::get(Alias->getType())); Alias->eraseFromParent(); } } void CodeGenModule::clear() { DeferredDeclsToEmit.clear(); if (OpenMPRuntime) OpenMPRuntime->clear(); } void InstrProfStats::reportDiagnostics(DiagnosticsEngine &Diags, StringRef MainFile) { if (!hasDiagnostics()) return; if (VisitedInMainFile > 0 && VisitedInMainFile == MissingInMainFile) { if (MainFile.empty()) MainFile = ""; Diags.Report(diag::warn_profile_data_unprofiled) << MainFile; } else { if (Mismatched > 0) Diags.Report(diag::warn_profile_data_out_of_date) << Visited << Mismatched; if (Missing > 0) Diags.Report(diag::warn_profile_data_missing) << Visited << Missing; } } void CodeGenModule::Release() { EmitDeferred(); EmitVTablesOpportunistically(); applyGlobalValReplacements(); applyReplacements(); checkAliases(); emitMultiVersionFunctions(); EmitCXXGlobalInitFunc(); EmitCXXGlobalDtorFunc(); registerGlobalDtorsWithAtExit(); EmitCXXThreadLocalInitFunc(); if (ObjCRuntime) if (llvm::Function *ObjCInitFunction = ObjCRuntime->ModuleInitFunction()) AddGlobalCtor(ObjCInitFunction); if (Context.getLangOpts().CUDA && !Context.getLangOpts().CUDAIsDevice && CUDARuntime) { if (llvm::Function *CudaCtorFunction = CUDARuntime->makeModuleCtorFunction()) AddGlobalCtor(CudaCtorFunction); } if (OpenMPRuntime) { if (llvm::Function *OpenMPRegistrationFunction = OpenMPRuntime->emitRegistrationFunction()) { auto ComdatKey = OpenMPRegistrationFunction->hasComdat() ? OpenMPRegistrationFunction : nullptr; AddGlobalCtor(OpenMPRegistrationFunction, 0, ComdatKey); } OpenMPRuntime->clear(); } if (PGOReader) { getModule().setProfileSummary(PGOReader->getSummary().getMD(VMContext)); if (PGOStats.hasDiagnostics()) PGOStats.reportDiagnostics(getDiags(), getCodeGenOpts().MainFileName); } EmitCtorList(GlobalCtors, "llvm.global_ctors"); EmitCtorList(GlobalDtors, "llvm.global_dtors"); EmitGlobalAnnotations(); EmitStaticExternCAliases(); EmitDeferredUnusedCoverageMappings(); if (CoverageMapping) CoverageMapping->emit(); if (CodeGenOpts.SanitizeCfiCrossDso) { CodeGenFunction(*this).EmitCfiCheckFail(); CodeGenFunction(*this).EmitCfiCheckStub(); } emitAtAvailableLinkGuard(); emitLLVMUsed(); if (SanStats) SanStats->finish(); if (CodeGenOpts.Autolink && (Context.getLangOpts().Modules || !LinkerOptionsMetadata.empty())) { EmitModuleLinkOptions(); } // Record mregparm value now so it is visible through rest of codegen. if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) getModule().addModuleFlag(llvm::Module::Error, "NumRegisterParameters", CodeGenOpts.NumRegisterParameters); if (CodeGenOpts.DwarfVersion) { // We actually want the latest version when there are conflicts. // We can change from Warning to Latest if such mode is supported. getModule().addModuleFlag(llvm::Module::Warning, "Dwarf Version", CodeGenOpts.DwarfVersion); } if (CodeGenOpts.EmitCodeView) { // Indicate that we want CodeView in the metadata. getModule().addModuleFlag(llvm::Module::Warning, "CodeView", 1); } if (CodeGenOpts.ControlFlowGuard) { // We want function ID tables for Control Flow Guard. getModule().addModuleFlag(llvm::Module::Warning, "cfguard", 1); } if (CodeGenOpts.OptimizationLevel > 0 && CodeGenOpts.StrictVTablePointers) { // We don't support LTO with 2 with different StrictVTablePointers // FIXME: we could support it by stripping all the information introduced // by StrictVTablePointers. getModule().addModuleFlag(llvm::Module::Error, "StrictVTablePointers",1); llvm::Metadata *Ops[2] = { llvm::MDString::get(VMContext, "StrictVTablePointers"), llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( llvm::Type::getInt32Ty(VMContext), 1))}; getModule().addModuleFlag(llvm::Module::Require, "StrictVTablePointersRequirement", llvm::MDNode::get(VMContext, Ops)); } if (DebugInfo) // We support a single version in the linked module. The LLVM // parser will drop debug info with a different version number // (and warn about it, too). getModule().addModuleFlag(llvm::Module::Warning, "Debug Info Version", llvm::DEBUG_METADATA_VERSION); // We need to record the widths of enums and wchar_t, so that we can generate // the correct build attributes in the ARM backend. wchar_size is also used by // TargetLibraryInfo. uint64_t WCharWidth = Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity(); getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth); llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch(); if ( Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb || Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb) { // The minimum width of an enum in bytes uint64_t EnumWidth = Context.getLangOpts().ShortEnums ? 1 : 4; getModule().addModuleFlag(llvm::Module::Error, "min_enum_size", EnumWidth); } if (CodeGenOpts.SanitizeCfiCrossDso) { // Indicate that we want cross-DSO control flow integrity checks. getModule().addModuleFlag(llvm::Module::Override, "Cross-DSO CFI", 1); } if (CodeGenOpts.CFProtectionReturn && Target.checkCFProtectionReturnSupported(getDiags())) { // Indicate that we want to instrument return control flow protection. getModule().addModuleFlag(llvm::Module::Override, "cf-protection-return", 1); } if (CodeGenOpts.CFProtectionBranch && Target.checkCFProtectionBranchSupported(getDiags())) { // Indicate that we want to instrument branch control flow protection. getModule().addModuleFlag(llvm::Module::Override, "cf-protection-branch", 1); } if (LangOpts.CUDAIsDevice && getTriple().isNVPTX()) { // Indicate whether __nvvm_reflect should be configured to flush denormal // floating point values to 0. (This corresponds to its "__CUDA_FTZ" // property.) getModule().addModuleFlag(llvm::Module::Override, "nvvm-reflect-ftz", CodeGenOpts.FlushDenorm ? 1 : 0); } // Emit OpenCL specific module metadata: OpenCL/SPIR version. if (LangOpts.OpenCL) { EmitOpenCLMetadata(); // Emit SPIR version. if (getTriple().getArch() == llvm::Triple::spir || getTriple().getArch() == llvm::Triple::spir64) { // SPIR v2.0 s2.12 - The SPIR version used by the module is stored in the // opencl.spir.version named metadata. llvm::Metadata *SPIRVerElts[] = { llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( Int32Ty, LangOpts.OpenCLVersion / 100)), llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( Int32Ty, (LangOpts.OpenCLVersion / 100 > 1) ? 0 : 2))}; llvm::NamedMDNode *SPIRVerMD = TheModule.getOrInsertNamedMetadata("opencl.spir.version"); llvm::LLVMContext &Ctx = TheModule.getContext(); SPIRVerMD->addOperand(llvm::MDNode::get(Ctx, SPIRVerElts)); } } if (uint32_t PLevel = Context.getLangOpts().PICLevel) { assert(PLevel < 3 && "Invalid PIC Level"); getModule().setPICLevel(static_cast(PLevel)); if (Context.getLangOpts().PIE) getModule().setPIELevel(static_cast(PLevel)); } if (CodeGenOpts.NoPLT) getModule().setRtLibUseGOT(); SimplifyPersonality(); if (getCodeGenOpts().EmitDeclMetadata) EmitDeclMetadata(); if (getCodeGenOpts().EmitGcovArcs || getCodeGenOpts().EmitGcovNotes) EmitCoverageFile(); if (DebugInfo) DebugInfo->finalize(); if (getCodeGenOpts().EmitVersionIdentMetadata) EmitVersionIdentMetadata(); EmitTargetMetadata(); } void CodeGenModule::EmitOpenCLMetadata() { // SPIR v2.0 s2.13 - The OpenCL version used by the module is stored in the // opencl.ocl.version named metadata node. llvm::Metadata *OCLVerElts[] = { llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( Int32Ty, LangOpts.OpenCLVersion / 100)), llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( Int32Ty, (LangOpts.OpenCLVersion % 100) / 10))}; llvm::NamedMDNode *OCLVerMD = TheModule.getOrInsertNamedMetadata("opencl.ocl.version"); llvm::LLVMContext &Ctx = TheModule.getContext(); OCLVerMD->addOperand(llvm::MDNode::get(Ctx, OCLVerElts)); } void CodeGenModule::UpdateCompletedType(const TagDecl *TD) { // Make sure that this type is translated. Types.UpdateCompletedType(TD); } void CodeGenModule::RefreshTypeCacheForClass(const CXXRecordDecl *RD) { // Make sure that this type is translated. Types.RefreshTypeCacheForClass(RD); } llvm::MDNode *CodeGenModule::getTBAATypeInfo(QualType QTy) { if (!TBAA) return nullptr; return TBAA->getTypeInfo(QTy); } TBAAAccessInfo CodeGenModule::getTBAAAccessInfo(QualType AccessType) { if (!TBAA) return TBAAAccessInfo(); return TBAA->getAccessInfo(AccessType); } TBAAAccessInfo CodeGenModule::getTBAAVTablePtrAccessInfo(llvm::Type *VTablePtrType) { if (!TBAA) return TBAAAccessInfo(); return TBAA->getVTablePtrAccessInfo(VTablePtrType); } llvm::MDNode *CodeGenModule::getTBAAStructInfo(QualType QTy) { if (!TBAA) return nullptr; return TBAA->getTBAAStructInfo(QTy); } llvm::MDNode *CodeGenModule::getTBAABaseTypeInfo(QualType QTy) { if (!TBAA) return nullptr; return TBAA->getBaseTypeInfo(QTy); } llvm::MDNode *CodeGenModule::getTBAAAccessTagInfo(TBAAAccessInfo Info) { if (!TBAA) return nullptr; return TBAA->getAccessTagInfo(Info); } TBAAAccessInfo CodeGenModule::mergeTBAAInfoForCast(TBAAAccessInfo SourceInfo, TBAAAccessInfo TargetInfo) { if (!TBAA) return TBAAAccessInfo(); return TBAA->mergeTBAAInfoForCast(SourceInfo, TargetInfo); } TBAAAccessInfo CodeGenModule::mergeTBAAInfoForConditionalOperator(TBAAAccessInfo InfoA, TBAAAccessInfo InfoB) { if (!TBAA) return TBAAAccessInfo(); return TBAA->mergeTBAAInfoForConditionalOperator(InfoA, InfoB); } TBAAAccessInfo CodeGenModule::mergeTBAAInfoForMemoryTransfer(TBAAAccessInfo DestInfo, TBAAAccessInfo SrcInfo) { if (!TBAA) return TBAAAccessInfo(); return TBAA->mergeTBAAInfoForConditionalOperator(DestInfo, SrcInfo); } void CodeGenModule::DecorateInstructionWithTBAA(llvm::Instruction *Inst, TBAAAccessInfo TBAAInfo) { if (llvm::MDNode *Tag = getTBAAAccessTagInfo(TBAAInfo)) Inst->setMetadata(llvm::LLVMContext::MD_tbaa, Tag); } void CodeGenModule::DecorateInstructionWithInvariantGroup( llvm::Instruction *I, const CXXRecordDecl *RD) { I->setMetadata(llvm::LLVMContext::MD_invariant_group, llvm::MDNode::get(getLLVMContext(), {})); } void CodeGenModule::Error(SourceLocation loc, StringRef message) { unsigned diagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, "%0"); getDiags().Report(Context.getFullLoc(loc), diagID) << message; } /// ErrorUnsupported - Print out an error that codegen doesn't support the /// specified stmt yet. void CodeGenModule::ErrorUnsupported(const Stmt *S, const char *Type) { unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, "cannot compile this %0 yet"); std::string Msg = Type; getDiags().Report(Context.getFullLoc(S->getLocStart()), DiagID) << Msg << S->getSourceRange(); } /// ErrorUnsupported - Print out an error that codegen doesn't support the /// specified decl yet. void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type) { unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, "cannot compile this %0 yet"); std::string Msg = Type; getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID) << Msg; } llvm::ConstantInt *CodeGenModule::getSize(CharUnits size) { return llvm::ConstantInt::get(SizeTy, size.getQuantity()); } void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const { if (GV->hasDLLImportStorageClass()) return; // Internal definitions always have default visibility. if (GV->hasLocalLinkage()) { GV->setVisibility(llvm::GlobalValue::DefaultVisibility); return; } if (!D) return; // Set visibility for definitions. LinkageInfo LV = D->getLinkageAndVisibility(); if (LV.isVisibilityExplicit() || !GV->isDeclarationForLinker()) GV->setVisibility(GetLLVMVisibility(LV.getVisibility())); } static bool shouldAssumeDSOLocal(const CodeGenModule &CGM, llvm::GlobalValue *GV) { if (GV->hasLocalLinkage()) return true; if (!GV->hasDefaultVisibility() && !GV->hasExternalWeakLinkage()) return true; // DLLImport explicitly marks the GV as external. if (GV->hasDLLImportStorageClass()) return false; const llvm::Triple &TT = CGM.getTriple(); // Every other GV is local on COFF. // Make an exception for windows OS in the triple: Some firmware builds use // *-win32-macho triples. This (accidentally?) produced windows relocations // without GOT tables in older clang versions; Keep this behaviour. // FIXME: even thread local variables? if (TT.isOSBinFormatCOFF() || (TT.isOSWindows() && TT.isOSBinFormatMachO())) return true; // Only handle COFF and ELF for now. if (!TT.isOSBinFormatELF()) return false; // If this is not an executable, don't assume anything is local. const auto &CGOpts = CGM.getCodeGenOpts(); llvm::Reloc::Model RM = CGOpts.RelocationModel; const auto &LOpts = CGM.getLangOpts(); if (RM != llvm::Reloc::Static && !LOpts.PIE) return false; // A definition cannot be preempted from an executable. if (!GV->isDeclarationForLinker()) return true; // Most PIC code sequences that assume that a symbol is local cannot produce a // 0 if it turns out the symbol is undefined. While this is ABI and relocation // depended, it seems worth it to handle it here. if (RM == llvm::Reloc::PIC_ && GV->hasExternalWeakLinkage()) return false; // PPC has no copy relocations and cannot use a plt entry as a symbol address. llvm::Triple::ArchType Arch = TT.getArch(); if (Arch == llvm::Triple::ppc || Arch == llvm::Triple::ppc64 || Arch == llvm::Triple::ppc64le) return false; // If we can use copy relocations we can assume it is local. if (auto *Var = dyn_cast(GV)) if (!Var->isThreadLocal() && (RM == llvm::Reloc::Static || CGOpts.PIECopyRelocations)) return true; // If we can use a plt entry as the symbol address we can assume it // is local. // FIXME: This should work for PIE, but the gold linker doesn't support it. if (isa(GV) && !CGOpts.NoPLT && RM == llvm::Reloc::Static) return true; // Otherwise don't assue it is local. return false; } void CodeGenModule::setDSOLocal(llvm::GlobalValue *GV) const { GV->setDSOLocal(shouldAssumeDSOLocal(*this, GV)); } void CodeGenModule::setDLLImportDLLExport(llvm::GlobalValue *GV, GlobalDecl GD) const { const auto *D = dyn_cast(GD.getDecl()); // C++ destructors have a few C++ ABI specific special cases. if (const auto *Dtor = dyn_cast_or_null(D)) { getCXXABI().setCXXDestructorDLLStorage(GV, Dtor, GD.getDtorType()); return; } setDLLImportDLLExport(GV, D); } void CodeGenModule::setDLLImportDLLExport(llvm::GlobalValue *GV, const NamedDecl *D) const { if (D && D->isExternallyVisible()) { if (D->hasAttr()) GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass); else if (D->hasAttr() && !GV->isDeclarationForLinker()) GV->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass); } } void CodeGenModule::setGVProperties(llvm::GlobalValue *GV, GlobalDecl GD) const { setDLLImportDLLExport(GV, GD); setGlobalVisibilityAndLocal(GV, dyn_cast(GD.getDecl())); } void CodeGenModule::setGVProperties(llvm::GlobalValue *GV, const NamedDecl *D) const { setDLLImportDLLExport(GV, D); setGlobalVisibilityAndLocal(GV, D); } void CodeGenModule::setGlobalVisibilityAndLocal(llvm::GlobalValue *GV, const NamedDecl *D) const { setGlobalVisibility(GV, D); setDSOLocal(GV); } static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel(StringRef S) { return llvm::StringSwitch(S) .Case("global-dynamic", llvm::GlobalVariable::GeneralDynamicTLSModel) .Case("local-dynamic", llvm::GlobalVariable::LocalDynamicTLSModel) .Case("initial-exec", llvm::GlobalVariable::InitialExecTLSModel) .Case("local-exec", llvm::GlobalVariable::LocalExecTLSModel); } static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel( CodeGenOptions::TLSModel M) { switch (M) { case CodeGenOptions::GeneralDynamicTLSModel: return llvm::GlobalVariable::GeneralDynamicTLSModel; case CodeGenOptions::LocalDynamicTLSModel: return llvm::GlobalVariable::LocalDynamicTLSModel; case CodeGenOptions::InitialExecTLSModel: return llvm::GlobalVariable::InitialExecTLSModel; case CodeGenOptions::LocalExecTLSModel: return llvm::GlobalVariable::LocalExecTLSModel; } llvm_unreachable("Invalid TLS model!"); } void CodeGenModule::setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const { assert(D.getTLSKind() && "setting TLS mode on non-TLS var!"); llvm::GlobalValue::ThreadLocalMode TLM; TLM = GetLLVMTLSModel(CodeGenOpts.getDefaultTLSModel()); // Override the TLS model if it is explicitly specified. if (const TLSModelAttr *Attr = D.getAttr()) { TLM = GetLLVMTLSModel(Attr->getModel()); } GV->setThreadLocalMode(TLM); } static std::string getCPUSpecificMangling(const CodeGenModule &CGM, StringRef Name) { const TargetInfo &Target = CGM.getTarget(); return (Twine('.') + Twine(Target.CPUSpecificManglingCharacter(Name))).str(); } static void AppendCPUSpecificCPUDispatchMangling(const CodeGenModule &CGM, const CPUSpecificAttr *Attr, raw_ostream &Out) { // cpu_specific gets the current name, dispatch gets the resolver. if (Attr) Out << getCPUSpecificMangling(CGM, Attr->getCurCPUName()->getName()); else Out << ".resolver"; } static void AppendTargetMangling(const CodeGenModule &CGM, const TargetAttr *Attr, raw_ostream &Out) { if (Attr->isDefaultVersion()) return; Out << '.'; const TargetInfo &Target = CGM.getTarget(); TargetAttr::ParsedTargetAttr Info = Attr->parse([&Target](StringRef LHS, StringRef RHS) { // Multiversioning doesn't allow "no-${feature}", so we can // only have "+" prefixes here. assert(LHS.startswith("+") && RHS.startswith("+") && "Features should always have a prefix."); return Target.multiVersionSortPriority(LHS.substr(1)) > Target.multiVersionSortPriority(RHS.substr(1)); }); bool IsFirst = true; if (!Info.Architecture.empty()) { IsFirst = false; Out << "arch_" << Info.Architecture; } for (StringRef Feat : Info.Features) { if (!IsFirst) Out << '_'; IsFirst = false; Out << Feat.substr(1); } } static std::string getMangledNameImpl(const CodeGenModule &CGM, GlobalDecl GD, const NamedDecl *ND, bool OmitMultiVersionMangling = false) { SmallString<256> Buffer; llvm::raw_svector_ostream Out(Buffer); MangleContext &MC = CGM.getCXXABI().getMangleContext(); if (MC.shouldMangleDeclName(ND)) { llvm::raw_svector_ostream Out(Buffer); if (const auto *D = dyn_cast(ND)) MC.mangleCXXCtor(D, GD.getCtorType(), Out); else if (const auto *D = dyn_cast(ND)) MC.mangleCXXDtor(D, GD.getDtorType(), Out); else MC.mangleName(ND, Out); } else { IdentifierInfo *II = ND->getIdentifier(); assert(II && "Attempt to mangle unnamed decl."); const auto *FD = dyn_cast(ND); if (FD && FD->getType()->castAs()->getCallConv() == CC_X86RegCall) { llvm::raw_svector_ostream Out(Buffer); Out << "__regcall3__" << II->getName(); } else { Out << II->getName(); } } if (const auto *FD = dyn_cast(ND)) if (FD->isMultiVersion() && !OmitMultiVersionMangling) { if (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion()) AppendCPUSpecificCPUDispatchMangling( CGM, FD->getAttr(), Out); else AppendTargetMangling(CGM, FD->getAttr(), Out); } return Out.str(); } void CodeGenModule::UpdateMultiVersionNames(GlobalDecl GD, const FunctionDecl *FD) { if (!FD->isMultiVersion()) return; // Get the name of what this would be without the 'target' attribute. This // allows us to lookup the version that was emitted when this wasn't a // multiversion function. std::string NonTargetName = getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true); GlobalDecl OtherGD; if (lookupRepresentativeDecl(NonTargetName, OtherGD)) { assert(OtherGD.getCanonicalDecl() .getDecl() ->getAsFunction() ->isMultiVersion() && "Other GD should now be a multiversioned function"); // OtherFD is the version of this function that was mangled BEFORE // becoming a MultiVersion function. It potentially needs to be updated. const FunctionDecl *OtherFD = OtherGD.getCanonicalDecl().getDecl()->getAsFunction(); std::string OtherName = getMangledNameImpl(*this, OtherGD, OtherFD); // This is so that if the initial version was already the 'default' // version, we don't try to update it. if (OtherName != NonTargetName) { // Remove instead of erase, since others may have stored the StringRef // to this. const auto ExistingRecord = Manglings.find(NonTargetName); if (ExistingRecord != std::end(Manglings)) Manglings.remove(&(*ExistingRecord)); auto Result = Manglings.insert(std::make_pair(OtherName, OtherGD)); MangledDeclNames[OtherGD.getCanonicalDecl()] = Result.first->first(); if (llvm::GlobalValue *Entry = GetGlobalValue(NonTargetName)) Entry->setName(OtherName); } } } StringRef CodeGenModule::getMangledName(GlobalDecl GD) { GlobalDecl CanonicalGD = GD.getCanonicalDecl(); // Some ABIs don't have constructor variants. Make sure that base and // complete constructors get mangled the same. if (const auto *CD = dyn_cast(CanonicalGD.getDecl())) { if (!getTarget().getCXXABI().hasConstructorVariants()) { CXXCtorType OrigCtorType = GD.getCtorType(); assert(OrigCtorType == Ctor_Base || OrigCtorType == Ctor_Complete); if (OrigCtorType == Ctor_Base) CanonicalGD = GlobalDecl(CD, Ctor_Complete); } } const auto *FD = dyn_cast(GD.getDecl()); // Since CPUSpecific can require multiple emits per decl, store the manglings // separately. if (FD && (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion())) { const auto *SD = FD->getAttr(); std::pair SpecCanonicalGD{ CanonicalGD, SD ? SD->ActiveArgIndex : std::numeric_limits::max()}; auto FoundName = CPUSpecificMangledDeclNames.find(SpecCanonicalGD); if (FoundName != CPUSpecificMangledDeclNames.end()) return FoundName->second; auto Result = CPUSpecificManglings.insert( std::make_pair(getMangledNameImpl(*this, GD, FD), SpecCanonicalGD)); return CPUSpecificMangledDeclNames[SpecCanonicalGD] = Result.first->first(); } auto FoundName = MangledDeclNames.find(CanonicalGD); if (FoundName != MangledDeclNames.end()) return FoundName->second; // Keep the first result in the case of a mangling collision. const auto *ND = cast(GD.getDecl()); auto Result = Manglings.insert(std::make_pair(getMangledNameImpl(*this, GD, ND), GD)); return MangledDeclNames[CanonicalGD] = Result.first->first(); } StringRef CodeGenModule::getBlockMangledName(GlobalDecl GD, const BlockDecl *BD) { MangleContext &MangleCtx = getCXXABI().getMangleContext(); const Decl *D = GD.getDecl(); SmallString<256> Buffer; llvm::raw_svector_ostream Out(Buffer); if (!D) MangleCtx.mangleGlobalBlock(BD, dyn_cast_or_null(initializedGlobalDecl.getDecl()), Out); else if (const auto *CD = dyn_cast(D)) MangleCtx.mangleCtorBlock(CD, GD.getCtorType(), BD, Out); else if (const auto *DD = dyn_cast(D)) MangleCtx.mangleDtorBlock(DD, GD.getDtorType(), BD, Out); else MangleCtx.mangleBlock(cast(D), BD, Out); auto Result = Manglings.insert(std::make_pair(Out.str(), BD)); return Result.first->first(); } llvm::GlobalValue *CodeGenModule::GetGlobalValue(StringRef Name) { return getModule().getNamedValue(Name); } /// AddGlobalCtor - Add a function to the list that will be called before /// main() runs. void CodeGenModule::AddGlobalCtor(llvm::Function *Ctor, int Priority, llvm::Constant *AssociatedData) { // FIXME: Type coercion of void()* types. GlobalCtors.push_back(Structor(Priority, Ctor, AssociatedData)); } /// AddGlobalDtor - Add a function to the list that will be called /// when the module is unloaded. void CodeGenModule::AddGlobalDtor(llvm::Function *Dtor, int Priority) { if (CodeGenOpts.RegisterGlobalDtorsWithAtExit) { DtorsUsingAtExit[Priority].push_back(Dtor); return; } // FIXME: Type coercion of void()* types. GlobalDtors.push_back(Structor(Priority, Dtor, nullptr)); } void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) { if (Fns.empty()) return; // Ctor function type is void()*. llvm::FunctionType* CtorFTy = llvm::FunctionType::get(VoidTy, false); llvm::Type *CtorPFTy = llvm::PointerType::getUnqual(CtorFTy); // Get the type of a ctor entry, { i32, void ()*, i8* }. llvm::StructType *CtorStructTy = llvm::StructType::get( Int32Ty, llvm::PointerType::getUnqual(CtorFTy), VoidPtrTy); // Construct the constructor and destructor arrays. ConstantInitBuilder builder(*this); auto ctors = builder.beginArray(CtorStructTy); for (const auto &I : Fns) { auto ctor = ctors.beginStruct(CtorStructTy); ctor.addInt(Int32Ty, I.Priority); ctor.add(llvm::ConstantExpr::getBitCast(I.Initializer, CtorPFTy)); if (I.AssociatedData) ctor.add(llvm::ConstantExpr::getBitCast(I.AssociatedData, VoidPtrTy)); else ctor.addNullPointer(VoidPtrTy); ctor.finishAndAddTo(ctors); } auto list = ctors.finishAndCreateGlobal(GlobalName, getPointerAlign(), /*constant*/ false, llvm::GlobalValue::AppendingLinkage); // The LTO linker doesn't seem to like it when we set an alignment // on appending variables. Take it off as a workaround. list->setAlignment(0); Fns.clear(); } llvm::GlobalValue::LinkageTypes CodeGenModule::getFunctionLinkage(GlobalDecl GD) { const auto *D = cast(GD.getDecl()); GVALinkage Linkage = getContext().GetGVALinkageForFunction(D); if (const auto *Dtor = dyn_cast(D)) return getCXXABI().getCXXDestructorLinkage(Linkage, Dtor, GD.getDtorType()); if (isa(D) && cast(D)->isInheritingConstructor() && Context.getTargetInfo().getCXXABI().isMicrosoft()) { // Our approach to inheriting constructors is fundamentally different from // that used by the MS ABI, so keep our inheriting constructor thunks // internal rather than trying to pick an unambiguous mangling for them. return llvm::GlobalValue::InternalLinkage; } return getLLVMLinkageForDeclarator(D, Linkage, /*isConstantVariable=*/false); } llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) { llvm::MDString *MDS = dyn_cast(MD); if (!MDS) return nullptr; return llvm::ConstantInt::get(Int64Ty, llvm::MD5Hash(MDS->getString())); } void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D, const CGFunctionInfo &Info, llvm::Function *F) { unsigned CallingConv; llvm::AttributeList PAL; ConstructAttributeList(F->getName(), Info, D, PAL, CallingConv, false); F->setAttributes(PAL); F->setCallingConv(static_cast(CallingConv)); } /// Determines whether the language options require us to model /// unwind exceptions. We treat -fexceptions as mandating this /// except under the fragile ObjC ABI with only ObjC exceptions /// enabled. This means, for example, that C with -fexceptions /// enables this. static bool hasUnwindExceptions(const LangOptions &LangOpts) { // If exceptions are completely disabled, obviously this is false. if (!LangOpts.Exceptions) return false; // If C++ exceptions are enabled, this is true. if (LangOpts.CXXExceptions) return true; // If ObjC exceptions are enabled, this depends on the ABI. if (LangOpts.ObjCExceptions) { return LangOpts.ObjCRuntime.hasUnwindExceptions(); } return true; } static bool requiresMemberFunctionPointerTypeMetadata(CodeGenModule &CGM, const CXXMethodDecl *MD) { // Check that the type metadata can ever actually be used by a call. if (!CGM.getCodeGenOpts().LTOUnit || !CGM.HasHiddenLTOVisibility(MD->getParent())) return false; // Only functions whose address can be taken with a member function pointer // need this sort of type metadata. return !MD->isStatic() && !MD->isVirtual() && !isa(MD) && !isa(MD); } std::vector CodeGenModule::getMostBaseClasses(const CXXRecordDecl *RD) { llvm::SetVector MostBases; std::function CollectMostBases; CollectMostBases = [&](const CXXRecordDecl *RD) { if (RD->getNumBases() == 0) MostBases.insert(RD); for (const CXXBaseSpecifier &B : RD->bases()) CollectMostBases(B.getType()->getAsCXXRecordDecl()); }; CollectMostBases(RD); return MostBases.takeVector(); } void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F) { llvm::AttrBuilder B; if (CodeGenOpts.UnwindTables) B.addAttribute(llvm::Attribute::UWTable); if (!hasUnwindExceptions(LangOpts)) B.addAttribute(llvm::Attribute::NoUnwind); if (!D || !D->hasAttr()) { if (LangOpts.getStackProtector() == LangOptions::SSPOn) B.addAttribute(llvm::Attribute::StackProtect); else if (LangOpts.getStackProtector() == LangOptions::SSPStrong) B.addAttribute(llvm::Attribute::StackProtectStrong); else if (LangOpts.getStackProtector() == LangOptions::SSPReq) B.addAttribute(llvm::Attribute::StackProtectReq); } if (!D) { // If we don't have a declaration to control inlining, the function isn't // explicitly marked as alwaysinline for semantic reasons, and inlining is // disabled, mark the function as noinline. if (!F->hasFnAttribute(llvm::Attribute::AlwaysInline) && CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) B.addAttribute(llvm::Attribute::NoInline); F->addAttributes(llvm::AttributeList::FunctionIndex, B); return; } // Track whether we need to add the optnone LLVM attribute, // starting with the default for this optimization level. bool ShouldAddOptNone = !CodeGenOpts.DisableO0ImplyOptNone && CodeGenOpts.OptimizationLevel == 0; // We can't add optnone in the following cases, it won't pass the verifier. ShouldAddOptNone &= !D->hasAttr(); ShouldAddOptNone &= !F->hasFnAttribute(llvm::Attribute::AlwaysInline); ShouldAddOptNone &= !D->hasAttr(); if (ShouldAddOptNone || D->hasAttr()) { B.addAttribute(llvm::Attribute::OptimizeNone); // OptimizeNone implies noinline; we should not be inlining such functions. B.addAttribute(llvm::Attribute::NoInline); assert(!F->hasFnAttribute(llvm::Attribute::AlwaysInline) && "OptimizeNone and AlwaysInline on same function!"); // We still need to handle naked functions even though optnone subsumes // much of their semantics. if (D->hasAttr()) B.addAttribute(llvm::Attribute::Naked); // OptimizeNone wins over OptimizeForSize and MinSize. F->removeFnAttr(llvm::Attribute::OptimizeForSize); F->removeFnAttr(llvm::Attribute::MinSize); } else if (D->hasAttr()) { // Naked implies noinline: we should not be inlining such functions. B.addAttribute(llvm::Attribute::Naked); B.addAttribute(llvm::Attribute::NoInline); } else if (D->hasAttr()) { B.addAttribute(llvm::Attribute::NoDuplicate); } else if (D->hasAttr()) { B.addAttribute(llvm::Attribute::NoInline); } else if (D->hasAttr() && !F->hasFnAttribute(llvm::Attribute::NoInline)) { // (noinline wins over always_inline, and we can't specify both in IR) B.addAttribute(llvm::Attribute::AlwaysInline); } else if (CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) { // If we're not inlining, then force everything that isn't always_inline to // carry an explicit noinline attribute. if (!F->hasFnAttribute(llvm::Attribute::AlwaysInline)) B.addAttribute(llvm::Attribute::NoInline); } else { // Otherwise, propagate the inline hint attribute and potentially use its // absence to mark things as noinline. if (auto *FD = dyn_cast(D)) { if (any_of(FD->redecls(), [&](const FunctionDecl *Redecl) { return Redecl->isInlineSpecified(); })) { B.addAttribute(llvm::Attribute::InlineHint); } else if (CodeGenOpts.getInlining() == CodeGenOptions::OnlyHintInlining && !FD->isInlined() && !F->hasFnAttribute(llvm::Attribute::AlwaysInline)) { B.addAttribute(llvm::Attribute::NoInline); } } } // Add other optimization related attributes if we are optimizing this // function. if (!D->hasAttr()) { if (D->hasAttr()) { if (!ShouldAddOptNone) B.addAttribute(llvm::Attribute::OptimizeForSize); B.addAttribute(llvm::Attribute::Cold); } if (D->hasAttr()) B.addAttribute(llvm::Attribute::MinSize); } F->addAttributes(llvm::AttributeList::FunctionIndex, B); unsigned alignment = D->getMaxAlignment() / Context.getCharWidth(); if (alignment) F->setAlignment(alignment); if (!D->hasAttr()) if (LangOpts.FunctionAlignment) F->setAlignment(1 << LangOpts.FunctionAlignment); // Some C++ ABIs require 2-byte alignment for member functions, in order to // reserve a bit for differentiating between virtual and non-virtual member // functions. If the current target's C++ ABI requires this and this is a // member function, set its alignment accordingly. if (getTarget().getCXXABI().areMemberFunctionsAligned()) { if (F->getAlignment() < 2 && isa(D)) F->setAlignment(2); } // In the cross-dso CFI mode, we want !type attributes on definitions only. if (CodeGenOpts.SanitizeCfiCrossDso) if (auto *FD = dyn_cast(D)) CreateFunctionTypeMetadataForIcall(FD, F); // Emit type metadata on member functions for member function pointer checks. // These are only ever necessary on definitions; we're guaranteed that the // definition will be present in the LTO unit as a result of LTO visibility. auto *MD = dyn_cast(D); if (MD && requiresMemberFunctionPointerTypeMetadata(*this, MD)) { for (const CXXRecordDecl *Base : getMostBaseClasses(MD->getParent())) { llvm::Metadata *Id = CreateMetadataIdentifierForType(Context.getMemberPointerType( MD->getType(), Context.getRecordType(Base).getTypePtr())); F->addTypeMetadata(0, Id); } } } void CodeGenModule::SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV) { const Decl *D = GD.getDecl(); if (dyn_cast_or_null(D)) setGVProperties(GV, GD); else GV->setVisibility(llvm::GlobalValue::DefaultVisibility); if (D && D->hasAttr()) addUsedGlobal(GV); } bool CodeGenModule::GetCPUAndFeaturesAttributes(const Decl *D, llvm::AttrBuilder &Attrs) { // Add target-cpu and target-features attributes to functions. If // we have a decl for the function and it has a target attribute then // parse that and add it to the feature set. StringRef TargetCPU = getTarget().getTargetOpts().CPU; std::vector Features; const auto *FD = dyn_cast_or_null(D); FD = FD ? FD->getMostRecentDecl() : FD; const auto *TD = FD ? FD->getAttr() : nullptr; const auto *SD = FD ? FD->getAttr() : nullptr; bool AddedAttr = false; if (TD || SD) { llvm::StringMap FeatureMap; getFunctionFeatureMap(FeatureMap, FD); // Produce the canonical string for this set of features. for (const llvm::StringMap::value_type &Entry : FeatureMap) Features.push_back((Entry.getValue() ? "+" : "-") + Entry.getKey().str()); // Now add the target-cpu and target-features to the function. // While we populated the feature map above, we still need to // get and parse the target attribute so we can get the cpu for // the function. if (TD) { TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse(); if (ParsedAttr.Architecture != "" && getTarget().isValidCPUName(ParsedAttr.Architecture)) TargetCPU = ParsedAttr.Architecture; } } else { // Otherwise just add the existing target cpu and target features to the // function. Features = getTarget().getTargetOpts().Features; } if (TargetCPU != "") { Attrs.addAttribute("target-cpu", TargetCPU); AddedAttr = true; } if (!Features.empty()) { llvm::sort(Features.begin(), Features.end()); Attrs.addAttribute("target-features", llvm::join(Features, ",")); AddedAttr = true; } return AddedAttr; } void CodeGenModule::setNonAliasAttributes(GlobalDecl GD, llvm::GlobalObject *GO) { const Decl *D = GD.getDecl(); SetCommonAttributes(GD, GO); if (D) { if (auto *GV = dyn_cast(GO)) { if (auto *SA = D->getAttr()) GV->addAttribute("bss-section", SA->getName()); if (auto *SA = D->getAttr()) GV->addAttribute("data-section", SA->getName()); if (auto *SA = D->getAttr()) GV->addAttribute("rodata-section", SA->getName()); } if (auto *F = dyn_cast(GO)) { if (auto *SA = D->getAttr()) if (!D->getAttr()) F->addFnAttr("implicit-section-name", SA->getName()); llvm::AttrBuilder Attrs; if (GetCPUAndFeaturesAttributes(D, Attrs)) { // We know that GetCPUAndFeaturesAttributes will always have the // newest set, since it has the newest possible FunctionDecl, so the // new ones should replace the old. F->removeFnAttr("target-cpu"); F->removeFnAttr("target-features"); F->addAttributes(llvm::AttributeList::FunctionIndex, Attrs); } } if (const auto *CSA = D->getAttr()) GO->setSection(CSA->getName()); else if (const auto *SA = D->getAttr()) GO->setSection(SA->getName()); } getTargetCodeGenInfo().setTargetAttributes(D, GO, *this); } void CodeGenModule::SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI) { const Decl *D = GD.getDecl(); SetLLVMFunctionAttributes(D, FI, F); SetLLVMFunctionAttributesForDefinition(D, F); F->setLinkage(llvm::Function::InternalLinkage); setNonAliasAttributes(GD, F); } static void setLinkageForGV(llvm::GlobalValue *GV, const NamedDecl *ND) { // Set linkage and visibility in case we never see a definition. LinkageInfo LV = ND->getLinkageAndVisibility(); // Don't set internal linkage on declarations. // "extern_weak" is overloaded in LLVM; we probably should have // separate linkage types for this. if (isExternallyVisible(LV.getLinkage()) && (ND->hasAttr() || ND->isWeakImported())) GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); } void CodeGenModule::CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD, llvm::Function *F) { // Only if we are checking indirect calls. if (!LangOpts.Sanitize.has(SanitizerKind::CFIICall)) return; // Non-static class methods are handled via vtable or member function pointer // checks elsewhere. if (isa(FD) && !cast(FD)->isStatic()) return; // Additionally, if building with cross-DSO support... if (CodeGenOpts.SanitizeCfiCrossDso) { // Skip available_externally functions. They won't be codegen'ed in the // current module anyway. if (getContext().GetGVALinkageForFunction(FD) == GVA_AvailableExternally) return; } llvm::Metadata *MD = CreateMetadataIdentifierForType(FD->getType()); F->addTypeMetadata(0, MD); F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType())); // Emit a hash-based bit set entry for cross-DSO calls. if (CodeGenOpts.SanitizeCfiCrossDso) if (auto CrossDsoTypeId = CreateCrossDsoCfiTypeId(MD)) F->addTypeMetadata(0, llvm::ConstantAsMetadata::get(CrossDsoTypeId)); } void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, bool IsIncompleteFunction, bool IsThunk) { if (llvm::Intrinsic::ID IID = F->getIntrinsicID()) { // If this is an intrinsic function, set the function's attributes // to the intrinsic's attributes. F->setAttributes(llvm::Intrinsic::getAttributes(getLLVMContext(), IID)); return; } const auto *FD = cast(GD.getDecl()); if (!IsIncompleteFunction) { SetLLVMFunctionAttributes(FD, getTypes().arrangeGlobalDeclaration(GD), F); // Setup target-specific attributes. if (F->isDeclaration()) getTargetCodeGenInfo().setTargetAttributes(FD, F, *this); } // Add the Returned attribute for "this", except for iOS 5 and earlier // where substantial code, including the libstdc++ dylib, was compiled with // GCC and does not actually return "this". if (!IsThunk && getCXXABI().HasThisReturn(GD) && !(getTriple().isiOS() && getTriple().isOSVersionLT(6))) { assert(!F->arg_empty() && F->arg_begin()->getType() ->canLosslesslyBitCastTo(F->getReturnType()) && "unexpected this return"); F->addAttribute(1, llvm::Attribute::Returned); } // Only a few attributes are set on declarations; these may later be // overridden by a definition. setLinkageForGV(F, FD); setGVProperties(F, FD); if (const auto *CSA = FD->getAttr()) F->setSection(CSA->getName()); else if (const auto *SA = FD->getAttr()) F->setSection(SA->getName()); if (FD->isReplaceableGlobalAllocationFunction()) { // A replaceable global allocation function does not act like a builtin by // default, only if it is invoked by a new-expression or delete-expression. F->addAttribute(llvm::AttributeList::FunctionIndex, llvm::Attribute::NoBuiltin); // A sane operator new returns a non-aliasing pointer. // FIXME: Also add NonNull attribute to the return value // for the non-nothrow forms? auto Kind = FD->getDeclName().getCXXOverloadedOperator(); if (getCodeGenOpts().AssumeSaneOperatorNew && (Kind == OO_New || Kind == OO_Array_New)) F->addAttribute(llvm::AttributeList::ReturnIndex, llvm::Attribute::NoAlias); } if (isa(FD) || isa(FD)) F->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); else if (const auto *MD = dyn_cast(FD)) if (MD->isVirtual()) F->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); // Don't emit entries for function declarations in the cross-DSO mode. This // is handled with better precision by the receiving DSO. if (!CodeGenOpts.SanitizeCfiCrossDso) CreateFunctionTypeMetadataForIcall(FD, F); if (getLangOpts().OpenMP && FD->hasAttr()) getOpenMPRuntime().emitDeclareSimdFunction(FD, F); } void CodeGenModule::addUsedGlobal(llvm::GlobalValue *GV) { assert(!GV->isDeclaration() && "Only globals with definition can force usage."); LLVMUsed.emplace_back(GV); } void CodeGenModule::addCompilerUsedGlobal(llvm::GlobalValue *GV) { assert(!GV->isDeclaration() && "Only globals with definition can force usage."); LLVMCompilerUsed.emplace_back(GV); } static void emitUsed(CodeGenModule &CGM, StringRef Name, std::vector &List) { // Don't create llvm.used if there is no need. if (List.empty()) return; // Convert List to what ConstantArray needs. SmallVector UsedArray; UsedArray.resize(List.size()); for (unsigned i = 0, e = List.size(); i != e; ++i) { UsedArray[i] = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast( cast(&*List[i]), CGM.Int8PtrTy); } if (UsedArray.empty()) return; llvm::ArrayType *ATy = llvm::ArrayType::get(CGM.Int8PtrTy, UsedArray.size()); auto *GV = new llvm::GlobalVariable( CGM.getModule(), ATy, false, llvm::GlobalValue::AppendingLinkage, llvm::ConstantArray::get(ATy, UsedArray), Name); GV->setSection("llvm.metadata"); } void CodeGenModule::emitLLVMUsed() { emitUsed(*this, "llvm.used", LLVMUsed); emitUsed(*this, "llvm.compiler.used", LLVMCompilerUsed); } void CodeGenModule::AppendLinkerOptions(StringRef Opts) { auto *MDOpts = llvm::MDString::get(getLLVMContext(), Opts); LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts)); } void CodeGenModule::AddDetectMismatch(StringRef Name, StringRef Value) { llvm::SmallString<32> Opt; getTargetCodeGenInfo().getDetectMismatchOption(Name, Value, Opt); auto *MDOpts = llvm::MDString::get(getLLVMContext(), Opt); LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts)); } void CodeGenModule::AddELFLibDirective(StringRef Lib) { auto &C = getLLVMContext(); LinkerOptionsMetadata.push_back(llvm::MDNode::get( C, {llvm::MDString::get(C, "lib"), llvm::MDString::get(C, Lib)})); } void CodeGenModule::AddDependentLib(StringRef Lib) { llvm::SmallString<24> Opt; getTargetCodeGenInfo().getDependentLibraryOption(Lib, Opt); auto *MDOpts = llvm::MDString::get(getLLVMContext(), Opt); LinkerOptionsMetadata.push_back(llvm::MDNode::get(getLLVMContext(), MDOpts)); } /// Add link options implied by the given module, including modules /// it depends on, using a postorder walk. static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod, SmallVectorImpl &Metadata, llvm::SmallPtrSet &Visited) { // Import this module's parent. if (Mod->Parent && Visited.insert(Mod->Parent).second) { addLinkOptionsPostorder(CGM, Mod->Parent, Metadata, Visited); } // Import this module's dependencies. for (unsigned I = Mod->Imports.size(); I > 0; --I) { if (Visited.insert(Mod->Imports[I - 1]).second) addLinkOptionsPostorder(CGM, Mod->Imports[I-1], Metadata, Visited); } // Add linker options to link against the libraries/frameworks // described by this module. llvm::LLVMContext &Context = CGM.getLLVMContext(); // For modules that use export_as for linking, use that module // name instead. if (Mod->UseExportAsModuleLinkName) return; for (unsigned I = Mod->LinkLibraries.size(); I > 0; --I) { // Link against a framework. Frameworks are currently Darwin only, so we // don't to ask TargetCodeGenInfo for the spelling of the linker option. if (Mod->LinkLibraries[I-1].IsFramework) { llvm::Metadata *Args[2] = { llvm::MDString::get(Context, "-framework"), llvm::MDString::get(Context, Mod->LinkLibraries[I - 1].Library)}; Metadata.push_back(llvm::MDNode::get(Context, Args)); continue; } // Link against a library. llvm::SmallString<24> Opt; CGM.getTargetCodeGenInfo().getDependentLibraryOption( Mod->LinkLibraries[I-1].Library, Opt); auto *OptString = llvm::MDString::get(Context, Opt); Metadata.push_back(llvm::MDNode::get(Context, OptString)); } } void CodeGenModule::EmitModuleLinkOptions() { // Collect the set of all of the modules we want to visit to emit link // options, which is essentially the imported modules and all of their // non-explicit child modules. llvm::SetVector LinkModules; llvm::SmallPtrSet Visited; SmallVector Stack; // Seed the stack with imported modules. for (Module *M : ImportedModules) { // Do not add any link flags when an implementation TU of a module imports // a header of that same module. if (M->getTopLevelModuleName() == getLangOpts().CurrentModule && !getLangOpts().isCompilingModule()) continue; if (Visited.insert(M).second) Stack.push_back(M); } // Find all of the modules to import, making a little effort to prune // non-leaf modules. while (!Stack.empty()) { clang::Module *Mod = Stack.pop_back_val(); bool AnyChildren = false; // Visit the submodules of this module. for (clang::Module::submodule_iterator Sub = Mod->submodule_begin(), SubEnd = Mod->submodule_end(); Sub != SubEnd; ++Sub) { // Skip explicit children; they need to be explicitly imported to be // linked against. if ((*Sub)->IsExplicit) continue; if (Visited.insert(*Sub).second) { Stack.push_back(*Sub); AnyChildren = true; } } // We didn't find any children, so add this module to the list of // modules to link against. if (!AnyChildren) { LinkModules.insert(Mod); } } // Add link options for all of the imported modules in reverse topological // order. We don't do anything to try to order import link flags with respect // to linker options inserted by things like #pragma comment(). SmallVector MetadataArgs; Visited.clear(); for (Module *M : LinkModules) if (Visited.insert(M).second) addLinkOptionsPostorder(*this, M, MetadataArgs, Visited); std::reverse(MetadataArgs.begin(), MetadataArgs.end()); LinkerOptionsMetadata.append(MetadataArgs.begin(), MetadataArgs.end()); // Add the linker options metadata flag. auto *NMD = getModule().getOrInsertNamedMetadata("llvm.linker.options"); for (auto *MD : LinkerOptionsMetadata) NMD->addOperand(MD); } void CodeGenModule::EmitDeferred() { // Emit code for any potentially referenced deferred decls. Since a // previously unused static decl may become used during the generation of code // for a static function, iterate until no changes are made. if (!DeferredVTables.empty()) { EmitDeferredVTables(); // Emitting a vtable doesn't directly cause more vtables to // become deferred, although it can cause functions to be // emitted that then need those vtables. assert(DeferredVTables.empty()); } // Stop if we're out of both deferred vtables and deferred declarations. if (DeferredDeclsToEmit.empty()) return; // Grab the list of decls to emit. If EmitGlobalDefinition schedules more // work, it will not interfere with this. std::vector CurDeclsToEmit; CurDeclsToEmit.swap(DeferredDeclsToEmit); for (GlobalDecl &D : CurDeclsToEmit) { // We should call GetAddrOfGlobal with IsForDefinition set to true in order // to get GlobalValue with exactly the type we need, not something that // might had been created for another decl with the same mangled name but // different type. llvm::GlobalValue *GV = dyn_cast( GetAddrOfGlobal(D, ForDefinition)); // In case of different address spaces, we may still get a cast, even with // IsForDefinition equal to true. Query mangled names table to get // GlobalValue. if (!GV) GV = GetGlobalValue(getMangledName(D)); // Make sure GetGlobalValue returned non-null. assert(GV); // Check to see if we've already emitted this. This is necessary // for a couple of reasons: first, decls can end up in the // deferred-decls queue multiple times, and second, decls can end // up with definitions in unusual ways (e.g. by an extern inline // function acquiring a strong function redefinition). Just // ignore these cases. if (!GV->isDeclaration()) continue; // Otherwise, emit the definition and move on to the next one. EmitGlobalDefinition(D, GV); // If we found out that we need to emit more decls, do that recursively. // This has the advantage that the decls are emitted in a DFS and related // ones are close together, which is convenient for testing. if (!DeferredVTables.empty() || !DeferredDeclsToEmit.empty()) { EmitDeferred(); assert(DeferredVTables.empty() && DeferredDeclsToEmit.empty()); } } } void CodeGenModule::EmitVTablesOpportunistically() { // Try to emit external vtables as available_externally if they have emitted // all inlined virtual functions. It runs after EmitDeferred() and therefore // is not allowed to create new references to things that need to be emitted // lazily. Note that it also uses fact that we eagerly emitting RTTI. assert((OpportunisticVTables.empty() || shouldOpportunisticallyEmitVTables()) && "Only emit opportunistic vtables with optimizations"); for (const CXXRecordDecl *RD : OpportunisticVTables) { assert(getVTables().isVTableExternal(RD) && "This queue should only contain external vtables"); if (getCXXABI().canSpeculativelyEmitVTable(RD)) VTables.GenerateClassData(RD); } OpportunisticVTables.clear(); } void CodeGenModule::EmitGlobalAnnotations() { if (Annotations.empty()) return; // Create a new global variable for the ConstantStruct in the Module. llvm::Constant *Array = llvm::ConstantArray::get(llvm::ArrayType::get( Annotations[0]->getType(), Annotations.size()), Annotations); auto *gv = new llvm::GlobalVariable(getModule(), Array->getType(), false, llvm::GlobalValue::AppendingLinkage, Array, "llvm.global.annotations"); gv->setSection(AnnotationSection); } llvm::Constant *CodeGenModule::EmitAnnotationString(StringRef Str) { llvm::Constant *&AStr = AnnotationStrings[Str]; if (AStr) return AStr; // Not found yet, create a new global. llvm::Constant *s = llvm::ConstantDataArray::getString(getLLVMContext(), Str); auto *gv = new llvm::GlobalVariable(getModule(), s->getType(), true, llvm::GlobalValue::PrivateLinkage, s, ".str"); gv->setSection(AnnotationSection); gv->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); AStr = gv; return gv; } llvm::Constant *CodeGenModule::EmitAnnotationUnit(SourceLocation Loc) { SourceManager &SM = getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(Loc); if (PLoc.isValid()) return EmitAnnotationString(PLoc.getFilename()); return EmitAnnotationString(SM.getBufferName(Loc)); } llvm::Constant *CodeGenModule::EmitAnnotationLineNo(SourceLocation L) { SourceManager &SM = getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(L); unsigned LineNo = PLoc.isValid() ? PLoc.getLine() : SM.getExpansionLineNumber(L); return llvm::ConstantInt::get(Int32Ty, LineNo); } llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV, const AnnotateAttr *AA, SourceLocation L) { // Get the globals for file name, annotation, and the line number. llvm::Constant *AnnoGV = EmitAnnotationString(AA->getAnnotation()), *UnitGV = EmitAnnotationUnit(L), *LineNoCst = EmitAnnotationLineNo(L); // Create the ConstantStruct for the global annotation. llvm::Constant *Fields[4] = { llvm::ConstantExpr::getBitCast(GV, Int8PtrTy), llvm::ConstantExpr::getBitCast(AnnoGV, Int8PtrTy), llvm::ConstantExpr::getBitCast(UnitGV, Int8PtrTy), LineNoCst }; return llvm::ConstantStruct::getAnon(Fields); } void CodeGenModule::AddGlobalAnnotations(const ValueDecl *D, llvm::GlobalValue *GV) { assert(D->hasAttr() && "no annotate attribute"); // Get the struct elements for these annotations. for (const auto *I : D->specific_attrs()) Annotations.push_back(EmitAnnotateAttr(GV, I, D->getLocation())); } bool CodeGenModule::isInSanitizerBlacklist(SanitizerMask Kind, llvm::Function *Fn, SourceLocation Loc) const { const auto &SanitizerBL = getContext().getSanitizerBlacklist(); // Blacklist by function name. if (SanitizerBL.isBlacklistedFunction(Kind, Fn->getName())) return true; // Blacklist by location. if (Loc.isValid()) return SanitizerBL.isBlacklistedLocation(Kind, Loc); // If location is unknown, this may be a compiler-generated function. Assume // it's located in the main file. auto &SM = Context.getSourceManager(); if (const auto *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { return SanitizerBL.isBlacklistedFile(Kind, MainFile->getName()); } return false; } bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV, SourceLocation Loc, QualType Ty, StringRef Category) const { // For now globals can be blacklisted only in ASan and KASan. const SanitizerMask EnabledAsanMask = LangOpts.Sanitize.Mask & (SanitizerKind::Address | SanitizerKind::KernelAddress | SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress); if (!EnabledAsanMask) return false; const auto &SanitizerBL = getContext().getSanitizerBlacklist(); if (SanitizerBL.isBlacklistedGlobal(EnabledAsanMask, GV->getName(), Category)) return true; if (SanitizerBL.isBlacklistedLocation(EnabledAsanMask, Loc, Category)) return true; // Check global type. if (!Ty.isNull()) { // Drill down the array types: if global variable of a fixed type is // blacklisted, we also don't instrument arrays of them. while (auto AT = dyn_cast(Ty.getTypePtr())) Ty = AT->getElementType(); Ty = Ty.getCanonicalType().getUnqualifiedType(); // We allow to blacklist only record types (classes, structs etc.) if (Ty->isRecordType()) { std::string TypeStr = Ty.getAsString(getContext().getPrintingPolicy()); if (SanitizerBL.isBlacklistedType(EnabledAsanMask, TypeStr, Category)) return true; } } return false; } bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc, StringRef Category) const { if (!LangOpts.XRayInstrument) return false; const auto &XRayFilter = getContext().getXRayFilter(); using ImbueAttr = XRayFunctionFilter::ImbueAttribute; auto Attr = ImbueAttr::NONE; if (Loc.isValid()) Attr = XRayFilter.shouldImbueLocation(Loc, Category); if (Attr == ImbueAttr::NONE) Attr = XRayFilter.shouldImbueFunction(Fn->getName()); switch (Attr) { case ImbueAttr::NONE: return false; case ImbueAttr::ALWAYS: Fn->addFnAttr("function-instrument", "xray-always"); break; case ImbueAttr::ALWAYS_ARG1: Fn->addFnAttr("function-instrument", "xray-always"); Fn->addFnAttr("xray-log-args", "1"); break; case ImbueAttr::NEVER: Fn->addFnAttr("function-instrument", "xray-never"); break; } return true; } bool CodeGenModule::MustBeEmitted(const ValueDecl *Global) { // Never defer when EmitAllDecls is specified. if (LangOpts.EmitAllDecls) return true; return getContext().DeclMustBeEmitted(Global); } bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) { if (const auto *FD = dyn_cast(Global)) if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) // Implicit template instantiations may change linkage if they are later // explicitly instantiated, so they should not be emitted eagerly. return false; if (const auto *VD = dyn_cast(Global)) if (Context.getInlineVariableDefinitionKind(VD) == ASTContext::InlineVariableDefinitionKind::WeakUnknown) // A definition of an inline constexpr static data member may change // linkage later if it's redeclared outside the class. return false; // If OpenMP is enabled and threadprivates must be generated like TLS, delay // codegen for global variables, because they may be marked as threadprivate. if (LangOpts.OpenMP && LangOpts.OpenMPUseTLS && getContext().getTargetInfo().isTLSSupported() && isa(Global) && !isTypeConstant(Global->getType(), false)) return false; return true; } ConstantAddress CodeGenModule::GetAddrOfUuidDescriptor( const CXXUuidofExpr* E) { // Sema has verified that IIDSource has a __declspec(uuid()), and that its // well-formed. StringRef Uuid = E->getUuidStr(); std::string Name = "_GUID_" + Uuid.lower(); std::replace(Name.begin(), Name.end(), '-', '_'); // The UUID descriptor should be pointer aligned. CharUnits Alignment = CharUnits::fromQuantity(PointerAlignInBytes); // Look for an existing global. if (llvm::GlobalVariable *GV = getModule().getNamedGlobal(Name)) return ConstantAddress(GV, Alignment); llvm::Constant *Init = EmitUuidofInitializer(Uuid); assert(Init && "failed to initialize as constant"); auto *GV = new llvm::GlobalVariable( getModule(), Init->getType(), /*isConstant=*/true, llvm::GlobalValue::LinkOnceODRLinkage, Init, Name); if (supportsCOMDAT()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); setDSOLocal(GV); return ConstantAddress(GV, Alignment); } ConstantAddress CodeGenModule::GetWeakRefReference(const ValueDecl *VD) { const AliasAttr *AA = VD->getAttr(); assert(AA && "No alias?"); CharUnits Alignment = getContext().getDeclAlign(VD); llvm::Type *DeclTy = getTypes().ConvertTypeForMem(VD->getType()); // See if there is already something with the target's name in the module. llvm::GlobalValue *Entry = GetGlobalValue(AA->getAliasee()); if (Entry) { unsigned AS = getContext().getTargetAddressSpace(VD->getType()); auto Ptr = llvm::ConstantExpr::getBitCast(Entry, DeclTy->getPointerTo(AS)); return ConstantAddress(Ptr, Alignment); } llvm::Constant *Aliasee; if (isa(DeclTy)) Aliasee = GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, GlobalDecl(cast(VD)), /*ForVTable=*/false); else Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(), llvm::PointerType::getUnqual(DeclTy), nullptr); auto *F = cast(Aliasee); F->setLinkage(llvm::Function::ExternalWeakLinkage); WeakRefReferences.insert(F); return ConstantAddress(Aliasee, Alignment); } void CodeGenModule::EmitGlobal(GlobalDecl GD) { const auto *Global = cast(GD.getDecl()); // Weak references don't produce any output by themselves. if (Global->hasAttr()) return; // If this is an alias definition (which otherwise looks like a declaration) // emit it now. if (Global->hasAttr()) return EmitAliasDefinition(GD); // IFunc like an alias whose value is resolved at runtime by calling resolver. if (Global->hasAttr()) return emitIFuncDefinition(GD); // If this is a cpu_dispatch multiversion function, emit the resolver. if (Global->hasAttr()) return emitCPUDispatchDefinition(GD); // If this is CUDA, be selective about which declarations we emit. if (LangOpts.CUDA) { if (LangOpts.CUDAIsDevice) { if (!Global->hasAttr() && !Global->hasAttr() && !Global->hasAttr() && !Global->hasAttr()) return; } else { // We need to emit host-side 'shadows' for all global // device-side variables because the CUDA runtime needs their // size and host-side address in order to provide access to // their device-side incarnations. // So device-only functions are the only things we skip. if (isa(Global) && !Global->hasAttr() && Global->hasAttr()) return; assert((isa(Global) || isa(Global)) && "Expected Variable or Function"); } } if (LangOpts.OpenMP) { // If this is OpenMP device, check if it is legal to emit this global // normally. if (OpenMPRuntime && OpenMPRuntime->emitTargetGlobal(GD)) return; if (auto *DRD = dyn_cast(Global)) { if (MustBeEmitted(Global)) EmitOMPDeclareReduction(DRD); return; } } // Ignore declarations, they will be emitted on their first use. if (const auto *FD = dyn_cast(Global)) { // Forward declarations are emitted lazily on first use. if (!FD->doesThisDeclarationHaveABody()) { if (!FD->doesDeclarationForceExternallyVisibleDefinition()) return; StringRef MangledName = getMangledName(GD); // Compute the function info and LLVM type. const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); llvm::Type *Ty = getTypes().GetFunctionType(FI); GetOrCreateLLVMFunction(MangledName, Ty, GD, /*ForVTable=*/false, /*DontDefer=*/false); return; } } else { const auto *VD = cast(Global); assert(VD->isFileVarDecl() && "Cannot emit local var decl as global."); // We need to emit device-side global CUDA variables even if a // variable does not have a definition -- we still need to define // host-side shadow for it. bool MustEmitForCuda = LangOpts.CUDA && !LangOpts.CUDAIsDevice && !VD->hasDefinition() && (VD->hasAttr() || VD->hasAttr()); if (!MustEmitForCuda && VD->isThisDeclarationADefinition() != VarDecl::Definition && !Context.isMSStaticDataMemberInlineDefinition(VD)) { // If this declaration may have caused an inline variable definition to // change linkage, make sure that it's emitted. if (Context.getInlineVariableDefinitionKind(VD) == ASTContext::InlineVariableDefinitionKind::Strong) GetAddrOfGlobalVar(VD); return; } } // Defer code generation to first use when possible, e.g. if this is an inline // function. If the global must always be emitted, do it eagerly if possible // to benefit from cache locality. if (MustBeEmitted(Global) && MayBeEmittedEagerly(Global)) { // Emit the definition if it can't be deferred. EmitGlobalDefinition(GD); return; } // If we're deferring emission of a C++ variable with an // initializer, remember the order in which it appeared in the file. if (getLangOpts().CPlusPlus && isa(Global) && cast(Global)->hasInit()) { DelayedCXXInitPosition[Global] = CXXGlobalInits.size(); CXXGlobalInits.push_back(nullptr); } StringRef MangledName = getMangledName(GD); if (GetGlobalValue(MangledName) != nullptr) { // The value has already been used and should therefore be emitted. addDeferredDeclToEmit(GD); } else if (MustBeEmitted(Global)) { // The value must be emitted, but cannot be emitted eagerly. assert(!MayBeEmittedEagerly(Global)); addDeferredDeclToEmit(GD); } else { // Otherwise, remember that we saw a deferred decl with this name. The // first use of the mangled name will cause it to move into // DeferredDeclsToEmit. DeferredDecls[MangledName] = GD; } } // Check if T is a class type with a destructor that's not dllimport. static bool HasNonDllImportDtor(QualType T) { if (const auto *RT = T->getBaseElementTypeUnsafe()->getAs()) if (CXXRecordDecl *RD = dyn_cast(RT->getDecl())) if (RD->getDestructor() && !RD->getDestructor()->hasAttr()) return true; return false; } namespace { struct FunctionIsDirectlyRecursive : public RecursiveASTVisitor { const StringRef Name; const Builtin::Context &BI; bool Result; FunctionIsDirectlyRecursive(StringRef N, const Builtin::Context &C) : Name(N), BI(C), Result(false) { } typedef RecursiveASTVisitor Base; bool TraverseCallExpr(CallExpr *E) { const FunctionDecl *FD = E->getDirectCallee(); if (!FD) return true; AsmLabelAttr *Attr = FD->getAttr(); if (Attr && Name == Attr->getLabel()) { Result = true; return false; } unsigned BuiltinID = FD->getBuiltinID(); if (!BuiltinID || !BI.isLibFunction(BuiltinID)) return true; StringRef BuiltinName = BI.getName(BuiltinID); if (BuiltinName.startswith("__builtin_") && Name == BuiltinName.slice(strlen("__builtin_"), StringRef::npos)) { Result = true; return false; } return true; } }; // Make sure we're not referencing non-imported vars or functions. struct DLLImportFunctionVisitor : public RecursiveASTVisitor { bool SafeToInline = true; bool shouldVisitImplicitCode() const { return true; } bool VisitVarDecl(VarDecl *VD) { if (VD->getTLSKind()) { // A thread-local variable cannot be imported. SafeToInline = false; return SafeToInline; } // A variable definition might imply a destructor call. if (VD->isThisDeclarationADefinition()) SafeToInline = !HasNonDllImportDtor(VD->getType()); return SafeToInline; } bool VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { if (const auto *D = E->getTemporary()->getDestructor()) SafeToInline = D->hasAttr(); return SafeToInline; } bool VisitDeclRefExpr(DeclRefExpr *E) { ValueDecl *VD = E->getDecl(); if (isa(VD)) SafeToInline = VD->hasAttr(); else if (VarDecl *V = dyn_cast(VD)) SafeToInline = !V->hasGlobalStorage() || V->hasAttr(); return SafeToInline; } bool VisitCXXConstructExpr(CXXConstructExpr *E) { SafeToInline = E->getConstructor()->hasAttr(); return SafeToInline; } bool VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { CXXMethodDecl *M = E->getMethodDecl(); if (!M) { // Call through a pointer to member function. This is safe to inline. SafeToInline = true; } else { SafeToInline = M->hasAttr(); } return SafeToInline; } bool VisitCXXDeleteExpr(CXXDeleteExpr *E) { SafeToInline = E->getOperatorDelete()->hasAttr(); return SafeToInline; } bool VisitCXXNewExpr(CXXNewExpr *E) { SafeToInline = E->getOperatorNew()->hasAttr(); return SafeToInline; } }; } // isTriviallyRecursive - Check if this function calls another // decl that, because of the asm attribute or the other decl being a builtin, // ends up pointing to itself. bool CodeGenModule::isTriviallyRecursive(const FunctionDecl *FD) { StringRef Name; if (getCXXABI().getMangleContext().shouldMangleDeclName(FD)) { // asm labels are a special kind of mangling we have to support. AsmLabelAttr *Attr = FD->getAttr(); if (!Attr) return false; Name = Attr->getLabel(); } else { Name = FD->getName(); } FunctionIsDirectlyRecursive Walker(Name, Context.BuiltinInfo); Walker.TraverseFunctionDecl(const_cast(FD)); return Walker.Result; } bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) { if (getFunctionLinkage(GD) != llvm::Function::AvailableExternallyLinkage) return true; const auto *F = cast(GD.getDecl()); if (CodeGenOpts.OptimizationLevel == 0 && !F->hasAttr()) return false; if (F->hasAttr()) { // Check whether it would be safe to inline this dllimport function. DLLImportFunctionVisitor Visitor; Visitor.TraverseFunctionDecl(const_cast(F)); if (!Visitor.SafeToInline) return false; if (const CXXDestructorDecl *Dtor = dyn_cast(F)) { // Implicit destructor invocations aren't captured in the AST, so the // check above can't see them. Check for them manually here. for (const Decl *Member : Dtor->getParent()->decls()) if (isa(Member)) if (HasNonDllImportDtor(cast(Member)->getType())) return false; for (const CXXBaseSpecifier &B : Dtor->getParent()->bases()) if (HasNonDllImportDtor(B.getType())) return false; } } // PR9614. Avoid cases where the source code is lying to us. An available // externally function should have an equivalent function somewhere else, // but a function that calls itself is clearly not equivalent to the real // implementation. // This happens in glibc's btowc and in some configure checks. return !isTriviallyRecursive(F); } bool CodeGenModule::shouldOpportunisticallyEmitVTables() { return CodeGenOpts.OptimizationLevel > 0; } void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) { const auto *D = cast(GD.getDecl()); PrettyStackTraceDecl CrashInfo(const_cast(D), D->getLocation(), Context.getSourceManager(), "Generating code for declaration"); if (isa(D)) { // At -O0, don't generate IR for functions with available_externally // linkage. if (!shouldEmitFunction(GD)) return; if (const auto *Method = dyn_cast(D)) { // Make sure to emit the definition(s) before we emit the thunks. // This is necessary for the generation of certain thunks. if (const auto *CD = dyn_cast(Method)) ABI->emitCXXStructor(CD, getFromCtorType(GD.getCtorType())); else if (const auto *DD = dyn_cast(Method)) ABI->emitCXXStructor(DD, getFromDtorType(GD.getDtorType())); else EmitGlobalFunctionDefinition(GD, GV); if (Method->isVirtual()) getVTables().EmitThunks(GD); return; } return EmitGlobalFunctionDefinition(GD, GV); } if (const auto *VD = dyn_cast(D)) return EmitGlobalVarDefinition(VD, !VD->hasDefinition()); llvm_unreachable("Invalid argument to EmitGlobalDefinition()"); } static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, llvm::Function *NewFn); void CodeGenModule::emitMultiVersionFunctions() { for (GlobalDecl GD : MultiVersionFuncs) { SmallVector Options; const FunctionDecl *FD = cast(GD.getDecl()); getContext().forEachMultiversionedFunctionVersion( FD, [this, &GD, &Options](const FunctionDecl *CurFD) { GlobalDecl CurGD{ (CurFD->isDefined() ? CurFD->getDefinition() : CurFD)}; StringRef MangledName = getMangledName(CurGD); llvm::Constant *Func = GetGlobalValue(MangledName); if (!Func) { if (CurFD->isDefined()) { EmitGlobalFunctionDefinition(CurGD, nullptr); Func = GetGlobalValue(MangledName); } else { const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false, /*DontDefer=*/false, ForDefinition); } assert(Func && "This should have just been created"); } Options.emplace_back(getTarget(), cast(Func), CurFD->getAttr()->parse()); }); llvm::Function *ResolverFunc = cast( GetGlobalValue((getMangledName(GD) + ".resolver").str())); if (supportsCOMDAT()) ResolverFunc->setComdat( getModule().getOrInsertComdat(ResolverFunc->getName())); std::stable_sort( Options.begin(), Options.end(), std::greater()); CodeGenFunction CGF(*this); CGF.EmitTargetMultiVersionResolver(ResolverFunc, Options); } } void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) { const auto *FD = cast(GD.getDecl()); assert(FD && "Not a FunctionDecl?"); const auto *DD = FD->getAttr(); assert(DD && "Not a cpu_dispatch Function?"); llvm::Type *DeclTy = getTypes().ConvertTypeForMem(FD->getType()); StringRef ResolverName = getMangledName(GD); llvm::Type *ResolverType = llvm::FunctionType::get( llvm::PointerType::get(DeclTy, Context.getTargetAddressSpace(FD->getType())), false); auto *ResolverFunc = cast( GetOrCreateLLVMFunction(ResolverName, ResolverType, GlobalDecl{}, /*ForVTable=*/false)); SmallVector Options; const TargetInfo &Target = getTarget(); for (const IdentifierInfo *II : DD->cpus()) { // Get the name of the target function so we can look it up/create it. std::string MangledName = getMangledNameImpl(*this, GD, FD, true) + getCPUSpecificMangling(*this, II->getName()); llvm::Constant *Func = GetOrCreateLLVMFunction( MangledName, DeclTy, GD, /*ForVTable=*/false, /*DontDefer=*/false, /*IsThunk=*/false, llvm::AttributeList(), ForDefinition); llvm::SmallVector Features; Target.getCPUSpecificCPUDispatchFeatures(II->getName(), Features); llvm::transform(Features, Features.begin(), [](StringRef Str) { return Str.substr(1); }); Features.erase(std::remove_if( Features.begin(), Features.end(), [&Target](StringRef Feat) { return !Target.validateCpuSupports(Feat); }), Features.end()); Options.emplace_back(cast(Func), CodeGenFunction::GetX86CpuSupportsMask(Features)); } llvm::sort( Options.begin(), Options.end(), std::greater()); CodeGenFunction CGF(*this); CGF.EmitCPUDispatchMultiVersionResolver(ResolverFunc, Options); } /// If an ifunc for the specified mangled name is not in the module, create and /// return an llvm IFunc Function with the specified type. llvm::Constant * CodeGenModule::GetOrCreateMultiVersionIFunc(GlobalDecl GD, llvm::Type *DeclTy, const FunctionDecl *FD) { std::string MangledName = getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true); std::string IFuncName = MangledName + ".ifunc"; if (llvm::GlobalValue *IFuncGV = GetGlobalValue(IFuncName)) return IFuncGV; // Since this is the first time we've created this IFunc, make sure // that we put this multiversioned function into the list to be // replaced later if necessary (target multiversioning only). if (!FD->isCPUDispatchMultiVersion() && !FD->isCPUSpecificMultiVersion()) MultiVersionFuncs.push_back(GD); std::string ResolverName = MangledName + ".resolver"; llvm::Type *ResolverType = llvm::FunctionType::get( llvm::PointerType::get(DeclTy, Context.getTargetAddressSpace(FD->getType())), false); llvm::Constant *Resolver = GetOrCreateLLVMFunction(ResolverName, ResolverType, GlobalDecl{}, /*ForVTable=*/false); llvm::GlobalIFunc *GIF = llvm::GlobalIFunc::create( DeclTy, 0, llvm::Function::ExternalLinkage, "", Resolver, &getModule()); GIF->setName(IFuncName); SetCommonAttributes(FD, GIF); return GIF; } /// GetOrCreateLLVMFunction - If the specified mangled name is not in the /// module, create and return an llvm Function with the specified type. If there /// is something in the module with the specified name, return it potentially /// bitcasted to the right type. /// /// If D is non-null, it specifies a decl that correspond to this. This is used /// to set the attributes on the function when it is first created. llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( StringRef MangledName, llvm::Type *Ty, GlobalDecl GD, bool ForVTable, bool DontDefer, bool IsThunk, llvm::AttributeList ExtraAttrs, ForDefinition_t IsForDefinition) { const Decl *D = GD.getDecl(); // Any attempts to use a MultiVersion function should result in retrieving // the iFunc instead. Name Mangling will handle the rest of the changes. if (const FunctionDecl *FD = cast_or_null(D)) { // For the device mark the function as one that should be emitted. if (getLangOpts().OpenMPIsDevice && OpenMPRuntime && !OpenMPRuntime->markAsGlobalTarget(GD) && FD->isDefined() && !DontDefer && !IsForDefinition) { if (const FunctionDecl *FDDef = FD->getDefinition()) if (getContext().DeclMustBeEmitted(FDDef)) { GlobalDecl GDDef; if (const auto *CD = dyn_cast(FDDef)) GDDef = GlobalDecl(CD, GD.getCtorType()); else if (const auto *DD = dyn_cast(FDDef)) GDDef = GlobalDecl(DD, GD.getDtorType()); else GDDef = GlobalDecl(FDDef); addDeferredDeclToEmit(GDDef); } } if (FD->isMultiVersion()) { const auto *TA = FD->getAttr(); if (TA && TA->isDefaultVersion()) UpdateMultiVersionNames(GD, FD); if (!IsForDefinition) return GetOrCreateMultiVersionIFunc(GD, Ty, FD); } } // Lookup the entry, lazily creating it if necessary. llvm::GlobalValue *Entry = GetGlobalValue(MangledName); if (Entry) { if (WeakRefReferences.erase(Entry)) { const FunctionDecl *FD = cast_or_null(D); if (FD && !FD->hasAttr()) Entry->setLinkage(llvm::Function::ExternalLinkage); } // Handle dropped DLL attributes. if (D && !D->hasAttr() && !D->hasAttr()) { Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); setDSOLocal(Entry); } // If there are two attempts to define the same mangled name, issue an // error. if (IsForDefinition && !Entry->isDeclaration()) { GlobalDecl OtherGD; // Check that GD is not yet in DiagnosedConflictingDefinitions is required // to make sure that we issue an error only once. if (lookupRepresentativeDecl(MangledName, OtherGD) && (GD.getCanonicalDecl().getDecl() != OtherGD.getCanonicalDecl().getDecl()) && DiagnosedConflictingDefinitions.insert(GD).second) { getDiags().Report(D->getLocation(), diag::err_duplicate_mangled_name) << MangledName; getDiags().Report(OtherGD.getDecl()->getLocation(), diag::note_previous_definition); } } if ((isa(Entry) || isa(Entry)) && (Entry->getType()->getElementType() == Ty)) { return Entry; } // Make sure the result is of the correct type. // (If function is requested for a definition, we always need to create a new // function, not just return a bitcast.) if (!IsForDefinition) return llvm::ConstantExpr::getBitCast(Entry, Ty->getPointerTo()); } // This function doesn't have a complete type (for example, the return // type is an incomplete struct). Use a fake type instead, and make // sure not to try to set attributes. bool IsIncompleteFunction = false; llvm::FunctionType *FTy; if (isa(Ty)) { FTy = cast(Ty); } else { FTy = llvm::FunctionType::get(VoidTy, false); IsIncompleteFunction = true; } llvm::Function *F = llvm::Function::Create(FTy, llvm::Function::ExternalLinkage, Entry ? StringRef() : MangledName, &getModule()); // If we already created a function with the same mangled name (but different // type) before, take its name and add it to the list of functions to be // replaced with F at the end of CodeGen. // // This happens if there is a prototype for a function (e.g. "int f()") and // then a definition of a different type (e.g. "int f(int x)"). if (Entry) { F->takeName(Entry); // This might be an implementation of a function without a prototype, in // which case, try to do special replacement of calls which match the new // prototype. The really key thing here is that we also potentially drop // arguments from the call site so as to make a direct call, which makes the // inliner happier and suppresses a number of optimizer warnings (!) about // dropping arguments. if (!Entry->use_empty()) { ReplaceUsesOfNonProtoTypeWithRealFunction(Entry, F); Entry->removeDeadConstantUsers(); } llvm::Constant *BC = llvm::ConstantExpr::getBitCast( F, Entry->getType()->getElementType()->getPointerTo()); addGlobalValReplacement(Entry, BC); } assert(F->getName() == MangledName && "name was uniqued!"); if (D) SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk); if (ExtraAttrs.hasAttributes(llvm::AttributeList::FunctionIndex)) { llvm::AttrBuilder B(ExtraAttrs, llvm::AttributeList::FunctionIndex); F->addAttributes(llvm::AttributeList::FunctionIndex, B); } if (!DontDefer) { // All MSVC dtors other than the base dtor are linkonce_odr and delegate to // each other bottoming out with the base dtor. Therefore we emit non-base // dtors on usage, even if there is no dtor definition in the TU. if (D && isa(D) && getCXXABI().useThunkForDtorVariant(cast(D), GD.getDtorType())) addDeferredDeclToEmit(GD); // This is the first use or definition of a mangled name. If there is a // deferred decl with this name, remember that we need to emit it at the end // of the file. auto DDI = DeferredDecls.find(MangledName); if (DDI != DeferredDecls.end()) { // Move the potentially referenced deferred decl to the // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we // don't need it anymore). addDeferredDeclToEmit(DDI->second); DeferredDecls.erase(DDI); // Otherwise, there are cases we have to worry about where we're // using a declaration for which we must emit a definition but where // we might not find a top-level definition: // - member functions defined inline in their classes // - friend functions defined inline in some class // - special member functions with implicit definitions // If we ever change our AST traversal to walk into class methods, // this will be unnecessary. // // We also don't emit a definition for a function if it's going to be an // entry in a vtable, unless it's already marked as used. } else if (getLangOpts().CPlusPlus && D) { // Look for a declaration that's lexically in a record. for (const auto *FD = cast(D)->getMostRecentDecl(); FD; FD = FD->getPreviousDecl()) { if (isa(FD->getLexicalDeclContext())) { if (FD->doesThisDeclarationHaveABody()) { addDeferredDeclToEmit(GD.getWithDecl(FD)); break; } } } } } // Make sure the result is of the requested type. if (!IsIncompleteFunction) { assert(F->getType()->getElementType() == Ty); return F; } llvm::Type *PTy = llvm::PointerType::getUnqual(Ty); return llvm::ConstantExpr::getBitCast(F, PTy); } /// GetAddrOfFunction - Return the address of the given function. If Ty is /// non-null, then this function will use the specified type if it has to /// create it (this occurs when we see a definition of the function). llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty, bool ForVTable, bool DontDefer, ForDefinition_t IsForDefinition) { // If there was no specific requested type, just convert it now. if (!Ty) { const auto *FD = cast(GD.getDecl()); auto CanonTy = Context.getCanonicalType(FD->getType()); Ty = getTypes().ConvertFunctionType(CanonTy, FD); } // Devirtualized destructor calls may come through here instead of via // getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead // of the complete destructor when necessary. if (const auto *DD = dyn_cast(GD.getDecl())) { if (getTarget().getCXXABI().isMicrosoft() && GD.getDtorType() == Dtor_Complete && DD->getParent()->getNumVBases() == 0) GD = GlobalDecl(DD, Dtor_Base); } StringRef MangledName = getMangledName(GD); return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer, /*IsThunk=*/false, llvm::AttributeList(), IsForDefinition); } static const FunctionDecl * GetRuntimeFunctionDecl(ASTContext &C, StringRef Name) { TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl(); DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl); IdentifierInfo &CII = C.Idents.get(Name); for (const auto &Result : DC->lookup(&CII)) if (const auto FD = dyn_cast(Result)) return FD; if (!C.getLangOpts().CPlusPlus) return nullptr; // Demangle the premangled name from getTerminateFn() IdentifierInfo &CXXII = (Name == "_ZSt9terminatev" || Name == "?terminate@@YAXXZ") ? C.Idents.get("terminate") : C.Idents.get(Name); for (const auto &N : {"__cxxabiv1", "std"}) { IdentifierInfo &NS = C.Idents.get(N); for (const auto &Result : DC->lookup(&NS)) { NamespaceDecl *ND = dyn_cast(Result); if (auto LSD = dyn_cast(Result)) for (const auto &Result : LSD->lookup(&NS)) if ((ND = dyn_cast(Result))) break; if (ND) for (const auto &Result : ND->lookup(&CXXII)) if (const auto *FD = dyn_cast(Result)) return FD; } } return nullptr; } /// CreateRuntimeFunction - Create a new runtime function with the specified /// type and name. llvm::Constant * CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name, llvm::AttributeList ExtraAttrs, bool Local) { llvm::Constant *C = GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false, /*DontDefer=*/false, /*IsThunk=*/false, ExtraAttrs); if (auto *F = dyn_cast(C)) { if (F->empty()) { F->setCallingConv(getRuntimeCC()); if (!Local && getTriple().isOSBinFormatCOFF() && !getCodeGenOpts().LTOVisibilityPublicStd && !getTriple().isWindowsGNUEnvironment()) { const FunctionDecl *FD = GetRuntimeFunctionDecl(Context, Name); if (!FD || FD->hasAttr()) { F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); F->setLinkage(llvm::GlobalValue::ExternalLinkage); } } setDSOLocal(F); } } return C; } /// CreateBuiltinFunction - Create a new builtin function with the specified /// type and name. llvm::Constant * CodeGenModule::CreateBuiltinFunction(llvm::FunctionType *FTy, StringRef Name, llvm::AttributeList ExtraAttrs) { return CreateRuntimeFunction(FTy, Name, ExtraAttrs, true); } /// isTypeConstant - Determine whether an object of this type can be emitted /// as a constant. /// /// If ExcludeCtor is true, the duration when the object's constructor runs /// will not be considered. The caller will need to verify that the object is /// not written to during its construction. bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor) { if (!Ty.isConstant(Context) && !Ty->isReferenceType()) return false; if (Context.getLangOpts().CPlusPlus) { if (const CXXRecordDecl *Record = Context.getBaseElementType(Ty)->getAsCXXRecordDecl()) return ExcludeCtor && !Record->hasMutableFields() && Record->hasTrivialDestructor(); } return true; } /// GetOrCreateLLVMGlobal - If the specified mangled name is not in the module, /// create and return an llvm GlobalVariable with the specified type. If there /// is something in the module with the specified name, return it potentially /// bitcasted to the right type. /// /// If D is non-null, it specifies a decl that correspond to this. This is used /// to set the attributes on the global when it is first created. /// /// If IsForDefinition is true, it is guaranteed that an actual global with /// type Ty will be returned, not conversion of a variable with the same /// mangled name but some other type. llvm::Constant * CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::PointerType *Ty, const VarDecl *D, ForDefinition_t IsForDefinition) { // Lookup the entry, lazily creating it if necessary. llvm::GlobalValue *Entry = GetGlobalValue(MangledName); if (Entry) { if (WeakRefReferences.erase(Entry)) { if (D && !D->hasAttr()) Entry->setLinkage(llvm::Function::ExternalLinkage); } // Handle dropped DLL attributes. if (D && !D->hasAttr() && !D->hasAttr()) Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); if (LangOpts.OpenMP && !LangOpts.OpenMPSimd && D) getOpenMPRuntime().registerTargetGlobalVariable(D, Entry); if (Entry->getType() == Ty) return Entry; // If there are two attempts to define the same mangled name, issue an // error. if (IsForDefinition && !Entry->isDeclaration()) { GlobalDecl OtherGD; const VarDecl *OtherD; // Check that D is not yet in DiagnosedConflictingDefinitions is required // to make sure that we issue an error only once. if (D && lookupRepresentativeDecl(MangledName, OtherGD) && (D->getCanonicalDecl() != OtherGD.getCanonicalDecl().getDecl()) && (OtherD = dyn_cast(OtherGD.getDecl())) && OtherD->hasInit() && DiagnosedConflictingDefinitions.insert(D).second) { getDiags().Report(D->getLocation(), diag::err_duplicate_mangled_name) << MangledName; getDiags().Report(OtherGD.getDecl()->getLocation(), diag::note_previous_definition); } } // Make sure the result is of the correct type. if (Entry->getType()->getAddressSpace() != Ty->getAddressSpace()) return llvm::ConstantExpr::getAddrSpaceCast(Entry, Ty); // (If global is requested for a definition, we always need to create a new // global, not just return a bitcast.) if (!IsForDefinition) return llvm::ConstantExpr::getBitCast(Entry, Ty); } auto AddrSpace = GetGlobalVarAddressSpace(D); auto TargetAddrSpace = getContext().getTargetAddressSpace(AddrSpace); auto *GV = new llvm::GlobalVariable( getModule(), Ty->getElementType(), false, llvm::GlobalValue::ExternalLinkage, nullptr, MangledName, nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAddrSpace); // If we already created a global with the same mangled name (but different // type) before, take its name and remove it from its parent. if (Entry) { GV->takeName(Entry); if (!Entry->use_empty()) { llvm::Constant *NewPtrForOldDecl = llvm::ConstantExpr::getBitCast(GV, Entry->getType()); Entry->replaceAllUsesWith(NewPtrForOldDecl); } Entry->eraseFromParent(); } // This is the first use or definition of a mangled name. If there is a // deferred decl with this name, remember that we need to emit it at the end // of the file. auto DDI = DeferredDecls.find(MangledName); if (DDI != DeferredDecls.end()) { // Move the potentially referenced deferred decl to the DeferredDeclsToEmit // list, and remove it from DeferredDecls (since we don't need it anymore). addDeferredDeclToEmit(DDI->second); DeferredDecls.erase(DDI); } // Handle things which are present even on external declarations. if (D) { if (LangOpts.OpenMP && !LangOpts.OpenMPSimd) getOpenMPRuntime().registerTargetGlobalVariable(D, GV); // FIXME: This code is overly simple and should be merged with other global // handling. GV->setConstant(isTypeConstant(D->getType(), false)); GV->setAlignment(getContext().getDeclAlign(D).getQuantity()); setLinkageForGV(GV, D); if (D->getTLSKind()) { if (D->getTLSKind() == VarDecl::TLS_Dynamic) CXXThreadLocals.push_back(D); setTLSMode(GV, *D); } setGVProperties(GV, D); // If required by the ABI, treat declarations of static data members with // inline initializers as definitions. if (getContext().isMSStaticDataMemberInlineDefinition(D)) { EmitGlobalVarDefinition(D); } // Emit section information for extern variables. if (D->hasExternalStorage()) { if (const SectionAttr *SA = D->getAttr()) GV->setSection(SA->getName()); } // Handle XCore specific ABI requirements. if (getTriple().getArch() == llvm::Triple::xcore && D->getLanguageLinkage() == CLanguageLinkage && D->getType().isConstant(Context) && isExternallyVisible(D->getLinkageAndVisibility().getLinkage())) GV->setSection(".cp.rodata"); // Check if we a have a const declaration with an initializer, we may be // able to emit it as available_externally to expose it's value to the // optimizer. if (Context.getLangOpts().CPlusPlus && GV->hasExternalLinkage() && D->getType().isConstQualified() && !GV->hasInitializer() && !D->hasDefinition() && D->hasInit() && !D->hasAttr()) { const auto *Record = Context.getBaseElementType(D->getType())->getAsCXXRecordDecl(); bool HasMutableFields = Record && Record->hasMutableFields(); if (!HasMutableFields) { const VarDecl *InitDecl; const Expr *InitExpr = D->getAnyInitializer(InitDecl); if (InitExpr) { ConstantEmitter emitter(*this); llvm::Constant *Init = emitter.tryEmitForInitializer(*InitDecl); if (Init) { auto *InitType = Init->getType(); if (GV->getType()->getElementType() != InitType) { // The type of the initializer does not match the definition. // This happens when an initializer has a different type from // the type of the global (because of padding at the end of a // structure for instance). GV->setName(StringRef()); // Make a new global with the correct type, this is now guaranteed // to work. auto *NewGV = cast( GetAddrOfGlobalVar(D, InitType, IsForDefinition)); // Erase the old global, since it is no longer used. GV->eraseFromParent(); GV = NewGV; } else { GV->setInitializer(Init); GV->setConstant(true); GV->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage); } emitter.finalize(GV); } } } } } LangAS ExpectedAS = D ? D->getType().getAddressSpace() : (LangOpts.OpenCL ? LangAS::opencl_global : LangAS::Default); assert(getContext().getTargetAddressSpace(ExpectedAS) == Ty->getPointerAddressSpace()); if (AddrSpace != ExpectedAS) return getTargetCodeGenInfo().performAddrSpaceCast(*this, GV, AddrSpace, ExpectedAS, Ty); return GV; } llvm::Constant * CodeGenModule::GetAddrOfGlobal(GlobalDecl GD, ForDefinition_t IsForDefinition) { const Decl *D = GD.getDecl(); if (isa(D)) return getAddrOfCXXStructor(cast(D), getFromCtorType(GD.getCtorType()), /*FnInfo=*/nullptr, /*FnType=*/nullptr, /*DontDefer=*/false, IsForDefinition); else if (isa(D)) return getAddrOfCXXStructor(cast(D), getFromDtorType(GD.getDtorType()), /*FnInfo=*/nullptr, /*FnType=*/nullptr, /*DontDefer=*/false, IsForDefinition); else if (isa(D)) { auto FInfo = &getTypes().arrangeCXXMethodDeclaration( cast(D)); auto Ty = getTypes().GetFunctionType(*FInfo); return GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer=*/false, IsForDefinition); } else if (isa(D)) { const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); return GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer=*/false, IsForDefinition); } else return GetAddrOfGlobalVar(cast(D), /*Ty=*/nullptr, IsForDefinition); } llvm::GlobalVariable * CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name, llvm::Type *Ty, llvm::GlobalValue::LinkageTypes Linkage) { llvm::GlobalVariable *GV = getModule().getNamedGlobal(Name); llvm::GlobalVariable *OldGV = nullptr; if (GV) { // Check if the variable has the right type. if (GV->getType()->getElementType() == Ty) return GV; // Because C++ name mangling, the only way we can end up with an already // existing global with the same name is if it has been declared extern "C". assert(GV->isDeclaration() && "Declaration has wrong type!"); OldGV = GV; } // Create a new variable. GV = new llvm::GlobalVariable(getModule(), Ty, /*isConstant=*/true, Linkage, nullptr, Name); if (OldGV) { // Replace occurrences of the old variable if needed. GV->takeName(OldGV); if (!OldGV->use_empty()) { llvm::Constant *NewPtrForOldDecl = llvm::ConstantExpr::getBitCast(GV, OldGV->getType()); OldGV->replaceAllUsesWith(NewPtrForOldDecl); } OldGV->eraseFromParent(); } if (supportsCOMDAT() && GV->isWeakForLinker() && !GV->hasAvailableExternallyLinkage()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); return GV; } /// GetAddrOfGlobalVar - Return the llvm::Constant for the address of the /// given global variable. If Ty is non-null and if the global doesn't exist, /// then it will be created with the specified type instead of whatever the /// normal requested type would be. If IsForDefinition is true, it is guaranteed /// that an actual global with type Ty will be returned, not conversion of a /// variable with the same mangled name but some other type. llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D, llvm::Type *Ty, ForDefinition_t IsForDefinition) { assert(D->hasGlobalStorage() && "Not a global variable"); QualType ASTTy = D->getType(); if (!Ty) Ty = getTypes().ConvertTypeForMem(ASTTy); llvm::PointerType *PTy = llvm::PointerType::get(Ty, getContext().getTargetAddressSpace(ASTTy)); StringRef MangledName = getMangledName(D); return GetOrCreateLLVMGlobal(MangledName, PTy, D, IsForDefinition); } /// CreateRuntimeVariable - Create a new runtime global variable with the /// specified type and name. llvm::Constant * CodeGenModule::CreateRuntimeVariable(llvm::Type *Ty, StringRef Name) { auto *Ret = GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), nullptr); setDSOLocal(cast(Ret->stripPointerCasts())); return Ret; } void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) { assert(!D->getInit() && "Cannot emit definite definitions here!"); StringRef MangledName = getMangledName(D); llvm::GlobalValue *GV = GetGlobalValue(MangledName); // We already have a definition, not declaration, with the same mangled name. // Emitting of declaration is not required (and actually overwrites emitted // definition). if (GV && !GV->isDeclaration()) return; // If we have not seen a reference to this variable yet, place it into the // deferred declarations table to be emitted if needed later. if (!MustBeEmitted(D) && !GV) { DeferredDecls[MangledName] = D; return; } // The tentative definition is the only definition. EmitGlobalVarDefinition(D); } CharUnits CodeGenModule::GetTargetTypeStoreSize(llvm::Type *Ty) const { return Context.toCharUnitsFromBits( getDataLayout().getTypeStoreSizeInBits(Ty)); } LangAS CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D) { LangAS AddrSpace = LangAS::Default; if (LangOpts.OpenCL) { AddrSpace = D ? D->getType().getAddressSpace() : LangAS::opencl_global; assert(AddrSpace == LangAS::opencl_global || AddrSpace == LangAS::opencl_constant || AddrSpace == LangAS::opencl_local || AddrSpace >= LangAS::FirstTargetAddressSpace); return AddrSpace; } if (LangOpts.CUDA && LangOpts.CUDAIsDevice) { if (D && D->hasAttr()) return LangAS::cuda_constant; else if (D && D->hasAttr()) return LangAS::cuda_shared; else if (D && D->hasAttr()) return LangAS::cuda_device; else if (D && D->getType().isConstQualified()) return LangAS::cuda_constant; else return LangAS::cuda_device; } return getTargetCodeGenInfo().getGlobalVarAddressSpace(*this, D); } LangAS CodeGenModule::getStringLiteralAddressSpace() const { // OpenCL v1.2 s6.5.3: a string literal is in the constant address space. if (LangOpts.OpenCL) return LangAS::opencl_constant; if (auto AS = getTarget().getConstantAddressSpace()) return AS.getValue(); return LangAS::Default; } // In address space agnostic languages, string literals are in default address // space in AST. However, certain targets (e.g. amdgcn) request them to be // emitted in constant address space in LLVM IR. To be consistent with other // parts of AST, string literal global variables in constant address space // need to be casted to default address space before being put into address // map and referenced by other part of CodeGen. // In OpenCL, string literals are in constant address space in AST, therefore // they should not be casted to default address space. static llvm::Constant * castStringLiteralToDefaultAddressSpace(CodeGenModule &CGM, llvm::GlobalVariable *GV) { llvm::Constant *Cast = GV; if (!CGM.getLangOpts().OpenCL) { if (auto AS = CGM.getTarget().getConstantAddressSpace()) { if (AS != LangAS::Default) Cast = CGM.getTargetCodeGenInfo().performAddrSpaceCast( CGM, GV, AS.getValue(), LangAS::Default, GV->getValueType()->getPointerTo( CGM.getContext().getTargetAddressSpace(LangAS::Default))); } } return Cast; } template void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D, llvm::GlobalValue *GV) { if (!getLangOpts().CPlusPlus) return; // Must have 'used' attribute, or else inline assembly can't rely on // the name existing. if (!D->template hasAttr()) return; // Must have internal linkage and an ordinary name. if (!D->getIdentifier() || D->getFormalLinkage() != InternalLinkage) return; // Must be in an extern "C" context. Entities declared directly within // a record are not extern "C" even if the record is in such a context. const SomeDecl *First = D->getFirstDecl(); if (First->getDeclContext()->isRecord() || !First->isInExternCContext()) return; // OK, this is an internal linkage entity inside an extern "C" linkage // specification. Make a note of that so we can give it the "expected" // mangled name if nothing else is using that name. std::pair R = StaticExternCValues.insert(std::make_pair(D->getIdentifier(), GV)); // If we have multiple internal linkage entities with the same name // in extern "C" regions, none of them gets that name. if (!R.second) R.first->second = nullptr; } static bool shouldBeInCOMDAT(CodeGenModule &CGM, const Decl &D) { if (!CGM.supportsCOMDAT()) return false; if (D.hasAttr()) return true; GVALinkage Linkage; if (auto *VD = dyn_cast(&D)) Linkage = CGM.getContext().GetGVALinkageForVariable(VD); else Linkage = CGM.getContext().GetGVALinkageForFunction(cast(&D)); switch (Linkage) { case GVA_Internal: case GVA_AvailableExternally: case GVA_StrongExternal: return false; case GVA_DiscardableODR: case GVA_StrongODR: return true; } llvm_unreachable("No such linkage"); } void CodeGenModule::maybeSetTrivialComdat(const Decl &D, llvm::GlobalObject &GO) { if (!shouldBeInCOMDAT(*this, D)) return; GO.setComdat(TheModule.getOrInsertComdat(GO.getName())); } /// Pass IsTentative as true if you want to create a tentative definition. void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, bool IsTentative) { // OpenCL global variables of sampler type are translated to function calls, // therefore no need to be translated. QualType ASTTy = D->getType(); if (getLangOpts().OpenCL && ASTTy->isSamplerT()) return; // If this is OpenMP device, check if it is legal to emit this global // normally. if (LangOpts.OpenMPIsDevice && OpenMPRuntime && OpenMPRuntime->emitTargetGlobalVariable(D)) return; llvm::Constant *Init = nullptr; CXXRecordDecl *RD = ASTTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); bool NeedsGlobalCtor = false; bool NeedsGlobalDtor = RD && !RD->hasTrivialDestructor(); const VarDecl *InitDecl; const Expr *InitExpr = D->getAnyInitializer(InitDecl); Optional emitter; // CUDA E.2.4.1 "__shared__ variables cannot have an initialization // as part of their declaration." Sema has already checked for // error cases, so we just need to set Init to UndefValue. if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice && D->hasAttr()) Init = llvm::UndefValue::get(getTypes().ConvertType(ASTTy)); else if (!InitExpr) { // This is a tentative definition; tentative definitions are // implicitly initialized with { 0 }. // // Note that tentative definitions are only emitted at the end of // a translation unit, so they should never have incomplete // type. In addition, EmitTentativeDefinition makes sure that we // never attempt to emit a tentative definition if a real one // exists. A use may still exists, however, so we still may need // to do a RAUW. assert(!ASTTy->isIncompleteType() && "Unexpected incomplete type"); Init = EmitNullConstant(D->getType()); } else { initializedGlobalDecl = GlobalDecl(D); emitter.emplace(*this); Init = emitter->tryEmitForInitializer(*InitDecl); if (!Init) { QualType T = InitExpr->getType(); if (D->getType()->isReferenceType()) T = D->getType(); if (getLangOpts().CPlusPlus) { Init = EmitNullConstant(T); NeedsGlobalCtor = true; } else { ErrorUnsupported(D, "static initializer"); Init = llvm::UndefValue::get(getTypes().ConvertType(T)); } } else { // We don't need an initializer, so remove the entry for the delayed // initializer position (just in case this entry was delayed) if we // also don't need to register a destructor. if (getLangOpts().CPlusPlus && !NeedsGlobalDtor) DelayedCXXInitPosition.erase(D); } } llvm::Type* InitType = Init->getType(); llvm::Constant *Entry = GetAddrOfGlobalVar(D, InitType, ForDefinition_t(!IsTentative)); // Strip off a bitcast if we got one back. if (auto *CE = dyn_cast(Entry)) { assert(CE->getOpcode() == llvm::Instruction::BitCast || CE->getOpcode() == llvm::Instruction::AddrSpaceCast || // All zero index gep. CE->getOpcode() == llvm::Instruction::GetElementPtr); Entry = CE->getOperand(0); } // Entry is now either a Function or GlobalVariable. auto *GV = dyn_cast(Entry); // We have a definition after a declaration with the wrong type. // We must make a new GlobalVariable* and update everything that used OldGV // (a declaration or tentative definition) with the new GlobalVariable* // (which will be a definition). // // This happens if there is a prototype for a global (e.g. // "extern int x[];") and then a definition of a different type (e.g. // "int x[10];"). This also happens when an initializer has a different type // from the type of the global (this happens with unions). if (!GV || GV->getType()->getElementType() != InitType || GV->getType()->getAddressSpace() != getContext().getTargetAddressSpace(GetGlobalVarAddressSpace(D))) { // Move the old entry aside so that we'll create a new one. Entry->setName(StringRef()); // Make a new global with the correct type, this is now guaranteed to work. GV = cast( GetAddrOfGlobalVar(D, InitType, ForDefinition_t(!IsTentative))); // Replace all uses of the old global with the new global llvm::Constant *NewPtrForOldDecl = llvm::ConstantExpr::getBitCast(GV, Entry->getType()); Entry->replaceAllUsesWith(NewPtrForOldDecl); // Erase the old global, since it is no longer used. cast(Entry)->eraseFromParent(); } MaybeHandleStaticInExternC(D, GV); if (D->hasAttr()) AddGlobalAnnotations(D, GV); // Set the llvm linkage type as appropriate. llvm::GlobalValue::LinkageTypes Linkage = getLLVMLinkageVarDefinition(D, GV->isConstant()); // CUDA B.2.1 "The __device__ qualifier declares a variable that resides on // the device. [...]" // CUDA B.2.2 "The __constant__ qualifier, optionally used together with // __device__, declares a variable that: [...] // Is accessible from all the threads within the grid and from the host // through the runtime library (cudaGetSymbolAddress() / cudaGetSymbolSize() // / cudaMemcpyToSymbol() / cudaMemcpyFromSymbol())." if (GV && LangOpts.CUDA) { if (LangOpts.CUDAIsDevice) { if (D->hasAttr() || D->hasAttr()) GV->setExternallyInitialized(true); } else { // Host-side shadows of external declarations of device-side // global variables become internal definitions. These have to // be internal in order to prevent name conflicts with global // host variables with the same name in a different TUs. if (D->hasAttr() || D->hasAttr()) { Linkage = llvm::GlobalValue::InternalLinkage; // Shadow variables and their properties must be registered // with CUDA runtime. unsigned Flags = 0; if (!D->hasDefinition()) Flags |= CGCUDARuntime::ExternDeviceVar; if (D->hasAttr()) Flags |= CGCUDARuntime::ConstantDeviceVar; getCUDARuntime().registerDeviceVar(*GV, Flags); } else if (D->hasAttr()) // __shared__ variables are odd. Shadows do get created, but // they are not registered with the CUDA runtime, so they // can't really be used to access their device-side // counterparts. It's not clear yet whether it's nvcc's bug or // a feature, but we've got to do the same for compatibility. Linkage = llvm::GlobalValue::InternalLinkage; } } GV->setInitializer(Init); if (emitter) emitter->finalize(GV); // If it is safe to mark the global 'constant', do so now. GV->setConstant(!NeedsGlobalCtor && !NeedsGlobalDtor && isTypeConstant(D->getType(), true)); // If it is in a read-only section, mark it 'constant'. if (const SectionAttr *SA = D->getAttr()) { const ASTContext::SectionInfo &SI = Context.SectionInfos[SA->getName()]; if ((SI.SectionFlags & ASTContext::PSF_Write) == 0) GV->setConstant(true); } GV->setAlignment(getContext().getDeclAlign(D).getQuantity()); // On Darwin, if the normal linkage of a C++ thread_local variable is // LinkOnce or Weak, we keep the normal linkage to prevent multiple // copies within a linkage unit; otherwise, the backing variable has // internal linkage and all accesses should just be calls to the // Itanium-specified entry point, which has the normal linkage of the // variable. This is to preserve the ability to change the implementation // behind the scenes. if (!D->isStaticLocal() && D->getTLSKind() == VarDecl::TLS_Dynamic && Context.getTargetInfo().getTriple().isOSDarwin() && !llvm::GlobalVariable::isLinkOnceLinkage(Linkage) && !llvm::GlobalVariable::isWeakLinkage(Linkage)) Linkage = llvm::GlobalValue::InternalLinkage; GV->setLinkage(Linkage); if (D->hasAttr()) GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass); else if (D->hasAttr()) GV->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass); else GV->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass); if (Linkage == llvm::GlobalVariable::CommonLinkage) { // common vars aren't constant even if declared const. GV->setConstant(false); // Tentative definition of global variables may be initialized with // non-zero null pointers. In this case they should have weak linkage // since common linkage must have zero initializer and must not have // explicit section therefore cannot have non-zero initial value. if (!GV->getInitializer()->isNullValue()) GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage); } setNonAliasAttributes(D, GV); if (D->getTLSKind() && !GV->isThreadLocal()) { if (D->getTLSKind() == VarDecl::TLS_Dynamic) CXXThreadLocals.push_back(D); setTLSMode(GV, *D); } maybeSetTrivialComdat(*D, *GV); // Emit the initializer function if necessary. if (NeedsGlobalCtor || NeedsGlobalDtor) EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor); SanitizerMD->reportGlobalToASan(GV, *D, NeedsGlobalCtor); // Emit global variable debug information. if (CGDebugInfo *DI = getModuleDebugInfo()) if (getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo) DI->EmitGlobalVariable(GV, D); } static bool isVarDeclStrongDefinition(const ASTContext &Context, CodeGenModule &CGM, const VarDecl *D, bool NoCommon) { // Don't give variables common linkage if -fno-common was specified unless it // was overridden by a NoCommon attribute. if ((NoCommon || D->hasAttr()) && !D->hasAttr()) return true; // C11 6.9.2/2: // A declaration of an identifier for an object that has file scope without // an initializer, and without a storage-class specifier or with the // storage-class specifier static, constitutes a tentative definition. if (D->getInit() || D->hasExternalStorage()) return true; // A variable cannot be both common and exist in a section. if (D->hasAttr()) return true; // A variable cannot be both common and exist in a section. // We don't try to determine which is the right section in the front-end. // If no specialized section name is applicable, it will resort to default. if (D->hasAttr() || D->hasAttr() || D->hasAttr()) return true; // Thread local vars aren't considered common linkage. if (D->getTLSKind()) return true; // Tentative definitions marked with WeakImportAttr are true definitions. if (D->hasAttr()) return true; // A variable cannot be both common and exist in a comdat. if (shouldBeInCOMDAT(CGM, *D)) return true; // Declarations with a required alignment do not have common linkage in MSVC // mode. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { if (D->hasAttr()) return true; QualType VarType = D->getType(); if (Context.isAlignmentRequired(VarType)) return true; if (const auto *RT = VarType->getAs()) { const RecordDecl *RD = RT->getDecl(); for (const FieldDecl *FD : RD->fields()) { if (FD->isBitField()) continue; if (FD->hasAttr()) return true; if (Context.isAlignmentRequired(FD->getType())) return true; } } } return false; } llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator( const DeclaratorDecl *D, GVALinkage Linkage, bool IsConstantVariable) { if (Linkage == GVA_Internal) return llvm::Function::InternalLinkage; if (D->hasAttr()) { if (IsConstantVariable) return llvm::GlobalVariable::WeakODRLinkage; else return llvm::GlobalVariable::WeakAnyLinkage; } // We are guaranteed to have a strong definition somewhere else, // so we can use available_externally linkage. if (Linkage == GVA_AvailableExternally) return llvm::GlobalValue::AvailableExternallyLinkage; // Note that Apple's kernel linker doesn't support symbol // coalescing, so we need to avoid linkonce and weak linkages there. // Normally, this means we just map to internal, but for explicit // instantiations we'll map to external. // In C++, the compiler has to emit a definition in every translation unit // that references the function. We should use linkonce_odr because // a) if all references in this translation unit are optimized away, we // don't need to codegen it. b) if the function persists, it needs to be // merged with other definitions. c) C++ has the ODR, so we know the // definition is dependable. if (Linkage == GVA_DiscardableODR) return !Context.getLangOpts().AppleKext ? llvm::Function::LinkOnceODRLinkage : llvm::Function::InternalLinkage; // An explicit instantiation of a template has weak linkage, since // explicit instantiations can occur in multiple translation units // and must all be equivalent. However, we are not allowed to // throw away these explicit instantiations. // // We don't currently support CUDA device code spread out across multiple TUs, // so say that CUDA templates are either external (for kernels) or internal. // This lets llvm perform aggressive inter-procedural optimizations. if (Linkage == GVA_StrongODR) { if (Context.getLangOpts().AppleKext) return llvm::Function::ExternalLinkage; if (Context.getLangOpts().CUDA && Context.getLangOpts().CUDAIsDevice) return D->hasAttr() ? llvm::Function::ExternalLinkage : llvm::Function::InternalLinkage; return llvm::Function::WeakODRLinkage; } // C++ doesn't have tentative definitions and thus cannot have common // linkage. if (!getLangOpts().CPlusPlus && isa(D) && !isVarDeclStrongDefinition(Context, *this, cast(D), CodeGenOpts.NoCommon)) return llvm::GlobalVariable::CommonLinkage; // selectany symbols are externally visible, so use weak instead of // linkonce. MSVC optimizes away references to const selectany globals, so // all definitions should be the same and ODR linkage should be used. // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx if (D->hasAttr()) return llvm::GlobalVariable::WeakODRLinkage; // Otherwise, we have strong external linkage. assert(Linkage == GVA_StrongExternal); return llvm::GlobalVariable::ExternalLinkage; } llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageVarDefinition( const VarDecl *VD, bool IsConstant) { GVALinkage Linkage = getContext().GetGVALinkageForVariable(VD); return getLLVMLinkageForDeclarator(VD, Linkage, IsConstant); } /// Replace the uses of a function that was declared with a non-proto type. /// We want to silently drop extra arguments from call sites static void replaceUsesOfNonProtoConstant(llvm::Constant *old, llvm::Function *newFn) { // Fast path. if (old->use_empty()) return; llvm::Type *newRetTy = newFn->getReturnType(); SmallVector newArgs; SmallVector newBundles; for (llvm::Value::use_iterator ui = old->use_begin(), ue = old->use_end(); ui != ue; ) { llvm::Value::use_iterator use = ui++; // Increment before the use is erased. llvm::User *user = use->getUser(); // Recognize and replace uses of bitcasts. Most calls to // unprototyped functions will use bitcasts. if (auto *bitcast = dyn_cast(user)) { if (bitcast->getOpcode() == llvm::Instruction::BitCast) replaceUsesOfNonProtoConstant(bitcast, newFn); continue; } // Recognize calls to the function. llvm::CallSite callSite(user); if (!callSite) continue; if (!callSite.isCallee(&*use)) continue; // If the return types don't match exactly, then we can't // transform this call unless it's dead. if (callSite->getType() != newRetTy && !callSite->use_empty()) continue; // Get the call site's attribute list. SmallVector newArgAttrs; llvm::AttributeList oldAttrs = callSite.getAttributes(); // If the function was passed too few arguments, don't transform. unsigned newNumArgs = newFn->arg_size(); if (callSite.arg_size() < newNumArgs) continue; // If extra arguments were passed, we silently drop them. // If any of the types mismatch, we don't transform. unsigned argNo = 0; bool dontTransform = false; for (llvm::Argument &A : newFn->args()) { if (callSite.getArgument(argNo)->getType() != A.getType()) { dontTransform = true; break; } // Add any parameter attributes. newArgAttrs.push_back(oldAttrs.getParamAttributes(argNo)); argNo++; } if (dontTransform) continue; // Okay, we can transform this. Create the new call instruction and copy // over the required information. newArgs.append(callSite.arg_begin(), callSite.arg_begin() + argNo); // Copy over any operand bundles. callSite.getOperandBundlesAsDefs(newBundles); llvm::CallSite newCall; if (callSite.isCall()) { newCall = llvm::CallInst::Create(newFn, newArgs, newBundles, "", callSite.getInstruction()); } else { auto *oldInvoke = cast(callSite.getInstruction()); newCall = llvm::InvokeInst::Create(newFn, oldInvoke->getNormalDest(), oldInvoke->getUnwindDest(), newArgs, newBundles, "", callSite.getInstruction()); } newArgs.clear(); // for the next iteration if (!newCall->getType()->isVoidTy()) newCall->takeName(callSite.getInstruction()); newCall.setAttributes(llvm::AttributeList::get( newFn->getContext(), oldAttrs.getFnAttributes(), oldAttrs.getRetAttributes(), newArgAttrs)); newCall.setCallingConv(callSite.getCallingConv()); // Finally, remove the old call, replacing any uses with the new one. if (!callSite->use_empty()) callSite->replaceAllUsesWith(newCall.getInstruction()); // Copy debug location attached to CI. if (callSite->getDebugLoc()) newCall->setDebugLoc(callSite->getDebugLoc()); callSite->eraseFromParent(); } } /// ReplaceUsesOfNonProtoTypeWithRealFunction - This function is called when we /// implement a function with no prototype, e.g. "int foo() {}". If there are /// existing call uses of the old function in the module, this adjusts them to /// call the new function directly. /// /// This is not just a cleanup: the always_inline pass requires direct calls to /// functions to be able to inline them. If there is a bitcast in the way, it /// won't inline them. Instcombine normally deletes these calls, but it isn't /// run at -O0. static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, llvm::Function *NewFn) { // If we're redefining a global as a function, don't transform it. if (!isa(Old)) return; replaceUsesOfNonProtoConstant(Old, NewFn); } void CodeGenModule::HandleCXXStaticMemberVarInstantiation(VarDecl *VD) { auto DK = VD->isThisDeclarationADefinition(); if (DK == VarDecl::Definition && VD->hasAttr()) return; TemplateSpecializationKind TSK = VD->getTemplateSpecializationKind(); // If we have a definition, this might be a deferred decl. If the // instantiation is explicit, make sure we emit it at the end. if (VD->getDefinition() && TSK == TSK_ExplicitInstantiationDefinition) GetAddrOfGlobalVar(VD); EmitTopLevelDecl(VD); } void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, llvm::GlobalValue *GV) { const auto *D = cast(GD.getDecl()); // Compute the function info and LLVM type. const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); // Get or create the prototype for the function. if (!GV || (GV->getType()->getElementType() != Ty)) GV = cast(GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer=*/true, ForDefinition)); // Already emitted. if (!GV->isDeclaration()) return; // We need to set linkage and visibility on the function before // generating code for it because various parts of IR generation // want to propagate this information down (e.g. to local static // declarations). auto *Fn = cast(GV); setFunctionLinkage(GD, Fn); // FIXME: this is redundant with part of setFunctionDefinitionAttributes setGVProperties(Fn, GD); MaybeHandleStaticInExternC(D, Fn); maybeSetTrivialComdat(*D, *Fn); CodeGenFunction(*this).GenerateCode(D, Fn, FI); setNonAliasAttributes(GD, Fn); SetLLVMFunctionAttributesForDefinition(D, Fn); if (const ConstructorAttr *CA = D->getAttr()) AddGlobalCtor(Fn, CA->getPriority()); if (const DestructorAttr *DA = D->getAttr()) AddGlobalDtor(Fn, DA->getPriority()); if (D->hasAttr()) AddGlobalAnnotations(D, Fn); if (D->isCPUSpecificMultiVersion()) { auto *Spec = D->getAttr(); // If there is another specific version we need to emit, do so here. if (Spec->ActiveArgIndex + 1 < Spec->cpus_size()) { ++Spec->ActiveArgIndex; EmitGlobalFunctionDefinition(GD, nullptr); } } } void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { const auto *D = cast(GD.getDecl()); const AliasAttr *AA = D->getAttr(); assert(AA && "Not an alias?"); StringRef MangledName = getMangledName(GD); if (AA->getAliasee() == MangledName) { Diags.Report(AA->getLocation(), diag::err_cyclic_alias) << 0; return; } // If there is a definition in the module, then it wins over the alias. // This is dubious, but allow it to be safe. Just ignore the alias. llvm::GlobalValue *Entry = GetGlobalValue(MangledName); if (Entry && !Entry->isDeclaration()) return; Aliases.push_back(GD); llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType()); // Create a reference to the named value. This ensures that it is emitted // if a deferred decl. llvm::Constant *Aliasee; if (isa(DeclTy)) Aliasee = GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, GD, /*ForVTable=*/false); else Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(), llvm::PointerType::getUnqual(DeclTy), /*D=*/nullptr); // Create the new alias itself, but don't set a name yet. auto *GA = llvm::GlobalAlias::create( DeclTy, 0, llvm::Function::ExternalLinkage, "", Aliasee, &getModule()); if (Entry) { if (GA->getAliasee() == Entry) { Diags.Report(AA->getLocation(), diag::err_cyclic_alias) << 0; return; } assert(Entry->isDeclaration()); // If there is a declaration in the module, then we had an extern followed // by the alias, as in: // extern int test6(); // ... // int test6() __attribute__((alias("test7"))); // // Remove it and replace uses of it with the alias. GA->takeName(Entry); Entry->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GA, Entry->getType())); Entry->eraseFromParent(); } else { GA->setName(MangledName); } // Set attributes which are particular to an alias; this is a // specialization of the attributes which may be set on a global // variable/function. if (D->hasAttr() || D->hasAttr() || D->isWeakImported()) { GA->setLinkage(llvm::Function::WeakAnyLinkage); } if (const auto *VD = dyn_cast(D)) if (VD->getTLSKind()) setTLSMode(GA, *VD); SetCommonAttributes(GD, GA); } void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) { const auto *D = cast(GD.getDecl()); const IFuncAttr *IFA = D->getAttr(); assert(IFA && "Not an ifunc?"); StringRef MangledName = getMangledName(GD); if (IFA->getResolver() == MangledName) { Diags.Report(IFA->getLocation(), diag::err_cyclic_alias) << 1; return; } // Report an error if some definition overrides ifunc. llvm::GlobalValue *Entry = GetGlobalValue(MangledName); if (Entry && !Entry->isDeclaration()) { GlobalDecl OtherGD; if (lookupRepresentativeDecl(MangledName, OtherGD) && DiagnosedConflictingDefinitions.insert(GD).second) { Diags.Report(D->getLocation(), diag::err_duplicate_mangled_name) << MangledName; Diags.Report(OtherGD.getDecl()->getLocation(), diag::note_previous_definition); } return; } Aliases.push_back(GD); llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType()); llvm::Constant *Resolver = GetOrCreateLLVMFunction(IFA->getResolver(), DeclTy, GD, /*ForVTable=*/false); llvm::GlobalIFunc *GIF = llvm::GlobalIFunc::create(DeclTy, 0, llvm::Function::ExternalLinkage, "", Resolver, &getModule()); if (Entry) { if (GIF->getResolver() == Entry) { Diags.Report(IFA->getLocation(), diag::err_cyclic_alias) << 1; return; } assert(Entry->isDeclaration()); // If there is a declaration in the module, then we had an extern followed // by the ifunc, as in: // extern int test(); // ... // int test() __attribute__((ifunc("resolver"))); // // Remove it and replace uses of it with the ifunc. GIF->takeName(Entry); Entry->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GIF, Entry->getType())); Entry->eraseFromParent(); } else GIF->setName(MangledName); SetCommonAttributes(GD, GIF); } llvm::Function *CodeGenModule::getIntrinsic(unsigned IID, ArrayRef Tys) { return llvm::Intrinsic::getDeclaration(&getModule(), (llvm::Intrinsic::ID)IID, Tys); } static llvm::StringMapEntry & GetConstantCFStringEntry(llvm::StringMap &Map, const StringLiteral *Literal, bool TargetIsLSB, bool &IsUTF16, unsigned &StringLength) { StringRef String = Literal->getString(); unsigned NumBytes = String.size(); // Check for simple case. if (!Literal->containsNonAsciiOrNull()) { StringLength = NumBytes; return *Map.insert(std::make_pair(String, nullptr)).first; } // Otherwise, convert the UTF8 literals into a string of shorts. IsUTF16 = true; SmallVector ToBuf(NumBytes + 1); // +1 for ending nulls. const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)String.data(); llvm::UTF16 *ToPtr = &ToBuf[0]; (void)llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, &ToPtr, ToPtr + NumBytes, llvm::strictConversion); // ConvertUTF8toUTF16 returns the length in ToPtr. StringLength = ToPtr - &ToBuf[0]; // Add an explicit null. *ToPtr = 0; return *Map.insert(std::make_pair( StringRef(reinterpret_cast(ToBuf.data()), (StringLength + 1) * 2), nullptr)).first; } ConstantAddress CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { unsigned StringLength = 0; bool isUTF16 = false; llvm::StringMapEntry &Entry = GetConstantCFStringEntry(CFConstantStringMap, Literal, getDataLayout().isLittleEndian(), isUTF16, StringLength); if (auto *C = Entry.second) return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment())); llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty); llvm::Constant *Zeros[] = { Zero, Zero }; // If we don't already have it, get __CFConstantStringClassReference. if (!CFConstantStringClassRef) { llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy); Ty = llvm::ArrayType::get(Ty, 0); llvm::GlobalValue *GV = cast( CreateRuntimeVariable(Ty, "__CFConstantStringClassReference")); if (getTriple().isOSBinFormatCOFF()) { IdentifierInfo &II = getContext().Idents.get(GV->getName()); TranslationUnitDecl *TUDecl = getContext().getTranslationUnitDecl(); DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl); const VarDecl *VD = nullptr; for (const auto &Result : DC->lookup(&II)) if ((VD = dyn_cast(Result))) break; if (!VD || !VD->hasAttr()) { GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); GV->setLinkage(llvm::GlobalValue::ExternalLinkage); } else { GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); GV->setLinkage(llvm::GlobalValue::ExternalLinkage); } } setDSOLocal(GV); // Decay array -> ptr CFConstantStringClassRef = llvm::ConstantExpr::getGetElementPtr(Ty, GV, Zeros); } QualType CFTy = getContext().getCFConstantStringType(); auto *STy = cast(getTypes().ConvertType(CFTy)); ConstantInitBuilder Builder(*this); auto Fields = Builder.beginStruct(STy); // Class pointer. Fields.add(cast(CFConstantStringClassRef)); // Flags. Fields.addInt(IntTy, isUTF16 ? 0x07d0 : 0x07C8); // String pointer. llvm::Constant *C = nullptr; if (isUTF16) { auto Arr = llvm::makeArrayRef( reinterpret_cast(const_cast(Entry.first().data())), Entry.first().size() / 2); C = llvm::ConstantDataArray::get(VMContext, Arr); } else { C = llvm::ConstantDataArray::getString(VMContext, Entry.first()); } // Note: -fwritable-strings doesn't make the backing store strings of // CFStrings writable. (See ) auto *GV = new llvm::GlobalVariable(getModule(), C->getType(), /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, C, ".str"); GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); // Don't enforce the target's minimum global alignment, since the only use // of the string is via this class initializer. CharUnits Align = isUTF16 ? getContext().getTypeAlignInChars(getContext().ShortTy) : getContext().getTypeAlignInChars(getContext().CharTy); GV->setAlignment(Align.getQuantity()); // FIXME: We set the section explicitly to avoid a bug in ld64 224.1. // Without it LLVM can merge the string with a non unnamed_addr one during // LTO. Doing that changes the section it ends in, which surprises ld64. if (getTriple().isOSBinFormatMachO()) GV->setSection(isUTF16 ? "__TEXT,__ustring" : "__TEXT,__cstring,cstring_literals"); // String. llvm::Constant *Str = llvm::ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Zeros); if (isUTF16) // Cast the UTF16 string to the correct type. Str = llvm::ConstantExpr::getBitCast(Str, Int8PtrTy); Fields.add(Str); // String length. auto Ty = getTypes().ConvertType(getContext().LongTy); Fields.addInt(cast(Ty), StringLength); CharUnits Alignment = getPointerAlign(); // The struct. GV = Fields.finishAndCreateGlobal("_unnamed_cfstring_", Alignment, /*isConstant=*/false, llvm::GlobalVariable::PrivateLinkage); switch (getTriple().getObjectFormat()) { case llvm::Triple::UnknownObjectFormat: llvm_unreachable("unknown file format"); case llvm::Triple::COFF: case llvm::Triple::ELF: case llvm::Triple::Wasm: GV->setSection("cfstring"); break; case llvm::Triple::MachO: GV->setSection("__DATA,__cfstring"); break; } Entry.second = GV; return ConstantAddress(GV, Alignment); } bool CodeGenModule::getExpressionLocationsEnabled() const { return !CodeGenOpts.EmitCodeView || CodeGenOpts.DebugColumnInfo; } QualType CodeGenModule::getObjCFastEnumerationStateType() { if (ObjCFastEnumerationStateType.isNull()) { RecordDecl *D = Context.buildImplicitRecord("__objcFastEnumerationState"); D->startDefinition(); QualType FieldTypes[] = { Context.UnsignedLongTy, Context.getPointerType(Context.getObjCIdType()), Context.getPointerType(Context.UnsignedLongTy), Context.getConstantArrayType(Context.UnsignedLongTy, llvm::APInt(32, 5), ArrayType::Normal, 0) }; for (size_t i = 0; i < 4; ++i) { FieldDecl *Field = FieldDecl::Create(Context, D, SourceLocation(), SourceLocation(), nullptr, FieldTypes[i], /*TInfo=*/nullptr, /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); D->addDecl(Field); } D->completeDefinition(); ObjCFastEnumerationStateType = Context.getTagDeclType(D); } return ObjCFastEnumerationStateType; } llvm::Constant * CodeGenModule::GetConstantArrayFromStringLiteral(const StringLiteral *E) { assert(!E->getType()->isPointerType() && "Strings are always arrays"); // Don't emit it as the address of the string, emit the string data itself // as an inline array. if (E->getCharByteWidth() == 1) { SmallString<64> Str(E->getString()); // Resize the string to the right size, which is indicated by its type. const ConstantArrayType *CAT = Context.getAsConstantArrayType(E->getType()); Str.resize(CAT->getSize().getZExtValue()); return llvm::ConstantDataArray::getString(VMContext, Str, false); } auto *AType = cast(getTypes().ConvertType(E->getType())); llvm::Type *ElemTy = AType->getElementType(); unsigned NumElements = AType->getNumElements(); // Wide strings have either 2-byte or 4-byte elements. if (ElemTy->getPrimitiveSizeInBits() == 16) { SmallVector Elements; Elements.reserve(NumElements); for(unsigned i = 0, e = E->getLength(); i != e; ++i) Elements.push_back(E->getCodeUnit(i)); Elements.resize(NumElements); return llvm::ConstantDataArray::get(VMContext, Elements); } assert(ElemTy->getPrimitiveSizeInBits() == 32); SmallVector Elements; Elements.reserve(NumElements); for(unsigned i = 0, e = E->getLength(); i != e; ++i) Elements.push_back(E->getCodeUnit(i)); Elements.resize(NumElements); return llvm::ConstantDataArray::get(VMContext, Elements); } static llvm::GlobalVariable * GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT, CodeGenModule &CGM, StringRef GlobalName, CharUnits Alignment) { unsigned AddrSpace = CGM.getContext().getTargetAddressSpace( CGM.getStringLiteralAddressSpace()); llvm::Module &M = CGM.getModule(); // Create a global variable for this string auto *GV = new llvm::GlobalVariable( M, C->getType(), !CGM.getLangOpts().WritableStrings, LT, C, GlobalName, nullptr, llvm::GlobalVariable::NotThreadLocal, AddrSpace); GV->setAlignment(Alignment.getQuantity()); GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); if (GV->isWeakForLinker()) { assert(CGM.supportsCOMDAT() && "Only COFF uses weak string literals"); GV->setComdat(M.getOrInsertComdat(GV->getName())); } CGM.setDSOLocal(GV); return GV; } /// GetAddrOfConstantStringFromLiteral - Return a pointer to a /// constant array for the given string literal. ConstantAddress CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S, StringRef Name) { CharUnits Alignment = getContext().getAlignOfGlobalVarInChars(S->getType()); llvm::Constant *C = GetConstantArrayFromStringLiteral(S); llvm::GlobalVariable **Entry = nullptr; if (!LangOpts.WritableStrings) { Entry = &ConstantStringMap[C]; if (auto GV = *Entry) { if (Alignment.getQuantity() > GV->getAlignment()) GV->setAlignment(Alignment.getQuantity()); return ConstantAddress(GV, Alignment); } } SmallString<256> MangledNameBuffer; StringRef GlobalVariableName; llvm::GlobalValue::LinkageTypes LT; // Mangle the string literal if the ABI allows for it. However, we cannot // do this if we are compiling with ASan or -fwritable-strings because they // rely on strings having normal linkage. if (!LangOpts.WritableStrings && !LangOpts.Sanitize.has(SanitizerKind::Address) && getCXXABI().getMangleContext().shouldMangleStringLiteral(S)) { llvm::raw_svector_ostream Out(MangledNameBuffer); getCXXABI().getMangleContext().mangleStringLiteral(S, Out); LT = llvm::GlobalValue::LinkOnceODRLinkage; GlobalVariableName = MangledNameBuffer; } else { LT = llvm::GlobalValue::PrivateLinkage; GlobalVariableName = Name; } auto GV = GenerateStringLiteral(C, LT, *this, GlobalVariableName, Alignment); if (Entry) *Entry = GV; SanitizerMD->reportGlobalToASan(GV, S->getStrTokenLoc(0), "", QualType()); return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV), Alignment); } /// GetAddrOfConstantStringFromObjCEncode - Return a pointer to a constant /// array for the given ObjCEncodeExpr node. ConstantAddress CodeGenModule::GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *E) { std::string Str; getContext().getObjCEncodingForType(E->getEncodedType(), Str); return GetAddrOfConstantCString(Str); } /// GetAddrOfConstantCString - Returns a pointer to a character array containing /// the literal and a terminating '\0' character. /// The result has pointer to array type. ConstantAddress CodeGenModule::GetAddrOfConstantCString( const std::string &Str, const char *GlobalName) { StringRef StrWithNull(Str.c_str(), Str.size() + 1); CharUnits Alignment = getContext().getAlignOfGlobalVarInChars(getContext().CharTy); llvm::Constant *C = llvm::ConstantDataArray::getString(getLLVMContext(), StrWithNull, false); // Don't share any string literals if strings aren't constant. llvm::GlobalVariable **Entry = nullptr; if (!LangOpts.WritableStrings) { Entry = &ConstantStringMap[C]; if (auto GV = *Entry) { if (Alignment.getQuantity() > GV->getAlignment()) GV->setAlignment(Alignment.getQuantity()); return ConstantAddress(GV, Alignment); } } // Get the default prefix if a name wasn't specified. if (!GlobalName) GlobalName = ".str"; // Create a global variable for this. auto GV = GenerateStringLiteral(C, llvm::GlobalValue::PrivateLinkage, *this, GlobalName, Alignment); if (Entry) *Entry = GV; return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV), Alignment); } ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( const MaterializeTemporaryExpr *E, const Expr *Init) { assert((E->getStorageDuration() == SD_Static || E->getStorageDuration() == SD_Thread) && "not a global temporary"); const auto *VD = cast(E->getExtendingDecl()); // If we're not materializing a subobject of the temporary, keep the // cv-qualifiers from the type of the MaterializeTemporaryExpr. QualType MaterializedType = Init->getType(); if (Init == E->GetTemporaryExpr()) MaterializedType = E->getType(); CharUnits Align = getContext().getTypeAlignInChars(MaterializedType); if (llvm::Constant *Slot = MaterializedGlobalTemporaryMap[E]) return ConstantAddress(Slot, Align); // FIXME: If an externally-visible declaration extends multiple temporaries, // we need to give each temporary the same name in every translation unit (and // we also need to make the temporaries externally-visible). SmallString<256> Name; llvm::raw_svector_ostream Out(Name); getCXXABI().getMangleContext().mangleReferenceTemporary( VD, E->getManglingNumber(), Out); APValue *Value = nullptr; if (E->getStorageDuration() == SD_Static) { // We might have a cached constant initializer for this temporary. Note // that this might have a different value from the value computed by // evaluating the initializer if the surrounding constant expression // modifies the temporary. Value = getContext().getMaterializedTemporaryValue(E, false); if (Value && Value->isUninit()) Value = nullptr; } // Try evaluating it now, it might have a constant initializer. Expr::EvalResult EvalResult; if (!Value && Init->EvaluateAsRValue(EvalResult, getContext()) && !EvalResult.hasSideEffects()) Value = &EvalResult.Val; LangAS AddrSpace = VD ? GetGlobalVarAddressSpace(VD) : MaterializedType.getAddressSpace(); Optional emitter; llvm::Constant *InitialValue = nullptr; bool Constant = false; llvm::Type *Type; if (Value) { // The temporary has a constant initializer, use it. emitter.emplace(*this); InitialValue = emitter->emitForInitializer(*Value, AddrSpace, MaterializedType); Constant = isTypeConstant(MaterializedType, /*ExcludeCtor*/Value); Type = InitialValue->getType(); } else { // No initializer, the initialization will be provided when we // initialize the declaration which performed lifetime extension. Type = getTypes().ConvertTypeForMem(MaterializedType); } // Create a global variable for this lifetime-extended temporary. llvm::GlobalValue::LinkageTypes Linkage = getLLVMLinkageVarDefinition(VD, Constant); if (Linkage == llvm::GlobalVariable::ExternalLinkage) { const VarDecl *InitVD; if (VD->isStaticDataMember() && VD->getAnyInitializer(InitVD) && isa(InitVD->getLexicalDeclContext())) { // Temporaries defined inside a class get linkonce_odr linkage because the // class can be defined in multiple translation units. Linkage = llvm::GlobalVariable::LinkOnceODRLinkage; } else { // There is no need for this temporary to have external linkage if the // VarDecl has external linkage. Linkage = llvm::GlobalVariable::InternalLinkage; } } auto TargetAS = getContext().getTargetAddressSpace(AddrSpace); auto *GV = new llvm::GlobalVariable( getModule(), Type, Constant, Linkage, InitialValue, Name.c_str(), /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS); if (emitter) emitter->finalize(GV); setGVProperties(GV, VD); GV->setAlignment(Align.getQuantity()); if (supportsCOMDAT() && GV->isWeakForLinker()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); if (VD->getTLSKind()) setTLSMode(GV, *VD); llvm::Constant *CV = GV; if (AddrSpace != LangAS::Default) CV = getTargetCodeGenInfo().performAddrSpaceCast( *this, GV, AddrSpace, LangAS::Default, Type->getPointerTo( getContext().getTargetAddressSpace(LangAS::Default))); MaterializedGlobalTemporaryMap[E] = CV; return ConstantAddress(CV, Align); } /// EmitObjCPropertyImplementations - Emit information for synthesized /// properties for an implementation. void CodeGenModule::EmitObjCPropertyImplementations(const ObjCImplementationDecl *D) { for (const auto *PID : D->property_impls()) { // Dynamic is just for type-checking. if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) { ObjCPropertyDecl *PD = PID->getPropertyDecl(); // Determine which methods need to be implemented, some may have // been overridden. Note that ::isPropertyAccessor is not the method // we want, that just indicates if the decl came from a // property. What we want to know is if the method is defined in // this implementation. if (!D->getInstanceMethod(PD->getGetterName())) CodeGenFunction(*this).GenerateObjCGetter( const_cast(D), PID); if (!PD->isReadOnly() && !D->getInstanceMethod(PD->getSetterName())) CodeGenFunction(*this).GenerateObjCSetter( const_cast(D), PID); } } } static bool needsDestructMethod(ObjCImplementationDecl *impl) { const ObjCInterfaceDecl *iface = impl->getClassInterface(); for (const ObjCIvarDecl *ivar = iface->all_declared_ivar_begin(); ivar; ivar = ivar->getNextIvar()) if (ivar->getType().isDestructedType()) return true; return false; } static bool AllTrivialInitializers(CodeGenModule &CGM, ObjCImplementationDecl *D) { CodeGenFunction CGF(CGM); for (ObjCImplementationDecl::init_iterator B = D->init_begin(), E = D->init_end(); B != E; ++B) { CXXCtorInitializer *CtorInitExp = *B; Expr *Init = CtorInitExp->getInit(); if (!CGF.isTrivialInitializer(Init)) return false; } return true; } /// EmitObjCIvarInitializations - Emit information for ivar initialization /// for an implementation. void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) { // We might need a .cxx_destruct even if we don't have any ivar initializers. if (needsDestructMethod(D)) { IdentifierInfo *II = &getContext().Idents.get(".cxx_destruct"); Selector cxxSelector = getContext().Selectors.getSelector(0, &II); ObjCMethodDecl *DTORMethod = ObjCMethodDecl::Create(getContext(), D->getLocation(), D->getLocation(), cxxSelector, getContext().VoidTy, nullptr, D, /*isInstance=*/true, /*isVariadic=*/false, /*isPropertyAccessor=*/true, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCMethodDecl::Required); D->addInstanceMethod(DTORMethod); CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false); D->setHasDestructors(true); } // If the implementation doesn't have any ivar initializers, we don't need // a .cxx_construct. if (D->getNumIvarInitializers() == 0 || AllTrivialInitializers(*this, D)) return; IdentifierInfo *II = &getContext().Idents.get(".cxx_construct"); Selector cxxSelector = getContext().Selectors.getSelector(0, &II); // The constructor returns 'self'. ObjCMethodDecl *CTORMethod = ObjCMethodDecl::Create(getContext(), D->getLocation(), D->getLocation(), cxxSelector, getContext().getObjCIdType(), nullptr, D, /*isInstance=*/true, /*isVariadic=*/false, /*isPropertyAccessor=*/true, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCMethodDecl::Required); D->addInstanceMethod(CTORMethod); CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true); D->setHasNonZeroConstructors(true); } // EmitLinkageSpec - Emit all declarations in a linkage spec. void CodeGenModule::EmitLinkageSpec(const LinkageSpecDecl *LSD) { if (LSD->getLanguage() != LinkageSpecDecl::lang_c && LSD->getLanguage() != LinkageSpecDecl::lang_cxx) { ErrorUnsupported(LSD, "linkage spec"); return; } EmitDeclContext(LSD); } void CodeGenModule::EmitDeclContext(const DeclContext *DC) { for (auto *I : DC->decls()) { // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope // are themselves considered "top-level", so EmitTopLevelDecl on an // ObjCImplDecl does not recursively visit them. We need to do that in // case they're nested inside another construct (LinkageSpecDecl / // ExportDecl) that does stop them from being considered "top-level". if (auto *OID = dyn_cast(I)) { for (auto *M : OID->methods()) EmitTopLevelDecl(M); } EmitTopLevelDecl(I); } } /// EmitTopLevelDecl - Emit code for a single top level declaration. void CodeGenModule::EmitTopLevelDecl(Decl *D) { // Ignore dependent declarations. if (D->isTemplated()) return; switch (D->getKind()) { case Decl::CXXConversion: case Decl::CXXMethod: case Decl::Function: EmitGlobal(cast(D)); // Always provide some coverage mapping // even for the functions that aren't emitted. AddDeferredUnusedCoverageMapping(D); break; case Decl::CXXDeductionGuide: // Function-like, but does not result in code emission. break; case Decl::Var: case Decl::Decomposition: case Decl::VarTemplateSpecialization: EmitGlobal(cast(D)); if (auto *DD = dyn_cast(D)) for (auto *B : DD->bindings()) if (auto *HD = B->getHoldingVar()) EmitGlobal(HD); break; // Indirect fields from global anonymous structs and unions can be // ignored; only the actual variable requires IR gen support. case Decl::IndirectField: break; // C++ Decls case Decl::Namespace: EmitDeclContext(cast(D)); break; case Decl::ClassTemplateSpecialization: { const auto *Spec = cast(D); if (DebugInfo && Spec->getSpecializationKind() == TSK_ExplicitInstantiationDefinition && Spec->hasDefinition()) DebugInfo->completeTemplateDefinition(*Spec); } LLVM_FALLTHROUGH; case Decl::CXXRecord: if (DebugInfo) { if (auto *ES = D->getASTContext().getExternalSource()) if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never) DebugInfo->completeUnusedClass(cast(*D)); } // Emit any static data members, they may be definitions. for (auto *I : cast(D)->decls()) if (isa(I) || isa(I)) EmitTopLevelDecl(I); break; // No code generation needed. case Decl::UsingShadow: case Decl::ClassTemplate: case Decl::VarTemplate: case Decl::VarTemplatePartialSpecialization: case Decl::FunctionTemplate: case Decl::TypeAliasTemplate: case Decl::Block: case Decl::Empty: break; case Decl::Using: // using X; [C++] if (CGDebugInfo *DI = getModuleDebugInfo()) DI->EmitUsingDecl(cast(*D)); return; case Decl::NamespaceAlias: if (CGDebugInfo *DI = getModuleDebugInfo()) DI->EmitNamespaceAlias(cast(*D)); return; case Decl::UsingDirective: // using namespace X; [C++] if (CGDebugInfo *DI = getModuleDebugInfo()) DI->EmitUsingDirective(cast(*D)); return; case Decl::CXXConstructor: getCXXABI().EmitCXXConstructors(cast(D)); break; case Decl::CXXDestructor: getCXXABI().EmitCXXDestructors(cast(D)); break; case Decl::StaticAssert: // Nothing to do. break; // Objective-C Decls // Forward declarations, no (immediate) code generation. case Decl::ObjCInterface: case Decl::ObjCCategory: break; case Decl::ObjCProtocol: { auto *Proto = cast(D); if (Proto->isThisDeclarationADefinition()) ObjCRuntime->GenerateProtocol(Proto); break; } case Decl::ObjCCategoryImpl: // Categories have properties but don't support synthesize so we // can ignore them here. ObjCRuntime->GenerateCategory(cast(D)); break; case Decl::ObjCImplementation: { auto *OMD = cast(D); EmitObjCPropertyImplementations(OMD); EmitObjCIvarInitializations(OMD); ObjCRuntime->GenerateClass(OMD); // Emit global variable debug information. if (CGDebugInfo *DI = getModuleDebugInfo()) if (getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo) DI->getOrCreateInterfaceType(getContext().getObjCInterfaceType( OMD->getClassInterface()), OMD->getLocation()); break; } case Decl::ObjCMethod: { auto *OMD = cast(D); // If this is not a prototype, emit the body. if (OMD->getBody()) CodeGenFunction(*this).GenerateObjCMethod(OMD); break; } case Decl::ObjCCompatibleAlias: ObjCRuntime->RegisterAlias(cast(D)); break; case Decl::PragmaComment: { const auto *PCD = cast(D); switch (PCD->getCommentKind()) { case PCK_Unknown: llvm_unreachable("unexpected pragma comment kind"); case PCK_Linker: AppendLinkerOptions(PCD->getArg()); break; case PCK_Lib: if (getTarget().getTriple().isOSBinFormatELF() && !getTarget().getTriple().isPS4()) AddELFLibDirective(PCD->getArg()); else AddDependentLib(PCD->getArg()); break; case PCK_Compiler: case PCK_ExeStr: case PCK_User: break; // We ignore all of these. } break; } case Decl::PragmaDetectMismatch: { const auto *PDMD = cast(D); AddDetectMismatch(PDMD->getName(), PDMD->getValue()); break; } case Decl::LinkageSpec: EmitLinkageSpec(cast(D)); break; case Decl::FileScopeAsm: { // File-scope asm is ignored during device-side CUDA compilation. if (LangOpts.CUDA && LangOpts.CUDAIsDevice) break; // File-scope asm is ignored during device-side OpenMP compilation. if (LangOpts.OpenMPIsDevice) break; auto *AD = cast(D); getModule().appendModuleInlineAsm(AD->getAsmString()->getString()); break; } case Decl::Import: { auto *Import = cast(D); // If we've already imported this module, we're done. if (!ImportedModules.insert(Import->getImportedModule())) break; // Emit debug information for direct imports. if (!Import->getImportedOwningModule()) { if (CGDebugInfo *DI = getModuleDebugInfo()) DI->EmitImportDecl(*Import); } // Find all of the submodules and emit the module initializers. llvm::SmallPtrSet Visited; SmallVector Stack; Visited.insert(Import->getImportedModule()); Stack.push_back(Import->getImportedModule()); while (!Stack.empty()) { clang::Module *Mod = Stack.pop_back_val(); if (!EmittedModuleInitializers.insert(Mod).second) continue; for (auto *D : Context.getModuleInitializers(Mod)) EmitTopLevelDecl(D); // Visit the submodules of this module. for (clang::Module::submodule_iterator Sub = Mod->submodule_begin(), SubEnd = Mod->submodule_end(); Sub != SubEnd; ++Sub) { // Skip explicit children; they need to be explicitly imported to emit // the initializers. if ((*Sub)->IsExplicit) continue; if (Visited.insert(*Sub).second) Stack.push_back(*Sub); } } break; } case Decl::Export: EmitDeclContext(cast(D)); break; case Decl::OMPThreadPrivate: EmitOMPThreadPrivateDecl(cast(D)); break; case Decl::OMPDeclareReduction: EmitOMPDeclareReduction(cast(D)); break; default: // Make sure we handled everything we should, every other kind is a // non-top-level decl. FIXME: Would be nice to have an isTopLevelDeclKind // function. Need to recode Decl::Kind to do that easily. assert(isa(D) && "Unsupported decl kind"); break; } } void CodeGenModule::AddDeferredUnusedCoverageMapping(Decl *D) { // Do we need to generate coverage mapping? if (!CodeGenOpts.CoverageMapping) return; switch (D->getKind()) { case Decl::CXXConversion: case Decl::CXXMethod: case Decl::Function: case Decl::ObjCMethod: case Decl::CXXConstructor: case Decl::CXXDestructor: { if (!cast(D)->doesThisDeclarationHaveABody()) return; SourceManager &SM = getContext().getSourceManager(); if (LimitedCoverage && SM.getMainFileID() != SM.getFileID(D->getLocStart())) return; auto I = DeferredEmptyCoverageMappingDecls.find(D); if (I == DeferredEmptyCoverageMappingDecls.end()) DeferredEmptyCoverageMappingDecls[D] = true; break; } default: break; }; } void CodeGenModule::ClearUnusedCoverageMapping(const Decl *D) { // Do we need to generate coverage mapping? if (!CodeGenOpts.CoverageMapping) return; if (const auto *Fn = dyn_cast(D)) { if (Fn->isTemplateInstantiation()) ClearUnusedCoverageMapping(Fn->getTemplateInstantiationPattern()); } auto I = DeferredEmptyCoverageMappingDecls.find(D); if (I == DeferredEmptyCoverageMappingDecls.end()) DeferredEmptyCoverageMappingDecls[D] = false; else I->second = false; } void CodeGenModule::EmitDeferredUnusedCoverageMappings() { // We call takeVector() here to avoid use-after-free. // FIXME: DeferredEmptyCoverageMappingDecls is getting mutated because // we deserialize function bodies to emit coverage info for them, and that // deserializes more declarations. How should we handle that case? for (const auto &Entry : DeferredEmptyCoverageMappingDecls.takeVector()) { if (!Entry.second) continue; const Decl *D = Entry.first; switch (D->getKind()) { case Decl::CXXConversion: case Decl::CXXMethod: case Decl::Function: case Decl::ObjCMethod: { CodeGenPGO PGO(*this); GlobalDecl GD(cast(D)); PGO.emitEmptyCounterMapping(D, getMangledName(GD), getFunctionLinkage(GD)); break; } case Decl::CXXConstructor: { CodeGenPGO PGO(*this); GlobalDecl GD(cast(D), Ctor_Base); PGO.emitEmptyCounterMapping(D, getMangledName(GD), getFunctionLinkage(GD)); break; } case Decl::CXXDestructor: { CodeGenPGO PGO(*this); GlobalDecl GD(cast(D), Dtor_Base); PGO.emitEmptyCounterMapping(D, getMangledName(GD), getFunctionLinkage(GD)); break; } default: break; }; } } /// Turns the given pointer into a constant. static llvm::Constant *GetPointerConstant(llvm::LLVMContext &Context, const void *Ptr) { uintptr_t PtrInt = reinterpret_cast(Ptr); llvm::Type *i64 = llvm::Type::getInt64Ty(Context); return llvm::ConstantInt::get(i64, PtrInt); } static void EmitGlobalDeclMetadata(CodeGenModule &CGM, llvm::NamedMDNode *&GlobalMetadata, GlobalDecl D, llvm::GlobalValue *Addr) { if (!GlobalMetadata) GlobalMetadata = CGM.getModule().getOrInsertNamedMetadata("clang.global.decl.ptrs"); // TODO: should we report variant information for ctors/dtors? llvm::Metadata *Ops[] = {llvm::ConstantAsMetadata::get(Addr), llvm::ConstantAsMetadata::get(GetPointerConstant( CGM.getLLVMContext(), D.getDecl()))}; GlobalMetadata->addOperand(llvm::MDNode::get(CGM.getLLVMContext(), Ops)); } /// For each function which is declared within an extern "C" region and marked /// as 'used', but has internal linkage, create an alias from the unmangled /// name to the mangled name if possible. People expect to be able to refer /// to such functions with an unmangled name from inline assembly within the /// same translation unit. void CodeGenModule::EmitStaticExternCAliases() { if (!getTargetCodeGenInfo().shouldEmitStaticExternCAliases()) return; for (auto &I : StaticExternCValues) { IdentifierInfo *Name = I.first; llvm::GlobalValue *Val = I.second; if (Val && !getModule().getNamedValue(Name->getName())) addUsedGlobal(llvm::GlobalAlias::create(Name->getName(), Val)); } } bool CodeGenModule::lookupRepresentativeDecl(StringRef MangledName, GlobalDecl &Result) const { auto Res = Manglings.find(MangledName); if (Res == Manglings.end()) return false; Result = Res->getValue(); return true; } /// Emits metadata nodes associating all the global values in the /// current module with the Decls they came from. This is useful for /// projects using IR gen as a subroutine. /// /// Since there's currently no way to associate an MDNode directly /// with an llvm::GlobalValue, we create a global named metadata /// with the name 'clang.global.decl.ptrs'. void CodeGenModule::EmitDeclMetadata() { llvm::NamedMDNode *GlobalMetadata = nullptr; for (auto &I : MangledDeclNames) { llvm::GlobalValue *Addr = getModule().getNamedValue(I.second); // Some mangled names don't necessarily have an associated GlobalValue // in this module, e.g. if we mangled it for DebugInfo. if (Addr) EmitGlobalDeclMetadata(*this, GlobalMetadata, I.first, Addr); } } /// Emits metadata nodes for all the local variables in the current /// function. void CodeGenFunction::EmitDeclMetadata() { if (LocalDeclMap.empty()) return; llvm::LLVMContext &Context = getLLVMContext(); // Find the unique metadata ID for this name. unsigned DeclPtrKind = Context.getMDKindID("clang.decl.ptr"); llvm::NamedMDNode *GlobalMetadata = nullptr; for (auto &I : LocalDeclMap) { const Decl *D = I.first; llvm::Value *Addr = I.second.getPointer(); if (auto *Alloca = dyn_cast(Addr)) { llvm::Value *DAddr = GetPointerConstant(getLLVMContext(), D); Alloca->setMetadata( DeclPtrKind, llvm::MDNode::get( Context, llvm::ValueAsMetadata::getConstant(DAddr))); } else if (auto *GV = dyn_cast(Addr)) { GlobalDecl GD = GlobalDecl(cast(D)); EmitGlobalDeclMetadata(CGM, GlobalMetadata, GD, GV); } } } void CodeGenModule::EmitVersionIdentMetadata() { llvm::NamedMDNode *IdentMetadata = TheModule.getOrInsertNamedMetadata("llvm.ident"); std::string Version = getClangFullVersion(); llvm::LLVMContext &Ctx = TheModule.getContext(); llvm::Metadata *IdentNode[] = {llvm::MDString::get(Ctx, Version)}; IdentMetadata->addOperand(llvm::MDNode::get(Ctx, IdentNode)); } void CodeGenModule::EmitTargetMetadata() { // Warning, new MangledDeclNames may be appended within this loop. // We rely on MapVector insertions adding new elements to the end // of the container. // FIXME: Move this loop into the one target that needs it, and only // loop over those declarations for which we couldn't emit the target // metadata when we emitted the declaration. for (unsigned I = 0; I != MangledDeclNames.size(); ++I) { auto Val = *(MangledDeclNames.begin() + I); const Decl *D = Val.first.getDecl()->getMostRecentDecl(); llvm::GlobalValue *GV = GetGlobalValue(Val.second); getTargetCodeGenInfo().emitTargetMD(D, GV, *this); } } void CodeGenModule::EmitCoverageFile() { if (getCodeGenOpts().CoverageDataFile.empty() && getCodeGenOpts().CoverageNotesFile.empty()) return; llvm::NamedMDNode *CUNode = TheModule.getNamedMetadata("llvm.dbg.cu"); if (!CUNode) return; llvm::NamedMDNode *GCov = TheModule.getOrInsertNamedMetadata("llvm.gcov"); llvm::LLVMContext &Ctx = TheModule.getContext(); auto *CoverageDataFile = llvm::MDString::get(Ctx, getCodeGenOpts().CoverageDataFile); auto *CoverageNotesFile = llvm::MDString::get(Ctx, getCodeGenOpts().CoverageNotesFile); for (int i = 0, e = CUNode->getNumOperands(); i != e; ++i) { llvm::MDNode *CU = CUNode->getOperand(i); llvm::Metadata *Elts[] = {CoverageNotesFile, CoverageDataFile, CU}; GCov->addOperand(llvm::MDNode::get(Ctx, Elts)); } } llvm::Constant *CodeGenModule::EmitUuidofInitializer(StringRef Uuid) { // Sema has checked that all uuid strings are of the form // "12345678-1234-1234-1234-1234567890ab". assert(Uuid.size() == 36); for (unsigned i = 0; i < 36; ++i) { if (i == 8 || i == 13 || i == 18 || i == 23) assert(Uuid[i] == '-'); else assert(isHexDigit(Uuid[i])); } // The starts of all bytes of Field3 in Uuid. Field 3 is "1234-1234567890ab". const unsigned Field3ValueOffsets[8] = { 19, 21, 24, 26, 28, 30, 32, 34 }; llvm::Constant *Field3[8]; for (unsigned Idx = 0; Idx < 8; ++Idx) Field3[Idx] = llvm::ConstantInt::get( Int8Ty, Uuid.substr(Field3ValueOffsets[Idx], 2), 16); llvm::Constant *Fields[4] = { llvm::ConstantInt::get(Int32Ty, Uuid.substr(0, 8), 16), llvm::ConstantInt::get(Int16Ty, Uuid.substr(9, 4), 16), llvm::ConstantInt::get(Int16Ty, Uuid.substr(14, 4), 16), llvm::ConstantArray::get(llvm::ArrayType::get(Int8Ty, 8), Field3) }; return llvm::ConstantStruct::getAnon(Fields); } llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH) { // Return a bogus pointer if RTTI is disabled, unless it's for EH. // FIXME: should we even be calling this method if RTTI is disabled // and it's not for EH? if ((!ForEH && !getLangOpts().RTTI) || getLangOpts().CUDAIsDevice) return llvm::Constant::getNullValue(Int8PtrTy); if (ForEH && Ty->isObjCObjectPointerType() && LangOpts.ObjCRuntime.isGNUFamily()) return ObjCRuntime->GetEHType(Ty); return getCXXABI().getAddrOfRTTIDescriptor(Ty); } void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { // Do not emit threadprivates in simd-only mode. if (LangOpts.OpenMP && LangOpts.OpenMPSimd) return; for (auto RefExpr : D->varlists()) { auto *VD = cast(cast(RefExpr)->getDecl()); bool PerformInit = VD->getAnyInitializer() && !VD->getAnyInitializer()->isConstantInitializer(getContext(), /*ForRef=*/false); Address Addr(GetAddrOfGlobalVar(VD), getContext().getDeclAlign(VD)); if (auto InitFunction = getOpenMPRuntime().emitThreadPrivateVarDefinition( VD, Addr, RefExpr->getLocStart(), PerformInit)) CXXGlobalInits.push_back(InitFunction); } } llvm::Metadata * CodeGenModule::CreateMetadataIdentifierImpl(QualType T, MetadataTypeMap &Map, StringRef Suffix) { llvm::Metadata *&InternalId = Map[T.getCanonicalType()]; if (InternalId) return InternalId; if (isExternallyVisible(T->getLinkage())) { std::string OutName; llvm::raw_string_ostream Out(OutName); getCXXABI().getMangleContext().mangleTypeName(T, Out); Out << Suffix; InternalId = llvm::MDString::get(getLLVMContext(), Out.str()); } else { InternalId = llvm::MDNode::getDistinct(getLLVMContext(), llvm::ArrayRef()); } return InternalId; } llvm::Metadata *CodeGenModule::CreateMetadataIdentifierForType(QualType T) { return CreateMetadataIdentifierImpl(T, MetadataIdMap, ""); } llvm::Metadata * CodeGenModule::CreateMetadataIdentifierForVirtualMemPtrType(QualType T) { return CreateMetadataIdentifierImpl(T, VirtualMetadataIdMap, ".virtual"); } // Generalize pointer types to a void pointer with the qualifiers of the // originally pointed-to type, e.g. 'const char *' and 'char * const *' // generalize to 'const void *' while 'char *' and 'const char **' generalize to // 'void *'. static QualType GeneralizeType(ASTContext &Ctx, QualType Ty) { if (!Ty->isPointerType()) return Ty; return Ctx.getPointerType( QualType(Ctx.VoidTy).withCVRQualifiers( Ty->getPointeeType().getCVRQualifiers())); } // Apply type generalization to a FunctionType's return and argument types static QualType GeneralizeFunctionType(ASTContext &Ctx, QualType Ty) { if (auto *FnType = Ty->getAs()) { SmallVector GeneralizedParams; for (auto &Param : FnType->param_types()) GeneralizedParams.push_back(GeneralizeType(Ctx, Param)); return Ctx.getFunctionType( GeneralizeType(Ctx, FnType->getReturnType()), GeneralizedParams, FnType->getExtProtoInfo()); } if (auto *FnType = Ty->getAs()) return Ctx.getFunctionNoProtoType( GeneralizeType(Ctx, FnType->getReturnType())); llvm_unreachable("Encountered unknown FunctionType"); } llvm::Metadata *CodeGenModule::CreateMetadataIdentifierGeneralized(QualType T) { return CreateMetadataIdentifierImpl(GeneralizeFunctionType(getContext(), T), GeneralizedMetadataIdMap, ".generalized"); } /// Returns whether this module needs the "all-vtables" type identifier. bool CodeGenModule::NeedAllVtablesTypeId() const { // Returns true if at least one of vtable-based CFI checkers is enabled and // is not in the trapping mode. return ((LangOpts.Sanitize.has(SanitizerKind::CFIVCall) && !CodeGenOpts.SanitizeTrap.has(SanitizerKind::CFIVCall)) || (LangOpts.Sanitize.has(SanitizerKind::CFINVCall) && !CodeGenOpts.SanitizeTrap.has(SanitizerKind::CFINVCall)) || (LangOpts.Sanitize.has(SanitizerKind::CFIDerivedCast) && !CodeGenOpts.SanitizeTrap.has(SanitizerKind::CFIDerivedCast)) || (LangOpts.Sanitize.has(SanitizerKind::CFIUnrelatedCast) && !CodeGenOpts.SanitizeTrap.has(SanitizerKind::CFIUnrelatedCast))); } void CodeGenModule::AddVTableTypeMetadata(llvm::GlobalVariable *VTable, CharUnits Offset, const CXXRecordDecl *RD) { llvm::Metadata *MD = CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0)); VTable->addTypeMetadata(Offset.getQuantity(), MD); if (CodeGenOpts.SanitizeCfiCrossDso) if (auto CrossDsoTypeId = CreateCrossDsoCfiTypeId(MD)) VTable->addTypeMetadata(Offset.getQuantity(), llvm::ConstantAsMetadata::get(CrossDsoTypeId)); if (NeedAllVtablesTypeId()) { llvm::Metadata *MD = llvm::MDString::get(getLLVMContext(), "all-vtables"); VTable->addTypeMetadata(Offset.getQuantity(), MD); } } TargetAttr::ParsedTargetAttr CodeGenModule::filterFunctionTargetAttrs(const TargetAttr *TD) { assert(TD != nullptr); TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse(); ParsedAttr.Features.erase( llvm::remove_if(ParsedAttr.Features, [&](const std::string &Feat) { return !Target.isValidFeatureName( StringRef{Feat}.substr(1)); }), ParsedAttr.Features.end()); return ParsedAttr; } // Fills in the supplied string map with the set of target features for the // passed in function. void CodeGenModule::getFunctionFeatureMap(llvm::StringMap &FeatureMap, const FunctionDecl *FD) { StringRef TargetCPU = Target.getTargetOpts().CPU; if (const auto *TD = FD->getAttr()) { TargetAttr::ParsedTargetAttr ParsedAttr = filterFunctionTargetAttrs(TD); // Make a copy of the features as passed on the command line into the // beginning of the additional features from the function to override. ParsedAttr.Features.insert(ParsedAttr.Features.begin(), Target.getTargetOpts().FeaturesAsWritten.begin(), Target.getTargetOpts().FeaturesAsWritten.end()); if (ParsedAttr.Architecture != "" && Target.isValidCPUName(ParsedAttr.Architecture)) TargetCPU = ParsedAttr.Architecture; // Now populate the feature map, first with the TargetCPU which is either // the default or a new one from the target attribute string. Then we'll use // the passed in features (FeaturesAsWritten) along with the new ones from // the attribute. Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU, ParsedAttr.Features); } else if (const auto *SD = FD->getAttr()) { llvm::SmallVector FeaturesTmp; Target.getCPUSpecificCPUDispatchFeatures(SD->getCurCPUName()->getName(), FeaturesTmp); std::vector Features(FeaturesTmp.begin(), FeaturesTmp.end()); Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU, Features); } else { Target.initFeatureMap(FeatureMap, getDiags(), TargetCPU, Target.getTargetOpts().Features); } } llvm::SanitizerStatReport &CodeGenModule::getSanStats() { if (!SanStats) SanStats = llvm::make_unique(&getModule()); return *SanStats; } llvm::Value * CodeGenModule::createOpenCLIntToSamplerConversion(const Expr *E, CodeGenFunction &CGF) { llvm::Constant *C = ConstantEmitter(CGF).emitAbstract(E, E->getType()); auto SamplerT = getOpenCLRuntime().getSamplerType(E->getType().getTypePtr()); auto FTy = llvm::FunctionType::get(SamplerT, {C->getType()}, false); return CGF.Builder.CreateCall(CreateRuntimeFunction(FTy, "__translate_sampler_initializer"), {C}); } Index: vendor/clang/dist-release_70/lib/CodeGen/CoverageMappingGen.cpp =================================================================== --- vendor/clang/dist-release_70/lib/CodeGen/CoverageMappingGen.cpp (revision 341366) +++ vendor/clang/dist-release_70/lib/CodeGen/CoverageMappingGen.cpp (revision 341367) @@ -1,1432 +1,1463 @@ //===--- CoverageMappingGen.cpp - Coverage mapping generation ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Instrumentation-based code coverage mapping generator // //===----------------------------------------------------------------------===// #include "CoverageMappingGen.h" #include "CodeGenFunction.h" #include "clang/AST/StmtVisitor.h" #include "clang/Lex/Lexer.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Optional.h" #include "llvm/ProfileData/Coverage/CoverageMapping.h" #include "llvm/ProfileData/Coverage/CoverageMappingReader.h" #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h" #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" using namespace clang; using namespace CodeGen; using namespace llvm::coverage; void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range, SourceLocation) { SkippedRanges.push_back(Range); } namespace { /// A region of source code that can be mapped to a counter. class SourceMappingRegion { Counter Count; /// The region's starting location. Optional LocStart; /// The region's ending location. Optional LocEnd; /// Whether this region should be emitted after its parent is emitted. bool DeferRegion; /// Whether this region is a gap region. The count from a gap region is set /// as the line execution count if there are no other regions on the line. bool GapRegion; public: SourceMappingRegion(Counter Count, Optional LocStart, Optional LocEnd, bool DeferRegion = false, bool GapRegion = false) : Count(Count), LocStart(LocStart), LocEnd(LocEnd), DeferRegion(DeferRegion), GapRegion(GapRegion) {} const Counter &getCounter() const { return Count; } void setCounter(Counter C) { Count = C; } bool hasStartLoc() const { return LocStart.hasValue(); } void setStartLoc(SourceLocation Loc) { LocStart = Loc; } SourceLocation getStartLoc() const LLVM_READONLY { return getBeginLoc(); } SourceLocation getBeginLoc() const { assert(LocStart && "Region has no start location"); return *LocStart; } bool hasEndLoc() const { return LocEnd.hasValue(); } void setEndLoc(SourceLocation Loc) { assert(Loc.isValid() && "Setting an invalid end location"); LocEnd = Loc; } SourceLocation getEndLoc() const { assert(LocEnd && "Region has no end location"); return *LocEnd; } bool isDeferred() const { return DeferRegion; } void setDeferred(bool Deferred) { DeferRegion = Deferred; } bool isGap() const { return GapRegion; } void setGap(bool Gap) { GapRegion = Gap; } }; /// Spelling locations for the start and end of a source region. struct SpellingRegion { /// The line where the region starts. unsigned LineStart; /// The column where the region starts. unsigned ColumnStart; /// The line where the region ends. unsigned LineEnd; /// The column where the region ends. unsigned ColumnEnd; SpellingRegion(SourceManager &SM, SourceLocation LocStart, SourceLocation LocEnd) { LineStart = SM.getSpellingLineNumber(LocStart); ColumnStart = SM.getSpellingColumnNumber(LocStart); LineEnd = SM.getSpellingLineNumber(LocEnd); ColumnEnd = SM.getSpellingColumnNumber(LocEnd); } SpellingRegion(SourceManager &SM, SourceMappingRegion &R) : SpellingRegion(SM, R.getStartLoc(), R.getEndLoc()) {} /// Check if the start and end locations appear in source order, i.e /// top->bottom, left->right. bool isInSourceOrder() const { return (LineStart < LineEnd) || (LineStart == LineEnd && ColumnStart <= ColumnEnd); } }; /// Provides the common functionality for the different /// coverage mapping region builders. class CoverageMappingBuilder { public: CoverageMappingModuleGen &CVM; SourceManager &SM; const LangOptions &LangOpts; private: /// Map of clang's FileIDs to IDs used for coverage mapping. llvm::SmallDenseMap, 8> FileIDMapping; public: /// The coverage mapping regions for this function llvm::SmallVector MappingRegions; /// The source mapping regions for this function. std::vector SourceRegions; /// A set of regions which can be used as a filter. /// /// It is produced by emitExpansionRegions() and is used in /// emitSourceRegions() to suppress producing code regions if /// the same area is covered by expansion regions. typedef llvm::SmallSet, 8> SourceRegionFilter; CoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM, const LangOptions &LangOpts) : CVM(CVM), SM(SM), LangOpts(LangOpts) {} /// Return the precise end location for the given token. SourceLocation getPreciseTokenLocEnd(SourceLocation Loc) { // We avoid getLocForEndOfToken here, because it doesn't do what we want for // macro locations, which we just treat as expanded files. unsigned TokLen = Lexer::MeasureTokenLength(SM.getSpellingLoc(Loc), SM, LangOpts); return Loc.getLocWithOffset(TokLen); } /// Return the start location of an included file or expanded macro. SourceLocation getStartOfFileOrMacro(SourceLocation Loc) { if (Loc.isMacroID()) return Loc.getLocWithOffset(-SM.getFileOffset(Loc)); return SM.getLocForStartOfFile(SM.getFileID(Loc)); } /// Return the end location of an included file or expanded macro. SourceLocation getEndOfFileOrMacro(SourceLocation Loc) { if (Loc.isMacroID()) return Loc.getLocWithOffset(SM.getFileIDSize(SM.getFileID(Loc)) - SM.getFileOffset(Loc)); return SM.getLocForEndOfFile(SM.getFileID(Loc)); } /// Find out where the current file is included or macro is expanded. SourceLocation getIncludeOrExpansionLoc(SourceLocation Loc) { return Loc.isMacroID() ? SM.getImmediateExpansionRange(Loc).getBegin() : SM.getIncludeLoc(SM.getFileID(Loc)); } /// Return true if \c Loc is a location in a built-in macro. bool isInBuiltin(SourceLocation Loc) { return SM.getBufferName(SM.getSpellingLoc(Loc)) == ""; } /// Check whether \c Loc is included or expanded from \c Parent. bool isNestedIn(SourceLocation Loc, FileID Parent) { do { Loc = getIncludeOrExpansionLoc(Loc); if (Loc.isInvalid()) return false; } while (!SM.isInFileID(Loc, Parent)); return true; } /// Get the start of \c S ignoring macro arguments and builtin macros. SourceLocation getStart(const Stmt *S) { SourceLocation Loc = S->getLocStart(); while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc)) Loc = SM.getImmediateExpansionRange(Loc).getBegin(); return Loc; } /// Get the end of \c S ignoring macro arguments and builtin macros. SourceLocation getEnd(const Stmt *S) { SourceLocation Loc = S->getLocEnd(); while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc)) Loc = SM.getImmediateExpansionRange(Loc).getBegin(); return getPreciseTokenLocEnd(Loc); } /// Find the set of files we have regions for and assign IDs /// /// Fills \c Mapping with the virtual file mapping needed to write out /// coverage and collects the necessary file information to emit source and /// expansion regions. void gatherFileIDs(SmallVectorImpl &Mapping) { FileIDMapping.clear(); llvm::SmallSet Visited; SmallVector, 8> FileLocs; for (const auto &Region : SourceRegions) { SourceLocation Loc = Region.getStartLoc(); FileID File = SM.getFileID(Loc); if (!Visited.insert(File).second) continue; // Do not map FileID's associated with system headers. if (SM.isInSystemHeader(SM.getSpellingLoc(Loc))) continue; unsigned Depth = 0; for (SourceLocation Parent = getIncludeOrExpansionLoc(Loc); Parent.isValid(); Parent = getIncludeOrExpansionLoc(Parent)) ++Depth; FileLocs.push_back(std::make_pair(Loc, Depth)); } std::stable_sort(FileLocs.begin(), FileLocs.end(), llvm::less_second()); for (const auto &FL : FileLocs) { SourceLocation Loc = FL.first; FileID SpellingFile = SM.getDecomposedSpellingLoc(Loc).first; auto Entry = SM.getFileEntryForID(SpellingFile); if (!Entry) continue; FileIDMapping[SM.getFileID(Loc)] = std::make_pair(Mapping.size(), Loc); Mapping.push_back(CVM.getFileID(Entry)); } } /// Get the coverage mapping file ID for \c Loc. /// /// If such file id doesn't exist, return None. Optional getCoverageFileID(SourceLocation Loc) { auto Mapping = FileIDMapping.find(SM.getFileID(Loc)); if (Mapping != FileIDMapping.end()) return Mapping->second.first; return None; } /// Gather all the regions that were skipped by the preprocessor /// using the constructs like #if. void gatherSkippedRegions() { /// An array of the minimum lineStarts and the maximum lineEnds /// for mapping regions from the appropriate source files. llvm::SmallVector, 8> FileLineRanges; FileLineRanges.resize( FileIDMapping.size(), std::make_pair(std::numeric_limits::max(), 0)); for (const auto &R : MappingRegions) { FileLineRanges[R.FileID].first = std::min(FileLineRanges[R.FileID].first, R.LineStart); FileLineRanges[R.FileID].second = std::max(FileLineRanges[R.FileID].second, R.LineEnd); } auto SkippedRanges = CVM.getSourceInfo().getSkippedRanges(); for (const auto &I : SkippedRanges) { auto LocStart = I.getBegin(); auto LocEnd = I.getEnd(); assert(SM.isWrittenInSameFile(LocStart, LocEnd) && "region spans multiple files"); auto CovFileID = getCoverageFileID(LocStart); if (!CovFileID) continue; SpellingRegion SR{SM, LocStart, LocEnd}; auto Region = CounterMappingRegion::makeSkipped( *CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd); // Make sure that we only collect the regions that are inside // the source code of this function. if (Region.LineStart >= FileLineRanges[*CovFileID].first && Region.LineEnd <= FileLineRanges[*CovFileID].second) MappingRegions.push_back(Region); } } /// Generate the coverage counter mapping regions from collected /// source regions. void emitSourceRegions(const SourceRegionFilter &Filter) { for (const auto &Region : SourceRegions) { assert(Region.hasEndLoc() && "incomplete region"); SourceLocation LocStart = Region.getStartLoc(); assert(SM.getFileID(LocStart).isValid() && "region in invalid file"); // Ignore regions from system headers. if (SM.isInSystemHeader(SM.getSpellingLoc(LocStart))) continue; auto CovFileID = getCoverageFileID(LocStart); // Ignore regions that don't have a file, such as builtin macros. if (!CovFileID) continue; SourceLocation LocEnd = Region.getEndLoc(); assert(SM.isWrittenInSameFile(LocStart, LocEnd) && "region spans multiple files"); // Don't add code regions for the area covered by expansion regions. // This not only suppresses redundant regions, but sometimes prevents // creating regions with wrong counters if, for example, a statement's // body ends at the end of a nested macro. if (Filter.count(std::make_pair(LocStart, LocEnd))) continue; // Find the spelling locations for the mapping region. SpellingRegion SR{SM, LocStart, LocEnd}; assert(SR.isInSourceOrder() && "region start and end out of order"); if (Region.isGap()) { MappingRegions.push_back(CounterMappingRegion::makeGapRegion( Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd)); } else { MappingRegions.push_back(CounterMappingRegion::makeRegion( Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd)); } } } /// Generate expansion regions for each virtual file we've seen. SourceRegionFilter emitExpansionRegions() { SourceRegionFilter Filter; for (const auto &FM : FileIDMapping) { SourceLocation ExpandedLoc = FM.second.second; SourceLocation ParentLoc = getIncludeOrExpansionLoc(ExpandedLoc); if (ParentLoc.isInvalid()) continue; auto ParentFileID = getCoverageFileID(ParentLoc); if (!ParentFileID) continue; auto ExpandedFileID = getCoverageFileID(ExpandedLoc); assert(ExpandedFileID && "expansion in uncovered file"); SourceLocation LocEnd = getPreciseTokenLocEnd(ParentLoc); assert(SM.isWrittenInSameFile(ParentLoc, LocEnd) && "region spans multiple files"); Filter.insert(std::make_pair(ParentLoc, LocEnd)); SpellingRegion SR{SM, ParentLoc, LocEnd}; assert(SR.isInSourceOrder() && "region start and end out of order"); MappingRegions.push_back(CounterMappingRegion::makeExpansion( *ParentFileID, *ExpandedFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd)); } return Filter; } }; /// Creates unreachable coverage regions for the functions that /// are not emitted. struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder { EmptyCoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM, const LangOptions &LangOpts) : CoverageMappingBuilder(CVM, SM, LangOpts) {} void VisitDecl(const Decl *D) { if (!D->hasBody()) return; auto Body = D->getBody(); SourceLocation Start = getStart(Body); SourceLocation End = getEnd(Body); if (!SM.isWrittenInSameFile(Start, End)) { // Walk up to find the common ancestor. // Correct the locations accordingly. FileID StartFileID = SM.getFileID(Start); FileID EndFileID = SM.getFileID(End); while (StartFileID != EndFileID && !isNestedIn(End, StartFileID)) { Start = getIncludeOrExpansionLoc(Start); assert(Start.isValid() && "Declaration start location not nested within a known region"); StartFileID = SM.getFileID(Start); } while (StartFileID != EndFileID) { End = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(End)); assert(End.isValid() && "Declaration end location not nested within a known region"); EndFileID = SM.getFileID(End); } } SourceRegions.emplace_back(Counter(), Start, End); } /// Write the mapping data to the output stream void write(llvm::raw_ostream &OS) { SmallVector FileIDMapping; gatherFileIDs(FileIDMapping); emitSourceRegions(SourceRegionFilter()); if (MappingRegions.empty()) return; CoverageMappingWriter Writer(FileIDMapping, None, MappingRegions); Writer.write(OS); } }; /// A StmtVisitor that creates coverage mapping regions which map /// from the source code locations to the PGO counters. struct CounterCoverageMappingBuilder : public CoverageMappingBuilder, public ConstStmtVisitor { /// The map of statements to count values. llvm::DenseMap &CounterMap; /// A stack of currently live regions. std::vector RegionStack; /// The currently deferred region: its end location and count can be set once /// its parent has been popped from the region stack. Optional DeferredRegion; CounterExpressionBuilder Builder; /// A location in the most recently visited file or macro. /// /// This is used to adjust the active source regions appropriately when /// expressions cross file or macro boundaries. SourceLocation MostRecentLocation; /// Location of the last terminated region. Optional> LastTerminatedRegion; /// Return a counter for the subtraction of \c RHS from \c LHS Counter subtractCounters(Counter LHS, Counter RHS) { return Builder.subtract(LHS, RHS); } /// Return a counter for the sum of \c LHS and \c RHS. Counter addCounters(Counter LHS, Counter RHS) { return Builder.add(LHS, RHS); } Counter addCounters(Counter C1, Counter C2, Counter C3) { return addCounters(addCounters(C1, C2), C3); } /// Return the region counter for the given statement. /// /// This should only be called on statements that have a dedicated counter. Counter getRegionCounter(const Stmt *S) { return Counter::getCounter(CounterMap[S]); } /// Push a region onto the stack. /// /// Returns the index on the stack where the region was pushed. This can be /// used with popRegions to exit a "scope", ending the region that was pushed. size_t pushRegion(Counter Count, Optional StartLoc = None, Optional EndLoc = None) { if (StartLoc) { MostRecentLocation = *StartLoc; completeDeferred(Count, MostRecentLocation); } RegionStack.emplace_back(Count, StartLoc, EndLoc); return RegionStack.size() - 1; } /// Complete any pending deferred region by setting its end location and /// count, and then pushing it onto the region stack. size_t completeDeferred(Counter Count, SourceLocation DeferredEndLoc) { size_t Index = RegionStack.size(); if (!DeferredRegion) return Index; // Consume the pending region. SourceMappingRegion DR = DeferredRegion.getValue(); DeferredRegion = None; // If the region ends in an expansion, find the expansion site. FileID StartFile = SM.getFileID(DR.getStartLoc()); if (SM.getFileID(DeferredEndLoc) != StartFile) { if (isNestedIn(DeferredEndLoc, StartFile)) { do { DeferredEndLoc = getIncludeOrExpansionLoc(DeferredEndLoc); } while (StartFile != SM.getFileID(DeferredEndLoc)); } else { return Index; } } // The parent of this deferred region ends where the containing decl ends, // so the region isn't useful. if (DR.getStartLoc() == DeferredEndLoc) return Index; // If we're visiting statements in non-source order (e.g switch cases or // a loop condition) we can't construct a sensible deferred region. if (!SpellingRegion(SM, DR.getStartLoc(), DeferredEndLoc).isInSourceOrder()) return Index; DR.setGap(true); DR.setCounter(Count); DR.setEndLoc(DeferredEndLoc); handleFileExit(DeferredEndLoc); RegionStack.push_back(DR); return Index; } /// Complete a deferred region created after a terminated region at the /// top-level. void completeTopLevelDeferredRegion(Counter Count, SourceLocation DeferredEndLoc) { if (DeferredRegion || !LastTerminatedRegion) return; if (LastTerminatedRegion->second != RegionStack.size()) return; SourceLocation Start = LastTerminatedRegion->first; if (SM.getFileID(Start) != SM.getMainFileID()) return; SourceMappingRegion DR = RegionStack.back(); DR.setStartLoc(Start); DR.setDeferred(false); DeferredRegion = DR; completeDeferred(Count, DeferredEndLoc); } + size_t locationDepth(SourceLocation Loc) { + size_t Depth = 0; + while (Loc.isValid()) { + Loc = getIncludeOrExpansionLoc(Loc); + Depth++; + } + return Depth; + } + /// Pop regions from the stack into the function's list of regions. /// /// Adds all regions from \c ParentIndex to the top of the stack to the /// function's \c SourceRegions. void popRegions(size_t ParentIndex) { assert(RegionStack.size() >= ParentIndex && "parent not in stack"); bool ParentOfDeferredRegion = false; while (RegionStack.size() > ParentIndex) { SourceMappingRegion &Region = RegionStack.back(); if (Region.hasStartLoc()) { SourceLocation StartLoc = Region.getStartLoc(); SourceLocation EndLoc = Region.hasEndLoc() ? Region.getEndLoc() : RegionStack[ParentIndex].getEndLoc(); + size_t StartDepth = locationDepth(StartLoc); + size_t EndDepth = locationDepth(EndLoc); while (!SM.isWrittenInSameFile(StartLoc, EndLoc)) { - // The region ends in a nested file or macro expansion. Create a - // separate region for each expansion. - SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc); - assert(SM.isWrittenInSameFile(NestedLoc, EndLoc)); + bool UnnestStart = StartDepth >= EndDepth; + bool UnnestEnd = EndDepth >= StartDepth; + if (UnnestEnd) { + // The region ends in a nested file or macro expansion. Create a + // separate region for each expansion. + SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc); + assert(SM.isWrittenInSameFile(NestedLoc, EndLoc)); - if (!isRegionAlreadyAdded(NestedLoc, EndLoc)) - SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc); + if (!isRegionAlreadyAdded(NestedLoc, EndLoc)) + SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc); - EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc)); - if (EndLoc.isInvalid()) - llvm::report_fatal_error("File exit not handled before popRegions"); + EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc)); + if (EndLoc.isInvalid()) + llvm::report_fatal_error("File exit not handled before popRegions"); + EndDepth--; + } + if (UnnestStart) { + // The region begins in a nested file or macro expansion. Create a + // separate region for each expansion. + SourceLocation NestedLoc = getEndOfFileOrMacro(StartLoc); + assert(SM.isWrittenInSameFile(StartLoc, NestedLoc)); + + if (!isRegionAlreadyAdded(StartLoc, NestedLoc)) + SourceRegions.emplace_back(Region.getCounter(), StartLoc, NestedLoc); + + StartLoc = getIncludeOrExpansionLoc(StartLoc); + if (StartLoc.isInvalid()) + llvm::report_fatal_error("File exit not handled before popRegions"); + StartDepth--; + } } + Region.setStartLoc(StartLoc); Region.setEndLoc(EndLoc); MostRecentLocation = EndLoc; // If this region happens to span an entire expansion, we need to make // sure we don't overlap the parent region with it. if (StartLoc == getStartOfFileOrMacro(StartLoc) && EndLoc == getEndOfFileOrMacro(EndLoc)) MostRecentLocation = getIncludeOrExpansionLoc(EndLoc); assert(SM.isWrittenInSameFile(Region.getStartLoc(), EndLoc)); assert(SpellingRegion(SM, Region).isInSourceOrder()); SourceRegions.push_back(Region); if (ParentOfDeferredRegion) { ParentOfDeferredRegion = false; // If there's an existing deferred region, keep the old one, because // it means there are two consecutive returns (or a similar pattern). if (!DeferredRegion.hasValue() && // File IDs aren't gathered within macro expansions, so it isn't // useful to try and create a deferred region inside of one. !EndLoc.isMacroID()) DeferredRegion = SourceMappingRegion(Counter::getZero(), EndLoc, None); } } else if (Region.isDeferred()) { assert(!ParentOfDeferredRegion && "Consecutive deferred regions"); ParentOfDeferredRegion = true; } RegionStack.pop_back(); // If the zero region pushed after the last terminated region no longer // exists, clear its cached information. if (LastTerminatedRegion && RegionStack.size() < LastTerminatedRegion->second) LastTerminatedRegion = None; } assert(!ParentOfDeferredRegion && "Deferred region with no parent"); } /// Return the currently active region. SourceMappingRegion &getRegion() { assert(!RegionStack.empty() && "statement has no region"); return RegionStack.back(); } /// Propagate counts through the children of \c S. Counter propagateCounts(Counter TopCount, const Stmt *S) { SourceLocation StartLoc = getStart(S); SourceLocation EndLoc = getEnd(S); size_t Index = pushRegion(TopCount, StartLoc, EndLoc); Visit(S); Counter ExitCount = getRegion().getCounter(); popRegions(Index); // The statement may be spanned by an expansion. Make sure we handle a file // exit out of this expansion before moving to the next statement. if (SM.isBeforeInTranslationUnit(StartLoc, S->getLocStart())) MostRecentLocation = EndLoc; return ExitCount; } /// Check whether a region with bounds \c StartLoc and \c EndLoc /// is already added to \c SourceRegions. bool isRegionAlreadyAdded(SourceLocation StartLoc, SourceLocation EndLoc) { return SourceRegions.rend() != std::find_if(SourceRegions.rbegin(), SourceRegions.rend(), [&](const SourceMappingRegion &Region) { return Region.getStartLoc() == StartLoc && Region.getEndLoc() == EndLoc; }); } /// Adjust the most recently visited location to \c EndLoc. /// /// This should be used after visiting any statements in non-source order. void adjustForOutOfOrderTraversal(SourceLocation EndLoc) { MostRecentLocation = EndLoc; // The code region for a whole macro is created in handleFileExit() when // it detects exiting of the virtual file of that macro. If we visited // statements in non-source order, we might already have such a region // added, for example, if a body of a loop is divided among multiple // macros. Avoid adding duplicate regions in such case. if (getRegion().hasEndLoc() && MostRecentLocation == getEndOfFileOrMacro(MostRecentLocation) && isRegionAlreadyAdded(getStartOfFileOrMacro(MostRecentLocation), MostRecentLocation)) MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation); } /// Adjust regions and state when \c NewLoc exits a file. /// /// If moving from our most recently tracked location to \c NewLoc exits any /// files, this adjusts our current region stack and creates the file regions /// for the exited file. void handleFileExit(SourceLocation NewLoc) { if (NewLoc.isInvalid() || SM.isWrittenInSameFile(MostRecentLocation, NewLoc)) return; // If NewLoc is not in a file that contains MostRecentLocation, walk up to // find the common ancestor. SourceLocation LCA = NewLoc; FileID ParentFile = SM.getFileID(LCA); while (!isNestedIn(MostRecentLocation, ParentFile)) { LCA = getIncludeOrExpansionLoc(LCA); if (LCA.isInvalid() || SM.isWrittenInSameFile(LCA, MostRecentLocation)) { // Since there isn't a common ancestor, no file was exited. We just need // to adjust our location to the new file. MostRecentLocation = NewLoc; return; } ParentFile = SM.getFileID(LCA); } llvm::SmallSet StartLocs; Optional ParentCounter; for (SourceMappingRegion &I : llvm::reverse(RegionStack)) { if (!I.hasStartLoc()) continue; SourceLocation Loc = I.getStartLoc(); if (!isNestedIn(Loc, ParentFile)) { ParentCounter = I.getCounter(); break; } while (!SM.isInFileID(Loc, ParentFile)) { // The most nested region for each start location is the one with the // correct count. We avoid creating redundant regions by stopping once // we've seen this region. if (StartLocs.insert(Loc).second) SourceRegions.emplace_back(I.getCounter(), Loc, getEndOfFileOrMacro(Loc)); Loc = getIncludeOrExpansionLoc(Loc); } I.setStartLoc(getPreciseTokenLocEnd(Loc)); } if (ParentCounter) { // If the file is contained completely by another region and doesn't // immediately start its own region, the whole file gets a region // corresponding to the parent. SourceLocation Loc = MostRecentLocation; while (isNestedIn(Loc, ParentFile)) { SourceLocation FileStart = getStartOfFileOrMacro(Loc); if (StartLocs.insert(FileStart).second) { SourceRegions.emplace_back(*ParentCounter, FileStart, getEndOfFileOrMacro(Loc)); assert(SpellingRegion(SM, SourceRegions.back()).isInSourceOrder()); } Loc = getIncludeOrExpansionLoc(Loc); } } MostRecentLocation = NewLoc; } /// Ensure that \c S is included in the current region. void extendRegion(const Stmt *S) { SourceMappingRegion &Region = getRegion(); SourceLocation StartLoc = getStart(S); handleFileExit(StartLoc); if (!Region.hasStartLoc()) Region.setStartLoc(StartLoc); completeDeferred(Region.getCounter(), StartLoc); } /// Mark \c S as a terminator, starting a zero region. void terminateRegion(const Stmt *S) { extendRegion(S); SourceMappingRegion &Region = getRegion(); SourceLocation EndLoc = getEnd(S); if (!Region.hasEndLoc()) Region.setEndLoc(EndLoc); pushRegion(Counter::getZero()); auto &ZeroRegion = getRegion(); ZeroRegion.setDeferred(true); LastTerminatedRegion = {EndLoc, RegionStack.size()}; } /// Find a valid gap range between \p AfterLoc and \p BeforeLoc. Optional findGapAreaBetween(SourceLocation AfterLoc, SourceLocation BeforeLoc) { // If the start and end locations of the gap are both within the same macro // file, the range may not be in source order. if (AfterLoc.isMacroID() || BeforeLoc.isMacroID()) return None; if (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc)) return None; return {{AfterLoc, BeforeLoc}}; } /// Find the source range after \p AfterStmt and before \p BeforeStmt. Optional findGapAreaBetween(const Stmt *AfterStmt, const Stmt *BeforeStmt) { return findGapAreaBetween(getPreciseTokenLocEnd(getEnd(AfterStmt)), getStart(BeforeStmt)); } /// Emit a gap region between \p StartLoc and \p EndLoc with the given count. void fillGapAreaWithCount(SourceLocation StartLoc, SourceLocation EndLoc, Counter Count) { if (StartLoc == EndLoc) return; assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder()); handleFileExit(StartLoc); size_t Index = pushRegion(Count, StartLoc, EndLoc); getRegion().setGap(true); handleFileExit(EndLoc); popRegions(Index); } /// Keep counts of breaks and continues inside loops. struct BreakContinue { Counter BreakCount; Counter ContinueCount; }; SmallVector BreakContinueStack; CounterCoverageMappingBuilder( CoverageMappingModuleGen &CVM, llvm::DenseMap &CounterMap, SourceManager &SM, const LangOptions &LangOpts) : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap), DeferredRegion(None) {} /// Write the mapping data to the output stream void write(llvm::raw_ostream &OS) { llvm::SmallVector VirtualFileMapping; gatherFileIDs(VirtualFileMapping); SourceRegionFilter Filter = emitExpansionRegions(); assert(!DeferredRegion && "Deferred region never completed"); emitSourceRegions(Filter); gatherSkippedRegions(); if (MappingRegions.empty()) return; CoverageMappingWriter Writer(VirtualFileMapping, Builder.getExpressions(), MappingRegions); Writer.write(OS); } void VisitStmt(const Stmt *S) { if (S->getLocStart().isValid()) extendRegion(S); for (const Stmt *Child : S->children()) if (Child) this->Visit(Child); handleFileExit(getEnd(S)); } void VisitDecl(const Decl *D) { assert(!DeferredRegion && "Deferred region never completed"); Stmt *Body = D->getBody(); // Do not propagate region counts into system headers. if (Body && SM.isInSystemHeader(SM.getSpellingLoc(getStart(Body)))) return; propagateCounts(getRegionCounter(Body), Body); assert(RegionStack.empty() && "Regions entered but never exited"); // Discard the last uncompleted deferred region in a decl, if one exists. // This prevents lines at the end of a function containing only whitespace // or closing braces from being marked as uncovered. DeferredRegion = None; } void VisitReturnStmt(const ReturnStmt *S) { extendRegion(S); if (S->getRetValue()) Visit(S->getRetValue()); terminateRegion(S); } void VisitCXXThrowExpr(const CXXThrowExpr *E) { extendRegion(E); if (E->getSubExpr()) Visit(E->getSubExpr()); terminateRegion(E); } void VisitGotoStmt(const GotoStmt *S) { terminateRegion(S); } void VisitLabelStmt(const LabelStmt *S) { Counter LabelCount = getRegionCounter(S); SourceLocation Start = getStart(S); completeTopLevelDeferredRegion(LabelCount, Start); completeDeferred(LabelCount, Start); // We can't extendRegion here or we risk overlapping with our new region. handleFileExit(Start); pushRegion(LabelCount, Start); Visit(S->getSubStmt()); } void VisitBreakStmt(const BreakStmt *S) { assert(!BreakContinueStack.empty() && "break not in a loop or switch!"); BreakContinueStack.back().BreakCount = addCounters( BreakContinueStack.back().BreakCount, getRegion().getCounter()); // FIXME: a break in a switch should terminate regions for all preceding // case statements, not just the most recent one. terminateRegion(S); } void VisitContinueStmt(const ContinueStmt *S) { assert(!BreakContinueStack.empty() && "continue stmt not in a loop!"); BreakContinueStack.back().ContinueCount = addCounters( BreakContinueStack.back().ContinueCount, getRegion().getCounter()); terminateRegion(S); } void VisitCallExpr(const CallExpr *E) { VisitStmt(E); // Terminate the region when we hit a noreturn function. // (This is helpful dealing with switch statements.) QualType CalleeType = E->getCallee()->getType(); if (getFunctionExtInfo(*CalleeType).getNoReturn()) terminateRegion(E); } void VisitWhileStmt(const WhileStmt *S) { extendRegion(S); Counter ParentCount = getRegion().getCounter(); Counter BodyCount = getRegionCounter(S); // Handle the body first so that we can get the backedge count. BreakContinueStack.push_back(BreakContinue()); extendRegion(S->getBody()); Counter BackedgeCount = propagateCounts(BodyCount, S->getBody()); BreakContinue BC = BreakContinueStack.pop_back_val(); // Go back to handle the condition. Counter CondCount = addCounters(ParentCount, BackedgeCount, BC.ContinueCount); propagateCounts(CondCount, S->getCond()); adjustForOutOfOrderTraversal(getEnd(S)); // The body count applies to the area immediately after the increment. auto Gap = findGapAreaBetween(S->getCond(), S->getBody()); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount); Counter OutCount = addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount)); if (OutCount != ParentCount) pushRegion(OutCount); } void VisitDoStmt(const DoStmt *S) { extendRegion(S); Counter ParentCount = getRegion().getCounter(); Counter BodyCount = getRegionCounter(S); BreakContinueStack.push_back(BreakContinue()); extendRegion(S->getBody()); Counter BackedgeCount = propagateCounts(addCounters(ParentCount, BodyCount), S->getBody()); BreakContinue BC = BreakContinueStack.pop_back_val(); Counter CondCount = addCounters(BackedgeCount, BC.ContinueCount); propagateCounts(CondCount, S->getCond()); Counter OutCount = addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount)); if (OutCount != ParentCount) pushRegion(OutCount); } void VisitForStmt(const ForStmt *S) { extendRegion(S); if (S->getInit()) Visit(S->getInit()); Counter ParentCount = getRegion().getCounter(); Counter BodyCount = getRegionCounter(S); // The loop increment may contain a break or continue. if (S->getInc()) BreakContinueStack.emplace_back(); // Handle the body first so that we can get the backedge count. BreakContinueStack.emplace_back(); extendRegion(S->getBody()); Counter BackedgeCount = propagateCounts(BodyCount, S->getBody()); BreakContinue BodyBC = BreakContinueStack.pop_back_val(); // The increment is essentially part of the body but it needs to include // the count for all the continue statements. BreakContinue IncrementBC; if (const Stmt *Inc = S->getInc()) { propagateCounts(addCounters(BackedgeCount, BodyBC.ContinueCount), Inc); IncrementBC = BreakContinueStack.pop_back_val(); } // Go back to handle the condition. Counter CondCount = addCounters( addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount), IncrementBC.ContinueCount); if (const Expr *Cond = S->getCond()) { propagateCounts(CondCount, Cond); adjustForOutOfOrderTraversal(getEnd(S)); } // The body count applies to the area immediately after the increment. auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()), getStart(S->getBody())); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount); Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount, subtractCounters(CondCount, BodyCount)); if (OutCount != ParentCount) pushRegion(OutCount); } void VisitCXXForRangeStmt(const CXXForRangeStmt *S) { extendRegion(S); Visit(S->getLoopVarStmt()); Visit(S->getRangeStmt()); Counter ParentCount = getRegion().getCounter(); Counter BodyCount = getRegionCounter(S); BreakContinueStack.push_back(BreakContinue()); extendRegion(S->getBody()); Counter BackedgeCount = propagateCounts(BodyCount, S->getBody()); BreakContinue BC = BreakContinueStack.pop_back_val(); // The body count applies to the area immediately after the range. auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()), getStart(S->getBody())); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount); Counter LoopCount = addCounters(ParentCount, BackedgeCount, BC.ContinueCount); Counter OutCount = addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount)); if (OutCount != ParentCount) pushRegion(OutCount); } void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) { extendRegion(S); Visit(S->getElement()); Counter ParentCount = getRegion().getCounter(); Counter BodyCount = getRegionCounter(S); BreakContinueStack.push_back(BreakContinue()); extendRegion(S->getBody()); Counter BackedgeCount = propagateCounts(BodyCount, S->getBody()); BreakContinue BC = BreakContinueStack.pop_back_val(); // The body count applies to the area immediately after the collection. auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()), getStart(S->getBody())); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount); Counter LoopCount = addCounters(ParentCount, BackedgeCount, BC.ContinueCount); Counter OutCount = addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount)); if (OutCount != ParentCount) pushRegion(OutCount); } void VisitSwitchStmt(const SwitchStmt *S) { extendRegion(S); if (S->getInit()) Visit(S->getInit()); Visit(S->getCond()); BreakContinueStack.push_back(BreakContinue()); const Stmt *Body = S->getBody(); extendRegion(Body); if (const auto *CS = dyn_cast(Body)) { if (!CS->body_empty()) { // Make a region for the body of the switch. If the body starts with // a case, that case will reuse this region; otherwise, this covers // the unreachable code at the beginning of the switch body. size_t Index = pushRegion(Counter::getZero(), getStart(CS->body_front())); for (const auto *Child : CS->children()) Visit(Child); // Set the end for the body of the switch, if it isn't already set. for (size_t i = RegionStack.size(); i != Index; --i) { if (!RegionStack[i - 1].hasEndLoc()) RegionStack[i - 1].setEndLoc(getEnd(CS->body_back())); } popRegions(Index); } } else propagateCounts(Counter::getZero(), Body); BreakContinue BC = BreakContinueStack.pop_back_val(); if (!BreakContinueStack.empty()) BreakContinueStack.back().ContinueCount = addCounters( BreakContinueStack.back().ContinueCount, BC.ContinueCount); Counter ExitCount = getRegionCounter(S); SourceLocation ExitLoc = getEnd(S); pushRegion(ExitCount); // Ensure that handleFileExit recognizes when the end location is located // in a different file. MostRecentLocation = getStart(S); handleFileExit(ExitLoc); } void VisitSwitchCase(const SwitchCase *S) { extendRegion(S); SourceMappingRegion &Parent = getRegion(); Counter Count = addCounters(Parent.getCounter(), getRegionCounter(S)); // Reuse the existing region if it starts at our label. This is typical of // the first case in a switch. if (Parent.hasStartLoc() && Parent.getStartLoc() == getStart(S)) Parent.setCounter(Count); else pushRegion(Count, getStart(S)); if (const auto *CS = dyn_cast(S)) { Visit(CS->getLHS()); if (const Expr *RHS = CS->getRHS()) Visit(RHS); } Visit(S->getSubStmt()); } void VisitIfStmt(const IfStmt *S) { extendRegion(S); if (S->getInit()) Visit(S->getInit()); // Extend into the condition before we propagate through it below - this is // needed to handle macros that generate the "if" but not the condition. extendRegion(S->getCond()); Counter ParentCount = getRegion().getCounter(); Counter ThenCount = getRegionCounter(S); // Emitting a counter for the condition makes it easier to interpret the // counter for the body when looking at the coverage. propagateCounts(ParentCount, S->getCond()); // The 'then' count applies to the area immediately after the condition. auto Gap = findGapAreaBetween(S->getCond(), S->getThen()); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount); extendRegion(S->getThen()); Counter OutCount = propagateCounts(ThenCount, S->getThen()); Counter ElseCount = subtractCounters(ParentCount, ThenCount); if (const Stmt *Else = S->getElse()) { // The 'else' count applies to the area immediately after the 'then'. Gap = findGapAreaBetween(S->getThen(), Else); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount); extendRegion(Else); OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else)); } else OutCount = addCounters(OutCount, ElseCount); if (OutCount != ParentCount) pushRegion(OutCount); } void VisitCXXTryStmt(const CXXTryStmt *S) { extendRegion(S); // Handle macros that generate the "try" but not the rest. extendRegion(S->getTryBlock()); Counter ParentCount = getRegion().getCounter(); propagateCounts(ParentCount, S->getTryBlock()); for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I) Visit(S->getHandler(I)); Counter ExitCount = getRegionCounter(S); pushRegion(ExitCount); } void VisitCXXCatchStmt(const CXXCatchStmt *S) { propagateCounts(getRegionCounter(S), S->getHandlerBlock()); } void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { extendRegion(E); Counter ParentCount = getRegion().getCounter(); Counter TrueCount = getRegionCounter(E); Visit(E->getCond()); if (!isa(E)) { // The 'then' count applies to the area immediately after the condition. auto Gap = findGapAreaBetween(E->getQuestionLoc(), getStart(E->getTrueExpr())); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), TrueCount); extendRegion(E->getTrueExpr()); propagateCounts(TrueCount, E->getTrueExpr()); } extendRegion(E->getFalseExpr()); propagateCounts(subtractCounters(ParentCount, TrueCount), E->getFalseExpr()); } void VisitBinLAnd(const BinaryOperator *E) { extendRegion(E->getLHS()); propagateCounts(getRegion().getCounter(), E->getLHS()); handleFileExit(getEnd(E->getLHS())); extendRegion(E->getRHS()); propagateCounts(getRegionCounter(E), E->getRHS()); } void VisitBinLOr(const BinaryOperator *E) { extendRegion(E->getLHS()); propagateCounts(getRegion().getCounter(), E->getLHS()); handleFileExit(getEnd(E->getLHS())); extendRegion(E->getRHS()); propagateCounts(getRegionCounter(E), E->getRHS()); } void VisitLambdaExpr(const LambdaExpr *LE) { // Lambdas are treated as their own functions for now, so we shouldn't // propagate counts into them. } }; std::string getCoverageSection(const CodeGenModule &CGM) { return llvm::getInstrProfSectionName( llvm::IPSK_covmap, CGM.getContext().getTargetInfo().getTriple().getObjectFormat()); } std::string normalizeFilename(StringRef Filename) { llvm::SmallString<256> Path(Filename); llvm::sys::fs::make_absolute(Path); llvm::sys::path::remove_dots(Path, /*remove_dot_dots=*/true); return Path.str().str(); } } // end anonymous namespace static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef Expressions, ArrayRef Regions) { OS << FunctionName << ":\n"; CounterMappingContext Ctx(Expressions); for (const auto &R : Regions) { OS.indent(2); switch (R.Kind) { case CounterMappingRegion::CodeRegion: break; case CounterMappingRegion::ExpansionRegion: OS << "Expansion,"; break; case CounterMappingRegion::SkippedRegion: OS << "Skipped,"; break; case CounterMappingRegion::GapRegion: OS << "Gap,"; break; } OS << "File " << R.FileID << ", " << R.LineStart << ":" << R.ColumnStart << " -> " << R.LineEnd << ":" << R.ColumnEnd << " = "; Ctx.dump(R.Count, OS); if (R.Kind == CounterMappingRegion::ExpansionRegion) OS << " (Expanded file = " << R.ExpandedFileID << ")"; OS << "\n"; } } void CoverageMappingModuleGen::addFunctionMappingRecord( llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash, const std::string &CoverageMapping, bool IsUsed) { llvm::LLVMContext &Ctx = CGM.getLLVMContext(); if (!FunctionRecordTy) { #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType, llvm::Type *FunctionRecordTypes[] = { #include "llvm/ProfileData/InstrProfData.inc" }; FunctionRecordTy = llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes), /*isPacked=*/true); } #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init, llvm::Constant *FunctionRecordVals[] = { #include "llvm/ProfileData/InstrProfData.inc" }; FunctionRecords.push_back(llvm::ConstantStruct::get( FunctionRecordTy, makeArrayRef(FunctionRecordVals))); if (!IsUsed) FunctionNames.push_back( llvm::ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx))); CoverageMappings.push_back(CoverageMapping); if (CGM.getCodeGenOpts().DumpCoverageMapping) { // Dump the coverage mapping data for this function by decoding the // encoded data. This allows us to dump the mapping regions which were // also processed by the CoverageMappingWriter which performs // additional minimization operations such as reducing the number of // expressions. std::vector Filenames; std::vector Expressions; std::vector Regions; llvm::SmallVector FilenameStrs; llvm::SmallVector FilenameRefs; FilenameStrs.resize(FileEntries.size()); FilenameRefs.resize(FileEntries.size()); for (const auto &Entry : FileEntries) { auto I = Entry.second; FilenameStrs[I] = normalizeFilename(Entry.first->getName()); FilenameRefs[I] = FilenameStrs[I]; } RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames, Expressions, Regions); if (Reader.read()) return; dump(llvm::outs(), NameValue, Expressions, Regions); } } void CoverageMappingModuleGen::emit() { if (FunctionRecords.empty()) return; llvm::LLVMContext &Ctx = CGM.getLLVMContext(); auto *Int32Ty = llvm::Type::getInt32Ty(Ctx); // Create the filenames and merge them with coverage mappings llvm::SmallVector FilenameStrs; llvm::SmallVector FilenameRefs; FilenameStrs.resize(FileEntries.size()); FilenameRefs.resize(FileEntries.size()); for (const auto &Entry : FileEntries) { auto I = Entry.second; FilenameStrs[I] = normalizeFilename(Entry.first->getName()); FilenameRefs[I] = FilenameStrs[I]; } std::string FilenamesAndCoverageMappings; llvm::raw_string_ostream OS(FilenamesAndCoverageMappings); CoverageFilenamesSectionWriter(FilenameRefs).write(OS); std::string RawCoverageMappings = llvm::join(CoverageMappings.begin(), CoverageMappings.end(), ""); OS << RawCoverageMappings; size_t CoverageMappingSize = RawCoverageMappings.size(); size_t FilenamesSize = OS.str().size() - CoverageMappingSize; // Append extra zeroes if necessary to ensure that the size of the filenames // and coverage mappings is a multiple of 8. if (size_t Rem = OS.str().size() % 8) { CoverageMappingSize += 8 - Rem; OS.write_zeros(8 - Rem); } auto *FilenamesAndMappingsVal = llvm::ConstantDataArray::getString(Ctx, OS.str(), false); // Create the deferred function records array auto RecordsTy = llvm::ArrayType::get(FunctionRecordTy, FunctionRecords.size()); auto RecordsVal = llvm::ConstantArray::get(RecordsTy, FunctionRecords); llvm::Type *CovDataHeaderTypes[] = { #define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType, #include "llvm/ProfileData/InstrProfData.inc" }; auto CovDataHeaderTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataHeaderTypes)); llvm::Constant *CovDataHeaderVals[] = { #define COVMAP_HEADER(Type, LLVMType, Name, Init) Init, #include "llvm/ProfileData/InstrProfData.inc" }; auto CovDataHeaderVal = llvm::ConstantStruct::get( CovDataHeaderTy, makeArrayRef(CovDataHeaderVals)); // Create the coverage data record llvm::Type *CovDataTypes[] = {CovDataHeaderTy, RecordsTy, FilenamesAndMappingsVal->getType()}; auto CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes)); llvm::Constant *TUDataVals[] = {CovDataHeaderVal, RecordsVal, FilenamesAndMappingsVal}; auto CovDataVal = llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals)); auto CovData = new llvm::GlobalVariable( CGM.getModule(), CovDataTy, true, llvm::GlobalValue::InternalLinkage, CovDataVal, llvm::getCoverageMappingVarName()); CovData->setSection(getCoverageSection(CGM)); CovData->setAlignment(8); // Make sure the data doesn't get deleted. CGM.addUsedGlobal(CovData); // Create the deferred function records array if (!FunctionNames.empty()) { auto NamesArrTy = llvm::ArrayType::get(llvm::Type::getInt8PtrTy(Ctx), FunctionNames.size()); auto NamesArrVal = llvm::ConstantArray::get(NamesArrTy, FunctionNames); // This variable will *NOT* be emitted to the object file. It is used // to pass the list of names referenced to codegen. new llvm::GlobalVariable(CGM.getModule(), NamesArrTy, true, llvm::GlobalValue::InternalLinkage, NamesArrVal, llvm::getCoverageUnusedNamesVarName()); } } unsigned CoverageMappingModuleGen::getFileID(const FileEntry *File) { auto It = FileEntries.find(File); if (It != FileEntries.end()) return It->second; unsigned FileID = FileEntries.size(); FileEntries.insert(std::make_pair(File, FileID)); return FileID; } void CoverageMappingGen::emitCounterMapping(const Decl *D, llvm::raw_ostream &OS) { assert(CounterMap); CounterCoverageMappingBuilder Walker(CVM, *CounterMap, SM, LangOpts); Walker.VisitDecl(D); Walker.write(OS); } void CoverageMappingGen::emitEmptyMapping(const Decl *D, llvm::raw_ostream &OS) { EmptyCoverageMappingBuilder Walker(CVM, SM, LangOpts); Walker.VisitDecl(D); Walker.write(OS); } Index: vendor/clang/dist-release_70/lib/Driver/ToolChains/Arch/PPC.cpp =================================================================== --- vendor/clang/dist-release_70/lib/Driver/ToolChains/Arch/PPC.cpp (revision 341366) +++ vendor/clang/dist-release_70/lib/Driver/ToolChains/Arch/PPC.cpp (revision 341367) @@ -1,153 +1,157 @@ //===--- PPC.cpp - PPC Helpers for Tools ------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "PPC.h" #include "ToolChains/CommonArgs.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Option/ArgList.h" using namespace clang::driver; using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; /// getPPCTargetCPU - Get the (LLVM) name of the PowerPC cpu we are targeting. std::string ppc::getPPCTargetCPU(const ArgList &Args) { if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) { StringRef CPUName = A->getValue(); if (CPUName == "native") { std::string CPU = llvm::sys::getHostCPUName(); if (!CPU.empty() && CPU != "generic") return CPU; else return ""; } return llvm::StringSwitch(CPUName) .Case("common", "generic") .Case("440", "440") .Case("440fp", "440") .Case("450", "450") .Case("601", "601") .Case("602", "602") .Case("603", "603") .Case("603e", "603e") .Case("603ev", "603ev") .Case("604", "604") .Case("604e", "604e") .Case("620", "620") .Case("630", "pwr3") .Case("G3", "g3") .Case("7400", "7400") .Case("G4", "g4") .Case("7450", "7450") .Case("G4+", "g4+") .Case("750", "750") .Case("970", "970") .Case("G5", "g5") .Case("a2", "a2") .Case("a2q", "a2q") .Case("e500mc", "e500mc") .Case("e5500", "e5500") .Case("power3", "pwr3") .Case("power4", "pwr4") .Case("power5", "pwr5") .Case("power5x", "pwr5x") .Case("power6", "pwr6") .Case("power6x", "pwr6x") .Case("power7", "pwr7") .Case("power8", "pwr8") .Case("power9", "pwr9") .Case("pwr3", "pwr3") .Case("pwr4", "pwr4") .Case("pwr5", "pwr5") .Case("pwr5x", "pwr5x") .Case("pwr6", "pwr6") .Case("pwr6x", "pwr6x") .Case("pwr7", "pwr7") .Case("pwr8", "pwr8") .Case("pwr9", "pwr9") .Case("powerpc", "ppc") .Case("powerpc64", "ppc64") .Case("powerpc64le", "ppc64le") .Default(""); } return ""; } const char *ppc::getPPCAsmModeForCPU(StringRef Name) { return llvm::StringSwitch(Name) .Case("pwr7", "-mpower7") .Case("power7", "-mpower7") .Case("pwr8", "-mpower8") .Case("power8", "-mpower8") .Case("ppc64le", "-mpower8") .Case("pwr9", "-mpower9") .Case("power9", "-mpower9") .Default("-many"); } void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple, const ArgList &Args, std::vector &Features) { handleTargetFeaturesGroup(Args, Features, options::OPT_m_ppc_Features_Group); ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args); if (FloatABI == ppc::FloatABI::Soft) Features.push_back("-hard-float"); - ppc::ReadGOTPtrMode ReadGOT = ppc::getPPCReadGOTPtrMode(D, Args); + ppc::ReadGOTPtrMode ReadGOT = ppc::getPPCReadGOTPtrMode(D, Triple, Args); if (ReadGOT == ppc::ReadGOTPtrMode::SecurePlt) Features.push_back("+secure-plt"); } -ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const ArgList &Args) { +ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) { if (Args.getLastArg(options::OPT_msecure_plt)) return ppc::ReadGOTPtrMode::SecurePlt; - return ppc::ReadGOTPtrMode::Bss; + if (Triple.isOSOpenBSD()) + return ppc::ReadGOTPtrMode::SecurePlt; + else + return ppc::ReadGOTPtrMode::Bss; } ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) { ppc::FloatABI ABI = ppc::FloatABI::Invalid; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, options::OPT_mfloat_abi_EQ)) { if (A->getOption().matches(options::OPT_msoft_float)) ABI = ppc::FloatABI::Soft; else if (A->getOption().matches(options::OPT_mhard_float)) ABI = ppc::FloatABI::Hard; else { ABI = llvm::StringSwitch(A->getValue()) .Case("soft", ppc::FloatABI::Soft) .Case("hard", ppc::FloatABI::Hard) .Default(ppc::FloatABI::Invalid); if (ABI == ppc::FloatABI::Invalid && !StringRef(A->getValue()).empty()) { D.Diag(clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); ABI = ppc::FloatABI::Hard; } } } // If unspecified, choose the default based on the platform. if (ABI == ppc::FloatABI::Invalid) { ABI = ppc::FloatABI::Hard; } return ABI; } bool ppc::hasPPCAbiArg(const ArgList &Args, const char *Value) { Arg *A = Args.getLastArg(options::OPT_mabi_EQ); return A && (A->getValue() == StringRef(Value)); } Index: vendor/clang/dist-release_70/lib/Driver/ToolChains/Arch/PPC.h =================================================================== --- vendor/clang/dist-release_70/lib/Driver/ToolChains/Arch/PPC.h (revision 341366) +++ vendor/clang/dist-release_70/lib/Driver/ToolChains/Arch/PPC.h (revision 341367) @@ -1,53 +1,53 @@ //===--- PPC.h - PPC-specific Tool Helpers ----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_PPC_H #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_PPC_H #include "clang/Driver/Driver.h" #include "llvm/ADT/StringRef.h" #include "llvm/Option/Option.h" #include #include namespace clang { namespace driver { namespace tools { namespace ppc { bool hasPPCAbiArg(const llvm::opt::ArgList &Args, const char *Value); enum class FloatABI { Invalid, Soft, Hard, }; enum class ReadGOTPtrMode { Bss, SecurePlt, }; FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args); std::string getPPCTargetCPU(const llvm::opt::ArgList &Args); const char *getPPCAsmModeForCPU(StringRef Name); -ReadGOTPtrMode getPPCReadGOTPtrMode(const Driver &D, +ReadGOTPtrMode getPPCReadGOTPtrMode(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args, std::vector &Features); } // end namespace ppc } // end namespace target } // end namespace driver } // end namespace clang #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_PPC_H Index: vendor/clang/dist-release_70/lib/Headers/altivec.h =================================================================== --- vendor/clang/dist-release_70/lib/Headers/altivec.h (revision 341366) +++ vendor/clang/dist-release_70/lib/Headers/altivec.h (revision 341367) @@ -1,16736 +1,16751 @@ /*===---- altivec.h - Standard header for type generic math ---------------===*\ * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in 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: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * 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 * AUTHORS 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 IN * THE SOFTWARE. * \*===----------------------------------------------------------------------===*/ #ifndef __ALTIVEC_H #define __ALTIVEC_H #ifndef __ALTIVEC__ #error "AltiVec support not enabled" #endif /* Constants for mapping CR6 bits to predicate result. */ #define __CR6_EQ 0 #define __CR6_EQ_REV 1 #define __CR6_LT 2 #define __CR6_LT_REV 3 /* Constants for vec_test_data_class */ #define __VEC_CLASS_FP_SUBNORMAL_N (1 << 0) #define __VEC_CLASS_FP_SUBNORMAL_P (1 << 1) #define __VEC_CLASS_FP_SUBNORMAL (__VEC_CLASS_FP_SUBNORMAL_P | \ __VEC_CLASS_FP_SUBNORMAL_N) #define __VEC_CLASS_FP_ZERO_N (1<<2) #define __VEC_CLASS_FP_ZERO_P (1<<3) #define __VEC_CLASS_FP_ZERO (__VEC_CLASS_FP_ZERO_P | \ __VEC_CLASS_FP_ZERO_N) #define __VEC_CLASS_FP_INFINITY_N (1<<4) #define __VEC_CLASS_FP_INFINITY_P (1<<5) #define __VEC_CLASS_FP_INFINITY (__VEC_CLASS_FP_INFINITY_P | \ __VEC_CLASS_FP_INFINITY_N) #define __VEC_CLASS_FP_NAN (1<<6) #define __VEC_CLASS_FP_NOT_NORMAL (__VEC_CLASS_FP_NAN | \ __VEC_CLASS_FP_SUBNORMAL | \ __VEC_CLASS_FP_ZERO | \ __VEC_CLASS_FP_INFINITY) #define __ATTRS_o_ai __attribute__((__overloadable__, __always_inline__)) #ifdef __POWER9_VECTOR__ #include #endif static __inline__ vector signed char __ATTRS_o_ai vec_perm( vector signed char __a, vector signed char __b, vector unsigned char __c); static __inline__ vector unsigned char __ATTRS_o_ai vec_perm(vector unsigned char __a, vector unsigned char __b, vector unsigned char __c); static __inline__ vector bool char __ATTRS_o_ai vec_perm(vector bool char __a, vector bool char __b, vector unsigned char __c); static __inline__ vector short __ATTRS_o_ai vec_perm(vector signed short __a, vector signed short __b, vector unsigned char __c); static __inline__ vector unsigned short __ATTRS_o_ai vec_perm(vector unsigned short __a, vector unsigned short __b, vector unsigned char __c); static __inline__ vector bool short __ATTRS_o_ai vec_perm( vector bool short __a, vector bool short __b, vector unsigned char __c); static __inline__ vector pixel __ATTRS_o_ai vec_perm(vector pixel __a, vector pixel __b, vector unsigned char __c); static __inline__ vector int __ATTRS_o_ai vec_perm(vector signed int __a, vector signed int __b, vector unsigned char __c); static __inline__ vector unsigned int __ATTRS_o_ai vec_perm( vector unsigned int __a, vector unsigned int __b, vector unsigned char __c); static __inline__ vector bool int __ATTRS_o_ai vec_perm(vector bool int __a, vector bool int __b, vector unsigned char __c); static __inline__ vector float __ATTRS_o_ai vec_perm(vector float __a, vector float __b, vector unsigned char __c); #ifdef __VSX__ static __inline__ vector long long __ATTRS_o_ai vec_perm(vector signed long long __a, vector signed long long __b, vector unsigned char __c); static __inline__ vector unsigned long long __ATTRS_o_ai vec_perm(vector unsigned long long __a, vector unsigned long long __b, vector unsigned char __c); static __inline__ vector bool long long __ATTRS_o_ai vec_perm(vector bool long long __a, vector bool long long __b, vector unsigned char __c); static __inline__ vector double __ATTRS_o_ai vec_perm(vector double __a, vector double __b, vector unsigned char __c); #endif static __inline__ vector unsigned char __ATTRS_o_ai vec_xor(vector unsigned char __a, vector unsigned char __b); /* vec_abs */ #define __builtin_altivec_abs_v16qi vec_abs #define __builtin_altivec_abs_v8hi vec_abs #define __builtin_altivec_abs_v4si vec_abs static __inline__ vector signed char __ATTRS_o_ai vec_abs(vector signed char __a) { return __builtin_altivec_vmaxsb(__a, -__a); } static __inline__ vector signed short __ATTRS_o_ai vec_abs(vector signed short __a) { return __builtin_altivec_vmaxsh(__a, -__a); } static __inline__ vector signed int __ATTRS_o_ai vec_abs(vector signed int __a) { return __builtin_altivec_vmaxsw(__a, -__a); } #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) static __inline__ vector signed long long __ATTRS_o_ai vec_abs(vector signed long long __a) { return __builtin_altivec_vmaxsd(__a, -__a); } #endif static __inline__ vector float __ATTRS_o_ai vec_abs(vector float __a) { #ifdef __VSX__ return __builtin_vsx_xvabssp(__a); #else vector unsigned int __res = (vector unsigned int)__a & (vector unsigned int)(0x7FFFFFFF); return (vector float)__res; #endif } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_abs(vector double __a) { return __builtin_vsx_xvabsdp(__a); } #endif /* vec_abss */ #define __builtin_altivec_abss_v16qi vec_abss #define __builtin_altivec_abss_v8hi vec_abss #define __builtin_altivec_abss_v4si vec_abss static __inline__ vector signed char __ATTRS_o_ai vec_abss(vector signed char __a) { return __builtin_altivec_vmaxsb( __a, __builtin_altivec_vsubsbs((vector signed char)(0), __a)); } static __inline__ vector signed short __ATTRS_o_ai vec_abss(vector signed short __a) { return __builtin_altivec_vmaxsh( __a, __builtin_altivec_vsubshs((vector signed short)(0), __a)); } static __inline__ vector signed int __ATTRS_o_ai vec_abss(vector signed int __a) { return __builtin_altivec_vmaxsw( __a, __builtin_altivec_vsubsws((vector signed int)(0), __a)); } /* vec_absd */ #if defined(__POWER9_VECTOR__) static __inline__ vector unsigned char __ATTRS_o_ai vec_absd(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vabsdub(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_absd(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vabsduh(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_absd(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vabsduw(__a, __b); } #endif /* End __POWER9_VECTOR__ */ /* vec_add */ static __inline__ vector signed char __ATTRS_o_ai vec_add(vector signed char __a, vector signed char __b) { return __a + __b; } static __inline__ vector signed char __ATTRS_o_ai vec_add(vector bool char __a, vector signed char __b) { return (vector signed char)__a + __b; } static __inline__ vector signed char __ATTRS_o_ai vec_add(vector signed char __a, vector bool char __b) { return __a + (vector signed char)__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_add(vector unsigned char __a, vector unsigned char __b) { return __a + __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_add(vector bool char __a, vector unsigned char __b) { return (vector unsigned char)__a + __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_add(vector unsigned char __a, vector bool char __b) { return __a + (vector unsigned char)__b; } static __inline__ vector short __ATTRS_o_ai vec_add(vector short __a, vector short __b) { return __a + __b; } static __inline__ vector short __ATTRS_o_ai vec_add(vector bool short __a, vector short __b) { return (vector short)__a + __b; } static __inline__ vector short __ATTRS_o_ai vec_add(vector short __a, vector bool short __b) { return __a + (vector short)__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_add(vector unsigned short __a, vector unsigned short __b) { return __a + __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_add(vector bool short __a, vector unsigned short __b) { return (vector unsigned short)__a + __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_add(vector unsigned short __a, vector bool short __b) { return __a + (vector unsigned short)__b; } static __inline__ vector int __ATTRS_o_ai vec_add(vector int __a, vector int __b) { return __a + __b; } static __inline__ vector int __ATTRS_o_ai vec_add(vector bool int __a, vector int __b) { return (vector int)__a + __b; } static __inline__ vector int __ATTRS_o_ai vec_add(vector int __a, vector bool int __b) { return __a + (vector int)__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_add(vector unsigned int __a, vector unsigned int __b) { return __a + __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_add(vector bool int __a, vector unsigned int __b) { return (vector unsigned int)__a + __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_add(vector unsigned int __a, vector bool int __b) { return __a + (vector unsigned int)__b; } #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) static __inline__ vector signed long long __ATTRS_o_ai vec_add(vector signed long long __a, vector signed long long __b) { return __a + __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_add(vector unsigned long long __a, vector unsigned long long __b) { return __a + __b; } static __inline__ vector signed __int128 __ATTRS_o_ai vec_add(vector signed __int128 __a, vector signed __int128 __b) { return __a + __b; } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_add(vector unsigned __int128 __a, vector unsigned __int128 __b) { return __a + __b; } #endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__) static __inline__ vector float __ATTRS_o_ai vec_add(vector float __a, vector float __b) { return __a + __b; } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_add(vector double __a, vector double __b) { return __a + __b; } #endif // __VSX__ /* vec_adde */ #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) static __inline__ vector signed __int128 __ATTRS_o_ai vec_adde(vector signed __int128 __a, vector signed __int128 __b, vector signed __int128 __c) { return __builtin_altivec_vaddeuqm(__a, __b, __c); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_adde(vector unsigned __int128 __a, vector unsigned __int128 __b, vector unsigned __int128 __c) { return __builtin_altivec_vaddeuqm(__a, __b, __c); } #endif static __inline__ vector signed int __ATTRS_o_ai vec_adde(vector signed int __a, vector signed int __b, vector signed int __c) { vector signed int __mask = {1, 1, 1, 1}; vector signed int __carry = __c & __mask; return vec_add(vec_add(__a, __b), __carry); } static __inline__ vector unsigned int __ATTRS_o_ai vec_adde(vector unsigned int __a, vector unsigned int __b, vector unsigned int __c) { vector unsigned int __mask = {1, 1, 1, 1}; vector unsigned int __carry = __c & __mask; return vec_add(vec_add(__a, __b), __carry); } /* vec_addec */ #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) static __inline__ vector signed __int128 __ATTRS_o_ai vec_addec(vector signed __int128 __a, vector signed __int128 __b, vector signed __int128 __c) { return __builtin_altivec_vaddecuq(__a, __b, __c); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_addec(vector unsigned __int128 __a, vector unsigned __int128 __b, vector unsigned __int128 __c) { return __builtin_altivec_vaddecuq(__a, __b, __c); } static __inline__ vector signed int __ATTRS_o_ai vec_addec(vector signed int __a, vector signed int __b, vector signed int __c) { signed int __result[4]; for (int i = 0; i < 4; i++) { unsigned int __tempa = (unsigned int) __a[i]; unsigned int __tempb = (unsigned int) __b[i]; unsigned int __tempc = (unsigned int) __c[i]; __tempc = __tempc & 0x00000001; unsigned long long __longa = (unsigned long long) __tempa; unsigned long long __longb = (unsigned long long) __tempb; unsigned long long __longc = (unsigned long long) __tempc; unsigned long long __sum = __longa + __longb + __longc; unsigned long long __res = (__sum >> 32) & 0x01; unsigned long long __tempres = (unsigned int) __res; __result[i] = (signed int) __tempres; } vector signed int ret = { __result[0], __result[1], __result[2], __result[3] }; return ret; } static __inline__ vector unsigned int __ATTRS_o_ai vec_addec(vector unsigned int __a, vector unsigned int __b, vector unsigned int __c) { unsigned int __result[4]; for (int i = 0; i < 4; i++) { unsigned int __tempc = __c[i] & 1; unsigned long long __longa = (unsigned long long) __a[i]; unsigned long long __longb = (unsigned long long) __b[i]; unsigned long long __longc = (unsigned long long) __tempc; unsigned long long __sum = __longa + __longb + __longc; unsigned long long __res = (__sum >> 32) & 0x01; unsigned long long __tempres = (unsigned int) __res; __result[i] = (signed int) __tempres; } vector unsigned int ret = { __result[0], __result[1], __result[2], __result[3] }; return ret; } #endif /* vec_vaddubm */ #define __builtin_altivec_vaddubm vec_vaddubm static __inline__ vector signed char __ATTRS_o_ai vec_vaddubm(vector signed char __a, vector signed char __b) { return __a + __b; } static __inline__ vector signed char __ATTRS_o_ai vec_vaddubm(vector bool char __a, vector signed char __b) { return (vector signed char)__a + __b; } static __inline__ vector signed char __ATTRS_o_ai vec_vaddubm(vector signed char __a, vector bool char __b) { return __a + (vector signed char)__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vaddubm(vector unsigned char __a, vector unsigned char __b) { return __a + __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vaddubm(vector bool char __a, vector unsigned char __b) { return (vector unsigned char)__a + __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vaddubm(vector unsigned char __a, vector bool char __b) { return __a + (vector unsigned char)__b; } /* vec_vadduhm */ #define __builtin_altivec_vadduhm vec_vadduhm static __inline__ vector short __ATTRS_o_ai vec_vadduhm(vector short __a, vector short __b) { return __a + __b; } static __inline__ vector short __ATTRS_o_ai vec_vadduhm(vector bool short __a, vector short __b) { return (vector short)__a + __b; } static __inline__ vector short __ATTRS_o_ai vec_vadduhm(vector short __a, vector bool short __b) { return __a + (vector short)__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vadduhm(vector unsigned short __a, vector unsigned short __b) { return __a + __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vadduhm(vector bool short __a, vector unsigned short __b) { return (vector unsigned short)__a + __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vadduhm(vector unsigned short __a, vector bool short __b) { return __a + (vector unsigned short)__b; } /* vec_vadduwm */ #define __builtin_altivec_vadduwm vec_vadduwm static __inline__ vector int __ATTRS_o_ai vec_vadduwm(vector int __a, vector int __b) { return __a + __b; } static __inline__ vector int __ATTRS_o_ai vec_vadduwm(vector bool int __a, vector int __b) { return (vector int)__a + __b; } static __inline__ vector int __ATTRS_o_ai vec_vadduwm(vector int __a, vector bool int __b) { return __a + (vector int)__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vadduwm(vector unsigned int __a, vector unsigned int __b) { return __a + __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vadduwm(vector bool int __a, vector unsigned int __b) { return (vector unsigned int)__a + __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vadduwm(vector unsigned int __a, vector bool int __b) { return __a + (vector unsigned int)__b; } /* vec_vaddfp */ #define __builtin_altivec_vaddfp vec_vaddfp static __inline__ vector float __attribute__((__always_inline__)) vec_vaddfp(vector float __a, vector float __b) { return __a + __b; } /* vec_addc */ static __inline__ vector signed int __ATTRS_o_ai vec_addc(vector signed int __a, vector signed int __b) { return (vector signed int)__builtin_altivec_vaddcuw((vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_addc(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vaddcuw(__a, __b); } #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) static __inline__ vector signed __int128 __ATTRS_o_ai vec_addc(vector signed __int128 __a, vector signed __int128 __b) { return (vector signed __int128)__builtin_altivec_vaddcuq( (vector unsigned __int128)__a, (vector unsigned __int128)__b); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_addc(vector unsigned __int128 __a, vector unsigned __int128 __b) { return __builtin_altivec_vaddcuq(__a, __b); } #endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__) /* vec_vaddcuw */ static __inline__ vector unsigned int __attribute__((__always_inline__)) vec_vaddcuw(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vaddcuw(__a, __b); } /* vec_adds */ static __inline__ vector signed char __ATTRS_o_ai vec_adds(vector signed char __a, vector signed char __b) { return __builtin_altivec_vaddsbs(__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_adds(vector bool char __a, vector signed char __b) { return __builtin_altivec_vaddsbs((vector signed char)__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_adds(vector signed char __a, vector bool char __b) { return __builtin_altivec_vaddsbs(__a, (vector signed char)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_adds(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vaddubs(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_adds(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vaddubs((vector unsigned char)__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_adds(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vaddubs(__a, (vector unsigned char)__b); } static __inline__ vector short __ATTRS_o_ai vec_adds(vector short __a, vector short __b) { return __builtin_altivec_vaddshs(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_adds(vector bool short __a, vector short __b) { return __builtin_altivec_vaddshs((vector short)__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_adds(vector short __a, vector bool short __b) { return __builtin_altivec_vaddshs(__a, (vector short)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_adds(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vadduhs(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_adds(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vadduhs((vector unsigned short)__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_adds(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vadduhs(__a, (vector unsigned short)__b); } static __inline__ vector int __ATTRS_o_ai vec_adds(vector int __a, vector int __b) { return __builtin_altivec_vaddsws(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_adds(vector bool int __a, vector int __b) { return __builtin_altivec_vaddsws((vector int)__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_adds(vector int __a, vector bool int __b) { return __builtin_altivec_vaddsws(__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_adds(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vadduws(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_adds(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vadduws((vector unsigned int)__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_adds(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vadduws(__a, (vector unsigned int)__b); } /* vec_vaddsbs */ static __inline__ vector signed char __ATTRS_o_ai vec_vaddsbs(vector signed char __a, vector signed char __b) { return __builtin_altivec_vaddsbs(__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_vaddsbs(vector bool char __a, vector signed char __b) { return __builtin_altivec_vaddsbs((vector signed char)__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_vaddsbs(vector signed char __a, vector bool char __b) { return __builtin_altivec_vaddsbs(__a, (vector signed char)__b); } /* vec_vaddubs */ static __inline__ vector unsigned char __ATTRS_o_ai vec_vaddubs(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vaddubs(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vaddubs(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vaddubs((vector unsigned char)__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vaddubs(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vaddubs(__a, (vector unsigned char)__b); } /* vec_vaddshs */ static __inline__ vector short __ATTRS_o_ai vec_vaddshs(vector short __a, vector short __b) { return __builtin_altivec_vaddshs(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_vaddshs(vector bool short __a, vector short __b) { return __builtin_altivec_vaddshs((vector short)__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_vaddshs(vector short __a, vector bool short __b) { return __builtin_altivec_vaddshs(__a, (vector short)__b); } /* vec_vadduhs */ static __inline__ vector unsigned short __ATTRS_o_ai vec_vadduhs(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vadduhs(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vadduhs(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vadduhs((vector unsigned short)__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vadduhs(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vadduhs(__a, (vector unsigned short)__b); } /* vec_vaddsws */ static __inline__ vector int __ATTRS_o_ai vec_vaddsws(vector int __a, vector int __b) { return __builtin_altivec_vaddsws(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_vaddsws(vector bool int __a, vector int __b) { return __builtin_altivec_vaddsws((vector int)__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_vaddsws(vector int __a, vector bool int __b) { return __builtin_altivec_vaddsws(__a, (vector int)__b); } /* vec_vadduws */ static __inline__ vector unsigned int __ATTRS_o_ai vec_vadduws(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vadduws(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vadduws(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vadduws((vector unsigned int)__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vadduws(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vadduws(__a, (vector unsigned int)__b); } #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) /* vec_vadduqm */ static __inline__ vector signed __int128 __ATTRS_o_ai vec_vadduqm(vector signed __int128 __a, vector signed __int128 __b) { return __a + __b; } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_vadduqm(vector unsigned __int128 __a, vector unsigned __int128 __b) { return __a + __b; } /* vec_vaddeuqm */ static __inline__ vector signed __int128 __ATTRS_o_ai vec_vaddeuqm(vector signed __int128 __a, vector signed __int128 __b, vector signed __int128 __c) { return __builtin_altivec_vaddeuqm(__a, __b, __c); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_vaddeuqm(vector unsigned __int128 __a, vector unsigned __int128 __b, vector unsigned __int128 __c) { return __builtin_altivec_vaddeuqm(__a, __b, __c); } /* vec_vaddcuq */ static __inline__ vector signed __int128 __ATTRS_o_ai vec_vaddcuq(vector signed __int128 __a, vector signed __int128 __b) { return __builtin_altivec_vaddcuq(__a, __b); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_vaddcuq(vector unsigned __int128 __a, vector unsigned __int128 __b) { return __builtin_altivec_vaddcuq(__a, __b); } /* vec_vaddecuq */ static __inline__ vector signed __int128 __ATTRS_o_ai vec_vaddecuq(vector signed __int128 __a, vector signed __int128 __b, vector signed __int128 __c) { return __builtin_altivec_vaddecuq(__a, __b, __c); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_vaddecuq(vector unsigned __int128 __a, vector unsigned __int128 __b, vector unsigned __int128 __c) { return __builtin_altivec_vaddecuq(__a, __b, __c); } #endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__) /* vec_and */ #define __builtin_altivec_vand vec_and static __inline__ vector signed char __ATTRS_o_ai vec_and(vector signed char __a, vector signed char __b) { return __a & __b; } static __inline__ vector signed char __ATTRS_o_ai vec_and(vector bool char __a, vector signed char __b) { return (vector signed char)__a & __b; } static __inline__ vector signed char __ATTRS_o_ai vec_and(vector signed char __a, vector bool char __b) { return __a & (vector signed char)__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_and(vector unsigned char __a, vector unsigned char __b) { return __a & __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_and(vector bool char __a, vector unsigned char __b) { return (vector unsigned char)__a & __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_and(vector unsigned char __a, vector bool char __b) { return __a & (vector unsigned char)__b; } static __inline__ vector bool char __ATTRS_o_ai vec_and(vector bool char __a, vector bool char __b) { return __a & __b; } static __inline__ vector short __ATTRS_o_ai vec_and(vector short __a, vector short __b) { return __a & __b; } static __inline__ vector short __ATTRS_o_ai vec_and(vector bool short __a, vector short __b) { return (vector short)__a & __b; } static __inline__ vector short __ATTRS_o_ai vec_and(vector short __a, vector bool short __b) { return __a & (vector short)__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_and(vector unsigned short __a, vector unsigned short __b) { return __a & __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_and(vector bool short __a, vector unsigned short __b) { return (vector unsigned short)__a & __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_and(vector unsigned short __a, vector bool short __b) { return __a & (vector unsigned short)__b; } static __inline__ vector bool short __ATTRS_o_ai vec_and(vector bool short __a, vector bool short __b) { return __a & __b; } static __inline__ vector int __ATTRS_o_ai vec_and(vector int __a, vector int __b) { return __a & __b; } static __inline__ vector int __ATTRS_o_ai vec_and(vector bool int __a, vector int __b) { return (vector int)__a & __b; } static __inline__ vector int __ATTRS_o_ai vec_and(vector int __a, vector bool int __b) { return __a & (vector int)__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_and(vector unsigned int __a, vector unsigned int __b) { return __a & __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_and(vector bool int __a, vector unsigned int __b) { return (vector unsigned int)__a & __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_and(vector unsigned int __a, vector bool int __b) { return __a & (vector unsigned int)__b; } static __inline__ vector bool int __ATTRS_o_ai vec_and(vector bool int __a, vector bool int __b) { return __a & __b; } static __inline__ vector float __ATTRS_o_ai vec_and(vector float __a, vector float __b) { vector unsigned int __res = (vector unsigned int)__a & (vector unsigned int)__b; return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_and(vector bool int __a, vector float __b) { vector unsigned int __res = (vector unsigned int)__a & (vector unsigned int)__b; return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_and(vector float __a, vector bool int __b) { vector unsigned int __res = (vector unsigned int)__a & (vector unsigned int)__b; return (vector float)__res; } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_and(vector bool long long __a, vector double __b) { vector unsigned long long __res = (vector unsigned long long)__a & (vector unsigned long long)__b; return (vector double)__res; } static __inline__ vector double __ATTRS_o_ai vec_and(vector double __a, vector bool long long __b) { vector unsigned long long __res = (vector unsigned long long)__a & (vector unsigned long long)__b; return (vector double)__res; } static __inline__ vector double __ATTRS_o_ai vec_and(vector double __a, vector double __b) { vector unsigned long long __res = (vector unsigned long long)__a & (vector unsigned long long)__b; return (vector double)__res; } static __inline__ vector signed long long __ATTRS_o_ai vec_and(vector signed long long __a, vector signed long long __b) { return __a & __b; } static __inline__ vector signed long long __ATTRS_o_ai vec_and(vector bool long long __a, vector signed long long __b) { return (vector signed long long)__a & __b; } static __inline__ vector signed long long __ATTRS_o_ai vec_and(vector signed long long __a, vector bool long long __b) { return __a & (vector signed long long)__b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_and(vector unsigned long long __a, vector unsigned long long __b) { return __a & __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_and(vector bool long long __a, vector unsigned long long __b) { return (vector unsigned long long)__a & __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_and(vector unsigned long long __a, vector bool long long __b) { return __a & (vector unsigned long long)__b; } static __inline__ vector bool long long __ATTRS_o_ai vec_and(vector bool long long __a, vector bool long long __b) { return __a & __b; } #endif /* vec_vand */ static __inline__ vector signed char __ATTRS_o_ai vec_vand(vector signed char __a, vector signed char __b) { return __a & __b; } static __inline__ vector signed char __ATTRS_o_ai vec_vand(vector bool char __a, vector signed char __b) { return (vector signed char)__a & __b; } static __inline__ vector signed char __ATTRS_o_ai vec_vand(vector signed char __a, vector bool char __b) { return __a & (vector signed char)__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vand(vector unsigned char __a, vector unsigned char __b) { return __a & __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vand(vector bool char __a, vector unsigned char __b) { return (vector unsigned char)__a & __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vand(vector unsigned char __a, vector bool char __b) { return __a & (vector unsigned char)__b; } static __inline__ vector bool char __ATTRS_o_ai vec_vand(vector bool char __a, vector bool char __b) { return __a & __b; } static __inline__ vector short __ATTRS_o_ai vec_vand(vector short __a, vector short __b) { return __a & __b; } static __inline__ vector short __ATTRS_o_ai vec_vand(vector bool short __a, vector short __b) { return (vector short)__a & __b; } static __inline__ vector short __ATTRS_o_ai vec_vand(vector short __a, vector bool short __b) { return __a & (vector short)__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vand(vector unsigned short __a, vector unsigned short __b) { return __a & __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vand(vector bool short __a, vector unsigned short __b) { return (vector unsigned short)__a & __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vand(vector unsigned short __a, vector bool short __b) { return __a & (vector unsigned short)__b; } static __inline__ vector bool short __ATTRS_o_ai vec_vand(vector bool short __a, vector bool short __b) { return __a & __b; } static __inline__ vector int __ATTRS_o_ai vec_vand(vector int __a, vector int __b) { return __a & __b; } static __inline__ vector int __ATTRS_o_ai vec_vand(vector bool int __a, vector int __b) { return (vector int)__a & __b; } static __inline__ vector int __ATTRS_o_ai vec_vand(vector int __a, vector bool int __b) { return __a & (vector int)__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vand(vector unsigned int __a, vector unsigned int __b) { return __a & __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vand(vector bool int __a, vector unsigned int __b) { return (vector unsigned int)__a & __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vand(vector unsigned int __a, vector bool int __b) { return __a & (vector unsigned int)__b; } static __inline__ vector bool int __ATTRS_o_ai vec_vand(vector bool int __a, vector bool int __b) { return __a & __b; } static __inline__ vector float __ATTRS_o_ai vec_vand(vector float __a, vector float __b) { vector unsigned int __res = (vector unsigned int)__a & (vector unsigned int)__b; return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_vand(vector bool int __a, vector float __b) { vector unsigned int __res = (vector unsigned int)__a & (vector unsigned int)__b; return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_vand(vector float __a, vector bool int __b) { vector unsigned int __res = (vector unsigned int)__a & (vector unsigned int)__b; return (vector float)__res; } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_vand(vector signed long long __a, vector signed long long __b) { return __a & __b; } static __inline__ vector signed long long __ATTRS_o_ai vec_vand(vector bool long long __a, vector signed long long __b) { return (vector signed long long)__a & __b; } static __inline__ vector signed long long __ATTRS_o_ai vec_vand(vector signed long long __a, vector bool long long __b) { return __a & (vector signed long long)__b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_vand(vector unsigned long long __a, vector unsigned long long __b) { return __a & __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_vand(vector bool long long __a, vector unsigned long long __b) { return (vector unsigned long long)__a & __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_vand(vector unsigned long long __a, vector bool long long __b) { return __a & (vector unsigned long long)__b; } static __inline__ vector bool long long __ATTRS_o_ai vec_vand(vector bool long long __a, vector bool long long __b) { return __a & __b; } #endif /* vec_andc */ #define __builtin_altivec_vandc vec_andc static __inline__ vector signed char __ATTRS_o_ai vec_andc(vector signed char __a, vector signed char __b) { return __a & ~__b; } static __inline__ vector signed char __ATTRS_o_ai vec_andc(vector bool char __a, vector signed char __b) { return (vector signed char)__a & ~__b; } static __inline__ vector signed char __ATTRS_o_ai vec_andc(vector signed char __a, vector bool char __b) { return __a & ~(vector signed char)__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_andc(vector unsigned char __a, vector unsigned char __b) { return __a & ~__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_andc(vector bool char __a, vector unsigned char __b) { return (vector unsigned char)__a & ~__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_andc(vector unsigned char __a, vector bool char __b) { return __a & ~(vector unsigned char)__b; } static __inline__ vector bool char __ATTRS_o_ai vec_andc(vector bool char __a, vector bool char __b) { return __a & ~__b; } static __inline__ vector short __ATTRS_o_ai vec_andc(vector short __a, vector short __b) { return __a & ~__b; } static __inline__ vector short __ATTRS_o_ai vec_andc(vector bool short __a, vector short __b) { return (vector short)__a & ~__b; } static __inline__ vector short __ATTRS_o_ai vec_andc(vector short __a, vector bool short __b) { return __a & ~(vector short)__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_andc(vector unsigned short __a, vector unsigned short __b) { return __a & ~__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_andc(vector bool short __a, vector unsigned short __b) { return (vector unsigned short)__a & ~__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_andc(vector unsigned short __a, vector bool short __b) { return __a & ~(vector unsigned short)__b; } static __inline__ vector bool short __ATTRS_o_ai vec_andc(vector bool short __a, vector bool short __b) { return __a & ~__b; } static __inline__ vector int __ATTRS_o_ai vec_andc(vector int __a, vector int __b) { return __a & ~__b; } static __inline__ vector int __ATTRS_o_ai vec_andc(vector bool int __a, vector int __b) { return (vector int)__a & ~__b; } static __inline__ vector int __ATTRS_o_ai vec_andc(vector int __a, vector bool int __b) { return __a & ~(vector int)__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_andc(vector unsigned int __a, vector unsigned int __b) { return __a & ~__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_andc(vector bool int __a, vector unsigned int __b) { return (vector unsigned int)__a & ~__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_andc(vector unsigned int __a, vector bool int __b) { return __a & ~(vector unsigned int)__b; } static __inline__ vector bool int __ATTRS_o_ai vec_andc(vector bool int __a, vector bool int __b) { return __a & ~__b; } static __inline__ vector float __ATTRS_o_ai vec_andc(vector float __a, vector float __b) { vector unsigned int __res = (vector unsigned int)__a & ~(vector unsigned int)__b; return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_andc(vector bool int __a, vector float __b) { vector unsigned int __res = (vector unsigned int)__a & ~(vector unsigned int)__b; return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_andc(vector float __a, vector bool int __b) { vector unsigned int __res = (vector unsigned int)__a & ~(vector unsigned int)__b; return (vector float)__res; } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_andc(vector bool long long __a, vector double __b) { vector unsigned long long __res = (vector unsigned long long)__a & ~(vector unsigned long long)__b; return (vector double)__res; } static __inline__ vector double __ATTRS_o_ai vec_andc(vector double __a, vector bool long long __b) { vector unsigned long long __res = (vector unsigned long long)__a & ~(vector unsigned long long)__b; return (vector double)__res; } static __inline__ vector double __ATTRS_o_ai vec_andc(vector double __a, vector double __b) { vector unsigned long long __res = (vector unsigned long long)__a & ~(vector unsigned long long)__b; return (vector double)__res; } static __inline__ vector signed long long __ATTRS_o_ai vec_andc(vector signed long long __a, vector signed long long __b) { return __a & ~__b; } static __inline__ vector signed long long __ATTRS_o_ai vec_andc(vector bool long long __a, vector signed long long __b) { return (vector signed long long)__a & ~__b; } static __inline__ vector signed long long __ATTRS_o_ai vec_andc(vector signed long long __a, vector bool long long __b) { return __a & ~(vector signed long long)__b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_andc(vector unsigned long long __a, vector unsigned long long __b) { return __a & ~__b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_andc(vector bool long long __a, vector unsigned long long __b) { return (vector unsigned long long)__a & ~__b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_andc(vector unsigned long long __a, vector bool long long __b) { return __a & ~(vector unsigned long long)__b; } static __inline__ vector bool long long __ATTRS_o_ai vec_andc(vector bool long long __a, vector bool long long __b) { return __a & ~__b; } #endif /* vec_vandc */ static __inline__ vector signed char __ATTRS_o_ai vec_vandc(vector signed char __a, vector signed char __b) { return __a & ~__b; } static __inline__ vector signed char __ATTRS_o_ai vec_vandc(vector bool char __a, vector signed char __b) { return (vector signed char)__a & ~__b; } static __inline__ vector signed char __ATTRS_o_ai vec_vandc(vector signed char __a, vector bool char __b) { return __a & ~(vector signed char)__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vandc(vector unsigned char __a, vector unsigned char __b) { return __a & ~__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vandc(vector bool char __a, vector unsigned char __b) { return (vector unsigned char)__a & ~__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vandc(vector unsigned char __a, vector bool char __b) { return __a & ~(vector unsigned char)__b; } static __inline__ vector bool char __ATTRS_o_ai vec_vandc(vector bool char __a, vector bool char __b) { return __a & ~__b; } static __inline__ vector short __ATTRS_o_ai vec_vandc(vector short __a, vector short __b) { return __a & ~__b; } static __inline__ vector short __ATTRS_o_ai vec_vandc(vector bool short __a, vector short __b) { return (vector short)__a & ~__b; } static __inline__ vector short __ATTRS_o_ai vec_vandc(vector short __a, vector bool short __b) { return __a & ~(vector short)__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vandc(vector unsigned short __a, vector unsigned short __b) { return __a & ~__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vandc(vector bool short __a, vector unsigned short __b) { return (vector unsigned short)__a & ~__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vandc(vector unsigned short __a, vector bool short __b) { return __a & ~(vector unsigned short)__b; } static __inline__ vector bool short __ATTRS_o_ai vec_vandc(vector bool short __a, vector bool short __b) { return __a & ~__b; } static __inline__ vector int __ATTRS_o_ai vec_vandc(vector int __a, vector int __b) { return __a & ~__b; } static __inline__ vector int __ATTRS_o_ai vec_vandc(vector bool int __a, vector int __b) { return (vector int)__a & ~__b; } static __inline__ vector int __ATTRS_o_ai vec_vandc(vector int __a, vector bool int __b) { return __a & ~(vector int)__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vandc(vector unsigned int __a, vector unsigned int __b) { return __a & ~__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vandc(vector bool int __a, vector unsigned int __b) { return (vector unsigned int)__a & ~__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vandc(vector unsigned int __a, vector bool int __b) { return __a & ~(vector unsigned int)__b; } static __inline__ vector bool int __ATTRS_o_ai vec_vandc(vector bool int __a, vector bool int __b) { return __a & ~__b; } static __inline__ vector float __ATTRS_o_ai vec_vandc(vector float __a, vector float __b) { vector unsigned int __res = (vector unsigned int)__a & ~(vector unsigned int)__b; return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_vandc(vector bool int __a, vector float __b) { vector unsigned int __res = (vector unsigned int)__a & ~(vector unsigned int)__b; return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_vandc(vector float __a, vector bool int __b) { vector unsigned int __res = (vector unsigned int)__a & ~(vector unsigned int)__b; return (vector float)__res; } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_vandc(vector signed long long __a, vector signed long long __b) { return __a & ~__b; } static __inline__ vector signed long long __ATTRS_o_ai vec_vandc(vector bool long long __a, vector signed long long __b) { return (vector signed long long)__a & ~__b; } static __inline__ vector signed long long __ATTRS_o_ai vec_vandc(vector signed long long __a, vector bool long long __b) { return __a & ~(vector signed long long)__b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_vandc(vector unsigned long long __a, vector unsigned long long __b) { return __a & ~__b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_vandc(vector bool long long __a, vector unsigned long long __b) { return (vector unsigned long long)__a & ~__b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_vandc(vector unsigned long long __a, vector bool long long __b) { return __a & ~(vector unsigned long long)__b; } static __inline__ vector bool long long __ATTRS_o_ai vec_vandc(vector bool long long __a, vector bool long long __b) { return __a & ~__b; } #endif /* vec_avg */ static __inline__ vector signed char __ATTRS_o_ai vec_avg(vector signed char __a, vector signed char __b) { return __builtin_altivec_vavgsb(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_avg(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vavgub(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_avg(vector short __a, vector short __b) { return __builtin_altivec_vavgsh(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_avg(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vavguh(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_avg(vector int __a, vector int __b) { return __builtin_altivec_vavgsw(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_avg(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vavguw(__a, __b); } /* vec_vavgsb */ static __inline__ vector signed char __attribute__((__always_inline__)) vec_vavgsb(vector signed char __a, vector signed char __b) { return __builtin_altivec_vavgsb(__a, __b); } /* vec_vavgub */ static __inline__ vector unsigned char __attribute__((__always_inline__)) vec_vavgub(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vavgub(__a, __b); } /* vec_vavgsh */ static __inline__ vector short __attribute__((__always_inline__)) vec_vavgsh(vector short __a, vector short __b) { return __builtin_altivec_vavgsh(__a, __b); } /* vec_vavguh */ static __inline__ vector unsigned short __attribute__((__always_inline__)) vec_vavguh(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vavguh(__a, __b); } /* vec_vavgsw */ static __inline__ vector int __attribute__((__always_inline__)) vec_vavgsw(vector int __a, vector int __b) { return __builtin_altivec_vavgsw(__a, __b); } /* vec_vavguw */ static __inline__ vector unsigned int __attribute__((__always_inline__)) vec_vavguw(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vavguw(__a, __b); } /* vec_ceil */ static __inline__ vector float __ATTRS_o_ai vec_ceil(vector float __a) { #ifdef __VSX__ return __builtin_vsx_xvrspip(__a); #else return __builtin_altivec_vrfip(__a); #endif } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_ceil(vector double __a) { return __builtin_vsx_xvrdpip(__a); } #endif /* vec_vrfip */ static __inline__ vector float __attribute__((__always_inline__)) vec_vrfip(vector float __a) { return __builtin_altivec_vrfip(__a); } /* vec_cmpb */ static __inline__ vector int __attribute__((__always_inline__)) vec_cmpb(vector float __a, vector float __b) { return __builtin_altivec_vcmpbfp(__a, __b); } /* vec_vcmpbfp */ static __inline__ vector int __attribute__((__always_inline__)) vec_vcmpbfp(vector float __a, vector float __b) { return __builtin_altivec_vcmpbfp(__a, __b); } /* vec_cmpeq */ static __inline__ vector bool char __ATTRS_o_ai vec_cmpeq(vector signed char __a, vector signed char __b) { return (vector bool char)__builtin_altivec_vcmpequb((vector char)__a, (vector char)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_cmpeq(vector unsigned char __a, vector unsigned char __b) { return (vector bool char)__builtin_altivec_vcmpequb((vector char)__a, (vector char)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_cmpeq(vector bool char __a, vector bool char __b) { return (vector bool char)__builtin_altivec_vcmpequb((vector char)__a, (vector char)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_cmpeq(vector short __a, vector short __b) { return (vector bool short)__builtin_altivec_vcmpequh(__a, __b); } static __inline__ vector bool short __ATTRS_o_ai vec_cmpeq(vector unsigned short __a, vector unsigned short __b) { return (vector bool short)__builtin_altivec_vcmpequh((vector short)__a, (vector short)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_cmpeq(vector bool short __a, vector bool short __b) { return (vector bool short)__builtin_altivec_vcmpequh((vector short)__a, (vector short)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_cmpeq(vector int __a, vector int __b) { return (vector bool int)__builtin_altivec_vcmpequw(__a, __b); } static __inline__ vector bool int __ATTRS_o_ai vec_cmpeq(vector unsigned int __a, vector unsigned int __b) { return (vector bool int)__builtin_altivec_vcmpequw((vector int)__a, (vector int)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_cmpeq(vector bool int __a, vector bool int __b) { return (vector bool int)__builtin_altivec_vcmpequw((vector int)__a, (vector int)__b); } #ifdef __POWER8_VECTOR__ static __inline__ vector bool long long __ATTRS_o_ai vec_cmpeq(vector signed long long __a, vector signed long long __b) { return (vector bool long long)__builtin_altivec_vcmpequd(__a, __b); } static __inline__ vector bool long long __ATTRS_o_ai vec_cmpeq(vector unsigned long long __a, vector unsigned long long __b) { return (vector bool long long)__builtin_altivec_vcmpequd( (vector long long)__a, (vector long long)__b); } static __inline__ vector bool long long __ATTRS_o_ai vec_cmpeq(vector bool long long __a, vector bool long long __b) { return (vector bool long long)__builtin_altivec_vcmpequd( (vector long long)__a, (vector long long)__b); } #endif static __inline__ vector bool int __ATTRS_o_ai vec_cmpeq(vector float __a, vector float __b) { #ifdef __VSX__ return (vector bool int)__builtin_vsx_xvcmpeqsp(__a, __b); #else return (vector bool int)__builtin_altivec_vcmpeqfp(__a, __b); #endif } #ifdef __VSX__ static __inline__ vector bool long long __ATTRS_o_ai vec_cmpeq(vector double __a, vector double __b) { return (vector bool long long)__builtin_vsx_xvcmpeqdp(__a, __b); } #endif #ifdef __POWER9_VECTOR__ /* vec_cmpne */ static __inline__ vector bool char __ATTRS_o_ai vec_cmpne(vector bool char __a, vector bool char __b) { return (vector bool char)__builtin_altivec_vcmpneb((vector char)__a, (vector char)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_cmpne(vector signed char __a, vector signed char __b) { return (vector bool char)__builtin_altivec_vcmpneb((vector char)__a, (vector char)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_cmpne(vector unsigned char __a, vector unsigned char __b) { return (vector bool char)__builtin_altivec_vcmpneb((vector char)__a, (vector char)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_cmpne(vector bool short __a, vector bool short __b) { return (vector bool short)__builtin_altivec_vcmpneh((vector short)__a, (vector short)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_cmpne(vector signed short __a, vector signed short __b) { return (vector bool short)__builtin_altivec_vcmpneh((vector short)__a, (vector short)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_cmpne(vector unsigned short __a, vector unsigned short __b) { return (vector bool short)__builtin_altivec_vcmpneh((vector short)__a, (vector short)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_cmpne(vector bool int __a, vector bool int __b) { return (vector bool int)__builtin_altivec_vcmpnew((vector int)__a, (vector int)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_cmpne(vector signed int __a, vector signed int __b) { return (vector bool int)__builtin_altivec_vcmpnew((vector int)__a, (vector int)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_cmpne(vector unsigned int __a, vector unsigned int __b) { return (vector bool int)__builtin_altivec_vcmpnew((vector int)__a, (vector int)__b); } static __inline__ vector bool long long __ATTRS_o_ai vec_cmpne(vector bool long long __a, vector bool long long __b) { return (vector bool long long) ~(__builtin_altivec_vcmpequd((vector long long)__a, (vector long long)__b)); } static __inline__ vector bool long long __ATTRS_o_ai vec_cmpne(vector signed long long __a, vector signed long long __b) { return (vector bool long long) ~(__builtin_altivec_vcmpequd((vector long long)__a, (vector long long)__b)); } static __inline__ vector bool long long __ATTRS_o_ai vec_cmpne(vector unsigned long long __a, vector unsigned long long __b) { return (vector bool long long) ~(__builtin_altivec_vcmpequd((vector long long)__a, (vector long long)__b)); } static __inline__ vector bool int __ATTRS_o_ai vec_cmpne(vector float __a, vector float __b) { return (vector bool int)__builtin_altivec_vcmpnew((vector int)__a, (vector int)__b); } static __inline__ vector bool long long __ATTRS_o_ai vec_cmpne(vector double __a, vector double __b) { return (vector bool long long) ~(__builtin_altivec_vcmpequd((vector long long)__a, (vector long long)__b)); } /* vec_cmpnez */ static __inline__ vector bool char __ATTRS_o_ai vec_cmpnez(vector signed char __a, vector signed char __b) { return (vector bool char)__builtin_altivec_vcmpnezb((vector char)__a, (vector char)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_cmpnez(vector unsigned char __a, vector unsigned char __b) { return (vector bool char)__builtin_altivec_vcmpnezb((vector char)__a, (vector char)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_cmpnez(vector signed short __a, vector signed short __b) { return (vector bool short)__builtin_altivec_vcmpnezh((vector short)__a, (vector short)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_cmpnez(vector unsigned short __a, vector unsigned short __b) { return (vector bool short)__builtin_altivec_vcmpnezh((vector short)__a, (vector short)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_cmpnez(vector signed int __a, vector signed int __b) { return (vector bool int)__builtin_altivec_vcmpnezw((vector int)__a, (vector int)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_cmpnez(vector unsigned int __a, vector unsigned int __b) { return (vector bool int)__builtin_altivec_vcmpnezw((vector int)__a, (vector int)__b); } static __inline__ signed int __ATTRS_o_ai vec_cntlz_lsbb(vector signed char __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vctzlsbb(__a); #else return __builtin_altivec_vclzlsbb(__a); #endif } static __inline__ signed int __ATTRS_o_ai vec_cntlz_lsbb(vector unsigned char __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vctzlsbb(__a); #else return __builtin_altivec_vclzlsbb(__a); #endif } static __inline__ signed int __ATTRS_o_ai vec_cnttz_lsbb(vector signed char __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vclzlsbb(__a); #else return __builtin_altivec_vctzlsbb(__a); #endif } static __inline__ signed int __ATTRS_o_ai vec_cnttz_lsbb(vector unsigned char __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vclzlsbb(__a); #else return __builtin_altivec_vctzlsbb(__a); #endif } static __inline__ vector unsigned int __ATTRS_o_ai vec_parity_lsbb(vector unsigned int __a) { return __builtin_altivec_vprtybw(__a); } static __inline__ vector unsigned int __ATTRS_o_ai vec_parity_lsbb(vector signed int __a) { return __builtin_altivec_vprtybw(__a); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_parity_lsbb(vector unsigned __int128 __a) { return __builtin_altivec_vprtybq(__a); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_parity_lsbb(vector signed __int128 __a) { return __builtin_altivec_vprtybq(__a); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_parity_lsbb(vector unsigned long long __a) { return __builtin_altivec_vprtybd(__a); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_parity_lsbb(vector signed long long __a) { return __builtin_altivec_vprtybd(__a); } #endif /* vec_cmpgt */ static __inline__ vector bool char __ATTRS_o_ai vec_cmpgt(vector signed char __a, vector signed char __b) { return (vector bool char)__builtin_altivec_vcmpgtsb(__a, __b); } static __inline__ vector bool char __ATTRS_o_ai vec_cmpgt(vector unsigned char __a, vector unsigned char __b) { return (vector bool char)__builtin_altivec_vcmpgtub(__a, __b); } static __inline__ vector bool short __ATTRS_o_ai vec_cmpgt(vector short __a, vector short __b) { return (vector bool short)__builtin_altivec_vcmpgtsh(__a, __b); } static __inline__ vector bool short __ATTRS_o_ai vec_cmpgt(vector unsigned short __a, vector unsigned short __b) { return (vector bool short)__builtin_altivec_vcmpgtuh(__a, __b); } static __inline__ vector bool int __ATTRS_o_ai vec_cmpgt(vector int __a, vector int __b) { return (vector bool int)__builtin_altivec_vcmpgtsw(__a, __b); } static __inline__ vector bool int __ATTRS_o_ai vec_cmpgt(vector unsigned int __a, vector unsigned int __b) { return (vector bool int)__builtin_altivec_vcmpgtuw(__a, __b); } #ifdef __POWER8_VECTOR__ static __inline__ vector bool long long __ATTRS_o_ai vec_cmpgt(vector signed long long __a, vector signed long long __b) { return (vector bool long long)__builtin_altivec_vcmpgtsd(__a, __b); } static __inline__ vector bool long long __ATTRS_o_ai vec_cmpgt(vector unsigned long long __a, vector unsigned long long __b) { return (vector bool long long)__builtin_altivec_vcmpgtud(__a, __b); } #endif static __inline__ vector bool int __ATTRS_o_ai vec_cmpgt(vector float __a, vector float __b) { #ifdef __VSX__ return (vector bool int)__builtin_vsx_xvcmpgtsp(__a, __b); #else return (vector bool int)__builtin_altivec_vcmpgtfp(__a, __b); #endif } #ifdef __VSX__ static __inline__ vector bool long long __ATTRS_o_ai vec_cmpgt(vector double __a, vector double __b) { return (vector bool long long)__builtin_vsx_xvcmpgtdp(__a, __b); } #endif /* vec_cmpge */ static __inline__ vector bool char __ATTRS_o_ai vec_cmpge(vector signed char __a, vector signed char __b) { return ~(vec_cmpgt(__b, __a)); } static __inline__ vector bool char __ATTRS_o_ai vec_cmpge(vector unsigned char __a, vector unsigned char __b) { return ~(vec_cmpgt(__b, __a)); } static __inline__ vector bool short __ATTRS_o_ai vec_cmpge(vector signed short __a, vector signed short __b) { return ~(vec_cmpgt(__b, __a)); } static __inline__ vector bool short __ATTRS_o_ai vec_cmpge(vector unsigned short __a, vector unsigned short __b) { return ~(vec_cmpgt(__b, __a)); } static __inline__ vector bool int __ATTRS_o_ai vec_cmpge(vector signed int __a, vector signed int __b) { return ~(vec_cmpgt(__b, __a)); } static __inline__ vector bool int __ATTRS_o_ai vec_cmpge(vector unsigned int __a, vector unsigned int __b) { return ~(vec_cmpgt(__b, __a)); } static __inline__ vector bool int __ATTRS_o_ai vec_cmpge(vector float __a, vector float __b) { #ifdef __VSX__ return (vector bool int)__builtin_vsx_xvcmpgesp(__a, __b); #else return (vector bool int)__builtin_altivec_vcmpgefp(__a, __b); #endif } #ifdef __VSX__ static __inline__ vector bool long long __ATTRS_o_ai vec_cmpge(vector double __a, vector double __b) { return (vector bool long long)__builtin_vsx_xvcmpgedp(__a, __b); } #endif #ifdef __POWER8_VECTOR__ static __inline__ vector bool long long __ATTRS_o_ai vec_cmpge(vector signed long long __a, vector signed long long __b) { return ~(vec_cmpgt(__b, __a)); } static __inline__ vector bool long long __ATTRS_o_ai vec_cmpge(vector unsigned long long __a, vector unsigned long long __b) { return ~(vec_cmpgt(__b, __a)); } #endif /* vec_vcmpgefp */ static __inline__ vector bool int __attribute__((__always_inline__)) vec_vcmpgefp(vector float __a, vector float __b) { return (vector bool int)__builtin_altivec_vcmpgefp(__a, __b); } /* vec_vcmpgtsb */ static __inline__ vector bool char __attribute__((__always_inline__)) vec_vcmpgtsb(vector signed char __a, vector signed char __b) { return (vector bool char)__builtin_altivec_vcmpgtsb(__a, __b); } /* vec_vcmpgtub */ static __inline__ vector bool char __attribute__((__always_inline__)) vec_vcmpgtub(vector unsigned char __a, vector unsigned char __b) { return (vector bool char)__builtin_altivec_vcmpgtub(__a, __b); } /* vec_vcmpgtsh */ static __inline__ vector bool short __attribute__((__always_inline__)) vec_vcmpgtsh(vector short __a, vector short __b) { return (vector bool short)__builtin_altivec_vcmpgtsh(__a, __b); } /* vec_vcmpgtuh */ static __inline__ vector bool short __attribute__((__always_inline__)) vec_vcmpgtuh(vector unsigned short __a, vector unsigned short __b) { return (vector bool short)__builtin_altivec_vcmpgtuh(__a, __b); } /* vec_vcmpgtsw */ static __inline__ vector bool int __attribute__((__always_inline__)) vec_vcmpgtsw(vector int __a, vector int __b) { return (vector bool int)__builtin_altivec_vcmpgtsw(__a, __b); } /* vec_vcmpgtuw */ static __inline__ vector bool int __attribute__((__always_inline__)) vec_vcmpgtuw(vector unsigned int __a, vector unsigned int __b) { return (vector bool int)__builtin_altivec_vcmpgtuw(__a, __b); } /* vec_vcmpgtfp */ static __inline__ vector bool int __attribute__((__always_inline__)) vec_vcmpgtfp(vector float __a, vector float __b) { return (vector bool int)__builtin_altivec_vcmpgtfp(__a, __b); } /* vec_cmple */ static __inline__ vector bool char __ATTRS_o_ai vec_cmple(vector signed char __a, vector signed char __b) { return vec_cmpge(__b, __a); } static __inline__ vector bool char __ATTRS_o_ai vec_cmple(vector unsigned char __a, vector unsigned char __b) { return vec_cmpge(__b, __a); } static __inline__ vector bool short __ATTRS_o_ai vec_cmple(vector signed short __a, vector signed short __b) { return vec_cmpge(__b, __a); } static __inline__ vector bool short __ATTRS_o_ai vec_cmple(vector unsigned short __a, vector unsigned short __b) { return vec_cmpge(__b, __a); } static __inline__ vector bool int __ATTRS_o_ai vec_cmple(vector signed int __a, vector signed int __b) { return vec_cmpge(__b, __a); } static __inline__ vector bool int __ATTRS_o_ai vec_cmple(vector unsigned int __a, vector unsigned int __b) { return vec_cmpge(__b, __a); } static __inline__ vector bool int __ATTRS_o_ai vec_cmple(vector float __a, vector float __b) { return vec_cmpge(__b, __a); } #ifdef __VSX__ static __inline__ vector bool long long __ATTRS_o_ai vec_cmple(vector double __a, vector double __b) { return vec_cmpge(__b, __a); } #endif #ifdef __POWER8_VECTOR__ static __inline__ vector bool long long __ATTRS_o_ai vec_cmple(vector signed long long __a, vector signed long long __b) { return vec_cmpge(__b, __a); } static __inline__ vector bool long long __ATTRS_o_ai vec_cmple(vector unsigned long long __a, vector unsigned long long __b) { return vec_cmpge(__b, __a); } #endif /* vec_cmplt */ static __inline__ vector bool char __ATTRS_o_ai vec_cmplt(vector signed char __a, vector signed char __b) { return vec_cmpgt(__b, __a); } static __inline__ vector bool char __ATTRS_o_ai vec_cmplt(vector unsigned char __a, vector unsigned char __b) { return vec_cmpgt(__b, __a); } static __inline__ vector bool short __ATTRS_o_ai vec_cmplt(vector short __a, vector short __b) { return vec_cmpgt(__b, __a); } static __inline__ vector bool short __ATTRS_o_ai vec_cmplt(vector unsigned short __a, vector unsigned short __b) { return vec_cmpgt(__b, __a); } static __inline__ vector bool int __ATTRS_o_ai vec_cmplt(vector int __a, vector int __b) { return vec_cmpgt(__b, __a); } static __inline__ vector bool int __ATTRS_o_ai vec_cmplt(vector unsigned int __a, vector unsigned int __b) { return vec_cmpgt(__b, __a); } static __inline__ vector bool int __ATTRS_o_ai vec_cmplt(vector float __a, vector float __b) { return vec_cmpgt(__b, __a); } #ifdef __VSX__ static __inline__ vector bool long long __ATTRS_o_ai vec_cmplt(vector double __a, vector double __b) { return vec_cmpgt(__b, __a); } #endif #ifdef __POWER8_VECTOR__ static __inline__ vector bool long long __ATTRS_o_ai vec_cmplt(vector signed long long __a, vector signed long long __b) { return vec_cmpgt(__b, __a); } static __inline__ vector bool long long __ATTRS_o_ai vec_cmplt(vector unsigned long long __a, vector unsigned long long __b) { return vec_cmpgt(__b, __a); } /* vec_popcnt */ static __inline__ vector signed char __ATTRS_o_ai vec_popcnt(vector signed char __a) { return __builtin_altivec_vpopcntb(__a); } static __inline__ vector unsigned char __ATTRS_o_ai vec_popcnt(vector unsigned char __a) { return __builtin_altivec_vpopcntb(__a); } static __inline__ vector signed short __ATTRS_o_ai vec_popcnt(vector signed short __a) { return __builtin_altivec_vpopcnth(__a); } static __inline__ vector unsigned short __ATTRS_o_ai vec_popcnt(vector unsigned short __a) { return __builtin_altivec_vpopcnth(__a); } static __inline__ vector signed int __ATTRS_o_ai vec_popcnt(vector signed int __a) { return __builtin_altivec_vpopcntw(__a); } static __inline__ vector unsigned int __ATTRS_o_ai vec_popcnt(vector unsigned int __a) { return __builtin_altivec_vpopcntw(__a); } static __inline__ vector signed long long __ATTRS_o_ai vec_popcnt(vector signed long long __a) { return __builtin_altivec_vpopcntd(__a); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_popcnt(vector unsigned long long __a) { return __builtin_altivec_vpopcntd(__a); } /* vec_cntlz */ static __inline__ vector signed char __ATTRS_o_ai vec_cntlz(vector signed char __a) { return __builtin_altivec_vclzb(__a); } static __inline__ vector unsigned char __ATTRS_o_ai vec_cntlz(vector unsigned char __a) { return __builtin_altivec_vclzb(__a); } static __inline__ vector signed short __ATTRS_o_ai vec_cntlz(vector signed short __a) { return __builtin_altivec_vclzh(__a); } static __inline__ vector unsigned short __ATTRS_o_ai vec_cntlz(vector unsigned short __a) { return __builtin_altivec_vclzh(__a); } static __inline__ vector signed int __ATTRS_o_ai vec_cntlz(vector signed int __a) { return __builtin_altivec_vclzw(__a); } static __inline__ vector unsigned int __ATTRS_o_ai vec_cntlz(vector unsigned int __a) { return __builtin_altivec_vclzw(__a); } static __inline__ vector signed long long __ATTRS_o_ai vec_cntlz(vector signed long long __a) { return __builtin_altivec_vclzd(__a); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_cntlz(vector unsigned long long __a) { return __builtin_altivec_vclzd(__a); } #endif #ifdef __POWER9_VECTOR__ /* vec_cnttz */ static __inline__ vector signed char __ATTRS_o_ai vec_cnttz(vector signed char __a) { return __builtin_altivec_vctzb(__a); } static __inline__ vector unsigned char __ATTRS_o_ai vec_cnttz(vector unsigned char __a) { return __builtin_altivec_vctzb(__a); } static __inline__ vector signed short __ATTRS_o_ai vec_cnttz(vector signed short __a) { return __builtin_altivec_vctzh(__a); } static __inline__ vector unsigned short __ATTRS_o_ai vec_cnttz(vector unsigned short __a) { return __builtin_altivec_vctzh(__a); } static __inline__ vector signed int __ATTRS_o_ai vec_cnttz(vector signed int __a) { return __builtin_altivec_vctzw(__a); } static __inline__ vector unsigned int __ATTRS_o_ai vec_cnttz(vector unsigned int __a) { return __builtin_altivec_vctzw(__a); } static __inline__ vector signed long long __ATTRS_o_ai vec_cnttz(vector signed long long __a) { return __builtin_altivec_vctzd(__a); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_cnttz(vector unsigned long long __a) { return __builtin_altivec_vctzd(__a); } /* vec_first_match_index */ static __inline__ unsigned __ATTRS_o_ai vec_first_match_index(vector signed char __a, vector signed char __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpeq(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpeq(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 3; } return __res[0] >> 3; } static __inline__ unsigned __ATTRS_o_ai vec_first_match_index(vector unsigned char __a, vector unsigned char __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpeq(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpeq(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 3; } return __res[0] >> 3; } static __inline__ unsigned __ATTRS_o_ai vec_first_match_index(vector signed short __a, vector signed short __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpeq(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpeq(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 4; } return __res[0] >> 4; } static __inline__ unsigned __ATTRS_o_ai vec_first_match_index(vector unsigned short __a, vector unsigned short __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpeq(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpeq(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 4; } return __res[0] >> 4; } static __inline__ unsigned __ATTRS_o_ai vec_first_match_index(vector signed int __a, vector signed int __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpeq(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpeq(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 5; } return __res[0] >> 5; } static __inline__ unsigned __ATTRS_o_ai vec_first_match_index(vector unsigned int __a, vector unsigned int __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpeq(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpeq(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 5; } return __res[0] >> 5; } /* vec_first_match_or_eos_index */ static __inline__ unsigned __ATTRS_o_ai vec_first_match_or_eos_index(vector signed char __a, vector signed char __b) { /* Compare the result of the comparison of two vectors with either and OR the result. Either the elements are equal or one will equal the comparison result if either is zero. */ vector bool char __tmp1 = vec_cmpeq(__a, __b); vector bool char __tmp2 = __tmp1 | vec_cmpeq((vector signed char)__tmp1, __a) | vec_cmpeq((vector signed char)__tmp1, __b); vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)__tmp2); #else vec_cntlz((vector unsigned long long)__tmp2); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 3; } return __res[0] >> 3; } static __inline__ unsigned __ATTRS_o_ai vec_first_match_or_eos_index(vector unsigned char __a, vector unsigned char __b) { vector bool char __tmp1 = vec_cmpeq(__a, __b); vector bool char __tmp2 = __tmp1 | vec_cmpeq((vector unsigned char)__tmp1, __a) | vec_cmpeq((vector unsigned char)__tmp1, __b); vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)__tmp2); #else vec_cntlz((vector unsigned long long)__tmp2); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 3; } return __res[0] >> 3; } static __inline__ unsigned __ATTRS_o_ai vec_first_match_or_eos_index(vector signed short __a, vector signed short __b) { vector bool short __tmp1 = vec_cmpeq(__a, __b); vector bool short __tmp2 = __tmp1 | vec_cmpeq((vector signed short)__tmp1, __a) | vec_cmpeq((vector signed short)__tmp1, __b); vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)__tmp2); #else vec_cntlz((vector unsigned long long)__tmp2); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 4; } return __res[0] >> 4; } static __inline__ unsigned __ATTRS_o_ai vec_first_match_or_eos_index(vector unsigned short __a, vector unsigned short __b) { vector bool short __tmp1 = vec_cmpeq(__a, __b); vector bool short __tmp2 = __tmp1 | vec_cmpeq((vector unsigned short)__tmp1, __a) | vec_cmpeq((vector unsigned short)__tmp1, __b); vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)__tmp2); #else vec_cntlz((vector unsigned long long)__tmp2); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 4; } return __res[0] >> 4; } static __inline__ unsigned __ATTRS_o_ai vec_first_match_or_eos_index(vector signed int __a, vector signed int __b) { vector bool int __tmp1 = vec_cmpeq(__a, __b); vector bool int __tmp2 = __tmp1 | vec_cmpeq((vector signed int)__tmp1, __a) | vec_cmpeq((vector signed int)__tmp1, __b); vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)__tmp2); #else vec_cntlz((vector unsigned long long)__tmp2); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 5; } return __res[0] >> 5; } static __inline__ unsigned __ATTRS_o_ai vec_first_match_or_eos_index(vector unsigned int __a, vector unsigned int __b) { vector bool int __tmp1 = vec_cmpeq(__a, __b); vector bool int __tmp2 = __tmp1 | vec_cmpeq((vector unsigned int)__tmp1, __a) | vec_cmpeq((vector unsigned int)__tmp1, __b); vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)__tmp2); #else vec_cntlz((vector unsigned long long)__tmp2); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 5; } return __res[0] >> 5; } /* vec_first_mismatch_index */ static __inline__ unsigned __ATTRS_o_ai vec_first_mismatch_index(vector signed char __a, vector signed char __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpne(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpne(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 3; } return __res[0] >> 3; } static __inline__ unsigned __ATTRS_o_ai vec_first_mismatch_index(vector unsigned char __a, vector unsigned char __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpne(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpne(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 3; } return __res[0] >> 3; } static __inline__ unsigned __ATTRS_o_ai vec_first_mismatch_index(vector signed short __a, vector signed short __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpne(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpne(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 4; } return __res[0] >> 4; } static __inline__ unsigned __ATTRS_o_ai vec_first_mismatch_index(vector unsigned short __a, vector unsigned short __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpne(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpne(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 4; } return __res[0] >> 4; } static __inline__ unsigned __ATTRS_o_ai vec_first_mismatch_index(vector signed int __a, vector signed int __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpne(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpne(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 5; } return __res[0] >> 5; } static __inline__ unsigned __ATTRS_o_ai vec_first_mismatch_index(vector unsigned int __a, vector unsigned int __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpne(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpne(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 5; } return __res[0] >> 5; } /* vec_first_mismatch_or_eos_index */ static __inline__ unsigned __ATTRS_o_ai vec_first_mismatch_or_eos_index(vector signed char __a, vector signed char __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpnez(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpnez(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 3; } return __res[0] >> 3; } static __inline__ unsigned __ATTRS_o_ai vec_first_mismatch_or_eos_index(vector unsigned char __a, vector unsigned char __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpnez(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpnez(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 3; } return __res[0] >> 3; } static __inline__ unsigned __ATTRS_o_ai vec_first_mismatch_or_eos_index(vector signed short __a, vector signed short __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpnez(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpnez(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 4; } return __res[0] >> 4; } static __inline__ unsigned __ATTRS_o_ai vec_first_mismatch_or_eos_index(vector unsigned short __a, vector unsigned short __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpnez(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpnez(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 4; } return __res[0] >> 4; } static __inline__ unsigned __ATTRS_o_ai vec_first_mismatch_or_eos_index(vector signed int __a, vector signed int __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpnez(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpnez(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 5; } return __res[0] >> 5; } static __inline__ unsigned __ATTRS_o_ai vec_first_mismatch_or_eos_index(vector unsigned int __a, vector unsigned int __b) { vector unsigned long long __res = #ifdef __LITTLE_ENDIAN__ vec_cnttz((vector unsigned long long)vec_cmpnez(__a, __b)); #else vec_cntlz((vector unsigned long long)vec_cmpnez(__a, __b)); #endif if (__res[0] == 64) { return (__res[1] + 64) >> 5; } return __res[0] >> 5; } static __inline__ vector double __ATTRS_o_ai vec_insert_exp(vector double __a, vector unsigned long long __b) { return __builtin_vsx_xviexpdp((vector unsigned long long)__a,__b); } static __inline__ vector double __ATTRS_o_ai vec_insert_exp(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_vsx_xviexpdp(__a,__b); } static __inline__ vector float __ATTRS_o_ai vec_insert_exp(vector float __a, vector unsigned int __b) { return __builtin_vsx_xviexpsp((vector unsigned int)__a,__b); } static __inline__ vector float __ATTRS_o_ai vec_insert_exp(vector unsigned int __a, vector unsigned int __b) { return __builtin_vsx_xviexpsp(__a,__b); } #if defined(__powerpc64__) static __inline__ vector signed char __ATTRS_o_ai vec_xl_len(signed char *__a, size_t __b) { return (vector signed char)__builtin_vsx_lxvl(__a, (__b << 56)); } static __inline__ vector unsigned char __ATTRS_o_ai vec_xl_len(unsigned char *__a, size_t __b) { return (vector unsigned char)__builtin_vsx_lxvl(__a, (__b << 56)); } static __inline__ vector signed short __ATTRS_o_ai vec_xl_len(signed short *__a, size_t __b) { return (vector signed short)__builtin_vsx_lxvl(__a, (__b << 56)); } static __inline__ vector unsigned short __ATTRS_o_ai vec_xl_len(unsigned short *__a, size_t __b) { return (vector unsigned short)__builtin_vsx_lxvl(__a, (__b << 56)); } static __inline__ vector signed int __ATTRS_o_ai vec_xl_len(signed int *__a, size_t __b) { return (vector signed int)__builtin_vsx_lxvl(__a, (__b << 56)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_xl_len(unsigned int *__a, size_t __b) { return (vector unsigned int)__builtin_vsx_lxvl(__a, (__b << 56)); } static __inline__ vector float __ATTRS_o_ai vec_xl_len(float *__a, size_t __b) { return (vector float)__builtin_vsx_lxvl(__a, (__b << 56)); } static __inline__ vector signed __int128 __ATTRS_o_ai vec_xl_len(signed __int128 *__a, size_t __b) { return (vector signed __int128)__builtin_vsx_lxvl(__a, (__b << 56)); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_xl_len(unsigned __int128 *__a, size_t __b) { return (vector unsigned __int128)__builtin_vsx_lxvl(__a, (__b << 56)); } static __inline__ vector signed long long __ATTRS_o_ai vec_xl_len(signed long long *__a, size_t __b) { return (vector signed long long)__builtin_vsx_lxvl(__a, (__b << 56)); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_xl_len(unsigned long long *__a, size_t __b) { return (vector unsigned long long)__builtin_vsx_lxvl(__a, (__b << 56)); } static __inline__ vector double __ATTRS_o_ai vec_xl_len(double *__a, size_t __b) { return (vector double)__builtin_vsx_lxvl(__a, (__b << 56)); } static __inline__ vector double __ATTRS_o_ai vec_xl_len_r(unsigned char *__a, size_t __b) { vector unsigned char __res = (vector unsigned char)__builtin_vsx_lxvll(__a, (__b << 56)); #ifdef __LITTLE_ENDIAN__ vector unsigned char __mask = (vector unsigned char)__builtin_altivec_lvsr(16 - __b, (int *)NULL); __res = (vector unsigned char)__builtin_altivec_vperm_4si( (vector int)__res, (vector int)__res, __mask); #endif return __res; } // vec_xst_len static __inline__ void __ATTRS_o_ai vec_xst_len(vector unsigned char __a, unsigned char *__b, size_t __c) { return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56)); } static __inline__ void __ATTRS_o_ai vec_xst_len(vector signed char __a, signed char *__b, size_t __c) { return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56)); } static __inline__ void __ATTRS_o_ai vec_xst_len(vector signed short __a, signed short *__b, size_t __c) { return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56)); } static __inline__ void __ATTRS_o_ai vec_xst_len(vector unsigned short __a, unsigned short *__b, size_t __c) { return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56)); } static __inline__ void __ATTRS_o_ai vec_xst_len(vector signed int __a, signed int *__b, size_t __c) { return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56)); } static __inline__ void __ATTRS_o_ai vec_xst_len(vector unsigned int __a, unsigned int *__b, size_t __c) { return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56)); } static __inline__ void __ATTRS_o_ai vec_xst_len(vector float __a, float *__b, size_t __c) { return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56)); } static __inline__ void __ATTRS_o_ai vec_xst_len(vector signed __int128 __a, signed __int128 *__b, size_t __c) { return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56)); } static __inline__ void __ATTRS_o_ai vec_xst_len(vector unsigned __int128 __a, unsigned __int128 *__b, size_t __c) { return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56)); } static __inline__ void __ATTRS_o_ai vec_xst_len(vector signed long long __a, signed long long *__b, size_t __c) { return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56)); } static __inline__ void __ATTRS_o_ai vec_xst_len(vector unsigned long long __a, unsigned long long *__b, size_t __c) { return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56)); } static __inline__ void __ATTRS_o_ai vec_xst_len(vector double __a, double *__b, size_t __c) { return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56)); } static __inline__ void __ATTRS_o_ai vec_xst_len_r(vector unsigned char __a, unsigned char *__b, size_t __c) { #ifdef __LITTLE_ENDIAN__ vector unsigned char __mask = (vector unsigned char)__builtin_altivec_lvsl(16 - __c, (int *)NULL); vector unsigned char __res = __builtin_altivec_vperm_4si((vector int)__a, (vector int)__a, __mask); return __builtin_vsx_stxvll((vector int)__res, __b, (__c << 56)); #else return __builtin_vsx_stxvll((vector int)__a, __b, (__c << 56)); #endif } #endif #endif /* vec_cpsgn */ #ifdef __VSX__ static __inline__ vector float __ATTRS_o_ai vec_cpsgn(vector float __a, vector float __b) { return __builtin_vsx_xvcpsgnsp(__a, __b); } static __inline__ vector double __ATTRS_o_ai vec_cpsgn(vector double __a, vector double __b) { return __builtin_vsx_xvcpsgndp(__a, __b); } #endif /* vec_ctf */ #ifdef __VSX__ #define vec_ctf(__a, __b) \ _Generic((__a), vector int \ : (vector float)__builtin_altivec_vcfsx((__a), (__b)), \ vector unsigned int \ : (vector float)__builtin_altivec_vcfux((vector int)(__a), (__b)), \ vector unsigned long long \ : (__builtin_convertvector((vector unsigned long long)(__a), \ vector double) * \ (vector double)(vector unsigned long long)((0x3ffULL - (__b)) \ << 52)), \ vector signed long long \ : (__builtin_convertvector((vector signed long long)(__a), \ vector double) * \ (vector double)(vector unsigned long long)((0x3ffULL - (__b)) \ << 52))) #else #define vec_ctf(__a, __b) \ _Generic((__a), vector int \ : (vector float)__builtin_altivec_vcfsx((__a), (__b)), \ vector unsigned int \ : (vector float)__builtin_altivec_vcfux((vector int)(__a), (__b))) #endif /* vec_vcfsx */ #define vec_vcfux __builtin_altivec_vcfux /* vec_vcfux */ #define vec_vcfsx(__a, __b) __builtin_altivec_vcfsx((vector int)(__a), (__b)) /* vec_cts */ #ifdef __VSX__ #define vec_cts(__a, __b) \ _Generic((__a), vector float \ : __builtin_altivec_vctsxs((__a), (__b)), vector double \ : __extension__({ \ vector double __ret = \ (__a) * \ (vector double)(vector unsigned long long)((0x3ffULL + (__b)) \ << 52); \ __builtin_convertvector(__ret, vector signed long long); \ })) #else #define vec_cts __builtin_altivec_vctsxs #endif /* vec_vctsxs */ #define vec_vctsxs __builtin_altivec_vctsxs /* vec_ctu */ #ifdef __VSX__ #define vec_ctu(__a, __b) \ _Generic((__a), vector float \ : __builtin_altivec_vctuxs((__a), (__b)), vector double \ : __extension__({ \ vector double __ret = \ (__a) * \ (vector double)(vector unsigned long long)((0x3ffULL + __b) \ << 52); \ __builtin_convertvector(__ret, vector unsigned long long); \ })) #else #define vec_ctu __builtin_altivec_vctuxs #endif /* vec_vctuxs */ #define vec_vctuxs __builtin_altivec_vctuxs /* vec_signed */ static __inline__ vector signed int __ATTRS_o_ai vec_sld(vector signed int, vector signed int, unsigned const int __c); static __inline__ vector signed int __ATTRS_o_ai vec_signed(vector float __a) { return __builtin_convertvector(__a, vector signed int); } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_signed(vector double __a) { return __builtin_convertvector(__a, vector signed long long); } static __inline__ vector signed int __attribute__((__always_inline__)) vec_signed2(vector double __a, vector double __b) { return (vector signed int) { __a[0], __a[1], __b[0], __b[1] }; } static __inline__ vector signed int __ATTRS_o_ai vec_signede(vector double __a) { #ifdef __LITTLE_ENDIAN__ vector signed int __ret = __builtin_vsx_xvcvdpsxws(__a); return vec_sld(__ret, __ret, 12); #else return __builtin_vsx_xvcvdpsxws(__a); #endif } static __inline__ vector signed int __ATTRS_o_ai vec_signedo(vector double __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_vsx_xvcvdpsxws(__a); #else vector signed int __ret = __builtin_vsx_xvcvdpsxws(__a); return vec_sld(__ret, __ret, 12); #endif } #endif /* vec_unsigned */ static __inline__ vector unsigned int __ATTRS_o_ai vec_sld(vector unsigned int, vector unsigned int, unsigned const int __c); static __inline__ vector unsigned int __ATTRS_o_ai vec_unsigned(vector float __a) { return __builtin_convertvector(__a, vector unsigned int); } #ifdef __VSX__ static __inline__ vector unsigned long long __ATTRS_o_ai vec_unsigned(vector double __a) { return __builtin_convertvector(__a, vector unsigned long long); } static __inline__ vector unsigned int __attribute__((__always_inline__)) vec_unsigned2(vector double __a, vector double __b) { return (vector unsigned int) { __a[0], __a[1], __b[0], __b[1] }; } static __inline__ vector unsigned int __ATTRS_o_ai vec_unsignede(vector double __a) { #ifdef __LITTLE_ENDIAN__ vector unsigned int __ret = __builtin_vsx_xvcvdpuxws(__a); return vec_sld(__ret, __ret, 12); #else return __builtin_vsx_xvcvdpuxws(__a); #endif } static __inline__ vector unsigned int __ATTRS_o_ai vec_unsignedo(vector double __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_vsx_xvcvdpuxws(__a); #else vector unsigned int __ret = __builtin_vsx_xvcvdpuxws(__a); return vec_sld(__ret, __ret, 12); #endif } #endif /* vec_float */ static __inline__ vector float __ATTRS_o_ai vec_sld(vector float, vector float, unsigned const int __c); static __inline__ vector float __ATTRS_o_ai vec_float(vector signed int __a) { return __builtin_convertvector(__a, vector float); } static __inline__ vector float __ATTRS_o_ai vec_float(vector unsigned int __a) { return __builtin_convertvector(__a, vector float); } #ifdef __VSX__ static __inline__ vector float __ATTRS_o_ai vec_float2(vector signed long long __a, vector signed long long __b) { return (vector float) { __a[0], __a[1], __b[0], __b[1] }; } static __inline__ vector float __ATTRS_o_ai vec_float2(vector unsigned long long __a, vector unsigned long long __b) { return (vector float) { __a[0], __a[1], __b[0], __b[1] }; } static __inline__ vector float __ATTRS_o_ai vec_float2(vector double __a, vector double __b) { return (vector float) { __a[0], __a[1], __b[0], __b[1] }; } static __inline__ vector float __ATTRS_o_ai vec_floate(vector signed long long __a) { #ifdef __LITTLE_ENDIAN__ vector float __ret = __builtin_vsx_xvcvsxdsp(__a); return vec_sld(__ret, __ret, 12); #else return __builtin_vsx_xvcvsxdsp(__a); #endif } static __inline__ vector float __ATTRS_o_ai vec_floate(vector unsigned long long __a) { #ifdef __LITTLE_ENDIAN__ vector float __ret = __builtin_vsx_xvcvuxdsp(__a); return vec_sld(__ret, __ret, 12); #else return __builtin_vsx_xvcvuxdsp(__a); #endif } static __inline__ vector float __ATTRS_o_ai vec_floate(vector double __a) { #ifdef __LITTLE_ENDIAN__ vector float __ret = __builtin_vsx_xvcvdpsp(__a); return vec_sld(__ret, __ret, 12); #else return __builtin_vsx_xvcvdpsp(__a); #endif } static __inline__ vector float __ATTRS_o_ai vec_floato(vector signed long long __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_vsx_xvcvsxdsp(__a); #else vector float __ret = __builtin_vsx_xvcvsxdsp(__a); return vec_sld(__ret, __ret, 12); #endif } static __inline__ vector float __ATTRS_o_ai vec_floato(vector unsigned long long __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_vsx_xvcvuxdsp(__a); #else vector float __ret = __builtin_vsx_xvcvuxdsp(__a); return vec_sld(__ret, __ret, 12); #endif } static __inline__ vector float __ATTRS_o_ai vec_floato(vector double __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_vsx_xvcvdpsp(__a); #else vector float __ret = __builtin_vsx_xvcvdpsp(__a); return vec_sld(__ret, __ret, 12); #endif } #endif /* vec_double */ #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_double(vector signed long long __a) { return __builtin_convertvector(__a, vector double); } static __inline__ vector double __ATTRS_o_ai vec_double(vector unsigned long long __a) { return __builtin_convertvector(__a, vector double); } static __inline__ vector double __ATTRS_o_ai vec_doublee(vector signed int __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_vsx_xvcvsxwdp(vec_sld(__a, __a, 4)); #else return __builtin_vsx_xvcvsxwdp(__a); #endif } static __inline__ vector double __ATTRS_o_ai vec_doublee(vector unsigned int __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_vsx_xvcvuxwdp(vec_sld(__a, __a, 4)); #else return __builtin_vsx_xvcvuxwdp(__a); #endif } static __inline__ vector double __ATTRS_o_ai vec_doublee(vector float __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_vsx_xvcvspdp(vec_sld(__a, __a, 4)); #else return __builtin_vsx_xvcvspdp(__a); #endif } static __inline__ vector double __ATTRS_o_ai vec_doubleh(vector signed int __a) { vector double __ret = {__a[0], __a[1]}; return __ret; } static __inline__ vector double __ATTRS_o_ai vec_doubleh(vector unsigned int __a) { vector double __ret = {__a[0], __a[1]}; return __ret; } static __inline__ vector double __ATTRS_o_ai vec_doubleh(vector float __a) { vector double __ret = {__a[0], __a[1]}; return __ret; } static __inline__ vector double __ATTRS_o_ai vec_doublel(vector signed int __a) { vector double __ret = {__a[2], __a[3]}; return __ret; } static __inline__ vector double __ATTRS_o_ai vec_doublel(vector unsigned int __a) { vector double __ret = {__a[2], __a[3]}; return __ret; } static __inline__ vector double __ATTRS_o_ai vec_doublel(vector float __a) { vector double __ret = {__a[2], __a[3]}; return __ret; } static __inline__ vector double __ATTRS_o_ai vec_doubleo(vector signed int __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_vsx_xvcvsxwdp(__a); #else return __builtin_vsx_xvcvsxwdp(vec_sld(__a, __a, 4)); #endif } static __inline__ vector double __ATTRS_o_ai vec_doubleo(vector unsigned int __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_vsx_xvcvuxwdp(__a); #else return __builtin_vsx_xvcvuxwdp(vec_sld(__a, __a, 4)); #endif } static __inline__ vector double __ATTRS_o_ai vec_doubleo(vector float __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_vsx_xvcvspdp(__a); #else return __builtin_vsx_xvcvspdp(vec_sld(__a, __a, 4)); #endif } #endif /* vec_div */ /* Integer vector divides (vectors are scalarized, elements divided and the vectors reassembled). */ static __inline__ vector signed char __ATTRS_o_ai vec_div(vector signed char __a, vector signed char __b) { return __a / __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_div(vector unsigned char __a, vector unsigned char __b) { return __a / __b; } static __inline__ vector signed short __ATTRS_o_ai vec_div(vector signed short __a, vector signed short __b) { return __a / __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_div(vector unsigned short __a, vector unsigned short __b) { return __a / __b; } static __inline__ vector signed int __ATTRS_o_ai vec_div(vector signed int __a, vector signed int __b) { return __a / __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_div(vector unsigned int __a, vector unsigned int __b) { return __a / __b; } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_div(vector signed long long __a, vector signed long long __b) { return __a / __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_div(vector unsigned long long __a, vector unsigned long long __b) { return __a / __b; } static __inline__ vector float __ATTRS_o_ai vec_div(vector float __a, vector float __b) { return __a / __b; } static __inline__ vector double __ATTRS_o_ai vec_div(vector double __a, vector double __b) { return __a / __b; } #endif /* vec_dss */ static __inline__ void __attribute__((__always_inline__)) vec_dss(int __a) { __builtin_altivec_dss(__a); } /* vec_dssall */ static __inline__ void __attribute__((__always_inline__)) vec_dssall(void) { __builtin_altivec_dssall(); } /* vec_dst */ #define vec_dst(__PTR, __CW, __STR) \ __extension__( \ { __builtin_altivec_dst((const void *)(__PTR), (__CW), (__STR)); }) /* vec_dstst */ #define vec_dstst(__PTR, __CW, __STR) \ __extension__( \ { __builtin_altivec_dstst((const void *)(__PTR), (__CW), (__STR)); }) /* vec_dststt */ #define vec_dststt(__PTR, __CW, __STR) \ __extension__( \ { __builtin_altivec_dststt((const void *)(__PTR), (__CW), (__STR)); }) /* vec_dstt */ #define vec_dstt(__PTR, __CW, __STR) \ __extension__( \ { __builtin_altivec_dstt((const void *)(__PTR), (__CW), (__STR)); }) /* vec_eqv */ #ifdef __POWER8_VECTOR__ static __inline__ vector signed char __ATTRS_o_ai vec_eqv(vector signed char __a, vector signed char __b) { return (vector signed char)__builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_eqv(vector unsigned char __a, vector unsigned char __b) { return (vector unsigned char)__builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_eqv(vector bool char __a, vector bool char __b) { return (vector bool char)__builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ vector signed short __ATTRS_o_ai vec_eqv(vector signed short __a, vector signed short __b) { return (vector signed short)__builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_eqv(vector unsigned short __a, vector unsigned short __b) { return (vector unsigned short)__builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_eqv(vector bool short __a, vector bool short __b) { return (vector bool short)__builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ vector signed int __ATTRS_o_ai vec_eqv(vector signed int __a, vector signed int __b) { return (vector signed int)__builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_eqv(vector unsigned int __a, vector unsigned int __b) { return __builtin_vsx_xxleqv(__a, __b); } static __inline__ vector bool int __ATTRS_o_ai vec_eqv(vector bool int __a, vector bool int __b) { return (vector bool int)__builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ vector signed long long __ATTRS_o_ai vec_eqv(vector signed long long __a, vector signed long long __b) { return (vector signed long long)__builtin_vsx_xxleqv( (vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_eqv(vector unsigned long long __a, vector unsigned long long __b) { return (vector unsigned long long)__builtin_vsx_xxleqv( (vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ vector bool long long __ATTRS_o_ai vec_eqv(vector bool long long __a, vector bool long long __b) { return (vector bool long long)__builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ vector float __ATTRS_o_ai vec_eqv(vector float __a, vector float __b) { return (vector float)__builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ vector double __ATTRS_o_ai vec_eqv(vector double __a, vector double __b) { return (vector double)__builtin_vsx_xxleqv((vector unsigned int)__a, (vector unsigned int)__b); } #endif /* vec_expte */ static __inline__ vector float __attribute__((__always_inline__)) vec_expte(vector float __a) { return __builtin_altivec_vexptefp(__a); } /* vec_vexptefp */ static __inline__ vector float __attribute__((__always_inline__)) vec_vexptefp(vector float __a) { return __builtin_altivec_vexptefp(__a); } /* vec_floor */ static __inline__ vector float __ATTRS_o_ai vec_floor(vector float __a) { #ifdef __VSX__ return __builtin_vsx_xvrspim(__a); #else return __builtin_altivec_vrfim(__a); #endif } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_floor(vector double __a) { return __builtin_vsx_xvrdpim(__a); } #endif /* vec_vrfim */ static __inline__ vector float __attribute__((__always_inline__)) vec_vrfim(vector float __a) { return __builtin_altivec_vrfim(__a); } /* vec_ld */ static __inline__ vector signed char __ATTRS_o_ai vec_ld(int __a, const vector signed char *__b) { return (vector signed char)__builtin_altivec_lvx(__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_ld(int __a, const signed char *__b) { return (vector signed char)__builtin_altivec_lvx(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_ld(int __a, const vector unsigned char *__b) { return (vector unsigned char)__builtin_altivec_lvx(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_ld(int __a, const unsigned char *__b) { return (vector unsigned char)__builtin_altivec_lvx(__a, __b); } static __inline__ vector bool char __ATTRS_o_ai vec_ld(int __a, const vector bool char *__b) { return (vector bool char)__builtin_altivec_lvx(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_ld(int __a, const vector short *__b) { return (vector short)__builtin_altivec_lvx(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_ld(int __a, const short *__b) { return (vector short)__builtin_altivec_lvx(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_ld(int __a, const vector unsigned short *__b) { return (vector unsigned short)__builtin_altivec_lvx(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_ld(int __a, const unsigned short *__b) { return (vector unsigned short)__builtin_altivec_lvx(__a, __b); } static __inline__ vector bool short __ATTRS_o_ai vec_ld(int __a, const vector bool short *__b) { return (vector bool short)__builtin_altivec_lvx(__a, __b); } static __inline__ vector pixel __ATTRS_o_ai vec_ld(int __a, const vector pixel *__b) { return (vector pixel)__builtin_altivec_lvx(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_ld(int __a, const vector int *__b) { return (vector int)__builtin_altivec_lvx(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_ld(int __a, const int *__b) { return (vector int)__builtin_altivec_lvx(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_ld(int __a, const vector unsigned int *__b) { return (vector unsigned int)__builtin_altivec_lvx(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_ld(int __a, const unsigned int *__b) { return (vector unsigned int)__builtin_altivec_lvx(__a, __b); } static __inline__ vector bool int __ATTRS_o_ai vec_ld(int __a, const vector bool int *__b) { return (vector bool int)__builtin_altivec_lvx(__a, __b); } static __inline__ vector float __ATTRS_o_ai vec_ld(int __a, const vector float *__b) { return (vector float)__builtin_altivec_lvx(__a, __b); } static __inline__ vector float __ATTRS_o_ai vec_ld(int __a, const float *__b) { return (vector float)__builtin_altivec_lvx(__a, __b); } /* vec_lvx */ static __inline__ vector signed char __ATTRS_o_ai vec_lvx(int __a, const vector signed char *__b) { return (vector signed char)__builtin_altivec_lvx(__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_lvx(int __a, const signed char *__b) { return (vector signed char)__builtin_altivec_lvx(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_lvx(int __a, const vector unsigned char *__b) { return (vector unsigned char)__builtin_altivec_lvx(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_lvx(int __a, const unsigned char *__b) { return (vector unsigned char)__builtin_altivec_lvx(__a, __b); } static __inline__ vector bool char __ATTRS_o_ai vec_lvx(int __a, const vector bool char *__b) { return (vector bool char)__builtin_altivec_lvx(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_lvx(int __a, const vector short *__b) { return (vector short)__builtin_altivec_lvx(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_lvx(int __a, const short *__b) { return (vector short)__builtin_altivec_lvx(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_lvx(int __a, const vector unsigned short *__b) { return (vector unsigned short)__builtin_altivec_lvx(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_lvx(int __a, const unsigned short *__b) { return (vector unsigned short)__builtin_altivec_lvx(__a, __b); } static __inline__ vector bool short __ATTRS_o_ai vec_lvx(int __a, const vector bool short *__b) { return (vector bool short)__builtin_altivec_lvx(__a, __b); } static __inline__ vector pixel __ATTRS_o_ai vec_lvx(int __a, const vector pixel *__b) { return (vector pixel)__builtin_altivec_lvx(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_lvx(int __a, const vector int *__b) { return (vector int)__builtin_altivec_lvx(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_lvx(int __a, const int *__b) { return (vector int)__builtin_altivec_lvx(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_lvx(int __a, const vector unsigned int *__b) { return (vector unsigned int)__builtin_altivec_lvx(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_lvx(int __a, const unsigned int *__b) { return (vector unsigned int)__builtin_altivec_lvx(__a, __b); } static __inline__ vector bool int __ATTRS_o_ai vec_lvx(int __a, const vector bool int *__b) { return (vector bool int)__builtin_altivec_lvx(__a, __b); } static __inline__ vector float __ATTRS_o_ai vec_lvx(int __a, const vector float *__b) { return (vector float)__builtin_altivec_lvx(__a, __b); } static __inline__ vector float __ATTRS_o_ai vec_lvx(int __a, const float *__b) { return (vector float)__builtin_altivec_lvx(__a, __b); } /* vec_lde */ static __inline__ vector signed char __ATTRS_o_ai vec_lde(int __a, const signed char *__b) { return (vector signed char)__builtin_altivec_lvebx(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_lde(int __a, const unsigned char *__b) { return (vector unsigned char)__builtin_altivec_lvebx(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_lde(int __a, const short *__b) { return (vector short)__builtin_altivec_lvehx(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_lde(int __a, const unsigned short *__b) { return (vector unsigned short)__builtin_altivec_lvehx(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_lde(int __a, const int *__b) { return (vector int)__builtin_altivec_lvewx(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_lde(int __a, const unsigned int *__b) { return (vector unsigned int)__builtin_altivec_lvewx(__a, __b); } static __inline__ vector float __ATTRS_o_ai vec_lde(int __a, const float *__b) { return (vector float)__builtin_altivec_lvewx(__a, __b); } /* vec_lvebx */ static __inline__ vector signed char __ATTRS_o_ai vec_lvebx(int __a, const signed char *__b) { return (vector signed char)__builtin_altivec_lvebx(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_lvebx(int __a, const unsigned char *__b) { return (vector unsigned char)__builtin_altivec_lvebx(__a, __b); } /* vec_lvehx */ static __inline__ vector short __ATTRS_o_ai vec_lvehx(int __a, const short *__b) { return (vector short)__builtin_altivec_lvehx(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_lvehx(int __a, const unsigned short *__b) { return (vector unsigned short)__builtin_altivec_lvehx(__a, __b); } /* vec_lvewx */ static __inline__ vector int __ATTRS_o_ai vec_lvewx(int __a, const int *__b) { return (vector int)__builtin_altivec_lvewx(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_lvewx(int __a, const unsigned int *__b) { return (vector unsigned int)__builtin_altivec_lvewx(__a, __b); } static __inline__ vector float __ATTRS_o_ai vec_lvewx(int __a, const float *__b) { return (vector float)__builtin_altivec_lvewx(__a, __b); } /* vec_ldl */ static __inline__ vector signed char __ATTRS_o_ai vec_ldl(int __a, const vector signed char *__b) { return (vector signed char)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_ldl(int __a, const signed char *__b) { return (vector signed char)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_ldl(int __a, const vector unsigned char *__b) { return (vector unsigned char)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_ldl(int __a, const unsigned char *__b) { return (vector unsigned char)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector bool char __ATTRS_o_ai vec_ldl(int __a, const vector bool char *__b) { return (vector bool char)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_ldl(int __a, const vector short *__b) { return (vector short)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_ldl(int __a, const short *__b) { return (vector short)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_ldl(int __a, const vector unsigned short *__b) { return (vector unsigned short)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_ldl(int __a, const unsigned short *__b) { return (vector unsigned short)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector bool short __ATTRS_o_ai vec_ldl(int __a, const vector bool short *__b) { return (vector bool short)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector pixel __ATTRS_o_ai vec_ldl(int __a, const vector pixel *__b) { return (vector pixel short)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_ldl(int __a, const vector int *__b) { return (vector int)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_ldl(int __a, const int *__b) { return (vector int)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_ldl(int __a, const vector unsigned int *__b) { return (vector unsigned int)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_ldl(int __a, const unsigned int *__b) { return (vector unsigned int)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector bool int __ATTRS_o_ai vec_ldl(int __a, const vector bool int *__b) { return (vector bool int)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector float __ATTRS_o_ai vec_ldl(int __a, const vector float *__b) { return (vector float)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector float __ATTRS_o_ai vec_ldl(int __a, const float *__b) { return (vector float)__builtin_altivec_lvxl(__a, __b); } /* vec_lvxl */ static __inline__ vector signed char __ATTRS_o_ai vec_lvxl(int __a, const vector signed char *__b) { return (vector signed char)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_lvxl(int __a, const signed char *__b) { return (vector signed char)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_lvxl(int __a, const vector unsigned char *__b) { return (vector unsigned char)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_lvxl(int __a, const unsigned char *__b) { return (vector unsigned char)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector bool char __ATTRS_o_ai vec_lvxl(int __a, const vector bool char *__b) { return (vector bool char)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_lvxl(int __a, const vector short *__b) { return (vector short)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_lvxl(int __a, const short *__b) { return (vector short)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_lvxl(int __a, const vector unsigned short *__b) { return (vector unsigned short)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_lvxl(int __a, const unsigned short *__b) { return (vector unsigned short)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector bool short __ATTRS_o_ai vec_lvxl(int __a, const vector bool short *__b) { return (vector bool short)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector pixel __ATTRS_o_ai vec_lvxl(int __a, const vector pixel *__b) { return (vector pixel)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_lvxl(int __a, const vector int *__b) { return (vector int)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_lvxl(int __a, const int *__b) { return (vector int)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_lvxl(int __a, const vector unsigned int *__b) { return (vector unsigned int)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_lvxl(int __a, const unsigned int *__b) { return (vector unsigned int)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector bool int __ATTRS_o_ai vec_lvxl(int __a, const vector bool int *__b) { return (vector bool int)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector float __ATTRS_o_ai vec_lvxl(int __a, const vector float *__b) { return (vector float)__builtin_altivec_lvxl(__a, __b); } static __inline__ vector float __ATTRS_o_ai vec_lvxl(int __a, const float *__b) { return (vector float)__builtin_altivec_lvxl(__a, __b); } /* vec_loge */ static __inline__ vector float __attribute__((__always_inline__)) vec_loge(vector float __a) { return __builtin_altivec_vlogefp(__a); } /* vec_vlogefp */ static __inline__ vector float __attribute__((__always_inline__)) vec_vlogefp(vector float __a) { return __builtin_altivec_vlogefp(__a); } /* vec_lvsl */ #ifdef __LITTLE_ENDIAN__ static __inline__ vector unsigned char __ATTRS_o_ai __attribute__((__deprecated__("use assignment for unaligned little endian \ loads/stores"))) vec_lvsl(int __a, const signed char *__b) { vector unsigned char mask = (vector unsigned char)__builtin_altivec_lvsl(__a, __b); vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; return vec_perm(mask, mask, reverse); } #else static __inline__ vector unsigned char __ATTRS_o_ai vec_lvsl(int __a, const signed char *__b) { return (vector unsigned char)__builtin_altivec_lvsl(__a, __b); } #endif #ifdef __LITTLE_ENDIAN__ static __inline__ vector unsigned char __ATTRS_o_ai __attribute__((__deprecated__("use assignment for unaligned little endian \ loads/stores"))) vec_lvsl(int __a, const unsigned char *__b) { vector unsigned char mask = (vector unsigned char)__builtin_altivec_lvsl(__a, __b); vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; return vec_perm(mask, mask, reverse); } #else static __inline__ vector unsigned char __ATTRS_o_ai vec_lvsl(int __a, const unsigned char *__b) { return (vector unsigned char)__builtin_altivec_lvsl(__a, __b); } #endif #ifdef __LITTLE_ENDIAN__ static __inline__ vector unsigned char __ATTRS_o_ai __attribute__((__deprecated__("use assignment for unaligned little endian \ loads/stores"))) vec_lvsl(int __a, const short *__b) { vector unsigned char mask = (vector unsigned char)__builtin_altivec_lvsl(__a, __b); vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; return vec_perm(mask, mask, reverse); } #else static __inline__ vector unsigned char __ATTRS_o_ai vec_lvsl(int __a, const short *__b) { return (vector unsigned char)__builtin_altivec_lvsl(__a, __b); } #endif #ifdef __LITTLE_ENDIAN__ static __inline__ vector unsigned char __ATTRS_o_ai __attribute__((__deprecated__("use assignment for unaligned little endian \ loads/stores"))) vec_lvsl(int __a, const unsigned short *__b) { vector unsigned char mask = (vector unsigned char)__builtin_altivec_lvsl(__a, __b); vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; return vec_perm(mask, mask, reverse); } #else static __inline__ vector unsigned char __ATTRS_o_ai vec_lvsl(int __a, const unsigned short *__b) { return (vector unsigned char)__builtin_altivec_lvsl(__a, __b); } #endif #ifdef __LITTLE_ENDIAN__ static __inline__ vector unsigned char __ATTRS_o_ai __attribute__((__deprecated__("use assignment for unaligned little endian \ loads/stores"))) vec_lvsl(int __a, const int *__b) { vector unsigned char mask = (vector unsigned char)__builtin_altivec_lvsl(__a, __b); vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; return vec_perm(mask, mask, reverse); } #else static __inline__ vector unsigned char __ATTRS_o_ai vec_lvsl(int __a, const int *__b) { return (vector unsigned char)__builtin_altivec_lvsl(__a, __b); } #endif #ifdef __LITTLE_ENDIAN__ static __inline__ vector unsigned char __ATTRS_o_ai __attribute__((__deprecated__("use assignment for unaligned little endian \ loads/stores"))) vec_lvsl(int __a, const unsigned int *__b) { vector unsigned char mask = (vector unsigned char)__builtin_altivec_lvsl(__a, __b); vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; return vec_perm(mask, mask, reverse); } #else static __inline__ vector unsigned char __ATTRS_o_ai vec_lvsl(int __a, const unsigned int *__b) { return (vector unsigned char)__builtin_altivec_lvsl(__a, __b); } #endif #ifdef __LITTLE_ENDIAN__ static __inline__ vector unsigned char __ATTRS_o_ai __attribute__((__deprecated__("use assignment for unaligned little endian \ loads/stores"))) vec_lvsl(int __a, const float *__b) { vector unsigned char mask = (vector unsigned char)__builtin_altivec_lvsl(__a, __b); vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; return vec_perm(mask, mask, reverse); } #else static __inline__ vector unsigned char __ATTRS_o_ai vec_lvsl(int __a, const float *__b) { return (vector unsigned char)__builtin_altivec_lvsl(__a, __b); } #endif /* vec_lvsr */ #ifdef __LITTLE_ENDIAN__ static __inline__ vector unsigned char __ATTRS_o_ai __attribute__((__deprecated__("use assignment for unaligned little endian \ loads/stores"))) vec_lvsr(int __a, const signed char *__b) { vector unsigned char mask = (vector unsigned char)__builtin_altivec_lvsr(__a, __b); vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; return vec_perm(mask, mask, reverse); } #else static __inline__ vector unsigned char __ATTRS_o_ai vec_lvsr(int __a, const signed char *__b) { return (vector unsigned char)__builtin_altivec_lvsr(__a, __b); } #endif #ifdef __LITTLE_ENDIAN__ static __inline__ vector unsigned char __ATTRS_o_ai __attribute__((__deprecated__("use assignment for unaligned little endian \ loads/stores"))) vec_lvsr(int __a, const unsigned char *__b) { vector unsigned char mask = (vector unsigned char)__builtin_altivec_lvsr(__a, __b); vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; return vec_perm(mask, mask, reverse); } #else static __inline__ vector unsigned char __ATTRS_o_ai vec_lvsr(int __a, const unsigned char *__b) { return (vector unsigned char)__builtin_altivec_lvsr(__a, __b); } #endif #ifdef __LITTLE_ENDIAN__ static __inline__ vector unsigned char __ATTRS_o_ai __attribute__((__deprecated__("use assignment for unaligned little endian \ loads/stores"))) vec_lvsr(int __a, const short *__b) { vector unsigned char mask = (vector unsigned char)__builtin_altivec_lvsr(__a, __b); vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; return vec_perm(mask, mask, reverse); } #else static __inline__ vector unsigned char __ATTRS_o_ai vec_lvsr(int __a, const short *__b) { return (vector unsigned char)__builtin_altivec_lvsr(__a, __b); } #endif #ifdef __LITTLE_ENDIAN__ static __inline__ vector unsigned char __ATTRS_o_ai __attribute__((__deprecated__("use assignment for unaligned little endian \ loads/stores"))) vec_lvsr(int __a, const unsigned short *__b) { vector unsigned char mask = (vector unsigned char)__builtin_altivec_lvsr(__a, __b); vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; return vec_perm(mask, mask, reverse); } #else static __inline__ vector unsigned char __ATTRS_o_ai vec_lvsr(int __a, const unsigned short *__b) { return (vector unsigned char)__builtin_altivec_lvsr(__a, __b); } #endif #ifdef __LITTLE_ENDIAN__ static __inline__ vector unsigned char __ATTRS_o_ai __attribute__((__deprecated__("use assignment for unaligned little endian \ loads/stores"))) vec_lvsr(int __a, const int *__b) { vector unsigned char mask = (vector unsigned char)__builtin_altivec_lvsr(__a, __b); vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; return vec_perm(mask, mask, reverse); } #else static __inline__ vector unsigned char __ATTRS_o_ai vec_lvsr(int __a, const int *__b) { return (vector unsigned char)__builtin_altivec_lvsr(__a, __b); } #endif #ifdef __LITTLE_ENDIAN__ static __inline__ vector unsigned char __ATTRS_o_ai __attribute__((__deprecated__("use assignment for unaligned little endian \ loads/stores"))) vec_lvsr(int __a, const unsigned int *__b) { vector unsigned char mask = (vector unsigned char)__builtin_altivec_lvsr(__a, __b); vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; return vec_perm(mask, mask, reverse); } #else static __inline__ vector unsigned char __ATTRS_o_ai vec_lvsr(int __a, const unsigned int *__b) { return (vector unsigned char)__builtin_altivec_lvsr(__a, __b); } #endif #ifdef __LITTLE_ENDIAN__ static __inline__ vector unsigned char __ATTRS_o_ai __attribute__((__deprecated__("use assignment for unaligned little endian \ loads/stores"))) vec_lvsr(int __a, const float *__b) { vector unsigned char mask = (vector unsigned char)__builtin_altivec_lvsr(__a, __b); vector unsigned char reverse = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; return vec_perm(mask, mask, reverse); } #else static __inline__ vector unsigned char __ATTRS_o_ai vec_lvsr(int __a, const float *__b) { return (vector unsigned char)__builtin_altivec_lvsr(__a, __b); } #endif /* vec_madd */ static __inline__ vector signed short __ATTRS_o_ai vec_mladd(vector signed short, vector signed short, vector signed short); static __inline__ vector signed short __ATTRS_o_ai vec_mladd(vector signed short, vector unsigned short, vector unsigned short); static __inline__ vector signed short __ATTRS_o_ai vec_mladd(vector unsigned short, vector signed short, vector signed short); static __inline__ vector unsigned short __ATTRS_o_ai vec_mladd(vector unsigned short, vector unsigned short, vector unsigned short); static __inline__ vector signed short __ATTRS_o_ai vec_madd( vector signed short __a, vector signed short __b, vector signed short __c) { return vec_mladd(__a, __b, __c); } static __inline__ vector signed short __ATTRS_o_ai vec_madd(vector signed short __a, vector unsigned short __b, vector unsigned short __c) { return vec_mladd(__a, __b, __c); } static __inline__ vector signed short __ATTRS_o_ai vec_madd(vector unsigned short __a, vector signed short __b, vector signed short __c) { return vec_mladd(__a, __b, __c); } static __inline__ vector unsigned short __ATTRS_o_ai vec_madd(vector unsigned short __a, vector unsigned short __b, vector unsigned short __c) { return vec_mladd(__a, __b, __c); } static __inline__ vector float __ATTRS_o_ai vec_madd(vector float __a, vector float __b, vector float __c) { #ifdef __VSX__ return __builtin_vsx_xvmaddasp(__a, __b, __c); #else return __builtin_altivec_vmaddfp(__a, __b, __c); #endif } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_madd(vector double __a, vector double __b, vector double __c) { return __builtin_vsx_xvmaddadp(__a, __b, __c); } #endif /* vec_vmaddfp */ static __inline__ vector float __attribute__((__always_inline__)) vec_vmaddfp(vector float __a, vector float __b, vector float __c) { return __builtin_altivec_vmaddfp(__a, __b, __c); } /* vec_madds */ static __inline__ vector signed short __attribute__((__always_inline__)) vec_madds(vector signed short __a, vector signed short __b, vector signed short __c) { return __builtin_altivec_vmhaddshs(__a, __b, __c); } /* vec_vmhaddshs */ static __inline__ vector signed short __attribute__((__always_inline__)) vec_vmhaddshs(vector signed short __a, vector signed short __b, vector signed short __c) { return __builtin_altivec_vmhaddshs(__a, __b, __c); } /* vec_msub */ #ifdef __VSX__ static __inline__ vector float __ATTRS_o_ai vec_msub(vector float __a, vector float __b, vector float __c) { return __builtin_vsx_xvmsubasp(__a, __b, __c); } static __inline__ vector double __ATTRS_o_ai vec_msub(vector double __a, vector double __b, vector double __c) { return __builtin_vsx_xvmsubadp(__a, __b, __c); } #endif /* vec_max */ static __inline__ vector signed char __ATTRS_o_ai vec_max(vector signed char __a, vector signed char __b) { return __builtin_altivec_vmaxsb(__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_max(vector bool char __a, vector signed char __b) { return __builtin_altivec_vmaxsb((vector signed char)__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_max(vector signed char __a, vector bool char __b) { return __builtin_altivec_vmaxsb(__a, (vector signed char)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_max(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vmaxub(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_max(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vmaxub((vector unsigned char)__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_max(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vmaxub(__a, (vector unsigned char)__b); } static __inline__ vector short __ATTRS_o_ai vec_max(vector short __a, vector short __b) { return __builtin_altivec_vmaxsh(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_max(vector bool short __a, vector short __b) { return __builtin_altivec_vmaxsh((vector short)__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_max(vector short __a, vector bool short __b) { return __builtin_altivec_vmaxsh(__a, (vector short)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_max(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vmaxuh(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_max(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vmaxuh((vector unsigned short)__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_max(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vmaxuh(__a, (vector unsigned short)__b); } static __inline__ vector int __ATTRS_o_ai vec_max(vector int __a, vector int __b) { return __builtin_altivec_vmaxsw(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_max(vector bool int __a, vector int __b) { return __builtin_altivec_vmaxsw((vector int)__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_max(vector int __a, vector bool int __b) { return __builtin_altivec_vmaxsw(__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_max(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vmaxuw(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_max(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vmaxuw((vector unsigned int)__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_max(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vmaxuw(__a, (vector unsigned int)__b); } #ifdef __POWER8_VECTOR__ static __inline__ vector signed long long __ATTRS_o_ai vec_max(vector signed long long __a, vector signed long long __b) { return __builtin_altivec_vmaxsd(__a, __b); } static __inline__ vector signed long long __ATTRS_o_ai vec_max(vector bool long long __a, vector signed long long __b) { return __builtin_altivec_vmaxsd((vector signed long long)__a, __b); } static __inline__ vector signed long long __ATTRS_o_ai vec_max(vector signed long long __a, vector bool long long __b) { return __builtin_altivec_vmaxsd(__a, (vector signed long long)__b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_max(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_vmaxud(__a, __b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_max(vector bool long long __a, vector unsigned long long __b) { return __builtin_altivec_vmaxud((vector unsigned long long)__a, __b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_max(vector unsigned long long __a, vector bool long long __b) { return __builtin_altivec_vmaxud(__a, (vector unsigned long long)__b); } #endif static __inline__ vector float __ATTRS_o_ai vec_max(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvmaxsp(__a, __b); #else return __builtin_altivec_vmaxfp(__a, __b); #endif } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_max(vector double __a, vector double __b) { return __builtin_vsx_xvmaxdp(__a, __b); } #endif /* vec_vmaxsb */ static __inline__ vector signed char __ATTRS_o_ai vec_vmaxsb(vector signed char __a, vector signed char __b) { return __builtin_altivec_vmaxsb(__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_vmaxsb(vector bool char __a, vector signed char __b) { return __builtin_altivec_vmaxsb((vector signed char)__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_vmaxsb(vector signed char __a, vector bool char __b) { return __builtin_altivec_vmaxsb(__a, (vector signed char)__b); } /* vec_vmaxub */ static __inline__ vector unsigned char __ATTRS_o_ai vec_vmaxub(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vmaxub(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vmaxub(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vmaxub((vector unsigned char)__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vmaxub(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vmaxub(__a, (vector unsigned char)__b); } /* vec_vmaxsh */ static __inline__ vector short __ATTRS_o_ai vec_vmaxsh(vector short __a, vector short __b) { return __builtin_altivec_vmaxsh(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_vmaxsh(vector bool short __a, vector short __b) { return __builtin_altivec_vmaxsh((vector short)__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_vmaxsh(vector short __a, vector bool short __b) { return __builtin_altivec_vmaxsh(__a, (vector short)__b); } /* vec_vmaxuh */ static __inline__ vector unsigned short __ATTRS_o_ai vec_vmaxuh(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vmaxuh(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vmaxuh(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vmaxuh((vector unsigned short)__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vmaxuh(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vmaxuh(__a, (vector unsigned short)__b); } /* vec_vmaxsw */ static __inline__ vector int __ATTRS_o_ai vec_vmaxsw(vector int __a, vector int __b) { return __builtin_altivec_vmaxsw(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_vmaxsw(vector bool int __a, vector int __b) { return __builtin_altivec_vmaxsw((vector int)__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_vmaxsw(vector int __a, vector bool int __b) { return __builtin_altivec_vmaxsw(__a, (vector int)__b); } /* vec_vmaxuw */ static __inline__ vector unsigned int __ATTRS_o_ai vec_vmaxuw(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vmaxuw(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vmaxuw(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vmaxuw((vector unsigned int)__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vmaxuw(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vmaxuw(__a, (vector unsigned int)__b); } /* vec_vmaxfp */ static __inline__ vector float __attribute__((__always_inline__)) vec_vmaxfp(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvmaxsp(__a, __b); #else return __builtin_altivec_vmaxfp(__a, __b); #endif } /* vec_mergeh */ static __inline__ vector signed char __ATTRS_o_ai vec_mergeh(vector signed char __a, vector signed char __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17)); } static __inline__ vector unsigned char __ATTRS_o_ai vec_mergeh(vector unsigned char __a, vector unsigned char __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17)); } static __inline__ vector bool char __ATTRS_o_ai vec_mergeh(vector bool char __a, vector bool char __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17)); } static __inline__ vector short __ATTRS_o_ai vec_mergeh(vector short __a, vector short __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13, 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17)); } static __inline__ vector unsigned short __ATTRS_o_ai vec_mergeh(vector unsigned short __a, vector unsigned short __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13, 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17)); } static __inline__ vector bool short __ATTRS_o_ai vec_mergeh(vector bool short __a, vector bool short __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13, 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17)); } static __inline__ vector pixel __ATTRS_o_ai vec_mergeh(vector pixel __a, vector pixel __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13, 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17)); } static __inline__ vector int __ATTRS_o_ai vec_mergeh(vector int __a, vector int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_mergeh(vector unsigned int __a, vector unsigned int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17)); } static __inline__ vector bool int __ATTRS_o_ai vec_mergeh(vector bool int __a, vector bool int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17)); } static __inline__ vector float __ATTRS_o_ai vec_mergeh(vector float __a, vector float __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17)); } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_mergeh(vector signed long long __a, vector signed long long __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17)); } static __inline__ vector signed long long __ATTRS_o_ai vec_mergeh(vector signed long long __a, vector bool long long __b) { return vec_perm(__a, (vector signed long long)__b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17)); } static __inline__ vector signed long long __ATTRS_o_ai vec_mergeh(vector bool long long __a, vector signed long long __b) { return vec_perm((vector signed long long)__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17)); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_mergeh(vector unsigned long long __a, vector unsigned long long __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17)); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_mergeh(vector unsigned long long __a, vector bool long long __b) { return vec_perm(__a, (vector unsigned long long)__b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17)); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_mergeh(vector bool long long __a, vector unsigned long long __b) { return vec_perm((vector unsigned long long)__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17)); } static __inline__ vector bool long long __ATTRS_o_ai vec_mergeh(vector bool long long __a, vector bool long long __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17)); } static __inline__ vector double __ATTRS_o_ai vec_mergeh(vector double __a, vector double __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17)); } static __inline__ vector double __ATTRS_o_ai vec_mergeh(vector double __a, vector bool long long __b) { return vec_perm(__a, (vector double)__b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17)); } static __inline__ vector double __ATTRS_o_ai vec_mergeh(vector bool long long __a, vector double __b) { return vec_perm((vector double)__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17)); } #endif /* vec_vmrghb */ #define __builtin_altivec_vmrghb vec_vmrghb static __inline__ vector signed char __ATTRS_o_ai vec_vmrghb(vector signed char __a, vector signed char __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17)); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vmrghb(vector unsigned char __a, vector unsigned char __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17)); } static __inline__ vector bool char __ATTRS_o_ai vec_vmrghb(vector bool char __a, vector bool char __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17)); } /* vec_vmrghh */ #define __builtin_altivec_vmrghh vec_vmrghh static __inline__ vector short __ATTRS_o_ai vec_vmrghh(vector short __a, vector short __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13, 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17)); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vmrghh(vector unsigned short __a, vector unsigned short __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13, 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17)); } static __inline__ vector bool short __ATTRS_o_ai vec_vmrghh(vector bool short __a, vector bool short __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13, 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17)); } static __inline__ vector pixel __ATTRS_o_ai vec_vmrghh(vector pixel __a, vector pixel __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13, 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17)); } /* vec_vmrghw */ #define __builtin_altivec_vmrghw vec_vmrghw static __inline__ vector int __ATTRS_o_ai vec_vmrghw(vector int __a, vector int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vmrghw(vector unsigned int __a, vector unsigned int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17)); } static __inline__ vector bool int __ATTRS_o_ai vec_vmrghw(vector bool int __a, vector bool int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17)); } static __inline__ vector float __ATTRS_o_ai vec_vmrghw(vector float __a, vector float __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17)); } /* vec_mergel */ static __inline__ vector signed char __ATTRS_o_ai vec_mergel(vector signed char __a, vector signed char __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B, 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F)); } static __inline__ vector unsigned char __ATTRS_o_ai vec_mergel(vector unsigned char __a, vector unsigned char __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B, 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F)); } static __inline__ vector bool char __ATTRS_o_ai vec_mergel(vector bool char __a, vector bool char __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B, 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F)); } static __inline__ vector short __ATTRS_o_ai vec_mergel(vector short __a, vector short __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B, 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F)); } static __inline__ vector unsigned short __ATTRS_o_ai vec_mergel(vector unsigned short __a, vector unsigned short __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B, 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F)); } static __inline__ vector bool short __ATTRS_o_ai vec_mergel(vector bool short __a, vector bool short __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B, 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F)); } static __inline__ vector pixel __ATTRS_o_ai vec_mergel(vector pixel __a, vector pixel __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B, 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F)); } static __inline__ vector int __ATTRS_o_ai vec_mergel(vector int __a, vector int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B, 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_mergel(vector unsigned int __a, vector unsigned int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B, 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector bool int __ATTRS_o_ai vec_mergel(vector bool int __a, vector bool int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B, 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector float __ATTRS_o_ai vec_mergel(vector float __a, vector float __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B, 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F)); } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_mergel(vector signed long long __a, vector signed long long __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x18, 0X19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector signed long long __ATTRS_o_ai vec_mergel(vector signed long long __a, vector bool long long __b) { return vec_perm(__a, (vector signed long long)__b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x18, 0X19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector signed long long __ATTRS_o_ai vec_mergel(vector bool long long __a, vector signed long long __b) { return vec_perm((vector signed long long)__a, __b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x18, 0X19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_mergel(vector unsigned long long __a, vector unsigned long long __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x18, 0X19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_mergel(vector unsigned long long __a, vector bool long long __b) { return vec_perm(__a, (vector unsigned long long)__b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x18, 0X19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_mergel(vector bool long long __a, vector unsigned long long __b) { return vec_perm((vector unsigned long long)__a, __b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x18, 0X19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector bool long long __ATTRS_o_ai vec_mergel(vector bool long long __a, vector bool long long __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x18, 0X19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector double __ATTRS_o_ai vec_mergel(vector double __a, vector double __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x18, 0X19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector double __ATTRS_o_ai vec_mergel(vector double __a, vector bool long long __b) { return vec_perm(__a, (vector double)__b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x18, 0X19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector double __ATTRS_o_ai vec_mergel(vector bool long long __a, vector double __b) { return vec_perm((vector double)__a, __b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x18, 0X19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F)); } #endif /* vec_vmrglb */ #define __builtin_altivec_vmrglb vec_vmrglb static __inline__ vector signed char __ATTRS_o_ai vec_vmrglb(vector signed char __a, vector signed char __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B, 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F)); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vmrglb(vector unsigned char __a, vector unsigned char __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B, 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F)); } static __inline__ vector bool char __ATTRS_o_ai vec_vmrglb(vector bool char __a, vector bool char __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B, 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F)); } /* vec_vmrglh */ #define __builtin_altivec_vmrglh vec_vmrglh static __inline__ vector short __ATTRS_o_ai vec_vmrglh(vector short __a, vector short __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B, 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F)); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vmrglh(vector unsigned short __a, vector unsigned short __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B, 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F)); } static __inline__ vector bool short __ATTRS_o_ai vec_vmrglh(vector bool short __a, vector bool short __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B, 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F)); } static __inline__ vector pixel __ATTRS_o_ai vec_vmrglh(vector pixel __a, vector pixel __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B, 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F)); } /* vec_vmrglw */ #define __builtin_altivec_vmrglw vec_vmrglw static __inline__ vector int __ATTRS_o_ai vec_vmrglw(vector int __a, vector int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B, 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vmrglw(vector unsigned int __a, vector unsigned int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B, 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector bool int __ATTRS_o_ai vec_vmrglw(vector bool int __a, vector bool int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B, 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector float __ATTRS_o_ai vec_vmrglw(vector float __a, vector float __b) { return vec_perm(__a, __b, (vector unsigned char)(0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B, 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F)); } #ifdef __POWER8_VECTOR__ /* vec_mergee */ static __inline__ vector bool int __ATTRS_o_ai vec_mergee(vector bool int __a, vector bool int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B)); } static __inline__ vector signed int __ATTRS_o_ai vec_mergee(vector signed int __a, vector signed int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_mergee(vector unsigned int __a, vector unsigned int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B)); } static __inline__ vector bool long long __ATTRS_o_ai vec_mergee(vector bool long long __a, vector bool long long __b) { return vec_mergeh(__a, __b); } static __inline__ vector signed long long __ATTRS_o_ai vec_mergee(vector signed long long __a, vector signed long long __b) { return vec_mergeh(__a, __b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_mergee(vector unsigned long long __a, vector unsigned long long __b) { return vec_mergeh(__a, __b); } static __inline__ vector float __ATTRS_o_ai vec_mergee(vector float __a, vector float __b) { return vec_perm(__a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B)); } static __inline__ vector double __ATTRS_o_ai vec_mergee(vector double __a, vector double __b) { return vec_mergeh(__a, __b); } /* vec_mergeo */ static __inline__ vector bool int __ATTRS_o_ai vec_mergeo(vector bool int __a, vector bool int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17, 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector signed int __ATTRS_o_ai vec_mergeo(vector signed int __a, vector signed int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17, 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_mergeo(vector unsigned int __a, vector unsigned int __b) { return vec_perm(__a, __b, (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17, 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector bool long long __ATTRS_o_ai vec_mergeo(vector bool long long __a, vector bool long long __b) { return vec_mergel(__a, __b); } static __inline__ vector signed long long __ATTRS_o_ai vec_mergeo(vector signed long long __a, vector signed long long __b) { return vec_mergel(__a, __b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_mergeo(vector unsigned long long __a, vector unsigned long long __b) { return vec_mergel(__a, __b); } static __inline__ vector float __ATTRS_o_ai vec_mergeo(vector float __a, vector float __b) { return vec_perm(__a, __b, (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17, 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F)); } static __inline__ vector double __ATTRS_o_ai vec_mergeo(vector double __a, vector double __b) { return vec_mergel(__a, __b); } #endif /* vec_mfvscr */ static __inline__ vector unsigned short __attribute__((__always_inline__)) vec_mfvscr(void) { return __builtin_altivec_mfvscr(); } /* vec_min */ static __inline__ vector signed char __ATTRS_o_ai vec_min(vector signed char __a, vector signed char __b) { return __builtin_altivec_vminsb(__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_min(vector bool char __a, vector signed char __b) { return __builtin_altivec_vminsb((vector signed char)__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_min(vector signed char __a, vector bool char __b) { return __builtin_altivec_vminsb(__a, (vector signed char)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_min(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vminub(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_min(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vminub((vector unsigned char)__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_min(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vminub(__a, (vector unsigned char)__b); } static __inline__ vector short __ATTRS_o_ai vec_min(vector short __a, vector short __b) { return __builtin_altivec_vminsh(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_min(vector bool short __a, vector short __b) { return __builtin_altivec_vminsh((vector short)__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_min(vector short __a, vector bool short __b) { return __builtin_altivec_vminsh(__a, (vector short)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_min(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vminuh(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_min(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vminuh((vector unsigned short)__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_min(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vminuh(__a, (vector unsigned short)__b); } static __inline__ vector int __ATTRS_o_ai vec_min(vector int __a, vector int __b) { return __builtin_altivec_vminsw(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_min(vector bool int __a, vector int __b) { return __builtin_altivec_vminsw((vector int)__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_min(vector int __a, vector bool int __b) { return __builtin_altivec_vminsw(__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_min(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vminuw(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_min(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vminuw((vector unsigned int)__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_min(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vminuw(__a, (vector unsigned int)__b); } #ifdef __POWER8_VECTOR__ static __inline__ vector signed long long __ATTRS_o_ai vec_min(vector signed long long __a, vector signed long long __b) { return __builtin_altivec_vminsd(__a, __b); } static __inline__ vector signed long long __ATTRS_o_ai vec_min(vector bool long long __a, vector signed long long __b) { return __builtin_altivec_vminsd((vector signed long long)__a, __b); } static __inline__ vector signed long long __ATTRS_o_ai vec_min(vector signed long long __a, vector bool long long __b) { return __builtin_altivec_vminsd(__a, (vector signed long long)__b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_min(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_vminud(__a, __b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_min(vector bool long long __a, vector unsigned long long __b) { return __builtin_altivec_vminud((vector unsigned long long)__a, __b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_min(vector unsigned long long __a, vector bool long long __b) { return __builtin_altivec_vminud(__a, (vector unsigned long long)__b); } #endif static __inline__ vector float __ATTRS_o_ai vec_min(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvminsp(__a, __b); #else return __builtin_altivec_vminfp(__a, __b); #endif } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_min(vector double __a, vector double __b) { return __builtin_vsx_xvmindp(__a, __b); } #endif /* vec_vminsb */ static __inline__ vector signed char __ATTRS_o_ai vec_vminsb(vector signed char __a, vector signed char __b) { return __builtin_altivec_vminsb(__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_vminsb(vector bool char __a, vector signed char __b) { return __builtin_altivec_vminsb((vector signed char)__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_vminsb(vector signed char __a, vector bool char __b) { return __builtin_altivec_vminsb(__a, (vector signed char)__b); } /* vec_vminub */ static __inline__ vector unsigned char __ATTRS_o_ai vec_vminub(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vminub(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vminub(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vminub((vector unsigned char)__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vminub(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vminub(__a, (vector unsigned char)__b); } /* vec_vminsh */ static __inline__ vector short __ATTRS_o_ai vec_vminsh(vector short __a, vector short __b) { return __builtin_altivec_vminsh(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_vminsh(vector bool short __a, vector short __b) { return __builtin_altivec_vminsh((vector short)__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_vminsh(vector short __a, vector bool short __b) { return __builtin_altivec_vminsh(__a, (vector short)__b); } /* vec_vminuh */ static __inline__ vector unsigned short __ATTRS_o_ai vec_vminuh(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vminuh(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vminuh(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vminuh((vector unsigned short)__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vminuh(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vminuh(__a, (vector unsigned short)__b); } /* vec_vminsw */ static __inline__ vector int __ATTRS_o_ai vec_vminsw(vector int __a, vector int __b) { return __builtin_altivec_vminsw(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_vminsw(vector bool int __a, vector int __b) { return __builtin_altivec_vminsw((vector int)__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_vminsw(vector int __a, vector bool int __b) { return __builtin_altivec_vminsw(__a, (vector int)__b); } /* vec_vminuw */ static __inline__ vector unsigned int __ATTRS_o_ai vec_vminuw(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vminuw(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vminuw(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vminuw((vector unsigned int)__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vminuw(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vminuw(__a, (vector unsigned int)__b); } /* vec_vminfp */ static __inline__ vector float __attribute__((__always_inline__)) vec_vminfp(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvminsp(__a, __b); #else return __builtin_altivec_vminfp(__a, __b); #endif } /* vec_mladd */ #define __builtin_altivec_vmladduhm vec_mladd static __inline__ vector short __ATTRS_o_ai vec_mladd(vector short __a, vector short __b, vector short __c) { return __a * __b + __c; } static __inline__ vector short __ATTRS_o_ai vec_mladd( vector short __a, vector unsigned short __b, vector unsigned short __c) { return __a * (vector short)__b + (vector short)__c; } static __inline__ vector short __ATTRS_o_ai vec_mladd(vector unsigned short __a, vector short __b, vector short __c) { return (vector short)__a * __b + __c; } static __inline__ vector unsigned short __ATTRS_o_ai vec_mladd(vector unsigned short __a, vector unsigned short __b, vector unsigned short __c) { return __a * __b + __c; } /* vec_vmladduhm */ static __inline__ vector short __ATTRS_o_ai vec_vmladduhm(vector short __a, vector short __b, vector short __c) { return __a * __b + __c; } static __inline__ vector short __ATTRS_o_ai vec_vmladduhm( vector short __a, vector unsigned short __b, vector unsigned short __c) { return __a * (vector short)__b + (vector short)__c; } static __inline__ vector short __ATTRS_o_ai vec_vmladduhm(vector unsigned short __a, vector short __b, vector short __c) { return (vector short)__a * __b + __c; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vmladduhm(vector unsigned short __a, vector unsigned short __b, vector unsigned short __c) { return __a * __b + __c; } /* vec_mradds */ static __inline__ vector short __attribute__((__always_inline__)) vec_mradds(vector short __a, vector short __b, vector short __c) { return __builtin_altivec_vmhraddshs(__a, __b, __c); } /* vec_vmhraddshs */ static __inline__ vector short __attribute__((__always_inline__)) vec_vmhraddshs(vector short __a, vector short __b, vector short __c) { return __builtin_altivec_vmhraddshs(__a, __b, __c); } /* vec_msum */ static __inline__ vector int __ATTRS_o_ai vec_msum(vector signed char __a, vector unsigned char __b, vector int __c) { return __builtin_altivec_vmsummbm(__a, __b, __c); } static __inline__ vector unsigned int __ATTRS_o_ai vec_msum(vector unsigned char __a, vector unsigned char __b, vector unsigned int __c) { return __builtin_altivec_vmsumubm(__a, __b, __c); } static __inline__ vector int __ATTRS_o_ai vec_msum(vector short __a, vector short __b, vector int __c) { return __builtin_altivec_vmsumshm(__a, __b, __c); } static __inline__ vector unsigned int __ATTRS_o_ai vec_msum(vector unsigned short __a, vector unsigned short __b, vector unsigned int __c) { return __builtin_altivec_vmsumuhm(__a, __b, __c); } /* vec_vmsummbm */ static __inline__ vector int __attribute__((__always_inline__)) vec_vmsummbm(vector signed char __a, vector unsigned char __b, vector int __c) { return __builtin_altivec_vmsummbm(__a, __b, __c); } /* vec_vmsumubm */ static __inline__ vector unsigned int __attribute__((__always_inline__)) vec_vmsumubm(vector unsigned char __a, vector unsigned char __b, vector unsigned int __c) { return __builtin_altivec_vmsumubm(__a, __b, __c); } /* vec_vmsumshm */ static __inline__ vector int __attribute__((__always_inline__)) vec_vmsumshm(vector short __a, vector short __b, vector int __c) { return __builtin_altivec_vmsumshm(__a, __b, __c); } /* vec_vmsumuhm */ static __inline__ vector unsigned int __attribute__((__always_inline__)) vec_vmsumuhm(vector unsigned short __a, vector unsigned short __b, vector unsigned int __c) { return __builtin_altivec_vmsumuhm(__a, __b, __c); } /* vec_msums */ static __inline__ vector int __ATTRS_o_ai vec_msums(vector short __a, vector short __b, vector int __c) { return __builtin_altivec_vmsumshs(__a, __b, __c); } static __inline__ vector unsigned int __ATTRS_o_ai vec_msums(vector unsigned short __a, vector unsigned short __b, vector unsigned int __c) { return __builtin_altivec_vmsumuhs(__a, __b, __c); } /* vec_vmsumshs */ static __inline__ vector int __attribute__((__always_inline__)) vec_vmsumshs(vector short __a, vector short __b, vector int __c) { return __builtin_altivec_vmsumshs(__a, __b, __c); } /* vec_vmsumuhs */ static __inline__ vector unsigned int __attribute__((__always_inline__)) vec_vmsumuhs(vector unsigned short __a, vector unsigned short __b, vector unsigned int __c) { return __builtin_altivec_vmsumuhs(__a, __b, __c); } /* vec_mtvscr */ static __inline__ void __ATTRS_o_ai vec_mtvscr(vector signed char __a) { __builtin_altivec_mtvscr((vector int)__a); } static __inline__ void __ATTRS_o_ai vec_mtvscr(vector unsigned char __a) { __builtin_altivec_mtvscr((vector int)__a); } static __inline__ void __ATTRS_o_ai vec_mtvscr(vector bool char __a) { __builtin_altivec_mtvscr((vector int)__a); } static __inline__ void __ATTRS_o_ai vec_mtvscr(vector short __a) { __builtin_altivec_mtvscr((vector int)__a); } static __inline__ void __ATTRS_o_ai vec_mtvscr(vector unsigned short __a) { __builtin_altivec_mtvscr((vector int)__a); } static __inline__ void __ATTRS_o_ai vec_mtvscr(vector bool short __a) { __builtin_altivec_mtvscr((vector int)__a); } static __inline__ void __ATTRS_o_ai vec_mtvscr(vector pixel __a) { __builtin_altivec_mtvscr((vector int)__a); } static __inline__ void __ATTRS_o_ai vec_mtvscr(vector int __a) { __builtin_altivec_mtvscr((vector int)__a); } static __inline__ void __ATTRS_o_ai vec_mtvscr(vector unsigned int __a) { __builtin_altivec_mtvscr((vector int)__a); } static __inline__ void __ATTRS_o_ai vec_mtvscr(vector bool int __a) { __builtin_altivec_mtvscr((vector int)__a); } static __inline__ void __ATTRS_o_ai vec_mtvscr(vector float __a) { __builtin_altivec_mtvscr((vector int)__a); } /* vec_mul */ /* Integer vector multiplication will involve multiplication of the odd/even elements separately, then truncating the results and moving to the result vector. */ static __inline__ vector signed char __ATTRS_o_ai vec_mul(vector signed char __a, vector signed char __b) { return __a * __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_mul(vector unsigned char __a, vector unsigned char __b) { return __a * __b; } static __inline__ vector signed short __ATTRS_o_ai vec_mul(vector signed short __a, vector signed short __b) { return __a * __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_mul(vector unsigned short __a, vector unsigned short __b) { return __a * __b; } static __inline__ vector signed int __ATTRS_o_ai vec_mul(vector signed int __a, vector signed int __b) { return __a * __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_mul(vector unsigned int __a, vector unsigned int __b) { return __a * __b; } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_mul(vector signed long long __a, vector signed long long __b) { return __a * __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_mul(vector unsigned long long __a, vector unsigned long long __b) { return __a * __b; } #endif static __inline__ vector float __ATTRS_o_ai vec_mul(vector float __a, vector float __b) { return __a * __b; } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_mul(vector double __a, vector double __b) { return __a * __b; } #endif /* The vmulos* and vmules* instructions have a big endian bias, so we must reverse the meaning of "even" and "odd" for little endian. */ /* vec_mule */ static __inline__ vector short __ATTRS_o_ai vec_mule(vector signed char __a, vector signed char __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmulosb(__a, __b); #else return __builtin_altivec_vmulesb(__a, __b); #endif } static __inline__ vector unsigned short __ATTRS_o_ai vec_mule(vector unsigned char __a, vector unsigned char __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmuloub(__a, __b); #else return __builtin_altivec_vmuleub(__a, __b); #endif } static __inline__ vector int __ATTRS_o_ai vec_mule(vector short __a, vector short __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmulosh(__a, __b); #else return __builtin_altivec_vmulesh(__a, __b); #endif } static __inline__ vector unsigned int __ATTRS_o_ai vec_mule(vector unsigned short __a, vector unsigned short __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmulouh(__a, __b); #else return __builtin_altivec_vmuleuh(__a, __b); #endif } #ifdef __POWER8_VECTOR__ static __inline__ vector signed long long __ATTRS_o_ai vec_mule(vector signed int __a, vector signed int __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmulosw(__a, __b); #else return __builtin_altivec_vmulesw(__a, __b); #endif } static __inline__ vector unsigned long long __ATTRS_o_ai vec_mule(vector unsigned int __a, vector unsigned int __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmulouw(__a, __b); #else return __builtin_altivec_vmuleuw(__a, __b); #endif } #endif /* vec_vmulesb */ static __inline__ vector short __attribute__((__always_inline__)) vec_vmulesb(vector signed char __a, vector signed char __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmulosb(__a, __b); #else return __builtin_altivec_vmulesb(__a, __b); #endif } /* vec_vmuleub */ static __inline__ vector unsigned short __attribute__((__always_inline__)) vec_vmuleub(vector unsigned char __a, vector unsigned char __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmuloub(__a, __b); #else return __builtin_altivec_vmuleub(__a, __b); #endif } /* vec_vmulesh */ static __inline__ vector int __attribute__((__always_inline__)) vec_vmulesh(vector short __a, vector short __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmulosh(__a, __b); #else return __builtin_altivec_vmulesh(__a, __b); #endif } /* vec_vmuleuh */ static __inline__ vector unsigned int __attribute__((__always_inline__)) vec_vmuleuh(vector unsigned short __a, vector unsigned short __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmulouh(__a, __b); #else return __builtin_altivec_vmuleuh(__a, __b); #endif } /* vec_mulo */ static __inline__ vector short __ATTRS_o_ai vec_mulo(vector signed char __a, vector signed char __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmulesb(__a, __b); #else return __builtin_altivec_vmulosb(__a, __b); #endif } static __inline__ vector unsigned short __ATTRS_o_ai vec_mulo(vector unsigned char __a, vector unsigned char __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmuleub(__a, __b); #else return __builtin_altivec_vmuloub(__a, __b); #endif } static __inline__ vector int __ATTRS_o_ai vec_mulo(vector short __a, vector short __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmulesh(__a, __b); #else return __builtin_altivec_vmulosh(__a, __b); #endif } static __inline__ vector unsigned int __ATTRS_o_ai vec_mulo(vector unsigned short __a, vector unsigned short __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmuleuh(__a, __b); #else return __builtin_altivec_vmulouh(__a, __b); #endif } #ifdef __POWER8_VECTOR__ static __inline__ vector signed long long __ATTRS_o_ai vec_mulo(vector signed int __a, vector signed int __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmulesw(__a, __b); #else return __builtin_altivec_vmulosw(__a, __b); #endif } static __inline__ vector unsigned long long __ATTRS_o_ai vec_mulo(vector unsigned int __a, vector unsigned int __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmuleuw(__a, __b); #else return __builtin_altivec_vmulouw(__a, __b); #endif } #endif /* vec_vmulosb */ static __inline__ vector short __attribute__((__always_inline__)) vec_vmulosb(vector signed char __a, vector signed char __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmulesb(__a, __b); #else return __builtin_altivec_vmulosb(__a, __b); #endif } /* vec_vmuloub */ static __inline__ vector unsigned short __attribute__((__always_inline__)) vec_vmuloub(vector unsigned char __a, vector unsigned char __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmuleub(__a, __b); #else return __builtin_altivec_vmuloub(__a, __b); #endif } /* vec_vmulosh */ static __inline__ vector int __attribute__((__always_inline__)) vec_vmulosh(vector short __a, vector short __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmulesh(__a, __b); #else return __builtin_altivec_vmulosh(__a, __b); #endif } /* vec_vmulouh */ static __inline__ vector unsigned int __attribute__((__always_inline__)) vec_vmulouh(vector unsigned short __a, vector unsigned short __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vmuleuh(__a, __b); #else return __builtin_altivec_vmulouh(__a, __b); #endif } /* vec_nand */ #ifdef __POWER8_VECTOR__ static __inline__ vector signed char __ATTRS_o_ai vec_nand(vector signed char __a, vector signed char __b) { return ~(__a & __b); } static __inline__ vector signed char __ATTRS_o_ai vec_nand(vector signed char __a, vector bool char __b) { return ~(__a & __b); } static __inline__ vector signed char __ATTRS_o_ai vec_nand(vector bool char __a, vector signed char __b) { return ~(__a & __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_nand(vector unsigned char __a, vector unsigned char __b) { return ~(__a & __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_nand(vector unsigned char __a, vector bool char __b) { return ~(__a & __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_nand(vector bool char __a, vector unsigned char __b) { return ~(__a & __b); } static __inline__ vector bool char __ATTRS_o_ai vec_nand(vector bool char __a, vector bool char __b) { return ~(__a & __b); } static __inline__ vector signed short __ATTRS_o_ai vec_nand(vector signed short __a, vector signed short __b) { return ~(__a & __b); } static __inline__ vector signed short __ATTRS_o_ai vec_nand(vector signed short __a, vector bool short __b) { return ~(__a & __b); } static __inline__ vector signed short __ATTRS_o_ai vec_nand(vector bool short __a, vector signed short __b) { return ~(__a & __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_nand(vector unsigned short __a, vector unsigned short __b) { return ~(__a & __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_nand(vector unsigned short __a, vector bool short __b) { return ~(__a & __b); } static __inline__ vector bool short __ATTRS_o_ai vec_nand(vector bool short __a, vector bool short __b) { return ~(__a & __b); } static __inline__ vector signed int __ATTRS_o_ai vec_nand(vector signed int __a, vector signed int __b) { return ~(__a & __b); } static __inline__ vector signed int __ATTRS_o_ai vec_nand(vector signed int __a, vector bool int __b) { return ~(__a & __b); } static __inline__ vector signed int __ATTRS_o_ai vec_nand(vector bool int __a, vector signed int __b) { return ~(__a & __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_nand(vector unsigned int __a, vector unsigned int __b) { return ~(__a & __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_nand(vector unsigned int __a, vector bool int __b) { return ~(__a & __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_nand(vector bool int __a, vector unsigned int __b) { return ~(__a & __b); } static __inline__ vector bool int __ATTRS_o_ai vec_nand(vector bool int __a, vector bool int __b) { return ~(__a & __b); } static __inline__ vector float __ATTRS_o_ai vec_nand(vector float __a, vector float __b) { return (vector float)(~((vector unsigned int)__a & (vector unsigned int)__b)); } static __inline__ vector signed long long __ATTRS_o_ai vec_nand(vector signed long long __a, vector signed long long __b) { return ~(__a & __b); } static __inline__ vector signed long long __ATTRS_o_ai vec_nand(vector signed long long __a, vector bool long long __b) { return ~(__a & __b); } static __inline__ vector signed long long __ATTRS_o_ai vec_nand(vector bool long long __a, vector signed long long __b) { return ~(__a & __b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_nand(vector unsigned long long __a, vector unsigned long long __b) { return ~(__a & __b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_nand(vector unsigned long long __a, vector bool long long __b) { return ~(__a & __b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_nand(vector bool long long __a, vector unsigned long long __b) { return ~(__a & __b); } static __inline__ vector bool long long __ATTRS_o_ai vec_nand(vector bool long long __a, vector bool long long __b) { return ~(__a & __b); } static __inline__ vector double __ATTRS_o_ai vec_nand(vector double __a, vector double __b) { return (vector double)(~((vector unsigned long long)__a & (vector unsigned long long)__b)); } #endif /* vec_nmadd */ #ifdef __VSX__ static __inline__ vector float __ATTRS_o_ai vec_nmadd(vector float __a, vector float __b, vector float __c) { return __builtin_vsx_xvnmaddasp(__a, __b, __c); } static __inline__ vector double __ATTRS_o_ai vec_nmadd(vector double __a, vector double __b, vector double __c) { return __builtin_vsx_xvnmaddadp(__a, __b, __c); } #endif /* vec_nmsub */ static __inline__ vector float __ATTRS_o_ai vec_nmsub(vector float __a, vector float __b, vector float __c) { #ifdef __VSX__ return __builtin_vsx_xvnmsubasp(__a, __b, __c); #else return __builtin_altivec_vnmsubfp(__a, __b, __c); #endif } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_nmsub(vector double __a, vector double __b, vector double __c) { return __builtin_vsx_xvnmsubadp(__a, __b, __c); } #endif /* vec_vnmsubfp */ static __inline__ vector float __attribute__((__always_inline__)) vec_vnmsubfp(vector float __a, vector float __b, vector float __c) { return __builtin_altivec_vnmsubfp(__a, __b, __c); } /* vec_nor */ #define __builtin_altivec_vnor vec_nor static __inline__ vector signed char __ATTRS_o_ai vec_nor(vector signed char __a, vector signed char __b) { return ~(__a | __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_nor(vector unsigned char __a, vector unsigned char __b) { return ~(__a | __b); } static __inline__ vector bool char __ATTRS_o_ai vec_nor(vector bool char __a, vector bool char __b) { return ~(__a | __b); } static __inline__ vector short __ATTRS_o_ai vec_nor(vector short __a, vector short __b) { return ~(__a | __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_nor(vector unsigned short __a, vector unsigned short __b) { return ~(__a | __b); } static __inline__ vector bool short __ATTRS_o_ai vec_nor(vector bool short __a, vector bool short __b) { return ~(__a | __b); } static __inline__ vector int __ATTRS_o_ai vec_nor(vector int __a, vector int __b) { return ~(__a | __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_nor(vector unsigned int __a, vector unsigned int __b) { return ~(__a | __b); } static __inline__ vector bool int __ATTRS_o_ai vec_nor(vector bool int __a, vector bool int __b) { return ~(__a | __b); } static __inline__ vector float __ATTRS_o_ai vec_nor(vector float __a, vector float __b) { vector unsigned int __res = ~((vector unsigned int)__a | (vector unsigned int)__b); return (vector float)__res; } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_nor(vector double __a, vector double __b) { vector unsigned long long __res = ~((vector unsigned long long)__a | (vector unsigned long long)__b); return (vector double)__res; } #endif /* vec_vnor */ static __inline__ vector signed char __ATTRS_o_ai vec_vnor(vector signed char __a, vector signed char __b) { return ~(__a | __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vnor(vector unsigned char __a, vector unsigned char __b) { return ~(__a | __b); } static __inline__ vector bool char __ATTRS_o_ai vec_vnor(vector bool char __a, vector bool char __b) { return ~(__a | __b); } static __inline__ vector short __ATTRS_o_ai vec_vnor(vector short __a, vector short __b) { return ~(__a | __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vnor(vector unsigned short __a, vector unsigned short __b) { return ~(__a | __b); } static __inline__ vector bool short __ATTRS_o_ai vec_vnor(vector bool short __a, vector bool short __b) { return ~(__a | __b); } static __inline__ vector int __ATTRS_o_ai vec_vnor(vector int __a, vector int __b) { return ~(__a | __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vnor(vector unsigned int __a, vector unsigned int __b) { return ~(__a | __b); } static __inline__ vector bool int __ATTRS_o_ai vec_vnor(vector bool int __a, vector bool int __b) { return ~(__a | __b); } static __inline__ vector float __ATTRS_o_ai vec_vnor(vector float __a, vector float __b) { vector unsigned int __res = ~((vector unsigned int)__a | (vector unsigned int)__b); return (vector float)__res; } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_nor(vector signed long long __a, vector signed long long __b) { return ~(__a | __b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_nor(vector unsigned long long __a, vector unsigned long long __b) { return ~(__a | __b); } static __inline__ vector bool long long __ATTRS_o_ai vec_nor(vector bool long long __a, vector bool long long __b) { return ~(__a | __b); } #endif /* vec_or */ #define __builtin_altivec_vor vec_or static __inline__ vector signed char __ATTRS_o_ai vec_or(vector signed char __a, vector signed char __b) { return __a | __b; } static __inline__ vector signed char __ATTRS_o_ai vec_or(vector bool char __a, vector signed char __b) { return (vector signed char)__a | __b; } static __inline__ vector signed char __ATTRS_o_ai vec_or(vector signed char __a, vector bool char __b) { return __a | (vector signed char)__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_or(vector unsigned char __a, vector unsigned char __b) { return __a | __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_or(vector bool char __a, vector unsigned char __b) { return (vector unsigned char)__a | __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_or(vector unsigned char __a, vector bool char __b) { return __a | (vector unsigned char)__b; } static __inline__ vector bool char __ATTRS_o_ai vec_or(vector bool char __a, vector bool char __b) { return __a | __b; } static __inline__ vector short __ATTRS_o_ai vec_or(vector short __a, vector short __b) { return __a | __b; } static __inline__ vector short __ATTRS_o_ai vec_or(vector bool short __a, vector short __b) { return (vector short)__a | __b; } static __inline__ vector short __ATTRS_o_ai vec_or(vector short __a, vector bool short __b) { return __a | (vector short)__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_or(vector unsigned short __a, vector unsigned short __b) { return __a | __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_or(vector bool short __a, vector unsigned short __b) { return (vector unsigned short)__a | __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_or(vector unsigned short __a, vector bool short __b) { return __a | (vector unsigned short)__b; } static __inline__ vector bool short __ATTRS_o_ai vec_or(vector bool short __a, vector bool short __b) { return __a | __b; } static __inline__ vector int __ATTRS_o_ai vec_or(vector int __a, vector int __b) { return __a | __b; } static __inline__ vector int __ATTRS_o_ai vec_or(vector bool int __a, vector int __b) { return (vector int)__a | __b; } static __inline__ vector int __ATTRS_o_ai vec_or(vector int __a, vector bool int __b) { return __a | (vector int)__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_or(vector unsigned int __a, vector unsigned int __b) { return __a | __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_or(vector bool int __a, vector unsigned int __b) { return (vector unsigned int)__a | __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_or(vector unsigned int __a, vector bool int __b) { return __a | (vector unsigned int)__b; } static __inline__ vector bool int __ATTRS_o_ai vec_or(vector bool int __a, vector bool int __b) { return __a | __b; } static __inline__ vector float __ATTRS_o_ai vec_or(vector float __a, vector float __b) { vector unsigned int __res = (vector unsigned int)__a | (vector unsigned int)__b; return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_or(vector bool int __a, vector float __b) { vector unsigned int __res = (vector unsigned int)__a | (vector unsigned int)__b; return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_or(vector float __a, vector bool int __b) { vector unsigned int __res = (vector unsigned int)__a | (vector unsigned int)__b; return (vector float)__res; } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_or(vector bool long long __a, vector double __b) { return (vector unsigned long long)__a | (vector unsigned long long)__b; } static __inline__ vector double __ATTRS_o_ai vec_or(vector double __a, vector bool long long __b) { return (vector unsigned long long)__a | (vector unsigned long long)__b; } static __inline__ vector double __ATTRS_o_ai vec_or(vector double __a, vector double __b) { vector unsigned long long __res = (vector unsigned long long)__a | (vector unsigned long long)__b; return (vector double)__res; } static __inline__ vector signed long long __ATTRS_o_ai vec_or(vector signed long long __a, vector signed long long __b) { return __a | __b; } static __inline__ vector signed long long __ATTRS_o_ai vec_or(vector bool long long __a, vector signed long long __b) { return (vector signed long long)__a | __b; } static __inline__ vector signed long long __ATTRS_o_ai vec_or(vector signed long long __a, vector bool long long __b) { return __a | (vector signed long long)__b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_or(vector unsigned long long __a, vector unsigned long long __b) { return __a | __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_or(vector bool long long __a, vector unsigned long long __b) { return (vector unsigned long long)__a | __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_or(vector unsigned long long __a, vector bool long long __b) { return __a | (vector unsigned long long)__b; } static __inline__ vector bool long long __ATTRS_o_ai vec_or(vector bool long long __a, vector bool long long __b) { return __a | __b; } #endif #ifdef __POWER8_VECTOR__ static __inline__ vector signed char __ATTRS_o_ai vec_orc(vector signed char __a, vector signed char __b) { return __a | ~__b; } static __inline__ vector signed char __ATTRS_o_ai vec_orc(vector signed char __a, vector bool char __b) { return __a | ~__b; } static __inline__ vector signed char __ATTRS_o_ai vec_orc(vector bool char __a, vector signed char __b) { return __a | ~__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_orc(vector unsigned char __a, vector unsigned char __b) { return __a | ~__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_orc(vector unsigned char __a, vector bool char __b) { return __a | ~__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_orc(vector bool char __a, vector unsigned char __b) { return __a | ~__b; } static __inline__ vector bool char __ATTRS_o_ai vec_orc(vector bool char __a, vector bool char __b) { return __a | ~__b; } static __inline__ vector signed short __ATTRS_o_ai vec_orc(vector signed short __a, vector signed short __b) { return __a | ~__b; } static __inline__ vector signed short __ATTRS_o_ai vec_orc(vector signed short __a, vector bool short __b) { return __a | ~__b; } static __inline__ vector signed short __ATTRS_o_ai vec_orc(vector bool short __a, vector signed short __b) { return __a | ~__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_orc(vector unsigned short __a, vector unsigned short __b) { return __a | ~__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_orc(vector unsigned short __a, vector bool short __b) { return __a | ~__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_orc(vector bool short __a, vector unsigned short __b) { return __a | ~__b; } static __inline__ vector bool short __ATTRS_o_ai vec_orc(vector bool short __a, vector bool short __b) { return __a | ~__b; } static __inline__ vector signed int __ATTRS_o_ai vec_orc(vector signed int __a, vector signed int __b) { return __a | ~__b; } static __inline__ vector signed int __ATTRS_o_ai vec_orc(vector signed int __a, vector bool int __b) { return __a | ~__b; } static __inline__ vector signed int __ATTRS_o_ai vec_orc(vector bool int __a, vector signed int __b) { return __a | ~__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_orc(vector unsigned int __a, vector unsigned int __b) { return __a | ~__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_orc(vector unsigned int __a, vector bool int __b) { return __a | ~__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_orc(vector bool int __a, vector unsigned int __b) { return __a | ~__b; } static __inline__ vector bool int __ATTRS_o_ai vec_orc(vector bool int __a, vector bool int __b) { return __a | ~__b; } static __inline__ vector float __ATTRS_o_ai vec_orc(vector bool int __a, vector float __b) { return (vector float)(__a | ~(vector unsigned int)__b); } static __inline__ vector float __ATTRS_o_ai vec_orc(vector float __a, vector bool int __b) { return (vector float)((vector unsigned int)__a | ~__b); } static __inline__ vector signed long long __ATTRS_o_ai vec_orc(vector signed long long __a, vector signed long long __b) { return __a | ~__b; } static __inline__ vector signed long long __ATTRS_o_ai vec_orc(vector signed long long __a, vector bool long long __b) { return __a | ~__b; } static __inline__ vector signed long long __ATTRS_o_ai vec_orc(vector bool long long __a, vector signed long long __b) { return __a | ~__b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_orc(vector unsigned long long __a, vector unsigned long long __b) { return __a | ~__b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_orc(vector unsigned long long __a, vector bool long long __b) { return __a | ~__b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_orc(vector bool long long __a, vector unsigned long long __b) { return __a | ~__b; } static __inline__ vector bool long long __ATTRS_o_ai vec_orc(vector bool long long __a, vector bool long long __b) { return __a | ~__b; } static __inline__ vector double __ATTRS_o_ai vec_orc(vector double __a, vector bool long long __b) { return (vector double)((vector unsigned long long)__a | ~__b); } static __inline__ vector double __ATTRS_o_ai vec_orc(vector bool long long __a, vector double __b) { return (vector double)(__a | ~(vector unsigned long long)__b); } #endif /* vec_vor */ static __inline__ vector signed char __ATTRS_o_ai vec_vor(vector signed char __a, vector signed char __b) { return __a | __b; } static __inline__ vector signed char __ATTRS_o_ai vec_vor(vector bool char __a, vector signed char __b) { return (vector signed char)__a | __b; } static __inline__ vector signed char __ATTRS_o_ai vec_vor(vector signed char __a, vector bool char __b) { return __a | (vector signed char)__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vor(vector unsigned char __a, vector unsigned char __b) { return __a | __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vor(vector bool char __a, vector unsigned char __b) { return (vector unsigned char)__a | __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vor(vector unsigned char __a, vector bool char __b) { return __a | (vector unsigned char)__b; } static __inline__ vector bool char __ATTRS_o_ai vec_vor(vector bool char __a, vector bool char __b) { return __a | __b; } static __inline__ vector short __ATTRS_o_ai vec_vor(vector short __a, vector short __b) { return __a | __b; } static __inline__ vector short __ATTRS_o_ai vec_vor(vector bool short __a, vector short __b) { return (vector short)__a | __b; } static __inline__ vector short __ATTRS_o_ai vec_vor(vector short __a, vector bool short __b) { return __a | (vector short)__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vor(vector unsigned short __a, vector unsigned short __b) { return __a | __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vor(vector bool short __a, vector unsigned short __b) { return (vector unsigned short)__a | __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vor(vector unsigned short __a, vector bool short __b) { return __a | (vector unsigned short)__b; } static __inline__ vector bool short __ATTRS_o_ai vec_vor(vector bool short __a, vector bool short __b) { return __a | __b; } static __inline__ vector int __ATTRS_o_ai vec_vor(vector int __a, vector int __b) { return __a | __b; } static __inline__ vector int __ATTRS_o_ai vec_vor(vector bool int __a, vector int __b) { return (vector int)__a | __b; } static __inline__ vector int __ATTRS_o_ai vec_vor(vector int __a, vector bool int __b) { return __a | (vector int)__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vor(vector unsigned int __a, vector unsigned int __b) { return __a | __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vor(vector bool int __a, vector unsigned int __b) { return (vector unsigned int)__a | __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vor(vector unsigned int __a, vector bool int __b) { return __a | (vector unsigned int)__b; } static __inline__ vector bool int __ATTRS_o_ai vec_vor(vector bool int __a, vector bool int __b) { return __a | __b; } static __inline__ vector float __ATTRS_o_ai vec_vor(vector float __a, vector float __b) { vector unsigned int __res = (vector unsigned int)__a | (vector unsigned int)__b; return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_vor(vector bool int __a, vector float __b) { vector unsigned int __res = (vector unsigned int)__a | (vector unsigned int)__b; return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_vor(vector float __a, vector bool int __b) { vector unsigned int __res = (vector unsigned int)__a | (vector unsigned int)__b; return (vector float)__res; } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_vor(vector signed long long __a, vector signed long long __b) { return __a | __b; } static __inline__ vector signed long long __ATTRS_o_ai vec_vor(vector bool long long __a, vector signed long long __b) { return (vector signed long long)__a | __b; } static __inline__ vector signed long long __ATTRS_o_ai vec_vor(vector signed long long __a, vector bool long long __b) { return __a | (vector signed long long)__b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_vor(vector unsigned long long __a, vector unsigned long long __b) { return __a | __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_vor(vector bool long long __a, vector unsigned long long __b) { return (vector unsigned long long)__a | __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_vor(vector unsigned long long __a, vector bool long long __b) { return __a | (vector unsigned long long)__b; } static __inline__ vector bool long long __ATTRS_o_ai vec_vor(vector bool long long __a, vector bool long long __b) { return __a | __b; } #endif /* vec_pack */ /* The various vector pack instructions have a big-endian bias, so for little endian we must handle reversed element numbering. */ static __inline__ vector signed char __ATTRS_o_ai vec_pack(vector signed short __a, vector signed short __b) { #ifdef __LITTLE_ENDIAN__ return (vector signed char)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E)); #else return (vector signed char)vec_perm( __a, __b, (vector unsigned char)(0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F)); #endif } static __inline__ vector unsigned char __ATTRS_o_ai vec_pack(vector unsigned short __a, vector unsigned short __b) { #ifdef __LITTLE_ENDIAN__ return (vector unsigned char)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E)); #else return (vector unsigned char)vec_perm( __a, __b, (vector unsigned char)(0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F)); #endif } static __inline__ vector bool char __ATTRS_o_ai vec_pack(vector bool short __a, vector bool short __b) { #ifdef __LITTLE_ENDIAN__ return (vector bool char)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E)); #else return (vector bool char)vec_perm( __a, __b, (vector unsigned char)(0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F)); #endif } static __inline__ vector short __ATTRS_o_ai vec_pack(vector int __a, vector int __b) { #ifdef __LITTLE_ENDIAN__ return (vector short)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D)); #else return (vector short)vec_perm( __a, __b, (vector unsigned char)(0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F, 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F)); #endif } static __inline__ vector unsigned short __ATTRS_o_ai vec_pack(vector unsigned int __a, vector unsigned int __b) { #ifdef __LITTLE_ENDIAN__ return (vector unsigned short)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D)); #else return (vector unsigned short)vec_perm( __a, __b, (vector unsigned char)(0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F, 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F)); #endif } static __inline__ vector bool short __ATTRS_o_ai vec_pack(vector bool int __a, vector bool int __b) { #ifdef __LITTLE_ENDIAN__ return (vector bool short)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D)); #else return (vector bool short)vec_perm( __a, __b, (vector unsigned char)(0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F, 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F)); #endif } #ifdef __VSX__ static __inline__ vector signed int __ATTRS_o_ai vec_pack(vector signed long long __a, vector signed long long __b) { #ifdef __LITTLE_ENDIAN__ return (vector signed int)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x11, 0x12, 0x13, 0x18, 0x19, 0x1A, 0x1B)); #else return (vector signed int)vec_perm( __a, __b, (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x0C, 0x0D, 0x0E, 0x0F, 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F)); #endif } static __inline__ vector unsigned int __ATTRS_o_ai vec_pack(vector unsigned long long __a, vector unsigned long long __b) { #ifdef __LITTLE_ENDIAN__ return (vector unsigned int)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x11, 0x12, 0x13, 0x18, 0x19, 0x1A, 0x1B)); #else return (vector unsigned int)vec_perm( __a, __b, (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x0C, 0x0D, 0x0E, 0x0F, 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F)); #endif } static __inline__ vector bool int __ATTRS_o_ai vec_pack(vector bool long long __a, vector bool long long __b) { #ifdef __LITTLE_ENDIAN__ return (vector bool int)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x11, 0x12, 0x13, 0x18, 0x19, 0x1A, 0x1B)); #else return (vector bool int)vec_perm( __a, __b, (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x0C, 0x0D, 0x0E, 0x0F, 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F)); #endif } static __inline__ vector float __ATTRS_o_ai vec_pack(vector double __a, vector double __b) { return (vector float) (__a[0], __a[1], __b[0], __b[1]); } #endif #ifdef __POWER9_VECTOR__ static __inline__ vector unsigned short __ATTRS_o_ai vec_pack_to_short_fp32(vector float __a, vector float __b) { vector float __resa = __builtin_vsx_xvcvsphp(__a); vector float __resb = __builtin_vsx_xvcvsphp(__b); #ifdef __LITTLE_ENDIAN__ return (vector unsigned short)vec_mergee(__resa, __resb); #else return (vector unsigned short)vec_mergeo(__resa, __resb); #endif } #endif /* vec_vpkuhum */ #define __builtin_altivec_vpkuhum vec_vpkuhum static __inline__ vector signed char __ATTRS_o_ai vec_vpkuhum(vector signed short __a, vector signed short __b) { #ifdef __LITTLE_ENDIAN__ return (vector signed char)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E)); #else return (vector signed char)vec_perm( __a, __b, (vector unsigned char)(0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F)); #endif } static __inline__ vector unsigned char __ATTRS_o_ai vec_vpkuhum(vector unsigned short __a, vector unsigned short __b) { #ifdef __LITTLE_ENDIAN__ return (vector unsigned char)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E)); #else return (vector unsigned char)vec_perm( __a, __b, (vector unsigned char)(0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F)); #endif } static __inline__ vector bool char __ATTRS_o_ai vec_vpkuhum(vector bool short __a, vector bool short __b) { #ifdef __LITTLE_ENDIAN__ return (vector bool char)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E)); #else return (vector bool char)vec_perm( __a, __b, (vector unsigned char)(0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F)); #endif } /* vec_vpkuwum */ #define __builtin_altivec_vpkuwum vec_vpkuwum static __inline__ vector short __ATTRS_o_ai vec_vpkuwum(vector int __a, vector int __b) { #ifdef __LITTLE_ENDIAN__ return (vector short)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D)); #else return (vector short)vec_perm( __a, __b, (vector unsigned char)(0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F, 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F)); #endif } static __inline__ vector unsigned short __ATTRS_o_ai vec_vpkuwum(vector unsigned int __a, vector unsigned int __b) { #ifdef __LITTLE_ENDIAN__ return (vector unsigned short)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D)); #else return (vector unsigned short)vec_perm( __a, __b, (vector unsigned char)(0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F, 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F)); #endif } static __inline__ vector bool short __ATTRS_o_ai vec_vpkuwum(vector bool int __a, vector bool int __b) { #ifdef __LITTLE_ENDIAN__ return (vector bool short)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0C, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x18, 0x19, 0x1C, 0x1D)); #else return (vector bool short)vec_perm( __a, __b, (vector unsigned char)(0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F, 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F)); #endif } /* vec_vpkudum */ #ifdef __POWER8_VECTOR__ #define __builtin_altivec_vpkudum vec_vpkudum static __inline__ vector int __ATTRS_o_ai vec_vpkudum(vector long long __a, vector long long __b) { #ifdef __LITTLE_ENDIAN__ return (vector int)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x11, 0x12, 0x13, 0x18, 0x19, 0x1A, 0x1B)); #else return (vector int)vec_perm( __a, __b, (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x0C, 0x0D, 0x0E, 0x0F, 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F)); #endif } static __inline__ vector unsigned int __ATTRS_o_ai vec_vpkudum(vector unsigned long long __a, vector unsigned long long __b) { #ifdef __LITTLE_ENDIAN__ return (vector unsigned int)vec_perm( __a, __b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x11, 0x12, 0x13, 0x18, 0x19, 0x1A, 0x1B)); #else return (vector unsigned int)vec_perm( __a, __b, (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x0C, 0x0D, 0x0E, 0x0F, 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F)); #endif } static __inline__ vector bool int __ATTRS_o_ai vec_vpkudum(vector bool long long __a, vector bool long long __b) { #ifdef __LITTLE_ENDIAN__ return (vector bool int)vec_perm( (vector long long)__a, (vector long long)__b, (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x11, 0x12, 0x13, 0x18, 0x19, 0x1A, 0x1B)); #else return (vector bool int)vec_perm( (vector long long)__a, (vector long long)__b, (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x0C, 0x0D, 0x0E, 0x0F, 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F)); #endif } #endif /* vec_packpx */ static __inline__ vector pixel __attribute__((__always_inline__)) vec_packpx(vector unsigned int __a, vector unsigned int __b) { #ifdef __LITTLE_ENDIAN__ return (vector pixel)__builtin_altivec_vpkpx(__b, __a); #else return (vector pixel)__builtin_altivec_vpkpx(__a, __b); #endif } /* vec_vpkpx */ static __inline__ vector pixel __attribute__((__always_inline__)) vec_vpkpx(vector unsigned int __a, vector unsigned int __b) { #ifdef __LITTLE_ENDIAN__ return (vector pixel)__builtin_altivec_vpkpx(__b, __a); #else return (vector pixel)__builtin_altivec_vpkpx(__a, __b); #endif } /* vec_packs */ static __inline__ vector signed char __ATTRS_o_ai vec_packs(vector short __a, vector short __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkshss(__b, __a); #else return __builtin_altivec_vpkshss(__a, __b); #endif } static __inline__ vector unsigned char __ATTRS_o_ai vec_packs(vector unsigned short __a, vector unsigned short __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkuhus(__b, __a); #else return __builtin_altivec_vpkuhus(__a, __b); #endif } static __inline__ vector signed short __ATTRS_o_ai vec_packs(vector int __a, vector int __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkswss(__b, __a); #else return __builtin_altivec_vpkswss(__a, __b); #endif } static __inline__ vector unsigned short __ATTRS_o_ai vec_packs(vector unsigned int __a, vector unsigned int __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkuwus(__b, __a); #else return __builtin_altivec_vpkuwus(__a, __b); #endif } #ifdef __POWER8_VECTOR__ static __inline__ vector int __ATTRS_o_ai vec_packs(vector long long __a, vector long long __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpksdss(__b, __a); #else return __builtin_altivec_vpksdss(__a, __b); #endif } static __inline__ vector unsigned int __ATTRS_o_ai vec_packs(vector unsigned long long __a, vector unsigned long long __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkudus(__b, __a); #else return __builtin_altivec_vpkudus(__a, __b); #endif } #endif /* vec_vpkshss */ static __inline__ vector signed char __attribute__((__always_inline__)) vec_vpkshss(vector short __a, vector short __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkshss(__b, __a); #else return __builtin_altivec_vpkshss(__a, __b); #endif } /* vec_vpksdss */ #ifdef __POWER8_VECTOR__ static __inline__ vector int __ATTRS_o_ai vec_vpksdss(vector long long __a, vector long long __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpksdss(__b, __a); #else return __builtin_altivec_vpksdss(__a, __b); #endif } #endif /* vec_vpkuhus */ static __inline__ vector unsigned char __attribute__((__always_inline__)) vec_vpkuhus(vector unsigned short __a, vector unsigned short __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkuhus(__b, __a); #else return __builtin_altivec_vpkuhus(__a, __b); #endif } /* vec_vpkudus */ #ifdef __POWER8_VECTOR__ static __inline__ vector unsigned int __attribute__((__always_inline__)) vec_vpkudus(vector unsigned long long __a, vector unsigned long long __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkudus(__b, __a); #else return __builtin_altivec_vpkudus(__a, __b); #endif } #endif /* vec_vpkswss */ static __inline__ vector signed short __attribute__((__always_inline__)) vec_vpkswss(vector int __a, vector int __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkswss(__b, __a); #else return __builtin_altivec_vpkswss(__a, __b); #endif } /* vec_vpkuwus */ static __inline__ vector unsigned short __attribute__((__always_inline__)) vec_vpkuwus(vector unsigned int __a, vector unsigned int __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkuwus(__b, __a); #else return __builtin_altivec_vpkuwus(__a, __b); #endif } /* vec_packsu */ static __inline__ vector unsigned char __ATTRS_o_ai vec_packsu(vector short __a, vector short __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkshus(__b, __a); #else return __builtin_altivec_vpkshus(__a, __b); #endif } static __inline__ vector unsigned char __ATTRS_o_ai vec_packsu(vector unsigned short __a, vector unsigned short __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkuhus(__b, __a); #else return __builtin_altivec_vpkuhus(__a, __b); #endif } static __inline__ vector unsigned short __ATTRS_o_ai vec_packsu(vector int __a, vector int __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkswus(__b, __a); #else return __builtin_altivec_vpkswus(__a, __b); #endif } static __inline__ vector unsigned short __ATTRS_o_ai vec_packsu(vector unsigned int __a, vector unsigned int __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkuwus(__b, __a); #else return __builtin_altivec_vpkuwus(__a, __b); #endif } #ifdef __POWER8_VECTOR__ static __inline__ vector unsigned int __ATTRS_o_ai vec_packsu(vector long long __a, vector long long __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpksdus(__b, __a); #else return __builtin_altivec_vpksdus(__a, __b); #endif } static __inline__ vector unsigned int __ATTRS_o_ai vec_packsu(vector unsigned long long __a, vector unsigned long long __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkudus(__b, __a); #else return __builtin_altivec_vpkudus(__a, __b); #endif } #endif /* vec_vpkshus */ static __inline__ vector unsigned char __ATTRS_o_ai vec_vpkshus(vector short __a, vector short __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkshus(__b, __a); #else return __builtin_altivec_vpkshus(__a, __b); #endif } static __inline__ vector unsigned char __ATTRS_o_ai vec_vpkshus(vector unsigned short __a, vector unsigned short __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkuhus(__b, __a); #else return __builtin_altivec_vpkuhus(__a, __b); #endif } /* vec_vpkswus */ static __inline__ vector unsigned short __ATTRS_o_ai vec_vpkswus(vector int __a, vector int __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkswus(__b, __a); #else return __builtin_altivec_vpkswus(__a, __b); #endif } static __inline__ vector unsigned short __ATTRS_o_ai vec_vpkswus(vector unsigned int __a, vector unsigned int __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpkuwus(__b, __a); #else return __builtin_altivec_vpkuwus(__a, __b); #endif } /* vec_vpksdus */ #ifdef __POWER8_VECTOR__ static __inline__ vector unsigned int __ATTRS_o_ai vec_vpksdus(vector long long __a, vector long long __b) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vpksdus(__b, __a); #else return __builtin_altivec_vpksdus(__a, __b); #endif } #endif /* vec_perm */ // The vperm instruction is defined architecturally with a big-endian bias. // For little endian, we swap the input operands and invert the permute // control vector. Only the rightmost 5 bits matter, so we could use // a vector of all 31s instead of all 255s to perform the inversion. // However, when the PCV is not a constant, using 255 has an advantage // in that the vec_xor can be recognized as a vec_nor (and for P8 and // later, possibly a vec_nand). static __inline__ vector signed char __ATTRS_o_ai vec_perm( vector signed char __a, vector signed char __b, vector unsigned char __c) { #ifdef __LITTLE_ENDIAN__ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; __d = vec_xor(__c, __d); return (vector signed char)__builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d); #else return (vector signed char)__builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c); #endif } static __inline__ vector unsigned char __ATTRS_o_ai vec_perm(vector unsigned char __a, vector unsigned char __b, vector unsigned char __c) { #ifdef __LITTLE_ENDIAN__ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; __d = vec_xor(__c, __d); return (vector unsigned char)__builtin_altivec_vperm_4si( (vector int)__b, (vector int)__a, __d); #else return (vector unsigned char)__builtin_altivec_vperm_4si( (vector int)__a, (vector int)__b, __c); #endif } static __inline__ vector bool char __ATTRS_o_ai vec_perm(vector bool char __a, vector bool char __b, vector unsigned char __c) { #ifdef __LITTLE_ENDIAN__ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; __d = vec_xor(__c, __d); return (vector bool char)__builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d); #else return (vector bool char)__builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c); #endif } static __inline__ vector short __ATTRS_o_ai vec_perm(vector signed short __a, vector signed short __b, vector unsigned char __c) { #ifdef __LITTLE_ENDIAN__ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; __d = vec_xor(__c, __d); return (vector signed short)__builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d); #else return (vector signed short)__builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c); #endif } static __inline__ vector unsigned short __ATTRS_o_ai vec_perm(vector unsigned short __a, vector unsigned short __b, vector unsigned char __c) { #ifdef __LITTLE_ENDIAN__ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; __d = vec_xor(__c, __d); return (vector unsigned short)__builtin_altivec_vperm_4si( (vector int)__b, (vector int)__a, __d); #else return (vector unsigned short)__builtin_altivec_vperm_4si( (vector int)__a, (vector int)__b, __c); #endif } static __inline__ vector bool short __ATTRS_o_ai vec_perm( vector bool short __a, vector bool short __b, vector unsigned char __c) { #ifdef __LITTLE_ENDIAN__ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; __d = vec_xor(__c, __d); return (vector bool short)__builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d); #else return (vector bool short)__builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c); #endif } static __inline__ vector pixel __ATTRS_o_ai vec_perm(vector pixel __a, vector pixel __b, vector unsigned char __c) { #ifdef __LITTLE_ENDIAN__ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; __d = vec_xor(__c, __d); return (vector pixel)__builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d); #else return (vector pixel)__builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c); #endif } static __inline__ vector int __ATTRS_o_ai vec_perm(vector signed int __a, vector signed int __b, vector unsigned char __c) { #ifdef __LITTLE_ENDIAN__ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; __d = vec_xor(__c, __d); return (vector signed int)__builtin_altivec_vperm_4si(__b, __a, __d); #else return (vector signed int)__builtin_altivec_vperm_4si(__a, __b, __c); #endif } static __inline__ vector unsigned int __ATTRS_o_ai vec_perm(vector unsigned int __a, vector unsigned int __b, vector unsigned char __c) { #ifdef __LITTLE_ENDIAN__ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; __d = vec_xor(__c, __d); return (vector unsigned int)__builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d); #else return (vector unsigned int)__builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c); #endif } static __inline__ vector bool int __ATTRS_o_ai vec_perm(vector bool int __a, vector bool int __b, vector unsigned char __c) { #ifdef __LITTLE_ENDIAN__ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; __d = vec_xor(__c, __d); return (vector bool int)__builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d); #else return (vector bool int)__builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c); #endif } static __inline__ vector float __ATTRS_o_ai vec_perm(vector float __a, vector float __b, vector unsigned char __c) { #ifdef __LITTLE_ENDIAN__ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; __d = vec_xor(__c, __d); return (vector float)__builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d); #else return (vector float)__builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c); #endif } #ifdef __VSX__ static __inline__ vector long long __ATTRS_o_ai vec_perm(vector signed long long __a, vector signed long long __b, vector unsigned char __c) { #ifdef __LITTLE_ENDIAN__ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; __d = vec_xor(__c, __d); return (vector signed long long)__builtin_altivec_vperm_4si( (vector int)__b, (vector int)__a, __d); #else return (vector signed long long)__builtin_altivec_vperm_4si( (vector int)__a, (vector int)__b, __c); #endif } static __inline__ vector unsigned long long __ATTRS_o_ai vec_perm(vector unsigned long long __a, vector unsigned long long __b, vector unsigned char __c) { #ifdef __LITTLE_ENDIAN__ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; __d = vec_xor(__c, __d); return (vector unsigned long long)__builtin_altivec_vperm_4si( (vector int)__b, (vector int)__a, __d); #else return (vector unsigned long long)__builtin_altivec_vperm_4si( (vector int)__a, (vector int)__b, __c); #endif } static __inline__ vector bool long long __ATTRS_o_ai vec_perm(vector bool long long __a, vector bool long long __b, vector unsigned char __c) { #ifdef __LITTLE_ENDIAN__ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; __d = vec_xor(__c, __d); return (vector bool long long)__builtin_altivec_vperm_4si( (vector int)__b, (vector int)__a, __d); #else return (vector bool long long)__builtin_altivec_vperm_4si( (vector int)__a, (vector int)__b, __c); #endif } static __inline__ vector double __ATTRS_o_ai vec_perm(vector double __a, vector double __b, vector unsigned char __c) { #ifdef __LITTLE_ENDIAN__ vector unsigned char __d = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; __d = vec_xor(__c, __d); return (vector double)__builtin_altivec_vperm_4si((vector int)__b, (vector int)__a, __d); #else return (vector double)__builtin_altivec_vperm_4si((vector int)__a, (vector int)__b, __c); #endif } #endif /* vec_vperm */ static __inline__ vector signed char __ATTRS_o_ai vec_vperm( vector signed char __a, vector signed char __b, vector unsigned char __c) { return vec_perm(__a, __b, __c); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vperm(vector unsigned char __a, vector unsigned char __b, vector unsigned char __c) { return vec_perm(__a, __b, __c); } static __inline__ vector bool char __ATTRS_o_ai vec_vperm( vector bool char __a, vector bool char __b, vector unsigned char __c) { return vec_perm(__a, __b, __c); } static __inline__ vector short __ATTRS_o_ai vec_vperm(vector short __a, vector short __b, vector unsigned char __c) { return vec_perm(__a, __b, __c); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vperm(vector unsigned short __a, vector unsigned short __b, vector unsigned char __c) { return vec_perm(__a, __b, __c); } static __inline__ vector bool short __ATTRS_o_ai vec_vperm( vector bool short __a, vector bool short __b, vector unsigned char __c) { return vec_perm(__a, __b, __c); } static __inline__ vector pixel __ATTRS_o_ai vec_vperm(vector pixel __a, vector pixel __b, vector unsigned char __c) { return vec_perm(__a, __b, __c); } static __inline__ vector int __ATTRS_o_ai vec_vperm(vector int __a, vector int __b, vector unsigned char __c) { return vec_perm(__a, __b, __c); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vperm(vector unsigned int __a, vector unsigned int __b, vector unsigned char __c) { return vec_perm(__a, __b, __c); } static __inline__ vector bool int __ATTRS_o_ai vec_vperm(vector bool int __a, vector bool int __b, vector unsigned char __c) { return vec_perm(__a, __b, __c); } static __inline__ vector float __ATTRS_o_ai vec_vperm(vector float __a, vector float __b, vector unsigned char __c) { return vec_perm(__a, __b, __c); } #ifdef __VSX__ static __inline__ vector long long __ATTRS_o_ai vec_vperm( vector long long __a, vector long long __b, vector unsigned char __c) { return vec_perm(__a, __b, __c); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_vperm(vector unsigned long long __a, vector unsigned long long __b, vector unsigned char __c) { return vec_perm(__a, __b, __c); } static __inline__ vector double __ATTRS_o_ai vec_vperm(vector double __a, vector double __b, vector unsigned char __c) { return vec_perm(__a, __b, __c); } #endif /* vec_re */ static __inline__ vector float __ATTRS_o_ai vec_re(vector float __a) { #ifdef __VSX__ return __builtin_vsx_xvresp(__a); #else return __builtin_altivec_vrefp(__a); #endif } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_re(vector double __a) { return __builtin_vsx_xvredp(__a); } #endif /* vec_vrefp */ static __inline__ vector float __attribute__((__always_inline__)) vec_vrefp(vector float __a) { return __builtin_altivec_vrefp(__a); } /* vec_rl */ static __inline__ vector signed char __ATTRS_o_ai vec_rl(vector signed char __a, vector unsigned char __b) { return (vector signed char)__builtin_altivec_vrlb((vector char)__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_rl(vector unsigned char __a, vector unsigned char __b) { return (vector unsigned char)__builtin_altivec_vrlb((vector char)__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_rl(vector short __a, vector unsigned short __b) { return __builtin_altivec_vrlh(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_rl(vector unsigned short __a, vector unsigned short __b) { return (vector unsigned short)__builtin_altivec_vrlh((vector short)__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_rl(vector int __a, vector unsigned int __b) { return __builtin_altivec_vrlw(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_rl(vector unsigned int __a, vector unsigned int __b) { return (vector unsigned int)__builtin_altivec_vrlw((vector int)__a, __b); } #ifdef __POWER8_VECTOR__ static __inline__ vector signed long long __ATTRS_o_ai vec_rl(vector signed long long __a, vector unsigned long long __b) { return __builtin_altivec_vrld(__a, __b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_rl(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_vrld(__a, __b); } #endif /* vec_rlmi */ #ifdef __POWER9_VECTOR__ static __inline__ vector unsigned int __ATTRS_o_ai vec_rlmi(vector unsigned int __a, vector unsigned int __b, vector unsigned int __c) { return __builtin_altivec_vrlwmi(__a, __c, __b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_rlmi(vector unsigned long long __a, vector unsigned long long __b, vector unsigned long long __c) { return __builtin_altivec_vrldmi(__a, __c, __b); } /* vec_rlnm */ static __inline__ vector unsigned int __ATTRS_o_ai vec_rlnm(vector unsigned int __a, vector unsigned int __b, vector unsigned int __c) { vector unsigned int OneByte = { 0x8, 0x8, 0x8, 0x8 }; return __builtin_altivec_vrlwnm(__a, ((__c << OneByte) | __b)); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_rlnm(vector unsigned long long __a, vector unsigned long long __b, vector unsigned long long __c) { vector unsigned long long OneByte = { 0x8, 0x8 }; return __builtin_altivec_vrldnm(__a, ((__c << OneByte) | __b)); } #endif /* vec_vrlb */ static __inline__ vector signed char __ATTRS_o_ai vec_vrlb(vector signed char __a, vector unsigned char __b) { return (vector signed char)__builtin_altivec_vrlb((vector char)__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vrlb(vector unsigned char __a, vector unsigned char __b) { return (vector unsigned char)__builtin_altivec_vrlb((vector char)__a, __b); } /* vec_vrlh */ static __inline__ vector short __ATTRS_o_ai vec_vrlh(vector short __a, vector unsigned short __b) { return __builtin_altivec_vrlh(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vrlh(vector unsigned short __a, vector unsigned short __b) { return (vector unsigned short)__builtin_altivec_vrlh((vector short)__a, __b); } /* vec_vrlw */ static __inline__ vector int __ATTRS_o_ai vec_vrlw(vector int __a, vector unsigned int __b) { return __builtin_altivec_vrlw(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vrlw(vector unsigned int __a, vector unsigned int __b) { return (vector unsigned int)__builtin_altivec_vrlw((vector int)__a, __b); } /* vec_round */ static __inline__ vector float __ATTRS_o_ai vec_round(vector float __a) { #ifdef __VSX__ return __builtin_vsx_xvrspi(__a); #else return __builtin_altivec_vrfin(__a); #endif } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_round(vector double __a) { return __builtin_vsx_xvrdpi(__a); } /* vec_rint */ static __inline__ vector float __ATTRS_o_ai vec_rint(vector float __a) { return __builtin_vsx_xvrspic(__a); } static __inline__ vector double __ATTRS_o_ai vec_rint(vector double __a) { return __builtin_vsx_xvrdpic(__a); } /* vec_nearbyint */ static __inline__ vector float __ATTRS_o_ai vec_nearbyint(vector float __a) { return __builtin_vsx_xvrspi(__a); } static __inline__ vector double __ATTRS_o_ai vec_nearbyint(vector double __a) { return __builtin_vsx_xvrdpi(__a); } #endif /* vec_vrfin */ static __inline__ vector float __attribute__((__always_inline__)) vec_vrfin(vector float __a) { return __builtin_altivec_vrfin(__a); } /* vec_sqrt */ #ifdef __VSX__ static __inline__ vector float __ATTRS_o_ai vec_sqrt(vector float __a) { return __builtin_vsx_xvsqrtsp(__a); } static __inline__ vector double __ATTRS_o_ai vec_sqrt(vector double __a) { return __builtin_vsx_xvsqrtdp(__a); } #endif /* vec_rsqrte */ static __inline__ vector float __ATTRS_o_ai vec_rsqrte(vector float __a) { #ifdef __VSX__ return __builtin_vsx_xvrsqrtesp(__a); #else return __builtin_altivec_vrsqrtefp(__a); #endif } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_rsqrte(vector double __a) { return __builtin_vsx_xvrsqrtedp(__a); } #endif /* vec_vrsqrtefp */ static __inline__ __vector float __attribute__((__always_inline__)) vec_vrsqrtefp(vector float __a) { return __builtin_altivec_vrsqrtefp(__a); } /* vec_sel */ #define __builtin_altivec_vsel_4si vec_sel static __inline__ vector signed char __ATTRS_o_ai vec_sel( vector signed char __a, vector signed char __b, vector unsigned char __c) { return (__a & ~(vector signed char)__c) | (__b & (vector signed char)__c); } static __inline__ vector signed char __ATTRS_o_ai vec_sel(vector signed char __a, vector signed char __b, vector bool char __c) { return (__a & ~(vector signed char)__c) | (__b & (vector signed char)__c); } static __inline__ vector unsigned char __ATTRS_o_ai vec_sel(vector unsigned char __a, vector unsigned char __b, vector unsigned char __c) { return (__a & ~__c) | (__b & __c); } static __inline__ vector unsigned char __ATTRS_o_ai vec_sel( vector unsigned char __a, vector unsigned char __b, vector bool char __c) { return (__a & ~(vector unsigned char)__c) | (__b & (vector unsigned char)__c); } static __inline__ vector bool char __ATTRS_o_ai vec_sel(vector bool char __a, vector bool char __b, vector unsigned char __c) { return (__a & ~(vector bool char)__c) | (__b & (vector bool char)__c); } static __inline__ vector bool char __ATTRS_o_ai vec_sel(vector bool char __a, vector bool char __b, vector bool char __c) { return (__a & ~__c) | (__b & __c); } static __inline__ vector short __ATTRS_o_ai vec_sel(vector short __a, vector short __b, vector unsigned short __c) { return (__a & ~(vector short)__c) | (__b & (vector short)__c); } static __inline__ vector short __ATTRS_o_ai vec_sel(vector short __a, vector short __b, vector bool short __c) { return (__a & ~(vector short)__c) | (__b & (vector short)__c); } static __inline__ vector unsigned short __ATTRS_o_ai vec_sel(vector unsigned short __a, vector unsigned short __b, vector unsigned short __c) { return (__a & ~__c) | (__b & __c); } static __inline__ vector unsigned short __ATTRS_o_ai vec_sel(vector unsigned short __a, vector unsigned short __b, vector bool short __c) { return (__a & ~(vector unsigned short)__c) | (__b & (vector unsigned short)__c); } static __inline__ vector bool short __ATTRS_o_ai vec_sel( vector bool short __a, vector bool short __b, vector unsigned short __c) { return (__a & ~(vector bool short)__c) | (__b & (vector bool short)__c); } static __inline__ vector bool short __ATTRS_o_ai vec_sel(vector bool short __a, vector bool short __b, vector bool short __c) { return (__a & ~__c) | (__b & __c); } static __inline__ vector int __ATTRS_o_ai vec_sel(vector int __a, vector int __b, vector unsigned int __c) { return (__a & ~(vector int)__c) | (__b & (vector int)__c); } static __inline__ vector int __ATTRS_o_ai vec_sel(vector int __a, vector int __b, vector bool int __c) { return (__a & ~(vector int)__c) | (__b & (vector int)__c); } static __inline__ vector unsigned int __ATTRS_o_ai vec_sel( vector unsigned int __a, vector unsigned int __b, vector unsigned int __c) { return (__a & ~__c) | (__b & __c); } static __inline__ vector unsigned int __ATTRS_o_ai vec_sel(vector unsigned int __a, vector unsigned int __b, vector bool int __c) { return (__a & ~(vector unsigned int)__c) | (__b & (vector unsigned int)__c); } static __inline__ vector bool int __ATTRS_o_ai vec_sel(vector bool int __a, vector bool int __b, vector unsigned int __c) { return (__a & ~(vector bool int)__c) | (__b & (vector bool int)__c); } static __inline__ vector bool int __ATTRS_o_ai vec_sel(vector bool int __a, vector bool int __b, vector bool int __c) { return (__a & ~__c) | (__b & __c); } static __inline__ vector float __ATTRS_o_ai vec_sel(vector float __a, vector float __b, vector unsigned int __c) { vector int __res = ((vector int)__a & ~(vector int)__c) | ((vector int)__b & (vector int)__c); return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_sel(vector float __a, vector float __b, vector bool int __c) { vector int __res = ((vector int)__a & ~(vector int)__c) | ((vector int)__b & (vector int)__c); return (vector float)__res; } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_sel(vector double __a, vector double __b, vector bool long long __c) { vector long long __res = ((vector long long)__a & ~(vector long long)__c) | ((vector long long)__b & (vector long long)__c); return (vector double)__res; } static __inline__ vector double __ATTRS_o_ai vec_sel(vector double __a, vector double __b, vector unsigned long long __c) { vector long long __res = ((vector long long)__a & ~(vector long long)__c) | ((vector long long)__b & (vector long long)__c); return (vector double)__res; } #endif /* vec_vsel */ static __inline__ vector signed char __ATTRS_o_ai vec_vsel( vector signed char __a, vector signed char __b, vector unsigned char __c) { return (__a & ~(vector signed char)__c) | (__b & (vector signed char)__c); } static __inline__ vector signed char __ATTRS_o_ai vec_vsel(vector signed char __a, vector signed char __b, vector bool char __c) { return (__a & ~(vector signed char)__c) | (__b & (vector signed char)__c); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsel(vector unsigned char __a, vector unsigned char __b, vector unsigned char __c) { return (__a & ~__c) | (__b & __c); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsel( vector unsigned char __a, vector unsigned char __b, vector bool char __c) { return (__a & ~(vector unsigned char)__c) | (__b & (vector unsigned char)__c); } static __inline__ vector bool char __ATTRS_o_ai vec_vsel(vector bool char __a, vector bool char __b, vector unsigned char __c) { return (__a & ~(vector bool char)__c) | (__b & (vector bool char)__c); } static __inline__ vector bool char __ATTRS_o_ai vec_vsel(vector bool char __a, vector bool char __b, vector bool char __c) { return (__a & ~__c) | (__b & __c); } static __inline__ vector short __ATTRS_o_ai vec_vsel(vector short __a, vector short __b, vector unsigned short __c) { return (__a & ~(vector short)__c) | (__b & (vector short)__c); } static __inline__ vector short __ATTRS_o_ai vec_vsel(vector short __a, vector short __b, vector bool short __c) { return (__a & ~(vector short)__c) | (__b & (vector short)__c); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsel(vector unsigned short __a, vector unsigned short __b, vector unsigned short __c) { return (__a & ~__c) | (__b & __c); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsel(vector unsigned short __a, vector unsigned short __b, vector bool short __c) { return (__a & ~(vector unsigned short)__c) | (__b & (vector unsigned short)__c); } static __inline__ vector bool short __ATTRS_o_ai vec_vsel( vector bool short __a, vector bool short __b, vector unsigned short __c) { return (__a & ~(vector bool short)__c) | (__b & (vector bool short)__c); } static __inline__ vector bool short __ATTRS_o_ai vec_vsel(vector bool short __a, vector bool short __b, vector bool short __c) { return (__a & ~__c) | (__b & __c); } static __inline__ vector int __ATTRS_o_ai vec_vsel(vector int __a, vector int __b, vector unsigned int __c) { return (__a & ~(vector int)__c) | (__b & (vector int)__c); } static __inline__ vector int __ATTRS_o_ai vec_vsel(vector int __a, vector int __b, vector bool int __c) { return (__a & ~(vector int)__c) | (__b & (vector int)__c); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsel( vector unsigned int __a, vector unsigned int __b, vector unsigned int __c) { return (__a & ~__c) | (__b & __c); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsel( vector unsigned int __a, vector unsigned int __b, vector bool int __c) { return (__a & ~(vector unsigned int)__c) | (__b & (vector unsigned int)__c); } static __inline__ vector bool int __ATTRS_o_ai vec_vsel(vector bool int __a, vector bool int __b, vector unsigned int __c) { return (__a & ~(vector bool int)__c) | (__b & (vector bool int)__c); } static __inline__ vector bool int __ATTRS_o_ai vec_vsel(vector bool int __a, vector bool int __b, vector bool int __c) { return (__a & ~__c) | (__b & __c); } static __inline__ vector float __ATTRS_o_ai vec_vsel(vector float __a, vector float __b, vector unsigned int __c) { vector int __res = ((vector int)__a & ~(vector int)__c) | ((vector int)__b & (vector int)__c); return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_vsel(vector float __a, vector float __b, vector bool int __c) { vector int __res = ((vector int)__a & ~(vector int)__c) | ((vector int)__b & (vector int)__c); return (vector float)__res; } /* vec_sl */ // vec_sl does modulo arithmetic on __b first, so __b is allowed to be more // than the length of __a. static __inline__ vector unsigned char __ATTRS_o_ai vec_sl(vector unsigned char __a, vector unsigned char __b) { return __a << (__b % (vector unsigned char)(sizeof(unsigned char) * __CHAR_BIT__)); } static __inline__ vector signed char __ATTRS_o_ai vec_sl(vector signed char __a, vector unsigned char __b) { return (vector signed char)vec_sl((vector unsigned char)__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_sl(vector unsigned short __a, vector unsigned short __b) { return __a << (__b % (vector unsigned short)(sizeof(unsigned short) * __CHAR_BIT__)); } static __inline__ vector short __ATTRS_o_ai vec_sl(vector short __a, vector unsigned short __b) { return (vector short)vec_sl((vector unsigned short)__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_sl(vector unsigned int __a, vector unsigned int __b) { return __a << (__b % (vector unsigned int)(sizeof(unsigned int) * __CHAR_BIT__)); } static __inline__ vector int __ATTRS_o_ai vec_sl(vector int __a, vector unsigned int __b) { return (vector int)vec_sl((vector unsigned int)__a, __b); } #ifdef __POWER8_VECTOR__ static __inline__ vector unsigned long long __ATTRS_o_ai vec_sl(vector unsigned long long __a, vector unsigned long long __b) { return __a << (__b % (vector unsigned long long)(sizeof(unsigned long long) * __CHAR_BIT__)); } static __inline__ vector long long __ATTRS_o_ai vec_sl(vector long long __a, vector unsigned long long __b) { return (vector long long)vec_sl((vector unsigned long long)__a, __b); } #endif /* vec_vslb */ #define __builtin_altivec_vslb vec_vslb static __inline__ vector signed char __ATTRS_o_ai vec_vslb(vector signed char __a, vector unsigned char __b) { return vec_sl(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vslb(vector unsigned char __a, vector unsigned char __b) { return vec_sl(__a, __b); } /* vec_vslh */ #define __builtin_altivec_vslh vec_vslh static __inline__ vector short __ATTRS_o_ai vec_vslh(vector short __a, vector unsigned short __b) { return vec_sl(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vslh(vector unsigned short __a, vector unsigned short __b) { return vec_sl(__a, __b); } /* vec_vslw */ #define __builtin_altivec_vslw vec_vslw static __inline__ vector int __ATTRS_o_ai vec_vslw(vector int __a, vector unsigned int __b) { return vec_sl(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vslw(vector unsigned int __a, vector unsigned int __b) { return vec_sl(__a, __b); } /* vec_sld */ #define __builtin_altivec_vsldoi_4si vec_sld static __inline__ vector signed char __ATTRS_o_ai vec_sld( vector signed char __a, vector signed char __b, unsigned const int __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector unsigned char __ATTRS_o_ai vec_sld(vector unsigned char __a, vector unsigned char __b, unsigned const int __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector bool char __ATTRS_o_ai vec_sld(vector bool char __a, vector bool char __b, unsigned const int __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector signed short __ATTRS_o_ai vec_sld( vector signed short __a, vector signed short __b, unsigned const int __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector unsigned short __ATTRS_o_ai vec_sld(vector unsigned short __a, vector unsigned short __b, unsigned const int __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector bool short __ATTRS_o_ai vec_sld(vector bool short __a, vector bool short __b, unsigned const int __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector pixel __ATTRS_o_ai vec_sld(vector pixel __a, vector pixel __b, unsigned const int __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector signed int __ATTRS_o_ai vec_sld(vector signed int __a, vector signed int __b, unsigned const int __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector unsigned int __ATTRS_o_ai vec_sld( vector unsigned int __a, vector unsigned int __b, unsigned const int __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector bool int __ATTRS_o_ai vec_sld(vector bool int __a, vector bool int __b, unsigned const int __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector float __ATTRS_o_ai vec_sld(vector float __a, vector float __b, unsigned const int __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } #ifdef __VSX__ static __inline__ vector bool long long __ATTRS_o_ai vec_sld(vector bool long long __a, vector bool long long __b, unsigned const int __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector signed long long __ATTRS_o_ai vec_sld(vector signed long long __a, vector signed long long __b, unsigned const int __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector unsigned long long __ATTRS_o_ai vec_sld(vector unsigned long long __a, vector unsigned long long __b, unsigned const int __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector double __ATTRS_o_ai vec_sld(vector double __a, vector double __b, unsigned const int __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } #endif /* vec_sldw */ static __inline__ vector signed char __ATTRS_o_ai vec_sldw( vector signed char __a, vector signed char __b, unsigned const int __c) { return vec_sld(__a, __b, ((__c << 2) & 0x0F)); } static __inline__ vector unsigned char __ATTRS_o_ai vec_sldw(vector unsigned char __a, vector unsigned char __b, unsigned const int __c) { return vec_sld(__a, __b, ((__c << 2) & 0x0F)); } static __inline__ vector signed short __ATTRS_o_ai vec_sldw( vector signed short __a, vector signed short __b, unsigned const int __c) { return vec_sld(__a, __b, ((__c << 2) & 0x0F)); } static __inline__ vector unsigned short __ATTRS_o_ai vec_sldw(vector unsigned short __a, vector unsigned short __b, unsigned const int __c) { return vec_sld(__a, __b, ((__c << 2) & 0x0F)); } static __inline__ vector signed int __ATTRS_o_ai vec_sldw(vector signed int __a, vector signed int __b, unsigned const int __c) { return vec_sld(__a, __b, ((__c << 2) & 0x0F)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_sldw( vector unsigned int __a, vector unsigned int __b, unsigned const int __c) { return vec_sld(__a, __b, ((__c << 2) & 0x0F)); } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_sldw(vector signed long long __a, vector signed long long __b, unsigned const int __c) { return vec_sld(__a, __b, ((__c << 2) & 0x0F)); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_sldw(vector unsigned long long __a, vector unsigned long long __b, unsigned const int __c) { return vec_sld(__a, __b, ((__c << 2) & 0x0F)); } #endif #ifdef __POWER9_VECTOR__ /* vec_slv */ static __inline__ vector unsigned char __ATTRS_o_ai vec_slv(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vslv(__a, __b); } /* vec_srv */ static __inline__ vector unsigned char __ATTRS_o_ai vec_srv(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vsrv(__a, __b); } #endif /* vec_vsldoi */ static __inline__ vector signed char __ATTRS_o_ai vec_vsldoi(vector signed char __a, vector signed char __b, unsigned char __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsldoi( vector unsigned char __a, vector unsigned char __b, unsigned char __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector short __ATTRS_o_ai vec_vsldoi(vector short __a, vector short __b, unsigned char __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsldoi( vector unsigned short __a, vector unsigned short __b, unsigned char __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector pixel __ATTRS_o_ai vec_vsldoi(vector pixel __a, vector pixel __b, unsigned char __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector int __ATTRS_o_ai vec_vsldoi(vector int __a, vector int __b, unsigned char __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsldoi( vector unsigned int __a, vector unsigned int __b, unsigned char __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } static __inline__ vector float __ATTRS_o_ai vec_vsldoi(vector float __a, vector float __b, unsigned char __c) { unsigned char __d = __c & 0x0F; #ifdef __LITTLE_ENDIAN__ return vec_perm( __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d, 20 - __d, 21 - __d, 22 - __d, 23 - __d, 24 - __d, 25 - __d, 26 - __d, 27 - __d, 28 - __d, 29 - __d, 30 - __d, 31 - __d)); #else return vec_perm( __a, __b, (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5, __d + 6, __d + 7, __d + 8, __d + 9, __d + 10, __d + 11, __d + 12, __d + 13, __d + 14, __d + 15)); #endif } /* vec_sll */ static __inline__ vector signed char __ATTRS_o_ai vec_sll(vector signed char __a, vector unsigned char __b) { return (vector signed char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector signed char __ATTRS_o_ai vec_sll(vector signed char __a, vector unsigned short __b) { return (vector signed char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector signed char __ATTRS_o_ai vec_sll(vector signed char __a, vector unsigned int __b) { return (vector signed char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_sll(vector unsigned char __a, vector unsigned char __b) { return (vector unsigned char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_sll(vector unsigned char __a, vector unsigned short __b) { return (vector unsigned char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_sll(vector unsigned char __a, vector unsigned int __b) { return (vector unsigned char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_sll(vector bool char __a, vector unsigned char __b) { return (vector bool char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_sll(vector bool char __a, vector unsigned short __b) { return (vector bool char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_sll(vector bool char __a, vector unsigned int __b) { return (vector bool char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_sll(vector short __a, vector unsigned char __b) { return (vector short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_sll(vector short __a, vector unsigned short __b) { return (vector short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_sll(vector short __a, vector unsigned int __b) { return (vector short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_sll(vector unsigned short __a, vector unsigned char __b) { return (vector unsigned short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_sll(vector unsigned short __a, vector unsigned short __b) { return (vector unsigned short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_sll(vector unsigned short __a, vector unsigned int __b) { return (vector unsigned short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_sll(vector bool short __a, vector unsigned char __b) { return (vector bool short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_sll(vector bool short __a, vector unsigned short __b) { return (vector bool short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_sll(vector bool short __a, vector unsigned int __b) { return (vector bool short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_sll(vector pixel __a, vector unsigned char __b) { return (vector pixel)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_sll(vector pixel __a, vector unsigned short __b) { return (vector pixel)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_sll(vector pixel __a, vector unsigned int __b) { return (vector pixel)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_sll(vector int __a, vector unsigned char __b) { return (vector int)__builtin_altivec_vsl(__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_sll(vector int __a, vector unsigned short __b) { return (vector int)__builtin_altivec_vsl(__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_sll(vector int __a, vector unsigned int __b) { return (vector int)__builtin_altivec_vsl(__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_sll(vector unsigned int __a, vector unsigned char __b) { return (vector unsigned int)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_sll(vector unsigned int __a, vector unsigned short __b) { return (vector unsigned int)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_sll(vector unsigned int __a, vector unsigned int __b) { return (vector unsigned int)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_sll(vector bool int __a, vector unsigned char __b) { return (vector bool int)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_sll(vector bool int __a, vector unsigned short __b) { return (vector bool int)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_sll(vector bool int __a, vector unsigned int __b) { return (vector bool int)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_sll(vector signed long long __a, vector unsigned char __b) { return (vector signed long long)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_sll(vector unsigned long long __a, vector unsigned char __b) { return (vector unsigned long long)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } #endif /* vec_vsl */ static __inline__ vector signed char __ATTRS_o_ai vec_vsl(vector signed char __a, vector unsigned char __b) { return (vector signed char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector signed char __ATTRS_o_ai vec_vsl(vector signed char __a, vector unsigned short __b) { return (vector signed char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector signed char __ATTRS_o_ai vec_vsl(vector signed char __a, vector unsigned int __b) { return (vector signed char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsl(vector unsigned char __a, vector unsigned char __b) { return (vector unsigned char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsl(vector unsigned char __a, vector unsigned short __b) { return (vector unsigned char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsl(vector unsigned char __a, vector unsigned int __b) { return (vector unsigned char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_vsl(vector bool char __a, vector unsigned char __b) { return (vector bool char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_vsl(vector bool char __a, vector unsigned short __b) { return (vector bool char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_vsl(vector bool char __a, vector unsigned int __b) { return (vector bool char)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_vsl(vector short __a, vector unsigned char __b) { return (vector short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_vsl(vector short __a, vector unsigned short __b) { return (vector short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_vsl(vector short __a, vector unsigned int __b) { return (vector short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsl(vector unsigned short __a, vector unsigned char __b) { return (vector unsigned short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsl(vector unsigned short __a, vector unsigned short __b) { return (vector unsigned short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsl(vector unsigned short __a, vector unsigned int __b) { return (vector unsigned short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_vsl(vector bool short __a, vector unsigned char __b) { return (vector bool short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_vsl(vector bool short __a, vector unsigned short __b) { return (vector bool short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_vsl(vector bool short __a, vector unsigned int __b) { return (vector bool short)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_vsl(vector pixel __a, vector unsigned char __b) { return (vector pixel)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_vsl(vector pixel __a, vector unsigned short __b) { return (vector pixel)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_vsl(vector pixel __a, vector unsigned int __b) { return (vector pixel)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_vsl(vector int __a, vector unsigned char __b) { return (vector int)__builtin_altivec_vsl(__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_vsl(vector int __a, vector unsigned short __b) { return (vector int)__builtin_altivec_vsl(__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_vsl(vector int __a, vector unsigned int __b) { return (vector int)__builtin_altivec_vsl(__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsl(vector unsigned int __a, vector unsigned char __b) { return (vector unsigned int)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsl(vector unsigned int __a, vector unsigned short __b) { return (vector unsigned int)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsl(vector unsigned int __a, vector unsigned int __b) { return (vector unsigned int)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_vsl(vector bool int __a, vector unsigned char __b) { return (vector bool int)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_vsl(vector bool int __a, vector unsigned short __b) { return (vector bool int)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_vsl(vector bool int __a, vector unsigned int __b) { return (vector bool int)__builtin_altivec_vsl((vector int)__a, (vector int)__b); } /* vec_slo */ static __inline__ vector signed char __ATTRS_o_ai vec_slo(vector signed char __a, vector signed char __b) { return (vector signed char)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector signed char __ATTRS_o_ai vec_slo(vector signed char __a, vector unsigned char __b) { return (vector signed char)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_slo(vector unsigned char __a, vector signed char __b) { return (vector unsigned char)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_slo(vector unsigned char __a, vector unsigned char __b) { return (vector unsigned char)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_slo(vector short __a, vector signed char __b) { return (vector short)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_slo(vector short __a, vector unsigned char __b) { return (vector short)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_slo(vector unsigned short __a, vector signed char __b) { return (vector unsigned short)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_slo(vector unsigned short __a, vector unsigned char __b) { return (vector unsigned short)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_slo(vector pixel __a, vector signed char __b) { return (vector pixel)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_slo(vector pixel __a, vector unsigned char __b) { return (vector pixel)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_slo(vector int __a, vector signed char __b) { return (vector int)__builtin_altivec_vslo(__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_slo(vector int __a, vector unsigned char __b) { return (vector int)__builtin_altivec_vslo(__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_slo(vector unsigned int __a, vector signed char __b) { return (vector unsigned int)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_slo(vector unsigned int __a, vector unsigned char __b) { return (vector unsigned int)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector float __ATTRS_o_ai vec_slo(vector float __a, vector signed char __b) { return (vector float)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector float __ATTRS_o_ai vec_slo(vector float __a, vector unsigned char __b) { return (vector float)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_slo(vector signed long long __a, vector signed char __b) { return (vector signed long long)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector signed long long __ATTRS_o_ai vec_slo(vector signed long long __a, vector unsigned char __b) { return (vector signed long long)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_slo(vector unsigned long long __a, vector signed char __b) { return (vector unsigned long long)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_slo(vector unsigned long long __a, vector unsigned char __b) { return (vector unsigned long long)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } #endif /* vec_vslo */ static __inline__ vector signed char __ATTRS_o_ai vec_vslo(vector signed char __a, vector signed char __b) { return (vector signed char)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector signed char __ATTRS_o_ai vec_vslo(vector signed char __a, vector unsigned char __b) { return (vector signed char)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vslo(vector unsigned char __a, vector signed char __b) { return (vector unsigned char)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vslo(vector unsigned char __a, vector unsigned char __b) { return (vector unsigned char)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_vslo(vector short __a, vector signed char __b) { return (vector short)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_vslo(vector short __a, vector unsigned char __b) { return (vector short)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vslo(vector unsigned short __a, vector signed char __b) { return (vector unsigned short)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vslo(vector unsigned short __a, vector unsigned char __b) { return (vector unsigned short)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_vslo(vector pixel __a, vector signed char __b) { return (vector pixel)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_vslo(vector pixel __a, vector unsigned char __b) { return (vector pixel)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_vslo(vector int __a, vector signed char __b) { return (vector int)__builtin_altivec_vslo(__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_vslo(vector int __a, vector unsigned char __b) { return (vector int)__builtin_altivec_vslo(__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vslo(vector unsigned int __a, vector signed char __b) { return (vector unsigned int)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vslo(vector unsigned int __a, vector unsigned char __b) { return (vector unsigned int)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector float __ATTRS_o_ai vec_vslo(vector float __a, vector signed char __b) { return (vector float)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } static __inline__ vector float __ATTRS_o_ai vec_vslo(vector float __a, vector unsigned char __b) { return (vector float)__builtin_altivec_vslo((vector int)__a, (vector int)__b); } /* vec_splat */ static __inline__ vector signed char __ATTRS_o_ai vec_splat(vector signed char __a, unsigned const int __b) { return vec_perm(__a, __a, (vector unsigned char)(__b & 0x0F)); } static __inline__ vector unsigned char __ATTRS_o_ai vec_splat(vector unsigned char __a, unsigned const int __b) { return vec_perm(__a, __a, (vector unsigned char)(__b & 0x0F)); } static __inline__ vector bool char __ATTRS_o_ai vec_splat(vector bool char __a, unsigned const int __b) { return vec_perm(__a, __a, (vector unsigned char)(__b & 0x0F)); } static __inline__ vector signed short __ATTRS_o_ai vec_splat(vector signed short __a, unsigned const int __b) { unsigned char b0 = (__b & 0x07) * 2; unsigned char b1 = b0 + 1; return vec_perm(__a, __a, (vector unsigned char)(b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1)); } static __inline__ vector unsigned short __ATTRS_o_ai vec_splat(vector unsigned short __a, unsigned const int __b) { unsigned char b0 = (__b & 0x07) * 2; unsigned char b1 = b0 + 1; return vec_perm(__a, __a, (vector unsigned char)(b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1)); } static __inline__ vector bool short __ATTRS_o_ai vec_splat(vector bool short __a, unsigned const int __b) { unsigned char b0 = (__b & 0x07) * 2; unsigned char b1 = b0 + 1; return vec_perm(__a, __a, (vector unsigned char)(b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1)); } static __inline__ vector pixel __ATTRS_o_ai vec_splat(vector pixel __a, unsigned const int __b) { unsigned char b0 = (__b & 0x07) * 2; unsigned char b1 = b0 + 1; return vec_perm(__a, __a, (vector unsigned char)(b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1)); } static __inline__ vector signed int __ATTRS_o_ai vec_splat(vector signed int __a, unsigned const int __b) { unsigned char b0 = (__b & 0x03) * 4; unsigned char b1 = b0 + 1, b2 = b0 + 2, b3 = b0 + 3; return vec_perm(__a, __a, (vector unsigned char)(b0, b1, b2, b3, b0, b1, b2, b3, b0, b1, b2, b3, b0, b1, b2, b3)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_splat(vector unsigned int __a, unsigned const int __b) { unsigned char b0 = (__b & 0x03) * 4; unsigned char b1 = b0 + 1, b2 = b0 + 2, b3 = b0 + 3; return vec_perm(__a, __a, (vector unsigned char)(b0, b1, b2, b3, b0, b1, b2, b3, b0, b1, b2, b3, b0, b1, b2, b3)); } static __inline__ vector bool int __ATTRS_o_ai vec_splat(vector bool int __a, unsigned const int __b) { unsigned char b0 = (__b & 0x03) * 4; unsigned char b1 = b0 + 1, b2 = b0 + 2, b3 = b0 + 3; return vec_perm(__a, __a, (vector unsigned char)(b0, b1, b2, b3, b0, b1, b2, b3, b0, b1, b2, b3, b0, b1, b2, b3)); } static __inline__ vector float __ATTRS_o_ai vec_splat(vector float __a, unsigned const int __b) { unsigned char b0 = (__b & 0x03) * 4; unsigned char b1 = b0 + 1, b2 = b0 + 2, b3 = b0 + 3; return vec_perm(__a, __a, (vector unsigned char)(b0, b1, b2, b3, b0, b1, b2, b3, b0, b1, b2, b3, b0, b1, b2, b3)); } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_splat(vector double __a, unsigned const int __b) { unsigned char b0 = (__b & 0x01) * 8; unsigned char b1 = b0 + 1, b2 = b0 + 2, b3 = b0 + 3, b4 = b0 + 4, b5 = b0 + 5, b6 = b0 + 6, b7 = b0 + 7; return vec_perm(__a, __a, (vector unsigned char)(b0, b1, b2, b3, b4, b5, b6, b7, b0, b1, b2, b3, b4, b5, b6, b7)); } static __inline__ vector bool long long __ATTRS_o_ai vec_splat(vector bool long long __a, unsigned const int __b) { unsigned char b0 = (__b & 0x01) * 8; unsigned char b1 = b0 + 1, b2 = b0 + 2, b3 = b0 + 3, b4 = b0 + 4, b5 = b0 + 5, b6 = b0 + 6, b7 = b0 + 7; return vec_perm(__a, __a, (vector unsigned char)(b0, b1, b2, b3, b4, b5, b6, b7, b0, b1, b2, b3, b4, b5, b6, b7)); } static __inline__ vector signed long long __ATTRS_o_ai vec_splat(vector signed long long __a, unsigned const int __b) { unsigned char b0 = (__b & 0x01) * 8; unsigned char b1 = b0 + 1, b2 = b0 + 2, b3 = b0 + 3, b4 = b0 + 4, b5 = b0 + 5, b6 = b0 + 6, b7 = b0 + 7; return vec_perm(__a, __a, (vector unsigned char)(b0, b1, b2, b3, b4, b5, b6, b7, b0, b1, b2, b3, b4, b5, b6, b7)); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_splat(vector unsigned long long __a, unsigned const int __b) { unsigned char b0 = (__b & 0x01) * 8; unsigned char b1 = b0 + 1, b2 = b0 + 2, b3 = b0 + 3, b4 = b0 + 4, b5 = b0 + 5, b6 = b0 + 6, b7 = b0 + 7; return vec_perm(__a, __a, (vector unsigned char)(b0, b1, b2, b3, b4, b5, b6, b7, b0, b1, b2, b3, b4, b5, b6, b7)); } #endif /* vec_vspltb */ #define __builtin_altivec_vspltb vec_vspltb static __inline__ vector signed char __ATTRS_o_ai vec_vspltb(vector signed char __a, unsigned char __b) { return vec_perm(__a, __a, (vector unsigned char)(__b)); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vspltb(vector unsigned char __a, unsigned char __b) { return vec_perm(__a, __a, (vector unsigned char)(__b)); } static __inline__ vector bool char __ATTRS_o_ai vec_vspltb(vector bool char __a, unsigned char __b) { return vec_perm(__a, __a, (vector unsigned char)(__b)); } /* vec_vsplth */ #define __builtin_altivec_vsplth vec_vsplth static __inline__ vector short __ATTRS_o_ai vec_vsplth(vector short __a, unsigned char __b) { __b *= 2; unsigned char b1 = __b + 1; return vec_perm(__a, __a, (vector unsigned char)(__b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1)); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsplth(vector unsigned short __a, unsigned char __b) { __b *= 2; unsigned char b1 = __b + 1; return vec_perm(__a, __a, (vector unsigned char)(__b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1)); } static __inline__ vector bool short __ATTRS_o_ai vec_vsplth(vector bool short __a, unsigned char __b) { __b *= 2; unsigned char b1 = __b + 1; return vec_perm(__a, __a, (vector unsigned char)(__b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1)); } static __inline__ vector pixel __ATTRS_o_ai vec_vsplth(vector pixel __a, unsigned char __b) { __b *= 2; unsigned char b1 = __b + 1; return vec_perm(__a, __a, (vector unsigned char)(__b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1, __b, b1)); } /* vec_vspltw */ #define __builtin_altivec_vspltw vec_vspltw static __inline__ vector int __ATTRS_o_ai vec_vspltw(vector int __a, unsigned char __b) { __b *= 4; unsigned char b1 = __b + 1, b2 = __b + 2, b3 = __b + 3; return vec_perm(__a, __a, (vector unsigned char)(__b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vspltw(vector unsigned int __a, unsigned char __b) { __b *= 4; unsigned char b1 = __b + 1, b2 = __b + 2, b3 = __b + 3; return vec_perm(__a, __a, (vector unsigned char)(__b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3)); } static __inline__ vector bool int __ATTRS_o_ai vec_vspltw(vector bool int __a, unsigned char __b) { __b *= 4; unsigned char b1 = __b + 1, b2 = __b + 2, b3 = __b + 3; return vec_perm(__a, __a, (vector unsigned char)(__b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3)); } static __inline__ vector float __ATTRS_o_ai vec_vspltw(vector float __a, unsigned char __b) { __b *= 4; unsigned char b1 = __b + 1, b2 = __b + 2, b3 = __b + 3; return vec_perm(__a, __a, (vector unsigned char)(__b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3, __b, b1, b2, b3)); } /* vec_splat_s8 */ #define __builtin_altivec_vspltisb vec_splat_s8 // FIXME: parameter should be treated as 5-bit signed literal static __inline__ vector signed char __ATTRS_o_ai vec_splat_s8(signed char __a) { return (vector signed char)(__a); } /* vec_vspltisb */ // FIXME: parameter should be treated as 5-bit signed literal static __inline__ vector signed char __ATTRS_o_ai vec_vspltisb(signed char __a) { return (vector signed char)(__a); } /* vec_splat_s16 */ #define __builtin_altivec_vspltish vec_splat_s16 // FIXME: parameter should be treated as 5-bit signed literal static __inline__ vector short __ATTRS_o_ai vec_splat_s16(signed char __a) { return (vector short)(__a); } /* vec_vspltish */ // FIXME: parameter should be treated as 5-bit signed literal static __inline__ vector short __ATTRS_o_ai vec_vspltish(signed char __a) { return (vector short)(__a); } /* vec_splat_s32 */ #define __builtin_altivec_vspltisw vec_splat_s32 // FIXME: parameter should be treated as 5-bit signed literal static __inline__ vector int __ATTRS_o_ai vec_splat_s32(signed char __a) { return (vector int)(__a); } /* vec_vspltisw */ // FIXME: parameter should be treated as 5-bit signed literal static __inline__ vector int __ATTRS_o_ai vec_vspltisw(signed char __a) { return (vector int)(__a); } /* vec_splat_u8 */ // FIXME: parameter should be treated as 5-bit signed literal static __inline__ vector unsigned char __ATTRS_o_ai vec_splat_u8(unsigned char __a) { return (vector unsigned char)(__a); } /* vec_splat_u16 */ // FIXME: parameter should be treated as 5-bit signed literal static __inline__ vector unsigned short __ATTRS_o_ai vec_splat_u16(signed char __a) { return (vector unsigned short)(__a); } /* vec_splat_u32 */ // FIXME: parameter should be treated as 5-bit signed literal static __inline__ vector unsigned int __ATTRS_o_ai vec_splat_u32(signed char __a) { return (vector unsigned int)(__a); } /* vec_sr */ static __inline__ vector signed char __ATTRS_o_ai vec_sr(vector signed char __a, vector unsigned char __b) { vector unsigned char __res = (vector unsigned char)__a >> __b; return (vector signed char)__res; } static __inline__ vector unsigned char __ATTRS_o_ai vec_sr(vector unsigned char __a, vector unsigned char __b) { return __a >> __b; } static __inline__ vector signed short __ATTRS_o_ai vec_sr(vector signed short __a, vector unsigned short __b) { vector unsigned short __res = (vector unsigned short)__a >> __b; return (vector signed short)__res; } static __inline__ vector unsigned short __ATTRS_o_ai vec_sr(vector unsigned short __a, vector unsigned short __b) { return __a >> __b; } static __inline__ vector signed int __ATTRS_o_ai vec_sr(vector signed int __a, vector unsigned int __b) { vector unsigned int __res = (vector unsigned int)__a >> __b; return (vector signed int)__res; } static __inline__ vector unsigned int __ATTRS_o_ai vec_sr(vector unsigned int __a, vector unsigned int __b) { return __a >> __b; } #ifdef __POWER8_VECTOR__ static __inline__ vector signed long long __ATTRS_o_ai vec_sr(vector signed long long __a, vector unsigned long long __b) { vector unsigned long long __res = (vector unsigned long long)__a >> __b; return (vector signed long long)__res; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_sr(vector unsigned long long __a, vector unsigned long long __b) { return __a >> __b; } #endif /* vec_vsrb */ #define __builtin_altivec_vsrb vec_vsrb static __inline__ vector signed char __ATTRS_o_ai vec_vsrb(vector signed char __a, vector unsigned char __b) { return __a >> (vector signed char)__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsrb(vector unsigned char __a, vector unsigned char __b) { return __a >> __b; } /* vec_vsrh */ #define __builtin_altivec_vsrh vec_vsrh static __inline__ vector short __ATTRS_o_ai vec_vsrh(vector short __a, vector unsigned short __b) { return __a >> (vector short)__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsrh(vector unsigned short __a, vector unsigned short __b) { return __a >> __b; } /* vec_vsrw */ #define __builtin_altivec_vsrw vec_vsrw static __inline__ vector int __ATTRS_o_ai vec_vsrw(vector int __a, vector unsigned int __b) { return __a >> (vector int)__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsrw(vector unsigned int __a, vector unsigned int __b) { return __a >> __b; } /* vec_sra */ static __inline__ vector signed char __ATTRS_o_ai vec_sra(vector signed char __a, vector unsigned char __b) { return (vector signed char)__builtin_altivec_vsrab((vector char)__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_sra(vector unsigned char __a, vector unsigned char __b) { return (vector unsigned char)__builtin_altivec_vsrab((vector char)__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_sra(vector short __a, vector unsigned short __b) { return __builtin_altivec_vsrah(__a, (vector unsigned short)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_sra(vector unsigned short __a, vector unsigned short __b) { return (vector unsigned short)__builtin_altivec_vsrah((vector short)__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_sra(vector int __a, vector unsigned int __b) { return __builtin_altivec_vsraw(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_sra(vector unsigned int __a, vector unsigned int __b) { return (vector unsigned int)__builtin_altivec_vsraw((vector int)__a, __b); } #ifdef __POWER8_VECTOR__ static __inline__ vector signed long long __ATTRS_o_ai vec_sra(vector signed long long __a, vector unsigned long long __b) { return __a >> __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_sra(vector unsigned long long __a, vector unsigned long long __b) { return (vector unsigned long long)((vector signed long long)__a >> __b); } #endif /* vec_vsrab */ static __inline__ vector signed char __ATTRS_o_ai vec_vsrab(vector signed char __a, vector unsigned char __b) { return (vector signed char)__builtin_altivec_vsrab((vector char)__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsrab(vector unsigned char __a, vector unsigned char __b) { return (vector unsigned char)__builtin_altivec_vsrab((vector char)__a, __b); } /* vec_vsrah */ static __inline__ vector short __ATTRS_o_ai vec_vsrah(vector short __a, vector unsigned short __b) { return __builtin_altivec_vsrah(__a, (vector unsigned short)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsrah(vector unsigned short __a, vector unsigned short __b) { return (vector unsigned short)__builtin_altivec_vsrah((vector short)__a, __b); } /* vec_vsraw */ static __inline__ vector int __ATTRS_o_ai vec_vsraw(vector int __a, vector unsigned int __b) { return __builtin_altivec_vsraw(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsraw(vector unsigned int __a, vector unsigned int __b) { return (vector unsigned int)__builtin_altivec_vsraw((vector int)__a, __b); } /* vec_srl */ static __inline__ vector signed char __ATTRS_o_ai vec_srl(vector signed char __a, vector unsigned char __b) { return (vector signed char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector signed char __ATTRS_o_ai vec_srl(vector signed char __a, vector unsigned short __b) { return (vector signed char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector signed char __ATTRS_o_ai vec_srl(vector signed char __a, vector unsigned int __b) { return (vector signed char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_srl(vector unsigned char __a, vector unsigned char __b) { return (vector unsigned char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_srl(vector unsigned char __a, vector unsigned short __b) { return (vector unsigned char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_srl(vector unsigned char __a, vector unsigned int __b) { return (vector unsigned char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_srl(vector bool char __a, vector unsigned char __b) { return (vector bool char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_srl(vector bool char __a, vector unsigned short __b) { return (vector bool char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_srl(vector bool char __a, vector unsigned int __b) { return (vector bool char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_srl(vector short __a, vector unsigned char __b) { return (vector short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_srl(vector short __a, vector unsigned short __b) { return (vector short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_srl(vector short __a, vector unsigned int __b) { return (vector short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_srl(vector unsigned short __a, vector unsigned char __b) { return (vector unsigned short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_srl(vector unsigned short __a, vector unsigned short __b) { return (vector unsigned short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_srl(vector unsigned short __a, vector unsigned int __b) { return (vector unsigned short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_srl(vector bool short __a, vector unsigned char __b) { return (vector bool short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_srl(vector bool short __a, vector unsigned short __b) { return (vector bool short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_srl(vector bool short __a, vector unsigned int __b) { return (vector bool short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_srl(vector pixel __a, vector unsigned char __b) { return (vector pixel)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_srl(vector pixel __a, vector unsigned short __b) { return (vector pixel)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_srl(vector pixel __a, vector unsigned int __b) { return (vector pixel)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_srl(vector int __a, vector unsigned char __b) { return (vector int)__builtin_altivec_vsr(__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_srl(vector int __a, vector unsigned short __b) { return (vector int)__builtin_altivec_vsr(__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_srl(vector int __a, vector unsigned int __b) { return (vector int)__builtin_altivec_vsr(__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_srl(vector unsigned int __a, vector unsigned char __b) { return (vector unsigned int)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_srl(vector unsigned int __a, vector unsigned short __b) { return (vector unsigned int)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_srl(vector unsigned int __a, vector unsigned int __b) { return (vector unsigned int)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_srl(vector bool int __a, vector unsigned char __b) { return (vector bool int)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_srl(vector bool int __a, vector unsigned short __b) { return (vector bool int)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_srl(vector bool int __a, vector unsigned int __b) { return (vector bool int)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_srl(vector signed long long __a, vector unsigned char __b) { return (vector signed long long)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_srl(vector unsigned long long __a, vector unsigned char __b) { return (vector unsigned long long)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } #endif /* vec_vsr */ static __inline__ vector signed char __ATTRS_o_ai vec_vsr(vector signed char __a, vector unsigned char __b) { return (vector signed char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector signed char __ATTRS_o_ai vec_vsr(vector signed char __a, vector unsigned short __b) { return (vector signed char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector signed char __ATTRS_o_ai vec_vsr(vector signed char __a, vector unsigned int __b) { return (vector signed char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsr(vector unsigned char __a, vector unsigned char __b) { return (vector unsigned char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsr(vector unsigned char __a, vector unsigned short __b) { return (vector unsigned char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsr(vector unsigned char __a, vector unsigned int __b) { return (vector unsigned char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_vsr(vector bool char __a, vector unsigned char __b) { return (vector bool char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_vsr(vector bool char __a, vector unsigned short __b) { return (vector bool char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool char __ATTRS_o_ai vec_vsr(vector bool char __a, vector unsigned int __b) { return (vector bool char)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_vsr(vector short __a, vector unsigned char __b) { return (vector short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_vsr(vector short __a, vector unsigned short __b) { return (vector short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_vsr(vector short __a, vector unsigned int __b) { return (vector short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsr(vector unsigned short __a, vector unsigned char __b) { return (vector unsigned short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsr(vector unsigned short __a, vector unsigned short __b) { return (vector unsigned short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsr(vector unsigned short __a, vector unsigned int __b) { return (vector unsigned short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_vsr(vector bool short __a, vector unsigned char __b) { return (vector bool short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_vsr(vector bool short __a, vector unsigned short __b) { return (vector bool short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool short __ATTRS_o_ai vec_vsr(vector bool short __a, vector unsigned int __b) { return (vector bool short)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_vsr(vector pixel __a, vector unsigned char __b) { return (vector pixel)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_vsr(vector pixel __a, vector unsigned short __b) { return (vector pixel)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_vsr(vector pixel __a, vector unsigned int __b) { return (vector pixel)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_vsr(vector int __a, vector unsigned char __b) { return (vector int)__builtin_altivec_vsr(__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_vsr(vector int __a, vector unsigned short __b) { return (vector int)__builtin_altivec_vsr(__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_vsr(vector int __a, vector unsigned int __b) { return (vector int)__builtin_altivec_vsr(__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsr(vector unsigned int __a, vector unsigned char __b) { return (vector unsigned int)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsr(vector unsigned int __a, vector unsigned short __b) { return (vector unsigned int)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsr(vector unsigned int __a, vector unsigned int __b) { return (vector unsigned int)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_vsr(vector bool int __a, vector unsigned char __b) { return (vector bool int)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_vsr(vector bool int __a, vector unsigned short __b) { return (vector bool int)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } static __inline__ vector bool int __ATTRS_o_ai vec_vsr(vector bool int __a, vector unsigned int __b) { return (vector bool int)__builtin_altivec_vsr((vector int)__a, (vector int)__b); } /* vec_sro */ static __inline__ vector signed char __ATTRS_o_ai vec_sro(vector signed char __a, vector signed char __b) { return (vector signed char)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector signed char __ATTRS_o_ai vec_sro(vector signed char __a, vector unsigned char __b) { return (vector signed char)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_sro(vector unsigned char __a, vector signed char __b) { return (vector unsigned char)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_sro(vector unsigned char __a, vector unsigned char __b) { return (vector unsigned char)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_sro(vector short __a, vector signed char __b) { return (vector short)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_sro(vector short __a, vector unsigned char __b) { return (vector short)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_sro(vector unsigned short __a, vector signed char __b) { return (vector unsigned short)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_sro(vector unsigned short __a, vector unsigned char __b) { return (vector unsigned short)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_sro(vector pixel __a, vector signed char __b) { return (vector pixel)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_sro(vector pixel __a, vector unsigned char __b) { return (vector pixel)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_sro(vector int __a, vector signed char __b) { return (vector int)__builtin_altivec_vsro(__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_sro(vector int __a, vector unsigned char __b) { return (vector int)__builtin_altivec_vsro(__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_sro(vector unsigned int __a, vector signed char __b) { return (vector unsigned int)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_sro(vector unsigned int __a, vector unsigned char __b) { return (vector unsigned int)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector float __ATTRS_o_ai vec_sro(vector float __a, vector signed char __b) { return (vector float)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector float __ATTRS_o_ai vec_sro(vector float __a, vector unsigned char __b) { return (vector float)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_sro(vector signed long long __a, vector signed char __b) { return (vector signed long long)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector signed long long __ATTRS_o_ai vec_sro(vector signed long long __a, vector unsigned char __b) { return (vector signed long long)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_sro(vector unsigned long long __a, vector signed char __b) { return (vector unsigned long long)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_sro(vector unsigned long long __a, vector unsigned char __b) { return (vector unsigned long long)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } #endif /* vec_vsro */ static __inline__ vector signed char __ATTRS_o_ai vec_vsro(vector signed char __a, vector signed char __b) { return (vector signed char)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector signed char __ATTRS_o_ai vec_vsro(vector signed char __a, vector unsigned char __b) { return (vector signed char)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsro(vector unsigned char __a, vector signed char __b) { return (vector unsigned char)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsro(vector unsigned char __a, vector unsigned char __b) { return (vector unsigned char)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_vsro(vector short __a, vector signed char __b) { return (vector short)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector short __ATTRS_o_ai vec_vsro(vector short __a, vector unsigned char __b) { return (vector short)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsro(vector unsigned short __a, vector signed char __b) { return (vector unsigned short)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsro(vector unsigned short __a, vector unsigned char __b) { return (vector unsigned short)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_vsro(vector pixel __a, vector signed char __b) { return (vector pixel)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector pixel __ATTRS_o_ai vec_vsro(vector pixel __a, vector unsigned char __b) { return (vector pixel)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_vsro(vector int __a, vector signed char __b) { return (vector int)__builtin_altivec_vsro(__a, (vector int)__b); } static __inline__ vector int __ATTRS_o_ai vec_vsro(vector int __a, vector unsigned char __b) { return (vector int)__builtin_altivec_vsro(__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsro(vector unsigned int __a, vector signed char __b) { return (vector unsigned int)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsro(vector unsigned int __a, vector unsigned char __b) { return (vector unsigned int)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector float __ATTRS_o_ai vec_vsro(vector float __a, vector signed char __b) { return (vector float)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } static __inline__ vector float __ATTRS_o_ai vec_vsro(vector float __a, vector unsigned char __b) { return (vector float)__builtin_altivec_vsro((vector int)__a, (vector int)__b); } /* vec_st */ static __inline__ void __ATTRS_o_ai vec_st(vector signed char __a, int __b, vector signed char *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector signed char __a, int __b, signed char *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector unsigned char __a, int __b, vector unsigned char *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector unsigned char __a, int __b, unsigned char *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector bool char __a, int __b, signed char *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector bool char __a, int __b, unsigned char *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector bool char __a, int __b, vector bool char *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector short __a, int __b, vector short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector short __a, int __b, short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector unsigned short __a, int __b, vector unsigned short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector unsigned short __a, int __b, unsigned short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector bool short __a, int __b, short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector bool short __a, int __b, unsigned short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector bool short __a, int __b, vector bool short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector pixel __a, int __b, short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector pixel __a, int __b, unsigned short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector pixel __a, int __b, vector pixel *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector int __a, int __b, vector int *__c) { __builtin_altivec_stvx(__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector int __a, int __b, int *__c) { __builtin_altivec_stvx(__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector unsigned int __a, int __b, vector unsigned int *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector unsigned int __a, int __b, unsigned int *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector bool int __a, int __b, int *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector bool int __a, int __b, unsigned int *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector bool int __a, int __b, vector bool int *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector float __a, int __b, vector float *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_st(vector float __a, int __b, float *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } /* vec_stvx */ static __inline__ void __ATTRS_o_ai vec_stvx(vector signed char __a, int __b, vector signed char *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector signed char __a, int __b, signed char *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned char __a, int __b, vector unsigned char *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned char __a, int __b, unsigned char *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector bool char __a, int __b, signed char *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector bool char __a, int __b, unsigned char *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector bool char __a, int __b, vector bool char *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector short __a, int __b, vector short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector short __a, int __b, short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned short __a, int __b, vector unsigned short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned short __a, int __b, unsigned short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector bool short __a, int __b, short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector bool short __a, int __b, unsigned short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector bool short __a, int __b, vector bool short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector pixel __a, int __b, short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector pixel __a, int __b, unsigned short *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector pixel __a, int __b, vector pixel *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector int __a, int __b, vector int *__c) { __builtin_altivec_stvx(__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector int __a, int __b, int *__c) { __builtin_altivec_stvx(__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned int __a, int __b, vector unsigned int *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned int __a, int __b, unsigned int *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector bool int __a, int __b, int *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector bool int __a, int __b, unsigned int *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector bool int __a, int __b, vector bool int *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector float __a, int __b, vector float *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvx(vector float __a, int __b, float *__c) { __builtin_altivec_stvx((vector int)__a, __b, __c); } /* vec_ste */ static __inline__ void __ATTRS_o_ai vec_ste(vector signed char __a, int __b, signed char *__c) { __builtin_altivec_stvebx((vector char)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_ste(vector unsigned char __a, int __b, unsigned char *__c) { __builtin_altivec_stvebx((vector char)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_ste(vector bool char __a, int __b, signed char *__c) { __builtin_altivec_stvebx((vector char)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_ste(vector bool char __a, int __b, unsigned char *__c) { __builtin_altivec_stvebx((vector char)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_ste(vector short __a, int __b, short *__c) { __builtin_altivec_stvehx(__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_ste(vector unsigned short __a, int __b, unsigned short *__c) { __builtin_altivec_stvehx((vector short)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_ste(vector bool short __a, int __b, short *__c) { __builtin_altivec_stvehx((vector short)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_ste(vector bool short __a, int __b, unsigned short *__c) { __builtin_altivec_stvehx((vector short)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_ste(vector pixel __a, int __b, short *__c) { __builtin_altivec_stvehx((vector short)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_ste(vector pixel __a, int __b, unsigned short *__c) { __builtin_altivec_stvehx((vector short)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_ste(vector int __a, int __b, int *__c) { __builtin_altivec_stvewx(__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_ste(vector unsigned int __a, int __b, unsigned int *__c) { __builtin_altivec_stvewx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_ste(vector bool int __a, int __b, int *__c) { __builtin_altivec_stvewx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_ste(vector bool int __a, int __b, unsigned int *__c) { __builtin_altivec_stvewx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_ste(vector float __a, int __b, float *__c) { __builtin_altivec_stvewx((vector int)__a, __b, __c); } /* vec_stvebx */ static __inline__ void __ATTRS_o_ai vec_stvebx(vector signed char __a, int __b, signed char *__c) { __builtin_altivec_stvebx((vector char)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvebx(vector unsigned char __a, int __b, unsigned char *__c) { __builtin_altivec_stvebx((vector char)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvebx(vector bool char __a, int __b, signed char *__c) { __builtin_altivec_stvebx((vector char)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvebx(vector bool char __a, int __b, unsigned char *__c) { __builtin_altivec_stvebx((vector char)__a, __b, __c); } /* vec_stvehx */ static __inline__ void __ATTRS_o_ai vec_stvehx(vector short __a, int __b, short *__c) { __builtin_altivec_stvehx(__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvehx(vector unsigned short __a, int __b, unsigned short *__c) { __builtin_altivec_stvehx((vector short)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvehx(vector bool short __a, int __b, short *__c) { __builtin_altivec_stvehx((vector short)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvehx(vector bool short __a, int __b, unsigned short *__c) { __builtin_altivec_stvehx((vector short)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvehx(vector pixel __a, int __b, short *__c) { __builtin_altivec_stvehx((vector short)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvehx(vector pixel __a, int __b, unsigned short *__c) { __builtin_altivec_stvehx((vector short)__a, __b, __c); } /* vec_stvewx */ static __inline__ void __ATTRS_o_ai vec_stvewx(vector int __a, int __b, int *__c) { __builtin_altivec_stvewx(__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvewx(vector unsigned int __a, int __b, unsigned int *__c) { __builtin_altivec_stvewx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvewx(vector bool int __a, int __b, int *__c) { __builtin_altivec_stvewx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvewx(vector bool int __a, int __b, unsigned int *__c) { __builtin_altivec_stvewx((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvewx(vector float __a, int __b, float *__c) { __builtin_altivec_stvewx((vector int)__a, __b, __c); } /* vec_stl */ static __inline__ void __ATTRS_o_ai vec_stl(vector signed char __a, int __b, vector signed char *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector signed char __a, int __b, signed char *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector unsigned char __a, int __b, vector unsigned char *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector unsigned char __a, int __b, unsigned char *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector bool char __a, int __b, signed char *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector bool char __a, int __b, unsigned char *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector bool char __a, int __b, vector bool char *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector short __a, int __b, vector short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector short __a, int __b, short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector unsigned short __a, int __b, vector unsigned short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector unsigned short __a, int __b, unsigned short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector bool short __a, int __b, short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector bool short __a, int __b, unsigned short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector bool short __a, int __b, vector bool short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector pixel __a, int __b, short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector pixel __a, int __b, unsigned short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector pixel __a, int __b, vector pixel *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector int __a, int __b, vector int *__c) { __builtin_altivec_stvxl(__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector int __a, int __b, int *__c) { __builtin_altivec_stvxl(__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector unsigned int __a, int __b, vector unsigned int *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector unsigned int __a, int __b, unsigned int *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector bool int __a, int __b, int *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector bool int __a, int __b, unsigned int *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector bool int __a, int __b, vector bool int *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector float __a, int __b, vector float *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stl(vector float __a, int __b, float *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } /* vec_stvxl */ static __inline__ void __ATTRS_o_ai vec_stvxl(vector signed char __a, int __b, vector signed char *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector signed char __a, int __b, signed char *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector unsigned char __a, int __b, vector unsigned char *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector unsigned char __a, int __b, unsigned char *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector bool char __a, int __b, signed char *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector bool char __a, int __b, unsigned char *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector bool char __a, int __b, vector bool char *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector short __a, int __b, vector short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector short __a, int __b, short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector unsigned short __a, int __b, vector unsigned short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector unsigned short __a, int __b, unsigned short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector bool short __a, int __b, short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector bool short __a, int __b, unsigned short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector bool short __a, int __b, vector bool short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector pixel __a, int __b, short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector pixel __a, int __b, unsigned short *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector pixel __a, int __b, vector pixel *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector int __a, int __b, vector int *__c) { __builtin_altivec_stvxl(__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector int __a, int __b, int *__c) { __builtin_altivec_stvxl(__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector unsigned int __a, int __b, vector unsigned int *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector unsigned int __a, int __b, unsigned int *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector bool int __a, int __b, int *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector bool int __a, int __b, unsigned int *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector bool int __a, int __b, vector bool int *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector float __a, int __b, vector float *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvxl(vector float __a, int __b, float *__c) { __builtin_altivec_stvxl((vector int)__a, __b, __c); } /* vec_sub */ static __inline__ vector signed char __ATTRS_o_ai vec_sub(vector signed char __a, vector signed char __b) { return __a - __b; } static __inline__ vector signed char __ATTRS_o_ai vec_sub(vector bool char __a, vector signed char __b) { return (vector signed char)__a - __b; } static __inline__ vector signed char __ATTRS_o_ai vec_sub(vector signed char __a, vector bool char __b) { return __a - (vector signed char)__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_sub(vector unsigned char __a, vector unsigned char __b) { return __a - __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_sub(vector bool char __a, vector unsigned char __b) { return (vector unsigned char)__a - __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_sub(vector unsigned char __a, vector bool char __b) { return __a - (vector unsigned char)__b; } static __inline__ vector short __ATTRS_o_ai vec_sub(vector short __a, vector short __b) { return __a - __b; } static __inline__ vector short __ATTRS_o_ai vec_sub(vector bool short __a, vector short __b) { return (vector short)__a - __b; } static __inline__ vector short __ATTRS_o_ai vec_sub(vector short __a, vector bool short __b) { return __a - (vector short)__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_sub(vector unsigned short __a, vector unsigned short __b) { return __a - __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_sub(vector bool short __a, vector unsigned short __b) { return (vector unsigned short)__a - __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_sub(vector unsigned short __a, vector bool short __b) { return __a - (vector unsigned short)__b; } static __inline__ vector int __ATTRS_o_ai vec_sub(vector int __a, vector int __b) { return __a - __b; } static __inline__ vector int __ATTRS_o_ai vec_sub(vector bool int __a, vector int __b) { return (vector int)__a - __b; } static __inline__ vector int __ATTRS_o_ai vec_sub(vector int __a, vector bool int __b) { return __a - (vector int)__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_sub(vector unsigned int __a, vector unsigned int __b) { return __a - __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_sub(vector bool int __a, vector unsigned int __b) { return (vector unsigned int)__a - __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_sub(vector unsigned int __a, vector bool int __b) { return __a - (vector unsigned int)__b; } #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) static __inline__ vector signed __int128 __ATTRS_o_ai vec_sub(vector signed __int128 __a, vector signed __int128 __b) { return __a - __b; } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_sub(vector unsigned __int128 __a, vector unsigned __int128 __b) { return __a - __b; } #endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__) #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_sub(vector signed long long __a, vector signed long long __b) { return __a - __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_sub(vector unsigned long long __a, vector unsigned long long __b) { return __a - __b; } static __inline__ vector double __ATTRS_o_ai vec_sub(vector double __a, vector double __b) { return __a - __b; } #endif static __inline__ vector float __ATTRS_o_ai vec_sub(vector float __a, vector float __b) { return __a - __b; } /* vec_vsububm */ #define __builtin_altivec_vsububm vec_vsububm static __inline__ vector signed char __ATTRS_o_ai vec_vsububm(vector signed char __a, vector signed char __b) { return __a - __b; } static __inline__ vector signed char __ATTRS_o_ai vec_vsububm(vector bool char __a, vector signed char __b) { return (vector signed char)__a - __b; } static __inline__ vector signed char __ATTRS_o_ai vec_vsububm(vector signed char __a, vector bool char __b) { return __a - (vector signed char)__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsububm(vector unsigned char __a, vector unsigned char __b) { return __a - __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsububm(vector bool char __a, vector unsigned char __b) { return (vector unsigned char)__a - __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsububm(vector unsigned char __a, vector bool char __b) { return __a - (vector unsigned char)__b; } /* vec_vsubuhm */ #define __builtin_altivec_vsubuhm vec_vsubuhm static __inline__ vector short __ATTRS_o_ai vec_vsubuhm(vector short __a, vector short __b) { return __a - __b; } static __inline__ vector short __ATTRS_o_ai vec_vsubuhm(vector bool short __a, vector short __b) { return (vector short)__a - __b; } static __inline__ vector short __ATTRS_o_ai vec_vsubuhm(vector short __a, vector bool short __b) { return __a - (vector short)__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsubuhm(vector unsigned short __a, vector unsigned short __b) { return __a - __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsubuhm(vector bool short __a, vector unsigned short __b) { return (vector unsigned short)__a - __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsubuhm(vector unsigned short __a, vector bool short __b) { return __a - (vector unsigned short)__b; } /* vec_vsubuwm */ #define __builtin_altivec_vsubuwm vec_vsubuwm static __inline__ vector int __ATTRS_o_ai vec_vsubuwm(vector int __a, vector int __b) { return __a - __b; } static __inline__ vector int __ATTRS_o_ai vec_vsubuwm(vector bool int __a, vector int __b) { return (vector int)__a - __b; } static __inline__ vector int __ATTRS_o_ai vec_vsubuwm(vector int __a, vector bool int __b) { return __a - (vector int)__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsubuwm(vector unsigned int __a, vector unsigned int __b) { return __a - __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsubuwm(vector bool int __a, vector unsigned int __b) { return (vector unsigned int)__a - __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsubuwm(vector unsigned int __a, vector bool int __b) { return __a - (vector unsigned int)__b; } /* vec_vsubfp */ #define __builtin_altivec_vsubfp vec_vsubfp static __inline__ vector float __attribute__((__always_inline__)) vec_vsubfp(vector float __a, vector float __b) { return __a - __b; } /* vec_subc */ static __inline__ vector signed int __ATTRS_o_ai vec_subc(vector signed int __a, vector signed int __b) { return (vector signed int)__builtin_altivec_vsubcuw((vector unsigned int)__a, (vector unsigned int) __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_subc(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vsubcuw(__a, __b); } #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_subc(vector unsigned __int128 __a, vector unsigned __int128 __b) { return __builtin_altivec_vsubcuq(__a, __b); } static __inline__ vector signed __int128 __ATTRS_o_ai vec_subc(vector signed __int128 __a, vector signed __int128 __b) { return __builtin_altivec_vsubcuq(__a, __b); } #endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__) /* vec_vsubcuw */ static __inline__ vector unsigned int __attribute__((__always_inline__)) vec_vsubcuw(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vsubcuw(__a, __b); } /* vec_subs */ static __inline__ vector signed char __ATTRS_o_ai vec_subs(vector signed char __a, vector signed char __b) { return __builtin_altivec_vsubsbs(__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_subs(vector bool char __a, vector signed char __b) { return __builtin_altivec_vsubsbs((vector signed char)__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_subs(vector signed char __a, vector bool char __b) { return __builtin_altivec_vsubsbs(__a, (vector signed char)__b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_subs(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vsububs(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_subs(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vsububs((vector unsigned char)__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_subs(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vsububs(__a, (vector unsigned char)__b); } static __inline__ vector short __ATTRS_o_ai vec_subs(vector short __a, vector short __b) { return __builtin_altivec_vsubshs(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_subs(vector bool short __a, vector short __b) { return __builtin_altivec_vsubshs((vector short)__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_subs(vector short __a, vector bool short __b) { return __builtin_altivec_vsubshs(__a, (vector short)__b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_subs(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vsubuhs(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_subs(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vsubuhs((vector unsigned short)__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_subs(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vsubuhs(__a, (vector unsigned short)__b); } static __inline__ vector int __ATTRS_o_ai vec_subs(vector int __a, vector int __b) { return __builtin_altivec_vsubsws(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_subs(vector bool int __a, vector int __b) { return __builtin_altivec_vsubsws((vector int)__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_subs(vector int __a, vector bool int __b) { return __builtin_altivec_vsubsws(__a, (vector int)__b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_subs(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vsubuws(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_subs(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vsubuws((vector unsigned int)__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_subs(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vsubuws(__a, (vector unsigned int)__b); } /* vec_vsubsbs */ static __inline__ vector signed char __ATTRS_o_ai vec_vsubsbs(vector signed char __a, vector signed char __b) { return __builtin_altivec_vsubsbs(__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_vsubsbs(vector bool char __a, vector signed char __b) { return __builtin_altivec_vsubsbs((vector signed char)__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_vsubsbs(vector signed char __a, vector bool char __b) { return __builtin_altivec_vsubsbs(__a, (vector signed char)__b); } /* vec_vsububs */ static __inline__ vector unsigned char __ATTRS_o_ai vec_vsububs(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vsububs(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsububs(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vsububs((vector unsigned char)__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsububs(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vsububs(__a, (vector unsigned char)__b); } /* vec_vsubshs */ static __inline__ vector short __ATTRS_o_ai vec_vsubshs(vector short __a, vector short __b) { return __builtin_altivec_vsubshs(__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_vsubshs(vector bool short __a, vector short __b) { return __builtin_altivec_vsubshs((vector short)__a, __b); } static __inline__ vector short __ATTRS_o_ai vec_vsubshs(vector short __a, vector bool short __b) { return __builtin_altivec_vsubshs(__a, (vector short)__b); } /* vec_vsubuhs */ static __inline__ vector unsigned short __ATTRS_o_ai vec_vsubuhs(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vsubuhs(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsubuhs(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vsubuhs((vector unsigned short)__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsubuhs(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vsubuhs(__a, (vector unsigned short)__b); } /* vec_vsubsws */ static __inline__ vector int __ATTRS_o_ai vec_vsubsws(vector int __a, vector int __b) { return __builtin_altivec_vsubsws(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_vsubsws(vector bool int __a, vector int __b) { return __builtin_altivec_vsubsws((vector int)__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_vsubsws(vector int __a, vector bool int __b) { return __builtin_altivec_vsubsws(__a, (vector int)__b); } /* vec_vsubuws */ static __inline__ vector unsigned int __ATTRS_o_ai vec_vsubuws(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vsubuws(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsubuws(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vsubuws((vector unsigned int)__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsubuws(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vsubuws(__a, (vector unsigned int)__b); } #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) /* vec_vsubuqm */ static __inline__ vector signed __int128 __ATTRS_o_ai vec_vsubuqm(vector signed __int128 __a, vector signed __int128 __b) { return __a - __b; } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_vsubuqm(vector unsigned __int128 __a, vector unsigned __int128 __b) { return __a - __b; } /* vec_vsubeuqm */ static __inline__ vector signed __int128 __ATTRS_o_ai vec_vsubeuqm(vector signed __int128 __a, vector signed __int128 __b, vector signed __int128 __c) { return __builtin_altivec_vsubeuqm(__a, __b, __c); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_vsubeuqm(vector unsigned __int128 __a, vector unsigned __int128 __b, vector unsigned __int128 __c) { return __builtin_altivec_vsubeuqm(__a, __b, __c); } static __inline__ vector signed __int128 __ATTRS_o_ai vec_sube(vector signed __int128 __a, vector signed __int128 __b, vector signed __int128 __c) { return __builtin_altivec_vsubeuqm(__a, __b, __c); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_sube(vector unsigned __int128 __a, vector unsigned __int128 __b, vector unsigned __int128 __c) { return __builtin_altivec_vsubeuqm(__a, __b, __c); } /* vec_vsubcuq */ static __inline__ vector signed __int128 __ATTRS_o_ai vec_vsubcuq(vector signed __int128 __a, vector signed __int128 __b) { return __builtin_altivec_vsubcuq(__a, __b); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_vsubcuq(vector unsigned __int128 __a, vector unsigned __int128 __b) { return __builtin_altivec_vsubcuq(__a, __b); } /* vec_vsubecuq */ static __inline__ vector signed __int128 __ATTRS_o_ai vec_vsubecuq(vector signed __int128 __a, vector signed __int128 __b, vector signed __int128 __c) { return __builtin_altivec_vsubecuq(__a, __b, __c); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_vsubecuq(vector unsigned __int128 __a, vector unsigned __int128 __b, vector unsigned __int128 __c) { return __builtin_altivec_vsubecuq(__a, __b, __c); } static __inline__ vector signed int __ATTRS_o_ai vec_subec(vector signed int __a, vector signed int __b, vector signed int __c) { return vec_addec(__a, ~__b, __c); } static __inline__ vector unsigned int __ATTRS_o_ai vec_subec(vector unsigned int __a, vector unsigned int __b, vector unsigned int __c) { return vec_addec(__a, ~__b, __c); } static __inline__ vector signed __int128 __ATTRS_o_ai vec_subec(vector signed __int128 __a, vector signed __int128 __b, vector signed __int128 __c) { return __builtin_altivec_vsubecuq(__a, __b, __c); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_subec(vector unsigned __int128 __a, vector unsigned __int128 __b, vector unsigned __int128 __c) { return __builtin_altivec_vsubecuq(__a, __b, __c); } #endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__) static __inline__ vector signed int __ATTRS_o_ai vec_sube(vector signed int __a, vector signed int __b, vector signed int __c) { vector signed int __mask = {1, 1, 1, 1}; vector signed int __carry = __c & __mask; return vec_adde(__a, ~__b, __carry); } static __inline__ vector unsigned int __ATTRS_o_ai vec_sube(vector unsigned int __a, vector unsigned int __b, vector unsigned int __c) { vector unsigned int __mask = {1, 1, 1, 1}; vector unsigned int __carry = __c & __mask; return vec_adde(__a, ~__b, __carry); } /* vec_sum4s */ static __inline__ vector int __ATTRS_o_ai vec_sum4s(vector signed char __a, vector int __b) { return __builtin_altivec_vsum4sbs(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_sum4s(vector unsigned char __a, vector unsigned int __b) { return __builtin_altivec_vsum4ubs(__a, __b); } static __inline__ vector int __ATTRS_o_ai vec_sum4s(vector signed short __a, vector int __b) { return __builtin_altivec_vsum4shs(__a, __b); } /* vec_vsum4sbs */ static __inline__ vector int __attribute__((__always_inline__)) vec_vsum4sbs(vector signed char __a, vector int __b) { return __builtin_altivec_vsum4sbs(__a, __b); } /* vec_vsum4ubs */ static __inline__ vector unsigned int __attribute__((__always_inline__)) vec_vsum4ubs(vector unsigned char __a, vector unsigned int __b) { return __builtin_altivec_vsum4ubs(__a, __b); } /* vec_vsum4shs */ static __inline__ vector int __attribute__((__always_inline__)) vec_vsum4shs(vector signed short __a, vector int __b) { return __builtin_altivec_vsum4shs(__a, __b); } /* vec_sum2s */ /* The vsum2sws instruction has a big-endian bias, so that the second input vector and the result always reference big-endian elements 1 and 3 (little-endian element 0 and 2). For ease of porting the programmer wants elements 1 and 3 in both cases, so for little endian we must perform some permutes. */ static __inline__ vector signed int __attribute__((__always_inline__)) vec_sum2s(vector int __a, vector int __b) { #ifdef __LITTLE_ENDIAN__ vector int __c = (vector signed int)vec_perm( __b, __b, (vector unsigned char)(4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11)); __c = __builtin_altivec_vsum2sws(__a, __c); return (vector signed int)vec_perm( __c, __c, (vector unsigned char)(4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11)); #else return __builtin_altivec_vsum2sws(__a, __b); #endif } /* vec_vsum2sws */ static __inline__ vector signed int __attribute__((__always_inline__)) vec_vsum2sws(vector int __a, vector int __b) { #ifdef __LITTLE_ENDIAN__ vector int __c = (vector signed int)vec_perm( __b, __b, (vector unsigned char)(4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11)); __c = __builtin_altivec_vsum2sws(__a, __c); return (vector signed int)vec_perm( __c, __c, (vector unsigned char)(4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11)); #else return __builtin_altivec_vsum2sws(__a, __b); #endif } /* vec_sums */ /* The vsumsws instruction has a big-endian bias, so that the second input vector and the result always reference big-endian element 3 (little-endian element 0). For ease of porting the programmer wants element 3 in both cases, so for little endian we must perform some permutes. */ static __inline__ vector signed int __attribute__((__always_inline__)) vec_sums(vector signed int __a, vector signed int __b) { #ifdef __LITTLE_ENDIAN__ __b = (vector signed int)vec_splat(__b, 3); __b = __builtin_altivec_vsumsws(__a, __b); return (vector signed int)(0, 0, 0, __b[0]); #else return __builtin_altivec_vsumsws(__a, __b); #endif } /* vec_vsumsws */ static __inline__ vector signed int __attribute__((__always_inline__)) vec_vsumsws(vector signed int __a, vector signed int __b) { #ifdef __LITTLE_ENDIAN__ __b = (vector signed int)vec_splat(__b, 3); __b = __builtin_altivec_vsumsws(__a, __b); return (vector signed int)(0, 0, 0, __b[0]); #else return __builtin_altivec_vsumsws(__a, __b); #endif } /* vec_trunc */ static __inline__ vector float __ATTRS_o_ai vec_trunc(vector float __a) { #ifdef __VSX__ return __builtin_vsx_xvrspiz(__a); #else return __builtin_altivec_vrfiz(__a); #endif } #ifdef __VSX__ static __inline__ vector double __ATTRS_o_ai vec_trunc(vector double __a) { return __builtin_vsx_xvrdpiz(__a); } #endif /* vec_vrfiz */ static __inline__ vector float __attribute__((__always_inline__)) vec_vrfiz(vector float __a) { return __builtin_altivec_vrfiz(__a); } /* vec_unpackh */ /* The vector unpack instructions all have a big-endian bias, so for little endian we must reverse the meanings of "high" and "low." */ static __inline__ vector short __ATTRS_o_ai vec_unpackh(vector signed char __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vupklsb((vector char)__a); #else return __builtin_altivec_vupkhsb((vector char)__a); #endif } static __inline__ vector bool short __ATTRS_o_ai vec_unpackh(vector bool char __a) { #ifdef __LITTLE_ENDIAN__ return (vector bool short)__builtin_altivec_vupklsb((vector char)__a); #else return (vector bool short)__builtin_altivec_vupkhsb((vector char)__a); #endif } static __inline__ vector int __ATTRS_o_ai vec_unpackh(vector short __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vupklsh(__a); #else return __builtin_altivec_vupkhsh(__a); #endif } static __inline__ vector bool int __ATTRS_o_ai vec_unpackh(vector bool short __a) { #ifdef __LITTLE_ENDIAN__ return (vector bool int)__builtin_altivec_vupklsh((vector short)__a); #else return (vector bool int)__builtin_altivec_vupkhsh((vector short)__a); #endif } static __inline__ vector unsigned int __ATTRS_o_ai vec_unpackh(vector pixel __a) { #ifdef __LITTLE_ENDIAN__ return (vector unsigned int)__builtin_altivec_vupklpx((vector short)__a); #else return (vector unsigned int)__builtin_altivec_vupkhpx((vector short)__a); #endif } #ifdef __POWER8_VECTOR__ static __inline__ vector long long __ATTRS_o_ai vec_unpackh(vector int __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vupklsw(__a); #else return __builtin_altivec_vupkhsw(__a); #endif } static __inline__ vector bool long long __ATTRS_o_ai vec_unpackh(vector bool int __a) { #ifdef __LITTLE_ENDIAN__ return (vector bool long long)__builtin_altivec_vupklsw((vector int)__a); #else return (vector bool long long)__builtin_altivec_vupkhsw((vector int)__a); #endif } static __inline__ vector double __ATTRS_o_ai vec_unpackh(vector float __a) { return (vector double)(__a[0], __a[1]); } #endif /* vec_vupkhsb */ static __inline__ vector short __ATTRS_o_ai vec_vupkhsb(vector signed char __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vupklsb((vector char)__a); #else return __builtin_altivec_vupkhsb((vector char)__a); #endif } static __inline__ vector bool short __ATTRS_o_ai vec_vupkhsb(vector bool char __a) { #ifdef __LITTLE_ENDIAN__ return (vector bool short)__builtin_altivec_vupklsb((vector char)__a); #else return (vector bool short)__builtin_altivec_vupkhsb((vector char)__a); #endif } /* vec_vupkhsh */ static __inline__ vector int __ATTRS_o_ai vec_vupkhsh(vector short __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vupklsh(__a); #else return __builtin_altivec_vupkhsh(__a); #endif } static __inline__ vector bool int __ATTRS_o_ai vec_vupkhsh(vector bool short __a) { #ifdef __LITTLE_ENDIAN__ return (vector bool int)__builtin_altivec_vupklsh((vector short)__a); #else return (vector bool int)__builtin_altivec_vupkhsh((vector short)__a); #endif } static __inline__ vector unsigned int __ATTRS_o_ai vec_vupkhsh(vector pixel __a) { #ifdef __LITTLE_ENDIAN__ return (vector unsigned int)__builtin_altivec_vupklpx((vector short)__a); #else return (vector unsigned int)__builtin_altivec_vupkhpx((vector short)__a); #endif } /* vec_vupkhsw */ #ifdef __POWER8_VECTOR__ static __inline__ vector long long __ATTRS_o_ai vec_vupkhsw(vector int __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vupklsw(__a); #else return __builtin_altivec_vupkhsw(__a); #endif } static __inline__ vector bool long long __ATTRS_o_ai vec_vupkhsw(vector bool int __a) { #ifdef __LITTLE_ENDIAN__ return (vector bool long long)__builtin_altivec_vupklsw((vector int)__a); #else return (vector bool long long)__builtin_altivec_vupkhsw((vector int)__a); #endif } #endif /* vec_unpackl */ static __inline__ vector short __ATTRS_o_ai vec_unpackl(vector signed char __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vupkhsb((vector char)__a); #else return __builtin_altivec_vupklsb((vector char)__a); #endif } static __inline__ vector bool short __ATTRS_o_ai vec_unpackl(vector bool char __a) { #ifdef __LITTLE_ENDIAN__ return (vector bool short)__builtin_altivec_vupkhsb((vector char)__a); #else return (vector bool short)__builtin_altivec_vupklsb((vector char)__a); #endif } static __inline__ vector int __ATTRS_o_ai vec_unpackl(vector short __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vupkhsh(__a); #else return __builtin_altivec_vupklsh(__a); #endif } static __inline__ vector bool int __ATTRS_o_ai vec_unpackl(vector bool short __a) { #ifdef __LITTLE_ENDIAN__ return (vector bool int)__builtin_altivec_vupkhsh((vector short)__a); #else return (vector bool int)__builtin_altivec_vupklsh((vector short)__a); #endif } static __inline__ vector unsigned int __ATTRS_o_ai vec_unpackl(vector pixel __a) { #ifdef __LITTLE_ENDIAN__ return (vector unsigned int)__builtin_altivec_vupkhpx((vector short)__a); #else return (vector unsigned int)__builtin_altivec_vupklpx((vector short)__a); #endif } #ifdef __POWER8_VECTOR__ static __inline__ vector long long __ATTRS_o_ai vec_unpackl(vector int __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vupkhsw(__a); #else return __builtin_altivec_vupklsw(__a); #endif } static __inline__ vector bool long long __ATTRS_o_ai vec_unpackl(vector bool int __a) { #ifdef __LITTLE_ENDIAN__ return (vector bool long long)__builtin_altivec_vupkhsw((vector int)__a); #else return (vector bool long long)__builtin_altivec_vupklsw((vector int)__a); #endif } static __inline__ vector double __ATTRS_o_ai vec_unpackl(vector float __a) { return (vector double)(__a[2], __a[3]); } #endif /* vec_vupklsb */ static __inline__ vector short __ATTRS_o_ai vec_vupklsb(vector signed char __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vupkhsb((vector char)__a); #else return __builtin_altivec_vupklsb((vector char)__a); #endif } static __inline__ vector bool short __ATTRS_o_ai vec_vupklsb(vector bool char __a) { #ifdef __LITTLE_ENDIAN__ return (vector bool short)__builtin_altivec_vupkhsb((vector char)__a); #else return (vector bool short)__builtin_altivec_vupklsb((vector char)__a); #endif } /* vec_vupklsh */ static __inline__ vector int __ATTRS_o_ai vec_vupklsh(vector short __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vupkhsh(__a); #else return __builtin_altivec_vupklsh(__a); #endif } static __inline__ vector bool int __ATTRS_o_ai vec_vupklsh(vector bool short __a) { #ifdef __LITTLE_ENDIAN__ return (vector bool int)__builtin_altivec_vupkhsh((vector short)__a); #else return (vector bool int)__builtin_altivec_vupklsh((vector short)__a); #endif } static __inline__ vector unsigned int __ATTRS_o_ai vec_vupklsh(vector pixel __a) { #ifdef __LITTLE_ENDIAN__ return (vector unsigned int)__builtin_altivec_vupkhpx((vector short)__a); #else return (vector unsigned int)__builtin_altivec_vupklpx((vector short)__a); #endif } /* vec_vupklsw */ #ifdef __POWER8_VECTOR__ static __inline__ vector long long __ATTRS_o_ai vec_vupklsw(vector int __a) { #ifdef __LITTLE_ENDIAN__ return __builtin_altivec_vupkhsw(__a); #else return __builtin_altivec_vupklsw(__a); #endif } static __inline__ vector bool long long __ATTRS_o_ai vec_vupklsw(vector bool int __a) { #ifdef __LITTLE_ENDIAN__ return (vector bool long long)__builtin_altivec_vupkhsw((vector int)__a); #else return (vector bool long long)__builtin_altivec_vupklsw((vector int)__a); #endif } #endif /* vec_vsx_ld */ #ifdef __VSX__ static __inline__ vector bool int __ATTRS_o_ai vec_vsx_ld(int __a, const vector bool int *__b) { return (vector bool int)__builtin_vsx_lxvw4x(__a, __b); } static __inline__ vector signed int __ATTRS_o_ai vec_vsx_ld(int __a, const vector signed int *__b) { return (vector signed int)__builtin_vsx_lxvw4x(__a, __b); } static __inline__ vector signed int __ATTRS_o_ai vec_vsx_ld(int __a, const signed int *__b) { return (vector signed int)__builtin_vsx_lxvw4x(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsx_ld(int __a, const vector unsigned int *__b) { return (vector unsigned int)__builtin_vsx_lxvw4x(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai vec_vsx_ld(int __a, const unsigned int *__b) { return (vector unsigned int)__builtin_vsx_lxvw4x(__a, __b); } static __inline__ vector float __ATTRS_o_ai vec_vsx_ld(int __a, const vector float *__b) { return (vector float)__builtin_vsx_lxvw4x(__a, __b); } static __inline__ vector float __ATTRS_o_ai vec_vsx_ld(int __a, const float *__b) { return (vector float)__builtin_vsx_lxvw4x(__a, __b); } static __inline__ vector signed long long __ATTRS_o_ai vec_vsx_ld(int __a, const vector signed long long *__b) { return (vector signed long long)__builtin_vsx_lxvd2x(__a, __b); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_vsx_ld(int __a, const vector unsigned long long *__b) { return (vector unsigned long long)__builtin_vsx_lxvd2x(__a, __b); } static __inline__ vector double __ATTRS_o_ai vec_vsx_ld(int __a, const vector double *__b) { return (vector double)__builtin_vsx_lxvd2x(__a, __b); } static __inline__ vector double __ATTRS_o_ai vec_vsx_ld(int __a, const double *__b) { return (vector double)__builtin_vsx_lxvd2x(__a, __b); } static __inline__ vector bool short __ATTRS_o_ai vec_vsx_ld(int __a, const vector bool short *__b) { return (vector bool short)__builtin_vsx_lxvw4x(__a, __b); } static __inline__ vector signed short __ATTRS_o_ai vec_vsx_ld(int __a, const vector signed short *__b) { return (vector signed short)__builtin_vsx_lxvw4x(__a, __b); } static __inline__ vector signed short __ATTRS_o_ai vec_vsx_ld(int __a, const signed short *__b) { return (vector signed short)__builtin_vsx_lxvw4x(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsx_ld(int __a, const vector unsigned short *__b) { return (vector unsigned short)__builtin_vsx_lxvw4x(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai vec_vsx_ld(int __a, const unsigned short *__b) { return (vector unsigned short)__builtin_vsx_lxvw4x(__a, __b); } static __inline__ vector bool char __ATTRS_o_ai vec_vsx_ld(int __a, const vector bool char *__b) { return (vector bool char)__builtin_vsx_lxvw4x(__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_vsx_ld(int __a, const vector signed char *__b) { return (vector signed char)__builtin_vsx_lxvw4x(__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_vsx_ld(int __a, const signed char *__b) { return (vector signed char)__builtin_vsx_lxvw4x(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsx_ld(int __a, const vector unsigned char *__b) { return (vector unsigned char)__builtin_vsx_lxvw4x(__a, __b); } static __inline__ vector unsigned char __ATTRS_o_ai vec_vsx_ld(int __a, const unsigned char *__b) { return (vector unsigned char)__builtin_vsx_lxvw4x(__a, __b); } #endif /* vec_vsx_st */ #ifdef __VSX__ static __inline__ void __ATTRS_o_ai vec_vsx_st(vector bool int __a, int __b, vector bool int *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector bool int __a, int __b, signed int *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector bool int __a, int __b, unsigned int *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector signed int __a, int __b, vector signed int *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector signed int __a, int __b, signed int *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector unsigned int __a, int __b, vector unsigned int *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector unsigned int __a, int __b, unsigned int *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector float __a, int __b, vector float *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector float __a, int __b, float *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector signed long long __a, int __b, vector signed long long *__c) { __builtin_vsx_stxvd2x((vector double)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector unsigned long long __a, int __b, vector unsigned long long *__c) { __builtin_vsx_stxvd2x((vector double)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector double __a, int __b, vector double *__c) { __builtin_vsx_stxvd2x((vector double)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector double __a, int __b, double *__c) { __builtin_vsx_stxvd2x((vector double)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector bool short __a, int __b, vector bool short *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector bool short __a, int __b, signed short *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector bool short __a, int __b, unsigned short *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector signed short __a, int __b, vector signed short *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector signed short __a, int __b, signed short *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector unsigned short __a, int __b, vector unsigned short *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector unsigned short __a, int __b, unsigned short *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector bool char __a, int __b, vector bool char *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector bool char __a, int __b, signed char *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector bool char __a, int __b, unsigned char *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector signed char __a, int __b, vector signed char *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector signed char __a, int __b, signed char *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector unsigned char __a, int __b, vector unsigned char *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } static __inline__ void __ATTRS_o_ai vec_vsx_st(vector unsigned char __a, int __b, unsigned char *__c) { __builtin_vsx_stxvw4x((vector int)__a, __b, __c); } #endif #ifdef __VSX__ #define vec_xxpermdi __builtin_vsx_xxpermdi #define vec_xxsldwi __builtin_vsx_xxsldwi #endif /* vec_xor */ #define __builtin_altivec_vxor vec_xor static __inline__ vector signed char __ATTRS_o_ai vec_xor(vector signed char __a, vector signed char __b) { return __a ^ __b; } static __inline__ vector signed char __ATTRS_o_ai vec_xor(vector bool char __a, vector signed char __b) { return (vector signed char)__a ^ __b; } static __inline__ vector signed char __ATTRS_o_ai vec_xor(vector signed char __a, vector bool char __b) { return __a ^ (vector signed char)__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_xor(vector unsigned char __a, vector unsigned char __b) { return __a ^ __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_xor(vector bool char __a, vector unsigned char __b) { return (vector unsigned char)__a ^ __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_xor(vector unsigned char __a, vector bool char __b) { return __a ^ (vector unsigned char)__b; } static __inline__ vector bool char __ATTRS_o_ai vec_xor(vector bool char __a, vector bool char __b) { return __a ^ __b; } static __inline__ vector short __ATTRS_o_ai vec_xor(vector short __a, vector short __b) { return __a ^ __b; } static __inline__ vector short __ATTRS_o_ai vec_xor(vector bool short __a, vector short __b) { return (vector short)__a ^ __b; } static __inline__ vector short __ATTRS_o_ai vec_xor(vector short __a, vector bool short __b) { return __a ^ (vector short)__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_xor(vector unsigned short __a, vector unsigned short __b) { return __a ^ __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_xor(vector bool short __a, vector unsigned short __b) { return (vector unsigned short)__a ^ __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_xor(vector unsigned short __a, vector bool short __b) { return __a ^ (vector unsigned short)__b; } static __inline__ vector bool short __ATTRS_o_ai vec_xor(vector bool short __a, vector bool short __b) { return __a ^ __b; } static __inline__ vector int __ATTRS_o_ai vec_xor(vector int __a, vector int __b) { return __a ^ __b; } static __inline__ vector int __ATTRS_o_ai vec_xor(vector bool int __a, vector int __b) { return (vector int)__a ^ __b; } static __inline__ vector int __ATTRS_o_ai vec_xor(vector int __a, vector bool int __b) { return __a ^ (vector int)__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_xor(vector unsigned int __a, vector unsigned int __b) { return __a ^ __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_xor(vector bool int __a, vector unsigned int __b) { return (vector unsigned int)__a ^ __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_xor(vector unsigned int __a, vector bool int __b) { return __a ^ (vector unsigned int)__b; } static __inline__ vector bool int __ATTRS_o_ai vec_xor(vector bool int __a, vector bool int __b) { return __a ^ __b; } static __inline__ vector float __ATTRS_o_ai vec_xor(vector float __a, vector float __b) { vector unsigned int __res = (vector unsigned int)__a ^ (vector unsigned int)__b; return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_xor(vector bool int __a, vector float __b) { vector unsigned int __res = (vector unsigned int)__a ^ (vector unsigned int)__b; return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_xor(vector float __a, vector bool int __b) { vector unsigned int __res = (vector unsigned int)__a ^ (vector unsigned int)__b; return (vector float)__res; } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_xor(vector signed long long __a, vector signed long long __b) { return __a ^ __b; } static __inline__ vector signed long long __ATTRS_o_ai vec_xor(vector bool long long __a, vector signed long long __b) { return (vector signed long long)__a ^ __b; } static __inline__ vector signed long long __ATTRS_o_ai vec_xor(vector signed long long __a, vector bool long long __b) { return __a ^ (vector signed long long)__b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_xor(vector unsigned long long __a, vector unsigned long long __b) { return __a ^ __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_xor(vector bool long long __a, vector unsigned long long __b) { return (vector unsigned long long)__a ^ __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_xor(vector unsigned long long __a, vector bool long long __b) { return __a ^ (vector unsigned long long)__b; } static __inline__ vector bool long long __ATTRS_o_ai vec_xor(vector bool long long __a, vector bool long long __b) { return __a ^ __b; } static __inline__ vector double __ATTRS_o_ai vec_xor(vector double __a, vector double __b) { return (vector double)((vector unsigned long long)__a ^ (vector unsigned long long)__b); } static __inline__ vector double __ATTRS_o_ai vec_xor(vector double __a, vector bool long long __b) { return (vector double)((vector unsigned long long)__a ^ (vector unsigned long long)__b); } static __inline__ vector double __ATTRS_o_ai vec_xor(vector bool long long __a, vector double __b) { return (vector double)((vector unsigned long long)__a ^ (vector unsigned long long)__b); } #endif /* vec_vxor */ static __inline__ vector signed char __ATTRS_o_ai vec_vxor(vector signed char __a, vector signed char __b) { return __a ^ __b; } static __inline__ vector signed char __ATTRS_o_ai vec_vxor(vector bool char __a, vector signed char __b) { return (vector signed char)__a ^ __b; } static __inline__ vector signed char __ATTRS_o_ai vec_vxor(vector signed char __a, vector bool char __b) { return __a ^ (vector signed char)__b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vxor(vector unsigned char __a, vector unsigned char __b) { return __a ^ __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vxor(vector bool char __a, vector unsigned char __b) { return (vector unsigned char)__a ^ __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_vxor(vector unsigned char __a, vector bool char __b) { return __a ^ (vector unsigned char)__b; } static __inline__ vector bool char __ATTRS_o_ai vec_vxor(vector bool char __a, vector bool char __b) { return __a ^ __b; } static __inline__ vector short __ATTRS_o_ai vec_vxor(vector short __a, vector short __b) { return __a ^ __b; } static __inline__ vector short __ATTRS_o_ai vec_vxor(vector bool short __a, vector short __b) { return (vector short)__a ^ __b; } static __inline__ vector short __ATTRS_o_ai vec_vxor(vector short __a, vector bool short __b) { return __a ^ (vector short)__b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vxor(vector unsigned short __a, vector unsigned short __b) { return __a ^ __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vxor(vector bool short __a, vector unsigned short __b) { return (vector unsigned short)__a ^ __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_vxor(vector unsigned short __a, vector bool short __b) { return __a ^ (vector unsigned short)__b; } static __inline__ vector bool short __ATTRS_o_ai vec_vxor(vector bool short __a, vector bool short __b) { return __a ^ __b; } static __inline__ vector int __ATTRS_o_ai vec_vxor(vector int __a, vector int __b) { return __a ^ __b; } static __inline__ vector int __ATTRS_o_ai vec_vxor(vector bool int __a, vector int __b) { return (vector int)__a ^ __b; } static __inline__ vector int __ATTRS_o_ai vec_vxor(vector int __a, vector bool int __b) { return __a ^ (vector int)__b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vxor(vector unsigned int __a, vector unsigned int __b) { return __a ^ __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vxor(vector bool int __a, vector unsigned int __b) { return (vector unsigned int)__a ^ __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_vxor(vector unsigned int __a, vector bool int __b) { return __a ^ (vector unsigned int)__b; } static __inline__ vector bool int __ATTRS_o_ai vec_vxor(vector bool int __a, vector bool int __b) { return __a ^ __b; } static __inline__ vector float __ATTRS_o_ai vec_vxor(vector float __a, vector float __b) { vector unsigned int __res = (vector unsigned int)__a ^ (vector unsigned int)__b; return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_vxor(vector bool int __a, vector float __b) { vector unsigned int __res = (vector unsigned int)__a ^ (vector unsigned int)__b; return (vector float)__res; } static __inline__ vector float __ATTRS_o_ai vec_vxor(vector float __a, vector bool int __b) { vector unsigned int __res = (vector unsigned int)__a ^ (vector unsigned int)__b; return (vector float)__res; } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_vxor(vector signed long long __a, vector signed long long __b) { return __a ^ __b; } static __inline__ vector signed long long __ATTRS_o_ai vec_vxor(vector bool long long __a, vector signed long long __b) { return (vector signed long long)__a ^ __b; } static __inline__ vector signed long long __ATTRS_o_ai vec_vxor(vector signed long long __a, vector bool long long __b) { return __a ^ (vector signed long long)__b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_vxor(vector unsigned long long __a, vector unsigned long long __b) { return __a ^ __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_vxor(vector bool long long __a, vector unsigned long long __b) { return (vector unsigned long long)__a ^ __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_vxor(vector unsigned long long __a, vector bool long long __b) { return __a ^ (vector unsigned long long)__b; } static __inline__ vector bool long long __ATTRS_o_ai vec_vxor(vector bool long long __a, vector bool long long __b) { return __a ^ __b; } #endif /* ------------------------ extensions for CBEA ----------------------------- */ /* vec_extract */ static __inline__ signed char __ATTRS_o_ai vec_extract(vector signed char __a, int __b) { return __a[__b]; } static __inline__ unsigned char __ATTRS_o_ai vec_extract(vector unsigned char __a, int __b) { return __a[__b]; } static __inline__ unsigned char __ATTRS_o_ai vec_extract(vector bool char __a, int __b) { return __a[__b]; } static __inline__ signed short __ATTRS_o_ai vec_extract(vector signed short __a, int __b) { return __a[__b]; } static __inline__ unsigned short __ATTRS_o_ai vec_extract(vector unsigned short __a, int __b) { return __a[__b]; } static __inline__ unsigned short __ATTRS_o_ai vec_extract(vector bool short __a, int __b) { return __a[__b]; } static __inline__ signed int __ATTRS_o_ai vec_extract(vector signed int __a, int __b) { return __a[__b]; } static __inline__ unsigned int __ATTRS_o_ai vec_extract(vector unsigned int __a, int __b) { return __a[__b]; } static __inline__ unsigned int __ATTRS_o_ai vec_extract(vector bool int __a, int __b) { return __a[__b]; } #ifdef __VSX__ static __inline__ signed long long __ATTRS_o_ai vec_extract(vector signed long long __a, int __b) { return __a[__b]; } static __inline__ unsigned long long __ATTRS_o_ai vec_extract(vector unsigned long long __a, int __b) { return __a[__b]; } static __inline__ unsigned long long __ATTRS_o_ai vec_extract(vector bool long long __a, int __b) { return __a[__b]; } static __inline__ double __ATTRS_o_ai vec_extract(vector double __a, int __b) { return __a[__b]; } #endif static __inline__ float __ATTRS_o_ai vec_extract(vector float __a, int __b) { return __a[__b]; } #ifdef __POWER9_VECTOR__ #define vec_insert4b __builtin_vsx_insertword #define vec_extract4b __builtin_vsx_extractuword /* vec_extract_exp */ static __inline__ vector unsigned int __ATTRS_o_ai vec_extract_exp(vector float __a) { return __builtin_vsx_xvxexpsp(__a); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_extract_exp(vector double __a) { return __builtin_vsx_xvxexpdp(__a); } /* vec_extract_sig */ static __inline__ vector unsigned int __ATTRS_o_ai vec_extract_sig(vector float __a) { return __builtin_vsx_xvxsigsp(__a); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_extract_sig (vector double __a) { return __builtin_vsx_xvxsigdp(__a); } static __inline__ vector float __ATTRS_o_ai vec_extract_fp32_from_shorth(vector unsigned short __a) { vector unsigned short __b = #ifdef __LITTLE_ENDIAN__ __builtin_shufflevector(__a, __a, 0, -1, 1, -1, 2, -1, 3, -1); #else __builtin_shufflevector(__a, __a, -1, 0, -1, 1, -1, 2, -1, 3); #endif return __builtin_vsx_xvcvhpsp(__b); } static __inline__ vector float __ATTRS_o_ai vec_extract_fp32_from_shortl(vector unsigned short __a) { vector unsigned short __b = #ifdef __LITTLE_ENDIAN__ __builtin_shufflevector(__a, __a, 4, -1, 5, -1, 6, -1, 7, -1); #else __builtin_shufflevector(__a, __a, -1, 4, -1, 5, -1, 6, -1, 7); #endif return __builtin_vsx_xvcvhpsp(__b); } #endif /* __POWER9_VECTOR__ */ /* vec_insert */ static __inline__ vector signed char __ATTRS_o_ai vec_insert(signed char __a, vector signed char __b, int __c) { __b[__c] = __a; return __b; } static __inline__ vector unsigned char __ATTRS_o_ai vec_insert(unsigned char __a, vector unsigned char __b, int __c) { __b[__c] = __a; return __b; } static __inline__ vector bool char __ATTRS_o_ai vec_insert(unsigned char __a, vector bool char __b, int __c) { __b[__c] = __a; return __b; } static __inline__ vector signed short __ATTRS_o_ai vec_insert(signed short __a, vector signed short __b, int __c) { __b[__c] = __a; return __b; } static __inline__ vector unsigned short __ATTRS_o_ai vec_insert(unsigned short __a, vector unsigned short __b, int __c) { __b[__c] = __a; return __b; } static __inline__ vector bool short __ATTRS_o_ai vec_insert(unsigned short __a, vector bool short __b, int __c) { __b[__c] = __a; return __b; } static __inline__ vector signed int __ATTRS_o_ai vec_insert(signed int __a, vector signed int __b, int __c) { __b[__c] = __a; return __b; } static __inline__ vector unsigned int __ATTRS_o_ai vec_insert(unsigned int __a, vector unsigned int __b, int __c) { __b[__c] = __a; return __b; } static __inline__ vector bool int __ATTRS_o_ai vec_insert(unsigned int __a, vector bool int __b, int __c) { __b[__c] = __a; return __b; } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_insert(signed long long __a, vector signed long long __b, int __c) { __b[__c] = __a; return __b; } static __inline__ vector unsigned long long __ATTRS_o_ai vec_insert(unsigned long long __a, vector unsigned long long __b, int __c) { __b[__c] = __a; return __b; } static __inline__ vector bool long long __ATTRS_o_ai vec_insert(unsigned long long __a, vector bool long long __b, int __c) { __b[__c] = __a; return __b; } static __inline__ vector double __ATTRS_o_ai vec_insert(double __a, vector double __b, int __c) { __b[__c] = __a; return __b; } #endif static __inline__ vector float __ATTRS_o_ai vec_insert(float __a, vector float __b, int __c) { __b[__c] = __a; return __b; } /* vec_lvlx */ static __inline__ vector signed char __ATTRS_o_ai vec_lvlx(int __a, const signed char *__b) { return vec_perm(vec_ld(__a, __b), (vector signed char)(0), vec_lvsl(__a, __b)); } static __inline__ vector signed char __ATTRS_o_ai vec_lvlx(int __a, const vector signed char *__b) { return vec_perm(vec_ld(__a, __b), (vector signed char)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector unsigned char __ATTRS_o_ai vec_lvlx(int __a, const unsigned char *__b) { return vec_perm(vec_ld(__a, __b), (vector unsigned char)(0), vec_lvsl(__a, __b)); } static __inline__ vector unsigned char __ATTRS_o_ai vec_lvlx(int __a, const vector unsigned char *__b) { return vec_perm(vec_ld(__a, __b), (vector unsigned char)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector bool char __ATTRS_o_ai vec_lvlx(int __a, const vector bool char *__b) { return vec_perm(vec_ld(__a, __b), (vector bool char)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector short __ATTRS_o_ai vec_lvlx(int __a, const short *__b) { return vec_perm(vec_ld(__a, __b), (vector short)(0), vec_lvsl(__a, __b)); } static __inline__ vector short __ATTRS_o_ai vec_lvlx(int __a, const vector short *__b) { return vec_perm(vec_ld(__a, __b), (vector short)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector unsigned short __ATTRS_o_ai vec_lvlx(int __a, const unsigned short *__b) { return vec_perm(vec_ld(__a, __b), (vector unsigned short)(0), vec_lvsl(__a, __b)); } static __inline__ vector unsigned short __ATTRS_o_ai vec_lvlx(int __a, const vector unsigned short *__b) { return vec_perm(vec_ld(__a, __b), (vector unsigned short)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector bool short __ATTRS_o_ai vec_lvlx(int __a, const vector bool short *__b) { return vec_perm(vec_ld(__a, __b), (vector bool short)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector pixel __ATTRS_o_ai vec_lvlx(int __a, const vector pixel *__b) { return vec_perm(vec_ld(__a, __b), (vector pixel)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector int __ATTRS_o_ai vec_lvlx(int __a, const int *__b) { return vec_perm(vec_ld(__a, __b), (vector int)(0), vec_lvsl(__a, __b)); } static __inline__ vector int __ATTRS_o_ai vec_lvlx(int __a, const vector int *__b) { return vec_perm(vec_ld(__a, __b), (vector int)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_lvlx(int __a, const unsigned int *__b) { return vec_perm(vec_ld(__a, __b), (vector unsigned int)(0), vec_lvsl(__a, __b)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_lvlx(int __a, const vector unsigned int *__b) { return vec_perm(vec_ld(__a, __b), (vector unsigned int)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector bool int __ATTRS_o_ai vec_lvlx(int __a, const vector bool int *__b) { return vec_perm(vec_ld(__a, __b), (vector bool int)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector float __ATTRS_o_ai vec_lvlx(int __a, const float *__b) { return vec_perm(vec_ld(__a, __b), (vector float)(0), vec_lvsl(__a, __b)); } static __inline__ vector float __ATTRS_o_ai vec_lvlx(int __a, const vector float *__b) { return vec_perm(vec_ld(__a, __b), (vector float)(0), vec_lvsl(__a, (unsigned char *)__b)); } /* vec_lvlxl */ static __inline__ vector signed char __ATTRS_o_ai vec_lvlxl(int __a, const signed char *__b) { return vec_perm(vec_ldl(__a, __b), (vector signed char)(0), vec_lvsl(__a, __b)); } static __inline__ vector signed char __ATTRS_o_ai vec_lvlxl(int __a, const vector signed char *__b) { return vec_perm(vec_ldl(__a, __b), (vector signed char)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector unsigned char __ATTRS_o_ai vec_lvlxl(int __a, const unsigned char *__b) { return vec_perm(vec_ldl(__a, __b), (vector unsigned char)(0), vec_lvsl(__a, __b)); } static __inline__ vector unsigned char __ATTRS_o_ai vec_lvlxl(int __a, const vector unsigned char *__b) { return vec_perm(vec_ldl(__a, __b), (vector unsigned char)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector bool char __ATTRS_o_ai vec_lvlxl(int __a, const vector bool char *__b) { return vec_perm(vec_ldl(__a, __b), (vector bool char)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector short __ATTRS_o_ai vec_lvlxl(int __a, const short *__b) { return vec_perm(vec_ldl(__a, __b), (vector short)(0), vec_lvsl(__a, __b)); } static __inline__ vector short __ATTRS_o_ai vec_lvlxl(int __a, const vector short *__b) { return vec_perm(vec_ldl(__a, __b), (vector short)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector unsigned short __ATTRS_o_ai vec_lvlxl(int __a, const unsigned short *__b) { return vec_perm(vec_ldl(__a, __b), (vector unsigned short)(0), vec_lvsl(__a, __b)); } static __inline__ vector unsigned short __ATTRS_o_ai vec_lvlxl(int __a, const vector unsigned short *__b) { return vec_perm(vec_ldl(__a, __b), (vector unsigned short)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector bool short __ATTRS_o_ai vec_lvlxl(int __a, const vector bool short *__b) { return vec_perm(vec_ldl(__a, __b), (vector bool short)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector pixel __ATTRS_o_ai vec_lvlxl(int __a, const vector pixel *__b) { return vec_perm(vec_ldl(__a, __b), (vector pixel)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector int __ATTRS_o_ai vec_lvlxl(int __a, const int *__b) { return vec_perm(vec_ldl(__a, __b), (vector int)(0), vec_lvsl(__a, __b)); } static __inline__ vector int __ATTRS_o_ai vec_lvlxl(int __a, const vector int *__b) { return vec_perm(vec_ldl(__a, __b), (vector int)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_lvlxl(int __a, const unsigned int *__b) { return vec_perm(vec_ldl(__a, __b), (vector unsigned int)(0), vec_lvsl(__a, __b)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_lvlxl(int __a, const vector unsigned int *__b) { return vec_perm(vec_ldl(__a, __b), (vector unsigned int)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector bool int __ATTRS_o_ai vec_lvlxl(int __a, const vector bool int *__b) { return vec_perm(vec_ldl(__a, __b), (vector bool int)(0), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector float __ATTRS_o_ai vec_lvlxl(int __a, const float *__b) { return vec_perm(vec_ldl(__a, __b), (vector float)(0), vec_lvsl(__a, __b)); } static __inline__ vector float __ATTRS_o_ai vec_lvlxl(int __a, vector float *__b) { return vec_perm(vec_ldl(__a, __b), (vector float)(0), vec_lvsl(__a, (unsigned char *)__b)); } /* vec_lvrx */ static __inline__ vector signed char __ATTRS_o_ai vec_lvrx(int __a, const signed char *__b) { return vec_perm((vector signed char)(0), vec_ld(__a, __b), vec_lvsl(__a, __b)); } static __inline__ vector signed char __ATTRS_o_ai vec_lvrx(int __a, const vector signed char *__b) { return vec_perm((vector signed char)(0), vec_ld(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector unsigned char __ATTRS_o_ai vec_lvrx(int __a, const unsigned char *__b) { return vec_perm((vector unsigned char)(0), vec_ld(__a, __b), vec_lvsl(__a, __b)); } static __inline__ vector unsigned char __ATTRS_o_ai vec_lvrx(int __a, const vector unsigned char *__b) { return vec_perm((vector unsigned char)(0), vec_ld(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector bool char __ATTRS_o_ai vec_lvrx(int __a, const vector bool char *__b) { return vec_perm((vector bool char)(0), vec_ld(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector short __ATTRS_o_ai vec_lvrx(int __a, const short *__b) { return vec_perm((vector short)(0), vec_ld(__a, __b), vec_lvsl(__a, __b)); } static __inline__ vector short __ATTRS_o_ai vec_lvrx(int __a, const vector short *__b) { return vec_perm((vector short)(0), vec_ld(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector unsigned short __ATTRS_o_ai vec_lvrx(int __a, const unsigned short *__b) { return vec_perm((vector unsigned short)(0), vec_ld(__a, __b), vec_lvsl(__a, __b)); } static __inline__ vector unsigned short __ATTRS_o_ai vec_lvrx(int __a, const vector unsigned short *__b) { return vec_perm((vector unsigned short)(0), vec_ld(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector bool short __ATTRS_o_ai vec_lvrx(int __a, const vector bool short *__b) { return vec_perm((vector bool short)(0), vec_ld(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector pixel __ATTRS_o_ai vec_lvrx(int __a, const vector pixel *__b) { return vec_perm((vector pixel)(0), vec_ld(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector int __ATTRS_o_ai vec_lvrx(int __a, const int *__b) { return vec_perm((vector int)(0), vec_ld(__a, __b), vec_lvsl(__a, __b)); } static __inline__ vector int __ATTRS_o_ai vec_lvrx(int __a, const vector int *__b) { return vec_perm((vector int)(0), vec_ld(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_lvrx(int __a, const unsigned int *__b) { return vec_perm((vector unsigned int)(0), vec_ld(__a, __b), vec_lvsl(__a, __b)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_lvrx(int __a, const vector unsigned int *__b) { return vec_perm((vector unsigned int)(0), vec_ld(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector bool int __ATTRS_o_ai vec_lvrx(int __a, const vector bool int *__b) { return vec_perm((vector bool int)(0), vec_ld(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector float __ATTRS_o_ai vec_lvrx(int __a, const float *__b) { return vec_perm((vector float)(0), vec_ld(__a, __b), vec_lvsl(__a, __b)); } static __inline__ vector float __ATTRS_o_ai vec_lvrx(int __a, const vector float *__b) { return vec_perm((vector float)(0), vec_ld(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } /* vec_lvrxl */ static __inline__ vector signed char __ATTRS_o_ai vec_lvrxl(int __a, const signed char *__b) { return vec_perm((vector signed char)(0), vec_ldl(__a, __b), vec_lvsl(__a, __b)); } static __inline__ vector signed char __ATTRS_o_ai vec_lvrxl(int __a, const vector signed char *__b) { return vec_perm((vector signed char)(0), vec_ldl(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector unsigned char __ATTRS_o_ai vec_lvrxl(int __a, const unsigned char *__b) { return vec_perm((vector unsigned char)(0), vec_ldl(__a, __b), vec_lvsl(__a, __b)); } static __inline__ vector unsigned char __ATTRS_o_ai vec_lvrxl(int __a, const vector unsigned char *__b) { return vec_perm((vector unsigned char)(0), vec_ldl(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector bool char __ATTRS_o_ai vec_lvrxl(int __a, const vector bool char *__b) { return vec_perm((vector bool char)(0), vec_ldl(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector short __ATTRS_o_ai vec_lvrxl(int __a, const short *__b) { return vec_perm((vector short)(0), vec_ldl(__a, __b), vec_lvsl(__a, __b)); } static __inline__ vector short __ATTRS_o_ai vec_lvrxl(int __a, const vector short *__b) { return vec_perm((vector short)(0), vec_ldl(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector unsigned short __ATTRS_o_ai vec_lvrxl(int __a, const unsigned short *__b) { return vec_perm((vector unsigned short)(0), vec_ldl(__a, __b), vec_lvsl(__a, __b)); } static __inline__ vector unsigned short __ATTRS_o_ai vec_lvrxl(int __a, const vector unsigned short *__b) { return vec_perm((vector unsigned short)(0), vec_ldl(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector bool short __ATTRS_o_ai vec_lvrxl(int __a, const vector bool short *__b) { return vec_perm((vector bool short)(0), vec_ldl(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector pixel __ATTRS_o_ai vec_lvrxl(int __a, const vector pixel *__b) { return vec_perm((vector pixel)(0), vec_ldl(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector int __ATTRS_o_ai vec_lvrxl(int __a, const int *__b) { return vec_perm((vector int)(0), vec_ldl(__a, __b), vec_lvsl(__a, __b)); } static __inline__ vector int __ATTRS_o_ai vec_lvrxl(int __a, const vector int *__b) { return vec_perm((vector int)(0), vec_ldl(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_lvrxl(int __a, const unsigned int *__b) { return vec_perm((vector unsigned int)(0), vec_ldl(__a, __b), vec_lvsl(__a, __b)); } static __inline__ vector unsigned int __ATTRS_o_ai vec_lvrxl(int __a, const vector unsigned int *__b) { return vec_perm((vector unsigned int)(0), vec_ldl(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector bool int __ATTRS_o_ai vec_lvrxl(int __a, const vector bool int *__b) { return vec_perm((vector bool int)(0), vec_ldl(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } static __inline__ vector float __ATTRS_o_ai vec_lvrxl(int __a, const float *__b) { return vec_perm((vector float)(0), vec_ldl(__a, __b), vec_lvsl(__a, __b)); } static __inline__ vector float __ATTRS_o_ai vec_lvrxl(int __a, const vector float *__b) { return vec_perm((vector float)(0), vec_ldl(__a, __b), vec_lvsl(__a, (unsigned char *)__b)); } /* vec_stvlx */ static __inline__ void __ATTRS_o_ai vec_stvlx(vector signed char __a, int __b, signed char *__c) { return vec_st(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlx(vector signed char __a, int __b, vector signed char *__c) { return vec_st( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlx(vector unsigned char __a, int __b, unsigned char *__c) { return vec_st(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlx(vector unsigned char __a, int __b, vector unsigned char *__c) { return vec_st( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlx(vector bool char __a, int __b, vector bool char *__c) { return vec_st( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlx(vector short __a, int __b, short *__c) { return vec_st(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlx(vector short __a, int __b, vector short *__c) { return vec_st( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlx(vector unsigned short __a, int __b, unsigned short *__c) { return vec_st(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlx(vector unsigned short __a, int __b, vector unsigned short *__c) { return vec_st( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlx(vector bool short __a, int __b, vector bool short *__c) { return vec_st( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlx(vector pixel __a, int __b, vector pixel *__c) { return vec_st( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlx(vector int __a, int __b, int *__c) { return vec_st(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlx(vector int __a, int __b, vector int *__c) { return vec_st( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlx(vector unsigned int __a, int __b, unsigned int *__c) { return vec_st(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlx(vector unsigned int __a, int __b, vector unsigned int *__c) { return vec_st( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlx(vector bool int __a, int __b, vector bool int *__c) { return vec_st( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlx(vector float __a, int __b, vector float *__c) { return vec_st( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } /* vec_stvlxl */ static __inline__ void __ATTRS_o_ai vec_stvlxl(vector signed char __a, int __b, signed char *__c) { return vec_stl(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlxl(vector signed char __a, int __b, vector signed char *__c) { return vec_stl( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlxl(vector unsigned char __a, int __b, unsigned char *__c) { return vec_stl(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlxl(vector unsigned char __a, int __b, vector unsigned char *__c) { return vec_stl( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlxl(vector bool char __a, int __b, vector bool char *__c) { return vec_stl( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlxl(vector short __a, int __b, short *__c) { return vec_stl(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlxl(vector short __a, int __b, vector short *__c) { return vec_stl( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlxl(vector unsigned short __a, int __b, unsigned short *__c) { return vec_stl(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlxl(vector unsigned short __a, int __b, vector unsigned short *__c) { return vec_stl( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlxl(vector bool short __a, int __b, vector bool short *__c) { return vec_stl( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlxl(vector pixel __a, int __b, vector pixel *__c) { return vec_stl( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlxl(vector int __a, int __b, int *__c) { return vec_stl(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlxl(vector int __a, int __b, vector int *__c) { return vec_stl( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlxl(vector unsigned int __a, int __b, unsigned int *__c) { return vec_stl(vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlxl(vector unsigned int __a, int __b, vector unsigned int *__c) { return vec_stl( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlxl(vector bool int __a, int __b, vector bool int *__c) { return vec_stl( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvlxl(vector float __a, int __b, vector float *__c) { return vec_stl( vec_perm(vec_lvrx(__b, __c), __a, vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } /* vec_stvrx */ static __inline__ void __ATTRS_o_ai vec_stvrx(vector signed char __a, int __b, signed char *__c) { return vec_st(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrx(vector signed char __a, int __b, vector signed char *__c) { return vec_st( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrx(vector unsigned char __a, int __b, unsigned char *__c) { return vec_st(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrx(vector unsigned char __a, int __b, vector unsigned char *__c) { return vec_st( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrx(vector bool char __a, int __b, vector bool char *__c) { return vec_st( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrx(vector short __a, int __b, short *__c) { return vec_st(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrx(vector short __a, int __b, vector short *__c) { return vec_st( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrx(vector unsigned short __a, int __b, unsigned short *__c) { return vec_st(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrx(vector unsigned short __a, int __b, vector unsigned short *__c) { return vec_st( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrx(vector bool short __a, int __b, vector bool short *__c) { return vec_st( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrx(vector pixel __a, int __b, vector pixel *__c) { return vec_st( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrx(vector int __a, int __b, int *__c) { return vec_st(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrx(vector int __a, int __b, vector int *__c) { return vec_st( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrx(vector unsigned int __a, int __b, unsigned int *__c) { return vec_st(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrx(vector unsigned int __a, int __b, vector unsigned int *__c) { return vec_st( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrx(vector bool int __a, int __b, vector bool int *__c) { return vec_st( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrx(vector float __a, int __b, vector float *__c) { return vec_st( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } /* vec_stvrxl */ static __inline__ void __ATTRS_o_ai vec_stvrxl(vector signed char __a, int __b, signed char *__c) { return vec_stl(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrxl(vector signed char __a, int __b, vector signed char *__c) { return vec_stl( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrxl(vector unsigned char __a, int __b, unsigned char *__c) { return vec_stl(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrxl(vector unsigned char __a, int __b, vector unsigned char *__c) { return vec_stl( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrxl(vector bool char __a, int __b, vector bool char *__c) { return vec_stl( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrxl(vector short __a, int __b, short *__c) { return vec_stl(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrxl(vector short __a, int __b, vector short *__c) { return vec_stl( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrxl(vector unsigned short __a, int __b, unsigned short *__c) { return vec_stl(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrxl(vector unsigned short __a, int __b, vector unsigned short *__c) { return vec_stl( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrxl(vector bool short __a, int __b, vector bool short *__c) { return vec_stl( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrxl(vector pixel __a, int __b, vector pixel *__c) { return vec_stl( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrxl(vector int __a, int __b, int *__c) { return vec_stl(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrxl(vector int __a, int __b, vector int *__c) { return vec_stl( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrxl(vector unsigned int __a, int __b, unsigned int *__c) { return vec_stl(vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, __c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrxl(vector unsigned int __a, int __b, vector unsigned int *__c) { return vec_stl( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrxl(vector bool int __a, int __b, vector bool int *__c) { return vec_stl( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } static __inline__ void __ATTRS_o_ai vec_stvrxl(vector float __a, int __b, vector float *__c) { return vec_stl( vec_perm(__a, vec_lvlx(__b, __c), vec_lvsr(__b, (unsigned char *)__c)), __b, __c); } /* vec_promote */ static __inline__ vector signed char __ATTRS_o_ai vec_promote(signed char __a, int __b) { vector signed char __res = (vector signed char)(0); __res[__b] = __a; return __res; } static __inline__ vector unsigned char __ATTRS_o_ai vec_promote(unsigned char __a, int __b) { vector unsigned char __res = (vector unsigned char)(0); __res[__b] = __a; return __res; } static __inline__ vector short __ATTRS_o_ai vec_promote(short __a, int __b) { vector short __res = (vector short)(0); __res[__b] = __a; return __res; } static __inline__ vector unsigned short __ATTRS_o_ai vec_promote(unsigned short __a, int __b) { vector unsigned short __res = (vector unsigned short)(0); __res[__b] = __a; return __res; } static __inline__ vector int __ATTRS_o_ai vec_promote(int __a, int __b) { vector int __res = (vector int)(0); __res[__b] = __a; return __res; } static __inline__ vector unsigned int __ATTRS_o_ai vec_promote(unsigned int __a, int __b) { vector unsigned int __res = (vector unsigned int)(0); __res[__b] = __a; return __res; } static __inline__ vector float __ATTRS_o_ai vec_promote(float __a, int __b) { vector float __res = (vector float)(0); __res[__b] = __a; return __res; } /* vec_splats */ static __inline__ vector signed char __ATTRS_o_ai vec_splats(signed char __a) { return (vector signed char)(__a); } static __inline__ vector unsigned char __ATTRS_o_ai vec_splats(unsigned char __a) { return (vector unsigned char)(__a); } static __inline__ vector short __ATTRS_o_ai vec_splats(short __a) { return (vector short)(__a); } static __inline__ vector unsigned short __ATTRS_o_ai vec_splats(unsigned short __a) { return (vector unsigned short)(__a); } static __inline__ vector int __ATTRS_o_ai vec_splats(int __a) { return (vector int)(__a); } static __inline__ vector unsigned int __ATTRS_o_ai vec_splats(unsigned int __a) { return (vector unsigned int)(__a); } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_splats(signed long long __a) { return (vector signed long long)(__a); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_splats(unsigned long long __a) { return (vector unsigned long long)(__a); } #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) static __inline__ vector signed __int128 __ATTRS_o_ai vec_splats(signed __int128 __a) { return (vector signed __int128)(__a); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_splats(unsigned __int128 __a) { return (vector unsigned __int128)(__a); } #endif static __inline__ vector double __ATTRS_o_ai vec_splats(double __a) { return (vector double)(__a); } #endif static __inline__ vector float __ATTRS_o_ai vec_splats(float __a) { return (vector float)(__a); } /* ----------------------------- predicates --------------------------------- */ /* vec_all_eq */ static __inline__ int __ATTRS_o_ai vec_all_eq(vector signed char __a, vector signed char __b) { return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector signed char __a, vector bool char __b) { return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector bool char __a, vector signed char __b) { return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector bool char __a, vector bool char __b) { return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector short __a, vector short __b) { return __builtin_altivec_vcmpequh_p(__CR6_LT, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector short __a, vector bool short __b) { return __builtin_altivec_vcmpequh_p(__CR6_LT, __a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector bool short __a, vector short __b) { return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector bool short __a, vector bool short __b) { return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector pixel __a, vector pixel __b) { return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector int __a, vector int __b) { return __builtin_altivec_vcmpequw_p(__CR6_LT, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector int __a, vector bool int __b) { return __builtin_altivec_vcmpequw_p(__CR6_LT, __a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)__a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)__a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector bool int __a, vector int __b) { return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)__a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)__a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector bool int __a, vector bool int __b) { return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)__a, (vector int)__b); } #ifdef __POWER8_VECTOR__ static __inline__ int __ATTRS_o_ai vec_all_eq(vector signed long long __a, vector signed long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_LT, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector long long __a, vector bool long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_LT, __a, (vector long long)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_LT, (vector long long)__a, (vector long long)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector unsigned long long __a, vector bool long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_LT, (vector long long)__a, (vector long long)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector bool long long __a, vector long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_LT, (vector long long)__a, (vector long long)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector bool long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_LT, (vector long long)__a, (vector long long)__b); } static __inline__ int __ATTRS_o_ai vec_all_eq(vector bool long long __a, vector bool long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_LT, (vector long long)__a, (vector long long)__b); } #endif static __inline__ int __ATTRS_o_ai vec_all_eq(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvcmpeqsp_p(__CR6_LT, __a, __b); #else return __builtin_altivec_vcmpeqfp_p(__CR6_LT, __a, __b); #endif } #ifdef __VSX__ static __inline__ int __ATTRS_o_ai vec_all_eq(vector double __a, vector double __b) { return __builtin_vsx_xvcmpeqdp_p(__CR6_LT, __a, __b); } #endif /* vec_all_ge */ static __inline__ int __ATTRS_o_ai vec_all_ge(vector signed char __a, vector signed char __b) { return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, __b, __a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector signed char __a, vector bool char __b) { return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, (vector signed char)__b, __a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ, __b, __a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)__b, __a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool char __a, vector signed char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)__b, (vector unsigned char)__a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ, __b, (vector unsigned char)__a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool char __a, vector bool char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)__b, (vector unsigned char)__a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector short __a, vector short __b) { return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, __b, __a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector short __a, vector bool short __b) { return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, (vector short)__b, __a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, __b, __a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__b, __a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool short __a, vector short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__b, (vector unsigned short)__a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, __b, (vector unsigned short)__a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool short __a, vector bool short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__b, (vector unsigned short)__a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector int __a, vector int __b) { return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, __b, __a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector int __a, vector bool int __b) { return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, (vector int)__b, __a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, __b, __a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)__b, __a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool int __a, vector int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)__b, (vector unsigned int)__a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, __b, (vector unsigned int)__a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool int __a, vector bool int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)__b, (vector unsigned int)__a); } #ifdef __POWER8_VECTOR__ static __inline__ int __ATTRS_o_ai vec_all_ge(vector signed long long __a, vector signed long long __b) { return __builtin_altivec_vcmpgtsd_p(__CR6_EQ, __b, __a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector signed long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtsd_p(__CR6_EQ, (vector signed long long)__b, __a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ, __b, __a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector unsigned long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ, (vector unsigned long long)__b, __a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool long long __a, vector signed long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ, (vector unsigned long long)__b, (vector unsigned long long)__a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ, __b, (vector unsigned long long)__a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ, (vector unsigned long long)__b, (vector unsigned long long)__a); } #endif static __inline__ int __ATTRS_o_ai vec_all_ge(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvcmpgesp_p(__CR6_LT, __a, __b); #else return __builtin_altivec_vcmpgefp_p(__CR6_LT, __a, __b); #endif } #ifdef __VSX__ static __inline__ int __ATTRS_o_ai vec_all_ge(vector double __a, vector double __b) { return __builtin_vsx_xvcmpgedp_p(__CR6_LT, __a, __b); } #endif /* vec_all_gt */ static __inline__ int __ATTRS_o_ai vec_all_gt(vector signed char __a, vector signed char __b) { return __builtin_altivec_vcmpgtsb_p(__CR6_LT, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector signed char __a, vector bool char __b) { return __builtin_altivec_vcmpgtsb_p(__CR6_LT, __a, (vector signed char)__b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT, __a, (vector unsigned char)__b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool char __a, vector signed char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)__a, (vector unsigned char)__b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)__a, __b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool char __a, vector bool char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)__a, (vector unsigned char)__b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector short __a, vector short __b) { return __builtin_altivec_vcmpgtsh_p(__CR6_LT, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector short __a, vector bool short __b) { return __builtin_altivec_vcmpgtsh_p(__CR6_LT, __a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT, __a, (vector unsigned short)__b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool short __a, vector short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__a, (vector unsigned short)__b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__a, __b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool short __a, vector bool short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__a, (vector unsigned short)__b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector int __a, vector int __b) { return __builtin_altivec_vcmpgtsw_p(__CR6_LT, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector int __a, vector bool int __b) { return __builtin_altivec_vcmpgtsw_p(__CR6_LT, __a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT, __a, (vector unsigned int)__b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool int __a, vector int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)__a, __b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool int __a, vector bool int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)__a, (vector unsigned int)__b); } #ifdef __POWER8_VECTOR__ static __inline__ int __ATTRS_o_ai vec_all_gt(vector signed long long __a, vector signed long long __b) { return __builtin_altivec_vcmpgtsd_p(__CR6_LT, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector signed long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtsd_p(__CR6_LT, __a, (vector signed long long)__b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector unsigned long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT, __a, (vector unsigned long long)__b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool long long __a, vector signed long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT, (vector unsigned long long)__a, (vector unsigned long long)__b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT, (vector unsigned long long)__a, __b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT, (vector unsigned long long)__a, (vector unsigned long long)__b); } #endif static __inline__ int __ATTRS_o_ai vec_all_gt(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvcmpgtsp_p(__CR6_LT, __a, __b); #else return __builtin_altivec_vcmpgtfp_p(__CR6_LT, __a, __b); #endif } #ifdef __VSX__ static __inline__ int __ATTRS_o_ai vec_all_gt(vector double __a, vector double __b) { return __builtin_vsx_xvcmpgtdp_p(__CR6_LT, __a, __b); } #endif /* vec_all_in */ static __inline__ int __attribute__((__always_inline__)) vec_all_in(vector float __a, vector float __b) { return __builtin_altivec_vcmpbfp_p(__CR6_EQ, __a, __b); } /* vec_all_le */ static __inline__ int __ATTRS_o_ai vec_all_le(vector signed char __a, vector signed char __b) { return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector signed char __a, vector bool char __b) { return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, __a, (vector signed char)__b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ, __a, (vector unsigned char)__b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector bool char __a, vector signed char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)__a, (vector unsigned char)__b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)__a, __b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector bool char __a, vector bool char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)__a, (vector unsigned char)__b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector short __a, vector short __b) { return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector short __a, vector bool short __b) { return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, __a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, __a, (vector unsigned short)__b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector bool short __a, vector short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__a, (vector unsigned short)__b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__a, __b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector bool short __a, vector bool short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__a, (vector unsigned short)__b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector int __a, vector int __b) { return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector int __a, vector bool int __b) { return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, __a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, __a, (vector unsigned int)__b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector bool int __a, vector int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)__a, __b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector bool int __a, vector bool int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)__a, (vector unsigned int)__b); } #ifdef __POWER8_VECTOR__ static __inline__ int __ATTRS_o_ai vec_all_le(vector signed long long __a, vector signed long long __b) { return __builtin_altivec_vcmpgtsd_p(__CR6_EQ, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector signed long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtsd_p(__CR6_EQ, __a, (vector signed long long)__b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector unsigned long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ, __a, (vector unsigned long long)__b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector bool long long __a, vector signed long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ, (vector unsigned long long)__a, (vector unsigned long long)__b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector bool long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ, (vector unsigned long long)__a, __b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector bool long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ, (vector unsigned long long)__a, (vector unsigned long long)__b); } #endif static __inline__ int __ATTRS_o_ai vec_all_le(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvcmpgesp_p(__CR6_LT, __b, __a); #else return __builtin_altivec_vcmpgefp_p(__CR6_LT, __b, __a); #endif } #ifdef __VSX__ static __inline__ int __ATTRS_o_ai vec_all_le(vector double __a, vector double __b) { return __builtin_vsx_xvcmpgedp_p(__CR6_LT, __b, __a); } #endif /* vec_all_lt */ static __inline__ int __ATTRS_o_ai vec_all_lt(vector signed char __a, vector signed char __b) { return __builtin_altivec_vcmpgtsb_p(__CR6_LT, __b, __a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector signed char __a, vector bool char __b) { return __builtin_altivec_vcmpgtsb_p(__CR6_LT, (vector signed char)__b, __a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT, __b, __a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)__b, __a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool char __a, vector signed char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)__b, (vector unsigned char)__a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT, __b, (vector unsigned char)__a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool char __a, vector bool char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)__b, (vector unsigned char)__a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector short __a, vector short __b) { return __builtin_altivec_vcmpgtsh_p(__CR6_LT, __b, __a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector short __a, vector bool short __b) { return __builtin_altivec_vcmpgtsh_p(__CR6_LT, (vector short)__b, __a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT, __b, __a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__b, __a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool short __a, vector short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__b, (vector unsigned short)__a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT, __b, (vector unsigned short)__a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool short __a, vector bool short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__b, (vector unsigned short)__a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector int __a, vector int __b) { return __builtin_altivec_vcmpgtsw_p(__CR6_LT, __b, __a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector int __a, vector bool int __b) { return __builtin_altivec_vcmpgtsw_p(__CR6_LT, (vector int)__b, __a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT, __b, __a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)__b, __a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool int __a, vector int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)__b, (vector unsigned int)__a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT, __b, (vector unsigned int)__a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool int __a, vector bool int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)__b, (vector unsigned int)__a); } #ifdef __POWER8_VECTOR__ static __inline__ int __ATTRS_o_ai vec_all_lt(vector signed long long __a, vector signed long long __b) { return __builtin_altivec_vcmpgtsd_p(__CR6_LT, __b, __a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT, __b, __a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector signed long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtsd_p(__CR6_LT, (vector signed long long)__b, __a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector unsigned long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT, (vector unsigned long long)__b, __a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool long long __a, vector signed long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT, (vector unsigned long long)__b, (vector unsigned long long)__a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT, __b, (vector unsigned long long)__a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT, (vector unsigned long long)__b, (vector unsigned long long)__a); } #endif static __inline__ int __ATTRS_o_ai vec_all_lt(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvcmpgtsp_p(__CR6_LT, __b, __a); #else return __builtin_altivec_vcmpgtfp_p(__CR6_LT, __b, __a); #endif } #ifdef __VSX__ static __inline__ int __ATTRS_o_ai vec_all_lt(vector double __a, vector double __b) { return __builtin_vsx_xvcmpgtdp_p(__CR6_LT, __b, __a); } #endif /* vec_all_nan */ static __inline__ int __ATTRS_o_ai vec_all_nan(vector float __a) { #ifdef __VSX__ return __builtin_vsx_xvcmpeqsp_p(__CR6_EQ, __a, __a); #else return __builtin_altivec_vcmpeqfp_p(__CR6_EQ, __a, __a); #endif } #ifdef __VSX__ static __inline__ int __ATTRS_o_ai vec_all_nan(vector double __a) { return __builtin_vsx_xvcmpeqdp_p(__CR6_EQ, __a, __a); } #endif /* vec_all_ne */ static __inline__ int __ATTRS_o_ai vec_all_ne(vector signed char __a, vector signed char __b) { return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector signed char __a, vector bool char __b) { return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector bool char __a, vector signed char __b) { return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector bool char __a, vector bool char __b) { return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector short __a, vector short __b) { return __builtin_altivec_vcmpequh_p(__CR6_EQ, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector short __a, vector bool short __b) { return __builtin_altivec_vcmpequh_p(__CR6_EQ, __a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector bool short __a, vector short __b) { return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector bool short __a, vector bool short __b) { return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector pixel __a, vector pixel __b) { return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector int __a, vector int __b) { return __builtin_altivec_vcmpequw_p(__CR6_EQ, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector int __a, vector bool int __b) { return __builtin_altivec_vcmpequw_p(__CR6_EQ, __a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)__a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)__a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector bool int __a, vector int __b) { return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)__a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)__a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector bool int __a, vector bool int __b) { return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)__a, (vector int)__b); } #ifdef __POWER8_VECTOR__ static __inline__ int __ATTRS_o_ai vec_all_ne(vector signed long long __a, vector signed long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_EQ, __a, __b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_EQ, (vector long long)__a, (vector long long)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector signed long long __a, vector bool long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_EQ, __a, (vector signed long long)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector unsigned long long __a, vector bool long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_EQ, (vector signed long long)__a, (vector signed long long)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector bool long long __a, vector signed long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_EQ, (vector signed long long)__a, (vector signed long long)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector bool long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_EQ, (vector signed long long)__a, (vector signed long long)__b); } static __inline__ int __ATTRS_o_ai vec_all_ne(vector bool long long __a, vector bool long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_EQ, (vector signed long long)__a, (vector signed long long)__b); } #endif static __inline__ int __ATTRS_o_ai vec_all_ne(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvcmpeqdp_p(__CR6_EQ, __a, __b); #else return __builtin_altivec_vcmpeqfp_p(__CR6_EQ, __a, __b); #endif } #ifdef __VSX__ static __inline__ int __ATTRS_o_ai vec_all_ne(vector double __a, vector double __b) { return __builtin_vsx_xvcmpeqdp_p(__CR6_EQ, __a, __b); } #endif /* vec_all_nge */ static __inline__ int __ATTRS_o_ai vec_all_nge(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvcmpgesp_p(__CR6_EQ, __a, __b); #else return __builtin_altivec_vcmpgefp_p(__CR6_EQ, __a, __b); #endif } #ifdef __VSX__ static __inline__ int __ATTRS_o_ai vec_all_nge(vector double __a, vector double __b) { return __builtin_vsx_xvcmpgedp_p(__CR6_EQ, __a, __b); } #endif /* vec_all_ngt */ static __inline__ int __ATTRS_o_ai vec_all_ngt(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvcmpgtsp_p(__CR6_EQ, __a, __b); #else return __builtin_altivec_vcmpgtfp_p(__CR6_EQ, __a, __b); #endif } #ifdef __VSX__ static __inline__ int __ATTRS_o_ai vec_all_ngt(vector double __a, vector double __b) { return __builtin_vsx_xvcmpgtdp_p(__CR6_EQ, __a, __b); } #endif /* vec_all_nle */ static __inline__ int __attribute__((__always_inline__)) vec_all_nle(vector float __a, vector float __b) { return __builtin_altivec_vcmpgefp_p(__CR6_EQ, __b, __a); } /* vec_all_nlt */ static __inline__ int __attribute__((__always_inline__)) vec_all_nlt(vector float __a, vector float __b) { return __builtin_altivec_vcmpgtfp_p(__CR6_EQ, __b, __a); } /* vec_all_numeric */ static __inline__ int __attribute__((__always_inline__)) vec_all_numeric(vector float __a) { return __builtin_altivec_vcmpeqfp_p(__CR6_LT, __a, __a); } /* vec_any_eq */ static __inline__ int __ATTRS_o_ai vec_any_eq(vector signed char __a, vector signed char __b) { return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector signed char __a, vector bool char __b) { return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector bool char __a, vector signed char __b) { return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector bool char __a, vector bool char __b) { return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector short __a, vector short __b) { return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector short __a, vector bool short __b) { return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, __a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector bool short __a, vector short __b) { return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector bool short __a, vector bool short __b) { return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector pixel __a, vector pixel __b) { return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector int __a, vector int __b) { return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector int __a, vector bool int __b) { return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, __a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)__a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)__a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector bool int __a, vector int __b) { return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)__a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)__a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector bool int __a, vector bool int __b) { return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)__a, (vector int)__b); } #ifdef __POWER8_VECTOR__ static __inline__ int __ATTRS_o_ai vec_any_eq(vector signed long long __a, vector signed long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_EQ_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_EQ_REV, (vector long long)__a, (vector long long)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector signed long long __a, vector bool long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_EQ_REV, __a, (vector signed long long)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector unsigned long long __a, vector bool long long __b) { return __builtin_altivec_vcmpequd_p( __CR6_EQ_REV, (vector signed long long)__a, (vector signed long long)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector bool long long __a, vector signed long long __b) { return __builtin_altivec_vcmpequd_p( __CR6_EQ_REV, (vector signed long long)__a, (vector signed long long)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector bool long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpequd_p( __CR6_EQ_REV, (vector signed long long)__a, (vector signed long long)__b); } static __inline__ int __ATTRS_o_ai vec_any_eq(vector bool long long __a, vector bool long long __b) { return __builtin_altivec_vcmpequd_p( __CR6_EQ_REV, (vector signed long long)__a, (vector signed long long)__b); } #endif static __inline__ int __ATTRS_o_ai vec_any_eq(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvcmpeqsp_p(__CR6_EQ_REV, __a, __b); #else return __builtin_altivec_vcmpeqfp_p(__CR6_EQ_REV, __a, __b); #endif } #ifdef __VSX__ static __inline__ int __ATTRS_o_ai vec_any_eq(vector double __a, vector double __b) { return __builtin_vsx_xvcmpeqdp_p(__CR6_EQ_REV, __a, __b); } #endif /* vec_any_ge */ static __inline__ int __ATTRS_o_ai vec_any_ge(vector signed char __a, vector signed char __b) { return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, __b, __a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector signed char __a, vector bool char __b) { return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, (vector signed char)__b, __a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, __b, __a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__b, __a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool char __a, vector signed char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__b, (vector unsigned char)__a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, __b, (vector unsigned char)__a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool char __a, vector bool char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__b, (vector unsigned char)__a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector short __a, vector short __b) { return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, __b, __a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector short __a, vector bool short __b) { return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, (vector short)__b, __a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, __b, __a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__b, __a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool short __a, vector short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__b, (vector unsigned short)__a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, __b, (vector unsigned short)__a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool short __a, vector bool short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__b, (vector unsigned short)__a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector int __a, vector int __b) { return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, __b, __a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector int __a, vector bool int __b) { return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, (vector int)__b, __a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, __b, __a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__b, __a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool int __a, vector int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__b, (vector unsigned int)__a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, __b, (vector unsigned int)__a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool int __a, vector bool int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__b, (vector unsigned int)__a); } #ifdef __POWER8_VECTOR__ static __inline__ int __ATTRS_o_ai vec_any_ge(vector signed long long __a, vector signed long long __b) { return __builtin_altivec_vcmpgtsd_p(__CR6_LT_REV, __b, __a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV, __b, __a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector signed long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtsd_p(__CR6_LT_REV, (vector signed long long)__b, __a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector unsigned long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV, (vector unsigned long long)__b, __a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool long long __a, vector signed long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV, (vector unsigned long long)__b, (vector unsigned long long)__a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV, __b, (vector unsigned long long)__a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV, (vector unsigned long long)__b, (vector unsigned long long)__a); } #endif static __inline__ int __ATTRS_o_ai vec_any_ge(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvcmpgesp_p(__CR6_EQ_REV, __a, __b); #else return __builtin_altivec_vcmpgefp_p(__CR6_EQ_REV, __a, __b); #endif } #ifdef __VSX__ static __inline__ int __ATTRS_o_ai vec_any_ge(vector double __a, vector double __b) { return __builtin_vsx_xvcmpgedp_p(__CR6_EQ_REV, __a, __b); } #endif /* vec_any_gt */ static __inline__ int __ATTRS_o_ai vec_any_gt(vector signed char __a, vector signed char __b) { return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector signed char __a, vector bool char __b) { return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, __a, (vector signed char)__b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, __a, (vector unsigned char)__b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool char __a, vector signed char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__a, (vector unsigned char)__b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__a, __b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool char __a, vector bool char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__a, (vector unsigned char)__b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector short __a, vector short __b) { return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector short __a, vector bool short __b) { return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, __a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, __a, (vector unsigned short)__b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool short __a, vector short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__a, (vector unsigned short)__b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__a, __b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool short __a, vector bool short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__a, (vector unsigned short)__b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector int __a, vector int __b) { return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector int __a, vector bool int __b) { return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, __a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, __a, (vector unsigned int)__b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool int __a, vector int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__a, __b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool int __a, vector bool int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__a, (vector unsigned int)__b); } #ifdef __POWER8_VECTOR__ static __inline__ int __ATTRS_o_ai vec_any_gt(vector signed long long __a, vector signed long long __b) { return __builtin_altivec_vcmpgtsd_p(__CR6_EQ_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector signed long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtsd_p(__CR6_EQ_REV, __a, (vector signed long long)__b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector unsigned long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV, __a, (vector unsigned long long)__b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool long long __a, vector signed long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV, (vector unsigned long long)__a, (vector unsigned long long)__b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV, (vector unsigned long long)__a, __b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV, (vector unsigned long long)__a, (vector unsigned long long)__b); } #endif static __inline__ int __ATTRS_o_ai vec_any_gt(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvcmpgtsp_p(__CR6_EQ_REV, __a, __b); #else return __builtin_altivec_vcmpgtfp_p(__CR6_EQ_REV, __a, __b); #endif } #ifdef __VSX__ static __inline__ int __ATTRS_o_ai vec_any_gt(vector double __a, vector double __b) { return __builtin_vsx_xvcmpgtdp_p(__CR6_EQ_REV, __a, __b); } #endif /* vec_any_le */ static __inline__ int __ATTRS_o_ai vec_any_le(vector signed char __a, vector signed char __b) { return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector signed char __a, vector bool char __b) { return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, __a, (vector signed char)__b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, __a, (vector unsigned char)__b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector bool char __a, vector signed char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__a, (vector unsigned char)__b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__a, __b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector bool char __a, vector bool char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__a, (vector unsigned char)__b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector short __a, vector short __b) { return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector short __a, vector bool short __b) { return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, __a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, __a, (vector unsigned short)__b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector bool short __a, vector short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__a, (vector unsigned short)__b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__a, __b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector bool short __a, vector bool short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__a, (vector unsigned short)__b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector int __a, vector int __b) { return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector int __a, vector bool int __b) { return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, __a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, __a, (vector unsigned int)__b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector bool int __a, vector int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__a, (vector unsigned int)__b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__a, __b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector bool int __a, vector bool int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__a, (vector unsigned int)__b); } #ifdef __POWER8_VECTOR__ static __inline__ int __ATTRS_o_ai vec_any_le(vector signed long long __a, vector signed long long __b) { return __builtin_altivec_vcmpgtsd_p(__CR6_LT_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector signed long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtsd_p(__CR6_LT_REV, __a, (vector signed long long)__b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector unsigned long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV, __a, (vector unsigned long long)__b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector bool long long __a, vector signed long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV, (vector unsigned long long)__a, (vector unsigned long long)__b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector bool long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV, (vector unsigned long long)__a, __b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector bool long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV, (vector unsigned long long)__a, (vector unsigned long long)__b); } #endif static __inline__ int __ATTRS_o_ai vec_any_le(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvcmpgesp_p(__CR6_EQ_REV, __b, __a); #else return __builtin_altivec_vcmpgefp_p(__CR6_EQ_REV, __b, __a); #endif } #ifdef __VSX__ static __inline__ int __ATTRS_o_ai vec_any_le(vector double __a, vector double __b) { return __builtin_vsx_xvcmpgedp_p(__CR6_EQ_REV, __b, __a); } #endif /* vec_any_lt */ static __inline__ int __ATTRS_o_ai vec_any_lt(vector signed char __a, vector signed char __b) { return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, __b, __a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector signed char __a, vector bool char __b) { return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, (vector signed char)__b, __a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, __b, __a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__b, __a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool char __a, vector signed char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__b, (vector unsigned char)__a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, __b, (vector unsigned char)__a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool char __a, vector bool char __b) { return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__b, (vector unsigned char)__a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector short __a, vector short __b) { return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, __b, __a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector short __a, vector bool short __b) { return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, (vector short)__b, __a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, __b, __a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__b, __a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool short __a, vector short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__b, (vector unsigned short)__a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, __b, (vector unsigned short)__a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool short __a, vector bool short __b) { return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__b, (vector unsigned short)__a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector int __a, vector int __b) { return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, __b, __a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector int __a, vector bool int __b) { return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, (vector int)__b, __a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, __b, __a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__b, __a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool int __a, vector int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__b, (vector unsigned int)__a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, __b, (vector unsigned int)__a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool int __a, vector bool int __b) { return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__b, (vector unsigned int)__a); } #ifdef __POWER8_VECTOR__ static __inline__ int __ATTRS_o_ai vec_any_lt(vector signed long long __a, vector signed long long __b) { return __builtin_altivec_vcmpgtsd_p(__CR6_EQ_REV, __b, __a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV, __b, __a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector signed long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtsd_p(__CR6_EQ_REV, (vector signed long long)__b, __a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector unsigned long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV, (vector unsigned long long)__b, __a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool long long __a, vector signed long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV, (vector unsigned long long)__b, (vector unsigned long long)__a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV, __b, (vector unsigned long long)__a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool long long __a, vector bool long long __b) { return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV, (vector unsigned long long)__b, (vector unsigned long long)__a); } #endif static __inline__ int __ATTRS_o_ai vec_any_lt(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvcmpgtsp_p(__CR6_EQ_REV, __b, __a); #else return __builtin_altivec_vcmpgtfp_p(__CR6_EQ_REV, __b, __a); #endif } #ifdef __VSX__ static __inline__ int __ATTRS_o_ai vec_any_lt(vector double __a, vector double __b) { return __builtin_vsx_xvcmpgtdp_p(__CR6_EQ_REV, __b, __a); } #endif /* vec_any_nan */ static __inline__ int __attribute__((__always_inline__)) vec_any_nan(vector float __a) { return __builtin_altivec_vcmpeqfp_p(__CR6_LT_REV, __a, __a); } /* vec_any_ne */ static __inline__ int __ATTRS_o_ai vec_any_ne(vector signed char __a, vector signed char __b) { return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector signed char __a, vector bool char __b) { return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector unsigned char __a, vector bool char __b) { return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector bool char __a, vector signed char __b) { return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector bool char __a, vector unsigned char __b) { return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector bool char __a, vector bool char __b) { return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)__a, (vector char)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector short __a, vector short __b) { return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector short __a, vector bool short __b) { return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, __a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector unsigned short __a, vector bool short __b) { return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector bool short __a, vector short __b) { return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector bool short __a, vector unsigned short __b) { return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector bool short __a, vector bool short __b) { return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector pixel __a, vector pixel __b) { return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)__a, (vector short)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector int __a, vector int __b) { return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector int __a, vector bool int __b) { return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, __a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)__a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector unsigned int __a, vector bool int __b) { return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)__a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector bool int __a, vector int __b) { return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)__a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector bool int __a, vector unsigned int __b) { return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)__a, (vector int)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector bool int __a, vector bool int __b) { return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)__a, (vector int)__b); } #ifdef __POWER8_VECTOR__ static __inline__ int __ATTRS_o_ai vec_any_ne(vector signed long long __a, vector signed long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_LT_REV, __a, __b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_LT_REV, (vector long long)__a, (vector long long)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector signed long long __a, vector bool long long __b) { return __builtin_altivec_vcmpequd_p(__CR6_LT_REV, __a, (vector signed long long)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector unsigned long long __a, vector bool long long __b) { return __builtin_altivec_vcmpequd_p( __CR6_LT_REV, (vector signed long long)__a, (vector signed long long)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector bool long long __a, vector signed long long __b) { return __builtin_altivec_vcmpequd_p( __CR6_LT_REV, (vector signed long long)__a, (vector signed long long)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector bool long long __a, vector unsigned long long __b) { return __builtin_altivec_vcmpequd_p( __CR6_LT_REV, (vector signed long long)__a, (vector signed long long)__b); } static __inline__ int __ATTRS_o_ai vec_any_ne(vector bool long long __a, vector bool long long __b) { return __builtin_altivec_vcmpequd_p( __CR6_LT_REV, (vector signed long long)__a, (vector signed long long)__b); } #endif static __inline__ int __ATTRS_o_ai vec_any_ne(vector float __a, vector float __b) { #ifdef __VSX__ return __builtin_vsx_xvcmpeqsp_p(__CR6_LT_REV, __a, __b); #else return __builtin_altivec_vcmpeqfp_p(__CR6_LT_REV, __a, __b); #endif } #ifdef __VSX__ static __inline__ int __ATTRS_o_ai vec_any_ne(vector double __a, vector double __b) { return __builtin_vsx_xvcmpeqdp_p(__CR6_LT_REV, __a, __b); } #endif /* vec_any_nge */ static __inline__ int __attribute__((__always_inline__)) vec_any_nge(vector float __a, vector float __b) { return __builtin_altivec_vcmpgefp_p(__CR6_LT_REV, __a, __b); } /* vec_any_ngt */ static __inline__ int __attribute__((__always_inline__)) vec_any_ngt(vector float __a, vector float __b) { return __builtin_altivec_vcmpgtfp_p(__CR6_LT_REV, __a, __b); } /* vec_any_nle */ static __inline__ int __attribute__((__always_inline__)) vec_any_nle(vector float __a, vector float __b) { return __builtin_altivec_vcmpgefp_p(__CR6_LT_REV, __b, __a); } /* vec_any_nlt */ static __inline__ int __attribute__((__always_inline__)) vec_any_nlt(vector float __a, vector float __b) { return __builtin_altivec_vcmpgtfp_p(__CR6_LT_REV, __b, __a); } /* vec_any_numeric */ static __inline__ int __attribute__((__always_inline__)) vec_any_numeric(vector float __a) { return __builtin_altivec_vcmpeqfp_p(__CR6_EQ_REV, __a, __a); } /* vec_any_out */ static __inline__ int __attribute__((__always_inline__)) vec_any_out(vector float __a, vector float __b) { return __builtin_altivec_vcmpbfp_p(__CR6_EQ_REV, __a, __b); } /* Power 8 Crypto functions Note: We diverge from the current GCC implementation with regard to cryptography and related functions as follows: - Only the SHA and AES instructions and builtins are disabled by -mno-crypto - The remaining ones are only available on Power8 and up so require -mpower8-vector The justification for this is that export requirements require that Category:Vector.Crypto is optional (i.e. compliant hardware may not provide support). As a result, we need to be able to turn off support for those. The remaining ones (currently controlled by -mcrypto for GCC) still need to be provided on compliant hardware even if Vector.Crypto is not provided. */ #ifdef __CRYPTO__ #define vec_sbox_be __builtin_altivec_crypto_vsbox #define vec_cipher_be __builtin_altivec_crypto_vcipher #define vec_cipherlast_be __builtin_altivec_crypto_vcipherlast #define vec_ncipher_be __builtin_altivec_crypto_vncipher #define vec_ncipherlast_be __builtin_altivec_crypto_vncipherlast static __inline__ vector unsigned long long __attribute__((__always_inline__)) __builtin_crypto_vsbox(vector unsigned long long __a) { return __builtin_altivec_crypto_vsbox(__a); } static __inline__ vector unsigned long long __attribute__((__always_inline__)) __builtin_crypto_vcipher(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_crypto_vcipher(__a, __b); } static __inline__ vector unsigned long long __attribute__((__always_inline__)) __builtin_crypto_vcipherlast(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_crypto_vcipherlast(__a, __b); } static __inline__ vector unsigned long long __attribute__((__always_inline__)) __builtin_crypto_vncipher(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_crypto_vncipher(__a, __b); } static __inline__ vector unsigned long long __attribute__((__always_inline__)) __builtin_crypto_vncipherlast(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_crypto_vncipherlast(__a, __b); } #define __builtin_crypto_vshasigmad __builtin_altivec_crypto_vshasigmad #define __builtin_crypto_vshasigmaw __builtin_altivec_crypto_vshasigmaw #define vec_shasigma_be(X, Y, Z) \ _Generic((X), vector unsigned int \ : __builtin_crypto_vshasigmaw, vector unsigned long long \ : __builtin_crypto_vshasigmad)((X), (Y), (Z)) #endif #ifdef __POWER8_VECTOR__ static __inline__ vector bool char __ATTRS_o_ai vec_permxor(vector bool char __a, vector bool char __b, vector bool char __c) { return __builtin_altivec_crypto_vpermxor(__a, __b, __c); } static __inline__ vector signed char __ATTRS_o_ai vec_permxor(vector signed char __a, vector signed char __b, vector signed char __c) { return __builtin_altivec_crypto_vpermxor(__a, __b, __c); } static __inline__ vector unsigned char __ATTRS_o_ai vec_permxor(vector unsigned char __a, vector unsigned char __b, vector unsigned char __c) { return __builtin_altivec_crypto_vpermxor(__a, __b, __c); } static __inline__ vector unsigned char __ATTRS_o_ai __builtin_crypto_vpermxor(vector unsigned char __a, vector unsigned char __b, vector unsigned char __c) { return __builtin_altivec_crypto_vpermxor(__a, __b, __c); } static __inline__ vector unsigned short __ATTRS_o_ai __builtin_crypto_vpermxor(vector unsigned short __a, vector unsigned short __b, vector unsigned short __c) { return (vector unsigned short)__builtin_altivec_crypto_vpermxor( (vector unsigned char)__a, (vector unsigned char)__b, (vector unsigned char)__c); } static __inline__ vector unsigned int __ATTRS_o_ai __builtin_crypto_vpermxor( vector unsigned int __a, vector unsigned int __b, vector unsigned int __c) { return (vector unsigned int)__builtin_altivec_crypto_vpermxor( (vector unsigned char)__a, (vector unsigned char)__b, (vector unsigned char)__c); } static __inline__ vector unsigned long long __ATTRS_o_ai __builtin_crypto_vpermxor(vector unsigned long long __a, vector unsigned long long __b, vector unsigned long long __c) { return (vector unsigned long long)__builtin_altivec_crypto_vpermxor( (vector unsigned char)__a, (vector unsigned char)__b, (vector unsigned char)__c); } static __inline__ vector unsigned char __ATTRS_o_ai __builtin_crypto_vpmsumb(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_crypto_vpmsumb(__a, __b); } static __inline__ vector unsigned short __ATTRS_o_ai __builtin_crypto_vpmsumb(vector unsigned short __a, vector unsigned short __b) { return __builtin_altivec_crypto_vpmsumh(__a, __b); } static __inline__ vector unsigned int __ATTRS_o_ai __builtin_crypto_vpmsumb(vector unsigned int __a, vector unsigned int __b) { return __builtin_altivec_crypto_vpmsumw(__a, __b); } static __inline__ vector unsigned long long __ATTRS_o_ai __builtin_crypto_vpmsumb(vector unsigned long long __a, vector unsigned long long __b) { return __builtin_altivec_crypto_vpmsumd(__a, __b); } static __inline__ vector signed char __ATTRS_o_ai vec_vgbbd(vector signed char __a) { return __builtin_altivec_vgbbd((vector unsigned char)__a); } #define vec_pmsum_be __builtin_crypto_vpmsumb #define vec_gb __builtin_altivec_vgbbd static __inline__ vector unsigned char __ATTRS_o_ai vec_vgbbd(vector unsigned char __a) { return __builtin_altivec_vgbbd(__a); } static __inline__ vector long long __ATTRS_o_ai vec_vbpermq(vector signed char __a, vector signed char __b) { return __builtin_altivec_vbpermq((vector unsigned char)__a, (vector unsigned char)__b); } static __inline__ vector long long __ATTRS_o_ai vec_vbpermq(vector unsigned char __a, vector unsigned char __b) { return __builtin_altivec_vbpermq(__a, __b); } #ifdef __powerpc64__ static __inline__ vector unsigned long long __attribute__((__always_inline__)) vec_bperm(vector unsigned __int128 __a, vector unsigned char __b) { return __builtin_altivec_vbpermq((vector unsigned char)__a, (vector unsigned char)__b); } #endif #endif /* vec_reve */ static inline __ATTRS_o_ai vector bool char vec_reve(vector bool char __a) { return __builtin_shufflevector(__a, __a, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); } static inline __ATTRS_o_ai vector signed char vec_reve(vector signed char __a) { return __builtin_shufflevector(__a, __a, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); } static inline __ATTRS_o_ai vector unsigned char vec_reve(vector unsigned char __a) { return __builtin_shufflevector(__a, __a, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); } static inline __ATTRS_o_ai vector bool int vec_reve(vector bool int __a) { return __builtin_shufflevector(__a, __a, 3, 2, 1, 0); } static inline __ATTRS_o_ai vector signed int vec_reve(vector signed int __a) { return __builtin_shufflevector(__a, __a, 3, 2, 1, 0); } static inline __ATTRS_o_ai vector unsigned int vec_reve(vector unsigned int __a) { return __builtin_shufflevector(__a, __a, 3, 2, 1, 0); } static inline __ATTRS_o_ai vector bool short vec_reve(vector bool short __a) { return __builtin_shufflevector(__a, __a, 7, 6, 5, 4, 3, 2, 1, 0); } static inline __ATTRS_o_ai vector signed short vec_reve(vector signed short __a) { return __builtin_shufflevector(__a, __a, 7, 6, 5, 4, 3, 2, 1, 0); } static inline __ATTRS_o_ai vector unsigned short vec_reve(vector unsigned short __a) { return __builtin_shufflevector(__a, __a, 7, 6, 5, 4, 3, 2, 1, 0); } static inline __ATTRS_o_ai vector float vec_reve(vector float __a) { return __builtin_shufflevector(__a, __a, 3, 2, 1, 0); } #ifdef __VSX__ static inline __ATTRS_o_ai vector bool long long vec_reve(vector bool long long __a) { return __builtin_shufflevector(__a, __a, 1, 0); } static inline __ATTRS_o_ai vector signed long long vec_reve(vector signed long long __a) { return __builtin_shufflevector(__a, __a, 1, 0); } static inline __ATTRS_o_ai vector unsigned long long vec_reve(vector unsigned long long __a) { return __builtin_shufflevector(__a, __a, 1, 0); } static inline __ATTRS_o_ai vector double vec_reve(vector double __a) { return __builtin_shufflevector(__a, __a, 1, 0); } #endif /* vec_revb */ static __inline__ vector bool char __ATTRS_o_ai vec_revb(vector bool char __a) { return __a; } static __inline__ vector signed char __ATTRS_o_ai vec_revb(vector signed char __a) { return __a; } static __inline__ vector unsigned char __ATTRS_o_ai vec_revb(vector unsigned char __a) { return __a; } static __inline__ vector bool short __ATTRS_o_ai vec_revb(vector bool short __a) { vector unsigned char __indices = { 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14 }; return vec_perm(__a, __a, __indices); } static __inline__ vector signed short __ATTRS_o_ai vec_revb(vector signed short __a) { vector unsigned char __indices = { 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14 }; return vec_perm(__a, __a, __indices); } static __inline__ vector unsigned short __ATTRS_o_ai vec_revb(vector unsigned short __a) { vector unsigned char __indices = { 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14 }; return vec_perm(__a, __a, __indices); } static __inline__ vector bool int __ATTRS_o_ai vec_revb(vector bool int __a) { vector unsigned char __indices = { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 }; return vec_perm(__a, __a, __indices); } static __inline__ vector signed int __ATTRS_o_ai vec_revb(vector signed int __a) { vector unsigned char __indices = { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 }; return vec_perm(__a, __a, __indices); } static __inline__ vector unsigned int __ATTRS_o_ai vec_revb(vector unsigned int __a) { vector unsigned char __indices = { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 }; return vec_perm(__a, __a, __indices); } static __inline__ vector float __ATTRS_o_ai vec_revb(vector float __a) { vector unsigned char __indices = { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 }; return vec_perm(__a, __a, __indices); } #ifdef __VSX__ static __inline__ vector bool long long __ATTRS_o_ai vec_revb(vector bool long long __a) { vector unsigned char __indices = { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 }; return vec_perm(__a, __a, __indices); } static __inline__ vector signed long long __ATTRS_o_ai vec_revb(vector signed long long __a) { vector unsigned char __indices = { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 }; return vec_perm(__a, __a, __indices); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_revb(vector unsigned long long __a) { vector unsigned char __indices = { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 }; return vec_perm(__a, __a, __indices); } static __inline__ vector double __ATTRS_o_ai vec_revb(vector double __a) { vector unsigned char __indices = { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 }; return vec_perm(__a, __a, __indices); } #endif /* End __VSX__ */ #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) static __inline__ vector signed __int128 __ATTRS_o_ai vec_revb(vector signed __int128 __a) { vector unsigned char __indices = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; return (vector signed __int128)vec_perm((vector signed int)__a, (vector signed int)__a, __indices); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_revb(vector unsigned __int128 __a) { vector unsigned char __indices = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; return (vector unsigned __int128)vec_perm((vector signed int)__a, (vector signed int)__a, __indices); } #endif /* END __POWER8_VECTOR__ && __powerpc64__ */ /* vec_xl */ +typedef vector signed char unaligned_vec_schar __attribute__((aligned(1))); +typedef vector unsigned char unaligned_vec_uchar __attribute__((aligned(1))); +typedef vector signed short unaligned_vec_sshort __attribute__((aligned(1))); +typedef vector unsigned short unaligned_vec_ushort __attribute__((aligned(1))); +typedef vector signed int unaligned_vec_sint __attribute__((aligned(1))); +typedef vector unsigned int unaligned_vec_uint __attribute__((aligned(1))); +typedef vector float unaligned_vec_float __attribute__((aligned(1))); + static inline __ATTRS_o_ai vector signed char vec_xl(signed long long __offset, signed char *__ptr) { - return *(vector signed char *)(__ptr + __offset); + return *(unaligned_vec_schar *)(__ptr + __offset); } static inline __ATTRS_o_ai vector unsigned char vec_xl(signed long long __offset, unsigned char *__ptr) { - return *(vector unsigned char *)(__ptr + __offset); + return *(unaligned_vec_uchar*)(__ptr + __offset); } static inline __ATTRS_o_ai vector signed short vec_xl(signed long long __offset, signed short *__ptr) { - return *(vector signed short *)(__ptr + __offset); + return *(unaligned_vec_sshort *)(__ptr + __offset); } static inline __ATTRS_o_ai vector unsigned short vec_xl(signed long long __offset, unsigned short *__ptr) { - return *(vector unsigned short *)(__ptr + __offset); + return *(unaligned_vec_ushort *)(__ptr + __offset); } static inline __ATTRS_o_ai vector signed int vec_xl(signed long long __offset, signed int *__ptr) { - return *(vector signed int *)(__ptr + __offset); + return *(unaligned_vec_sint *)(__ptr + __offset); } static inline __ATTRS_o_ai vector unsigned int vec_xl(signed long long __offset, unsigned int *__ptr) { - return *(vector unsigned int *)(__ptr + __offset); + return *(unaligned_vec_uint *)(__ptr + __offset); } static inline __ATTRS_o_ai vector float vec_xl(signed long long __offset, float *__ptr) { - return *(vector float *)(__ptr + __offset); + return *(unaligned_vec_float *)(__ptr + __offset); } #ifdef __VSX__ +typedef vector signed long long unaligned_vec_sll __attribute__((aligned(1))); +typedef vector unsigned long long unaligned_vec_ull __attribute__((aligned(1))); +typedef vector double unaligned_vec_double __attribute__((aligned(1))); + static inline __ATTRS_o_ai vector signed long long vec_xl(signed long long __offset, signed long long *__ptr) { - return *(vector signed long long *)(__ptr + __offset); + return *(unaligned_vec_sll *)(__ptr + __offset); } static inline __ATTRS_o_ai vector unsigned long long vec_xl(signed long long __offset, unsigned long long *__ptr) { - return *(vector unsigned long long *)(__ptr + __offset); + return *(unaligned_vec_ull *)(__ptr + __offset); } static inline __ATTRS_o_ai vector double vec_xl(signed long long __offset, double *__ptr) { - return *(vector double *)(__ptr + __offset); + return *(unaligned_vec_double *)(__ptr + __offset); } #endif #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) +typedef vector signed __int128 unaligned_vec_si128 __attribute__((aligned(1))); +typedef vector unsigned __int128 unaligned_vec_ui128 + __attribute__((aligned(1))); static inline __ATTRS_o_ai vector signed __int128 vec_xl(signed long long __offset, signed __int128 *__ptr) { - return *(vector signed __int128 *)(__ptr + __offset); + return *(unaligned_vec_si128 *)(__ptr + __offset); } static inline __ATTRS_o_ai vector unsigned __int128 vec_xl(signed long long __offset, unsigned __int128 *__ptr) { - return *(vector unsigned __int128 *)(__ptr + __offset); + return *(unaligned_vec_ui128 *)(__ptr + __offset); } #endif /* vec_xl_be */ #ifdef __LITTLE_ENDIAN__ static __inline__ vector signed char __ATTRS_o_ai vec_xl_be(signed long long __offset, signed char *__ptr) { vector signed char __vec = __builtin_vsx_lxvd2x_be(__offset, __ptr); return __builtin_shufflevector(__vec, __vec, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8); } static __inline__ vector unsigned char __ATTRS_o_ai vec_xl_be(signed long long __offset, unsigned char *__ptr) { vector unsigned char __vec = __builtin_vsx_lxvd2x_be(__offset, __ptr); return __builtin_shufflevector(__vec, __vec, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8); } static __inline__ vector signed short __ATTRS_o_ai vec_xl_be(signed long long __offset, signed short *__ptr) { vector signed short __vec = __builtin_vsx_lxvd2x_be(__offset, __ptr); return __builtin_shufflevector(__vec, __vec, 3, 2, 1, 0, 7, 6, 5, 4); } static __inline__ vector unsigned short __ATTRS_o_ai vec_xl_be(signed long long __offset, unsigned short *__ptr) { vector unsigned short __vec = __builtin_vsx_lxvd2x_be(__offset, __ptr); return __builtin_shufflevector(__vec, __vec, 3, 2, 1, 0, 7, 6, 5, 4); } static __inline__ vector signed int __ATTRS_o_ai vec_xl_be(signed long long __offset, signed int *__ptr) { return (vector signed int)__builtin_vsx_lxvw4x_be(__offset, __ptr); } static __inline__ vector unsigned int __ATTRS_o_ai vec_xl_be(signed long long __offset, unsigned int *__ptr) { return (vector unsigned int)__builtin_vsx_lxvw4x_be(__offset, __ptr); } static __inline__ vector float __ATTRS_o_ai vec_xl_be(signed long long __offset, float *__ptr) { return (vector float)__builtin_vsx_lxvw4x_be(__offset, __ptr); } #ifdef __VSX__ static __inline__ vector signed long long __ATTRS_o_ai vec_xl_be(signed long long __offset, signed long long *__ptr) { return (vector signed long long)__builtin_vsx_lxvd2x_be(__offset, __ptr); } static __inline__ vector unsigned long long __ATTRS_o_ai vec_xl_be(signed long long __offset, unsigned long long *__ptr) { return (vector unsigned long long)__builtin_vsx_lxvd2x_be(__offset, __ptr); } static __inline__ vector double __ATTRS_o_ai vec_xl_be(signed long long __offset, double *__ptr) { return (vector double)__builtin_vsx_lxvd2x_be(__offset, __ptr); } #endif #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) static __inline__ vector signed __int128 __ATTRS_o_ai vec_xl_be(signed long long __offset, signed __int128 *__ptr) { return vec_xl(__offset, __ptr); } static __inline__ vector unsigned __int128 __ATTRS_o_ai vec_xl_be(signed long long __offset, unsigned __int128 *__ptr) { return vec_xl(__offset, __ptr); } #endif #else #define vec_xl_be vec_xl #endif /* vec_xst */ static inline __ATTRS_o_ai void vec_xst(vector signed char __vec, signed long long __offset, signed char *__ptr) { - *(vector signed char *)(__ptr + __offset) = __vec; + *(unaligned_vec_schar *)(__ptr + __offset) = __vec; } static inline __ATTRS_o_ai void vec_xst(vector unsigned char __vec, signed long long __offset, unsigned char *__ptr) { - *(vector unsigned char *)(__ptr + __offset) = __vec; + *(unaligned_vec_uchar *)(__ptr + __offset) = __vec; } static inline __ATTRS_o_ai void vec_xst(vector signed short __vec, signed long long __offset, signed short *__ptr) { - *(vector signed short *)(__ptr + __offset) = __vec; + *(unaligned_vec_sshort *)(__ptr + __offset) = __vec; } static inline __ATTRS_o_ai void vec_xst(vector unsigned short __vec, signed long long __offset, unsigned short *__ptr) { - *(vector unsigned short *)(__ptr + __offset) = __vec; + *(unaligned_vec_ushort *)(__ptr + __offset) = __vec; } static inline __ATTRS_o_ai void vec_xst(vector signed int __vec, signed long long __offset, signed int *__ptr) { - *(vector signed int *)(__ptr + __offset) = __vec; + *(unaligned_vec_sint *)(__ptr + __offset) = __vec; } static inline __ATTRS_o_ai void vec_xst(vector unsigned int __vec, signed long long __offset, unsigned int *__ptr) { - *(vector unsigned int *)(__ptr + __offset) = __vec; + *(unaligned_vec_uint *)(__ptr + __offset) = __vec; } static inline __ATTRS_o_ai void vec_xst(vector float __vec, signed long long __offset, float *__ptr) { - *(vector float *)(__ptr + __offset) = __vec; + *(unaligned_vec_float *)(__ptr + __offset) = __vec; } #ifdef __VSX__ static inline __ATTRS_o_ai void vec_xst(vector signed long long __vec, signed long long __offset, signed long long *__ptr) { - *(vector signed long long *)(__ptr + __offset) = __vec; + *(unaligned_vec_sll *)(__ptr + __offset) = __vec; } static inline __ATTRS_o_ai void vec_xst(vector unsigned long long __vec, signed long long __offset, unsigned long long *__ptr) { - *(vector unsigned long long *)(__ptr + __offset) = __vec; + *(unaligned_vec_ull *)(__ptr + __offset) = __vec; } static inline __ATTRS_o_ai void vec_xst(vector double __vec, signed long long __offset, double *__ptr) { - *(vector double *)(__ptr + __offset) = __vec; + *(unaligned_vec_double *)(__ptr + __offset) = __vec; } #endif #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) static inline __ATTRS_o_ai void vec_xst(vector signed __int128 __vec, signed long long __offset, signed __int128 *__ptr) { - *(vector signed __int128 *)(__ptr + __offset) = __vec; + *(unaligned_vec_si128 *)(__ptr + __offset) = __vec; } static inline __ATTRS_o_ai void vec_xst(vector unsigned __int128 __vec, signed long long __offset, unsigned __int128 *__ptr) { - *(vector unsigned __int128 *)(__ptr + __offset) = __vec; + *(unaligned_vec_ui128 *)(__ptr + __offset) = __vec; } #endif /* vec_xst_be */ #ifdef __LITTLE_ENDIAN__ static __inline__ void __ATTRS_o_ai vec_xst_be(vector signed char __vec, signed long long __offset, signed char *__ptr) { vector signed char __tmp = __builtin_shufflevector(__vec, __vec, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8); __builtin_vsx_stxvd2x_be(__tmp, __offset, __ptr); } static __inline__ void __ATTRS_o_ai vec_xst_be(vector unsigned char __vec, signed long long __offset, unsigned char *__ptr) { vector unsigned char __tmp = __builtin_shufflevector(__vec, __vec, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8); __builtin_vsx_stxvd2x_be(__tmp, __offset, __ptr); } static __inline__ void __ATTRS_o_ai vec_xst_be(vector signed short __vec, signed long long __offset, signed short *__ptr) { vector signed short __tmp = __builtin_shufflevector(__vec, __vec, 3, 2, 1, 0, 7, 6, 5, 4); __builtin_vsx_stxvd2x_be(__tmp, __offset, __ptr); } static __inline__ void __ATTRS_o_ai vec_xst_be(vector unsigned short __vec, signed long long __offset, unsigned short *__ptr) { vector unsigned short __tmp = __builtin_shufflevector(__vec, __vec, 3, 2, 1, 0, 7, 6, 5, 4); __builtin_vsx_stxvd2x_be(__tmp, __offset, __ptr); } static __inline__ void __ATTRS_o_ai vec_xst_be(vector signed int __vec, signed long long __offset, signed int *__ptr) { __builtin_vsx_stxvw4x_be(__vec, __offset, __ptr); } static __inline__ void __ATTRS_o_ai vec_xst_be(vector unsigned int __vec, signed long long __offset, unsigned int *__ptr) { __builtin_vsx_stxvw4x_be(__vec, __offset, __ptr); } static __inline__ void __ATTRS_o_ai vec_xst_be(vector float __vec, signed long long __offset, float *__ptr) { __builtin_vsx_stxvw4x_be(__vec, __offset, __ptr); } #ifdef __VSX__ static __inline__ void __ATTRS_o_ai vec_xst_be(vector signed long long __vec, signed long long __offset, signed long long *__ptr) { __builtin_vsx_stxvd2x_be(__vec, __offset, __ptr); } static __inline__ void __ATTRS_o_ai vec_xst_be(vector unsigned long long __vec, signed long long __offset, unsigned long long *__ptr) { __builtin_vsx_stxvd2x_be(__vec, __offset, __ptr); } static __inline__ void __ATTRS_o_ai vec_xst_be(vector double __vec, signed long long __offset, double *__ptr) { __builtin_vsx_stxvd2x_be(__vec, __offset, __ptr); } #endif #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) static __inline__ void __ATTRS_o_ai vec_xst_be(vector signed __int128 __vec, signed long long __offset, signed __int128 *__ptr) { vec_xst(__vec, __offset, __ptr); } static __inline__ void __ATTRS_o_ai vec_xst_be(vector unsigned __int128 __vec, signed long long __offset, unsigned __int128 *__ptr) { vec_xst(__vec, __offset, __ptr); } #endif #else #define vec_xst_be vec_xst #endif #ifdef __POWER9_VECTOR__ #define vec_test_data_class(__a, __b) \ _Generic((__a), \ vector float: \ (vector bool int)__builtin_vsx_xvtstdcsp((__a), (__b)), \ vector double: \ (vector bool long long)__builtin_vsx_xvtstdcdp((__a), (__b)) \ ) #endif /* #ifdef __POWER9_VECTOR__ */ static vector float __ATTRS_o_ai vec_neg(vector float __a) { return -__a; } #ifdef __VSX__ static vector double __ATTRS_o_ai vec_neg(vector double __a) { return -__a; } #endif #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) static vector long long __ATTRS_o_ai vec_neg(vector long long __a) { return -__a; } #endif static vector signed int __ATTRS_o_ai vec_neg(vector signed int __a) { return -__a; } static vector signed short __ATTRS_o_ai vec_neg(vector signed short __a) { return -__a; } static vector signed char __ATTRS_o_ai vec_neg(vector signed char __a) { return -__a; } static vector float __ATTRS_o_ai vec_nabs(vector float __a) { return - vec_abs(__a); } #ifdef __VSX__ static vector double __ATTRS_o_ai vec_nabs(vector double __a) { return - vec_abs(__a); } #endif #if defined(__POWER8_VECTOR__) && defined(__powerpc64__) static vector long long __ATTRS_o_ai vec_nabs(vector long long __a) { return __builtin_altivec_vminsd(__a, -__a); } #endif static vector signed int __ATTRS_o_ai vec_nabs(vector signed int __a) { return __builtin_altivec_vminsw(__a, -__a); } static vector signed short __ATTRS_o_ai vec_nabs(vector signed short __a) { return __builtin_altivec_vminsh(__a, -__a); } static vector signed char __ATTRS_o_ai vec_nabs(vector signed char __a) { return __builtin_altivec_vminsb(__a, -__a); } #undef __ATTRS_o_ai #endif /* __ALTIVEC_H */ Index: vendor/clang/dist-release_70/lib/Sema/SemaInit.cpp =================================================================== --- vendor/clang/dist-release_70/lib/Sema/SemaInit.cpp (revision 341366) +++ vendor/clang/dist-release_70/lib/Sema/SemaInit.cpp (revision 341367) @@ -1,9290 +1,9293 @@ //===--- SemaInit.cpp - Semantic Analysis for Initializers ----------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements semantic analysis for initializers. // //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/Designator.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" using namespace clang; //===----------------------------------------------------------------------===// // Sema Initialization Checking //===----------------------------------------------------------------------===// /// Check whether T is compatible with a wide character type (wchar_t, /// char16_t or char32_t). static bool IsWideCharCompatible(QualType T, ASTContext &Context) { if (Context.typesAreCompatible(Context.getWideCharType(), T)) return true; if (Context.getLangOpts().CPlusPlus || Context.getLangOpts().C11) { return Context.typesAreCompatible(Context.Char16Ty, T) || Context.typesAreCompatible(Context.Char32Ty, T); } return false; } enum StringInitFailureKind { SIF_None, SIF_NarrowStringIntoWideChar, SIF_WideStringIntoChar, SIF_IncompatWideStringIntoWideChar, SIF_UTF8StringIntoPlainChar, SIF_PlainStringIntoUTF8Char, SIF_Other }; /// Check whether the array of type AT can be initialized by the Init /// expression by means of string initialization. Returns SIF_None if so, /// otherwise returns a StringInitFailureKind that describes why the /// initialization would not work. static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, ASTContext &Context) { if (!isa(AT) && !isa(AT)) return SIF_Other; // See if this is a string literal or @encode. Init = Init->IgnoreParens(); // Handle @encode, which is a narrow string. if (isa(Init) && AT->getElementType()->isCharType()) return SIF_None; // Otherwise we can only handle string literals. StringLiteral *SL = dyn_cast(Init); if (!SL) return SIF_Other; const QualType ElemTy = Context.getCanonicalType(AT->getElementType()).getUnqualifiedType(); switch (SL->getKind()) { case StringLiteral::UTF8: // char8_t array can be initialized with a UTF-8 string. if (ElemTy->isChar8Type()) return SIF_None; LLVM_FALLTHROUGH; case StringLiteral::Ascii: // char array can be initialized with a narrow string. // Only allow char x[] = "foo"; not char x[] = L"foo"; if (ElemTy->isCharType()) return (SL->getKind() == StringLiteral::UTF8 && Context.getLangOpts().Char8) ? SIF_UTF8StringIntoPlainChar : SIF_None; if (ElemTy->isChar8Type()) return SIF_PlainStringIntoUTF8Char; if (IsWideCharCompatible(ElemTy, Context)) return SIF_NarrowStringIntoWideChar; return SIF_Other; // C99 6.7.8p15 (with correction from DR343), or C11 6.7.9p15: // "An array with element type compatible with a qualified or unqualified // version of wchar_t, char16_t, or char32_t may be initialized by a wide // string literal with the corresponding encoding prefix (L, u, or U, // respectively), optionally enclosed in braces. case StringLiteral::UTF16: if (Context.typesAreCompatible(Context.Char16Ty, ElemTy)) return SIF_None; if (ElemTy->isCharType() || ElemTy->isChar8Type()) return SIF_WideStringIntoChar; if (IsWideCharCompatible(ElemTy, Context)) return SIF_IncompatWideStringIntoWideChar; return SIF_Other; case StringLiteral::UTF32: if (Context.typesAreCompatible(Context.Char32Ty, ElemTy)) return SIF_None; if (ElemTy->isCharType() || ElemTy->isChar8Type()) return SIF_WideStringIntoChar; if (IsWideCharCompatible(ElemTy, Context)) return SIF_IncompatWideStringIntoWideChar; return SIF_Other; case StringLiteral::Wide: if (Context.typesAreCompatible(Context.getWideCharType(), ElemTy)) return SIF_None; if (ElemTy->isCharType() || ElemTy->isChar8Type()) return SIF_WideStringIntoChar; if (IsWideCharCompatible(ElemTy, Context)) return SIF_IncompatWideStringIntoWideChar; return SIF_Other; } llvm_unreachable("missed a StringLiteral kind?"); } static StringInitFailureKind IsStringInit(Expr *init, QualType declType, ASTContext &Context) { const ArrayType *arrayType = Context.getAsArrayType(declType); if (!arrayType) return SIF_Other; return IsStringInit(init, arrayType, Context); } /// Update the type of a string literal, including any surrounding parentheses, /// to match the type of the object which it is initializing. static void updateStringLiteralType(Expr *E, QualType Ty) { while (true) { E->setType(Ty); if (isa(E) || isa(E)) break; else if (ParenExpr *PE = dyn_cast(E)) E = PE->getSubExpr(); else if (UnaryOperator *UO = dyn_cast(E)) E = UO->getSubExpr(); else if (GenericSelectionExpr *GSE = dyn_cast(E)) E = GSE->getResultExpr(); else llvm_unreachable("unexpected expr in string literal init"); } } static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, Sema &S) { // Get the length of the string as parsed. auto *ConstantArrayTy = cast(Str->getType()->getAsArrayTypeUnsafe()); uint64_t StrLength = ConstantArrayTy->getSize().getZExtValue(); if (const IncompleteArrayType *IAT = dyn_cast(AT)) { // C99 6.7.8p14. We have an array of character type with unknown size // being initialized to a string literal. llvm::APInt ConstVal(32, StrLength); // Return a new array type (C99 6.7.8p22). DeclT = S.Context.getConstantArrayType(IAT->getElementType(), ConstVal, ArrayType::Normal, 0); updateStringLiteralType(Str, DeclT); return; } const ConstantArrayType *CAT = cast(AT); // We have an array of character type with known size. However, // the size may be smaller or larger than the string we are initializing. // FIXME: Avoid truncation for 64-bit length strings. if (S.getLangOpts().CPlusPlus) { if (StringLiteral *SL = dyn_cast(Str->IgnoreParens())) { // For Pascal strings it's OK to strip off the terminating null character, // so the example below is valid: // // unsigned char a[2] = "\pa"; if (SL->isPascal()) StrLength--; } // [dcl.init.string]p2 if (StrLength > CAT->getSize().getZExtValue()) S.Diag(Str->getLocStart(), diag::err_initializer_string_for_char_array_too_long) << Str->getSourceRange(); } else { // C99 6.7.8p14. if (StrLength-1 > CAT->getSize().getZExtValue()) S.Diag(Str->getLocStart(), diag::ext_initializer_string_for_char_array_too_long) << Str->getSourceRange(); } // Set the type to the actual size that we are initializing. If we have // something like: // char x[1] = "foo"; // then this will set the string literal's type to char[1]. updateStringLiteralType(Str, DeclT); } //===----------------------------------------------------------------------===// // Semantic checking for initializer lists. //===----------------------------------------------------------------------===// namespace { /// Semantic checking for initializer lists. /// /// The InitListChecker class contains a set of routines that each /// handle the initialization of a certain kind of entity, e.g., /// arrays, vectors, struct/union types, scalars, etc. The /// InitListChecker itself performs a recursive walk of the subobject /// structure of the type to be initialized, while stepping through /// the initializer list one element at a time. The IList and Index /// parameters to each of the Check* routines contain the active /// (syntactic) initializer list and the index into that initializer /// list that represents the current initializer. Each routine is /// responsible for moving that Index forward as it consumes elements. /// /// Each Check* routine also has a StructuredList/StructuredIndex /// arguments, which contains the current "structured" (semantic) /// initializer list and the index into that initializer list where we /// are copying initializers as we map them over to the semantic /// list. Once we have completed our recursive walk of the subobject /// structure, we will have constructed a full semantic initializer /// list. /// /// C99 designators cause changes in the initializer list traversal, /// because they make the initialization "jump" into a specific /// subobject and then continue the initialization from that /// point. CheckDesignatedInitializer() recursively steps into the /// designated subobject and manages backing out the recursion to /// initialize the subobjects after the one designated. class InitListChecker { Sema &SemaRef; bool hadError; bool VerifyOnly; // no diagnostics, no structure building bool TreatUnavailableAsInvalid; // Used only in VerifyOnly mode. llvm::DenseMap SyntacticToSemantic; InitListExpr *FullyStructuredList; void CheckImplicitInitList(const InitializedEntity &Entity, InitListExpr *ParentIList, QualType T, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); void CheckExplicitInitList(const InitializedEntity &Entity, InitListExpr *IList, QualType &T, InitListExpr *StructuredList, bool TopLevelObject = false); void CheckListElementTypes(const InitializedEntity &Entity, InitListExpr *IList, QualType &DeclType, bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool TopLevelObject = false); void CheckSubElementType(const InitializedEntity &Entity, InitListExpr *IList, QualType ElemType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); void CheckComplexType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); void CheckScalarType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); void CheckReferenceType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); void CheckVectorType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); void CheckStructUnionTypes(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, CXXRecordDecl::base_class_range Bases, RecordDecl::field_iterator Field, bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool TopLevelObject = false); void CheckArrayType(const InitializedEntity &Entity, InitListExpr *IList, QualType &DeclType, llvm::APSInt elementIndex, bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); bool CheckDesignatedInitializer(const InitializedEntity &Entity, InitListExpr *IList, DesignatedInitExpr *DIE, unsigned DesigIdx, QualType &CurrentObjectType, RecordDecl::field_iterator *NextField, llvm::APSInt *NextElementIndex, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool FinishSubobjectInit, bool TopLevelObject); InitListExpr *getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, QualType CurrentObjectType, InitListExpr *StructuredList, unsigned StructuredIndex, SourceRange InitRange, bool IsFullyOverwritten = false); void UpdateStructuredListElement(InitListExpr *StructuredList, unsigned &StructuredIndex, Expr *expr); int numArrayElements(QualType DeclType); int numStructUnionElements(QualType DeclType); static ExprResult PerformEmptyInit(Sema &SemaRef, SourceLocation Loc, const InitializedEntity &Entity, bool VerifyOnly, bool TreatUnavailableAsInvalid); // Explanation on the "FillWithNoInit" mode: // // Assume we have the following definitions (Case#1): // struct P { char x[6][6]; } xp = { .x[1] = "bar" }; // struct PP { struct P lp; } l = { .lp = xp, .lp.x[1][2] = 'f' }; // // l.lp.x[1][0..1] should not be filled with implicit initializers because the // "base" initializer "xp" will provide values for them; l.lp.x[1] will be "baf". // // But if we have (Case#2): // struct PP l = { .lp = xp, .lp.x[1] = { [2] = 'f' } }; // // l.lp.x[1][0..1] are implicitly initialized and do not use values from the // "base" initializer; l.lp.x[1] will be "\0\0f\0\0\0". // // To distinguish Case#1 from Case#2, and also to avoid leaving many "holes" // in the InitListExpr, the "holes" in Case#1 are filled not with empty // initializers but with special "NoInitExpr" place holders, which tells the // CodeGen not to generate any initializers for these parts. void FillInEmptyInitForBase(unsigned Init, const CXXBaseSpecifier &Base, const InitializedEntity &ParentEntity, InitListExpr *ILE, bool &RequiresSecondPass, bool FillWithNoInit); void FillInEmptyInitForField(unsigned Init, FieldDecl *Field, const InitializedEntity &ParentEntity, InitListExpr *ILE, bool &RequiresSecondPass, bool FillWithNoInit = false); void FillInEmptyInitializations(const InitializedEntity &Entity, InitListExpr *ILE, bool &RequiresSecondPass, InitListExpr *OuterILE, unsigned OuterIndex, bool FillWithNoInit = false); bool CheckFlexibleArrayInit(const InitializedEntity &Entity, Expr *InitExpr, FieldDecl *Field, bool TopLevelObject); void CheckEmptyInitializable(const InitializedEntity &Entity, SourceLocation Loc); public: InitListChecker(Sema &S, const InitializedEntity &Entity, InitListExpr *IL, QualType &T, bool VerifyOnly, bool TreatUnavailableAsInvalid); bool HadError() { return hadError; } // Retrieves the fully-structured initializer list used for // semantic analysis and code generation. InitListExpr *getFullyStructuredList() const { return FullyStructuredList; } }; } // end anonymous namespace ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef, SourceLocation Loc, const InitializedEntity &Entity, bool VerifyOnly, bool TreatUnavailableAsInvalid) { InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc, true); MultiExprArg SubInit; Expr *InitExpr; InitListExpr DummyInitList(SemaRef.Context, Loc, None, Loc); // C++ [dcl.init.aggr]p7: // If there are fewer initializer-clauses in the list than there are // members in the aggregate, then each member not explicitly initialized // ... bool EmptyInitList = SemaRef.getLangOpts().CPlusPlus11 && Entity.getType()->getBaseElementTypeUnsafe()->isRecordType(); if (EmptyInitList) { // C++1y / DR1070: // shall be initialized [...] from an empty initializer list. // // We apply the resolution of this DR to C++11 but not C++98, since C++98 // does not have useful semantics for initialization from an init list. // We treat this as copy-initialization, because aggregate initialization // always performs copy-initialization on its elements. // // Only do this if we're initializing a class type, to avoid filling in // the initializer list where possible. InitExpr = VerifyOnly ? &DummyInitList : new (SemaRef.Context) InitListExpr(SemaRef.Context, Loc, None, Loc); InitExpr->setType(SemaRef.Context.VoidTy); SubInit = InitExpr; Kind = InitializationKind::CreateCopy(Loc, Loc); } else { // C++03: // shall be value-initialized. } InitializationSequence InitSeq(SemaRef, Entity, Kind, SubInit); // libstdc++4.6 marks the vector default constructor as explicit in // _GLIBCXX_DEBUG mode, so recover using the C++03 logic in that case. // stlport does so too. Look for std::__debug for libstdc++, and for // std:: for stlport. This is effectively a compiler-side implementation of // LWG2193. if (!InitSeq && EmptyInitList && InitSeq.getFailureKind() == InitializationSequence::FK_ExplicitConstructor) { OverloadCandidateSet::iterator Best; OverloadingResult O = InitSeq.getFailedCandidateSet() .BestViableFunction(SemaRef, Kind.getLocation(), Best); (void)O; assert(O == OR_Success && "Inconsistent overload resolution"); CXXConstructorDecl *CtorDecl = cast(Best->Function); CXXRecordDecl *R = CtorDecl->getParent(); if (CtorDecl->getMinRequiredArguments() == 0 && CtorDecl->isExplicit() && R->getDeclName() && SemaRef.SourceMgr.isInSystemHeader(CtorDecl->getLocation())) { bool IsInStd = false; for (NamespaceDecl *ND = dyn_cast(R->getDeclContext()); ND && !IsInStd; ND = dyn_cast(ND->getParent())) { if (SemaRef.getStdNamespace()->InEnclosingNamespaceSetOf(ND)) IsInStd = true; } if (IsInStd && llvm::StringSwitch(R->getName()) .Cases("basic_string", "deque", "forward_list", true) .Cases("list", "map", "multimap", "multiset", true) .Cases("priority_queue", "queue", "set", "stack", true) .Cases("unordered_map", "unordered_set", "vector", true) .Default(false)) { InitSeq.InitializeFrom( SemaRef, Entity, InitializationKind::CreateValue(Loc, Loc, Loc, true), MultiExprArg(), /*TopLevelOfInitList=*/false, TreatUnavailableAsInvalid); // Emit a warning for this. System header warnings aren't shown // by default, but people working on system headers should see it. if (!VerifyOnly) { SemaRef.Diag(CtorDecl->getLocation(), diag::warn_invalid_initializer_from_system_header); if (Entity.getKind() == InitializedEntity::EK_Member) SemaRef.Diag(Entity.getDecl()->getLocation(), diag::note_used_in_initialization_here); else if (Entity.getKind() == InitializedEntity::EK_ArrayElement) SemaRef.Diag(Loc, diag::note_used_in_initialization_here); } } } } if (!InitSeq) { if (!VerifyOnly) { InitSeq.Diagnose(SemaRef, Entity, Kind, SubInit); if (Entity.getKind() == InitializedEntity::EK_Member) SemaRef.Diag(Entity.getDecl()->getLocation(), diag::note_in_omitted_aggregate_initializer) << /*field*/1 << Entity.getDecl(); else if (Entity.getKind() == InitializedEntity::EK_ArrayElement) { bool IsTrailingArrayNewMember = Entity.getParent() && Entity.getParent()->isVariableLengthArrayNew(); SemaRef.Diag(Loc, diag::note_in_omitted_aggregate_initializer) << (IsTrailingArrayNewMember ? 2 : /*array element*/0) << Entity.getElementIndex(); } } return ExprError(); } return VerifyOnly ? ExprResult(static_cast(nullptr)) : InitSeq.Perform(SemaRef, Entity, Kind, SubInit); } void InitListChecker::CheckEmptyInitializable(const InitializedEntity &Entity, SourceLocation Loc) { assert(VerifyOnly && "CheckEmptyInitializable is only inteded for verification mode."); if (PerformEmptyInit(SemaRef, Loc, Entity, /*VerifyOnly*/true, TreatUnavailableAsInvalid).isInvalid()) hadError = true; } void InitListChecker::FillInEmptyInitForBase( unsigned Init, const CXXBaseSpecifier &Base, const InitializedEntity &ParentEntity, InitListExpr *ILE, bool &RequiresSecondPass, bool FillWithNoInit) { assert(Init < ILE->getNumInits() && "should have been expanded"); InitializedEntity BaseEntity = InitializedEntity::InitializeBase( SemaRef.Context, &Base, false, &ParentEntity); if (!ILE->getInit(Init)) { ExprResult BaseInit = FillWithNoInit ? new (SemaRef.Context) NoInitExpr(Base.getType()) : PerformEmptyInit(SemaRef, ILE->getLocEnd(), BaseEntity, /*VerifyOnly*/ false, TreatUnavailableAsInvalid); if (BaseInit.isInvalid()) { hadError = true; return; } ILE->setInit(Init, BaseInit.getAs()); } else if (InitListExpr *InnerILE = dyn_cast(ILE->getInit(Init))) { FillInEmptyInitializations(BaseEntity, InnerILE, RequiresSecondPass, ILE, Init, FillWithNoInit); } else if (DesignatedInitUpdateExpr *InnerDIUE = dyn_cast(ILE->getInit(Init))) { FillInEmptyInitializations(BaseEntity, InnerDIUE->getUpdater(), RequiresSecondPass, ILE, Init, /*FillWithNoInit =*/true); } } void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, const InitializedEntity &ParentEntity, InitListExpr *ILE, bool &RequiresSecondPass, bool FillWithNoInit) { SourceLocation Loc = ILE->getLocEnd(); unsigned NumInits = ILE->getNumInits(); InitializedEntity MemberEntity = InitializedEntity::InitializeMember(Field, &ParentEntity); if (const RecordType *RType = ILE->getType()->getAs()) if (!RType->getDecl()->isUnion()) assert(Init < NumInits && "This ILE should have been expanded"); if (Init >= NumInits || !ILE->getInit(Init)) { if (FillWithNoInit) { Expr *Filler = new (SemaRef.Context) NoInitExpr(Field->getType()); if (Init < NumInits) ILE->setInit(Init, Filler); else ILE->updateInit(SemaRef.Context, Init, Filler); return; } // C++1y [dcl.init.aggr]p7: // If there are fewer initializer-clauses in the list than there are // members in the aggregate, then each member not explicitly initialized // shall be initialized from its brace-or-equal-initializer [...] if (Field->hasInClassInitializer()) { ExprResult DIE = SemaRef.BuildCXXDefaultInitExpr(Loc, Field); if (DIE.isInvalid()) { hadError = true; return; } SemaRef.checkInitializerLifetime(MemberEntity, DIE.get()); if (Init < NumInits) ILE->setInit(Init, DIE.get()); else { ILE->updateInit(SemaRef.Context, Init, DIE.get()); RequiresSecondPass = true; } return; } if (Field->getType()->isReferenceType()) { // C++ [dcl.init.aggr]p9: // If an incomplete or empty initializer-list leaves a // member of reference type uninitialized, the program is // ill-formed. SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized) << Field->getType() << ILE->getSyntacticForm()->getSourceRange(); SemaRef.Diag(Field->getLocation(), diag::note_uninit_reference_member); hadError = true; return; } ExprResult MemberInit = PerformEmptyInit(SemaRef, Loc, MemberEntity, /*VerifyOnly*/false, TreatUnavailableAsInvalid); if (MemberInit.isInvalid()) { hadError = true; return; } if (hadError) { // Do nothing } else if (Init < NumInits) { ILE->setInit(Init, MemberInit.getAs()); } else if (!isa(MemberInit.get())) { // Empty initialization requires a constructor call, so // extend the initializer list to include the constructor // call and make a note that we'll need to take another pass // through the initializer list. ILE->updateInit(SemaRef.Context, Init, MemberInit.getAs()); RequiresSecondPass = true; } } else if (InitListExpr *InnerILE = dyn_cast(ILE->getInit(Init))) FillInEmptyInitializations(MemberEntity, InnerILE, RequiresSecondPass, ILE, Init, FillWithNoInit); else if (DesignatedInitUpdateExpr *InnerDIUE = dyn_cast(ILE->getInit(Init))) FillInEmptyInitializations(MemberEntity, InnerDIUE->getUpdater(), RequiresSecondPass, ILE, Init, /*FillWithNoInit =*/true); } /// Recursively replaces NULL values within the given initializer list /// with expressions that perform value-initialization of the /// appropriate type, and finish off the InitListExpr formation. void InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, InitListExpr *ILE, bool &RequiresSecondPass, InitListExpr *OuterILE, unsigned OuterIndex, bool FillWithNoInit) { assert((ILE->getType() != SemaRef.Context.VoidTy) && "Should not have void type"); // If this is a nested initializer list, we might have changed its contents // (and therefore some of its properties, such as instantiation-dependence) // while filling it in. Inform the outer initializer list so that its state // can be updated to match. // FIXME: We should fully build the inner initializers before constructing // the outer InitListExpr instead of mutating AST nodes after they have // been used as subexpressions of other nodes. struct UpdateOuterILEWithUpdatedInit { InitListExpr *Outer; unsigned OuterIndex; ~UpdateOuterILEWithUpdatedInit() { if (Outer) Outer->setInit(OuterIndex, Outer->getInit(OuterIndex)); } } UpdateOuterRAII = {OuterILE, OuterIndex}; // A transparent ILE is not performing aggregate initialization and should // not be filled in. if (ILE->isTransparent()) return; if (const RecordType *RType = ILE->getType()->getAs()) { const RecordDecl *RDecl = RType->getDecl(); if (RDecl->isUnion() && ILE->getInitializedFieldInUnion()) FillInEmptyInitForField(0, ILE->getInitializedFieldInUnion(), Entity, ILE, RequiresSecondPass, FillWithNoInit); else if (RDecl->isUnion() && isa(RDecl) && cast(RDecl)->hasInClassInitializer()) { for (auto *Field : RDecl->fields()) { if (Field->hasInClassInitializer()) { FillInEmptyInitForField(0, Field, Entity, ILE, RequiresSecondPass, FillWithNoInit); break; } } } else { // The fields beyond ILE->getNumInits() are default initialized, so in // order to leave them uninitialized, the ILE is expanded and the extra // fields are then filled with NoInitExpr. unsigned NumElems = numStructUnionElements(ILE->getType()); if (RDecl->hasFlexibleArrayMember()) ++NumElems; if (ILE->getNumInits() < NumElems) ILE->resizeInits(SemaRef.Context, NumElems); unsigned Init = 0; if (auto *CXXRD = dyn_cast(RDecl)) { for (auto &Base : CXXRD->bases()) { if (hadError) return; FillInEmptyInitForBase(Init, Base, Entity, ILE, RequiresSecondPass, FillWithNoInit); ++Init; } } for (auto *Field : RDecl->fields()) { if (Field->isUnnamedBitfield()) continue; if (hadError) return; FillInEmptyInitForField(Init, Field, Entity, ILE, RequiresSecondPass, FillWithNoInit); if (hadError) return; ++Init; // Only look at the first initialization of a union. if (RDecl->isUnion()) break; } } return; } QualType ElementType; InitializedEntity ElementEntity = Entity; unsigned NumInits = ILE->getNumInits(); unsigned NumElements = NumInits; if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) { ElementType = AType->getElementType(); if (const auto *CAType = dyn_cast(AType)) NumElements = CAType->getSize().getZExtValue(); // For an array new with an unknown bound, ask for one additional element // in order to populate the array filler. if (Entity.isVariableLengthArrayNew()) ++NumElements; ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); } else if (const VectorType *VType = ILE->getType()->getAs()) { ElementType = VType->getElementType(); NumElements = VType->getNumElements(); ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); } else ElementType = ILE->getType(); for (unsigned Init = 0; Init != NumElements; ++Init) { if (hadError) return; if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement || ElementEntity.getKind() == InitializedEntity::EK_VectorElement) ElementEntity.setElementIndex(Init); if (Init >= NumInits && ILE->hasArrayFiller()) return; Expr *InitExpr = (Init < NumInits ? ILE->getInit(Init) : nullptr); if (!InitExpr && Init < NumInits && ILE->hasArrayFiller()) ILE->setInit(Init, ILE->getArrayFiller()); else if (!InitExpr && !ILE->hasArrayFiller()) { Expr *Filler = nullptr; if (FillWithNoInit) Filler = new (SemaRef.Context) NoInitExpr(ElementType); else { ExprResult ElementInit = PerformEmptyInit(SemaRef, ILE->getLocEnd(), ElementEntity, /*VerifyOnly*/false, TreatUnavailableAsInvalid); if (ElementInit.isInvalid()) { hadError = true; return; } Filler = ElementInit.getAs(); } if (hadError) { // Do nothing } else if (Init < NumInits) { // For arrays, just set the expression used for value-initialization // of the "holes" in the array. if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) ILE->setArrayFiller(Filler); else ILE->setInit(Init, Filler); } else { // For arrays, just set the expression used for value-initialization // of the rest of elements and exit. if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) { ILE->setArrayFiller(Filler); return; } if (!isa(Filler) && !isa(Filler)) { // Empty initialization requires a constructor call, so // extend the initializer list to include the constructor // call and make a note that we'll need to take another pass // through the initializer list. ILE->updateInit(SemaRef.Context, Init, Filler); RequiresSecondPass = true; } } } else if (InitListExpr *InnerILE = dyn_cast_or_null(InitExpr)) FillInEmptyInitializations(ElementEntity, InnerILE, RequiresSecondPass, ILE, Init, FillWithNoInit); else if (DesignatedInitUpdateExpr *InnerDIUE = dyn_cast_or_null(InitExpr)) FillInEmptyInitializations(ElementEntity, InnerDIUE->getUpdater(), RequiresSecondPass, ILE, Init, /*FillWithNoInit =*/true); } } InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, InitListExpr *IL, QualType &T, bool VerifyOnly, bool TreatUnavailableAsInvalid) : SemaRef(S), VerifyOnly(VerifyOnly), TreatUnavailableAsInvalid(TreatUnavailableAsInvalid) { // FIXME: Check that IL isn't already the semantic form of some other // InitListExpr. If it is, we'd create a broken AST. hadError = false; FullyStructuredList = getStructuredSubobjectInit(IL, 0, T, nullptr, 0, IL->getSourceRange()); CheckExplicitInitList(Entity, IL, T, FullyStructuredList, /*TopLevelObject=*/true); if (!hadError && !VerifyOnly) { bool RequiresSecondPass = false; FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass, /*OuterILE=*/nullptr, /*OuterIndex=*/0); if (RequiresSecondPass && !hadError) FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass, nullptr, 0); } } int InitListChecker::numArrayElements(QualType DeclType) { // FIXME: use a proper constant int maxElements = 0x7FFFFFFF; if (const ConstantArrayType *CAT = SemaRef.Context.getAsConstantArrayType(DeclType)) { maxElements = static_cast(CAT->getSize().getZExtValue()); } return maxElements; } int InitListChecker::numStructUnionElements(QualType DeclType) { RecordDecl *structDecl = DeclType->getAs()->getDecl(); int InitializableMembers = 0; if (auto *CXXRD = dyn_cast(structDecl)) InitializableMembers += CXXRD->getNumBases(); for (const auto *Field : structDecl->fields()) if (!Field->isUnnamedBitfield()) ++InitializableMembers; if (structDecl->isUnion()) return std::min(InitializableMembers, 1); return InitializableMembers - structDecl->hasFlexibleArrayMember(); } /// Determine whether Entity is an entity for which it is idiomatic to elide /// the braces in aggregate initialization. static bool isIdiomaticBraceElisionEntity(const InitializedEntity &Entity) { // Recursive initialization of the one and only field within an aggregate // class is considered idiomatic. This case arises in particular for // initialization of std::array, where the C++ standard suggests the idiom of // // std::array arr = {1, 2, 3}; // // (where std::array is an aggregate struct containing a single array field. // FIXME: Should aggregate initialization of a struct with a single // base class and no members also suppress the warning? if (Entity.getKind() != InitializedEntity::EK_Member || !Entity.getParent()) return false; auto *ParentRD = Entity.getParent()->getType()->castAs()->getDecl(); if (CXXRecordDecl *CXXRD = dyn_cast(ParentRD)) if (CXXRD->getNumBases()) return false; auto FieldIt = ParentRD->field_begin(); assert(FieldIt != ParentRD->field_end() && "no fields but have initializer for member?"); return ++FieldIt == ParentRD->field_end(); } /// Check whether the range of the initializer \p ParentIList from element /// \p Index onwards can be used to initialize an object of type \p T. Update /// \p Index to indicate how many elements of the list were consumed. /// /// This also fills in \p StructuredList, from element \p StructuredIndex /// onwards, with the fully-braced, desugared form of the initialization. void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, InitListExpr *ParentIList, QualType T, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { int maxElements = 0; if (T->isArrayType()) maxElements = numArrayElements(T); else if (T->isRecordType()) maxElements = numStructUnionElements(T); else if (T->isVectorType()) maxElements = T->getAs()->getNumElements(); else llvm_unreachable("CheckImplicitInitList(): Illegal type"); if (maxElements == 0) { if (!VerifyOnly) SemaRef.Diag(ParentIList->getInit(Index)->getLocStart(), diag::err_implicit_empty_initializer); ++Index; hadError = true; return; } // Build a structured initializer list corresponding to this subobject. InitListExpr *StructuredSubobjectInitList = getStructuredSubobjectInit(ParentIList, Index, T, StructuredList, StructuredIndex, SourceRange(ParentIList->getInit(Index)->getLocStart(), ParentIList->getSourceRange().getEnd())); unsigned StructuredSubobjectInitIndex = 0; // Check the element types and build the structural subobject. unsigned StartIndex = Index; CheckListElementTypes(Entity, ParentIList, T, /*SubobjectIsDesignatorContext=*/false, Index, StructuredSubobjectInitList, StructuredSubobjectInitIndex); if (!VerifyOnly) { StructuredSubobjectInitList->setType(T); unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1); // Update the structured sub-object initializer so that it's ending // range corresponds with the end of the last initializer it used. if (EndIndex < ParentIList->getNumInits() && ParentIList->getInit(EndIndex)) { SourceLocation EndLoc = ParentIList->getInit(EndIndex)->getSourceRange().getEnd(); StructuredSubobjectInitList->setRBraceLoc(EndLoc); } // Complain about missing braces. if ((T->isArrayType() || T->isRecordType()) && !ParentIList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) && !isIdiomaticBraceElisionEntity(Entity)) { SemaRef.Diag(StructuredSubobjectInitList->getLocStart(), diag::warn_missing_braces) << StructuredSubobjectInitList->getSourceRange() << FixItHint::CreateInsertion( StructuredSubobjectInitList->getLocStart(), "{") << FixItHint::CreateInsertion( SemaRef.getLocForEndOfToken( StructuredSubobjectInitList->getLocEnd()), "}"); } } } /// Warn that \p Entity was of scalar type and was initialized by a /// single-element braced initializer list. static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity, SourceRange Braces) { // Don't warn during template instantiation. If the initialization was // non-dependent, we warned during the initial parse; otherwise, the // type might not be scalar in some uses of the template. if (S.inTemplateInstantiation()) return; unsigned DiagID = 0; switch (Entity.getKind()) { case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: case InitializedEntity::EK_Result: // Extra braces here are suspicious. DiagID = diag::warn_braces_around_scalar_init; break; case InitializedEntity::EK_Member: // Warn on aggregate initialization but not on ctor init list or // default member initializer. if (Entity.getParent()) DiagID = diag::warn_braces_around_scalar_init; break; case InitializedEntity::EK_Variable: case InitializedEntity::EK_LambdaCapture: // No warning, might be direct-list-initialization. // FIXME: Should we warn for copy-list-initialization in these cases? break; case InitializedEntity::EK_New: case InitializedEntity::EK_Temporary: case InitializedEntity::EK_CompoundLiteralInit: // No warning, braces are part of the syntax of the underlying construct. break; case InitializedEntity::EK_RelatedResult: // No warning, we already warned when initializing the result. break; case InitializedEntity::EK_Exception: case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_Binding: case InitializedEntity::EK_StmtExprResult: llvm_unreachable("unexpected braced scalar init"); } if (DiagID) { S.Diag(Braces.getBegin(), DiagID) << Braces << FixItHint::CreateRemoval(Braces.getBegin()) << FixItHint::CreateRemoval(Braces.getEnd()); } } /// Check whether the initializer \p IList (that was written with explicit /// braces) can be used to initialize an object of type \p T. /// /// This also fills in \p StructuredList with the fully-braced, desugared /// form of the initialization. void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, InitListExpr *IList, QualType &T, InitListExpr *StructuredList, bool TopLevelObject) { if (!VerifyOnly) { SyntacticToSemantic[IList] = StructuredList; StructuredList->setSyntacticForm(IList); } unsigned Index = 0, StructuredIndex = 0; CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true, Index, StructuredList, StructuredIndex, TopLevelObject); if (!VerifyOnly) { QualType ExprTy = T; if (!ExprTy->isArrayType()) ExprTy = ExprTy.getNonLValueExprType(SemaRef.Context); IList->setType(ExprTy); StructuredList->setType(ExprTy); } if (hadError) return; if (Index < IList->getNumInits()) { // We have leftover initializers if (VerifyOnly) { if (SemaRef.getLangOpts().CPlusPlus || (SemaRef.getLangOpts().OpenCL && IList->getType()->isVectorType())) { hadError = true; } return; } if (StructuredIndex == 1 && IsStringInit(StructuredList->getInit(0), T, SemaRef.Context) == SIF_None) { unsigned DK = diag::ext_excess_initializers_in_char_array_initializer; if (SemaRef.getLangOpts().CPlusPlus) { DK = diag::err_excess_initializers_in_char_array_initializer; hadError = true; } // Special-case SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK) << IList->getInit(Index)->getSourceRange(); } else if (!T->isIncompleteType()) { // Don't complain for incomplete types, since we'll get an error // elsewhere QualType CurrentObjectType = StructuredList->getType(); int initKind = CurrentObjectType->isArrayType()? 0 : CurrentObjectType->isVectorType()? 1 : CurrentObjectType->isScalarType()? 2 : CurrentObjectType->isUnionType()? 3 : 4; unsigned DK = diag::ext_excess_initializers; if (SemaRef.getLangOpts().CPlusPlus) { DK = diag::err_excess_initializers; hadError = true; } if (SemaRef.getLangOpts().OpenCL && initKind == 1) { DK = diag::err_excess_initializers; hadError = true; } SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK) << initKind << IList->getInit(Index)->getSourceRange(); } } if (!VerifyOnly && T->isScalarType() && IList->getNumInits() == 1 && !isa(IList->getInit(0))) warnBracedScalarInit(SemaRef, Entity, IList->getSourceRange()); } void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity, InitListExpr *IList, QualType &DeclType, bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool TopLevelObject) { if (DeclType->isAnyComplexType() && SubobjectIsDesignatorContext) { // Explicitly braced initializer for complex type can be real+imaginary // parts. CheckComplexType(Entity, IList, DeclType, Index, StructuredList, StructuredIndex); } else if (DeclType->isScalarType()) { CheckScalarType(Entity, IList, DeclType, Index, StructuredList, StructuredIndex); } else if (DeclType->isVectorType()) { CheckVectorType(Entity, IList, DeclType, Index, StructuredList, StructuredIndex); } else if (DeclType->isRecordType()) { assert(DeclType->isAggregateType() && "non-aggregate records should be handed in CheckSubElementType"); RecordDecl *RD = DeclType->getAs()->getDecl(); auto Bases = CXXRecordDecl::base_class_range(CXXRecordDecl::base_class_iterator(), CXXRecordDecl::base_class_iterator()); if (auto *CXXRD = dyn_cast(RD)) Bases = CXXRD->bases(); CheckStructUnionTypes(Entity, IList, DeclType, Bases, RD->field_begin(), SubobjectIsDesignatorContext, Index, StructuredList, StructuredIndex, TopLevelObject); } else if (DeclType->isArrayType()) { llvm::APSInt Zero( SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()), false); CheckArrayType(Entity, IList, DeclType, Zero, SubobjectIsDesignatorContext, Index, StructuredList, StructuredIndex); } else if (DeclType->isVoidType() || DeclType->isFunctionType()) { // This type is invalid, issue a diagnostic. ++Index; if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type) << DeclType; hadError = true; } else if (DeclType->isReferenceType()) { CheckReferenceType(Entity, IList, DeclType, Index, StructuredList, StructuredIndex); } else if (DeclType->isObjCObjectType()) { if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::err_init_objc_class) << DeclType; hadError = true; } else { if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type) << DeclType; hadError = true; } } void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, InitListExpr *IList, QualType ElemType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { Expr *expr = IList->getInit(Index); if (ElemType->isReferenceType()) return CheckReferenceType(Entity, IList, ElemType, Index, StructuredList, StructuredIndex); if (InitListExpr *SubInitList = dyn_cast(expr)) { if (SubInitList->getNumInits() == 1 && IsStringInit(SubInitList->getInit(0), ElemType, SemaRef.Context) == SIF_None) { expr = SubInitList->getInit(0); } else if (!SemaRef.getLangOpts().CPlusPlus) { InitListExpr *InnerStructuredList = getStructuredSubobjectInit(IList, Index, ElemType, StructuredList, StructuredIndex, SubInitList->getSourceRange(), true); CheckExplicitInitList(Entity, SubInitList, ElemType, InnerStructuredList); if (!hadError && !VerifyOnly) { bool RequiresSecondPass = false; FillInEmptyInitializations(Entity, InnerStructuredList, RequiresSecondPass, StructuredList, StructuredIndex); if (RequiresSecondPass && !hadError) FillInEmptyInitializations(Entity, InnerStructuredList, RequiresSecondPass, StructuredList, StructuredIndex); } ++StructuredIndex; ++Index; return; } // C++ initialization is handled later. } else if (isa(expr)) { // This happens during template instantiation when we see an InitListExpr // that we've already checked once. assert(SemaRef.Context.hasSameType(expr->getType(), ElemType) && "found implicit initialization for the wrong type"); if (!VerifyOnly) UpdateStructuredListElement(StructuredList, StructuredIndex, expr); ++Index; return; } if (SemaRef.getLangOpts().CPlusPlus) { // C++ [dcl.init.aggr]p2: // Each member is copy-initialized from the corresponding // initializer-clause. // FIXME: Better EqualLoc? InitializationKind Kind = InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation()); InitializationSequence Seq(SemaRef, Entity, Kind, expr, /*TopLevelOfInitList*/ true); // C++14 [dcl.init.aggr]p13: // If the assignment-expression can initialize a member, the member is // initialized. Otherwise [...] brace elision is assumed // // Brace elision is never performed if the element is not an // assignment-expression. if (Seq || isa(expr)) { if (!VerifyOnly) { ExprResult Result = Seq.Perform(SemaRef, Entity, Kind, expr); if (Result.isInvalid()) hadError = true; UpdateStructuredListElement(StructuredList, StructuredIndex, Result.getAs()); } else if (!Seq) hadError = true; ++Index; return; } // Fall through for subaggregate initialization } else if (ElemType->isScalarType() || ElemType->isAtomicType()) { // FIXME: Need to handle atomic aggregate types with implicit init lists. return CheckScalarType(Entity, IList, ElemType, Index, StructuredList, StructuredIndex); } else if (const ArrayType *arrayType = SemaRef.Context.getAsArrayType(ElemType)) { // arrayType can be incomplete if we're initializing a flexible // array member. There's nothing we can do with the completed // type here, though. if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) { if (!VerifyOnly) { CheckStringInit(expr, ElemType, arrayType, SemaRef); UpdateStructuredListElement(StructuredList, StructuredIndex, expr); } ++Index; return; } // Fall through for subaggregate initialization. } else { assert((ElemType->isRecordType() || ElemType->isVectorType() || ElemType->isOpenCLSpecificType()) && "Unexpected type"); // C99 6.7.8p13: // // The initializer for a structure or union object that has // automatic storage duration shall be either an initializer // list as described below, or a single expression that has // compatible structure or union type. In the latter case, the // initial value of the object, including unnamed members, is // that of the expression. ExprResult ExprRes = expr; if (SemaRef.CheckSingleAssignmentConstraints( ElemType, ExprRes, !VerifyOnly) != Sema::Incompatible) { if (ExprRes.isInvalid()) hadError = true; else { ExprRes = SemaRef.DefaultFunctionArrayLvalueConversion(ExprRes.get()); if (ExprRes.isInvalid()) hadError = true; } UpdateStructuredListElement(StructuredList, StructuredIndex, ExprRes.getAs()); ++Index; return; } ExprRes.get(); // Fall through for subaggregate initialization } // C++ [dcl.init.aggr]p12: // // [...] Otherwise, if the member is itself a non-empty // subaggregate, brace elision is assumed and the initializer is // considered for the initialization of the first member of // the subaggregate. // OpenCL vector initializer is handled elsewhere. if ((!SemaRef.getLangOpts().OpenCL && ElemType->isVectorType()) || ElemType->isAggregateType()) { CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList, StructuredIndex); ++StructuredIndex; } else { if (!VerifyOnly) { // We cannot initialize this element, so let // PerformCopyInitialization produce the appropriate diagnostic. SemaRef.PerformCopyInitialization(Entity, SourceLocation(), expr, /*TopLevelOfInitList=*/true); } hadError = true; ++Index; ++StructuredIndex; } } void InitListChecker::CheckComplexType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { assert(Index == 0 && "Index in explicit init list must be zero"); // As an extension, clang supports complex initializers, which initialize // a complex number component-wise. When an explicit initializer list for // a complex number contains two two initializers, this extension kicks in: // it exepcts the initializer list to contain two elements convertible to // the element type of the complex type. The first element initializes // the real part, and the second element intitializes the imaginary part. if (IList->getNumInits() != 2) return CheckScalarType(Entity, IList, DeclType, Index, StructuredList, StructuredIndex); // This is an extension in C. (The builtin _Complex type does not exist // in the C++ standard.) if (!SemaRef.getLangOpts().CPlusPlus && !VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::ext_complex_component_init) << IList->getSourceRange(); // Initialize the complex number. QualType elementType = DeclType->getAs()->getElementType(); InitializedEntity ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); for (unsigned i = 0; i < 2; ++i) { ElementEntity.setElementIndex(Index); CheckSubElementType(ElementEntity, IList, elementType, Index, StructuredList, StructuredIndex); } } void InitListChecker::CheckScalarType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { if (Index >= IList->getNumInits()) { if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), SemaRef.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_empty_scalar_initializer : diag::err_empty_scalar_initializer) << IList->getSourceRange(); hadError = !SemaRef.getLangOpts().CPlusPlus11; ++Index; ++StructuredIndex; return; } Expr *expr = IList->getInit(Index); if (InitListExpr *SubIList = dyn_cast(expr)) { // FIXME: This is invalid, and accepting it causes overload resolution // to pick the wrong overload in some corner cases. if (!VerifyOnly) SemaRef.Diag(SubIList->getLocStart(), diag::ext_many_braces_around_scalar_init) << SubIList->getSourceRange(); CheckScalarType(Entity, SubIList, DeclType, Index, StructuredList, StructuredIndex); return; } else if (isa(expr)) { if (!VerifyOnly) SemaRef.Diag(expr->getLocStart(), diag::err_designator_for_scalar_init) << DeclType << expr->getSourceRange(); hadError = true; ++Index; ++StructuredIndex; return; } if (VerifyOnly) { if (!SemaRef.CanPerformCopyInitialization(Entity,expr)) hadError = true; ++Index; return; } ExprResult Result = SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), expr, /*TopLevelOfInitList=*/true); Expr *ResultExpr = nullptr; if (Result.isInvalid()) hadError = true; // types weren't compatible. else { ResultExpr = Result.getAs(); if (ResultExpr != expr) { // The type was promoted, update initializer list. IList->setInit(Index, ResultExpr); } } if (hadError) ++StructuredIndex; else UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr); ++Index; } void InitListChecker::CheckReferenceType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { if (Index >= IList->getNumInits()) { // FIXME: It would be wonderful if we could point at the actual member. In // general, it would be useful to pass location information down the stack, // so that we know the location (or decl) of the "current object" being // initialized. if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::err_init_reference_member_uninitialized) << DeclType << IList->getSourceRange(); hadError = true; ++Index; ++StructuredIndex; return; } Expr *expr = IList->getInit(Index); if (isa(expr) && !SemaRef.getLangOpts().CPlusPlus11) { if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list) << DeclType << IList->getSourceRange(); hadError = true; ++Index; ++StructuredIndex; return; } if (VerifyOnly) { if (!SemaRef.CanPerformCopyInitialization(Entity,expr)) hadError = true; ++Index; return; } ExprResult Result = SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), expr, /*TopLevelOfInitList=*/true); if (Result.isInvalid()) hadError = true; expr = Result.getAs(); IList->setInit(Index, expr); if (hadError) ++StructuredIndex; else UpdateStructuredListElement(StructuredList, StructuredIndex, expr); ++Index; } void InitListChecker::CheckVectorType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { const VectorType *VT = DeclType->getAs(); unsigned maxElements = VT->getNumElements(); unsigned numEltsInit = 0; QualType elementType = VT->getElementType(); if (Index >= IList->getNumInits()) { // Make sure the element type can be value-initialized. if (VerifyOnly) CheckEmptyInitializable( InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity), IList->getLocEnd()); return; } if (!SemaRef.getLangOpts().OpenCL) { // If the initializing element is a vector, try to copy-initialize // instead of breaking it apart (which is doomed to failure anyway). Expr *Init = IList->getInit(Index); if (!isa(Init) && Init->getType()->isVectorType()) { if (VerifyOnly) { if (!SemaRef.CanPerformCopyInitialization(Entity, Init)) hadError = true; ++Index; return; } ExprResult Result = SemaRef.PerformCopyInitialization(Entity, Init->getLocStart(), Init, /*TopLevelOfInitList=*/true); Expr *ResultExpr = nullptr; if (Result.isInvalid()) hadError = true; // types weren't compatible. else { ResultExpr = Result.getAs(); if (ResultExpr != Init) { // The type was promoted, update initializer list. IList->setInit(Index, ResultExpr); } } if (hadError) ++StructuredIndex; else UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr); ++Index; return; } InitializedEntity ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); for (unsigned i = 0; i < maxElements; ++i, ++numEltsInit) { // Don't attempt to go past the end of the init list if (Index >= IList->getNumInits()) { if (VerifyOnly) CheckEmptyInitializable(ElementEntity, IList->getLocEnd()); break; } ElementEntity.setElementIndex(Index); CheckSubElementType(ElementEntity, IList, elementType, Index, StructuredList, StructuredIndex); } if (VerifyOnly) return; bool isBigEndian = SemaRef.Context.getTargetInfo().isBigEndian(); const VectorType *T = Entity.getType()->getAs(); if (isBigEndian && (T->getVectorKind() == VectorType::NeonVector || T->getVectorKind() == VectorType::NeonPolyVector)) { // The ability to use vector initializer lists is a GNU vector extension // and is unrelated to the NEON intrinsics in arm_neon.h. On little // endian machines it works fine, however on big endian machines it // exhibits surprising behaviour: // // uint32x2_t x = {42, 64}; // return vget_lane_u32(x, 0); // Will return 64. // // Because of this, explicitly call out that it is non-portable. // SemaRef.Diag(IList->getLocStart(), diag::warn_neon_vector_initializer_non_portable); const char *typeCode; unsigned typeSize = SemaRef.Context.getTypeSize(elementType); if (elementType->isFloatingType()) typeCode = "f"; else if (elementType->isSignedIntegerType()) typeCode = "s"; else if (elementType->isUnsignedIntegerType()) typeCode = "u"; else llvm_unreachable("Invalid element type!"); SemaRef.Diag(IList->getLocStart(), SemaRef.Context.getTypeSize(VT) > 64 ? diag::note_neon_vector_initializer_non_portable_q : diag::note_neon_vector_initializer_non_portable) << typeCode << typeSize; } return; } InitializedEntity ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); // OpenCL initializers allows vectors to be constructed from vectors. for (unsigned i = 0; i < maxElements; ++i) { // Don't attempt to go past the end of the init list if (Index >= IList->getNumInits()) break; ElementEntity.setElementIndex(Index); QualType IType = IList->getInit(Index)->getType(); if (!IType->isVectorType()) { CheckSubElementType(ElementEntity, IList, elementType, Index, StructuredList, StructuredIndex); ++numEltsInit; } else { QualType VecType; const VectorType *IVT = IType->getAs(); unsigned numIElts = IVT->getNumElements(); if (IType->isExtVectorType()) VecType = SemaRef.Context.getExtVectorType(elementType, numIElts); else VecType = SemaRef.Context.getVectorType(elementType, numIElts, IVT->getVectorKind()); CheckSubElementType(ElementEntity, IList, VecType, Index, StructuredList, StructuredIndex); numEltsInit += numIElts; } } // OpenCL requires all elements to be initialized. if (numEltsInit != maxElements) { if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::err_vector_incorrect_num_initializers) << (numEltsInit < maxElements) << maxElements << numEltsInit; hadError = true; } } void InitListChecker::CheckArrayType(const InitializedEntity &Entity, InitListExpr *IList, QualType &DeclType, llvm::APSInt elementIndex, bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { const ArrayType *arrayType = SemaRef.Context.getAsArrayType(DeclType); // Check for the special-case of initializing an array with a string. if (Index < IList->getNumInits()) { if (IsStringInit(IList->getInit(Index), arrayType, SemaRef.Context) == SIF_None) { // We place the string literal directly into the resulting // initializer list. This is the only place where the structure // of the structured initializer list doesn't match exactly, // because doing so would involve allocating one character // constant for each string. if (!VerifyOnly) { CheckStringInit(IList->getInit(Index), DeclType, arrayType, SemaRef); UpdateStructuredListElement(StructuredList, StructuredIndex, IList->getInit(Index)); StructuredList->resizeInits(SemaRef.Context, StructuredIndex); } ++Index; return; } } if (const VariableArrayType *VAT = dyn_cast(arrayType)) { // Check for VLAs; in standard C it would be possible to check this // earlier, but I don't know where clang accepts VLAs (gcc accepts // them in all sorts of strange places). if (!VerifyOnly) SemaRef.Diag(VAT->getSizeExpr()->getLocStart(), diag::err_variable_object_no_init) << VAT->getSizeExpr()->getSourceRange(); hadError = true; ++Index; ++StructuredIndex; return; } // We might know the maximum number of elements in advance. llvm::APSInt maxElements(elementIndex.getBitWidth(), elementIndex.isUnsigned()); bool maxElementsKnown = false; if (const ConstantArrayType *CAT = dyn_cast(arrayType)) { maxElements = CAT->getSize(); elementIndex = elementIndex.extOrTrunc(maxElements.getBitWidth()); elementIndex.setIsUnsigned(maxElements.isUnsigned()); maxElementsKnown = true; } QualType elementType = arrayType->getElementType(); while (Index < IList->getNumInits()) { Expr *Init = IList->getInit(Index); if (DesignatedInitExpr *DIE = dyn_cast(Init)) { // If we're not the subobject that matches up with the '{' for // the designator, we shouldn't be handling the // designator. Return immediately. if (!SubobjectIsDesignatorContext) return; // Handle this designated initializer. elementIndex will be // updated to be the next array element we'll initialize. if (CheckDesignatedInitializer(Entity, IList, DIE, 0, DeclType, nullptr, &elementIndex, Index, StructuredList, StructuredIndex, true, false)) { hadError = true; continue; } if (elementIndex.getBitWidth() > maxElements.getBitWidth()) maxElements = maxElements.extend(elementIndex.getBitWidth()); else if (elementIndex.getBitWidth() < maxElements.getBitWidth()) elementIndex = elementIndex.extend(maxElements.getBitWidth()); elementIndex.setIsUnsigned(maxElements.isUnsigned()); // If the array is of incomplete type, keep track of the number of // elements in the initializer. if (!maxElementsKnown && elementIndex > maxElements) maxElements = elementIndex; continue; } // If we know the maximum number of elements, and we've already // hit it, stop consuming elements in the initializer list. if (maxElementsKnown && elementIndex == maxElements) break; InitializedEntity ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, StructuredIndex, Entity); // Check this element. CheckSubElementType(ElementEntity, IList, elementType, Index, StructuredList, StructuredIndex); ++elementIndex; // If the array is of incomplete type, keep track of the number of // elements in the initializer. if (!maxElementsKnown && elementIndex > maxElements) maxElements = elementIndex; } if (!hadError && DeclType->isIncompleteArrayType() && !VerifyOnly) { // If this is an incomplete array type, the actual type needs to // be calculated here. llvm::APSInt Zero(maxElements.getBitWidth(), maxElements.isUnsigned()); if (maxElements == Zero && !Entity.isVariableLengthArrayNew()) { // Sizing an array implicitly to zero is not allowed by ISO C, // but is supported by GNU. SemaRef.Diag(IList->getLocStart(), diag::ext_typecheck_zero_array_size); } DeclType = SemaRef.Context.getConstantArrayType(elementType, maxElements, ArrayType::Normal, 0); } if (!hadError && VerifyOnly) { // If there are any members of the array that get value-initialized, check // that is possible. That happens if we know the bound and don't have // enough elements, or if we're performing an array new with an unknown // bound. // FIXME: This needs to detect holes left by designated initializers too. if ((maxElementsKnown && elementIndex < maxElements) || Entity.isVariableLengthArrayNew()) CheckEmptyInitializable(InitializedEntity::InitializeElement( SemaRef.Context, 0, Entity), IList->getLocEnd()); } } bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity, Expr *InitExpr, FieldDecl *Field, bool TopLevelObject) { // Handle GNU flexible array initializers. unsigned FlexArrayDiag; if (isa(InitExpr) && cast(InitExpr)->getNumInits() == 0) { // Empty flexible array init always allowed as an extension FlexArrayDiag = diag::ext_flexible_array_init; } else if (SemaRef.getLangOpts().CPlusPlus) { // Disallow flexible array init in C++; it is not required for gcc // compatibility, and it needs work to IRGen correctly in general. FlexArrayDiag = diag::err_flexible_array_init; } else if (!TopLevelObject) { // Disallow flexible array init on non-top-level object FlexArrayDiag = diag::err_flexible_array_init; } else if (Entity.getKind() != InitializedEntity::EK_Variable) { // Disallow flexible array init on anything which is not a variable. FlexArrayDiag = diag::err_flexible_array_init; } else if (cast(Entity.getDecl())->hasLocalStorage()) { // Disallow flexible array init on local variables. FlexArrayDiag = diag::err_flexible_array_init; } else { // Allow other cases. FlexArrayDiag = diag::ext_flexible_array_init; } if (!VerifyOnly) { SemaRef.Diag(InitExpr->getLocStart(), FlexArrayDiag) << InitExpr->getLocStart(); SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) << Field; } return FlexArrayDiag != diag::ext_flexible_array_init; } void InitListChecker::CheckStructUnionTypes( const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, CXXRecordDecl::base_class_range Bases, RecordDecl::field_iterator Field, bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool TopLevelObject) { RecordDecl *structDecl = DeclType->getAs()->getDecl(); // If the record is invalid, some of it's members are invalid. To avoid // confusion, we forgo checking the intializer for the entire record. if (structDecl->isInvalidDecl()) { // Assume it was supposed to consume a single initializer. ++Index; hadError = true; return; } if (DeclType->isUnionType() && IList->getNumInits() == 0) { RecordDecl *RD = DeclType->getAs()->getDecl(); // If there's a default initializer, use it. if (isa(RD) && cast(RD)->hasInClassInitializer()) { if (VerifyOnly) return; for (RecordDecl::field_iterator FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { if (Field->hasInClassInitializer()) { StructuredList->setInitializedFieldInUnion(*Field); // FIXME: Actually build a CXXDefaultInitExpr? return; } } } // Value-initialize the first member of the union that isn't an unnamed // bitfield. for (RecordDecl::field_iterator FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { if (!Field->isUnnamedBitfield()) { if (VerifyOnly) CheckEmptyInitializable( InitializedEntity::InitializeMember(*Field, &Entity), IList->getLocEnd()); else StructuredList->setInitializedFieldInUnion(*Field); break; } } return; } bool InitializedSomething = false; // If we have any base classes, they are initialized prior to the fields. for (auto &Base : Bases) { Expr *Init = Index < IList->getNumInits() ? IList->getInit(Index) : nullptr; SourceLocation InitLoc = Init ? Init->getLocStart() : IList->getLocEnd(); // Designated inits always initialize fields, so if we see one, all // remaining base classes have no explicit initializer. if (Init && isa(Init)) Init = nullptr; InitializedEntity BaseEntity = InitializedEntity::InitializeBase( SemaRef.Context, &Base, false, &Entity); if (Init) { CheckSubElementType(BaseEntity, IList, Base.getType(), Index, StructuredList, StructuredIndex); InitializedSomething = true; } else if (VerifyOnly) { CheckEmptyInitializable(BaseEntity, InitLoc); } } // If structDecl is a forward declaration, this loop won't do // anything except look at designated initializers; That's okay, // because an error should get printed out elsewhere. It might be // worthwhile to skip over the rest of the initializer, though. RecordDecl *RD = DeclType->getAs()->getDecl(); RecordDecl::field_iterator FieldEnd = RD->field_end(); bool CheckForMissingFields = !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()); while (Index < IList->getNumInits()) { Expr *Init = IList->getInit(Index); if (DesignatedInitExpr *DIE = dyn_cast(Init)) { // If we're not the subobject that matches up with the '{' for // the designator, we shouldn't be handling the // designator. Return immediately. if (!SubobjectIsDesignatorContext) return; // Handle this designated initializer. Field will be updated to // the next field that we'll be initializing. if (CheckDesignatedInitializer(Entity, IList, DIE, 0, DeclType, &Field, nullptr, Index, StructuredList, StructuredIndex, true, TopLevelObject)) hadError = true; InitializedSomething = true; // Disable check for missing fields when designators are used. // This matches gcc behaviour. CheckForMissingFields = false; continue; } if (Field == FieldEnd) { // We've run out of fields. We're done. break; } // We've already initialized a member of a union. We're done. if (InitializedSomething && DeclType->isUnionType()) break; // If we've hit the flexible array member at the end, we're done. if (Field->getType()->isIncompleteArrayType()) break; if (Field->isUnnamedBitfield()) { // Don't initialize unnamed bitfields, e.g. "int : 20;" ++Field; continue; } // Make sure we can use this declaration. bool InvalidUse; if (VerifyOnly) InvalidUse = !SemaRef.CanUseDecl(*Field, TreatUnavailableAsInvalid); else InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, IList->getInit(Index)->getLocStart()); if (InvalidUse) { ++Index; ++Field; hadError = true; continue; } InitializedEntity MemberEntity = InitializedEntity::InitializeMember(*Field, &Entity); CheckSubElementType(MemberEntity, IList, Field->getType(), Index, StructuredList, StructuredIndex); InitializedSomething = true; if (DeclType->isUnionType() && !VerifyOnly) { // Initialize the first field within the union. StructuredList->setInitializedFieldInUnion(*Field); } ++Field; } // Emit warnings for missing struct field initializers. if (!VerifyOnly && InitializedSomething && CheckForMissingFields && Field != FieldEnd && !Field->getType()->isIncompleteArrayType() && !DeclType->isUnionType()) { // It is possible we have one or more unnamed bitfields remaining. // Find first (if any) named field and emit warning. for (RecordDecl::field_iterator it = Field, end = RD->field_end(); it != end; ++it) { if (!it->isUnnamedBitfield() && !it->hasInClassInitializer()) { SemaRef.Diag(IList->getSourceRange().getEnd(), diag::warn_missing_field_initializers) << *it; break; } } } // Check that any remaining fields can be value-initialized. if (VerifyOnly && Field != FieldEnd && !DeclType->isUnionType() && !Field->getType()->isIncompleteArrayType()) { // FIXME: Should check for holes left by designated initializers too. for (; Field != FieldEnd && !hadError; ++Field) { if (!Field->isUnnamedBitfield() && !Field->hasInClassInitializer()) CheckEmptyInitializable( InitializedEntity::InitializeMember(*Field, &Entity), IList->getLocEnd()); } } if (Field == FieldEnd || !Field->getType()->isIncompleteArrayType() || Index >= IList->getNumInits()) return; if (CheckFlexibleArrayInit(Entity, IList->getInit(Index), *Field, TopLevelObject)) { hadError = true; ++Index; return; } InitializedEntity MemberEntity = InitializedEntity::InitializeMember(*Field, &Entity); if (isa(IList->getInit(Index))) CheckSubElementType(MemberEntity, IList, Field->getType(), Index, StructuredList, StructuredIndex); else CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index, StructuredList, StructuredIndex); } /// Expand a field designator that refers to a member of an /// anonymous struct or union into a series of field designators that /// refers to the field within the appropriate subobject. /// static void ExpandAnonymousFieldDesignator(Sema &SemaRef, DesignatedInitExpr *DIE, unsigned DesigIdx, IndirectFieldDecl *IndirectField) { typedef DesignatedInitExpr::Designator Designator; // Build the replacement designators. SmallVector Replacements; for (IndirectFieldDecl::chain_iterator PI = IndirectField->chain_begin(), PE = IndirectField->chain_end(); PI != PE; ++PI) { if (PI + 1 == PE) Replacements.push_back(Designator((IdentifierInfo *)nullptr, DIE->getDesignator(DesigIdx)->getDotLoc(), DIE->getDesignator(DesigIdx)->getFieldLoc())); else Replacements.push_back(Designator((IdentifierInfo *)nullptr, SourceLocation(), SourceLocation())); assert(isa(*PI)); Replacements.back().setField(cast(*PI)); } // Expand the current designator into the set of replacement // designators, so we have a full subobject path down to where the // member of the anonymous struct/union is actually stored. DIE->ExpandDesignator(SemaRef.Context, DesigIdx, &Replacements[0], &Replacements[0] + Replacements.size()); } static DesignatedInitExpr *CloneDesignatedInitExpr(Sema &SemaRef, DesignatedInitExpr *DIE) { unsigned NumIndexExprs = DIE->getNumSubExprs() - 1; SmallVector IndexExprs(NumIndexExprs); for (unsigned I = 0; I < NumIndexExprs; ++I) IndexExprs[I] = DIE->getSubExpr(I + 1); return DesignatedInitExpr::Create(SemaRef.Context, DIE->designators(), IndexExprs, DIE->getEqualOrColonLoc(), DIE->usesGNUSyntax(), DIE->getInit()); } namespace { // Callback to only accept typo corrections that are for field members of // the given struct or union. class FieldInitializerValidatorCCC : public CorrectionCandidateCallback { public: explicit FieldInitializerValidatorCCC(RecordDecl *RD) : Record(RD) {} bool ValidateCandidate(const TypoCorrection &candidate) override { FieldDecl *FD = candidate.getCorrectionDeclAs(); return FD && FD->getDeclContext()->getRedeclContext()->Equals(Record); } private: RecordDecl *Record; }; } // end anonymous namespace /// Check the well-formedness of a C99 designated initializer. /// /// Determines whether the designated initializer @p DIE, which /// resides at the given @p Index within the initializer list @p /// IList, is well-formed for a current object of type @p DeclType /// (C99 6.7.8). The actual subobject that this designator refers to /// within the current subobject is returned in either /// @p NextField or @p NextElementIndex (whichever is appropriate). /// /// @param IList The initializer list in which this designated /// initializer occurs. /// /// @param DIE The designated initializer expression. /// /// @param DesigIdx The index of the current designator. /// /// @param CurrentObjectType The type of the "current object" (C99 6.7.8p17), /// into which the designation in @p DIE should refer. /// /// @param NextField If non-NULL and the first designator in @p DIE is /// a field, this will be set to the field declaration corresponding /// to the field named by the designator. /// /// @param NextElementIndex If non-NULL and the first designator in @p /// DIE is an array designator or GNU array-range designator, this /// will be set to the last index initialized by this designator. /// /// @param Index Index into @p IList where the designated initializer /// @p DIE occurs. /// /// @param StructuredList The initializer list expression that /// describes all of the subobject initializers in the order they'll /// actually be initialized. /// /// @returns true if there was an error, false otherwise. bool InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, InitListExpr *IList, DesignatedInitExpr *DIE, unsigned DesigIdx, QualType &CurrentObjectType, RecordDecl::field_iterator *NextField, llvm::APSInt *NextElementIndex, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool FinishSubobjectInit, bool TopLevelObject) { if (DesigIdx == DIE->size()) { // Check the actual initialization for the designated object type. bool prevHadError = hadError; // Temporarily remove the designator expression from the // initializer list that the child calls see, so that we don't try // to re-process the designator. unsigned OldIndex = Index; IList->setInit(OldIndex, DIE->getInit()); CheckSubElementType(Entity, IList, CurrentObjectType, Index, StructuredList, StructuredIndex); // Restore the designated initializer expression in the syntactic // form of the initializer list. if (IList->getInit(OldIndex) != DIE->getInit()) DIE->setInit(IList->getInit(OldIndex)); IList->setInit(OldIndex, DIE); return hadError && !prevHadError; } DesignatedInitExpr::Designator *D = DIE->getDesignator(DesigIdx); bool IsFirstDesignator = (DesigIdx == 0); if (!VerifyOnly) { assert((IsFirstDesignator || StructuredList) && "Need a non-designated initializer list to start from"); // Determine the structural initializer list that corresponds to the // current subobject. if (IsFirstDesignator) StructuredList = SyntacticToSemantic.lookup(IList); else { Expr *ExistingInit = StructuredIndex < StructuredList->getNumInits() ? StructuredList->getInit(StructuredIndex) : nullptr; if (!ExistingInit && StructuredList->hasArrayFiller()) ExistingInit = StructuredList->getArrayFiller(); if (!ExistingInit) StructuredList = getStructuredSubobjectInit(IList, Index, CurrentObjectType, StructuredList, StructuredIndex, SourceRange(D->getLocStart(), DIE->getLocEnd())); else if (InitListExpr *Result = dyn_cast(ExistingInit)) StructuredList = Result; else { if (DesignatedInitUpdateExpr *E = dyn_cast(ExistingInit)) StructuredList = E->getUpdater(); else { DesignatedInitUpdateExpr *DIUE = new (SemaRef.Context) DesignatedInitUpdateExpr(SemaRef.Context, D->getLocStart(), ExistingInit, DIE->getLocEnd()); StructuredList->updateInit(SemaRef.Context, StructuredIndex, DIUE); StructuredList = DIUE->getUpdater(); } // We need to check on source range validity because the previous // initializer does not have to be an explicit initializer. e.g., // // struct P { int a, b; }; // struct PP { struct P p } l = { { .a = 2 }, .p.b = 3 }; // // There is an overwrite taking place because the first braced initializer // list "{ .a = 2 }" already provides value for .p.b (which is zero). if (ExistingInit->getSourceRange().isValid()) { // We are creating an initializer list that initializes the // subobjects of the current object, but there was already an // initialization that completely initialized the current // subobject, e.g., by a compound literal: // // struct X { int a, b; }; // struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 }; // // Here, xs[0].a == 0 and xs[0].b == 3, since the second, // designated initializer re-initializes the whole // subobject [0], overwriting previous initializers. SemaRef.Diag(D->getLocStart(), diag::warn_subobject_initializer_overrides) << SourceRange(D->getLocStart(), DIE->getLocEnd()); SemaRef.Diag(ExistingInit->getLocStart(), diag::note_previous_initializer) << /*FIXME:has side effects=*/0 << ExistingInit->getSourceRange(); } } } assert(StructuredList && "Expected a structured initializer list"); } if (D->isFieldDesignator()) { // C99 6.7.8p7: // // If a designator has the form // // . identifier // // then the current object (defined below) shall have // structure or union type and the identifier shall be the // name of a member of that type. const RecordType *RT = CurrentObjectType->getAs(); if (!RT) { SourceLocation Loc = D->getDotLoc(); if (Loc.isInvalid()) Loc = D->getFieldLoc(); if (!VerifyOnly) SemaRef.Diag(Loc, diag::err_field_designator_non_aggr) << SemaRef.getLangOpts().CPlusPlus << CurrentObjectType; ++Index; return true; } FieldDecl *KnownField = D->getField(); if (!KnownField) { IdentifierInfo *FieldName = D->getFieldName(); DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName); for (NamedDecl *ND : Lookup) { if (auto *FD = dyn_cast(ND)) { KnownField = FD; break; } if (auto *IFD = dyn_cast(ND)) { // In verify mode, don't modify the original. if (VerifyOnly) DIE = CloneDesignatedInitExpr(SemaRef, DIE); ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IFD); D = DIE->getDesignator(DesigIdx); KnownField = cast(*IFD->chain_begin()); break; } } if (!KnownField) { if (VerifyOnly) { ++Index; return true; // No typo correction when just trying this out. } // Name lookup found something, but it wasn't a field. if (!Lookup.empty()) { SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield) << FieldName; SemaRef.Diag(Lookup.front()->getLocation(), diag::note_field_designator_found); ++Index; return true; } // Name lookup didn't find anything. // Determine whether this was a typo for another field name. if (TypoCorrection Corrected = SemaRef.CorrectTypo( DeclarationNameInfo(FieldName, D->getFieldLoc()), Sema::LookupMemberName, /*Scope=*/nullptr, /*SS=*/nullptr, llvm::make_unique(RT->getDecl()), Sema::CTK_ErrorRecovery, RT->getDecl())) { SemaRef.diagnoseTypo( Corrected, SemaRef.PDiag(diag::err_field_designator_unknown_suggest) << FieldName << CurrentObjectType); KnownField = Corrected.getCorrectionDeclAs(); hadError = true; } else { // Typo correction didn't find anything. SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown) << FieldName << CurrentObjectType; ++Index; return true; } } } unsigned FieldIndex = 0; if (auto *CXXRD = dyn_cast(RT->getDecl())) FieldIndex = CXXRD->getNumBases(); for (auto *FI : RT->getDecl()->fields()) { if (FI->isUnnamedBitfield()) continue; if (declaresSameEntity(KnownField, FI)) { KnownField = FI; break; } ++FieldIndex; } RecordDecl::field_iterator Field = RecordDecl::field_iterator(DeclContext::decl_iterator(KnownField)); // All of the fields of a union are located at the same place in // the initializer list. if (RT->getDecl()->isUnion()) { FieldIndex = 0; if (!VerifyOnly) { FieldDecl *CurrentField = StructuredList->getInitializedFieldInUnion(); if (CurrentField && !declaresSameEntity(CurrentField, *Field)) { assert(StructuredList->getNumInits() == 1 && "A union should never have more than one initializer!"); Expr *ExistingInit = StructuredList->getInit(0); if (ExistingInit) { // We're about to throw away an initializer, emit warning. SemaRef.Diag(D->getFieldLoc(), diag::warn_initializer_overrides) << D->getSourceRange(); SemaRef.Diag(ExistingInit->getLocStart(), diag::note_previous_initializer) << /*FIXME:has side effects=*/0 << ExistingInit->getSourceRange(); } // remove existing initializer StructuredList->resizeInits(SemaRef.Context, 0); StructuredList->setInitializedFieldInUnion(nullptr); } StructuredList->setInitializedFieldInUnion(*Field); } } // Make sure we can use this declaration. bool InvalidUse; if (VerifyOnly) InvalidUse = !SemaRef.CanUseDecl(*Field, TreatUnavailableAsInvalid); else InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, D->getFieldLoc()); if (InvalidUse) { ++Index; return true; } if (!VerifyOnly) { // Update the designator with the field declaration. D->setField(*Field); // Make sure that our non-designated initializer list has space // for a subobject corresponding to this field. if (FieldIndex >= StructuredList->getNumInits()) StructuredList->resizeInits(SemaRef.Context, FieldIndex + 1); } // This designator names a flexible array member. if (Field->getType()->isIncompleteArrayType()) { bool Invalid = false; if ((DesigIdx + 1) != DIE->size()) { // We can't designate an object within the flexible array // member (because GCC doesn't allow it). if (!VerifyOnly) { DesignatedInitExpr::Designator *NextD = DIE->getDesignator(DesigIdx + 1); SemaRef.Diag(NextD->getLocStart(), diag::err_designator_into_flexible_array_member) << SourceRange(NextD->getLocStart(), DIE->getLocEnd()); SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) << *Field; } Invalid = true; } if (!hadError && !isa(DIE->getInit()) && !isa(DIE->getInit())) { // The initializer is not an initializer list. if (!VerifyOnly) { SemaRef.Diag(DIE->getInit()->getLocStart(), diag::err_flexible_array_init_needs_braces) << DIE->getInit()->getSourceRange(); SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) << *Field; } Invalid = true; } // Check GNU flexible array initializer. if (!Invalid && CheckFlexibleArrayInit(Entity, DIE->getInit(), *Field, TopLevelObject)) Invalid = true; if (Invalid) { ++Index; return true; } // Initialize the array. bool prevHadError = hadError; unsigned newStructuredIndex = FieldIndex; unsigned OldIndex = Index; IList->setInit(Index, DIE->getInit()); InitializedEntity MemberEntity = InitializedEntity::InitializeMember(*Field, &Entity); CheckSubElementType(MemberEntity, IList, Field->getType(), Index, StructuredList, newStructuredIndex); IList->setInit(OldIndex, DIE); if (hadError && !prevHadError) { ++Field; ++FieldIndex; if (NextField) *NextField = Field; StructuredIndex = FieldIndex; return true; } } else { // Recurse to check later designated subobjects. QualType FieldType = Field->getType(); unsigned newStructuredIndex = FieldIndex; InitializedEntity MemberEntity = InitializedEntity::InitializeMember(*Field, &Entity); if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1, FieldType, nullptr, nullptr, Index, StructuredList, newStructuredIndex, FinishSubobjectInit, false)) return true; } // Find the position of the next field to be initialized in this // subobject. ++Field; ++FieldIndex; // If this the first designator, our caller will continue checking // the rest of this struct/class/union subobject. if (IsFirstDesignator) { if (NextField) *NextField = Field; StructuredIndex = FieldIndex; return false; } if (!FinishSubobjectInit) return false; // We've already initialized something in the union; we're done. if (RT->getDecl()->isUnion()) return hadError; // Check the remaining fields within this class/struct/union subobject. bool prevHadError = hadError; auto NoBases = CXXRecordDecl::base_class_range(CXXRecordDecl::base_class_iterator(), CXXRecordDecl::base_class_iterator()); CheckStructUnionTypes(Entity, IList, CurrentObjectType, NoBases, Field, false, Index, StructuredList, FieldIndex); return hadError && !prevHadError; } // C99 6.7.8p6: // // If a designator has the form // // [ constant-expression ] // // then the current object (defined below) shall have array // type and the expression shall be an integer constant // expression. If the array is of unknown size, any // nonnegative value is valid. // // Additionally, cope with the GNU extension that permits // designators of the form // // [ constant-expression ... constant-expression ] const ArrayType *AT = SemaRef.Context.getAsArrayType(CurrentObjectType); if (!AT) { if (!VerifyOnly) SemaRef.Diag(D->getLBracketLoc(), diag::err_array_designator_non_array) << CurrentObjectType; ++Index; return true; } Expr *IndexExpr = nullptr; llvm::APSInt DesignatedStartIndex, DesignatedEndIndex; if (D->isArrayDesignator()) { IndexExpr = DIE->getArrayIndex(*D); DesignatedStartIndex = IndexExpr->EvaluateKnownConstInt(SemaRef.Context); DesignatedEndIndex = DesignatedStartIndex; } else { assert(D->isArrayRangeDesignator() && "Need array-range designator"); DesignatedStartIndex = DIE->getArrayRangeStart(*D)->EvaluateKnownConstInt(SemaRef.Context); DesignatedEndIndex = DIE->getArrayRangeEnd(*D)->EvaluateKnownConstInt(SemaRef.Context); IndexExpr = DIE->getArrayRangeEnd(*D); // Codegen can't handle evaluating array range designators that have side // effects, because we replicate the AST value for each initialized element. // As such, set the sawArrayRangeDesignator() bit if we initialize multiple // elements with something that has a side effect, so codegen can emit an // "error unsupported" error instead of miscompiling the app. if (DesignatedStartIndex.getZExtValue()!=DesignatedEndIndex.getZExtValue()&& DIE->getInit()->HasSideEffects(SemaRef.Context) && !VerifyOnly) FullyStructuredList->sawArrayRangeDesignator(); } if (isa(AT)) { llvm::APSInt MaxElements(cast(AT)->getSize(), false); DesignatedStartIndex = DesignatedStartIndex.extOrTrunc(MaxElements.getBitWidth()); DesignatedStartIndex.setIsUnsigned(MaxElements.isUnsigned()); DesignatedEndIndex = DesignatedEndIndex.extOrTrunc(MaxElements.getBitWidth()); DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned()); if (DesignatedEndIndex >= MaxElements) { if (!VerifyOnly) SemaRef.Diag(IndexExpr->getLocStart(), diag::err_array_designator_too_large) << DesignatedEndIndex.toString(10) << MaxElements.toString(10) << IndexExpr->getSourceRange(); ++Index; return true; } } else { unsigned DesignatedIndexBitWidth = ConstantArrayType::getMaxSizeBits(SemaRef.Context); DesignatedStartIndex = DesignatedStartIndex.extOrTrunc(DesignatedIndexBitWidth); DesignatedEndIndex = DesignatedEndIndex.extOrTrunc(DesignatedIndexBitWidth); DesignatedStartIndex.setIsUnsigned(true); DesignatedEndIndex.setIsUnsigned(true); } if (!VerifyOnly && StructuredList->isStringLiteralInit()) { // We're modifying a string literal init; we have to decompose the string // so we can modify the individual characters. ASTContext &Context = SemaRef.Context; Expr *SubExpr = StructuredList->getInit(0)->IgnoreParens(); // Compute the character type QualType CharTy = AT->getElementType(); // Compute the type of the integer literals. QualType PromotedCharTy = CharTy; if (CharTy->isPromotableIntegerType()) PromotedCharTy = Context.getPromotedIntegerType(CharTy); unsigned PromotedCharTyWidth = Context.getTypeSize(PromotedCharTy); if (StringLiteral *SL = dyn_cast(SubExpr)) { // Get the length of the string. uint64_t StrLen = SL->getLength(); if (cast(AT)->getSize().ult(StrLen)) StrLen = cast(AT)->getSize().getZExtValue(); StructuredList->resizeInits(Context, StrLen); // Build a literal for each character in the string, and put them into // the init list. for (unsigned i = 0, e = StrLen; i != e; ++i) { llvm::APInt CodeUnit(PromotedCharTyWidth, SL->getCodeUnit(i)); Expr *Init = new (Context) IntegerLiteral( Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc()); if (CharTy != PromotedCharTy) Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast, Init, nullptr, VK_RValue); StructuredList->updateInit(Context, i, Init); } } else { ObjCEncodeExpr *E = cast(SubExpr); std::string Str; Context.getObjCEncodingForType(E->getEncodedType(), Str); // Get the length of the string. uint64_t StrLen = Str.size(); if (cast(AT)->getSize().ult(StrLen)) StrLen = cast(AT)->getSize().getZExtValue(); StructuredList->resizeInits(Context, StrLen); // Build a literal for each character in the string, and put them into // the init list. for (unsigned i = 0, e = StrLen; i != e; ++i) { llvm::APInt CodeUnit(PromotedCharTyWidth, Str[i]); Expr *Init = new (Context) IntegerLiteral( Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc()); if (CharTy != PromotedCharTy) Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast, Init, nullptr, VK_RValue); StructuredList->updateInit(Context, i, Init); } } } // Make sure that our non-designated initializer list has space // for a subobject corresponding to this array element. if (!VerifyOnly && DesignatedEndIndex.getZExtValue() >= StructuredList->getNumInits()) StructuredList->resizeInits(SemaRef.Context, DesignatedEndIndex.getZExtValue() + 1); // Repeatedly perform subobject initializations in the range // [DesignatedStartIndex, DesignatedEndIndex]. // Move to the next designator unsigned ElementIndex = DesignatedStartIndex.getZExtValue(); unsigned OldIndex = Index; InitializedEntity ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); while (DesignatedStartIndex <= DesignatedEndIndex) { // Recurse to check later designated subobjects. QualType ElementType = AT->getElementType(); Index = OldIndex; ElementEntity.setElementIndex(ElementIndex); if (CheckDesignatedInitializer( ElementEntity, IList, DIE, DesigIdx + 1, ElementType, nullptr, nullptr, Index, StructuredList, ElementIndex, FinishSubobjectInit && (DesignatedStartIndex == DesignatedEndIndex), false)) return true; // Move to the next index in the array that we'll be initializing. ++DesignatedStartIndex; ElementIndex = DesignatedStartIndex.getZExtValue(); } // If this the first designator, our caller will continue checking // the rest of this array subobject. if (IsFirstDesignator) { if (NextElementIndex) *NextElementIndex = DesignatedStartIndex; StructuredIndex = ElementIndex; return false; } if (!FinishSubobjectInit) return false; // Check the remaining elements within this array subobject. bool prevHadError = hadError; CheckArrayType(Entity, IList, CurrentObjectType, DesignatedStartIndex, /*SubobjectIsDesignatorContext=*/false, Index, StructuredList, ElementIndex); return hadError && !prevHadError; } // Get the structured initializer list for a subobject of type // @p CurrentObjectType. InitListExpr * InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, QualType CurrentObjectType, InitListExpr *StructuredList, unsigned StructuredIndex, SourceRange InitRange, bool IsFullyOverwritten) { if (VerifyOnly) return nullptr; // No structured list in verification-only mode. Expr *ExistingInit = nullptr; if (!StructuredList) ExistingInit = SyntacticToSemantic.lookup(IList); else if (StructuredIndex < StructuredList->getNumInits()) ExistingInit = StructuredList->getInit(StructuredIndex); if (InitListExpr *Result = dyn_cast_or_null(ExistingInit)) // There might have already been initializers for subobjects of the current // object, but a subsequent initializer list will overwrite the entirety // of the current object. (See DR 253 and C99 6.7.8p21). e.g., // // struct P { char x[6]; }; // struct P l = { .x[2] = 'x', .x = { [0] = 'f' } }; // // The first designated initializer is ignored, and l.x is just "f". if (!IsFullyOverwritten) return Result; if (ExistingInit) { // We are creating an initializer list that initializes the // subobjects of the current object, but there was already an // initialization that completely initialized the current // subobject, e.g., by a compound literal: // // struct X { int a, b; }; // struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 }; // // Here, xs[0].a == 0 and xs[0].b == 3, since the second, // designated initializer re-initializes the whole // subobject [0], overwriting previous initializers. SemaRef.Diag(InitRange.getBegin(), diag::warn_subobject_initializer_overrides) << InitRange; SemaRef.Diag(ExistingInit->getLocStart(), diag::note_previous_initializer) << /*FIXME:has side effects=*/0 << ExistingInit->getSourceRange(); } InitListExpr *Result = new (SemaRef.Context) InitListExpr(SemaRef.Context, InitRange.getBegin(), None, InitRange.getEnd()); QualType ResultType = CurrentObjectType; if (!ResultType->isArrayType()) ResultType = ResultType.getNonLValueExprType(SemaRef.Context); Result->setType(ResultType); // Pre-allocate storage for the structured initializer list. unsigned NumElements = 0; unsigned NumInits = 0; bool GotNumInits = false; if (!StructuredList) { NumInits = IList->getNumInits(); GotNumInits = true; } else if (Index < IList->getNumInits()) { if (InitListExpr *SubList = dyn_cast(IList->getInit(Index))) { NumInits = SubList->getNumInits(); GotNumInits = true; } } if (const ArrayType *AType = SemaRef.Context.getAsArrayType(CurrentObjectType)) { if (const ConstantArrayType *CAType = dyn_cast(AType)) { NumElements = CAType->getSize().getZExtValue(); // Simple heuristic so that we don't allocate a very large // initializer with many empty entries at the end. if (GotNumInits && NumElements > NumInits) NumElements = 0; } } else if (const VectorType *VType = CurrentObjectType->getAs()) NumElements = VType->getNumElements(); else if (const RecordType *RType = CurrentObjectType->getAs()) { RecordDecl *RDecl = RType->getDecl(); if (RDecl->isUnion()) NumElements = 1; else NumElements = std::distance(RDecl->field_begin(), RDecl->field_end()); } Result->reserveInits(SemaRef.Context, NumElements); // Link this new initializer list into the structured initializer // lists. if (StructuredList) StructuredList->updateInit(SemaRef.Context, StructuredIndex, Result); else { Result->setSyntacticForm(IList); SyntacticToSemantic[IList] = Result; } return Result; } /// Update the initializer at index @p StructuredIndex within the /// structured initializer list to the value @p expr. void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList, unsigned &StructuredIndex, Expr *expr) { // No structured initializer list to update if (!StructuredList) return; if (Expr *PrevInit = StructuredList->updateInit(SemaRef.Context, StructuredIndex, expr)) { // This initializer overwrites a previous initializer. Warn. // We need to check on source range validity because the previous // initializer does not have to be an explicit initializer. // struct P { int a, b; }; // struct PP { struct P p } l = { { .a = 2 }, .p.b = 3 }; // There is an overwrite taking place because the first braced initializer // list "{ .a = 2 }' already provides value for .p.b (which is zero). if (PrevInit->getSourceRange().isValid()) { SemaRef.Diag(expr->getLocStart(), diag::warn_initializer_overrides) << expr->getSourceRange(); SemaRef.Diag(PrevInit->getLocStart(), diag::note_previous_initializer) << /*FIXME:has side effects=*/0 << PrevInit->getSourceRange(); } } ++StructuredIndex; } /// Check that the given Index expression is a valid array designator /// value. This is essentially just a wrapper around /// VerifyIntegerConstantExpression that also checks for negative values /// and produces a reasonable diagnostic if there is a /// failure. Returns the index expression, possibly with an implicit cast /// added, on success. If everything went okay, Value will receive the /// value of the constant expression. static ExprResult CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) { SourceLocation Loc = Index->getLocStart(); // Make sure this is an integer constant expression. ExprResult Result = S.VerifyIntegerConstantExpression(Index, &Value); if (Result.isInvalid()) return Result; if (Value.isSigned() && Value.isNegative()) return S.Diag(Loc, diag::err_array_designator_negative) << Value.toString(10) << Index->getSourceRange(); Value.setIsUnsigned(true); return Result; } ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, SourceLocation Loc, bool GNUSyntax, ExprResult Init) { typedef DesignatedInitExpr::Designator ASTDesignator; bool Invalid = false; SmallVector Designators; SmallVector InitExpressions; // Build designators and check array designator expressions. for (unsigned Idx = 0; Idx < Desig.getNumDesignators(); ++Idx) { const Designator &D = Desig.getDesignator(Idx); switch (D.getKind()) { case Designator::FieldDesignator: Designators.push_back(ASTDesignator(D.getField(), D.getDotLoc(), D.getFieldLoc())); break; case Designator::ArrayDesignator: { Expr *Index = static_cast(D.getArrayIndex()); llvm::APSInt IndexValue; if (!Index->isTypeDependent() && !Index->isValueDependent()) Index = CheckArrayDesignatorExpr(*this, Index, IndexValue).get(); if (!Index) Invalid = true; else { Designators.push_back(ASTDesignator(InitExpressions.size(), D.getLBracketLoc(), D.getRBracketLoc())); InitExpressions.push_back(Index); } break; } case Designator::ArrayRangeDesignator: { Expr *StartIndex = static_cast(D.getArrayRangeStart()); Expr *EndIndex = static_cast(D.getArrayRangeEnd()); llvm::APSInt StartValue; llvm::APSInt EndValue; bool StartDependent = StartIndex->isTypeDependent() || StartIndex->isValueDependent(); bool EndDependent = EndIndex->isTypeDependent() || EndIndex->isValueDependent(); if (!StartDependent) StartIndex = CheckArrayDesignatorExpr(*this, StartIndex, StartValue).get(); if (!EndDependent) EndIndex = CheckArrayDesignatorExpr(*this, EndIndex, EndValue).get(); if (!StartIndex || !EndIndex) Invalid = true; else { // Make sure we're comparing values with the same bit width. if (StartDependent || EndDependent) { // Nothing to compute. } else if (StartValue.getBitWidth() > EndValue.getBitWidth()) EndValue = EndValue.extend(StartValue.getBitWidth()); else if (StartValue.getBitWidth() < EndValue.getBitWidth()) StartValue = StartValue.extend(EndValue.getBitWidth()); if (!StartDependent && !EndDependent && EndValue < StartValue) { Diag(D.getEllipsisLoc(), diag::err_array_designator_empty_range) << StartValue.toString(10) << EndValue.toString(10) << StartIndex->getSourceRange() << EndIndex->getSourceRange(); Invalid = true; } else { Designators.push_back(ASTDesignator(InitExpressions.size(), D.getLBracketLoc(), D.getEllipsisLoc(), D.getRBracketLoc())); InitExpressions.push_back(StartIndex); InitExpressions.push_back(EndIndex); } } break; } } } if (Invalid || Init.isInvalid()) return ExprError(); // Clear out the expressions within the designation. Desig.ClearExprs(*this); DesignatedInitExpr *DIE = DesignatedInitExpr::Create(Context, Designators, InitExpressions, Loc, GNUSyntax, Init.getAs()); if (!getLangOpts().C99) Diag(DIE->getLocStart(), diag::ext_designated_init) << DIE->getSourceRange(); return DIE; } //===----------------------------------------------------------------------===// // Initialization entity //===----------------------------------------------------------------------===// InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index, const InitializedEntity &Parent) : Parent(&Parent), Index(Index) { if (const ArrayType *AT = Context.getAsArrayType(Parent.getType())) { Kind = EK_ArrayElement; Type = AT->getElementType(); } else if (const VectorType *VT = Parent.getType()->getAs()) { Kind = EK_VectorElement; Type = VT->getElementType(); } else { const ComplexType *CT = Parent.getType()->getAs(); assert(CT && "Unexpected type"); Kind = EK_ComplexElement; Type = CT->getElementType(); } } InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context, const CXXBaseSpecifier *Base, bool IsInheritedVirtualBase, const InitializedEntity *Parent) { InitializedEntity Result; Result.Kind = EK_Base; Result.Parent = Parent; Result.Base = reinterpret_cast(Base); if (IsInheritedVirtualBase) Result.Base |= 0x01; Result.Type = Base->getType(); return Result; } DeclarationName InitializedEntity::getName() const { switch (getKind()) { case EK_Parameter: case EK_Parameter_CF_Audited: { ParmVarDecl *D = reinterpret_cast(Parameter & ~0x1); return (D ? D->getDeclName() : DeclarationName()); } case EK_Variable: case EK_Member: case EK_Binding: return Variable.VariableOrMember->getDeclName(); case EK_LambdaCapture: return DeclarationName(Capture.VarID); case EK_Result: case EK_StmtExprResult: case EK_Exception: case EK_New: case EK_Temporary: case EK_Base: case EK_Delegating: case EK_ArrayElement: case EK_VectorElement: case EK_ComplexElement: case EK_BlockElement: case EK_LambdaToBlockConversionBlockElement: case EK_CompoundLiteralInit: case EK_RelatedResult: return DeclarationName(); } llvm_unreachable("Invalid EntityKind!"); } ValueDecl *InitializedEntity::getDecl() const { switch (getKind()) { case EK_Variable: case EK_Member: case EK_Binding: return Variable.VariableOrMember; case EK_Parameter: case EK_Parameter_CF_Audited: return reinterpret_cast(Parameter & ~0x1); case EK_Result: case EK_StmtExprResult: case EK_Exception: case EK_New: case EK_Temporary: case EK_Base: case EK_Delegating: case EK_ArrayElement: case EK_VectorElement: case EK_ComplexElement: case EK_BlockElement: case EK_LambdaToBlockConversionBlockElement: case EK_LambdaCapture: case EK_CompoundLiteralInit: case EK_RelatedResult: return nullptr; } llvm_unreachable("Invalid EntityKind!"); } bool InitializedEntity::allowsNRVO() const { switch (getKind()) { case EK_Result: case EK_Exception: return LocAndNRVO.NRVO; case EK_StmtExprResult: case EK_Variable: case EK_Parameter: case EK_Parameter_CF_Audited: case EK_Member: case EK_Binding: case EK_New: case EK_Temporary: case EK_CompoundLiteralInit: case EK_Base: case EK_Delegating: case EK_ArrayElement: case EK_VectorElement: case EK_ComplexElement: case EK_BlockElement: case EK_LambdaToBlockConversionBlockElement: case EK_LambdaCapture: case EK_RelatedResult: break; } return false; } unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const { assert(getParent() != this); unsigned Depth = getParent() ? getParent()->dumpImpl(OS) : 0; for (unsigned I = 0; I != Depth; ++I) OS << "`-"; switch (getKind()) { case EK_Variable: OS << "Variable"; break; case EK_Parameter: OS << "Parameter"; break; case EK_Parameter_CF_Audited: OS << "CF audited function Parameter"; break; case EK_Result: OS << "Result"; break; case EK_StmtExprResult: OS << "StmtExprResult"; break; case EK_Exception: OS << "Exception"; break; case EK_Member: OS << "Member"; break; case EK_Binding: OS << "Binding"; break; case EK_New: OS << "New"; break; case EK_Temporary: OS << "Temporary"; break; case EK_CompoundLiteralInit: OS << "CompoundLiteral";break; case EK_RelatedResult: OS << "RelatedResult"; break; case EK_Base: OS << "Base"; break; case EK_Delegating: OS << "Delegating"; break; case EK_ArrayElement: OS << "ArrayElement " << Index; break; case EK_VectorElement: OS << "VectorElement " << Index; break; case EK_ComplexElement: OS << "ComplexElement " << Index; break; case EK_BlockElement: OS << "Block"; break; case EK_LambdaToBlockConversionBlockElement: OS << "Block (lambda)"; break; case EK_LambdaCapture: OS << "LambdaCapture "; OS << DeclarationName(Capture.VarID); break; } if (auto *D = getDecl()) { OS << " "; D->printQualifiedName(OS); } OS << " '" << getType().getAsString() << "'\n"; return Depth + 1; } LLVM_DUMP_METHOD void InitializedEntity::dump() const { dumpImpl(llvm::errs()); } //===----------------------------------------------------------------------===// // Initialization sequence //===----------------------------------------------------------------------===// void InitializationSequence::Step::Destroy() { switch (Kind) { case SK_ResolveAddressOfOverloadedFunction: case SK_CastDerivedToBaseRValue: case SK_CastDerivedToBaseXValue: case SK_CastDerivedToBaseLValue: case SK_BindReference: case SK_BindReferenceToTemporary: case SK_FinalCopy: case SK_ExtraneousCopyToTemporary: case SK_UserConversion: case SK_QualificationConversionRValue: case SK_QualificationConversionXValue: case SK_QualificationConversionLValue: case SK_AtomicConversion: case SK_LValueToRValue: case SK_ListInitialization: case SK_UnwrapInitList: case SK_RewrapInitList: case SK_ConstructorInitialization: case SK_ConstructorInitializationFromList: case SK_ZeroInitialization: case SK_CAssignment: case SK_StringInit: case SK_ObjCObjectConversion: case SK_ArrayLoopIndex: case SK_ArrayLoopInit: case SK_ArrayInit: case SK_GNUArrayInit: case SK_ParenthesizedArrayInit: case SK_PassByIndirectCopyRestore: case SK_PassByIndirectRestore: case SK_ProduceObjCObject: case SK_StdInitializerList: case SK_StdInitializerListConstructorCall: case SK_OCLSamplerInit: case SK_OCLZeroEvent: case SK_OCLZeroQueue: break; case SK_ConversionSequence: case SK_ConversionSequenceNoNarrowing: delete ICS; } } bool InitializationSequence::isDirectReferenceBinding() const { // There can be some lvalue adjustments after the SK_BindReference step. for (auto I = Steps.rbegin(); I != Steps.rend(); ++I) { if (I->Kind == SK_BindReference) return true; if (I->Kind == SK_BindReferenceToTemporary) return false; } return false; } bool InitializationSequence::isAmbiguous() const { if (!Failed()) return false; switch (getFailureKind()) { case FK_TooManyInitsForReference: case FK_ParenthesizedListInitForReference: case FK_ArrayNeedsInitList: case FK_ArrayNeedsInitListOrStringLiteral: case FK_ArrayNeedsInitListOrWideStringLiteral: case FK_NarrowStringIntoWideCharArray: case FK_WideStringIntoCharArray: case FK_IncompatWideStringIntoWideChar: case FK_PlainStringIntoUTF8Char: case FK_UTF8StringIntoPlainChar: case FK_AddressOfOverloadFailed: // FIXME: Could do better case FK_NonConstLValueReferenceBindingToTemporary: case FK_NonConstLValueReferenceBindingToBitfield: case FK_NonConstLValueReferenceBindingToVectorElement: case FK_NonConstLValueReferenceBindingToUnrelated: case FK_RValueReferenceBindingToLValue: case FK_ReferenceInitDropsQualifiers: case FK_ReferenceInitFailed: case FK_ConversionFailed: case FK_ConversionFromPropertyFailed: case FK_TooManyInitsForScalar: case FK_ParenthesizedListInitForScalar: case FK_ReferenceBindingToInitList: case FK_InitListBadDestinationType: case FK_DefaultInitOfConst: case FK_Incomplete: case FK_ArrayTypeMismatch: case FK_NonConstantArrayInit: case FK_ListInitializationFailed: case FK_VariableLengthArrayHasInitializer: case FK_PlaceholderType: case FK_ExplicitConstructor: case FK_AddressOfUnaddressableFunction: return false; case FK_ReferenceInitOverloadFailed: case FK_UserConversionOverloadFailed: case FK_ConstructorOverloadFailed: case FK_ListConstructorOverloadFailed: return FailedOverloadResult == OR_Ambiguous; } llvm_unreachable("Invalid EntityKind!"); } bool InitializationSequence::isConstructorInitialization() const { return !Steps.empty() && Steps.back().Kind == SK_ConstructorInitialization; } void InitializationSequence ::AddAddressOverloadResolutionStep(FunctionDecl *Function, DeclAccessPair Found, bool HadMultipleCandidates) { Step S; S.Kind = SK_ResolveAddressOfOverloadedFunction; S.Type = Function->getType(); S.Function.HadMultipleCandidates = HadMultipleCandidates; S.Function.Function = Function; S.Function.FoundDecl = Found; Steps.push_back(S); } void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType, ExprValueKind VK) { Step S; switch (VK) { case VK_RValue: S.Kind = SK_CastDerivedToBaseRValue; break; case VK_XValue: S.Kind = SK_CastDerivedToBaseXValue; break; case VK_LValue: S.Kind = SK_CastDerivedToBaseLValue; break; } S.Type = BaseType; Steps.push_back(S); } void InitializationSequence::AddReferenceBindingStep(QualType T, bool BindingTemporary) { Step S; S.Kind = BindingTemporary? SK_BindReferenceToTemporary : SK_BindReference; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddFinalCopy(QualType T) { Step S; S.Kind = SK_FinalCopy; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddExtraneousCopyToTemporary(QualType T) { Step S; S.Kind = SK_ExtraneousCopyToTemporary; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddUserConversionStep(FunctionDecl *Function, DeclAccessPair FoundDecl, QualType T, bool HadMultipleCandidates) { Step S; S.Kind = SK_UserConversion; S.Type = T; S.Function.HadMultipleCandidates = HadMultipleCandidates; S.Function.Function = Function; S.Function.FoundDecl = FoundDecl; Steps.push_back(S); } void InitializationSequence::AddQualificationConversionStep(QualType Ty, ExprValueKind VK) { Step S; S.Kind = SK_QualificationConversionRValue; // work around a gcc warning switch (VK) { case VK_RValue: S.Kind = SK_QualificationConversionRValue; break; case VK_XValue: S.Kind = SK_QualificationConversionXValue; break; case VK_LValue: S.Kind = SK_QualificationConversionLValue; break; } S.Type = Ty; Steps.push_back(S); } void InitializationSequence::AddAtomicConversionStep(QualType Ty) { Step S; S.Kind = SK_AtomicConversion; S.Type = Ty; Steps.push_back(S); } void InitializationSequence::AddLValueToRValueStep(QualType Ty) { assert(!Ty.hasQualifiers() && "rvalues may not have qualifiers"); Step S; S.Kind = SK_LValueToRValue; S.Type = Ty; Steps.push_back(S); } void InitializationSequence::AddConversionSequenceStep( const ImplicitConversionSequence &ICS, QualType T, bool TopLevelOfInitList) { Step S; S.Kind = TopLevelOfInitList ? SK_ConversionSequenceNoNarrowing : SK_ConversionSequence; S.Type = T; S.ICS = new ImplicitConversionSequence(ICS); Steps.push_back(S); } void InitializationSequence::AddListInitializationStep(QualType T) { Step S; S.Kind = SK_ListInitialization; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddConstructorInitializationStep( DeclAccessPair FoundDecl, CXXConstructorDecl *Constructor, QualType T, bool HadMultipleCandidates, bool FromInitList, bool AsInitList) { Step S; S.Kind = FromInitList ? AsInitList ? SK_StdInitializerListConstructorCall : SK_ConstructorInitializationFromList : SK_ConstructorInitialization; S.Type = T; S.Function.HadMultipleCandidates = HadMultipleCandidates; S.Function.Function = Constructor; S.Function.FoundDecl = FoundDecl; Steps.push_back(S); } void InitializationSequence::AddZeroInitializationStep(QualType T) { Step S; S.Kind = SK_ZeroInitialization; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddCAssignmentStep(QualType T) { Step S; S.Kind = SK_CAssignment; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddStringInitStep(QualType T) { Step S; S.Kind = SK_StringInit; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddObjCObjectConversionStep(QualType T) { Step S; S.Kind = SK_ObjCObjectConversion; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddArrayInitStep(QualType T, bool IsGNUExtension) { Step S; S.Kind = IsGNUExtension ? SK_GNUArrayInit : SK_ArrayInit; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddArrayInitLoopStep(QualType T, QualType EltT) { Step S; S.Kind = SK_ArrayLoopIndex; S.Type = EltT; Steps.insert(Steps.begin(), S); S.Kind = SK_ArrayLoopInit; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddParenthesizedArrayInitStep(QualType T) { Step S; S.Kind = SK_ParenthesizedArrayInit; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddPassByIndirectCopyRestoreStep(QualType type, bool shouldCopy) { Step s; s.Kind = (shouldCopy ? SK_PassByIndirectCopyRestore : SK_PassByIndirectRestore); s.Type = type; Steps.push_back(s); } void InitializationSequence::AddProduceObjCObjectStep(QualType T) { Step S; S.Kind = SK_ProduceObjCObject; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddStdInitializerListConstructionStep(QualType T) { Step S; S.Kind = SK_StdInitializerList; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddOCLSamplerInitStep(QualType T) { Step S; S.Kind = SK_OCLSamplerInit; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddOCLZeroEventStep(QualType T) { Step S; S.Kind = SK_OCLZeroEvent; S.Type = T; Steps.push_back(S); } void InitializationSequence::AddOCLZeroQueueStep(QualType T) { Step S; S.Kind = SK_OCLZeroQueue; S.Type = T; Steps.push_back(S); } void InitializationSequence::RewrapReferenceInitList(QualType T, InitListExpr *Syntactic) { assert(Syntactic->getNumInits() == 1 && "Can only rewrap trivial init lists."); Step S; S.Kind = SK_UnwrapInitList; S.Type = Syntactic->getInit(0)->getType(); Steps.insert(Steps.begin(), S); S.Kind = SK_RewrapInitList; S.Type = T; S.WrappingSyntacticList = Syntactic; Steps.push_back(S); } void InitializationSequence::SetOverloadFailure(FailureKind Failure, OverloadingResult Result) { setSequenceKind(FailedSequence); this->Failure = Failure; this->FailedOverloadResult = Result; } //===----------------------------------------------------------------------===// // Attempt initialization //===----------------------------------------------------------------------===// /// Tries to add a zero initializer. Returns true if that worked. static bool maybeRecoverWithZeroInitialization(Sema &S, InitializationSequence &Sequence, const InitializedEntity &Entity) { if (Entity.getKind() != InitializedEntity::EK_Variable) return false; VarDecl *VD = cast(Entity.getDecl()); if (VD->getInit() || VD->getLocEnd().isMacroID()) return false; QualType VariableTy = VD->getType().getCanonicalType(); SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd()); std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc); if (!Init.empty()) { Sequence.AddZeroInitializationStep(Entity.getType()); Sequence.SetZeroInitializationFixit(Init, Loc); return true; } return false; } static void MaybeProduceObjCObject(Sema &S, InitializationSequence &Sequence, const InitializedEntity &Entity) { if (!S.getLangOpts().ObjCAutoRefCount) return; /// When initializing a parameter, produce the value if it's marked /// __attribute__((ns_consumed)). if (Entity.isParameterKind()) { if (!Entity.isParameterConsumed()) return; assert(Entity.getType()->isObjCRetainableType() && "consuming an object of unretainable type?"); Sequence.AddProduceObjCObjectStep(Entity.getType()); /// When initializing a return value, if the return type is a /// retainable type, then returns need to immediately retain the /// object. If an autorelease is required, it will be done at the /// last instant. } else if (Entity.getKind() == InitializedEntity::EK_Result || Entity.getKind() == InitializedEntity::EK_StmtExprResult) { if (!Entity.getType()->isObjCRetainableType()) return; Sequence.AddProduceObjCObjectStep(Entity.getType()); } } static void TryListInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, InitListExpr *InitList, InitializationSequence &Sequence, bool TreatUnavailableAsInvalid); /// When initializing from init list via constructor, handle /// initialization of an object of type std::initializer_list. /// /// \return true if we have handled initialization of an object of type /// std::initializer_list, false otherwise. static bool TryInitializerListConstruction(Sema &S, InitListExpr *List, QualType DestType, InitializationSequence &Sequence, bool TreatUnavailableAsInvalid) { QualType E; if (!S.isStdInitializerList(DestType, &E)) return false; if (!S.isCompleteType(List->getExprLoc(), E)) { Sequence.setIncompleteTypeFailure(E); return true; } // Try initializing a temporary array from the init list. QualType ArrayType = S.Context.getConstantArrayType( E.withConst(), llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()), List->getNumInits()), clang::ArrayType::Normal, 0); InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(ArrayType); InitializationKind Kind = InitializationKind::CreateDirectList( List->getExprLoc(), List->getLocStart(), List->getLocEnd()); TryListInitialization(S, HiddenArray, Kind, List, Sequence, TreatUnavailableAsInvalid); if (Sequence) Sequence.AddStdInitializerListConstructionStep(DestType); return true; } /// Determine if the constructor has the signature of a copy or move /// constructor for the type T of the class in which it was found. That is, /// determine if its first parameter is of type T or reference to (possibly /// cv-qualified) T. static bool hasCopyOrMoveCtorParam(ASTContext &Ctx, const ConstructorInfo &Info) { if (Info.Constructor->getNumParams() == 0) return false; QualType ParmT = Info.Constructor->getParamDecl(0)->getType().getNonReferenceType(); QualType ClassT = Ctx.getRecordType(cast(Info.FoundDecl->getDeclContext())); return Ctx.hasSameUnqualifiedType(ParmT, ClassT); } static OverloadingResult ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, MultiExprArg Args, OverloadCandidateSet &CandidateSet, QualType DestType, DeclContext::lookup_result Ctors, OverloadCandidateSet::iterator &Best, bool CopyInitializing, bool AllowExplicit, bool OnlyListConstructors, bool IsListInit, bool SecondStepOfCopyInit = false) { CandidateSet.clear(OverloadCandidateSet::CSK_InitByConstructor); for (NamedDecl *D : Ctors) { auto Info = getConstructorInfo(D); if (!Info.Constructor || Info.Constructor->isInvalidDecl()) continue; if (!AllowExplicit && Info.Constructor->isExplicit()) continue; if (OnlyListConstructors && !S.isInitListConstructor(Info.Constructor)) continue; // C++11 [over.best.ics]p4: // ... and the constructor or user-defined conversion function is a // candidate by // - 13.3.1.3, when the argument is the temporary in the second step // of a class copy-initialization, or // - 13.3.1.4, 13.3.1.5, or 13.3.1.6 (in all cases), [not handled here] // - the second phase of 13.3.1.7 when the initializer list has exactly // one element that is itself an initializer list, and the target is // the first parameter of a constructor of class X, and the conversion // is to X or reference to (possibly cv-qualified X), // user-defined conversion sequences are not considered. bool SuppressUserConversions = SecondStepOfCopyInit || (IsListInit && Args.size() == 1 && isa(Args[0]) && hasCopyOrMoveCtorParam(S.Context, Info)); if (Info.ConstructorTmpl) S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, Args, CandidateSet, SuppressUserConversions); else { // C++ [over.match.copy]p1: // - When initializing a temporary to be bound to the first parameter // of a constructor [for type T] that takes a reference to possibly // cv-qualified T as its first argument, called with a single // argument in the context of direct-initialization, explicit // conversion functions are also considered. // FIXME: What if a constructor template instantiates to such a signature? bool AllowExplicitConv = AllowExplicit && !CopyInitializing && Args.size() == 1 && hasCopyOrMoveCtorParam(S.Context, Info); S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args, CandidateSet, SuppressUserConversions, /*PartialOverloading=*/false, /*AllowExplicit=*/AllowExplicitConv); } } // FIXME: Work around a bug in C++17 guaranteed copy elision. // // When initializing an object of class type T by constructor // ([over.match.ctor]) or by list-initialization ([over.match.list]) // from a single expression of class type U, conversion functions of // U that convert to the non-reference type cv T are candidates. // Explicit conversion functions are only candidates during // direct-initialization. // // Note: SecondStepOfCopyInit is only ever true in this case when // evaluating whether to produce a C++98 compatibility warning. if (S.getLangOpts().CPlusPlus17 && Args.size() == 1 && !SecondStepOfCopyInit) { Expr *Initializer = Args[0]; auto *SourceRD = Initializer->getType()->getAsCXXRecordDecl(); if (SourceRD && S.isCompleteType(DeclLoc, Initializer->getType())) { const auto &Conversions = SourceRD->getVisibleConversionFunctions(); for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { NamedDecl *D = *I; CXXRecordDecl *ActingDC = cast(D->getDeclContext()); D = D->getUnderlyingDecl(); FunctionTemplateDecl *ConvTemplate = dyn_cast(D); CXXConversionDecl *Conv; if (ConvTemplate) Conv = cast(ConvTemplate->getTemplatedDecl()); else Conv = cast(D); if ((AllowExplicit && !CopyInitializing) || !Conv->isExplicit()) { if (ConvTemplate) S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, AllowExplicit, /*AllowResultConversion*/false); else S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, AllowExplicit, /*AllowResultConversion*/false); } } } } // Perform overload resolution and return the result. return CandidateSet.BestViableFunction(S, DeclLoc, Best); } /// Attempt initialization by constructor (C++ [dcl.init]), which /// enumerates the constructors of the initialized entity and performs overload /// resolution to select the best. /// \param DestType The destination class type. /// \param DestArrayType The destination type, which is either DestType or /// a (possibly multidimensional) array of DestType. /// \param IsListInit Is this list-initialization? /// \param IsInitListCopy Is this non-list-initialization resulting from a /// list-initialization from {x} where x is the same /// type as the entity? static void TryConstructorInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType DestType, QualType DestArrayType, InitializationSequence &Sequence, bool IsListInit = false, bool IsInitListCopy = false) { assert(((!IsListInit && !IsInitListCopy) || (Args.size() == 1 && isa(Args[0]))) && "IsListInit/IsInitListCopy must come with a single initializer list " "argument."); InitListExpr *ILE = (IsListInit || IsInitListCopy) ? cast(Args[0]) : nullptr; MultiExprArg UnwrappedArgs = ILE ? MultiExprArg(ILE->getInits(), ILE->getNumInits()) : Args; // The type we're constructing needs to be complete. if (!S.isCompleteType(Kind.getLocation(), DestType)) { Sequence.setIncompleteTypeFailure(DestType); return; } // C++17 [dcl.init]p17: // - If the initializer expression is a prvalue and the cv-unqualified // version of the source type is the same class as the class of the // destination, the initializer expression is used to initialize the // destination object. // Per DR (no number yet), this does not apply when initializing a base // class or delegating to another constructor from a mem-initializer. // ObjC++: Lambda captured by the block in the lambda to block conversion // should avoid copy elision. if (S.getLangOpts().CPlusPlus17 && Entity.getKind() != InitializedEntity::EK_Base && Entity.getKind() != InitializedEntity::EK_Delegating && Entity.getKind() != InitializedEntity::EK_LambdaToBlockConversionBlockElement && UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isRValue() && S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) { // Convert qualifications if necessary. Sequence.AddQualificationConversionStep(DestType, VK_RValue); if (ILE) Sequence.RewrapReferenceInitList(DestType, ILE); return; } const RecordType *DestRecordType = DestType->getAs(); assert(DestRecordType && "Constructor initialization requires record type"); CXXRecordDecl *DestRecordDecl = cast(DestRecordType->getDecl()); // Build the candidate set directly in the initialization sequence // structure, so that it will persist if we fail. OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); // Determine whether we are allowed to call explicit constructors or // explicit conversion operators. bool AllowExplicit = Kind.AllowExplicit() || IsListInit; bool CopyInitialization = Kind.getKind() == InitializationKind::IK_Copy; // - Otherwise, if T is a class type, constructors are considered. The // applicable constructors are enumerated, and the best one is chosen // through overload resolution. DeclContext::lookup_result Ctors = S.LookupConstructors(DestRecordDecl); OverloadingResult Result = OR_No_Viable_Function; OverloadCandidateSet::iterator Best; bool AsInitializerList = false; // C++11 [over.match.list]p1, per DR1467: // When objects of non-aggregate type T are list-initialized, such that // 8.5.4 [dcl.init.list] specifies that overload resolution is performed // according to the rules in this section, overload resolution selects // the constructor in two phases: // // - Initially, the candidate functions are the initializer-list // constructors of the class T and the argument list consists of the // initializer list as a single argument. if (IsListInit) { AsInitializerList = true; // If the initializer list has no elements and T has a default constructor, // the first phase is omitted. if (!(UnwrappedArgs.empty() && DestRecordDecl->hasDefaultConstructor())) Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, CandidateSet, DestType, Ctors, Best, CopyInitialization, AllowExplicit, /*OnlyListConstructor=*/true, IsListInit); } // C++11 [over.match.list]p1: // - If no viable initializer-list constructor is found, overload resolution // is performed again, where the candidate functions are all the // constructors of the class T and the argument list consists of the // elements of the initializer list. if (Result == OR_No_Viable_Function) { AsInitializerList = false; Result = ResolveConstructorOverload(S, Kind.getLocation(), UnwrappedArgs, CandidateSet, DestType, Ctors, Best, CopyInitialization, AllowExplicit, /*OnlyListConstructors=*/false, IsListInit); } if (Result) { Sequence.SetOverloadFailure(IsListInit ? InitializationSequence::FK_ListConstructorOverloadFailed : InitializationSequence::FK_ConstructorOverloadFailed, Result); return; } bool HadMultipleCandidates = (CandidateSet.size() > 1); // In C++17, ResolveConstructorOverload can select a conversion function // instead of a constructor. if (auto *CD = dyn_cast(Best->Function)) { // Add the user-defined conversion step that calls the conversion function. QualType ConvType = CD->getConversionType(); assert(S.Context.hasSameUnqualifiedType(ConvType, DestType) && "should not have selected this conversion function"); Sequence.AddUserConversionStep(CD, Best->FoundDecl, ConvType, HadMultipleCandidates); if (!S.Context.hasSameType(ConvType, DestType)) Sequence.AddQualificationConversionStep(DestType, VK_RValue); if (IsListInit) Sequence.RewrapReferenceInitList(Entity.getType(), ILE); return; } // C++11 [dcl.init]p6: // If a program calls for the default initialization of an object // of a const-qualified type T, T shall be a class type with a // user-provided default constructor. // C++ core issue 253 proposal: // If the implicit default constructor initializes all subobjects, no // initializer should be required. // The 253 proposal is for example needed to process libstdc++ headers in 5.x. CXXConstructorDecl *CtorDecl = cast(Best->Function); if (Kind.getKind() == InitializationKind::IK_Default && Entity.getType().isConstQualified()) { if (!CtorDecl->getParent()->allowConstDefaultInit()) { if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity)) Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); return; } } // C++11 [over.match.list]p1: // In copy-list-initialization, if an explicit constructor is chosen, the // initializer is ill-formed. if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) { Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor); return; } // Add the constructor initialization step. Any cv-qualification conversion is // subsumed by the initialization. Sequence.AddConstructorInitializationStep( Best->FoundDecl, CtorDecl, DestArrayType, HadMultipleCandidates, IsListInit | IsInitListCopy, AsInitializerList); } static bool ResolveOverloadedFunctionForReferenceBinding(Sema &S, Expr *Initializer, QualType &SourceType, QualType &UnqualifiedSourceType, QualType UnqualifiedTargetType, InitializationSequence &Sequence) { if (S.Context.getCanonicalType(UnqualifiedSourceType) == S.Context.OverloadTy) { DeclAccessPair Found; bool HadMultipleCandidates = false; if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Initializer, UnqualifiedTargetType, false, Found, &HadMultipleCandidates)) { Sequence.AddAddressOverloadResolutionStep(Fn, Found, HadMultipleCandidates); SourceType = Fn->getType(); UnqualifiedSourceType = SourceType.getUnqualifiedType(); } else if (!UnqualifiedTargetType->isRecordType()) { Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); return true; } } return false; } static void TryReferenceInitializationCore(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, Expr *Initializer, QualType cv1T1, QualType T1, Qualifiers T1Quals, QualType cv2T2, QualType T2, Qualifiers T2Quals, InitializationSequence &Sequence); static void TryValueInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, InitializationSequence &Sequence, InitListExpr *InitList = nullptr); /// Attempt list initialization of a reference. static void TryReferenceListInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, InitListExpr *InitList, InitializationSequence &Sequence, bool TreatUnavailableAsInvalid) { // First, catch C++03 where this isn't possible. if (!S.getLangOpts().CPlusPlus11) { Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList); return; } // Can't reference initialize a compound literal. if (Entity.getKind() == InitializedEntity::EK_CompoundLiteralInit) { Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList); return; } QualType DestType = Entity.getType(); QualType cv1T1 = DestType->getAs()->getPointeeType(); Qualifiers T1Quals; QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals); // Reference initialization via an initializer list works thus: // If the initializer list consists of a single element that is // reference-related to the referenced type, bind directly to that element // (possibly creating temporaries). // Otherwise, initialize a temporary with the initializer list and // bind to that. if (InitList->getNumInits() == 1) { Expr *Initializer = InitList->getInit(0); QualType cv2T2 = Initializer->getType(); Qualifiers T2Quals; QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals); // If this fails, creating a temporary wouldn't work either. if (ResolveOverloadedFunctionForReferenceBinding(S, Initializer, cv2T2, T2, T1, Sequence)) return; SourceLocation DeclLoc = Initializer->getLocStart(); bool dummy1, dummy2, dummy3; Sema::ReferenceCompareResult RefRelationship = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, dummy1, dummy2, dummy3); if (RefRelationship >= Sema::Ref_Related) { // Try to bind the reference here. TryReferenceInitializationCore(S, Entity, Kind, Initializer, cv1T1, T1, T1Quals, cv2T2, T2, T2Quals, Sequence); if (Sequence) Sequence.RewrapReferenceInitList(cv1T1, InitList); return; } // Update the initializer if we've resolved an overloaded function. if (Sequence.step_begin() != Sequence.step_end()) Sequence.RewrapReferenceInitList(cv1T1, InitList); } // Not reference-related. Create a temporary and bind to that. InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1); TryListInitialization(S, TempEntity, Kind, InitList, Sequence, TreatUnavailableAsInvalid); if (Sequence) { if (DestType->isRValueReferenceType() || (T1Quals.hasConst() && !T1Quals.hasVolatile())) Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true); else Sequence.SetFailed( InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary); } } /// Attempt list initialization (C++0x [dcl.init.list]) static void TryListInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, InitListExpr *InitList, InitializationSequence &Sequence, bool TreatUnavailableAsInvalid) { QualType DestType = Entity.getType(); // C++ doesn't allow scalar initialization with more than one argument. // But C99 complex numbers are scalars and it makes sense there. if (S.getLangOpts().CPlusPlus && DestType->isScalarType() && !DestType->isAnyComplexType() && InitList->getNumInits() > 1) { Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar); return; } if (DestType->isReferenceType()) { TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence, TreatUnavailableAsInvalid); return; } if (DestType->isRecordType() && !S.isCompleteType(InitList->getLocStart(), DestType)) { Sequence.setIncompleteTypeFailure(DestType); return; } // C++11 [dcl.init.list]p3, per DR1467: // - If T is a class type and the initializer list has a single element of // type cv U, where U is T or a class derived from T, the object is // initialized from that element (by copy-initialization for // copy-list-initialization, or by direct-initialization for // direct-list-initialization). // - Otherwise, if T is a character array and the initializer list has a // single element that is an appropriately-typed string literal // (8.5.2 [dcl.init.string]), initialization is performed as described // in that section. // - Otherwise, if T is an aggregate, [...] (continue below). if (S.getLangOpts().CPlusPlus11 && InitList->getNumInits() == 1) { if (DestType->isRecordType()) { QualType InitType = InitList->getInit(0)->getType(); if (S.Context.hasSameUnqualifiedType(InitType, DestType) || S.IsDerivedFrom(InitList->getLocStart(), InitType, DestType)) { Expr *InitListAsExpr = InitList; TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType, DestType, Sequence, /*InitListSyntax*/false, /*IsInitListCopy*/true); return; } } if (const ArrayType *DestAT = S.Context.getAsArrayType(DestType)) { Expr *SubInit[1] = {InitList->getInit(0)}; if (!isa(DestAT) && IsStringInit(SubInit[0], DestAT, S.Context) == SIF_None) { InitializationKind SubKind = Kind.getKind() == InitializationKind::IK_DirectList ? InitializationKind::CreateDirect(Kind.getLocation(), InitList->getLBraceLoc(), InitList->getRBraceLoc()) : Kind; Sequence.InitializeFrom(S, Entity, SubKind, SubInit, /*TopLevelOfInitList*/ true, TreatUnavailableAsInvalid); // TryStringLiteralInitialization() (in InitializeFrom()) will fail if // the element is not an appropriately-typed string literal, in which // case we should proceed as in C++11 (below). if (Sequence) { Sequence.RewrapReferenceInitList(Entity.getType(), InitList); return; } } } } // C++11 [dcl.init.list]p3: // - If T is an aggregate, aggregate initialization is performed. if ((DestType->isRecordType() && !DestType->isAggregateType()) || (S.getLangOpts().CPlusPlus11 && S.isStdInitializerList(DestType, nullptr))) { if (S.getLangOpts().CPlusPlus11) { // - Otherwise, if the initializer list has no elements and T is a // class type with a default constructor, the object is // value-initialized. if (InitList->getNumInits() == 0) { CXXRecordDecl *RD = DestType->getAsCXXRecordDecl(); if (RD->hasDefaultConstructor()) { TryValueInitialization(S, Entity, Kind, Sequence, InitList); return; } } // - Otherwise, if T is a specialization of std::initializer_list, // an initializer_list object constructed [...] if (TryInitializerListConstruction(S, InitList, DestType, Sequence, TreatUnavailableAsInvalid)) return; // - Otherwise, if T is a class type, constructors are considered. Expr *InitListAsExpr = InitList; TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType, DestType, Sequence, /*InitListSyntax*/true); } else Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType); return; } if (S.getLangOpts().CPlusPlus && !DestType->isAggregateType() && InitList->getNumInits() == 1) { Expr *E = InitList->getInit(0); // - Otherwise, if T is an enumeration with a fixed underlying type, // the initializer-list has a single element v, and the initialization // is direct-list-initialization, the object is initialized with the // value T(v); if a narrowing conversion is required to convert v to // the underlying type of T, the program is ill-formed. auto *ET = DestType->getAs(); if (S.getLangOpts().CPlusPlus17 && Kind.getKind() == InitializationKind::IK_DirectList && ET && ET->getDecl()->isFixed() && !S.Context.hasSameUnqualifiedType(E->getType(), DestType) && (E->getType()->isIntegralOrEnumerationType() || E->getType()->isFloatingType())) { // There are two ways that T(v) can work when T is an enumeration type. // If there is either an implicit conversion sequence from v to T or // a conversion function that can convert from v to T, then we use that. // Otherwise, if v is of integral, enumeration, or floating-point type, // it is converted to the enumeration type via its underlying type. // There is no overlap possible between these two cases (except when the // source value is already of the destination type), and the first // case is handled by the general case for single-element lists below. ImplicitConversionSequence ICS; ICS.setStandard(); ICS.Standard.setAsIdentityConversion(); if (!E->isRValue()) ICS.Standard.First = ICK_Lvalue_To_Rvalue; // If E is of a floating-point type, then the conversion is ill-formed // due to narrowing, but go through the motions in order to produce the // right diagnostic. ICS.Standard.Second = E->getType()->isFloatingType() ? ICK_Floating_Integral : ICK_Integral_Conversion; ICS.Standard.setFromType(E->getType()); ICS.Standard.setToType(0, E->getType()); ICS.Standard.setToType(1, DestType); ICS.Standard.setToType(2, DestType); Sequence.AddConversionSequenceStep(ICS, ICS.Standard.getToType(2), /*TopLevelOfInitList*/true); Sequence.RewrapReferenceInitList(Entity.getType(), InitList); return; } // - Otherwise, if the initializer list has a single element of type E // [...references are handled above...], the object or reference is // initialized from that element (by copy-initialization for // copy-list-initialization, or by direct-initialization for // direct-list-initialization); if a narrowing conversion is required // to convert the element to T, the program is ill-formed. // // Per core-24034, this is direct-initialization if we were performing // direct-list-initialization and copy-initialization otherwise. // We can't use InitListChecker for this, because it always performs // copy-initialization. This only matters if we might use an 'explicit' // conversion operator, so we only need to handle the cases where the source // is of record type. if (InitList->getInit(0)->getType()->isRecordType()) { InitializationKind SubKind = Kind.getKind() == InitializationKind::IK_DirectList ? InitializationKind::CreateDirect(Kind.getLocation(), InitList->getLBraceLoc(), InitList->getRBraceLoc()) : Kind; Expr *SubInit[1] = { InitList->getInit(0) }; Sequence.InitializeFrom(S, Entity, SubKind, SubInit, /*TopLevelOfInitList*/true, TreatUnavailableAsInvalid); if (Sequence) Sequence.RewrapReferenceInitList(Entity.getType(), InitList); return; } } InitListChecker CheckInitList(S, Entity, InitList, DestType, /*VerifyOnly=*/true, TreatUnavailableAsInvalid); if (CheckInitList.HadError()) { Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed); return; } // Add the list initialization step with the built init list. Sequence.AddListInitializationStep(DestType); } /// Try a reference initialization that involves calling a conversion /// function. static OverloadingResult TryRefInitWithConversionFunction( Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, Expr *Initializer, bool AllowRValues, bool IsLValueRef, InitializationSequence &Sequence) { QualType DestType = Entity.getType(); QualType cv1T1 = DestType->getAs()->getPointeeType(); QualType T1 = cv1T1.getUnqualifiedType(); QualType cv2T2 = Initializer->getType(); QualType T2 = cv2T2.getUnqualifiedType(); bool DerivedToBase; bool ObjCConversion; bool ObjCLifetimeConversion; assert(!S.CompareReferenceRelationship(Initializer->getLocStart(), T1, T2, DerivedToBase, ObjCConversion, ObjCLifetimeConversion) && "Must have incompatible references when binding via conversion"); (void)DerivedToBase; (void)ObjCConversion; (void)ObjCLifetimeConversion; // Build the candidate set directly in the initialization sequence // structure, so that it will persist if we fail. OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion); // Determine whether we are allowed to call explicit conversion operators. // Note that none of [over.match.copy], [over.match.conv], nor // [over.match.ref] permit an explicit constructor to be chosen when // initializing a reference, not even for direct-initialization. bool AllowExplicitCtors = false; bool AllowExplicitConvs = Kind.allowExplicitConversionFunctionsInRefBinding(); const RecordType *T1RecordType = nullptr; if (AllowRValues && (T1RecordType = T1->getAs()) && S.isCompleteType(Kind.getLocation(), T1)) { // The type we're converting to is a class type. Enumerate its constructors // to see if there is a suitable conversion. CXXRecordDecl *T1RecordDecl = cast(T1RecordType->getDecl()); for (NamedDecl *D : S.LookupConstructors(T1RecordDecl)) { auto Info = getConstructorInfo(D); if (!Info.Constructor) continue; if (!Info.Constructor->isInvalidDecl() && Info.Constructor->isConvertingConstructor(AllowExplicitCtors)) { if (Info.ConstructorTmpl) S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, Initializer, CandidateSet, /*SuppressUserConversions=*/true); else S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Initializer, CandidateSet, /*SuppressUserConversions=*/true); } } } if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl()) return OR_No_Viable_Function; const RecordType *T2RecordType = nullptr; if ((T2RecordType = T2->getAs()) && S.isCompleteType(Kind.getLocation(), T2)) { // The type we're converting from is a class type, enumerate its conversion // functions. CXXRecordDecl *T2RecordDecl = cast(T2RecordType->getDecl()); const auto &Conversions = T2RecordDecl->getVisibleConversionFunctions(); for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { NamedDecl *D = *I; CXXRecordDecl *ActingDC = cast(D->getDeclContext()); if (isa(D)) D = cast(D)->getTargetDecl(); FunctionTemplateDecl *ConvTemplate = dyn_cast(D); CXXConversionDecl *Conv; if (ConvTemplate) Conv = cast(ConvTemplate->getTemplatedDecl()); else Conv = cast(D); // If the conversion function doesn't return a reference type, // it can't be considered for this conversion unless we're allowed to // consider rvalues. // FIXME: Do we need to make sure that we only consider conversion // candidates with reference-compatible results? That might be needed to // break recursion. if ((AllowExplicitConvs || !Conv->isExplicit()) && (AllowRValues || Conv->getConversionType()->isLValueReferenceType())){ if (ConvTemplate) S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, /*AllowObjCConversionOnExplicit=*/ false); else S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, /*AllowObjCConversionOnExplicit=*/false); } } } if (T2RecordType && T2RecordType->getDecl()->isInvalidDecl()) return OR_No_Viable_Function; SourceLocation DeclLoc = Initializer->getLocStart(); // Perform overload resolution. If it fails, return the failed result. OverloadCandidateSet::iterator Best; if (OverloadingResult Result = CandidateSet.BestViableFunction(S, DeclLoc, Best)) return Result; FunctionDecl *Function = Best->Function; // This is the overload that will be used for this initialization step if we // use this initialization. Mark it as referenced. Function->setReferenced(); // Compute the returned type and value kind of the conversion. QualType cv3T3; if (isa(Function)) cv3T3 = Function->getReturnType(); else cv3T3 = T1; ExprValueKind VK = VK_RValue; if (cv3T3->isLValueReferenceType()) VK = VK_LValue; else if (const auto *RRef = cv3T3->getAs()) VK = RRef->getPointeeType()->isFunctionType() ? VK_LValue : VK_XValue; cv3T3 = cv3T3.getNonLValueExprType(S.Context); // Add the user-defined conversion step. bool HadMultipleCandidates = (CandidateSet.size() > 1); Sequence.AddUserConversionStep(Function, Best->FoundDecl, cv3T3, HadMultipleCandidates); // Determine whether we'll need to perform derived-to-base adjustments or // other conversions. bool NewDerivedToBase = false; bool NewObjCConversion = false; bool NewObjCLifetimeConversion = false; Sema::ReferenceCompareResult NewRefRelationship = S.CompareReferenceRelationship(DeclLoc, T1, cv3T3, NewDerivedToBase, NewObjCConversion, NewObjCLifetimeConversion); // Add the final conversion sequence, if necessary. if (NewRefRelationship == Sema::Ref_Incompatible) { assert(!isa(Function) && "should not have conversion after constructor"); ImplicitConversionSequence ICS; ICS.setStandard(); ICS.Standard = Best->FinalConversion; Sequence.AddConversionSequenceStep(ICS, ICS.Standard.getToType(2)); // Every implicit conversion results in a prvalue, except for a glvalue // derived-to-base conversion, which we handle below. cv3T3 = ICS.Standard.getToType(2); VK = VK_RValue; } // If the converted initializer is a prvalue, its type T4 is adjusted to // type "cv1 T4" and the temporary materialization conversion is applied. // // We adjust the cv-qualifications to match the reference regardless of // whether we have a prvalue so that the AST records the change. In this // case, T4 is "cv3 T3". QualType cv1T4 = S.Context.getQualifiedType(cv3T3, cv1T1.getQualifiers()); if (cv1T4.getQualifiers() != cv3T3.getQualifiers()) Sequence.AddQualificationConversionStep(cv1T4, VK); Sequence.AddReferenceBindingStep(cv1T4, VK == VK_RValue); VK = IsLValueRef ? VK_LValue : VK_XValue; if (NewDerivedToBase) Sequence.AddDerivedToBaseCastStep(cv1T1, VK); else if (NewObjCConversion) Sequence.AddObjCObjectConversionStep(cv1T1); return OR_Success; } static void CheckCXX98CompatAccessibleCopy(Sema &S, const InitializedEntity &Entity, Expr *CurInitExpr); /// Attempt reference initialization (C++0x [dcl.init.ref]) static void TryReferenceInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, Expr *Initializer, InitializationSequence &Sequence) { QualType DestType = Entity.getType(); QualType cv1T1 = DestType->getAs()->getPointeeType(); Qualifiers T1Quals; QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals); QualType cv2T2 = Initializer->getType(); Qualifiers T2Quals; QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals); // If the initializer is the address of an overloaded function, try // to resolve the overloaded function. If all goes well, T2 is the // type of the resulting function. if (ResolveOverloadedFunctionForReferenceBinding(S, Initializer, cv2T2, T2, T1, Sequence)) return; // Delegate everything else to a subfunction. TryReferenceInitializationCore(S, Entity, Kind, Initializer, cv1T1, T1, T1Quals, cv2T2, T2, T2Quals, Sequence); } /// Determine whether an expression is a non-referenceable glvalue (one to /// which a reference can never bind). Attempting to bind a reference to /// such a glvalue will always create a temporary. static bool isNonReferenceableGLValue(Expr *E) { return E->refersToBitField() || E->refersToVectorElement(); } /// Reference initialization without resolving overloaded functions. static void TryReferenceInitializationCore(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, Expr *Initializer, QualType cv1T1, QualType T1, Qualifiers T1Quals, QualType cv2T2, QualType T2, Qualifiers T2Quals, InitializationSequence &Sequence) { QualType DestType = Entity.getType(); SourceLocation DeclLoc = Initializer->getLocStart(); // Compute some basic properties of the types and the initializer. bool isLValueRef = DestType->isLValueReferenceType(); bool isRValueRef = !isLValueRef; bool DerivedToBase = false; bool ObjCConversion = false; bool ObjCLifetimeConversion = false; Expr::Classification InitCategory = Initializer->Classify(S.Context); Sema::ReferenceCompareResult RefRelationship = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase, ObjCConversion, ObjCLifetimeConversion); // C++0x [dcl.init.ref]p5: // A reference to type "cv1 T1" is initialized by an expression of type // "cv2 T2" as follows: // // - If the reference is an lvalue reference and the initializer // expression // Note the analogous bullet points for rvalue refs to functions. Because // there are no function rvalues in C++, rvalue refs to functions are treated // like lvalue refs. OverloadingResult ConvOvlResult = OR_Success; bool T1Function = T1->isFunctionType(); if (isLValueRef || T1Function) { if (InitCategory.isLValue() && !isNonReferenceableGLValue(Initializer) && (RefRelationship == Sema::Ref_Compatible || (Kind.isCStyleOrFunctionalCast() && RefRelationship == Sema::Ref_Related))) { // - is an lvalue (but is not a bit-field), and "cv1 T1" is // reference-compatible with "cv2 T2," or if (T1Quals != T2Quals) // Convert to cv1 T2. This should only add qualifiers unless this is a // c-style cast. The removal of qualifiers in that case notionally // happens after the reference binding, but that doesn't matter. Sequence.AddQualificationConversionStep( S.Context.getQualifiedType(T2, T1Quals), Initializer->getValueKind()); if (DerivedToBase) Sequence.AddDerivedToBaseCastStep(cv1T1, VK_LValue); else if (ObjCConversion) Sequence.AddObjCObjectConversionStep(cv1T1); // We only create a temporary here when binding a reference to a // bit-field or vector element. Those cases are't supposed to be // handled by this bullet, but the outcome is the same either way. Sequence.AddReferenceBindingStep(cv1T1, false); return; } // - has a class type (i.e., T2 is a class type), where T1 is not // reference-related to T2, and can be implicitly converted to an // lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible // with "cv3 T3" (this conversion is selected by enumerating the // applicable conversion functions (13.3.1.6) and choosing the best // one through overload resolution (13.3)), // If we have an rvalue ref to function type here, the rhs must be // an rvalue. DR1287 removed the "implicitly" here. if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType() && (isLValueRef || InitCategory.isRValue())) { ConvOvlResult = TryRefInitWithConversionFunction( S, Entity, Kind, Initializer, /*AllowRValues*/ isRValueRef, /*IsLValueRef*/ isLValueRef, Sequence); if (ConvOvlResult == OR_Success) return; if (ConvOvlResult != OR_No_Viable_Function) Sequence.SetOverloadFailure( InitializationSequence::FK_ReferenceInitOverloadFailed, ConvOvlResult); } } // - Otherwise, the reference shall be an lvalue reference to a // non-volatile const type (i.e., cv1 shall be const), or the reference // shall be an rvalue reference. if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile())) { if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty()) Sequence.SetOverloadFailure( InitializationSequence::FK_ReferenceInitOverloadFailed, ConvOvlResult); else if (!InitCategory.isLValue()) Sequence.SetFailed( InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary); else { InitializationSequence::FailureKind FK; switch (RefRelationship) { case Sema::Ref_Compatible: if (Initializer->refersToBitField()) FK = InitializationSequence:: FK_NonConstLValueReferenceBindingToBitfield; else if (Initializer->refersToVectorElement()) FK = InitializationSequence:: FK_NonConstLValueReferenceBindingToVectorElement; else llvm_unreachable("unexpected kind of compatible initializer"); break; case Sema::Ref_Related: FK = InitializationSequence::FK_ReferenceInitDropsQualifiers; break; case Sema::Ref_Incompatible: FK = InitializationSequence:: FK_NonConstLValueReferenceBindingToUnrelated; break; } Sequence.SetFailed(FK); } return; } // - If the initializer expression // - is an // [<=14] xvalue (but not a bit-field), class prvalue, array prvalue, or // [1z] rvalue (but not a bit-field) or // function lvalue and "cv1 T1" is reference-compatible with "cv2 T2" // // Note: functions are handled above and below rather than here... if (!T1Function && (RefRelationship == Sema::Ref_Compatible || (Kind.isCStyleOrFunctionalCast() && RefRelationship == Sema::Ref_Related)) && ((InitCategory.isXValue() && !isNonReferenceableGLValue(Initializer)) || (InitCategory.isPRValue() && (S.getLangOpts().CPlusPlus17 || T2->isRecordType() || T2->isArrayType())))) { ExprValueKind ValueKind = InitCategory.isXValue() ? VK_XValue : VK_RValue; if (InitCategory.isPRValue() && T2->isRecordType()) { // The corresponding bullet in C++03 [dcl.init.ref]p5 gives the // compiler the freedom to perform a copy here or bind to the // object, while C++0x requires that we bind directly to the // object. Hence, we always bind to the object without making an // extra copy. However, in C++03 requires that we check for the // presence of a suitable copy constructor: // // The constructor that would be used to make the copy shall // be callable whether or not the copy is actually done. if (!S.getLangOpts().CPlusPlus11 && !S.getLangOpts().MicrosoftExt) Sequence.AddExtraneousCopyToTemporary(cv2T2); else if (S.getLangOpts().CPlusPlus11) CheckCXX98CompatAccessibleCopy(S, Entity, Initializer); } // C++1z [dcl.init.ref]/5.2.1.2: // If the converted initializer is a prvalue, its type T4 is adjusted // to type "cv1 T4" and the temporary materialization conversion is // applied. QualType cv1T4 = S.Context.getQualifiedType(cv2T2, T1Quals); if (T1Quals != T2Quals) Sequence.AddQualificationConversionStep(cv1T4, ValueKind); Sequence.AddReferenceBindingStep(cv1T4, ValueKind == VK_RValue); ValueKind = isLValueRef ? VK_LValue : VK_XValue; // In any case, the reference is bound to the resulting glvalue (or to // an appropriate base class subobject). if (DerivedToBase) Sequence.AddDerivedToBaseCastStep(cv1T1, ValueKind); else if (ObjCConversion) Sequence.AddObjCObjectConversionStep(cv1T1); return; } // - has a class type (i.e., T2 is a class type), where T1 is not // reference-related to T2, and can be implicitly converted to an // xvalue, class prvalue, or function lvalue of type "cv3 T3", // where "cv1 T1" is reference-compatible with "cv3 T3", // // DR1287 removes the "implicitly" here. if (T2->isRecordType()) { if (RefRelationship == Sema::Ref_Incompatible) { ConvOvlResult = TryRefInitWithConversionFunction( S, Entity, Kind, Initializer, /*AllowRValues*/ true, /*IsLValueRef*/ isLValueRef, Sequence); if (ConvOvlResult) Sequence.SetOverloadFailure( InitializationSequence::FK_ReferenceInitOverloadFailed, ConvOvlResult); return; } if (RefRelationship == Sema::Ref_Compatible && isRValueRef && InitCategory.isLValue()) { Sequence.SetFailed( InitializationSequence::FK_RValueReferenceBindingToLValue); return; } Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers); return; } // - Otherwise, a temporary of type "cv1 T1" is created and initialized // from the initializer expression using the rules for a non-reference // copy-initialization (8.5). The reference is then bound to the // temporary. [...] InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1); // FIXME: Why do we use an implicit conversion here rather than trying // copy-initialization? ImplicitConversionSequence ICS = S.TryImplicitConversion(Initializer, TempEntity.getType(), /*SuppressUserConversions=*/false, /*AllowExplicit=*/false, /*FIXME:InOverloadResolution=*/false, /*CStyle=*/Kind.isCStyleOrFunctionalCast(), /*AllowObjCWritebackConversion=*/false); if (ICS.isBad()) { // FIXME: Use the conversion function set stored in ICS to turn // this into an overloading ambiguity diagnostic. However, we need // to keep that set as an OverloadCandidateSet rather than as some // other kind of set. if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty()) Sequence.SetOverloadFailure( InitializationSequence::FK_ReferenceInitOverloadFailed, ConvOvlResult); else if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); else Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed); return; } else { Sequence.AddConversionSequenceStep(ICS, TempEntity.getType()); } // [...] If T1 is reference-related to T2, cv1 must be the // same cv-qualification as, or greater cv-qualification // than, cv2; otherwise, the program is ill-formed. unsigned T1CVRQuals = T1Quals.getCVRQualifiers(); unsigned T2CVRQuals = T2Quals.getCVRQualifiers(); if (RefRelationship == Sema::Ref_Related && (T1CVRQuals | T2CVRQuals) != T1CVRQuals) { Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers); return; } // [...] If T1 is reference-related to T2 and the reference is an rvalue // reference, the initializer expression shall not be an lvalue. if (RefRelationship >= Sema::Ref_Related && !isLValueRef && InitCategory.isLValue()) { Sequence.SetFailed( InitializationSequence::FK_RValueReferenceBindingToLValue); return; } Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true); } /// Attempt character array initialization from a string literal /// (C++ [dcl.init.string], C99 6.7.8). static void TryStringLiteralInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, Expr *Initializer, InitializationSequence &Sequence) { Sequence.AddStringInitStep(Entity.getType()); } /// Attempt value initialization (C++ [dcl.init]p7). static void TryValueInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, InitializationSequence &Sequence, InitListExpr *InitList) { assert((!InitList || InitList->getNumInits() == 0) && "Shouldn't use value-init for non-empty init lists"); // C++98 [dcl.init]p5, C++11 [dcl.init]p7: // // To value-initialize an object of type T means: QualType T = Entity.getType(); // -- if T is an array type, then each element is value-initialized; T = S.Context.getBaseElementType(T); if (const RecordType *RT = T->getAs()) { if (CXXRecordDecl *ClassDecl = dyn_cast(RT->getDecl())) { bool NeedZeroInitialization = true; // C++98: // -- if T is a class type (clause 9) with a user-declared constructor // (12.1), then the default constructor for T is called (and the // initialization is ill-formed if T has no accessible default // constructor); // C++11: // -- if T is a class type (clause 9) with either no default constructor // (12.1 [class.ctor]) or a default constructor that is user-provided // or deleted, then the object is default-initialized; // // Note that the C++11 rule is the same as the C++98 rule if there are no // defaulted or deleted constructors, so we just use it unconditionally. CXXConstructorDecl *CD = S.LookupDefaultConstructor(ClassDecl); if (!CD || !CD->getCanonicalDecl()->isDefaulted() || CD->isDeleted()) NeedZeroInitialization = false; // -- if T is a (possibly cv-qualified) non-union class type without a // user-provided or deleted default constructor, then the object is // zero-initialized and, if T has a non-trivial default constructor, // default-initialized; // The 'non-union' here was removed by DR1502. The 'non-trivial default // constructor' part was removed by DR1507. if (NeedZeroInitialization) Sequence.AddZeroInitializationStep(Entity.getType()); // C++03: // -- if T is a non-union class type without a user-declared constructor, // then every non-static data member and base class component of T is // value-initialized; // [...] A program that calls for [...] value-initialization of an // entity of reference type is ill-formed. // // C++11 doesn't need this handling, because value-initialization does not // occur recursively there, and the implicit default constructor is // defined as deleted in the problematic cases. if (!S.getLangOpts().CPlusPlus11 && ClassDecl->hasUninitializedReferenceMember()) { Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForReference); return; } // If this is list-value-initialization, pass the empty init list on when // building the constructor call. This affects the semantics of a few // things (such as whether an explicit default constructor can be called). Expr *InitListAsExpr = InitList; MultiExprArg Args(&InitListAsExpr, InitList ? 1 : 0); bool InitListSyntax = InitList; // FIXME: Instead of creating a CXXConstructExpr of array type here, // wrap a class-typed CXXConstructExpr in an ArrayInitLoopExpr. return TryConstructorInitialization( S, Entity, Kind, Args, T, Entity.getType(), Sequence, InitListSyntax); } } Sequence.AddZeroInitializationStep(Entity.getType()); } /// Attempt default initialization (C++ [dcl.init]p6). static void TryDefaultInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, InitializationSequence &Sequence) { assert(Kind.getKind() == InitializationKind::IK_Default); // C++ [dcl.init]p6: // To default-initialize an object of type T means: // - if T is an array type, each element is default-initialized; QualType DestType = S.Context.getBaseElementType(Entity.getType()); // - if T is a (possibly cv-qualified) class type (Clause 9), the default // constructor for T is called (and the initialization is ill-formed if // T has no accessible default constructor); if (DestType->isRecordType() && S.getLangOpts().CPlusPlus) { TryConstructorInitialization(S, Entity, Kind, None, DestType, Entity.getType(), Sequence); return; } // - otherwise, no initialization is performed. // If a program calls for the default initialization of an object of // a const-qualified type T, T shall be a class type with a user-provided // default constructor. if (DestType.isConstQualified() && S.getLangOpts().CPlusPlus) { if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity)) Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); return; } // If the destination type has a lifetime property, zero-initialize it. if (DestType.getQualifiers().hasObjCLifetime()) { Sequence.AddZeroInitializationStep(Entity.getType()); return; } } /// Attempt a user-defined conversion between two types (C++ [dcl.init]), /// which enumerates all conversion functions and performs overload resolution /// to select the best. static void TryUserDefinedConversion(Sema &S, QualType DestType, const InitializationKind &Kind, Expr *Initializer, InitializationSequence &Sequence, bool TopLevelOfInitList) { assert(!DestType->isReferenceType() && "References are handled elsewhere"); QualType SourceType = Initializer->getType(); assert((DestType->isRecordType() || SourceType->isRecordType()) && "Must have a class type to perform a user-defined conversion"); // Build the candidate set directly in the initialization sequence // structure, so that it will persist if we fail. OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion); // Determine whether we are allowed to call explicit constructors or // explicit conversion operators. bool AllowExplicit = Kind.AllowExplicit(); if (const RecordType *DestRecordType = DestType->getAs()) { // The type we're converting to is a class type. Enumerate its constructors // to see if there is a suitable conversion. CXXRecordDecl *DestRecordDecl = cast(DestRecordType->getDecl()); // Try to complete the type we're converting to. if (S.isCompleteType(Kind.getLocation(), DestType)) { for (NamedDecl *D : S.LookupConstructors(DestRecordDecl)) { auto Info = getConstructorInfo(D); if (!Info.Constructor) continue; if (!Info.Constructor->isInvalidDecl() && Info.Constructor->isConvertingConstructor(AllowExplicit)) { if (Info.ConstructorTmpl) S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, Initializer, CandidateSet, /*SuppressUserConversions=*/true); else S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Initializer, CandidateSet, /*SuppressUserConversions=*/true); } } } } SourceLocation DeclLoc = Initializer->getLocStart(); if (const RecordType *SourceRecordType = SourceType->getAs()) { // The type we're converting from is a class type, enumerate its conversion // functions. // We can only enumerate the conversion functions for a complete type; if // the type isn't complete, simply skip this step. if (S.isCompleteType(DeclLoc, SourceType)) { CXXRecordDecl *SourceRecordDecl = cast(SourceRecordType->getDecl()); const auto &Conversions = SourceRecordDecl->getVisibleConversionFunctions(); for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { NamedDecl *D = *I; CXXRecordDecl *ActingDC = cast(D->getDeclContext()); if (isa(D)) D = cast(D)->getTargetDecl(); FunctionTemplateDecl *ConvTemplate = dyn_cast(D); CXXConversionDecl *Conv; if (ConvTemplate) Conv = cast(ConvTemplate->getTemplatedDecl()); else Conv = cast(D); if (AllowExplicit || !Conv->isExplicit()) { if (ConvTemplate) S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, AllowExplicit); else S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, AllowExplicit); } } } } // Perform overload resolution. If it fails, return the failed result. OverloadCandidateSet::iterator Best; if (OverloadingResult Result = CandidateSet.BestViableFunction(S, DeclLoc, Best)) { Sequence.SetOverloadFailure( InitializationSequence::FK_UserConversionOverloadFailed, Result); return; } FunctionDecl *Function = Best->Function; Function->setReferenced(); bool HadMultipleCandidates = (CandidateSet.size() > 1); if (isa(Function)) { // Add the user-defined conversion step. Any cv-qualification conversion is // subsumed by the initialization. Per DR5, the created temporary is of the // cv-unqualified type of the destination. Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType.getUnqualifiedType(), HadMultipleCandidates); // C++14 and before: // - if the function is a constructor, the call initializes a temporary // of the cv-unqualified version of the destination type. The [...] // temporary [...] is then used to direct-initialize, according to the // rules above, the object that is the destination of the // copy-initialization. // Note that this just performs a simple object copy from the temporary. // // C++17: // - if the function is a constructor, the call is a prvalue of the // cv-unqualified version of the destination type whose return object // is initialized by the constructor. The call is used to // direct-initialize, according to the rules above, the object that // is the destination of the copy-initialization. // Therefore we need to do nothing further. // // FIXME: Mark this copy as extraneous. if (!S.getLangOpts().CPlusPlus17) Sequence.AddFinalCopy(DestType); else if (DestType.hasQualifiers()) Sequence.AddQualificationConversionStep(DestType, VK_RValue); return; } // Add the user-defined conversion step that calls the conversion function. QualType ConvType = Function->getCallResultType(); Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType, HadMultipleCandidates); if (ConvType->getAs()) { // The call is used to direct-initialize [...] the object that is the // destination of the copy-initialization. // // In C++17, this does not call a constructor if we enter /17.6.1: // - If the initializer expression is a prvalue and the cv-unqualified // version of the source type is the same as the class of the // destination [... do not make an extra copy] // // FIXME: Mark this copy as extraneous. if (!S.getLangOpts().CPlusPlus17 || Function->getReturnType()->isReferenceType() || !S.Context.hasSameUnqualifiedType(ConvType, DestType)) Sequence.AddFinalCopy(DestType); else if (!S.Context.hasSameType(ConvType, DestType)) Sequence.AddQualificationConversionStep(DestType, VK_RValue); return; } // If the conversion following the call to the conversion function // is interesting, add it as a separate step. if (Best->FinalConversion.First || Best->FinalConversion.Second || Best->FinalConversion.Third) { ImplicitConversionSequence ICS; ICS.setStandard(); ICS.Standard = Best->FinalConversion; Sequence.AddConversionSequenceStep(ICS, DestType, TopLevelOfInitList); } } /// An egregious hack for compatibility with libstdc++-4.2: in , /// a function with a pointer return type contains a 'return false;' statement. /// In C++11, 'false' is not a null pointer, so this breaks the build of any /// code using that header. /// /// Work around this by treating 'return false;' as zero-initializing the result /// if it's used in a pointer-returning function in a system header. static bool isLibstdcxxPointerReturnFalseHack(Sema &S, const InitializedEntity &Entity, const Expr *Init) { return S.getLangOpts().CPlusPlus11 && Entity.getKind() == InitializedEntity::EK_Result && Entity.getType()->isPointerType() && isa(Init) && !cast(Init)->getValue() && S.getSourceManager().isInSystemHeader(Init->getExprLoc()); } /// The non-zero enum values here are indexes into diagnostic alternatives. enum InvalidICRKind { IIK_okay, IIK_nonlocal, IIK_nonscalar }; /// Determines whether this expression is an acceptable ICR source. static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e, bool isAddressOf, bool &isWeakAccess) { // Skip parens. e = e->IgnoreParens(); // Skip address-of nodes. if (UnaryOperator *op = dyn_cast(e)) { if (op->getOpcode() == UO_AddrOf) return isInvalidICRSource(C, op->getSubExpr(), /*addressof*/ true, isWeakAccess); // Skip certain casts. } else if (CastExpr *ce = dyn_cast(e)) { switch (ce->getCastKind()) { case CK_Dependent: case CK_BitCast: case CK_LValueBitCast: case CK_NoOp: return isInvalidICRSource(C, ce->getSubExpr(), isAddressOf, isWeakAccess); case CK_ArrayToPointerDecay: return IIK_nonscalar; case CK_NullToPointer: return IIK_okay; default: break; } // If we have a declaration reference, it had better be a local variable. } else if (isa(e)) { // set isWeakAccess to true, to mean that there will be an implicit // load which requires a cleanup. if (e->getType().getObjCLifetime() == Qualifiers::OCL_Weak) isWeakAccess = true; if (!isAddressOf) return IIK_nonlocal; VarDecl *var = dyn_cast(cast(e)->getDecl()); if (!var) return IIK_nonlocal; return (var->hasLocalStorage() ? IIK_okay : IIK_nonlocal); // If we have a conditional operator, check both sides. } else if (ConditionalOperator *cond = dyn_cast(e)) { if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS(), isAddressOf, isWeakAccess)) return iik; return isInvalidICRSource(C, cond->getRHS(), isAddressOf, isWeakAccess); // These are never scalar. } else if (isa(e)) { return IIK_nonscalar; // Otherwise, it needs to be a null pointer constant. } else { return (e->isNullPointerConstant(C, Expr::NPC_ValueDependentIsNull) ? IIK_okay : IIK_nonlocal); } return IIK_nonlocal; } /// Check whether the given expression is a valid operand for an /// indirect copy/restore. static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) { assert(src->isRValue()); bool isWeakAccess = false; InvalidICRKind iik = isInvalidICRSource(S.Context, src, false, isWeakAccess); // If isWeakAccess to true, there will be an implicit // load which requires a cleanup. if (S.getLangOpts().ObjCAutoRefCount && isWeakAccess) S.Cleanup.setExprNeedsCleanups(true); if (iik == IIK_okay) return; S.Diag(src->getExprLoc(), diag::err_arc_nonlocal_writeback) << ((unsigned) iik - 1) // shift index into diagnostic explanations << src->getSourceRange(); } /// Determine whether we have compatible array types for the /// purposes of GNU by-copy array initialization. static bool hasCompatibleArrayTypes(ASTContext &Context, const ArrayType *Dest, const ArrayType *Source) { // If the source and destination array types are equivalent, we're // done. if (Context.hasSameType(QualType(Dest, 0), QualType(Source, 0))) return true; // Make sure that the element types are the same. if (!Context.hasSameType(Dest->getElementType(), Source->getElementType())) return false; // The only mismatch we allow is when the destination is an // incomplete array type and the source is a constant array type. return Source->isConstantArrayType() && Dest->isIncompleteArrayType(); } static bool tryObjCWritebackConversion(Sema &S, InitializationSequence &Sequence, const InitializedEntity &Entity, Expr *Initializer) { bool ArrayDecay = false; QualType ArgType = Initializer->getType(); QualType ArgPointee; if (const ArrayType *ArgArrayType = S.Context.getAsArrayType(ArgType)) { ArrayDecay = true; ArgPointee = ArgArrayType->getElementType(); ArgType = S.Context.getPointerType(ArgPointee); } // Handle write-back conversion. QualType ConvertedArgType; if (!S.isObjCWritebackConversion(ArgType, Entity.getType(), ConvertedArgType)) return false; // We should copy unless we're passing to an argument explicitly // marked 'out'. bool ShouldCopy = true; if (ParmVarDecl *param = cast_or_null(Entity.getDecl())) ShouldCopy = (param->getObjCDeclQualifier() != ParmVarDecl::OBJC_TQ_Out); // Do we need an lvalue conversion? if (ArrayDecay || Initializer->isGLValue()) { ImplicitConversionSequence ICS; ICS.setStandard(); ICS.Standard.setAsIdentityConversion(); QualType ResultType; if (ArrayDecay) { ICS.Standard.First = ICK_Array_To_Pointer; ResultType = S.Context.getPointerType(ArgPointee); } else { ICS.Standard.First = ICK_Lvalue_To_Rvalue; ResultType = Initializer->getType().getNonLValueExprType(S.Context); } Sequence.AddConversionSequenceStep(ICS, ResultType); } Sequence.AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy); return true; } static bool TryOCLSamplerInitialization(Sema &S, InitializationSequence &Sequence, QualType DestType, Expr *Initializer) { if (!S.getLangOpts().OpenCL || !DestType->isSamplerT() || (!Initializer->isIntegerConstantExpr(S.Context) && !Initializer->getType()->isSamplerT())) return false; Sequence.AddOCLSamplerInitStep(DestType); return true; } // // OpenCL 1.2 spec, s6.12.10 // // The event argument can also be used to associate the // async_work_group_copy with a previous async copy allowing // an event to be shared by multiple async copies; otherwise // event should be zero. // static bool TryOCLZeroEventInitialization(Sema &S, InitializationSequence &Sequence, QualType DestType, Expr *Initializer) { if (!S.getLangOpts().OpenCL || !DestType->isEventT() || !Initializer->isIntegerConstantExpr(S.getASTContext()) || (Initializer->EvaluateKnownConstInt(S.getASTContext()) != 0)) return false; Sequence.AddOCLZeroEventStep(DestType); return true; } static bool TryOCLZeroQueueInitialization(Sema &S, InitializationSequence &Sequence, QualType DestType, Expr *Initializer) { if (!S.getLangOpts().OpenCL || S.getLangOpts().OpenCLVersion < 200 || !DestType->isQueueT() || !Initializer->isIntegerConstantExpr(S.getASTContext()) || (Initializer->EvaluateKnownConstInt(S.getASTContext()) != 0)) return false; Sequence.AddOCLZeroQueueStep(DestType); return true; } InitializationSequence::InitializationSequence(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, bool TopLevelOfInitList, bool TreatUnavailableAsInvalid) : FailedCandidateSet(Kind.getLocation(), OverloadCandidateSet::CSK_Normal) { InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList, TreatUnavailableAsInvalid); } /// Tries to get a FunctionDecl out of `E`. If it succeeds and we can take the /// address of that function, this returns true. Otherwise, it returns false. static bool isExprAnUnaddressableFunction(Sema &S, const Expr *E) { auto *DRE = dyn_cast(E); if (!DRE || !isa(DRE->getDecl())) return false; return !S.checkAddressOfFunctionIsAvailable( cast(DRE->getDecl())); } /// Determine whether we can perform an elementwise array copy for this kind /// of entity. static bool canPerformArrayCopy(const InitializedEntity &Entity) { switch (Entity.getKind()) { case InitializedEntity::EK_LambdaCapture: // C++ [expr.prim.lambda]p24: // For array members, the array elements are direct-initialized in // increasing subscript order. return true; case InitializedEntity::EK_Variable: // C++ [dcl.decomp]p1: // [...] each element is copy-initialized or direct-initialized from the // corresponding element of the assignment-expression [...] return isa(Entity.getDecl()); case InitializedEntity::EK_Member: // C++ [class.copy.ctor]p14: // - if the member is an array, each element is direct-initialized with // the corresponding subobject of x return Entity.isImplicitMemberInitializer(); case InitializedEntity::EK_ArrayElement: // All the above cases are intended to apply recursively, even though none // of them actually say that. if (auto *E = Entity.getParent()) return canPerformArrayCopy(*E); break; default: break; } return false; } void InitializationSequence::InitializeFrom(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, bool TopLevelOfInitList, bool TreatUnavailableAsInvalid) { ASTContext &Context = S.Context; // Eliminate non-overload placeholder types in the arguments. We // need to do this before checking whether types are dependent // because lowering a pseudo-object expression might well give us // something of dependent type. for (unsigned I = 0, E = Args.size(); I != E; ++I) if (Args[I]->getType()->isNonOverloadPlaceholderType()) { // FIXME: should we be doing this here? ExprResult result = S.CheckPlaceholderExpr(Args[I]); if (result.isInvalid()) { SetFailed(FK_PlaceholderType); return; } Args[I] = result.get(); } // C++0x [dcl.init]p16: // The semantics of initializers are as follows. The destination type is // the type of the object or reference being initialized and the source // type is the type of the initializer expression. The source type is not // defined when the initializer is a braced-init-list or when it is a // parenthesized list of expressions. QualType DestType = Entity.getType(); if (DestType->isDependentType() || Expr::hasAnyTypeDependentArguments(Args)) { SequenceKind = DependentSequence; return; } // Almost everything is a normal sequence. setSequenceKind(NormalSequence); QualType SourceType; Expr *Initializer = nullptr; if (Args.size() == 1) { Initializer = Args[0]; if (S.getLangOpts().ObjC1) { if (S.CheckObjCBridgeRelatedConversions(Initializer->getLocStart(), DestType, Initializer->getType(), Initializer) || S.ConversionToObjCStringLiteralCheck(DestType, Initializer)) Args[0] = Initializer; } if (!isa(Initializer)) SourceType = Initializer->getType(); } // - If the initializer is a (non-parenthesized) braced-init-list, the // object is list-initialized (8.5.4). if (Kind.getKind() != InitializationKind::IK_Direct) { if (InitListExpr *InitList = dyn_cast_or_null(Initializer)) { TryListInitialization(S, Entity, Kind, InitList, *this, TreatUnavailableAsInvalid); return; } } // - If the destination type is a reference type, see 8.5.3. if (DestType->isReferenceType()) { // C++0x [dcl.init.ref]p1: // A variable declared to be a T& or T&&, that is, "reference to type T" // (8.3.2), shall be initialized by an object, or function, of type T or // by an object that can be converted into a T. // (Therefore, multiple arguments are not permitted.) if (Args.size() != 1) SetFailed(FK_TooManyInitsForReference); // C++17 [dcl.init.ref]p5: // A reference [...] is initialized by an expression [...] as follows: // If the initializer is not an expression, presumably we should reject, // but the standard fails to actually say so. else if (isa(Args[0])) SetFailed(FK_ParenthesizedListInitForReference); else TryReferenceInitialization(S, Entity, Kind, Args[0], *this); return; } // - If the initializer is (), the object is value-initialized. if (Kind.getKind() == InitializationKind::IK_Value || (Kind.getKind() == InitializationKind::IK_Direct && Args.empty())) { TryValueInitialization(S, Entity, Kind, *this); return; } // Handle default initialization. if (Kind.getKind() == InitializationKind::IK_Default) { TryDefaultInitialization(S, Entity, Kind, *this); return; } // - If the destination type is an array of characters, an array of // char16_t, an array of char32_t, or an array of wchar_t, and the // initializer is a string literal, see 8.5.2. // - Otherwise, if the destination type is an array, the program is // ill-formed. if (const ArrayType *DestAT = Context.getAsArrayType(DestType)) { if (Initializer && isa(DestAT)) { SetFailed(FK_VariableLengthArrayHasInitializer); return; } if (Initializer) { switch (IsStringInit(Initializer, DestAT, Context)) { case SIF_None: TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this); return; case SIF_NarrowStringIntoWideChar: SetFailed(FK_NarrowStringIntoWideCharArray); return; case SIF_WideStringIntoChar: SetFailed(FK_WideStringIntoCharArray); return; case SIF_IncompatWideStringIntoWideChar: SetFailed(FK_IncompatWideStringIntoWideChar); return; case SIF_PlainStringIntoUTF8Char: SetFailed(FK_PlainStringIntoUTF8Char); return; case SIF_UTF8StringIntoPlainChar: SetFailed(FK_UTF8StringIntoPlainChar); return; case SIF_Other: break; } } // Some kinds of initialization permit an array to be initialized from // another array of the same type, and perform elementwise initialization. if (Initializer && isa(DestAT) && S.Context.hasSameUnqualifiedType(Initializer->getType(), Entity.getType()) && canPerformArrayCopy(Entity)) { // If source is a prvalue, use it directly. if (Initializer->getValueKind() == VK_RValue) { AddArrayInitStep(DestType, /*IsGNUExtension*/false); return; } // Emit element-at-a-time copy loop. InitializedEntity Element = InitializedEntity::InitializeElement(S.Context, 0, Entity); QualType InitEltT = Context.getAsArrayType(Initializer->getType())->getElementType(); OpaqueValueExpr OVE(Initializer->getExprLoc(), InitEltT, Initializer->getValueKind(), Initializer->getObjectKind()); Expr *OVEAsExpr = &OVE; InitializeFrom(S, Element, Kind, OVEAsExpr, TopLevelOfInitList, TreatUnavailableAsInvalid); if (!Failed()) AddArrayInitLoopStep(Entity.getType(), InitEltT); return; } // Note: as an GNU C extension, we allow initialization of an // array from a compound literal that creates an array of the same // type, so long as the initializer has no side effects. if (!S.getLangOpts().CPlusPlus && Initializer && isa(Initializer->IgnoreParens()) && Initializer->getType()->isArrayType()) { const ArrayType *SourceAT = Context.getAsArrayType(Initializer->getType()); if (!hasCompatibleArrayTypes(S.Context, DestAT, SourceAT)) SetFailed(FK_ArrayTypeMismatch); else if (Initializer->HasSideEffects(S.Context)) SetFailed(FK_NonConstantArrayInit); else { AddArrayInitStep(DestType, /*IsGNUExtension*/true); } } // Note: as a GNU C++ extension, we allow list-initialization of a // class member of array type from a parenthesized initializer list. else if (S.getLangOpts().CPlusPlus && Entity.getKind() == InitializedEntity::EK_Member && Initializer && isa(Initializer)) { TryListInitialization(S, Entity, Kind, cast(Initializer), *this, TreatUnavailableAsInvalid); AddParenthesizedArrayInitStep(DestType); } else if (DestAT->getElementType()->isCharType()) SetFailed(FK_ArrayNeedsInitListOrStringLiteral); else if (IsWideCharCompatible(DestAT->getElementType(), Context)) SetFailed(FK_ArrayNeedsInitListOrWideStringLiteral); else SetFailed(FK_ArrayNeedsInitList); return; } // Determine whether we should consider writeback conversions for // Objective-C ARC. bool allowObjCWritebackConversion = S.getLangOpts().ObjCAutoRefCount && Entity.isParameterKind(); // We're at the end of the line for C: it's either a write-back conversion // or it's a C assignment. There's no need to check anything else. if (!S.getLangOpts().CPlusPlus) { // If allowed, check whether this is an Objective-C writeback conversion. if (allowObjCWritebackConversion && tryObjCWritebackConversion(S, *this, Entity, Initializer)) { return; } if (TryOCLSamplerInitialization(S, *this, DestType, Initializer)) return; if (TryOCLZeroEventInitialization(S, *this, DestType, Initializer)) return; if (TryOCLZeroQueueInitialization(S, *this, DestType, Initializer)) return; // Handle initialization in C AddCAssignmentStep(DestType); MaybeProduceObjCObject(S, *this, Entity); return; } assert(S.getLangOpts().CPlusPlus); // - If the destination type is a (possibly cv-qualified) class type: if (DestType->isRecordType()) { // - If the initialization is direct-initialization, or if it is // copy-initialization where the cv-unqualified version of the // source type is the same class as, or a derived class of, the // class of the destination, constructors are considered. [...] if (Kind.getKind() == InitializationKind::IK_Direct || (Kind.getKind() == InitializationKind::IK_Copy && (Context.hasSameUnqualifiedType(SourceType, DestType) || S.IsDerivedFrom(Initializer->getLocStart(), SourceType, DestType)))) TryConstructorInitialization(S, Entity, Kind, Args, DestType, DestType, *this); // - Otherwise (i.e., for the remaining copy-initialization cases), // user-defined conversion sequences that can convert from the source // type to the destination type or (when a conversion function is // used) to a derived class thereof are enumerated as described in // 13.3.1.4, and the best one is chosen through overload resolution // (13.3). else TryUserDefinedConversion(S, DestType, Kind, Initializer, *this, TopLevelOfInitList); return; } assert(Args.size() >= 1 && "Zero-argument case handled above"); // The remaining cases all need a source type. if (Args.size() > 1) { SetFailed(FK_TooManyInitsForScalar); return; } else if (isa(Args[0])) { SetFailed(FK_ParenthesizedListInitForScalar); return; } // - Otherwise, if the source type is a (possibly cv-qualified) class // type, conversion functions are considered. if (!SourceType.isNull() && SourceType->isRecordType()) { // For a conversion to _Atomic(T) from either T or a class type derived // from T, initialize the T object then convert to _Atomic type. bool NeedAtomicConversion = false; if (const AtomicType *Atomic = DestType->getAs()) { if (Context.hasSameUnqualifiedType(SourceType, Atomic->getValueType()) || S.IsDerivedFrom(Initializer->getLocStart(), SourceType, Atomic->getValueType())) { DestType = Atomic->getValueType(); NeedAtomicConversion = true; } } TryUserDefinedConversion(S, DestType, Kind, Initializer, *this, TopLevelOfInitList); MaybeProduceObjCObject(S, *this, Entity); if (!Failed() && NeedAtomicConversion) AddAtomicConversionStep(Entity.getType()); return; } // - Otherwise, the initial value of the object being initialized is the // (possibly converted) value of the initializer expression. Standard // conversions (Clause 4) will be used, if necessary, to convert the // initializer expression to the cv-unqualified version of the // destination type; no user-defined conversions are considered. ImplicitConversionSequence ICS = S.TryImplicitConversion(Initializer, DestType, /*SuppressUserConversions*/true, /*AllowExplicitConversions*/ false, /*InOverloadResolution*/ false, /*CStyle=*/Kind.isCStyleOrFunctionalCast(), allowObjCWritebackConversion); if (ICS.isStandard() && ICS.Standard.Second == ICK_Writeback_Conversion) { // Objective-C ARC writeback conversion. // We should copy unless we're passing to an argument explicitly // marked 'out'. bool ShouldCopy = true; if (ParmVarDecl *Param = cast_or_null(Entity.getDecl())) ShouldCopy = (Param->getObjCDeclQualifier() != ParmVarDecl::OBJC_TQ_Out); // If there was an lvalue adjustment, add it as a separate conversion. if (ICS.Standard.First == ICK_Array_To_Pointer || ICS.Standard.First == ICK_Lvalue_To_Rvalue) { ImplicitConversionSequence LvalueICS; LvalueICS.setStandard(); LvalueICS.Standard.setAsIdentityConversion(); LvalueICS.Standard.setAllToTypes(ICS.Standard.getToType(0)); LvalueICS.Standard.First = ICS.Standard.First; AddConversionSequenceStep(LvalueICS, ICS.Standard.getToType(0)); } AddPassByIndirectCopyRestoreStep(DestType, ShouldCopy); } else if (ICS.isBad()) { DeclAccessPair dap; if (isLibstdcxxPointerReturnFalseHack(S, Entity, Initializer)) { AddZeroInitializationStep(Entity.getType()); } else if (Initializer->getType() == Context.OverloadTy && !S.ResolveAddressOfOverloadedFunction(Initializer, DestType, false, dap)) SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); else if (Initializer->getType()->isFunctionType() && isExprAnUnaddressableFunction(S, Initializer)) SetFailed(InitializationSequence::FK_AddressOfUnaddressableFunction); else SetFailed(InitializationSequence::FK_ConversionFailed); } else { AddConversionSequenceStep(ICS, DestType, TopLevelOfInitList); MaybeProduceObjCObject(S, *this, Entity); } } InitializationSequence::~InitializationSequence() { for (auto &S : Steps) S.Destroy(); } //===----------------------------------------------------------------------===// // Perform initialization //===----------------------------------------------------------------------===// static Sema::AssignmentAction getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) { switch(Entity.getKind()) { case InitializedEntity::EK_Variable: case InitializedEntity::EK_New: case InitializedEntity::EK_Exception: case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: return Sema::AA_Initializing; case InitializedEntity::EK_Parameter: if (Entity.getDecl() && isa(Entity.getDecl()->getDeclContext())) return Sema::AA_Sending; return Sema::AA_Passing; case InitializedEntity::EK_Parameter_CF_Audited: if (Entity.getDecl() && isa(Entity.getDecl()->getDeclContext())) return Sema::AA_Sending; return !Diagnose ? Sema::AA_Passing : Sema::AA_Passing_CFAudited; case InitializedEntity::EK_Result: case InitializedEntity::EK_StmtExprResult: // FIXME: Not quite right. return Sema::AA_Returning; case InitializedEntity::EK_Temporary: case InitializedEntity::EK_RelatedResult: // FIXME: Can we tell apart casting vs. converting? return Sema::AA_Casting; case InitializedEntity::EK_Member: case InitializedEntity::EK_Binding: case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: case InitializedEntity::EK_CompoundLiteralInit: return Sema::AA_Initializing; } llvm_unreachable("Invalid EntityKind!"); } /// Whether we should bind a created object as a temporary when /// initializing the given entity. static bool shouldBindAsTemporary(const InitializedEntity &Entity) { switch (Entity.getKind()) { case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Member: case InitializedEntity::EK_Result: case InitializedEntity::EK_StmtExprResult: case InitializedEntity::EK_New: case InitializedEntity::EK_Variable: case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_Exception: case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: case InitializedEntity::EK_CompoundLiteralInit: return false; case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: case InitializedEntity::EK_Temporary: case InitializedEntity::EK_RelatedResult: case InitializedEntity::EK_Binding: return true; } llvm_unreachable("missed an InitializedEntity kind?"); } /// Whether the given entity, when initialized with an object /// created for that initialization, requires destruction. static bool shouldDestroyEntity(const InitializedEntity &Entity) { switch (Entity.getKind()) { case InitializedEntity::EK_Result: case InitializedEntity::EK_StmtExprResult: case InitializedEntity::EK_New: case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: return false; case InitializedEntity::EK_Member: case InitializedEntity::EK_Binding: case InitializedEntity::EK_Variable: case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: case InitializedEntity::EK_Temporary: case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Exception: case InitializedEntity::EK_CompoundLiteralInit: case InitializedEntity::EK_RelatedResult: return true; } llvm_unreachable("missed an InitializedEntity kind?"); } /// Get the location at which initialization diagnostics should appear. static SourceLocation getInitializationLoc(const InitializedEntity &Entity, Expr *Initializer) { switch (Entity.getKind()) { case InitializedEntity::EK_Result: case InitializedEntity::EK_StmtExprResult: return Entity.getReturnLoc(); case InitializedEntity::EK_Exception: return Entity.getThrowLoc(); case InitializedEntity::EK_Variable: case InitializedEntity::EK_Binding: return Entity.getDecl()->getLocation(); case InitializedEntity::EK_LambdaCapture: return Entity.getCaptureLoc(); case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_Member: case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: case InitializedEntity::EK_Temporary: case InitializedEntity::EK_New: case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_CompoundLiteralInit: case InitializedEntity::EK_RelatedResult: return Initializer->getLocStart(); } llvm_unreachable("missed an InitializedEntity kind?"); } /// Make a (potentially elidable) temporary copy of the object /// provided by the given initializer by calling the appropriate copy /// constructor. /// /// \param S The Sema object used for type-checking. /// /// \param T The type of the temporary object, which must either be /// the type of the initializer expression or a superclass thereof. /// /// \param Entity The entity being initialized. /// /// \param CurInit The initializer expression. /// /// \param IsExtraneousCopy Whether this is an "extraneous" copy that /// is permitted in C++03 (but not C++0x) when binding a reference to /// an rvalue. /// /// \returns An expression that copies the initializer expression into /// a temporary object, or an error expression if a copy could not be /// created. static ExprResult CopyObject(Sema &S, QualType T, const InitializedEntity &Entity, ExprResult CurInit, bool IsExtraneousCopy) { if (CurInit.isInvalid()) return CurInit; // Determine which class type we're copying to. Expr *CurInitExpr = (Expr *)CurInit.get(); CXXRecordDecl *Class = nullptr; if (const RecordType *Record = T->getAs()) Class = cast(Record->getDecl()); if (!Class) return CurInit; SourceLocation Loc = getInitializationLoc(Entity, CurInit.get()); // Make sure that the type we are copying is complete. if (S.RequireCompleteType(Loc, T, diag::err_temp_copy_incomplete)) return CurInit; // Perform overload resolution using the class's constructors. Per // C++11 [dcl.init]p16, second bullet for class types, this initialization // is direct-initialization. OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); DeclContext::lookup_result Ctors = S.LookupConstructors(Class); OverloadCandidateSet::iterator Best; switch (ResolveConstructorOverload( S, Loc, CurInitExpr, CandidateSet, T, Ctors, Best, /*CopyInitializing=*/false, /*AllowExplicit=*/true, /*OnlyListConstructors=*/false, /*IsListInit=*/false, /*SecondStepOfCopyInit=*/true)) { case OR_Success: break; case OR_No_Viable_Function: S.Diag(Loc, IsExtraneousCopy && !S.isSFINAEContext() ? diag::ext_rvalue_to_reference_temp_copy_no_viable : diag::err_temp_copy_no_viable) << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); CandidateSet.NoteCandidates(S, OCD_AllCandidates, CurInitExpr); if (!IsExtraneousCopy || S.isSFINAEContext()) return ExprError(); return CurInit; case OR_Ambiguous: S.Diag(Loc, diag::err_temp_copy_ambiguous) << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); CandidateSet.NoteCandidates(S, OCD_ViableCandidates, CurInitExpr); return ExprError(); case OR_Deleted: S.Diag(Loc, diag::err_temp_copy_deleted) << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); S.NoteDeletedFunction(Best->Function); return ExprError(); } bool HadMultipleCandidates = CandidateSet.size() > 1; CXXConstructorDecl *Constructor = cast(Best->Function); SmallVector ConstructorArgs; CurInit.get(); // Ownership transferred into MultiExprArg, below. S.CheckConstructorAccess(Loc, Constructor, Best->FoundDecl, Entity, IsExtraneousCopy); if (IsExtraneousCopy) { // If this is a totally extraneous copy for C++03 reference // binding purposes, just return the original initialization // expression. We don't generate an (elided) copy operation here // because doing so would require us to pass down a flag to avoid // infinite recursion, where each step adds another extraneous, // elidable copy. // Instantiate the default arguments of any extra parameters in // the selected copy constructor, as if we were going to create a // proper call to the copy constructor. for (unsigned I = 1, N = Constructor->getNumParams(); I != N; ++I) { ParmVarDecl *Parm = Constructor->getParamDecl(I); if (S.RequireCompleteType(Loc, Parm->getType(), diag::err_call_incomplete_argument)) break; // Build the default argument expression; we don't actually care // if this succeeds or not, because this routine will complain // if there was a problem. S.BuildCXXDefaultArgExpr(Loc, Constructor, Parm); } return CurInitExpr; } // Determine the arguments required to actually perform the // constructor call (we might have derived-to-base conversions, or // the copy constructor may have default arguments). if (S.CompleteConstructorCall(Constructor, CurInitExpr, Loc, ConstructorArgs)) return ExprError(); // C++0x [class.copy]p32: // When certain criteria are met, an implementation is allowed to // omit the copy/move construction of a class object, even if the // copy/move constructor and/or destructor for the object have // side effects. [...] // - when a temporary class object that has not been bound to a // reference (12.2) would be copied/moved to a class object // with the same cv-unqualified type, the copy/move operation // can be omitted by constructing the temporary object // directly into the target of the omitted copy/move // // Note that the other three bullets are handled elsewhere. Copy // elision for return statements and throw expressions are handled as part // of constructor initialization, while copy elision for exception handlers // is handled by the run-time. // // FIXME: If the function parameter is not the same type as the temporary, we // should still be able to elide the copy, but we don't have a way to // represent in the AST how much should be elided in this case. bool Elidable = CurInitExpr->isTemporaryObject(S.Context, Class) && S.Context.hasSameUnqualifiedType( Best->Function->getParamDecl(0)->getType().getNonReferenceType(), CurInitExpr->getType()); // Actually perform the constructor call. CurInit = S.BuildCXXConstructExpr(Loc, T, Best->FoundDecl, Constructor, Elidable, ConstructorArgs, HadMultipleCandidates, /*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); // If we're supposed to bind temporaries, do so. if (!CurInit.isInvalid() && shouldBindAsTemporary(Entity)) CurInit = S.MaybeBindToTemporary(CurInit.getAs()); return CurInit; } /// Check whether elidable copy construction for binding a reference to /// a temporary would have succeeded if we were building in C++98 mode, for /// -Wc++98-compat. static void CheckCXX98CompatAccessibleCopy(Sema &S, const InitializedEntity &Entity, Expr *CurInitExpr) { assert(S.getLangOpts().CPlusPlus11); const RecordType *Record = CurInitExpr->getType()->getAs(); if (!Record) return; SourceLocation Loc = getInitializationLoc(Entity, CurInitExpr); if (S.Diags.isIgnored(diag::warn_cxx98_compat_temp_copy, Loc)) return; // Find constructors which would have been considered. OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); DeclContext::lookup_result Ctors = S.LookupConstructors(cast(Record->getDecl())); // Perform overload resolution. OverloadCandidateSet::iterator Best; OverloadingResult OR = ResolveConstructorOverload( S, Loc, CurInitExpr, CandidateSet, CurInitExpr->getType(), Ctors, Best, /*CopyInitializing=*/false, /*AllowExplicit=*/true, /*OnlyListConstructors=*/false, /*IsListInit=*/false, /*SecondStepOfCopyInit=*/true); PartialDiagnostic Diag = S.PDiag(diag::warn_cxx98_compat_temp_copy) << OR << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); switch (OR) { case OR_Success: S.CheckConstructorAccess(Loc, cast(Best->Function), Best->FoundDecl, Entity, Diag); // FIXME: Check default arguments as far as that's possible. break; case OR_No_Viable_Function: S.Diag(Loc, Diag); CandidateSet.NoteCandidates(S, OCD_AllCandidates, CurInitExpr); break; case OR_Ambiguous: S.Diag(Loc, Diag); CandidateSet.NoteCandidates(S, OCD_ViableCandidates, CurInitExpr); break; case OR_Deleted: S.Diag(Loc, Diag); S.NoteDeletedFunction(Best->Function); break; } } void InitializationSequence::PrintInitLocationNote(Sema &S, const InitializedEntity &Entity) { if (Entity.isParameterKind() && Entity.getDecl()) { if (Entity.getDecl()->getLocation().isInvalid()) return; if (Entity.getDecl()->getDeclName()) S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_named_here) << Entity.getDecl()->getDeclName(); else S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_here); } else if (Entity.getKind() == InitializedEntity::EK_RelatedResult && Entity.getMethodDecl()) S.Diag(Entity.getMethodDecl()->getLocation(), diag::note_method_return_type_change) << Entity.getMethodDecl()->getDeclName(); } /// Returns true if the parameters describe a constructor initialization of /// an explicit temporary object, e.g. "Point(x, y)". static bool isExplicitTemporary(const InitializedEntity &Entity, const InitializationKind &Kind, unsigned NumArgs) { switch (Entity.getKind()) { case InitializedEntity::EK_Temporary: case InitializedEntity::EK_CompoundLiteralInit: case InitializedEntity::EK_RelatedResult: break; default: return false; } switch (Kind.getKind()) { case InitializationKind::IK_DirectList: return true; // FIXME: Hack to work around cast weirdness. case InitializationKind::IK_Direct: case InitializationKind::IK_Value: return NumArgs != 1; default: return false; } } static ExprResult PerformConstructorInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, const InitializationSequence::Step& Step, bool &ConstructorInitRequiresZeroInit, bool IsListInitialization, bool IsStdInitListInitialization, SourceLocation LBraceLoc, SourceLocation RBraceLoc) { unsigned NumArgs = Args.size(); CXXConstructorDecl *Constructor = cast(Step.Function.Function); bool HadMultipleCandidates = Step.Function.HadMultipleCandidates; // Build a call to the selected constructor. SmallVector ConstructorArgs; SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid()) ? Kind.getEqualLoc() : Kind.getLocation(); if (Kind.getKind() == InitializationKind::IK_Default) { // Force even a trivial, implicit default constructor to be // semantically checked. We do this explicitly because we don't build // the definition for completely trivial constructors. assert(Constructor->getParent() && "No parent class for constructor."); if (Constructor->isDefaulted() && Constructor->isDefaultConstructor() && Constructor->isTrivial() && !Constructor->isUsed(false)) S.DefineImplicitDefaultConstructor(Loc, Constructor); } ExprResult CurInit((Expr *)nullptr); // C++ [over.match.copy]p1: // - When initializing a temporary to be bound to the first parameter // of a constructor that takes a reference to possibly cv-qualified // T as its first argument, called with a single argument in the // context of direct-initialization, explicit conversion functions // are also considered. bool AllowExplicitConv = Kind.AllowExplicit() && !Kind.isCopyInit() && Args.size() == 1 && hasCopyOrMoveCtorParam(S.Context, getConstructorInfo(Step.Function.FoundDecl)); // Determine the arguments required to actually perform the constructor // call. if (S.CompleteConstructorCall(Constructor, Args, Loc, ConstructorArgs, AllowExplicitConv, IsListInitialization)) return ExprError(); if (isExplicitTemporary(Entity, Kind, NumArgs)) { // An explicitly-constructed temporary, e.g., X(1, 2). if (S.DiagnoseUseOfDecl(Constructor, Loc)) return ExprError(); TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); if (!TSInfo) TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc); - SourceRange ParenOrBraceRange = Kind.getParenOrBraceRange(); + SourceRange ParenOrBraceRange = + (Kind.getKind() == InitializationKind::IK_DirectList) + ? SourceRange(LBraceLoc, RBraceLoc) + : Kind.getParenOrBraceRange(); if (auto *Shadow = dyn_cast( Step.Function.FoundDecl.getDecl())) { Constructor = S.findInheritingConstructor(Loc, Constructor, Shadow); if (S.DiagnoseUseOfDecl(Constructor, Loc)) return ExprError(); } S.MarkFunctionReferenced(Loc, Constructor); CurInit = new (S.Context) CXXTemporaryObjectExpr( S.Context, Constructor, Entity.getType().getNonLValueExprType(S.Context), TSInfo, ConstructorArgs, ParenOrBraceRange, HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, ConstructorInitRequiresZeroInit); } else { CXXConstructExpr::ConstructionKind ConstructKind = CXXConstructExpr::CK_Complete; if (Entity.getKind() == InitializedEntity::EK_Base) { ConstructKind = Entity.getBaseSpecifier()->isVirtual() ? CXXConstructExpr::CK_VirtualBase : CXXConstructExpr::CK_NonVirtualBase; } else if (Entity.getKind() == InitializedEntity::EK_Delegating) { ConstructKind = CXXConstructExpr::CK_Delegating; } // Only get the parenthesis or brace range if it is a list initialization or // direct construction. SourceRange ParenOrBraceRange; if (IsListInitialization) ParenOrBraceRange = SourceRange(LBraceLoc, RBraceLoc); else if (Kind.getKind() == InitializationKind::IK_Direct) ParenOrBraceRange = Kind.getParenOrBraceRange(); // If the entity allows NRVO, mark the construction as elidable // unconditionally. if (Entity.allowsNRVO()) CurInit = S.BuildCXXConstructExpr(Loc, Step.Type, Step.Function.FoundDecl, Constructor, /*Elidable=*/true, ConstructorArgs, HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, ConstructorInitRequiresZeroInit, ConstructKind, ParenOrBraceRange); else CurInit = S.BuildCXXConstructExpr(Loc, Step.Type, Step.Function.FoundDecl, Constructor, ConstructorArgs, HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, ConstructorInitRequiresZeroInit, ConstructKind, ParenOrBraceRange); } if (CurInit.isInvalid()) return ExprError(); // Only check access if all of that succeeded. S.CheckConstructorAccess(Loc, Constructor, Step.Function.FoundDecl, Entity); if (S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc)) return ExprError(); if (shouldBindAsTemporary(Entity)) CurInit = S.MaybeBindToTemporary(CurInit.get()); return CurInit; } namespace { enum LifetimeKind { /// The lifetime of a temporary bound to this entity ends at the end of the /// full-expression, and that's (probably) fine. LK_FullExpression, /// The lifetime of a temporary bound to this entity is extended to the /// lifeitme of the entity itself. LK_Extended, /// The lifetime of a temporary bound to this entity probably ends too soon, /// because the entity is allocated in a new-expression. LK_New, /// The lifetime of a temporary bound to this entity ends too soon, because /// the entity is a return object. LK_Return, /// The lifetime of a temporary bound to this entity ends too soon, because /// the entity is the result of a statement expression. LK_StmtExprResult, /// This is a mem-initializer: if it would extend a temporary (other than via /// a default member initializer), the program is ill-formed. LK_MemInitializer, }; using LifetimeResult = llvm::PointerIntPair; } /// Determine the declaration which an initialized entity ultimately refers to, /// for the purpose of lifetime-extending a temporary bound to a reference in /// the initialization of \p Entity. static LifetimeResult getEntityLifetime( const InitializedEntity *Entity, const InitializedEntity *InitField = nullptr) { // C++11 [class.temporary]p5: switch (Entity->getKind()) { case InitializedEntity::EK_Variable: // The temporary [...] persists for the lifetime of the reference return {Entity, LK_Extended}; case InitializedEntity::EK_Member: // For subobjects, we look at the complete object. if (Entity->getParent()) return getEntityLifetime(Entity->getParent(), Entity); // except: // C++17 [class.base.init]p8: // A temporary expression bound to a reference member in a // mem-initializer is ill-formed. // C++17 [class.base.init]p11: // A temporary expression bound to a reference member from a // default member initializer is ill-formed. // // The context of p11 and its example suggest that it's only the use of a // default member initializer from a constructor that makes the program // ill-formed, not its mere existence, and that it can even be used by // aggregate initialization. return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended : LK_MemInitializer}; case InitializedEntity::EK_Binding: // Per [dcl.decomp]p3, the binding is treated as a variable of reference // type. return {Entity, LK_Extended}; case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: // -- A temporary bound to a reference parameter in a function call // persists until the completion of the full-expression containing // the call. return {nullptr, LK_FullExpression}; case InitializedEntity::EK_Result: // -- The lifetime of a temporary bound to the returned value in a // function return statement is not extended; the temporary is // destroyed at the end of the full-expression in the return statement. return {nullptr, LK_Return}; case InitializedEntity::EK_StmtExprResult: // FIXME: Should we lifetime-extend through the result of a statement // expression? return {nullptr, LK_StmtExprResult}; case InitializedEntity::EK_New: // -- A temporary bound to a reference in a new-initializer persists // until the completion of the full-expression containing the // new-initializer. return {nullptr, LK_New}; case InitializedEntity::EK_Temporary: case InitializedEntity::EK_CompoundLiteralInit: case InitializedEntity::EK_RelatedResult: // We don't yet know the storage duration of the surrounding temporary. // Assume it's got full-expression duration for now, it will patch up our // storage duration if that's not correct. return {nullptr, LK_FullExpression}; case InitializedEntity::EK_ArrayElement: // For subobjects, we look at the complete object. return getEntityLifetime(Entity->getParent(), InitField); case InitializedEntity::EK_Base: // For subobjects, we look at the complete object. if (Entity->getParent()) return getEntityLifetime(Entity->getParent(), InitField); return {InitField, LK_MemInitializer}; case InitializedEntity::EK_Delegating: // We can reach this case for aggregate initialization in a constructor: // struct A { int &&r; }; // struct B : A { B() : A{0} {} }; // In this case, use the outermost field decl as the context. return {InitField, LK_MemInitializer}; case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: return {nullptr, LK_FullExpression}; case InitializedEntity::EK_Exception: // FIXME: Can we diagnose lifetime problems with exceptions? return {nullptr, LK_FullExpression}; } llvm_unreachable("unknown entity kind"); } namespace { enum ReferenceKind { /// Lifetime would be extended by a reference binding to a temporary. RK_ReferenceBinding, /// Lifetime would be extended by a std::initializer_list object binding to /// its backing array. RK_StdInitializerList, }; /// A temporary or local variable. This will be one of: /// * A MaterializeTemporaryExpr. /// * A DeclRefExpr whose declaration is a local. /// * An AddrLabelExpr. /// * A BlockExpr for a block with captures. using Local = Expr*; /// Expressions we stepped over when looking for the local state. Any steps /// that would inhibit lifetime extension or take us out of subexpressions of /// the initializer are included. struct IndirectLocalPathEntry { enum EntryKind { DefaultInit, AddressOf, VarInit, LValToRVal, LifetimeBoundCall, } Kind; Expr *E; const Decl *D = nullptr; IndirectLocalPathEntry() {} IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {} IndirectLocalPathEntry(EntryKind K, Expr *E, const Decl *D) : Kind(K), E(E), D(D) {} }; using IndirectLocalPath = llvm::SmallVectorImpl; struct RevertToOldSizeRAII { IndirectLocalPath &Path; unsigned OldSize = Path.size(); RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {} ~RevertToOldSizeRAII() { Path.resize(OldSize); } }; using LocalVisitor = llvm::function_ref; } static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD) { for (auto E : Path) if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD) return true; return false; } static bool pathContainsInit(IndirectLocalPath &Path) { return std::any_of(Path.begin(), Path.end(), [=](IndirectLocalPathEntry E) { return E.Kind == IndirectLocalPathEntry::DefaultInit || E.Kind == IndirectLocalPathEntry::VarInit; }); } static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, Expr *Init, LocalVisitor Visit, bool RevisitSubinits); static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, Expr *Init, ReferenceKind RK, LocalVisitor Visit); static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) { const TypeSourceInfo *TSI = FD->getTypeSourceInfo(); if (!TSI) return false; // Don't declare this variable in the second operand of the for-statement; // GCC miscompiles that by ending its lifetime before evaluating the // third operand. See gcc.gnu.org/PR86769. AttributedTypeLoc ATL; for (TypeLoc TL = TSI->getTypeLoc(); (ATL = TL.getAsAdjusted()); TL = ATL.getModifiedLoc()) { if (ATL.getAttrKind() == AttributedType::attr_lifetimebound) return true; } return false; } static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call, LocalVisitor Visit) { const FunctionDecl *Callee; ArrayRef Args; if (auto *CE = dyn_cast(Call)) { Callee = CE->getDirectCallee(); Args = llvm::makeArrayRef(CE->getArgs(), CE->getNumArgs()); } else { auto *CCE = cast(Call); Callee = CCE->getConstructor(); Args = llvm::makeArrayRef(CCE->getArgs(), CCE->getNumArgs()); } if (!Callee) return; Expr *ObjectArg = nullptr; if (isa(Call) && Callee->isCXXInstanceMember()) { ObjectArg = Args[0]; Args = Args.slice(1); } else if (auto *MCE = dyn_cast(Call)) { ObjectArg = MCE->getImplicitObjectArgument(); } auto VisitLifetimeBoundArg = [&](const Decl *D, Expr *Arg) { Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D}); if (Arg->isGLValue()) visitLocalsRetainedByReferenceBinding(Path, Arg, RK_ReferenceBinding, Visit); else visitLocalsRetainedByInitializer(Path, Arg, Visit, true); Path.pop_back(); }; if (ObjectArg && implicitObjectParamIsLifetimeBound(Callee)) VisitLifetimeBoundArg(Callee, ObjectArg); for (unsigned I = 0, N = std::min(Callee->getNumParams(), Args.size()); I != N; ++I) { if (Callee->getParamDecl(I)->hasAttr()) VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]); } } /// Visit the locals that would be reachable through a reference bound to the /// glvalue expression \c Init. static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, Expr *Init, ReferenceKind RK, LocalVisitor Visit) { RevertToOldSizeRAII RAII(Path); // Walk past any constructs which we can lifetime-extend across. Expr *Old; do { Old = Init; if (auto *EWC = dyn_cast(Init)) Init = EWC->getSubExpr(); if (InitListExpr *ILE = dyn_cast(Init)) { // If this is just redundant braces around an initializer, step over it. if (ILE->isTransparent()) Init = ILE->getInit(0); } // Step over any subobject adjustments; we may have a materialized // temporary inside them. Init = const_cast(Init->skipRValueSubobjectAdjustments()); // Per current approach for DR1376, look through casts to reference type // when performing lifetime extension. if (CastExpr *CE = dyn_cast(Init)) if (CE->getSubExpr()->isGLValue()) Init = CE->getSubExpr(); // Per the current approach for DR1299, look through array element access // on array glvalues when performing lifetime extension. if (auto *ASE = dyn_cast(Init)) { Init = ASE->getBase(); auto *ICE = dyn_cast(Init); if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay) Init = ICE->getSubExpr(); else // We can't lifetime extend through this but we might still find some // retained temporaries. return visitLocalsRetainedByInitializer(Path, Init, Visit, true); } // Step into CXXDefaultInitExprs so we can diagnose cases where a // constructor inherits one as an implicit mem-initializer. if (auto *DIE = dyn_cast(Init)) { Path.push_back( {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()}); Init = DIE->getExpr(); } } while (Init != Old); if (auto *MTE = dyn_cast(Init)) { if (Visit(Path, Local(MTE), RK)) visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(), Visit, true); } if (isa(Init)) return visitLifetimeBoundArguments(Path, Init, Visit); switch (Init->getStmtClass()) { case Stmt::DeclRefExprClass: { // If we find the name of a local non-reference parameter, we could have a // lifetime problem. auto *DRE = cast(Init); auto *VD = dyn_cast(DRE->getDecl()); if (VD && VD->hasLocalStorage() && !DRE->refersToEnclosingVariableOrCapture()) { if (!VD->getType()->isReferenceType()) { Visit(Path, Local(DRE), RK); } else if (isa(DRE->getDecl())) { // The lifetime of a reference parameter is unknown; assume it's OK // for now. break; } else if (VD->getInit() && !isVarOnPath(Path, VD)) { Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD}); visitLocalsRetainedByReferenceBinding(Path, VD->getInit(), RK_ReferenceBinding, Visit); } } break; } case Stmt::UnaryOperatorClass: { // The only unary operator that make sense to handle here // is Deref. All others don't resolve to a "name." This includes // handling all sorts of rvalues passed to a unary operator. const UnaryOperator *U = cast(Init); if (U->getOpcode() == UO_Deref) visitLocalsRetainedByInitializer(Path, U->getSubExpr(), Visit, true); break; } case Stmt::OMPArraySectionExprClass: { visitLocalsRetainedByInitializer( Path, cast(Init)->getBase(), Visit, true); break; } case Stmt::ConditionalOperatorClass: case Stmt::BinaryConditionalOperatorClass: { auto *C = cast(Init); if (!C->getTrueExpr()->getType()->isVoidType()) visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit); if (!C->getFalseExpr()->getType()->isVoidType()) visitLocalsRetainedByReferenceBinding(Path, C->getFalseExpr(), RK, Visit); break; } // FIXME: Visit the left-hand side of an -> or ->*. default: break; } } /// Visit the locals that would be reachable through an object initialized by /// the prvalue expression \c Init. static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, Expr *Init, LocalVisitor Visit, bool RevisitSubinits) { RevertToOldSizeRAII RAII(Path); Expr *Old; do { Old = Init; // Step into CXXDefaultInitExprs so we can diagnose cases where a // constructor inherits one as an implicit mem-initializer. if (auto *DIE = dyn_cast(Init)) { Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()}); Init = DIE->getExpr(); } if (auto *EWC = dyn_cast(Init)) Init = EWC->getSubExpr(); // Dig out the expression which constructs the extended temporary. Init = const_cast(Init->skipRValueSubobjectAdjustments()); if (CXXBindTemporaryExpr *BTE = dyn_cast(Init)) Init = BTE->getSubExpr(); Init = Init->IgnoreParens(); // Step over value-preserving rvalue casts. if (auto *CE = dyn_cast(Init)) { switch (CE->getCastKind()) { case CK_LValueToRValue: // If we can match the lvalue to a const object, we can look at its // initializer. Path.push_back({IndirectLocalPathEntry::LValToRVal, CE}); return visitLocalsRetainedByReferenceBinding( Path, Init, RK_ReferenceBinding, [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool { if (auto *DRE = dyn_cast(L)) { auto *VD = dyn_cast(DRE->getDecl()); if (VD && VD->getType().isConstQualified() && VD->getInit() && !isVarOnPath(Path, VD)) { Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD}); visitLocalsRetainedByInitializer(Path, VD->getInit(), Visit, true); } } else if (auto *MTE = dyn_cast(L)) { if (MTE->getType().isConstQualified()) visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(), Visit, true); } return false; }); // We assume that objects can be retained by pointers cast to integers, // but not if the integer is cast to floating-point type or to _Complex. // We assume that casts to 'bool' do not preserve enough information to // retain a local object. case CK_NoOp: case CK_BitCast: case CK_BaseToDerived: case CK_DerivedToBase: case CK_UncheckedDerivedToBase: case CK_Dynamic: case CK_ToUnion: case CK_UserDefinedConversion: case CK_ConstructorConversion: case CK_IntegralToPointer: case CK_PointerToIntegral: case CK_VectorSplat: case CK_IntegralCast: case CK_CPointerToObjCPointerCast: case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_AddressSpaceConversion: break; case CK_ArrayToPointerDecay: // Model array-to-pointer decay as taking the address of the array // lvalue. Path.push_back({IndirectLocalPathEntry::AddressOf, CE}); return visitLocalsRetainedByReferenceBinding(Path, CE->getSubExpr(), RK_ReferenceBinding, Visit); default: return; } Init = CE->getSubExpr(); } } while (Old != Init); // C++17 [dcl.init.list]p6: // initializing an initializer_list object from the array extends the // lifetime of the array exactly like binding a reference to a temporary. if (auto *ILE = dyn_cast(Init)) return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(), RK_StdInitializerList, Visit); if (InitListExpr *ILE = dyn_cast(Init)) { // We already visited the elements of this initializer list while // performing the initialization. Don't visit them again unless we've // changed the lifetime of the initialized entity. if (!RevisitSubinits) return; if (ILE->isTransparent()) return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit, RevisitSubinits); if (ILE->getType()->isArrayType()) { for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I) visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit, RevisitSubinits); return; } if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) { assert(RD->isAggregate() && "aggregate init on non-aggregate"); // If we lifetime-extend a braced initializer which is initializing an // aggregate, and that aggregate contains reference members which are // bound to temporaries, those temporaries are also lifetime-extended. if (RD->isUnion() && ILE->getInitializedFieldInUnion() && ILE->getInitializedFieldInUnion()->getType()->isReferenceType()) visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0), RK_ReferenceBinding, Visit); else { unsigned Index = 0; for (const auto *I : RD->fields()) { if (Index >= ILE->getNumInits()) break; if (I->isUnnamedBitfield()) continue; Expr *SubInit = ILE->getInit(Index); if (I->getType()->isReferenceType()) visitLocalsRetainedByReferenceBinding(Path, SubInit, RK_ReferenceBinding, Visit); else // This might be either aggregate-initialization of a member or // initialization of a std::initializer_list object. Regardless, // we should recursively lifetime-extend that initializer. visitLocalsRetainedByInitializer(Path, SubInit, Visit, RevisitSubinits); ++Index; } } } return; } if (isa(Init) || isa(Init)) return visitLifetimeBoundArguments(Path, Init, Visit); switch (Init->getStmtClass()) { case Stmt::UnaryOperatorClass: { auto *UO = cast(Init); // If the initializer is the address of a local, we could have a lifetime // problem. if (UO->getOpcode() == UO_AddrOf) { // If this is &rvalue, then it's ill-formed and we have already diagnosed // it. Don't produce a redundant warning about the lifetime of the // temporary. if (isa(UO->getSubExpr())) return; Path.push_back({IndirectLocalPathEntry::AddressOf, UO}); visitLocalsRetainedByReferenceBinding(Path, UO->getSubExpr(), RK_ReferenceBinding, Visit); } break; } case Stmt::BinaryOperatorClass: { // Handle pointer arithmetic. auto *BO = cast(Init); BinaryOperatorKind BOK = BO->getOpcode(); if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub)) break; if (BO->getLHS()->getType()->isPointerType()) visitLocalsRetainedByInitializer(Path, BO->getLHS(), Visit, true); else if (BO->getRHS()->getType()->isPointerType()) visitLocalsRetainedByInitializer(Path, BO->getRHS(), Visit, true); break; } case Stmt::ConditionalOperatorClass: case Stmt::BinaryConditionalOperatorClass: { auto *C = cast(Init); // In C++, we can have a throw-expression operand, which has 'void' type // and isn't interesting from a lifetime perspective. if (!C->getTrueExpr()->getType()->isVoidType()) visitLocalsRetainedByInitializer(Path, C->getTrueExpr(), Visit, true); if (!C->getFalseExpr()->getType()->isVoidType()) visitLocalsRetainedByInitializer(Path, C->getFalseExpr(), Visit, true); break; } case Stmt::BlockExprClass: if (cast(Init)->getBlockDecl()->hasCaptures()) { // This is a local block, whose lifetime is that of the function. Visit(Path, Local(cast(Init)), RK_ReferenceBinding); } break; case Stmt::AddrLabelExprClass: // We want to warn if the address of a label would escape the function. Visit(Path, Local(cast(Init)), RK_ReferenceBinding); break; default: break; } } /// Determine whether this is an indirect path to a temporary that we are /// supposed to lifetime-extend along (but don't). static bool shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { for (auto Elem : Path) { if (Elem.Kind != IndirectLocalPathEntry::DefaultInit) return false; } return true; } /// Find the range for the first interesting entry in the path at or after I. static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I, Expr *E) { for (unsigned N = Path.size(); I != N; ++I) { switch (Path[I].Kind) { case IndirectLocalPathEntry::AddressOf: case IndirectLocalPathEntry::LValToRVal: case IndirectLocalPathEntry::LifetimeBoundCall: // These exist primarily to mark the path as not permitting or // supporting lifetime extension. break; case IndirectLocalPathEntry::DefaultInit: case IndirectLocalPathEntry::VarInit: return Path[I].E->getSourceRange(); } } return E->getSourceRange(); } void Sema::checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init) { LifetimeResult LR = getEntityLifetime(&Entity); LifetimeKind LK = LR.getInt(); const InitializedEntity *ExtendingEntity = LR.getPointer(); // If this entity doesn't have an interesting lifetime, don't bother looking // for temporaries within its initializer. if (LK == LK_FullExpression) return; auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool { SourceRange DiagRange = nextPathEntryRange(Path, 0, L); SourceLocation DiagLoc = DiagRange.getBegin(); switch (LK) { case LK_FullExpression: llvm_unreachable("already handled this"); case LK_Extended: { auto *MTE = dyn_cast(L); if (!MTE) { // The initialized entity has lifetime beyond the full-expression, // and the local entity does too, so don't warn. // // FIXME: We should consider warning if a static / thread storage // duration variable retains an automatic storage duration local. return false; } // Lifetime-extend the temporary. if (Path.empty()) { // Update the storage duration of the materialized temporary. // FIXME: Rebuild the expression instead of mutating it. MTE->setExtendingDecl(ExtendingEntity->getDecl(), ExtendingEntity->allocateManglingNumber()); // Also visit the temporaries lifetime-extended by this initializer. return true; } if (shouldLifetimeExtendThroughPath(Path)) { // We're supposed to lifetime-extend the temporary along this path (per // the resolution of DR1815), but we don't support that yet. // // FIXME: Properly handle this situation. Perhaps the easiest approach // would be to clone the initializer expression on each use that would // lifetime extend its temporaries. Diag(DiagLoc, diag::warn_unsupported_lifetime_extension) << RK << DiagRange; } else { // If the path goes through the initialization of a variable or field, // it can't possibly reach a temporary created in this full-expression. // We will have already diagnosed any problems with the initializer. if (pathContainsInit(Path)) return false; Diag(DiagLoc, diag::warn_dangling_variable) << RK << !Entity.getParent() << ExtendingEntity->getDecl()->isImplicit() << ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange; } break; } case LK_MemInitializer: { if (isa(L)) { // Under C++ DR1696, if a mem-initializer (or a default member // initializer used by the absence of one) would lifetime-extend a // temporary, the program is ill-formed. if (auto *ExtendingDecl = ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { bool IsSubobjectMember = ExtendingEntity != &Entity; Diag(DiagLoc, shouldLifetimeExtendThroughPath(Path) ? diag::err_dangling_member : diag::warn_dangling_member) << ExtendingDecl << IsSubobjectMember << RK << DiagRange; // Don't bother adding a note pointing to the field if we're inside // its default member initializer; our primary diagnostic points to // the same place in that case. if (Path.empty() || Path.back().Kind != IndirectLocalPathEntry::DefaultInit) { Diag(ExtendingDecl->getLocation(), diag::note_lifetime_extending_member_declared_here) << RK << IsSubobjectMember; } } else { // We have a mem-initializer but no particular field within it; this // is either a base class or a delegating initializer directly // initializing the base-class from something that doesn't live long // enough. // // FIXME: Warn on this. return false; } } else { // Paths via a default initializer can only occur during error recovery // (there's no other way that a default initializer can refer to a // local). Don't produce a bogus warning on those cases. if (pathContainsInit(Path)) return false; auto *DRE = dyn_cast(L); auto *VD = DRE ? dyn_cast(DRE->getDecl()) : nullptr; if (!VD) { // A member was initialized to a local block. // FIXME: Warn on this. return false; } if (auto *Member = ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { bool IsPointer = Member->getType()->isAnyPointerType(); Diag(DiagLoc, IsPointer ? diag::warn_init_ptr_member_to_parameter_addr : diag::warn_bind_ref_member_to_parameter) << Member << VD << isa(VD) << DiagRange; Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here) << (unsigned)IsPointer; } } break; } case LK_New: if (isa(L)) { Diag(DiagLoc, RK == RK_ReferenceBinding ? diag::warn_new_dangling_reference : diag::warn_new_dangling_initializer_list) << !Entity.getParent() << DiagRange; } else { // We can't determine if the allocation outlives the local declaration. return false; } break; case LK_Return: case LK_StmtExprResult: if (auto *DRE = dyn_cast(L)) { // We can't determine if the local variable outlives the statement // expression. if (LK == LK_StmtExprResult) return false; Diag(DiagLoc, diag::warn_ret_stack_addr_ref) << Entity.getType()->isReferenceType() << DRE->getDecl() << isa(DRE->getDecl()) << DiagRange; } else if (isa(L)) { Diag(DiagLoc, diag::err_ret_local_block) << DiagRange; } else if (isa(L)) { // Don't warn when returning a label from a statement expression. // Leaving the scope doesn't end its lifetime. if (LK == LK_StmtExprResult) return false; Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange; } else { Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref) << Entity.getType()->isReferenceType() << DiagRange; } break; } for (unsigned I = 0; I != Path.size(); ++I) { auto Elem = Path[I]; switch (Elem.Kind) { case IndirectLocalPathEntry::AddressOf: case IndirectLocalPathEntry::LValToRVal: // These exist primarily to mark the path as not permitting or // supporting lifetime extension. break; case IndirectLocalPathEntry::LifetimeBoundCall: // FIXME: Consider adding a note for this. break; case IndirectLocalPathEntry::DefaultInit: { auto *FD = cast(Elem.D); Diag(FD->getLocation(), diag::note_init_with_default_member_initalizer) << FD << nextPathEntryRange(Path, I + 1, L); break; } case IndirectLocalPathEntry::VarInit: const VarDecl *VD = cast(Elem.D); Diag(VD->getLocation(), diag::note_local_var_initializer) << VD->getType()->isReferenceType() << VD->isImplicit() << VD->getDeclName() << nextPathEntryRange(Path, I + 1, L); break; } } // We didn't lifetime-extend, so don't go any further; we don't need more // warnings or errors on inner temporaries within this one's initializer. return false; }; llvm::SmallVector Path; if (Init->isGLValue()) visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding, TemporaryVisitor); else visitLocalsRetainedByInitializer(Path, Init, TemporaryVisitor, false); } static void DiagnoseNarrowingInInitList(Sema &S, const ImplicitConversionSequence &ICS, QualType PreNarrowingType, QualType EntityType, const Expr *PostInit); /// Provide warnings when std::move is used on construction. static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr, bool IsReturnStmt) { if (!InitExpr) return; if (S.inTemplateInstantiation()) return; QualType DestType = InitExpr->getType(); if (!DestType->isRecordType()) return; unsigned DiagID = 0; if (IsReturnStmt) { const CXXConstructExpr *CCE = dyn_cast(InitExpr->IgnoreParens()); if (!CCE || CCE->getNumArgs() != 1) return; if (!CCE->getConstructor()->isCopyOrMoveConstructor()) return; InitExpr = CCE->getArg(0)->IgnoreImpCasts(); } // Find the std::move call and get the argument. const CallExpr *CE = dyn_cast(InitExpr->IgnoreParens()); if (!CE || !CE->isCallToStdMove()) return; const Expr *Arg = CE->getArg(0)->IgnoreImplicit(); if (IsReturnStmt) { const DeclRefExpr *DRE = dyn_cast(Arg->IgnoreParenImpCasts()); if (!DRE || DRE->refersToEnclosingVariableOrCapture()) return; const VarDecl *VD = dyn_cast(DRE->getDecl()); if (!VD || !VD->hasLocalStorage()) return; // __block variables are not moved implicitly. if (VD->hasAttr()) return; QualType SourceType = VD->getType(); if (!SourceType->isRecordType()) return; if (!S.Context.hasSameUnqualifiedType(DestType, SourceType)) { return; } // If we're returning a function parameter, copy elision // is not possible. if (isa(VD)) DiagID = diag::warn_redundant_move_on_return; else DiagID = diag::warn_pessimizing_move_on_return; } else { DiagID = diag::warn_pessimizing_move_on_initialization; const Expr *ArgStripped = Arg->IgnoreImplicit()->IgnoreParens(); if (!ArgStripped->isRValue() || !ArgStripped->getType()->isRecordType()) return; } S.Diag(CE->getLocStart(), DiagID); // Get all the locations for a fix-it. Don't emit the fix-it if any location // is within a macro. SourceLocation CallBegin = CE->getCallee()->getLocStart(); if (CallBegin.isMacroID()) return; SourceLocation RParen = CE->getRParenLoc(); if (RParen.isMacroID()) return; SourceLocation LParen; SourceLocation ArgLoc = Arg->getLocStart(); // Special testing for the argument location. Since the fix-it needs the // location right before the argument, the argument location can be in a // macro only if it is at the beginning of the macro. while (ArgLoc.isMacroID() && S.getSourceManager().isAtStartOfImmediateMacroExpansion(ArgLoc)) { ArgLoc = S.getSourceManager().getImmediateExpansionRange(ArgLoc).getBegin(); } if (LParen.isMacroID()) return; LParen = ArgLoc.getLocWithOffset(-1); S.Diag(CE->getLocStart(), diag::note_remove_move) << FixItHint::CreateRemoval(SourceRange(CallBegin, LParen)) << FixItHint::CreateRemoval(SourceRange(RParen, RParen)); } static void CheckForNullPointerDereference(Sema &S, const Expr *E) { // Check to see if we are dereferencing a null pointer. If so, this is // undefined behavior, so warn about it. This only handles the pattern // "*null", which is a very syntactic check. if (const UnaryOperator *UO = dyn_cast(E->IgnoreParenCasts())) if (UO->getOpcode() == UO_Deref && UO->getSubExpr()->IgnoreParenCasts()-> isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull)) { S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO, S.PDiag(diag::warn_binding_null_to_reference) << UO->getSubExpr()->getSourceRange()); } } MaterializeTemporaryExpr * Sema::CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, bool BoundToLvalueReference) { auto MTE = new (Context) MaterializeTemporaryExpr(T, Temporary, BoundToLvalueReference); // Order an ExprWithCleanups for lifetime marks. // // TODO: It'll be good to have a single place to check the access of the // destructor and generate ExprWithCleanups for various uses. Currently these // are done in both CreateMaterializeTemporaryExpr and MaybeBindToTemporary, // but there may be a chance to merge them. Cleanup.setExprNeedsCleanups(false); return MTE; } ExprResult Sema::TemporaryMaterializationConversion(Expr *E) { // In C++98, we don't want to implicitly create an xvalue. // FIXME: This means that AST consumers need to deal with "prvalues" that // denote materialized temporaries. Maybe we should add another ValueKind // for "xvalue pretending to be a prvalue" for C++98 support. if (!E->isRValue() || !getLangOpts().CPlusPlus11) return E; // C++1z [conv.rval]/1: T shall be a complete type. // FIXME: Does this ever matter (can we form a prvalue of incomplete type)? // If so, we should check for a non-abstract class type here too. QualType T = E->getType(); if (RequireCompleteType(E->getExprLoc(), T, diag::err_incomplete_type)) return ExprError(); return CreateMaterializeTemporaryExpr(E->getType(), E, false); } ExprResult InitializationSequence::Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType) { if (Failed()) { Diagnose(S, Entity, Kind, Args); return ExprError(); } if (!ZeroInitializationFixit.empty()) { unsigned DiagID = diag::err_default_init_const; if (Decl *D = Entity.getDecl()) if (S.getLangOpts().MSVCCompat && D->hasAttr()) DiagID = diag::ext_default_init_const; // The initialization would have succeeded with this fixit. Since the fixit // is on the error, we need to build a valid AST in this case, so this isn't // handled in the Failed() branch above. QualType DestType = Entity.getType(); S.Diag(Kind.getLocation(), DiagID) << DestType << (bool)DestType->getAs() << FixItHint::CreateInsertion(ZeroInitializationFixitLoc, ZeroInitializationFixit); } if (getKind() == DependentSequence) { // If the declaration is a non-dependent, incomplete array type // that has an initializer, then its type will be completed once // the initializer is instantiated. if (ResultType && !Entity.getType()->isDependentType() && Args.size() == 1) { QualType DeclType = Entity.getType(); if (const IncompleteArrayType *ArrayT = S.Context.getAsIncompleteArrayType(DeclType)) { // FIXME: We don't currently have the ability to accurately // compute the length of an initializer list without // performing full type-checking of the initializer list // (since we have to determine where braces are implicitly // introduced and such). So, we fall back to making the array // type a dependently-sized array type with no specified // bound. if (isa((Expr *)Args[0])) { SourceRange Brackets; // Scavange the location of the brackets from the entity, if we can. if (auto *DD = dyn_cast_or_null(Entity.getDecl())) { if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) { TypeLoc TL = TInfo->getTypeLoc(); if (IncompleteArrayTypeLoc ArrayLoc = TL.getAs()) Brackets = ArrayLoc.getBracketsRange(); } } *ResultType = S.Context.getDependentSizedArrayType(ArrayT->getElementType(), /*NumElts=*/nullptr, ArrayT->getSizeModifier(), ArrayT->getIndexTypeCVRQualifiers(), Brackets); } } } if (Kind.getKind() == InitializationKind::IK_Direct && !Kind.isExplicitCast()) { // Rebuild the ParenListExpr. SourceRange ParenRange = Kind.getParenOrBraceRange(); return S.ActOnParenListExpr(ParenRange.getBegin(), ParenRange.getEnd(), Args); } assert(Kind.getKind() == InitializationKind::IK_Copy || Kind.isExplicitCast() || Kind.getKind() == InitializationKind::IK_DirectList); return ExprResult(Args[0]); } // No steps means no initialization. if (Steps.empty()) return ExprResult((Expr *)nullptr); if (S.getLangOpts().CPlusPlus11 && Entity.getType()->isReferenceType() && Args.size() == 1 && isa(Args[0]) && !Entity.isParameterKind()) { // Produce a C++98 compatibility warning if we are initializing a reference // from an initializer list. For parameters, we produce a better warning // elsewhere. Expr *Init = Args[0]; S.Diag(Init->getLocStart(), diag::warn_cxx98_compat_reference_list_init) << Init->getSourceRange(); } // OpenCL v2.0 s6.13.11.1. atomic variables can be initialized in global scope QualType ETy = Entity.getType(); Qualifiers TyQualifiers = ETy.getQualifiers(); bool HasGlobalAS = TyQualifiers.hasAddressSpace() && TyQualifiers.getAddressSpace() == LangAS::opencl_global; if (S.getLangOpts().OpenCLVersion >= 200 && ETy->isAtomicType() && !HasGlobalAS && Entity.getKind() == InitializedEntity::EK_Variable && Args.size() > 0) { S.Diag(Args[0]->getLocStart(), diag::err_opencl_atomic_init) << 1 << SourceRange(Entity.getDecl()->getLocStart(), Args[0]->getLocEnd()); return ExprError(); } QualType DestType = Entity.getType().getNonReferenceType(); // FIXME: Ugly hack around the fact that Entity.getType() is not // the same as Entity.getDecl()->getType() in cases involving type merging, // and we want latter when it makes sense. if (ResultType) *ResultType = Entity.getDecl() ? Entity.getDecl()->getType() : Entity.getType(); ExprResult CurInit((Expr *)nullptr); SmallVector ArrayLoopCommonExprs; // For initialization steps that start with a single initializer, // grab the only argument out the Args and place it into the "current" // initializer. switch (Steps.front().Kind) { case SK_ResolveAddressOfOverloadedFunction: case SK_CastDerivedToBaseRValue: case SK_CastDerivedToBaseXValue: case SK_CastDerivedToBaseLValue: case SK_BindReference: case SK_BindReferenceToTemporary: case SK_FinalCopy: case SK_ExtraneousCopyToTemporary: case SK_UserConversion: case SK_QualificationConversionLValue: case SK_QualificationConversionXValue: case SK_QualificationConversionRValue: case SK_AtomicConversion: case SK_LValueToRValue: case SK_ConversionSequence: case SK_ConversionSequenceNoNarrowing: case SK_ListInitialization: case SK_UnwrapInitList: case SK_RewrapInitList: case SK_CAssignment: case SK_StringInit: case SK_ObjCObjectConversion: case SK_ArrayLoopIndex: case SK_ArrayLoopInit: case SK_ArrayInit: case SK_GNUArrayInit: case SK_ParenthesizedArrayInit: case SK_PassByIndirectCopyRestore: case SK_PassByIndirectRestore: case SK_ProduceObjCObject: case SK_StdInitializerList: case SK_OCLSamplerInit: case SK_OCLZeroEvent: case SK_OCLZeroQueue: { assert(Args.size() == 1); CurInit = Args[0]; if (!CurInit.get()) return ExprError(); break; } case SK_ConstructorInitialization: case SK_ConstructorInitializationFromList: case SK_StdInitializerListConstructorCall: case SK_ZeroInitialization: break; } // Promote from an unevaluated context to an unevaluated list context in // C++11 list-initialization; we need to instantiate entities usable in // constant expressions here in order to perform narrowing checks =( EnterExpressionEvaluationContext Evaluated( S, EnterExpressionEvaluationContext::InitList, CurInit.get() && isa(CurInit.get())); // C++ [class.abstract]p2: // no objects of an abstract class can be created except as subobjects // of a class derived from it auto checkAbstractType = [&](QualType T) -> bool { if (Entity.getKind() == InitializedEntity::EK_Base || Entity.getKind() == InitializedEntity::EK_Delegating) return false; return S.RequireNonAbstractType(Kind.getLocation(), T, diag::err_allocation_of_abstract_type); }; // Walk through the computed steps for the initialization sequence, // performing the specified conversions along the way. bool ConstructorInitRequiresZeroInit = false; for (step_iterator Step = step_begin(), StepEnd = step_end(); Step != StepEnd; ++Step) { if (CurInit.isInvalid()) return ExprError(); QualType SourceType = CurInit.get() ? CurInit.get()->getType() : QualType(); switch (Step->Kind) { case SK_ResolveAddressOfOverloadedFunction: // Overload resolution determined which function invoke; update the // initializer to reflect that choice. S.CheckAddressOfMemberAccess(CurInit.get(), Step->Function.FoundDecl); if (S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation())) return ExprError(); CurInit = S.FixOverloadedFunctionReference(CurInit, Step->Function.FoundDecl, Step->Function.Function); break; case SK_CastDerivedToBaseRValue: case SK_CastDerivedToBaseXValue: case SK_CastDerivedToBaseLValue: { // We have a derived-to-base cast that produces either an rvalue or an // lvalue. Perform that cast. CXXCastPath BasePath; // Casts to inaccessible base classes are allowed with C-style casts. bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast(); if (S.CheckDerivedToBaseConversion(SourceType, Step->Type, CurInit.get()->getLocStart(), CurInit.get()->getSourceRange(), &BasePath, IgnoreBaseAccess)) return ExprError(); ExprValueKind VK = Step->Kind == SK_CastDerivedToBaseLValue ? VK_LValue : (Step->Kind == SK_CastDerivedToBaseXValue ? VK_XValue : VK_RValue); CurInit = ImplicitCastExpr::Create(S.Context, Step->Type, CK_DerivedToBase, CurInit.get(), &BasePath, VK); break; } case SK_BindReference: // Reference binding does not have any corresponding ASTs. // Check exception specifications if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType)) return ExprError(); // We don't check for e.g. function pointers here, since address // availability checks should only occur when the function first decays // into a pointer or reference. if (CurInit.get()->getType()->isFunctionProtoType()) { if (auto *DRE = dyn_cast(CurInit.get()->IgnoreParens())) { if (auto *FD = dyn_cast(DRE->getDecl())) { if (!S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true, DRE->getLocStart())) return ExprError(); } } } CheckForNullPointerDereference(S, CurInit.get()); break; case SK_BindReferenceToTemporary: { // Make sure the "temporary" is actually an rvalue. assert(CurInit.get()->isRValue() && "not a temporary"); // Check exception specifications if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType)) return ExprError(); // Materialize the temporary into memory. MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr( Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType()); CurInit = MTE; // If we're extending this temporary to automatic storage duration -- we // need to register its cleanup during the full-expression's cleanups. if (MTE->getStorageDuration() == SD_Automatic && MTE->getType().isDestructedType()) S.Cleanup.setExprNeedsCleanups(true); break; } case SK_FinalCopy: if (checkAbstractType(Step->Type)) return ExprError(); // If the overall initialization is initializing a temporary, we already // bound our argument if it was necessary to do so. If not (if we're // ultimately initializing a non-temporary), our argument needs to be // bound since it's initializing a function parameter. // FIXME: This is a mess. Rationalize temporary destruction. if (!shouldBindAsTemporary(Entity)) CurInit = S.MaybeBindToTemporary(CurInit.get()); CurInit = CopyObject(S, Step->Type, Entity, CurInit, /*IsExtraneousCopy=*/false); break; case SK_ExtraneousCopyToTemporary: CurInit = CopyObject(S, Step->Type, Entity, CurInit, /*IsExtraneousCopy=*/true); break; case SK_UserConversion: { // We have a user-defined conversion that invokes either a constructor // or a conversion function. CastKind CastKind; FunctionDecl *Fn = Step->Function.Function; DeclAccessPair FoundFn = Step->Function.FoundDecl; bool HadMultipleCandidates = Step->Function.HadMultipleCandidates; bool CreatedObject = false; if (CXXConstructorDecl *Constructor = dyn_cast(Fn)) { // Build a call to the selected constructor. SmallVector ConstructorArgs; SourceLocation Loc = CurInit.get()->getLocStart(); // Determine the arguments required to actually perform the constructor // call. Expr *Arg = CurInit.get(); if (S.CompleteConstructorCall(Constructor, MultiExprArg(&Arg, 1), Loc, ConstructorArgs)) return ExprError(); // Build an expression that constructs a temporary. CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, FoundFn, Constructor, ConstructorArgs, HadMultipleCandidates, /*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); if (CurInit.isInvalid()) return ExprError(); S.CheckConstructorAccess(Kind.getLocation(), Constructor, FoundFn, Entity); if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation())) return ExprError(); CastKind = CK_ConstructorConversion; CreatedObject = true; } else { // Build a call to the conversion function. CXXConversionDecl *Conversion = cast(Fn); S.CheckMemberOperatorAccess(Kind.getLocation(), CurInit.get(), nullptr, FoundFn); if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation())) return ExprError(); CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion, HadMultipleCandidates); if (CurInit.isInvalid()) return ExprError(); CastKind = CK_UserDefinedConversion; CreatedObject = Conversion->getReturnType()->isRecordType(); } if (CreatedObject && checkAbstractType(CurInit.get()->getType())) return ExprError(); CurInit = ImplicitCastExpr::Create(S.Context, CurInit.get()->getType(), CastKind, CurInit.get(), nullptr, CurInit.get()->getValueKind()); if (shouldBindAsTemporary(Entity)) // The overall entity is temporary, so this expression should be // destroyed at the end of its full-expression. CurInit = S.MaybeBindToTemporary(CurInit.getAs()); else if (CreatedObject && shouldDestroyEntity(Entity)) { // The object outlasts the full-expression, but we need to prepare for // a destructor being run on it. // FIXME: It makes no sense to do this here. This should happen // regardless of how we initialized the entity. QualType T = CurInit.get()->getType(); if (const RecordType *Record = T->getAs()) { CXXDestructorDecl *Destructor = S.LookupDestructor(cast(Record->getDecl())); S.CheckDestructorAccess(CurInit.get()->getLocStart(), Destructor, S.PDiag(diag::err_access_dtor_temp) << T); S.MarkFunctionReferenced(CurInit.get()->getLocStart(), Destructor); if (S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getLocStart())) return ExprError(); } } break; } case SK_QualificationConversionLValue: case SK_QualificationConversionXValue: case SK_QualificationConversionRValue: { // Perform a qualification conversion; these can never go wrong. ExprValueKind VK = Step->Kind == SK_QualificationConversionLValue ? VK_LValue : (Step->Kind == SK_QualificationConversionXValue ? VK_XValue : VK_RValue); CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, CK_NoOp, VK); break; } case SK_AtomicConversion: { assert(CurInit.get()->isRValue() && "cannot convert glvalue to atomic"); CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, CK_NonAtomicToAtomic, VK_RValue); break; } case SK_LValueToRValue: { assert(CurInit.get()->isGLValue() && "cannot load from a prvalue"); CurInit = ImplicitCastExpr::Create(S.Context, Step->Type, CK_LValueToRValue, CurInit.get(), /*BasePath=*/nullptr, VK_RValue); break; } case SK_ConversionSequence: case SK_ConversionSequenceNoNarrowing: { Sema::CheckedConversionKind CCK = Kind.isCStyleCast()? Sema::CCK_CStyleCast : Kind.isFunctionalCast()? Sema::CCK_FunctionalCast : Kind.isExplicitCast()? Sema::CCK_OtherCast : Sema::CCK_ImplicitConversion; ExprResult CurInitExprRes = S.PerformImplicitConversion(CurInit.get(), Step->Type, *Step->ICS, getAssignmentAction(Entity), CCK); if (CurInitExprRes.isInvalid()) return ExprError(); S.DiscardMisalignedMemberAddress(Step->Type.getTypePtr(), CurInit.get()); CurInit = CurInitExprRes; if (Step->Kind == SK_ConversionSequenceNoNarrowing && S.getLangOpts().CPlusPlus) DiagnoseNarrowingInInitList(S, *Step->ICS, SourceType, Entity.getType(), CurInit.get()); break; } case SK_ListInitialization: { if (checkAbstractType(Step->Type)) return ExprError(); InitListExpr *InitList = cast(CurInit.get()); // If we're not initializing the top-level entity, we need to create an // InitializeTemporary entity for our target type. QualType Ty = Step->Type; bool IsTemporary = !S.Context.hasSameType(Entity.getType(), Ty); InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(Ty); InitializedEntity InitEntity = IsTemporary ? TempEntity : Entity; InitListChecker PerformInitList(S, InitEntity, InitList, Ty, /*VerifyOnly=*/false, /*TreatUnavailableAsInvalid=*/false); if (PerformInitList.HadError()) return ExprError(); // Hack: We must update *ResultType if available in order to set the // bounds of arrays, e.g. in 'int ar[] = {1, 2, 3};'. // Worst case: 'const int (&arref)[] = {1, 2, 3};'. if (ResultType && ResultType->getNonReferenceType()->isIncompleteArrayType()) { if ((*ResultType)->isRValueReferenceType()) Ty = S.Context.getRValueReferenceType(Ty); else if ((*ResultType)->isLValueReferenceType()) Ty = S.Context.getLValueReferenceType(Ty, (*ResultType)->getAs()->isSpelledAsLValue()); *ResultType = Ty; } InitListExpr *StructuredInitList = PerformInitList.getFullyStructuredList(); CurInit.get(); CurInit = shouldBindAsTemporary(InitEntity) ? S.MaybeBindToTemporary(StructuredInitList) : StructuredInitList; break; } case SK_ConstructorInitializationFromList: { if (checkAbstractType(Step->Type)) return ExprError(); // When an initializer list is passed for a parameter of type "reference // to object", we don't get an EK_Temporary entity, but instead an // EK_Parameter entity with reference type. // FIXME: This is a hack. What we really should do is create a user // conversion step for this case, but this makes it considerably more // complicated. For now, this will do. InitializedEntity TempEntity = InitializedEntity::InitializeTemporary( Entity.getType().getNonReferenceType()); bool UseTemporary = Entity.getType()->isReferenceType(); assert(Args.size() == 1 && "expected a single argument for list init"); InitListExpr *InitList = cast(Args[0]); S.Diag(InitList->getExprLoc(), diag::warn_cxx98_compat_ctor_list_init) << InitList->getSourceRange(); MultiExprArg Arg(InitList->getInits(), InitList->getNumInits()); CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity : Entity, Kind, Arg, *Step, ConstructorInitRequiresZeroInit, /*IsListInitialization*/true, /*IsStdInitListInit*/false, InitList->getLBraceLoc(), InitList->getRBraceLoc()); break; } case SK_UnwrapInitList: CurInit = cast(CurInit.get())->getInit(0); break; case SK_RewrapInitList: { Expr *E = CurInit.get(); InitListExpr *Syntactic = Step->WrappingSyntacticList; InitListExpr *ILE = new (S.Context) InitListExpr(S.Context, Syntactic->getLBraceLoc(), E, Syntactic->getRBraceLoc()); ILE->setSyntacticForm(Syntactic); ILE->setType(E->getType()); ILE->setValueKind(E->getValueKind()); CurInit = ILE; break; } case SK_ConstructorInitialization: case SK_StdInitializerListConstructorCall: { if (checkAbstractType(Step->Type)) return ExprError(); // When an initializer list is passed for a parameter of type "reference // to object", we don't get an EK_Temporary entity, but instead an // EK_Parameter entity with reference type. // FIXME: This is a hack. What we really should do is create a user // conversion step for this case, but this makes it considerably more // complicated. For now, this will do. InitializedEntity TempEntity = InitializedEntity::InitializeTemporary( Entity.getType().getNonReferenceType()); bool UseTemporary = Entity.getType()->isReferenceType(); bool IsStdInitListInit = Step->Kind == SK_StdInitializerListConstructorCall; Expr *Source = CurInit.get(); SourceRange Range = Kind.hasParenOrBraceRange() ? Kind.getParenOrBraceRange() : SourceRange(); CurInit = PerformConstructorInitialization( S, UseTemporary ? TempEntity : Entity, Kind, Source ? MultiExprArg(Source) : Args, *Step, ConstructorInitRequiresZeroInit, /*IsListInitialization*/ IsStdInitListInit, /*IsStdInitListInitialization*/ IsStdInitListInit, /*LBraceLoc*/ Range.getBegin(), /*RBraceLoc*/ Range.getEnd()); break; } case SK_ZeroInitialization: { step_iterator NextStep = Step; ++NextStep; if (NextStep != StepEnd && (NextStep->Kind == SK_ConstructorInitialization || NextStep->Kind == SK_ConstructorInitializationFromList)) { // The need for zero-initialization is recorded directly into // the call to the object's constructor within the next step. ConstructorInitRequiresZeroInit = true; } else if (Kind.getKind() == InitializationKind::IK_Value && S.getLangOpts().CPlusPlus && !Kind.isImplicitValueInit()) { TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); if (!TSInfo) TSInfo = S.Context.getTrivialTypeSourceInfo(Step->Type, Kind.getRange().getBegin()); CurInit = new (S.Context) CXXScalarValueInitExpr( Entity.getType().getNonLValueExprType(S.Context), TSInfo, Kind.getRange().getEnd()); } else { CurInit = new (S.Context) ImplicitValueInitExpr(Step->Type); } break; } case SK_CAssignment: { QualType SourceType = CurInit.get()->getType(); // Save off the initial CurInit in case we need to emit a diagnostic ExprResult InitialCurInit = CurInit; ExprResult Result = CurInit; Sema::AssignConvertType ConvTy = S.CheckSingleAssignmentConstraints(Step->Type, Result, true, Entity.getKind() == InitializedEntity::EK_Parameter_CF_Audited); if (Result.isInvalid()) return ExprError(); CurInit = Result; // If this is a call, allow conversion to a transparent union. ExprResult CurInitExprRes = CurInit; if (ConvTy != Sema::Compatible && Entity.isParameterKind() && S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExprRes) == Sema::Compatible) ConvTy = Sema::Compatible; if (CurInitExprRes.isInvalid()) return ExprError(); CurInit = CurInitExprRes; bool Complained; if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(), Step->Type, SourceType, InitialCurInit.get(), getAssignmentAction(Entity, true), &Complained)) { PrintInitLocationNote(S, Entity); return ExprError(); } else if (Complained) PrintInitLocationNote(S, Entity); break; } case SK_StringInit: { QualType Ty = Step->Type; CheckStringInit(CurInit.get(), ResultType ? *ResultType : Ty, S.Context.getAsArrayType(Ty), S); break; } case SK_ObjCObjectConversion: CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, CK_ObjCObjectLValueCast, CurInit.get()->getValueKind()); break; case SK_ArrayLoopIndex: { Expr *Cur = CurInit.get(); Expr *BaseExpr = new (S.Context) OpaqueValueExpr(Cur->getExprLoc(), Cur->getType(), Cur->getValueKind(), Cur->getObjectKind(), Cur); Expr *IndexExpr = new (S.Context) ArrayInitIndexExpr(S.Context.getSizeType()); CurInit = S.CreateBuiltinArraySubscriptExpr( BaseExpr, Kind.getLocation(), IndexExpr, Kind.getLocation()); ArrayLoopCommonExprs.push_back(BaseExpr); break; } case SK_ArrayLoopInit: { assert(!ArrayLoopCommonExprs.empty() && "mismatched SK_ArrayLoopIndex and SK_ArrayLoopInit"); Expr *Common = ArrayLoopCommonExprs.pop_back_val(); CurInit = new (S.Context) ArrayInitLoopExpr(Step->Type, Common, CurInit.get()); break; } case SK_GNUArrayInit: // Okay: we checked everything before creating this step. Note that // this is a GNU extension. S.Diag(Kind.getLocation(), diag::ext_array_init_copy) << Step->Type << CurInit.get()->getType() << CurInit.get()->getSourceRange(); LLVM_FALLTHROUGH; case SK_ArrayInit: // If the destination type is an incomplete array type, update the // type accordingly. if (ResultType) { if (const IncompleteArrayType *IncompleteDest = S.Context.getAsIncompleteArrayType(Step->Type)) { if (const ConstantArrayType *ConstantSource = S.Context.getAsConstantArrayType(CurInit.get()->getType())) { *ResultType = S.Context.getConstantArrayType( IncompleteDest->getElementType(), ConstantSource->getSize(), ArrayType::Normal, 0); } } } break; case SK_ParenthesizedArrayInit: // Okay: we checked everything before creating this step. Note that // this is a GNU extension. S.Diag(Kind.getLocation(), diag::ext_array_init_parens) << CurInit.get()->getSourceRange(); break; case SK_PassByIndirectCopyRestore: case SK_PassByIndirectRestore: checkIndirectCopyRestoreSource(S, CurInit.get()); CurInit = new (S.Context) ObjCIndirectCopyRestoreExpr( CurInit.get(), Step->Type, Step->Kind == SK_PassByIndirectCopyRestore); break; case SK_ProduceObjCObject: CurInit = ImplicitCastExpr::Create(S.Context, Step->Type, CK_ARCProduceObject, CurInit.get(), nullptr, VK_RValue); break; case SK_StdInitializerList: { S.Diag(CurInit.get()->getExprLoc(), diag::warn_cxx98_compat_initializer_list_init) << CurInit.get()->getSourceRange(); // Materialize the temporary into memory. MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr( CurInit.get()->getType(), CurInit.get(), /*BoundToLvalueReference=*/false); // Wrap it in a construction of a std::initializer_list. CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE); // Bind the result, in case the library has given initializer_list a // non-trivial destructor. if (shouldBindAsTemporary(Entity)) CurInit = S.MaybeBindToTemporary(CurInit.get()); break; } case SK_OCLSamplerInit: { // Sampler initialzation have 5 cases: // 1. function argument passing // 1a. argument is a file-scope variable // 1b. argument is a function-scope variable // 1c. argument is one of caller function's parameters // 2. variable initialization // 2a. initializing a file-scope variable // 2b. initializing a function-scope variable // // For file-scope variables, since they cannot be initialized by function // call of __translate_sampler_initializer in LLVM IR, their references // need to be replaced by a cast from their literal initializers to // sampler type. Since sampler variables can only be used in function // calls as arguments, we only need to replace them when handling the // argument passing. assert(Step->Type->isSamplerT() && "Sampler initialization on non-sampler type."); Expr *Init = CurInit.get(); QualType SourceType = Init->getType(); // Case 1 if (Entity.isParameterKind()) { if (!SourceType->isSamplerT() && !SourceType->isIntegerType()) { S.Diag(Kind.getLocation(), diag::err_sampler_argument_required) << SourceType; break; } else if (const DeclRefExpr *DRE = dyn_cast(Init)) { auto Var = cast(DRE->getDecl()); // Case 1b and 1c // No cast from integer to sampler is needed. if (!Var->hasGlobalStorage()) { CurInit = ImplicitCastExpr::Create(S.Context, Step->Type, CK_LValueToRValue, Init, /*BasePath=*/nullptr, VK_RValue); break; } // Case 1a // For function call with a file-scope sampler variable as argument, // get the integer literal. // Do not diagnose if the file-scope variable does not have initializer // since this has already been diagnosed when parsing the variable // declaration. if (!Var->getInit() || !isa(Var->getInit())) break; Init = cast(const_cast( Var->getInit()))->getSubExpr(); SourceType = Init->getType(); } } else { // Case 2 // Check initializer is 32 bit integer constant. // If the initializer is taken from global variable, do not diagnose since // this has already been done when parsing the variable declaration. if (!Init->isConstantInitializer(S.Context, false)) break; if (!SourceType->isIntegerType() || 32 != S.Context.getIntWidth(SourceType)) { S.Diag(Kind.getLocation(), diag::err_sampler_initializer_not_integer) << SourceType; break; } llvm::APSInt Result; Init->EvaluateAsInt(Result, S.Context); const uint64_t SamplerValue = Result.getLimitedValue(); // 32-bit value of sampler's initializer is interpreted as // bit-field with the following structure: // |unspecified|Filter|Addressing Mode| Normalized Coords| // |31 6|5 4|3 1| 0| // This structure corresponds to enum values of sampler properties // defined in SPIR spec v1.2 and also opencl-c.h unsigned AddressingMode = (0x0E & SamplerValue) >> 1; unsigned FilterMode = (0x30 & SamplerValue) >> 4; if (FilterMode != 1 && FilterMode != 2) S.Diag(Kind.getLocation(), diag::warn_sampler_initializer_invalid_bits) << "Filter Mode"; if (AddressingMode > 4) S.Diag(Kind.getLocation(), diag::warn_sampler_initializer_invalid_bits) << "Addressing Mode"; } // Cases 1a, 2a and 2b // Insert cast from integer to sampler. CurInit = S.ImpCastExprToType(Init, S.Context.OCLSamplerTy, CK_IntToOCLSampler); break; } case SK_OCLZeroEvent: { assert(Step->Type->isEventT() && "Event initialization on non-event type."); CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, CK_ZeroToOCLEvent, CurInit.get()->getValueKind()); break; } case SK_OCLZeroQueue: { assert(Step->Type->isQueueT() && "Event initialization on non queue type."); CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, CK_ZeroToOCLQueue, CurInit.get()->getValueKind()); break; } } } // Check whether the initializer has a shorter lifetime than the initialized // entity, and if not, either lifetime-extend or warn as appropriate. if (auto *Init = CurInit.get()) S.checkInitializerLifetime(Entity, Init); // Diagnose non-fatal problems with the completed initialization. if (Entity.getKind() == InitializedEntity::EK_Member && cast(Entity.getDecl())->isBitField()) S.CheckBitFieldInitialization(Kind.getLocation(), cast(Entity.getDecl()), CurInit.get()); // Check for std::move on construction. if (const Expr *E = CurInit.get()) { CheckMoveOnConstruction(S, E, Entity.getKind() == InitializedEntity::EK_Result); } return CurInit; } /// Somewhere within T there is an uninitialized reference subobject. /// Dig it out and diagnose it. static bool DiagnoseUninitializedReference(Sema &S, SourceLocation Loc, QualType T) { if (T->isReferenceType()) { S.Diag(Loc, diag::err_reference_without_init) << T.getNonReferenceType(); return true; } CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); if (!RD || !RD->hasUninitializedReferenceMember()) return false; for (const auto *FI : RD->fields()) { if (FI->isUnnamedBitfield()) continue; if (DiagnoseUninitializedReference(S, FI->getLocation(), FI->getType())) { S.Diag(Loc, diag::note_value_initialization_here) << RD; return true; } } for (const auto &BI : RD->bases()) { if (DiagnoseUninitializedReference(S, BI.getLocStart(), BI.getType())) { S.Diag(Loc, diag::note_value_initialization_here) << RD; return true; } } return false; } //===----------------------------------------------------------------------===// // Diagnose initialization failures //===----------------------------------------------------------------------===// /// Emit notes associated with an initialization that failed due to a /// "simple" conversion failure. static void emitBadConversionNotes(Sema &S, const InitializedEntity &entity, Expr *op) { QualType destType = entity.getType(); if (destType.getNonReferenceType()->isObjCObjectPointerType() && op->getType()->isObjCObjectPointerType()) { // Emit a possible note about the conversion failing because the // operand is a message send with a related result type. S.EmitRelatedResultTypeNote(op); // Emit a possible note about a return failing because we're // expecting a related result type. if (entity.getKind() == InitializedEntity::EK_Result) S.EmitRelatedResultTypeNoteForReturn(destType); } } static void diagnoseListInit(Sema &S, const InitializedEntity &Entity, InitListExpr *InitList) { QualType DestType = Entity.getType(); QualType E; if (S.getLangOpts().CPlusPlus11 && S.isStdInitializerList(DestType, &E)) { QualType ArrayType = S.Context.getConstantArrayType( E.withConst(), llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()), InitList->getNumInits()), clang::ArrayType::Normal, 0); InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(ArrayType); return diagnoseListInit(S, HiddenArray, InitList); } if (DestType->isReferenceType()) { // A list-initialization failure for a reference means that we tried to // create a temporary of the inner type (per [dcl.init.list]p3.6) and the // inner initialization failed. QualType T = DestType->getAs()->getPointeeType(); diagnoseListInit(S, InitializedEntity::InitializeTemporary(T), InitList); SourceLocation Loc = InitList->getLocStart(); if (auto *D = Entity.getDecl()) Loc = D->getLocation(); S.Diag(Loc, diag::note_in_reference_temporary_list_initializer) << T; return; } InitListChecker DiagnoseInitList(S, Entity, InitList, DestType, /*VerifyOnly=*/false, /*TreatUnavailableAsInvalid=*/false); assert(DiagnoseInitList.HadError() && "Inconsistent init list check result."); } bool InitializationSequence::Diagnose(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, ArrayRef Args) { if (!Failed()) return false; // When we want to diagnose only one element of a braced-init-list, // we need to factor it out. Expr *OnlyArg; if (Args.size() == 1) { auto *List = dyn_cast(Args[0]); if (List && List->getNumInits() == 1) OnlyArg = List->getInit(0); else OnlyArg = Args[0]; } else OnlyArg = nullptr; QualType DestType = Entity.getType(); switch (Failure) { case FK_TooManyInitsForReference: // FIXME: Customize for the initialized entity? if (Args.empty()) { // Dig out the reference subobject which is uninitialized and diagnose it. // If this is value-initialization, this could be nested some way within // the target type. assert(Kind.getKind() == InitializationKind::IK_Value || DestType->isReferenceType()); bool Diagnosed = DiagnoseUninitializedReference(S, Kind.getLocation(), DestType); assert(Diagnosed && "couldn't find uninitialized reference to diagnose"); (void)Diagnosed; } else // FIXME: diagnostic below could be better! S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits) << SourceRange(Args.front()->getLocStart(), Args.back()->getLocEnd()); break; case FK_ParenthesizedListInitForReference: S.Diag(Kind.getLocation(), diag::err_list_init_in_parens) << 1 << Entity.getType() << Args[0]->getSourceRange(); break; case FK_ArrayNeedsInitList: S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 0; break; case FK_ArrayNeedsInitListOrStringLiteral: S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 1; break; case FK_ArrayNeedsInitListOrWideStringLiteral: S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 2; break; case FK_NarrowStringIntoWideCharArray: S.Diag(Kind.getLocation(), diag::err_array_init_narrow_string_into_wchar); break; case FK_WideStringIntoCharArray: S.Diag(Kind.getLocation(), diag::err_array_init_wide_string_into_char); break; case FK_IncompatWideStringIntoWideChar: S.Diag(Kind.getLocation(), diag::err_array_init_incompat_wide_string_into_wchar); break; case FK_PlainStringIntoUTF8Char: S.Diag(Kind.getLocation(), diag::err_array_init_plain_string_into_char8_t); S.Diag(Args.front()->getLocStart(), diag::note_array_init_plain_string_into_char8_t) << FixItHint::CreateInsertion(Args.front()->getLocStart(), "u8"); break; case FK_UTF8StringIntoPlainChar: S.Diag(Kind.getLocation(), diag::err_array_init_utf8_string_into_char); break; case FK_ArrayTypeMismatch: case FK_NonConstantArrayInit: S.Diag(Kind.getLocation(), (Failure == FK_ArrayTypeMismatch ? diag::err_array_init_different_type : diag::err_array_init_non_constant_array)) << DestType.getNonReferenceType() << OnlyArg->getType() << Args[0]->getSourceRange(); break; case FK_VariableLengthArrayHasInitializer: S.Diag(Kind.getLocation(), diag::err_variable_object_no_init) << Args[0]->getSourceRange(); break; case FK_AddressOfOverloadFailed: { DeclAccessPair Found; S.ResolveAddressOfOverloadedFunction(OnlyArg, DestType.getNonReferenceType(), true, Found); break; } case FK_AddressOfUnaddressableFunction: { auto *FD = cast(cast(OnlyArg)->getDecl()); S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true, OnlyArg->getLocStart()); break; } case FK_ReferenceInitOverloadFailed: case FK_UserConversionOverloadFailed: switch (FailedOverloadResult) { case OR_Ambiguous: if (Failure == FK_UserConversionOverloadFailed) S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition) << OnlyArg->getType() << DestType << Args[0]->getSourceRange(); else S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous) << DestType << OnlyArg->getType() << Args[0]->getSourceRange(); FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args); break; case OR_No_Viable_Function: if (!S.RequireCompleteType(Kind.getLocation(), DestType.getNonReferenceType(), diag::err_typecheck_nonviable_condition_incomplete, OnlyArg->getType(), Args[0]->getSourceRange())) S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition) << (Entity.getKind() == InitializedEntity::EK_Result) << OnlyArg->getType() << Args[0]->getSourceRange() << DestType.getNonReferenceType(); FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args); break; case OR_Deleted: { S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function) << OnlyArg->getType() << DestType.getNonReferenceType() << Args[0]->getSourceRange(); OverloadCandidateSet::iterator Best; OverloadingResult Ovl = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best); if (Ovl == OR_Deleted) { S.NoteDeletedFunction(Best->Function); } else { llvm_unreachable("Inconsistent overload resolution?"); } break; } case OR_Success: llvm_unreachable("Conversion did not fail!"); } break; case FK_NonConstLValueReferenceBindingToTemporary: if (isa(Args[0])) { S.Diag(Kind.getLocation(), diag::err_lvalue_reference_bind_to_initlist) << DestType.getNonReferenceType().isVolatileQualified() << DestType.getNonReferenceType() << Args[0]->getSourceRange(); break; } LLVM_FALLTHROUGH; case FK_NonConstLValueReferenceBindingToUnrelated: S.Diag(Kind.getLocation(), Failure == FK_NonConstLValueReferenceBindingToTemporary ? diag::err_lvalue_reference_bind_to_temporary : diag::err_lvalue_reference_bind_to_unrelated) << DestType.getNonReferenceType().isVolatileQualified() << DestType.getNonReferenceType() << OnlyArg->getType() << Args[0]->getSourceRange(); break; case FK_NonConstLValueReferenceBindingToBitfield: { // We don't necessarily have an unambiguous source bit-field. FieldDecl *BitField = Args[0]->getSourceBitField(); S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield) << DestType.isVolatileQualified() << (BitField ? BitField->getDeclName() : DeclarationName()) << (BitField != nullptr) << Args[0]->getSourceRange(); if (BitField) S.Diag(BitField->getLocation(), diag::note_bitfield_decl); break; } case FK_NonConstLValueReferenceBindingToVectorElement: S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element) << DestType.isVolatileQualified() << Args[0]->getSourceRange(); break; case FK_RValueReferenceBindingToLValue: S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref) << DestType.getNonReferenceType() << OnlyArg->getType() << Args[0]->getSourceRange(); break; case FK_ReferenceInitDropsQualifiers: { QualType SourceType = OnlyArg->getType(); QualType NonRefType = DestType.getNonReferenceType(); Qualifiers DroppedQualifiers = SourceType.getQualifiers() - NonRefType.getQualifiers(); S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals) << SourceType << NonRefType << DroppedQualifiers.getCVRQualifiers() << Args[0]->getSourceRange(); break; } case FK_ReferenceInitFailed: S.Diag(Kind.getLocation(), diag::err_reference_bind_failed) << DestType.getNonReferenceType() << OnlyArg->isLValue() << OnlyArg->getType() << Args[0]->getSourceRange(); emitBadConversionNotes(S, Entity, Args[0]); break; case FK_ConversionFailed: { QualType FromType = OnlyArg->getType(); PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed) << (int)Entity.getKind() << DestType << OnlyArg->isLValue() << FromType << Args[0]->getSourceRange(); S.HandleFunctionTypeMismatch(PDiag, FromType, DestType); S.Diag(Kind.getLocation(), PDiag); emitBadConversionNotes(S, Entity, Args[0]); break; } case FK_ConversionFromPropertyFailed: // No-op. This error has already been reported. break; case FK_TooManyInitsForScalar: { SourceRange R; auto *InitList = dyn_cast(Args[0]); if (InitList && InitList->getNumInits() >= 1) { R = SourceRange(InitList->getInit(0)->getLocEnd(), InitList->getLocEnd()); } else { assert(Args.size() > 1 && "Expected multiple initializers!"); R = SourceRange(Args.front()->getLocEnd(), Args.back()->getLocEnd()); } R.setBegin(S.getLocForEndOfToken(R.getBegin())); if (Kind.isCStyleOrFunctionalCast()) S.Diag(Kind.getLocation(), diag::err_builtin_func_cast_more_than_one_arg) << R; else S.Diag(Kind.getLocation(), diag::err_excess_initializers) << /*scalar=*/2 << R; break; } case FK_ParenthesizedListInitForScalar: S.Diag(Kind.getLocation(), diag::err_list_init_in_parens) << 0 << Entity.getType() << Args[0]->getSourceRange(); break; case FK_ReferenceBindingToInitList: S.Diag(Kind.getLocation(), diag::err_reference_bind_init_list) << DestType.getNonReferenceType() << Args[0]->getSourceRange(); break; case FK_InitListBadDestinationType: S.Diag(Kind.getLocation(), diag::err_init_list_bad_dest_type) << (DestType->isRecordType()) << DestType << Args[0]->getSourceRange(); break; case FK_ListConstructorOverloadFailed: case FK_ConstructorOverloadFailed: { SourceRange ArgsRange; if (Args.size()) ArgsRange = SourceRange(Args.front()->getLocStart(), Args.back()->getLocEnd()); if (Failure == FK_ListConstructorOverloadFailed) { assert(Args.size() == 1 && "List construction from other than 1 argument."); InitListExpr *InitList = cast(Args[0]); Args = MultiExprArg(InitList->getInits(), InitList->getNumInits()); } // FIXME: Using "DestType" for the entity we're printing is probably // bad. switch (FailedOverloadResult) { case OR_Ambiguous: S.Diag(Kind.getLocation(), diag::err_ovl_ambiguous_init) << DestType << ArgsRange; FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args); break; case OR_No_Viable_Function: if (Kind.getKind() == InitializationKind::IK_Default && (Entity.getKind() == InitializedEntity::EK_Base || Entity.getKind() == InitializedEntity::EK_Member) && isa(S.CurContext)) { // This is implicit default initialization of a member or // base within a constructor. If no viable function was // found, notify the user that they need to explicitly // initialize this base/member. CXXConstructorDecl *Constructor = cast(S.CurContext); const CXXRecordDecl *InheritedFrom = nullptr; if (auto Inherited = Constructor->getInheritedConstructor()) InheritedFrom = Inherited.getShadowDecl()->getNominatedBaseClass(); if (Entity.getKind() == InitializedEntity::EK_Base) { S.Diag(Kind.getLocation(), diag::err_missing_default_ctor) << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0) << S.Context.getTypeDeclType(Constructor->getParent()) << /*base=*/0 << Entity.getType() << InheritedFrom; RecordDecl *BaseDecl = Entity.getBaseSpecifier()->getType()->getAs() ->getDecl(); S.Diag(BaseDecl->getLocation(), diag::note_previous_decl) << S.Context.getTagDeclType(BaseDecl); } else { S.Diag(Kind.getLocation(), diag::err_missing_default_ctor) << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0) << S.Context.getTypeDeclType(Constructor->getParent()) << /*member=*/1 << Entity.getName() << InheritedFrom; S.Diag(Entity.getDecl()->getLocation(), diag::note_member_declared_at); if (const RecordType *Record = Entity.getType()->getAs()) S.Diag(Record->getDecl()->getLocation(), diag::note_previous_decl) << S.Context.getTagDeclType(Record->getDecl()); } break; } S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init) << DestType << ArgsRange; FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args); break; case OR_Deleted: { OverloadCandidateSet::iterator Best; OverloadingResult Ovl = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best); if (Ovl != OR_Deleted) { S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init) << true << DestType << ArgsRange; llvm_unreachable("Inconsistent overload resolution?"); break; } // If this is a defaulted or implicitly-declared function, then // it was implicitly deleted. Make it clear that the deletion was // implicit. if (S.isImplicitlyDeleted(Best->Function)) S.Diag(Kind.getLocation(), diag::err_ovl_deleted_special_init) << S.getSpecialMember(cast(Best->Function)) << DestType << ArgsRange; else S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init) << true << DestType << ArgsRange; S.NoteDeletedFunction(Best->Function); break; } case OR_Success: llvm_unreachable("Conversion did not fail!"); } } break; case FK_DefaultInitOfConst: if (Entity.getKind() == InitializedEntity::EK_Member && isa(S.CurContext)) { // This is implicit default-initialization of a const member in // a constructor. Complain that it needs to be explicitly // initialized. CXXConstructorDecl *Constructor = cast(S.CurContext); S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor) << (Constructor->getInheritedConstructor() ? 2 : Constructor->isImplicit() ? 1 : 0) << S.Context.getTypeDeclType(Constructor->getParent()) << /*const=*/1 << Entity.getName(); S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl) << Entity.getName(); } else { S.Diag(Kind.getLocation(), diag::err_default_init_const) << DestType << (bool)DestType->getAs(); } break; case FK_Incomplete: S.RequireCompleteType(Kind.getLocation(), FailedIncompleteType, diag::err_init_incomplete_type); break; case FK_ListInitializationFailed: { // Run the init list checker again to emit diagnostics. InitListExpr *InitList = cast(Args[0]); diagnoseListInit(S, Entity, InitList); break; } case FK_PlaceholderType: { // FIXME: Already diagnosed! break; } case FK_ExplicitConstructor: { S.Diag(Kind.getLocation(), diag::err_selected_explicit_constructor) << Args[0]->getSourceRange(); OverloadCandidateSet::iterator Best; OverloadingResult Ovl = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best); (void)Ovl; assert(Ovl == OR_Success && "Inconsistent overload resolution"); CXXConstructorDecl *CtorDecl = cast(Best->Function); S.Diag(CtorDecl->getLocation(), diag::note_explicit_ctor_deduction_guide_here) << false; break; } } PrintInitLocationNote(S, Entity); return true; } void InitializationSequence::dump(raw_ostream &OS) const { switch (SequenceKind) { case FailedSequence: { OS << "Failed sequence: "; switch (Failure) { case FK_TooManyInitsForReference: OS << "too many initializers for reference"; break; case FK_ParenthesizedListInitForReference: OS << "parenthesized list init for reference"; break; case FK_ArrayNeedsInitList: OS << "array requires initializer list"; break; case FK_AddressOfUnaddressableFunction: OS << "address of unaddressable function was taken"; break; case FK_ArrayNeedsInitListOrStringLiteral: OS << "array requires initializer list or string literal"; break; case FK_ArrayNeedsInitListOrWideStringLiteral: OS << "array requires initializer list or wide string literal"; break; case FK_NarrowStringIntoWideCharArray: OS << "narrow string into wide char array"; break; case FK_WideStringIntoCharArray: OS << "wide string into char array"; break; case FK_IncompatWideStringIntoWideChar: OS << "incompatible wide string into wide char array"; break; case FK_PlainStringIntoUTF8Char: OS << "plain string literal into char8_t array"; break; case FK_UTF8StringIntoPlainChar: OS << "u8 string literal into char array"; break; case FK_ArrayTypeMismatch: OS << "array type mismatch"; break; case FK_NonConstantArrayInit: OS << "non-constant array initializer"; break; case FK_AddressOfOverloadFailed: OS << "address of overloaded function failed"; break; case FK_ReferenceInitOverloadFailed: OS << "overload resolution for reference initialization failed"; break; case FK_NonConstLValueReferenceBindingToTemporary: OS << "non-const lvalue reference bound to temporary"; break; case FK_NonConstLValueReferenceBindingToBitfield: OS << "non-const lvalue reference bound to bit-field"; break; case FK_NonConstLValueReferenceBindingToVectorElement: OS << "non-const lvalue reference bound to vector element"; break; case FK_NonConstLValueReferenceBindingToUnrelated: OS << "non-const lvalue reference bound to unrelated type"; break; case FK_RValueReferenceBindingToLValue: OS << "rvalue reference bound to an lvalue"; break; case FK_ReferenceInitDropsQualifiers: OS << "reference initialization drops qualifiers"; break; case FK_ReferenceInitFailed: OS << "reference initialization failed"; break; case FK_ConversionFailed: OS << "conversion failed"; break; case FK_ConversionFromPropertyFailed: OS << "conversion from property failed"; break; case FK_TooManyInitsForScalar: OS << "too many initializers for scalar"; break; case FK_ParenthesizedListInitForScalar: OS << "parenthesized list init for reference"; break; case FK_ReferenceBindingToInitList: OS << "referencing binding to initializer list"; break; case FK_InitListBadDestinationType: OS << "initializer list for non-aggregate, non-scalar type"; break; case FK_UserConversionOverloadFailed: OS << "overloading failed for user-defined conversion"; break; case FK_ConstructorOverloadFailed: OS << "constructor overloading failed"; break; case FK_DefaultInitOfConst: OS << "default initialization of a const variable"; break; case FK_Incomplete: OS << "initialization of incomplete type"; break; case FK_ListInitializationFailed: OS << "list initialization checker failure"; break; case FK_VariableLengthArrayHasInitializer: OS << "variable length array has an initializer"; break; case FK_PlaceholderType: OS << "initializer expression isn't contextually valid"; break; case FK_ListConstructorOverloadFailed: OS << "list constructor overloading failed"; break; case FK_ExplicitConstructor: OS << "list copy initialization chose explicit constructor"; break; } OS << '\n'; return; } case DependentSequence: OS << "Dependent sequence\n"; return; case NormalSequence: OS << "Normal sequence: "; break; } for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) { if (S != step_begin()) { OS << " -> "; } switch (S->Kind) { case SK_ResolveAddressOfOverloadedFunction: OS << "resolve address of overloaded function"; break; case SK_CastDerivedToBaseRValue: OS << "derived-to-base (rvalue)"; break; case SK_CastDerivedToBaseXValue: OS << "derived-to-base (xvalue)"; break; case SK_CastDerivedToBaseLValue: OS << "derived-to-base (lvalue)"; break; case SK_BindReference: OS << "bind reference to lvalue"; break; case SK_BindReferenceToTemporary: OS << "bind reference to a temporary"; break; case SK_FinalCopy: OS << "final copy in class direct-initialization"; break; case SK_ExtraneousCopyToTemporary: OS << "extraneous C++03 copy to temporary"; break; case SK_UserConversion: OS << "user-defined conversion via " << *S->Function.Function; break; case SK_QualificationConversionRValue: OS << "qualification conversion (rvalue)"; break; case SK_QualificationConversionXValue: OS << "qualification conversion (xvalue)"; break; case SK_QualificationConversionLValue: OS << "qualification conversion (lvalue)"; break; case SK_AtomicConversion: OS << "non-atomic-to-atomic conversion"; break; case SK_LValueToRValue: OS << "load (lvalue to rvalue)"; break; case SK_ConversionSequence: OS << "implicit conversion sequence ("; S->ICS->dump(); // FIXME: use OS OS << ")"; break; case SK_ConversionSequenceNoNarrowing: OS << "implicit conversion sequence with narrowing prohibited ("; S->ICS->dump(); // FIXME: use OS OS << ")"; break; case SK_ListInitialization: OS << "list aggregate initialization"; break; case SK_UnwrapInitList: OS << "unwrap reference initializer list"; break; case SK_RewrapInitList: OS << "rewrap reference initializer list"; break; case SK_ConstructorInitialization: OS << "constructor initialization"; break; case SK_ConstructorInitializationFromList: OS << "list initialization via constructor"; break; case SK_ZeroInitialization: OS << "zero initialization"; break; case SK_CAssignment: OS << "C assignment"; break; case SK_StringInit: OS << "string initialization"; break; case SK_ObjCObjectConversion: OS << "Objective-C object conversion"; break; case SK_ArrayLoopIndex: OS << "indexing for array initialization loop"; break; case SK_ArrayLoopInit: OS << "array initialization loop"; break; case SK_ArrayInit: OS << "array initialization"; break; case SK_GNUArrayInit: OS << "array initialization (GNU extension)"; break; case SK_ParenthesizedArrayInit: OS << "parenthesized array initialization"; break; case SK_PassByIndirectCopyRestore: OS << "pass by indirect copy and restore"; break; case SK_PassByIndirectRestore: OS << "pass by indirect restore"; break; case SK_ProduceObjCObject: OS << "Objective-C object retension"; break; case SK_StdInitializerList: OS << "std::initializer_list from initializer list"; break; case SK_StdInitializerListConstructorCall: OS << "list initialization from std::initializer_list"; break; case SK_OCLSamplerInit: OS << "OpenCL sampler_t from integer constant"; break; case SK_OCLZeroEvent: OS << "OpenCL event_t from zero"; break; case SK_OCLZeroQueue: OS << "OpenCL queue_t from zero"; break; } OS << " [" << S->Type.getAsString() << ']'; } OS << '\n'; } void InitializationSequence::dump() const { dump(llvm::errs()); } static bool NarrowingErrs(const LangOptions &L) { return L.CPlusPlus11 && (!L.MicrosoftExt || L.isCompatibleWithMSVC(LangOptions::MSVC2015)); } static void DiagnoseNarrowingInInitList(Sema &S, const ImplicitConversionSequence &ICS, QualType PreNarrowingType, QualType EntityType, const Expr *PostInit) { const StandardConversionSequence *SCS = nullptr; switch (ICS.getKind()) { case ImplicitConversionSequence::StandardConversion: SCS = &ICS.Standard; break; case ImplicitConversionSequence::UserDefinedConversion: SCS = &ICS.UserDefined.After; break; case ImplicitConversionSequence::AmbiguousConversion: case ImplicitConversionSequence::EllipsisConversion: case ImplicitConversionSequence::BadConversion: return; } // C++11 [dcl.init.list]p7: Check whether this is a narrowing conversion. APValue ConstantValue; QualType ConstantType; switch (SCS->getNarrowingKind(S.Context, PostInit, ConstantValue, ConstantType)) { case NK_Not_Narrowing: case NK_Dependent_Narrowing: // No narrowing occurred. return; case NK_Type_Narrowing: // This was a floating-to-integer conversion, which is always considered a // narrowing conversion even if the value is a constant and can be // represented exactly as an integer. S.Diag(PostInit->getLocStart(), NarrowingErrs(S.getLangOpts()) ? diag::ext_init_list_type_narrowing : diag::warn_init_list_type_narrowing) << PostInit->getSourceRange() << PreNarrowingType.getLocalUnqualifiedType() << EntityType.getLocalUnqualifiedType(); break; case NK_Constant_Narrowing: // A constant value was narrowed. S.Diag(PostInit->getLocStart(), NarrowingErrs(S.getLangOpts()) ? diag::ext_init_list_constant_narrowing : diag::warn_init_list_constant_narrowing) << PostInit->getSourceRange() << ConstantValue.getAsString(S.getASTContext(), ConstantType) << EntityType.getLocalUnqualifiedType(); break; case NK_Variable_Narrowing: // A variable's value may have been narrowed. S.Diag(PostInit->getLocStart(), NarrowingErrs(S.getLangOpts()) ? diag::ext_init_list_variable_narrowing : diag::warn_init_list_variable_narrowing) << PostInit->getSourceRange() << PreNarrowingType.getLocalUnqualifiedType() << EntityType.getLocalUnqualifiedType(); break; } SmallString<128> StaticCast; llvm::raw_svector_ostream OS(StaticCast); OS << "static_cast<"; if (const TypedefType *TT = EntityType->getAs()) { // It's important to use the typedef's name if there is one so that the // fixit doesn't break code using types like int64_t. // // FIXME: This will break if the typedef requires qualification. But // getQualifiedNameAsString() includes non-machine-parsable components. OS << *TT->getDecl(); } else if (const BuiltinType *BT = EntityType->getAs()) OS << BT->getName(S.getLangOpts()); else { // Oops, we didn't find the actual type of the variable. Don't emit a fixit // with a broken cast. return; } OS << ">("; S.Diag(PostInit->getLocStart(), diag::note_init_list_narrowing_silence) << PostInit->getSourceRange() << FixItHint::CreateInsertion(PostInit->getLocStart(), OS.str()) << FixItHint::CreateInsertion( S.getLocForEndOfToken(PostInit->getLocEnd()), ")"); } //===----------------------------------------------------------------------===// // Initialization helper functions //===----------------------------------------------------------------------===// bool Sema::CanPerformCopyInitialization(const InitializedEntity &Entity, ExprResult Init) { if (Init.isInvalid()) return false; Expr *InitE = Init.get(); assert(InitE && "No initialization expression"); InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(), SourceLocation()); InitializationSequence Seq(*this, Entity, Kind, InitE); return !Seq.Failed(); } ExprResult Sema::PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList, bool AllowExplicit) { if (Init.isInvalid()) return ExprError(); Expr *InitE = Init.get(); assert(InitE && "No initialization expression?"); if (EqualLoc.isInvalid()) EqualLoc = InitE->getLocStart(); InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(), EqualLoc, AllowExplicit); InitializationSequence Seq(*this, Entity, Kind, InitE, TopLevelOfInitList); // Prevent infinite recursion when performing parameter copy-initialization. const bool ShouldTrackCopy = Entity.isParameterKind() && Seq.isConstructorInitialization(); if (ShouldTrackCopy) { if (llvm::find(CurrentParameterCopyTypes, Entity.getType()) != CurrentParameterCopyTypes.end()) { Seq.SetOverloadFailure( InitializationSequence::FK_ConstructorOverloadFailed, OR_No_Viable_Function); // Try to give a meaningful diagnostic note for the problematic // constructor. const auto LastStep = Seq.step_end() - 1; assert(LastStep->Kind == InitializationSequence::SK_ConstructorInitialization); const FunctionDecl *Function = LastStep->Function.Function; auto Candidate = llvm::find_if(Seq.getFailedCandidateSet(), [Function](const OverloadCandidate &Candidate) -> bool { return Candidate.Viable && Candidate.Function == Function && Candidate.Conversions.size() > 0; }); if (Candidate != Seq.getFailedCandidateSet().end() && Function->getNumParams() > 0) { Candidate->Viable = false; Candidate->FailureKind = ovl_fail_bad_conversion; Candidate->Conversions[0].setBad(BadConversionSequence::no_conversion, InitE, Function->getParamDecl(0)->getType()); } } CurrentParameterCopyTypes.push_back(Entity.getType()); } ExprResult Result = Seq.Perform(*this, Entity, Kind, InitE); if (ShouldTrackCopy) CurrentParameterCopyTypes.pop_back(); return Result; } /// Determine whether RD is, or is derived from, a specialization of CTD. static bool isOrIsDerivedFromSpecializationOf(CXXRecordDecl *RD, ClassTemplateDecl *CTD) { auto NotSpecialization = [&] (const CXXRecordDecl *Candidate) { auto *CTSD = dyn_cast(Candidate); return !CTSD || !declaresSameEntity(CTSD->getSpecializedTemplate(), CTD); }; return !(NotSpecialization(RD) && RD->forallBases(NotSpecialization)); } QualType Sema::DeduceTemplateSpecializationFromInitializer( TypeSourceInfo *TSInfo, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Inits) { auto *DeducedTST = dyn_cast( TSInfo->getType()->getContainedDeducedType()); assert(DeducedTST && "not a deduced template specialization type"); // We can only perform deduction for class templates. auto TemplateName = DeducedTST->getTemplateName(); auto *Template = dyn_cast_or_null(TemplateName.getAsTemplateDecl()); if (!Template) { Diag(Kind.getLocation(), diag::err_deduced_non_class_template_specialization_type) << (int)getTemplateNameKindForDiagnostics(TemplateName) << TemplateName; if (auto *TD = TemplateName.getAsTemplateDecl()) Diag(TD->getLocation(), diag::note_template_decl_here); return QualType(); } // Can't deduce from dependent arguments. if (Expr::hasAnyTypeDependentArguments(Inits)) return Context.DependentTy; // FIXME: Perform "exact type" matching first, per CWG discussion? // Or implement this via an implied 'T(T) -> T' deduction guide? // FIXME: Do we need/want a std::initializer_list special case? // Look up deduction guides, including those synthesized from constructors. // // C++1z [over.match.class.deduct]p1: // A set of functions and function templates is formed comprising: // - For each constructor of the class template designated by the // template-name, a function template [...] // - For each deduction-guide, a function or function template [...] DeclarationNameInfo NameInfo( Context.DeclarationNames.getCXXDeductionGuideName(Template), TSInfo->getTypeLoc().getEndLoc()); LookupResult Guides(*this, NameInfo, LookupOrdinaryName); LookupQualifiedName(Guides, Template->getDeclContext()); // FIXME: Do not diagnose inaccessible deduction guides. The standard isn't // clear on this, but they're not found by name so access does not apply. Guides.suppressDiagnostics(); // Figure out if this is list-initialization. InitListExpr *ListInit = (Inits.size() == 1 && Kind.getKind() != InitializationKind::IK_Direct) ? dyn_cast(Inits[0]) : nullptr; // C++1z [over.match.class.deduct]p1: // Initialization and overload resolution are performed as described in // [dcl.init] and [over.match.ctor], [over.match.copy], or [over.match.list] // (as appropriate for the type of initialization performed) for an object // of a hypothetical class type, where the selected functions and function // templates are considered to be the constructors of that class type // // Since we know we're initializing a class type of a type unrelated to that // of the initializer, this reduces to something fairly reasonable. OverloadCandidateSet Candidates(Kind.getLocation(), OverloadCandidateSet::CSK_Normal); OverloadCandidateSet::iterator Best; auto tryToResolveOverload = [&](bool OnlyListConstructors) -> OverloadingResult { Candidates.clear(OverloadCandidateSet::CSK_Normal); for (auto I = Guides.begin(), E = Guides.end(); I != E; ++I) { NamedDecl *D = (*I)->getUnderlyingDecl(); if (D->isInvalidDecl()) continue; auto *TD = dyn_cast(D); auto *GD = dyn_cast_or_null( TD ? TD->getTemplatedDecl() : dyn_cast(D)); if (!GD) continue; // C++ [over.match.ctor]p1: (non-list copy-initialization from non-class) // For copy-initialization, the candidate functions are all the // converting constructors (12.3.1) of that class. // C++ [over.match.copy]p1: (non-list copy-initialization from class) // The converting constructors of T are candidate functions. if (Kind.isCopyInit() && !ListInit) { // Only consider converting constructors. if (GD->isExplicit()) continue; // When looking for a converting constructor, deduction guides that // could never be called with one argument are not interesting to // check or note. if (GD->getMinRequiredArguments() > 1 || (GD->getNumParams() == 0 && !GD->isVariadic())) continue; } // C++ [over.match.list]p1.1: (first phase list initialization) // Initially, the candidate functions are the initializer-list // constructors of the class T if (OnlyListConstructors && !isInitListConstructor(GD)) continue; // C++ [over.match.list]p1.2: (second phase list initialization) // the candidate functions are all the constructors of the class T // C++ [over.match.ctor]p1: (all other cases) // the candidate functions are all the constructors of the class of // the object being initialized // C++ [over.best.ics]p4: // When [...] the constructor [...] is a candidate by // - [over.match.copy] (in all cases) // FIXME: The "second phase of [over.match.list] case can also // theoretically happen here, but it's not clear whether we can // ever have a parameter of the right type. bool SuppressUserConversions = Kind.isCopyInit(); if (TD) AddTemplateOverloadCandidate(TD, I.getPair(), /*ExplicitArgs*/ nullptr, Inits, Candidates, SuppressUserConversions); else AddOverloadCandidate(GD, I.getPair(), Inits, Candidates, SuppressUserConversions); } return Candidates.BestViableFunction(*this, Kind.getLocation(), Best); }; OverloadingResult Result = OR_No_Viable_Function; // C++11 [over.match.list]p1, per DR1467: for list-initialization, first // try initializer-list constructors. if (ListInit) { bool TryListConstructors = true; // Try list constructors unless the list is empty and the class has one or // more default constructors, in which case those constructors win. if (!ListInit->getNumInits()) { for (NamedDecl *D : Guides) { auto *FD = dyn_cast(D->getUnderlyingDecl()); if (FD && FD->getMinRequiredArguments() == 0) { TryListConstructors = false; break; } } } else if (ListInit->getNumInits() == 1) { // C++ [over.match.class.deduct]: // As an exception, the first phase in [over.match.list] (considering // initializer-list constructors) is omitted if the initializer list // consists of a single expression of type cv U, where U is a // specialization of C or a class derived from a specialization of C. Expr *E = ListInit->getInit(0); auto *RD = E->getType()->getAsCXXRecordDecl(); if (!isa(E) && RD && isCompleteType(Kind.getLocation(), E->getType()) && isOrIsDerivedFromSpecializationOf(RD, Template)) TryListConstructors = false; } if (TryListConstructors) Result = tryToResolveOverload(/*OnlyListConstructor*/true); // Then unwrap the initializer list and try again considering all // constructors. Inits = MultiExprArg(ListInit->getInits(), ListInit->getNumInits()); } // If list-initialization fails, or if we're doing any other kind of // initialization, we (eventually) consider constructors. if (Result == OR_No_Viable_Function) Result = tryToResolveOverload(/*OnlyListConstructor*/false); switch (Result) { case OR_Ambiguous: Diag(Kind.getLocation(), diag::err_deduced_class_template_ctor_ambiguous) << TemplateName; // FIXME: For list-initialization candidates, it'd usually be better to // list why they were not viable when given the initializer list itself as // an argument. Candidates.NoteCandidates(*this, OCD_ViableCandidates, Inits); return QualType(); case OR_No_Viable_Function: { CXXRecordDecl *Primary = cast(Template)->getTemplatedDecl(); bool Complete = isCompleteType(Kind.getLocation(), Context.getTypeDeclType(Primary)); Diag(Kind.getLocation(), Complete ? diag::err_deduced_class_template_ctor_no_viable : diag::err_deduced_class_template_incomplete) << TemplateName << !Guides.empty(); Candidates.NoteCandidates(*this, OCD_AllCandidates, Inits); return QualType(); } case OR_Deleted: { Diag(Kind.getLocation(), diag::err_deduced_class_template_deleted) << TemplateName; NoteDeletedFunction(Best->Function); return QualType(); } case OR_Success: // C++ [over.match.list]p1: // In copy-list-initialization, if an explicit constructor is chosen, the // initialization is ill-formed. if (Kind.isCopyInit() && ListInit && cast(Best->Function)->isExplicit()) { bool IsDeductionGuide = !Best->Function->isImplicit(); Diag(Kind.getLocation(), diag::err_deduced_class_template_explicit) << TemplateName << IsDeductionGuide; Diag(Best->Function->getLocation(), diag::note_explicit_ctor_deduction_guide_here) << IsDeductionGuide; return QualType(); } // Make sure we didn't select an unusable deduction guide, and mark it // as referenced. DiagnoseUseOfDecl(Best->Function, Kind.getLocation()); MarkFunctionReferenced(Kind.getLocation(), Best->Function); break; } // C++ [dcl.type.class.deduct]p1: // The placeholder is replaced by the return type of the function selected // by overload resolution for class template deduction. return SubstAutoType(TSInfo->getType(), Best->Function->getReturnType()); } Index: vendor/clang/dist-release_70/lib/Serialization/ASTWriter.cpp =================================================================== --- vendor/clang/dist-release_70/lib/Serialization/ASTWriter.cpp (revision 341366) +++ vendor/clang/dist-release_70/lib/Serialization/ASTWriter.cpp (revision 341367) @@ -1,6474 +1,6477 @@ //===- ASTWriter.cpp - AST File Writer ------------------------------------===// // // 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 ASTWriter class, which writes AST files. // //===----------------------------------------------------------------------===// #include "clang/Serialization/ASTWriter.h" #include "ASTCommon.h" #include "ASTReaderInternals.h" #include "MultiOnDiskHashTable.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTUnresolvedSet.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclContextInternals.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/LambdaCapture.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/RawCommentList.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLocVisitor.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemOptions.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/Lambda.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/MemoryBufferCache.h" #include "clang/Basic/Module.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/OpenCLOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManagerInternals.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "clang/Basic/Version.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/ModuleMap.h" #include "clang/Lex/PreprocessingRecord.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Lex/Token.h" #include "clang/Sema/IdentifierResolver.h" #include "clang/Sema/ObjCMethodList.h" #include "clang/Sema/Sema.h" #include "clang/Sema/Weak.h" #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/Module.h" #include "clang/Serialization/ModuleFileExtension.h" #include "clang/Serialization/SerializationDiagnostic.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Bitcode/BitCodes.h" #include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compression.h" #include "llvm/Support/DJB.h" #include "llvm/Support/Endian.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/Path.h" #include "llvm/Support/SHA1.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace clang; using namespace clang::serialization; template static StringRef bytes(const std::vector &v) { if (v.empty()) return StringRef(); return StringRef(reinterpret_cast(&v[0]), sizeof(T) * v.size()); } template static StringRef bytes(const SmallVectorImpl &v) { return StringRef(reinterpret_cast(v.data()), sizeof(T) * v.size()); } //===----------------------------------------------------------------------===// // Type serialization //===----------------------------------------------------------------------===// namespace clang { class ASTTypeWriter { ASTWriter &Writer; ASTRecordWriter Record; /// Type code that corresponds to the record generated. TypeCode Code = static_cast(0); /// Abbreviation to use for the record, if any. unsigned AbbrevToUse = 0; public: ASTTypeWriter(ASTWriter &Writer, ASTWriter::RecordDataImpl &Record) : Writer(Writer), Record(Writer, Record) {} uint64_t Emit() { return Record.Emit(Code, AbbrevToUse); } void Visit(QualType T) { if (T.hasLocalNonFastQualifiers()) { Qualifiers Qs = T.getLocalQualifiers(); Record.AddTypeRef(T.getLocalUnqualifiedType()); Record.push_back(Qs.getAsOpaqueValue()); Code = TYPE_EXT_QUAL; AbbrevToUse = Writer.TypeExtQualAbbrev; } else { switch (T->getTypeClass()) { // For all of the concrete, non-dependent types, call the // appropriate visitor function. #define TYPE(Class, Base) \ case Type::Class: Visit##Class##Type(cast(T)); break; #define ABSTRACT_TYPE(Class, Base) #include "clang/AST/TypeNodes.def" } } } void VisitArrayType(const ArrayType *T); void VisitFunctionType(const FunctionType *T); void VisitTagType(const TagType *T); #define TYPE(Class, Base) void Visit##Class##Type(const Class##Type *T); #define ABSTRACT_TYPE(Class, Base) #include "clang/AST/TypeNodes.def" }; } // namespace clang void ASTTypeWriter::VisitBuiltinType(const BuiltinType *T) { llvm_unreachable("Built-in types are never serialized"); } void ASTTypeWriter::VisitComplexType(const ComplexType *T) { Record.AddTypeRef(T->getElementType()); Code = TYPE_COMPLEX; } void ASTTypeWriter::VisitPointerType(const PointerType *T) { Record.AddTypeRef(T->getPointeeType()); Code = TYPE_POINTER; } void ASTTypeWriter::VisitDecayedType(const DecayedType *T) { Record.AddTypeRef(T->getOriginalType()); Code = TYPE_DECAYED; } void ASTTypeWriter::VisitAdjustedType(const AdjustedType *T) { Record.AddTypeRef(T->getOriginalType()); Record.AddTypeRef(T->getAdjustedType()); Code = TYPE_ADJUSTED; } void ASTTypeWriter::VisitBlockPointerType(const BlockPointerType *T) { Record.AddTypeRef(T->getPointeeType()); Code = TYPE_BLOCK_POINTER; } void ASTTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) { Record.AddTypeRef(T->getPointeeTypeAsWritten()); Record.push_back(T->isSpelledAsLValue()); Code = TYPE_LVALUE_REFERENCE; } void ASTTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) { Record.AddTypeRef(T->getPointeeTypeAsWritten()); Code = TYPE_RVALUE_REFERENCE; } void ASTTypeWriter::VisitMemberPointerType(const MemberPointerType *T) { Record.AddTypeRef(T->getPointeeType()); Record.AddTypeRef(QualType(T->getClass(), 0)); Code = TYPE_MEMBER_POINTER; } void ASTTypeWriter::VisitArrayType(const ArrayType *T) { Record.AddTypeRef(T->getElementType()); Record.push_back(T->getSizeModifier()); // FIXME: stable values Record.push_back(T->getIndexTypeCVRQualifiers()); // FIXME: stable values } void ASTTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) { VisitArrayType(T); Record.AddAPInt(T->getSize()); Code = TYPE_CONSTANT_ARRAY; } void ASTTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) { VisitArrayType(T); Code = TYPE_INCOMPLETE_ARRAY; } void ASTTypeWriter::VisitVariableArrayType(const VariableArrayType *T) { VisitArrayType(T); Record.AddSourceLocation(T->getLBracketLoc()); Record.AddSourceLocation(T->getRBracketLoc()); Record.AddStmt(T->getSizeExpr()); Code = TYPE_VARIABLE_ARRAY; } void ASTTypeWriter::VisitVectorType(const VectorType *T) { Record.AddTypeRef(T->getElementType()); Record.push_back(T->getNumElements()); Record.push_back(T->getVectorKind()); Code = TYPE_VECTOR; } void ASTTypeWriter::VisitExtVectorType(const ExtVectorType *T) { VisitVectorType(T); Code = TYPE_EXT_VECTOR; } void ASTTypeWriter::VisitFunctionType(const FunctionType *T) { Record.AddTypeRef(T->getReturnType()); FunctionType::ExtInfo C = T->getExtInfo(); Record.push_back(C.getNoReturn()); Record.push_back(C.getHasRegParm()); Record.push_back(C.getRegParm()); // FIXME: need to stabilize encoding of calling convention... Record.push_back(C.getCC()); Record.push_back(C.getProducesResult()); Record.push_back(C.getNoCallerSavedRegs()); Record.push_back(C.getNoCfCheck()); if (C.getHasRegParm() || C.getRegParm() || C.getProducesResult()) AbbrevToUse = 0; } void ASTTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { VisitFunctionType(T); Code = TYPE_FUNCTION_NO_PROTO; } static void addExceptionSpec(const FunctionProtoType *T, ASTRecordWriter &Record) { Record.push_back(T->getExceptionSpecType()); if (T->getExceptionSpecType() == EST_Dynamic) { Record.push_back(T->getNumExceptions()); for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) Record.AddTypeRef(T->getExceptionType(I)); } else if (isComputedNoexcept(T->getExceptionSpecType())) { Record.AddStmt(T->getNoexceptExpr()); } else if (T->getExceptionSpecType() == EST_Uninstantiated) { Record.AddDeclRef(T->getExceptionSpecDecl()); Record.AddDeclRef(T->getExceptionSpecTemplate()); } else if (T->getExceptionSpecType() == EST_Unevaluated) { Record.AddDeclRef(T->getExceptionSpecDecl()); } } void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) { VisitFunctionType(T); Record.push_back(T->isVariadic()); Record.push_back(T->hasTrailingReturn()); Record.push_back(T->getTypeQuals()); Record.push_back(static_cast(T->getRefQualifier())); addExceptionSpec(T, Record); Record.push_back(T->getNumParams()); for (unsigned I = 0, N = T->getNumParams(); I != N; ++I) Record.AddTypeRef(T->getParamType(I)); if (T->hasExtParameterInfos()) { for (unsigned I = 0, N = T->getNumParams(); I != N; ++I) Record.push_back(T->getExtParameterInfo(I).getOpaqueValue()); } if (T->isVariadic() || T->hasTrailingReturn() || T->getTypeQuals() || T->getRefQualifier() || T->getExceptionSpecType() != EST_None || T->hasExtParameterInfos()) AbbrevToUse = 0; Code = TYPE_FUNCTION_PROTO; } void ASTTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) { Record.AddDeclRef(T->getDecl()); Code = TYPE_UNRESOLVED_USING; } void ASTTypeWriter::VisitTypedefType(const TypedefType *T) { Record.AddDeclRef(T->getDecl()); assert(!T->isCanonicalUnqualified() && "Invalid typedef ?"); Record.AddTypeRef(T->getCanonicalTypeInternal()); Code = TYPE_TYPEDEF; } void ASTTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) { Record.AddStmt(T->getUnderlyingExpr()); Code = TYPE_TYPEOF_EXPR; } void ASTTypeWriter::VisitTypeOfType(const TypeOfType *T) { Record.AddTypeRef(T->getUnderlyingType()); Code = TYPE_TYPEOF; } void ASTTypeWriter::VisitDecltypeType(const DecltypeType *T) { Record.AddTypeRef(T->getUnderlyingType()); Record.AddStmt(T->getUnderlyingExpr()); Code = TYPE_DECLTYPE; } void ASTTypeWriter::VisitUnaryTransformType(const UnaryTransformType *T) { Record.AddTypeRef(T->getBaseType()); Record.AddTypeRef(T->getUnderlyingType()); Record.push_back(T->getUTTKind()); Code = TYPE_UNARY_TRANSFORM; } void ASTTypeWriter::VisitAutoType(const AutoType *T) { Record.AddTypeRef(T->getDeducedType()); Record.push_back((unsigned)T->getKeyword()); if (T->getDeducedType().isNull()) Record.push_back(T->isDependentType()); Code = TYPE_AUTO; } void ASTTypeWriter::VisitDeducedTemplateSpecializationType( const DeducedTemplateSpecializationType *T) { Record.AddTemplateName(T->getTemplateName()); Record.AddTypeRef(T->getDeducedType()); if (T->getDeducedType().isNull()) Record.push_back(T->isDependentType()); Code = TYPE_DEDUCED_TEMPLATE_SPECIALIZATION; } void ASTTypeWriter::VisitTagType(const TagType *T) { Record.push_back(T->isDependentType()); Record.AddDeclRef(T->getDecl()->getCanonicalDecl()); assert(!T->isBeingDefined() && "Cannot serialize in the middle of a type definition"); } void ASTTypeWriter::VisitRecordType(const RecordType *T) { VisitTagType(T); Code = TYPE_RECORD; } void ASTTypeWriter::VisitEnumType(const EnumType *T) { VisitTagType(T); Code = TYPE_ENUM; } void ASTTypeWriter::VisitAttributedType(const AttributedType *T) { Record.AddTypeRef(T->getModifiedType()); Record.AddTypeRef(T->getEquivalentType()); Record.push_back(T->getAttrKind()); Code = TYPE_ATTRIBUTED; } void ASTTypeWriter::VisitSubstTemplateTypeParmType( const SubstTemplateTypeParmType *T) { Record.AddTypeRef(QualType(T->getReplacedParameter(), 0)); Record.AddTypeRef(T->getReplacementType()); Code = TYPE_SUBST_TEMPLATE_TYPE_PARM; } void ASTTypeWriter::VisitSubstTemplateTypeParmPackType( const SubstTemplateTypeParmPackType *T) { Record.AddTypeRef(QualType(T->getReplacedParameter(), 0)); Record.AddTemplateArgument(T->getArgumentPack()); Code = TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK; } void ASTTypeWriter::VisitTemplateSpecializationType( const TemplateSpecializationType *T) { Record.push_back(T->isDependentType()); Record.AddTemplateName(T->getTemplateName()); Record.push_back(T->getNumArgs()); for (const auto &ArgI : *T) Record.AddTemplateArgument(ArgI); Record.AddTypeRef(T->isTypeAlias() ? T->getAliasedType() : T->isCanonicalUnqualified() ? QualType() : T->getCanonicalTypeInternal()); Code = TYPE_TEMPLATE_SPECIALIZATION; } void ASTTypeWriter::VisitDependentSizedArrayType(const DependentSizedArrayType *T) { VisitArrayType(T); Record.AddStmt(T->getSizeExpr()); Record.AddSourceRange(T->getBracketsRange()); Code = TYPE_DEPENDENT_SIZED_ARRAY; } void ASTTypeWriter::VisitDependentSizedExtVectorType( const DependentSizedExtVectorType *T) { Record.AddTypeRef(T->getElementType()); Record.AddStmt(T->getSizeExpr()); Record.AddSourceLocation(T->getAttributeLoc()); Code = TYPE_DEPENDENT_SIZED_EXT_VECTOR; } void ASTTypeWriter::VisitDependentVectorType(const DependentVectorType *T) { Record.AddTypeRef(T->getElementType()); Record.AddStmt(const_cast(T->getSizeExpr())); Record.AddSourceLocation(T->getAttributeLoc()); Record.push_back(T->getVectorKind()); Code = TYPE_DEPENDENT_SIZED_VECTOR; } void ASTTypeWriter::VisitDependentAddressSpaceType( const DependentAddressSpaceType *T) { Record.AddTypeRef(T->getPointeeType()); Record.AddStmt(T->getAddrSpaceExpr()); Record.AddSourceLocation(T->getAttributeLoc()); Code = TYPE_DEPENDENT_ADDRESS_SPACE; } void ASTTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) { Record.push_back(T->getDepth()); Record.push_back(T->getIndex()); Record.push_back(T->isParameterPack()); Record.AddDeclRef(T->getDecl()); Code = TYPE_TEMPLATE_TYPE_PARM; } void ASTTypeWriter::VisitDependentNameType(const DependentNameType *T) { Record.push_back(T->getKeyword()); Record.AddNestedNameSpecifier(T->getQualifier()); Record.AddIdentifierRef(T->getIdentifier()); Record.AddTypeRef( T->isCanonicalUnqualified() ? QualType() : T->getCanonicalTypeInternal()); Code = TYPE_DEPENDENT_NAME; } void ASTTypeWriter::VisitDependentTemplateSpecializationType( const DependentTemplateSpecializationType *T) { Record.push_back(T->getKeyword()); Record.AddNestedNameSpecifier(T->getQualifier()); Record.AddIdentifierRef(T->getIdentifier()); Record.push_back(T->getNumArgs()); for (const auto &I : *T) Record.AddTemplateArgument(I); Code = TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION; } void ASTTypeWriter::VisitPackExpansionType(const PackExpansionType *T) { Record.AddTypeRef(T->getPattern()); if (Optional NumExpansions = T->getNumExpansions()) Record.push_back(*NumExpansions + 1); else Record.push_back(0); Code = TYPE_PACK_EXPANSION; } void ASTTypeWriter::VisitParenType(const ParenType *T) { Record.AddTypeRef(T->getInnerType()); Code = TYPE_PAREN; } void ASTTypeWriter::VisitElaboratedType(const ElaboratedType *T) { Record.push_back(T->getKeyword()); Record.AddNestedNameSpecifier(T->getQualifier()); Record.AddTypeRef(T->getNamedType()); Record.AddDeclRef(T->getOwnedTagDecl()); Code = TYPE_ELABORATED; } void ASTTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) { Record.AddDeclRef(T->getDecl()->getCanonicalDecl()); Record.AddTypeRef(T->getInjectedSpecializationType()); Code = TYPE_INJECTED_CLASS_NAME; } void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { Record.AddDeclRef(T->getDecl()->getCanonicalDecl()); Code = TYPE_OBJC_INTERFACE; } void ASTTypeWriter::VisitObjCTypeParamType(const ObjCTypeParamType *T) { Record.AddDeclRef(T->getDecl()); Record.push_back(T->getNumProtocols()); for (const auto *I : T->quals()) Record.AddDeclRef(I); Code = TYPE_OBJC_TYPE_PARAM; } void ASTTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) { Record.AddTypeRef(T->getBaseType()); Record.push_back(T->getTypeArgsAsWritten().size()); for (auto TypeArg : T->getTypeArgsAsWritten()) Record.AddTypeRef(TypeArg); Record.push_back(T->getNumProtocols()); for (const auto *I : T->quals()) Record.AddDeclRef(I); Record.push_back(T->isKindOfTypeAsWritten()); Code = TYPE_OBJC_OBJECT; } void ASTTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { Record.AddTypeRef(T->getPointeeType()); Code = TYPE_OBJC_OBJECT_POINTER; } void ASTTypeWriter::VisitAtomicType(const AtomicType *T) { Record.AddTypeRef(T->getValueType()); Code = TYPE_ATOMIC; } void ASTTypeWriter::VisitPipeType(const PipeType *T) { Record.AddTypeRef(T->getElementType()); Record.push_back(T->isReadOnly()); Code = TYPE_PIPE; } namespace { class TypeLocWriter : public TypeLocVisitor { ASTRecordWriter &Record; public: TypeLocWriter(ASTRecordWriter &Record) : Record(Record) {} #define ABSTRACT_TYPELOC(CLASS, PARENT) #define TYPELOC(CLASS, PARENT) \ void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc); #include "clang/AST/TypeLocNodes.def" void VisitArrayTypeLoc(ArrayTypeLoc TyLoc); void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc); }; } // namespace void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { // nothing to do } void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { Record.AddSourceLocation(TL.getBuiltinLoc()); if (TL.needsExtraLocalData()) { Record.push_back(TL.getWrittenTypeSpec()); Record.push_back(TL.getWrittenSignSpec()); Record.push_back(TL.getWrittenWidthSpec()); Record.push_back(TL.hasModeAttr()); } } void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) { Record.AddSourceLocation(TL.getStarLoc()); } void TypeLocWriter::VisitDecayedTypeLoc(DecayedTypeLoc TL) { // nothing to do } void TypeLocWriter::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { // nothing to do } void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { Record.AddSourceLocation(TL.getCaretLoc()); } void TypeLocWriter::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { Record.AddSourceLocation(TL.getAmpLoc()); } void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { Record.AddSourceLocation(TL.getAmpAmpLoc()); } void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { Record.AddSourceLocation(TL.getStarLoc()); Record.AddTypeSourceInfo(TL.getClassTInfo()); } void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) { Record.AddSourceLocation(TL.getLBracketLoc()); Record.AddSourceLocation(TL.getRBracketLoc()); Record.push_back(TL.getSizeExpr() ? 1 : 0); if (TL.getSizeExpr()) Record.AddStmt(TL.getSizeExpr()); } void TypeLocWriter::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) { VisitArrayTypeLoc(TL); } void TypeLocWriter::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) { VisitArrayTypeLoc(TL); } void TypeLocWriter::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) { VisitArrayTypeLoc(TL); } void TypeLocWriter::VisitDependentSizedArrayTypeLoc( DependentSizedArrayTypeLoc TL) { VisitArrayTypeLoc(TL); } void TypeLocWriter::VisitDependentAddressSpaceTypeLoc( DependentAddressSpaceTypeLoc TL) { Record.AddSourceLocation(TL.getAttrNameLoc()); SourceRange range = TL.getAttrOperandParensRange(); Record.AddSourceLocation(range.getBegin()); Record.AddSourceLocation(range.getEnd()); Record.AddStmt(TL.getAttrExprOperand()); } void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc( DependentSizedExtVectorTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitDependentVectorTypeLoc( DependentVectorTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) { Record.AddSourceLocation(TL.getLocalRangeBegin()); Record.AddSourceLocation(TL.getLParenLoc()); Record.AddSourceLocation(TL.getRParenLoc()); Record.AddSourceRange(TL.getExceptionSpecRange()); Record.AddSourceLocation(TL.getLocalRangeEnd()); for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i) Record.AddDeclRef(TL.getParam(i)); } void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) { VisitFunctionTypeLoc(TL); } void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) { VisitFunctionTypeLoc(TL); } void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) { if (TL.getNumProtocols()) { Record.AddSourceLocation(TL.getProtocolLAngleLoc()); Record.AddSourceLocation(TL.getProtocolRAngleLoc()); } for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) Record.AddSourceLocation(TL.getProtocolLoc(i)); } void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { Record.AddSourceLocation(TL.getTypeofLoc()); Record.AddSourceLocation(TL.getLParenLoc()); Record.AddSourceLocation(TL.getRParenLoc()); } void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { Record.AddSourceLocation(TL.getTypeofLoc()); Record.AddSourceLocation(TL.getLParenLoc()); Record.AddSourceLocation(TL.getRParenLoc()); Record.AddTypeSourceInfo(TL.getUnderlyingTInfo()); } void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) { Record.AddSourceLocation(TL.getKWLoc()); Record.AddSourceLocation(TL.getLParenLoc()); Record.AddSourceLocation(TL.getRParenLoc()); Record.AddTypeSourceInfo(TL.getUnderlyingTInfo()); } void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitDeducedTemplateSpecializationTypeLoc( DeducedTemplateSpecializationTypeLoc TL) { Record.AddSourceLocation(TL.getTemplateNameLoc()); } void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) { Record.AddSourceLocation(TL.getAttrNameLoc()); if (TL.hasAttrOperand()) { SourceRange range = TL.getAttrOperandParensRange(); Record.AddSourceLocation(range.getBegin()); Record.AddSourceLocation(range.getEnd()); } if (TL.hasAttrExprOperand()) { Expr *operand = TL.getAttrExprOperand(); Record.push_back(operand ? 1 : 0); if (operand) Record.AddStmt(operand); } else if (TL.hasAttrEnumOperand()) { Record.AddSourceLocation(TL.getAttrEnumOperandLoc()); } } void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc( SubstTemplateTypeParmTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitSubstTemplateTypeParmPackTypeLoc( SubstTemplateTypeParmPackTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitTemplateSpecializationTypeLoc( TemplateSpecializationTypeLoc TL) { Record.AddSourceLocation(TL.getTemplateKeywordLoc()); Record.AddSourceLocation(TL.getTemplateNameLoc()); Record.AddSourceLocation(TL.getLAngleLoc()); Record.AddSourceLocation(TL.getRAngleLoc()); for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) Record.AddTemplateArgumentLocInfo(TL.getArgLoc(i).getArgument().getKind(), TL.getArgLoc(i).getLocInfo()); } void TypeLocWriter::VisitParenTypeLoc(ParenTypeLoc TL) { Record.AddSourceLocation(TL.getLParenLoc()); Record.AddSourceLocation(TL.getRParenLoc()); } void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { Record.AddSourceLocation(TL.getElaboratedKeywordLoc()); Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); } void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { Record.AddSourceLocation(TL.getElaboratedKeywordLoc()); Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc( DependentTemplateSpecializationTypeLoc TL) { Record.AddSourceLocation(TL.getElaboratedKeywordLoc()); Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); Record.AddSourceLocation(TL.getTemplateKeywordLoc()); Record.AddSourceLocation(TL.getTemplateNameLoc()); Record.AddSourceLocation(TL.getLAngleLoc()); Record.AddSourceLocation(TL.getRAngleLoc()); for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) Record.AddTemplateArgumentLocInfo(TL.getArgLoc(I).getArgument().getKind(), TL.getArgLoc(I).getLocInfo()); } void TypeLocWriter::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) { Record.AddSourceLocation(TL.getEllipsisLoc()); } void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { Record.push_back(TL.hasBaseTypeAsWritten()); Record.AddSourceLocation(TL.getTypeArgsLAngleLoc()); Record.AddSourceLocation(TL.getTypeArgsRAngleLoc()); for (unsigned i = 0, e = TL.getNumTypeArgs(); i != e; ++i) Record.AddTypeSourceInfo(TL.getTypeArgTInfo(i)); Record.AddSourceLocation(TL.getProtocolLAngleLoc()); Record.AddSourceLocation(TL.getProtocolRAngleLoc()); for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) Record.AddSourceLocation(TL.getProtocolLoc(i)); } void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { Record.AddSourceLocation(TL.getStarLoc()); } void TypeLocWriter::VisitAtomicTypeLoc(AtomicTypeLoc TL) { Record.AddSourceLocation(TL.getKWLoc()); Record.AddSourceLocation(TL.getLParenLoc()); Record.AddSourceLocation(TL.getRParenLoc()); } void TypeLocWriter::VisitPipeTypeLoc(PipeTypeLoc TL) { Record.AddSourceLocation(TL.getKWLoc()); } void ASTWriter::WriteTypeAbbrevs() { using namespace llvm; std::shared_ptr Abv; // Abbreviation for TYPE_EXT_QUAL Abv = std::make_shared(); Abv->Add(BitCodeAbbrevOp(serialization::TYPE_EXT_QUAL)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 3)); // Quals TypeExtQualAbbrev = Stream.EmitAbbrev(std::move(Abv)); // Abbreviation for TYPE_FUNCTION_PROTO Abv = std::make_shared(); Abv->Add(BitCodeAbbrevOp(serialization::TYPE_FUNCTION_PROTO)); // FunctionType Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ReturnType Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // NoReturn Abv->Add(BitCodeAbbrevOp(0)); // HasRegParm Abv->Add(BitCodeAbbrevOp(0)); // RegParm Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // CC Abv->Add(BitCodeAbbrevOp(0)); // ProducesResult Abv->Add(BitCodeAbbrevOp(0)); // NoCallerSavedRegs Abv->Add(BitCodeAbbrevOp(0)); // NoCfCheck // FunctionProtoType Abv->Add(BitCodeAbbrevOp(0)); // IsVariadic Abv->Add(BitCodeAbbrevOp(0)); // HasTrailingReturn Abv->Add(BitCodeAbbrevOp(0)); // TypeQuals Abv->Add(BitCodeAbbrevOp(0)); // RefQualifier Abv->Add(BitCodeAbbrevOp(EST_None)); // ExceptionSpec Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // NumParams Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Params TypeFunctionProtoAbbrev = Stream.EmitAbbrev(std::move(Abv)); } //===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// static void EmitBlockID(unsigned ID, const char *Name, llvm::BitstreamWriter &Stream, ASTWriter::RecordDataImpl &Record) { Record.clear(); Record.push_back(ID); Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); // Emit the block name if present. if (!Name || Name[0] == 0) return; Record.clear(); while (*Name) Record.push_back(*Name++); Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); } static void EmitRecordID(unsigned ID, const char *Name, llvm::BitstreamWriter &Stream, ASTWriter::RecordDataImpl &Record) { Record.clear(); Record.push_back(ID); while (*Name) Record.push_back(*Name++); Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); } static void AddStmtsExprs(llvm::BitstreamWriter &Stream, ASTWriter::RecordDataImpl &Record) { #define RECORD(X) EmitRecordID(X, #X, Stream, Record) RECORD(STMT_STOP); RECORD(STMT_NULL_PTR); RECORD(STMT_REF_PTR); RECORD(STMT_NULL); RECORD(STMT_COMPOUND); RECORD(STMT_CASE); RECORD(STMT_DEFAULT); RECORD(STMT_LABEL); RECORD(STMT_ATTRIBUTED); RECORD(STMT_IF); RECORD(STMT_SWITCH); RECORD(STMT_WHILE); RECORD(STMT_DO); RECORD(STMT_FOR); RECORD(STMT_GOTO); RECORD(STMT_INDIRECT_GOTO); RECORD(STMT_CONTINUE); RECORD(STMT_BREAK); RECORD(STMT_RETURN); RECORD(STMT_DECL); RECORD(STMT_GCCASM); RECORD(STMT_MSASM); RECORD(EXPR_PREDEFINED); RECORD(EXPR_DECL_REF); RECORD(EXPR_INTEGER_LITERAL); RECORD(EXPR_FLOATING_LITERAL); RECORD(EXPR_IMAGINARY_LITERAL); RECORD(EXPR_STRING_LITERAL); RECORD(EXPR_CHARACTER_LITERAL); RECORD(EXPR_PAREN); RECORD(EXPR_PAREN_LIST); RECORD(EXPR_UNARY_OPERATOR); RECORD(EXPR_SIZEOF_ALIGN_OF); RECORD(EXPR_ARRAY_SUBSCRIPT); RECORD(EXPR_CALL); RECORD(EXPR_MEMBER); RECORD(EXPR_BINARY_OPERATOR); RECORD(EXPR_COMPOUND_ASSIGN_OPERATOR); RECORD(EXPR_CONDITIONAL_OPERATOR); RECORD(EXPR_IMPLICIT_CAST); RECORD(EXPR_CSTYLE_CAST); RECORD(EXPR_COMPOUND_LITERAL); RECORD(EXPR_EXT_VECTOR_ELEMENT); RECORD(EXPR_INIT_LIST); RECORD(EXPR_DESIGNATED_INIT); RECORD(EXPR_DESIGNATED_INIT_UPDATE); RECORD(EXPR_IMPLICIT_VALUE_INIT); RECORD(EXPR_NO_INIT); RECORD(EXPR_VA_ARG); RECORD(EXPR_ADDR_LABEL); RECORD(EXPR_STMT); RECORD(EXPR_CHOOSE); RECORD(EXPR_GNU_NULL); RECORD(EXPR_SHUFFLE_VECTOR); RECORD(EXPR_BLOCK); RECORD(EXPR_GENERIC_SELECTION); RECORD(EXPR_OBJC_STRING_LITERAL); RECORD(EXPR_OBJC_BOXED_EXPRESSION); RECORD(EXPR_OBJC_ARRAY_LITERAL); RECORD(EXPR_OBJC_DICTIONARY_LITERAL); RECORD(EXPR_OBJC_ENCODE); RECORD(EXPR_OBJC_SELECTOR_EXPR); RECORD(EXPR_OBJC_PROTOCOL_EXPR); RECORD(EXPR_OBJC_IVAR_REF_EXPR); RECORD(EXPR_OBJC_PROPERTY_REF_EXPR); RECORD(EXPR_OBJC_KVC_REF_EXPR); RECORD(EXPR_OBJC_MESSAGE_EXPR); RECORD(STMT_OBJC_FOR_COLLECTION); RECORD(STMT_OBJC_CATCH); RECORD(STMT_OBJC_FINALLY); RECORD(STMT_OBJC_AT_TRY); RECORD(STMT_OBJC_AT_SYNCHRONIZED); RECORD(STMT_OBJC_AT_THROW); RECORD(EXPR_OBJC_BOOL_LITERAL); RECORD(STMT_CXX_CATCH); RECORD(STMT_CXX_TRY); RECORD(STMT_CXX_FOR_RANGE); RECORD(EXPR_CXX_OPERATOR_CALL); RECORD(EXPR_CXX_MEMBER_CALL); RECORD(EXPR_CXX_CONSTRUCT); RECORD(EXPR_CXX_TEMPORARY_OBJECT); RECORD(EXPR_CXX_STATIC_CAST); RECORD(EXPR_CXX_DYNAMIC_CAST); RECORD(EXPR_CXX_REINTERPRET_CAST); RECORD(EXPR_CXX_CONST_CAST); RECORD(EXPR_CXX_FUNCTIONAL_CAST); RECORD(EXPR_USER_DEFINED_LITERAL); RECORD(EXPR_CXX_STD_INITIALIZER_LIST); RECORD(EXPR_CXX_BOOL_LITERAL); RECORD(EXPR_CXX_NULL_PTR_LITERAL); RECORD(EXPR_CXX_TYPEID_EXPR); RECORD(EXPR_CXX_TYPEID_TYPE); RECORD(EXPR_CXX_THIS); RECORD(EXPR_CXX_THROW); RECORD(EXPR_CXX_DEFAULT_ARG); RECORD(EXPR_CXX_DEFAULT_INIT); RECORD(EXPR_CXX_BIND_TEMPORARY); RECORD(EXPR_CXX_SCALAR_VALUE_INIT); RECORD(EXPR_CXX_NEW); RECORD(EXPR_CXX_DELETE); RECORD(EXPR_CXX_PSEUDO_DESTRUCTOR); RECORD(EXPR_EXPR_WITH_CLEANUPS); RECORD(EXPR_CXX_DEPENDENT_SCOPE_MEMBER); RECORD(EXPR_CXX_DEPENDENT_SCOPE_DECL_REF); RECORD(EXPR_CXX_UNRESOLVED_CONSTRUCT); RECORD(EXPR_CXX_UNRESOLVED_MEMBER); RECORD(EXPR_CXX_UNRESOLVED_LOOKUP); RECORD(EXPR_CXX_EXPRESSION_TRAIT); RECORD(EXPR_CXX_NOEXCEPT); RECORD(EXPR_OPAQUE_VALUE); RECORD(EXPR_BINARY_CONDITIONAL_OPERATOR); RECORD(EXPR_TYPE_TRAIT); RECORD(EXPR_ARRAY_TYPE_TRAIT); RECORD(EXPR_PACK_EXPANSION); RECORD(EXPR_SIZEOF_PACK); RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM); RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK); RECORD(EXPR_FUNCTION_PARM_PACK); RECORD(EXPR_MATERIALIZE_TEMPORARY); RECORD(EXPR_CUDA_KERNEL_CALL); RECORD(EXPR_CXX_UUIDOF_EXPR); RECORD(EXPR_CXX_UUIDOF_TYPE); RECORD(EXPR_LAMBDA); #undef RECORD } void ASTWriter::WriteBlockInfoBlock() { RecordData Record; Stream.EnterBlockInfoBlock(); #define BLOCK(X) EmitBlockID(X ## _ID, #X, Stream, Record) #define RECORD(X) EmitRecordID(X, #X, Stream, Record) // Control Block. BLOCK(CONTROL_BLOCK); RECORD(METADATA); RECORD(MODULE_NAME); RECORD(MODULE_DIRECTORY); RECORD(MODULE_MAP_FILE); RECORD(IMPORTS); RECORD(ORIGINAL_FILE); RECORD(ORIGINAL_PCH_DIR); RECORD(ORIGINAL_FILE_ID); RECORD(INPUT_FILE_OFFSETS); BLOCK(OPTIONS_BLOCK); RECORD(LANGUAGE_OPTIONS); RECORD(TARGET_OPTIONS); RECORD(FILE_SYSTEM_OPTIONS); RECORD(HEADER_SEARCH_OPTIONS); RECORD(PREPROCESSOR_OPTIONS); BLOCK(INPUT_FILES_BLOCK); RECORD(INPUT_FILE); // AST Top-Level Block. BLOCK(AST_BLOCK); RECORD(TYPE_OFFSET); RECORD(DECL_OFFSET); RECORD(IDENTIFIER_OFFSET); RECORD(IDENTIFIER_TABLE); RECORD(EAGERLY_DESERIALIZED_DECLS); RECORD(MODULAR_CODEGEN_DECLS); RECORD(SPECIAL_TYPES); RECORD(STATISTICS); RECORD(TENTATIVE_DEFINITIONS); RECORD(SELECTOR_OFFSETS); RECORD(METHOD_POOL); RECORD(PP_COUNTER_VALUE); RECORD(SOURCE_LOCATION_OFFSETS); RECORD(SOURCE_LOCATION_PRELOADS); RECORD(EXT_VECTOR_DECLS); RECORD(UNUSED_FILESCOPED_DECLS); RECORD(PPD_ENTITIES_OFFSETS); RECORD(VTABLE_USES); RECORD(PPD_SKIPPED_RANGES); RECORD(REFERENCED_SELECTOR_POOL); RECORD(TU_UPDATE_LEXICAL); RECORD(SEMA_DECL_REFS); RECORD(WEAK_UNDECLARED_IDENTIFIERS); RECORD(PENDING_IMPLICIT_INSTANTIATIONS); RECORD(UPDATE_VISIBLE); RECORD(DECL_UPDATE_OFFSETS); RECORD(DECL_UPDATES); RECORD(CUDA_SPECIAL_DECL_REFS); RECORD(HEADER_SEARCH_TABLE); RECORD(FP_PRAGMA_OPTIONS); RECORD(OPENCL_EXTENSIONS); RECORD(OPENCL_EXTENSION_TYPES); RECORD(OPENCL_EXTENSION_DECLS); RECORD(DELEGATING_CTORS); RECORD(KNOWN_NAMESPACES); RECORD(MODULE_OFFSET_MAP); RECORD(SOURCE_MANAGER_LINE_TABLE); RECORD(OBJC_CATEGORIES_MAP); RECORD(FILE_SORTED_DECLS); RECORD(IMPORTED_MODULES); RECORD(OBJC_CATEGORIES); RECORD(MACRO_OFFSET); RECORD(INTERESTING_IDENTIFIERS); RECORD(UNDEFINED_BUT_USED); RECORD(LATE_PARSED_TEMPLATE); RECORD(OPTIMIZE_PRAGMA_OPTIONS); RECORD(MSSTRUCT_PRAGMA_OPTIONS); RECORD(POINTERS_TO_MEMBERS_PRAGMA_OPTIONS); RECORD(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES); RECORD(DELETE_EXPRS_TO_ANALYZE); RECORD(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH); RECORD(PP_CONDITIONAL_STACK); // SourceManager Block. BLOCK(SOURCE_MANAGER_BLOCK); RECORD(SM_SLOC_FILE_ENTRY); RECORD(SM_SLOC_BUFFER_ENTRY); RECORD(SM_SLOC_BUFFER_BLOB); RECORD(SM_SLOC_BUFFER_BLOB_COMPRESSED); RECORD(SM_SLOC_EXPANSION_ENTRY); // Preprocessor Block. BLOCK(PREPROCESSOR_BLOCK); RECORD(PP_MACRO_DIRECTIVE_HISTORY); RECORD(PP_MACRO_FUNCTION_LIKE); RECORD(PP_MACRO_OBJECT_LIKE); RECORD(PP_MODULE_MACRO); RECORD(PP_TOKEN); // Submodule Block. BLOCK(SUBMODULE_BLOCK); RECORD(SUBMODULE_METADATA); RECORD(SUBMODULE_DEFINITION); RECORD(SUBMODULE_UMBRELLA_HEADER); RECORD(SUBMODULE_HEADER); RECORD(SUBMODULE_TOPHEADER); RECORD(SUBMODULE_UMBRELLA_DIR); RECORD(SUBMODULE_IMPORTS); RECORD(SUBMODULE_EXPORTS); RECORD(SUBMODULE_REQUIRES); RECORD(SUBMODULE_EXCLUDED_HEADER); RECORD(SUBMODULE_LINK_LIBRARY); RECORD(SUBMODULE_CONFIG_MACRO); RECORD(SUBMODULE_CONFLICT); RECORD(SUBMODULE_PRIVATE_HEADER); RECORD(SUBMODULE_TEXTUAL_HEADER); RECORD(SUBMODULE_PRIVATE_TEXTUAL_HEADER); RECORD(SUBMODULE_INITIALIZERS); RECORD(SUBMODULE_EXPORT_AS); // Comments Block. BLOCK(COMMENTS_BLOCK); RECORD(COMMENTS_RAW_COMMENT); // Decls and Types block. BLOCK(DECLTYPES_BLOCK); RECORD(TYPE_EXT_QUAL); RECORD(TYPE_COMPLEX); RECORD(TYPE_POINTER); RECORD(TYPE_BLOCK_POINTER); RECORD(TYPE_LVALUE_REFERENCE); RECORD(TYPE_RVALUE_REFERENCE); RECORD(TYPE_MEMBER_POINTER); RECORD(TYPE_CONSTANT_ARRAY); RECORD(TYPE_INCOMPLETE_ARRAY); RECORD(TYPE_VARIABLE_ARRAY); RECORD(TYPE_VECTOR); RECORD(TYPE_EXT_VECTOR); RECORD(TYPE_FUNCTION_NO_PROTO); RECORD(TYPE_FUNCTION_PROTO); RECORD(TYPE_TYPEDEF); RECORD(TYPE_TYPEOF_EXPR); RECORD(TYPE_TYPEOF); RECORD(TYPE_RECORD); RECORD(TYPE_ENUM); RECORD(TYPE_OBJC_INTERFACE); RECORD(TYPE_OBJC_OBJECT_POINTER); RECORD(TYPE_DECLTYPE); RECORD(TYPE_ELABORATED); RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM); RECORD(TYPE_UNRESOLVED_USING); RECORD(TYPE_INJECTED_CLASS_NAME); RECORD(TYPE_OBJC_OBJECT); RECORD(TYPE_TEMPLATE_TYPE_PARM); RECORD(TYPE_TEMPLATE_SPECIALIZATION); RECORD(TYPE_DEPENDENT_NAME); RECORD(TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION); RECORD(TYPE_DEPENDENT_SIZED_ARRAY); RECORD(TYPE_PAREN); RECORD(TYPE_PACK_EXPANSION); RECORD(TYPE_ATTRIBUTED); RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK); RECORD(TYPE_AUTO); RECORD(TYPE_UNARY_TRANSFORM); RECORD(TYPE_ATOMIC); RECORD(TYPE_DECAYED); RECORD(TYPE_ADJUSTED); RECORD(TYPE_OBJC_TYPE_PARAM); RECORD(LOCAL_REDECLARATIONS); RECORD(DECL_TYPEDEF); RECORD(DECL_TYPEALIAS); RECORD(DECL_ENUM); RECORD(DECL_RECORD); RECORD(DECL_ENUM_CONSTANT); RECORD(DECL_FUNCTION); RECORD(DECL_OBJC_METHOD); RECORD(DECL_OBJC_INTERFACE); RECORD(DECL_OBJC_PROTOCOL); RECORD(DECL_OBJC_IVAR); RECORD(DECL_OBJC_AT_DEFS_FIELD); RECORD(DECL_OBJC_CATEGORY); RECORD(DECL_OBJC_CATEGORY_IMPL); RECORD(DECL_OBJC_IMPLEMENTATION); RECORD(DECL_OBJC_COMPATIBLE_ALIAS); RECORD(DECL_OBJC_PROPERTY); RECORD(DECL_OBJC_PROPERTY_IMPL); RECORD(DECL_FIELD); RECORD(DECL_MS_PROPERTY); RECORD(DECL_VAR); RECORD(DECL_IMPLICIT_PARAM); RECORD(DECL_PARM_VAR); RECORD(DECL_FILE_SCOPE_ASM); RECORD(DECL_BLOCK); RECORD(DECL_CONTEXT_LEXICAL); RECORD(DECL_CONTEXT_VISIBLE); RECORD(DECL_NAMESPACE); RECORD(DECL_NAMESPACE_ALIAS); RECORD(DECL_USING); RECORD(DECL_USING_SHADOW); RECORD(DECL_USING_DIRECTIVE); RECORD(DECL_UNRESOLVED_USING_VALUE); RECORD(DECL_UNRESOLVED_USING_TYPENAME); RECORD(DECL_LINKAGE_SPEC); RECORD(DECL_CXX_RECORD); RECORD(DECL_CXX_METHOD); RECORD(DECL_CXX_CONSTRUCTOR); RECORD(DECL_CXX_INHERITED_CONSTRUCTOR); RECORD(DECL_CXX_DESTRUCTOR); RECORD(DECL_CXX_CONVERSION); RECORD(DECL_ACCESS_SPEC); RECORD(DECL_FRIEND); RECORD(DECL_FRIEND_TEMPLATE); RECORD(DECL_CLASS_TEMPLATE); RECORD(DECL_CLASS_TEMPLATE_SPECIALIZATION); RECORD(DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION); RECORD(DECL_VAR_TEMPLATE); RECORD(DECL_VAR_TEMPLATE_SPECIALIZATION); RECORD(DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION); RECORD(DECL_FUNCTION_TEMPLATE); RECORD(DECL_TEMPLATE_TYPE_PARM); RECORD(DECL_NON_TYPE_TEMPLATE_PARM); RECORD(DECL_TEMPLATE_TEMPLATE_PARM); RECORD(DECL_TYPE_ALIAS_TEMPLATE); RECORD(DECL_STATIC_ASSERT); RECORD(DECL_CXX_BASE_SPECIFIERS); RECORD(DECL_CXX_CTOR_INITIALIZERS); RECORD(DECL_INDIRECTFIELD); RECORD(DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK); RECORD(DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK); RECORD(DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION); RECORD(DECL_IMPORT); RECORD(DECL_OMP_THREADPRIVATE); RECORD(DECL_EMPTY); RECORD(DECL_OBJC_TYPE_PARAM); RECORD(DECL_OMP_CAPTUREDEXPR); RECORD(DECL_PRAGMA_COMMENT); RECORD(DECL_PRAGMA_DETECT_MISMATCH); RECORD(DECL_OMP_DECLARE_REDUCTION); // Statements and Exprs can occur in the Decls and Types block. AddStmtsExprs(Stream, Record); BLOCK(PREPROCESSOR_DETAIL_BLOCK); RECORD(PPD_MACRO_EXPANSION); RECORD(PPD_MACRO_DEFINITION); RECORD(PPD_INCLUSION_DIRECTIVE); // Decls and Types block. BLOCK(EXTENSION_BLOCK); RECORD(EXTENSION_METADATA); BLOCK(UNHASHED_CONTROL_BLOCK); RECORD(SIGNATURE); RECORD(DIAGNOSTIC_OPTIONS); RECORD(DIAG_PRAGMA_MAPPINGS); #undef RECORD #undef BLOCK Stream.ExitBlock(); } /// Prepares a path for being written to an AST file by converting it /// to an absolute path and removing nested './'s. /// /// \return \c true if the path was changed. static bool cleanPathForOutput(FileManager &FileMgr, SmallVectorImpl &Path) { bool Changed = FileMgr.makeAbsolutePath(Path); return Changed | llvm::sys::path::remove_dots(Path); } /// Adjusts the given filename to only write out the portion of the /// filename that is not part of the system root directory. /// /// \param Filename the file name to adjust. /// /// \param BaseDir When non-NULL, the PCH file is a relocatable AST file and /// the returned filename will be adjusted by this root directory. /// /// \returns either the original filename (if it needs no adjustment) or the /// adjusted filename (which points into the @p Filename parameter). static const char * adjustFilenameForRelocatableAST(const char *Filename, StringRef BaseDir) { assert(Filename && "No file name to adjust?"); if (BaseDir.empty()) return Filename; // Verify that the filename and the system root have the same prefix. unsigned Pos = 0; for (; Filename[Pos] && Pos < BaseDir.size(); ++Pos) if (Filename[Pos] != BaseDir[Pos]) return Filename; // Prefixes don't match. // We hit the end of the filename before we hit the end of the system root. if (!Filename[Pos]) return Filename; // If there's not a path separator at the end of the base directory nor // immediately after it, then this isn't within the base directory. if (!llvm::sys::path::is_separator(Filename[Pos])) { if (!llvm::sys::path::is_separator(BaseDir.back())) return Filename; } else { // If the file name has a '/' at the current position, skip over the '/'. // We distinguish relative paths from absolute paths by the // absence of '/' at the beginning of relative paths. // // FIXME: This is wrong. We distinguish them by asking if the path is // absolute, which isn't the same thing. And there might be multiple '/'s // in a row. Use a better mechanism to indicate whether we have emitted an // absolute or relative path. ++Pos; } return Filename + Pos; } ASTFileSignature ASTWriter::createSignature(StringRef Bytes) { // Calculate the hash till start of UNHASHED_CONTROL_BLOCK. llvm::SHA1 Hasher; Hasher.update(ArrayRef(Bytes.bytes_begin(), Bytes.size())); auto Hash = Hasher.result(); // Convert to an array [5*i32]. ASTFileSignature Signature; auto LShift = [&](unsigned char Val, unsigned Shift) { return (uint32_t)Val << Shift; }; for (int I = 0; I != 5; ++I) Signature[I] = LShift(Hash[I * 4 + 0], 24) | LShift(Hash[I * 4 + 1], 16) | LShift(Hash[I * 4 + 2], 8) | LShift(Hash[I * 4 + 3], 0); return Signature; } ASTFileSignature ASTWriter::writeUnhashedControlBlock(Preprocessor &PP, ASTContext &Context) { // Flush first to prepare the PCM hash (signature). Stream.FlushToWord(); auto StartOfUnhashedControl = Stream.GetCurrentBitNo() >> 3; // Enter the block and prepare to write records. RecordData Record; Stream.EnterSubblock(UNHASHED_CONTROL_BLOCK_ID, 5); // For implicit modules, write the hash of the PCM as its signature. ASTFileSignature Signature; if (WritingModule && PP.getHeaderSearchInfo().getHeaderSearchOpts().ModulesHashContent) { Signature = createSignature(StringRef(Buffer.begin(), StartOfUnhashedControl)); Record.append(Signature.begin(), Signature.end()); Stream.EmitRecord(SIGNATURE, Record); Record.clear(); } // Diagnostic options. const auto &Diags = Context.getDiagnostics(); const DiagnosticOptions &DiagOpts = Diags.getDiagnosticOptions(); #define DIAGOPT(Name, Bits, Default) Record.push_back(DiagOpts.Name); #define ENUM_DIAGOPT(Name, Type, Bits, Default) \ Record.push_back(static_cast(DiagOpts.get##Name())); #include "clang/Basic/DiagnosticOptions.def" Record.push_back(DiagOpts.Warnings.size()); for (unsigned I = 0, N = DiagOpts.Warnings.size(); I != N; ++I) AddString(DiagOpts.Warnings[I], Record); Record.push_back(DiagOpts.Remarks.size()); for (unsigned I = 0, N = DiagOpts.Remarks.size(); I != N; ++I) AddString(DiagOpts.Remarks[I], Record); // Note: we don't serialize the log or serialization file names, because they // are generally transient files and will almost always be overridden. Stream.EmitRecord(DIAGNOSTIC_OPTIONS, Record); // Write out the diagnostic/pragma mappings. WritePragmaDiagnosticMappings(Diags, /* IsModule = */ WritingModule); // Leave the options block. Stream.ExitBlock(); return Signature; } /// Write the control block. void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, StringRef isysroot, const std::string &OutputFile) { using namespace llvm; Stream.EnterSubblock(CONTROL_BLOCK_ID, 5); RecordData Record; // Metadata auto MetadataAbbrev = std::make_shared(); MetadataAbbrev->Add(BitCodeAbbrevOp(METADATA)); MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Major MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Minor MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang maj. MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang min. MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Timestamps MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // PCHHasObjectFile MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Errors MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag unsigned MetadataAbbrevCode = Stream.EmitAbbrev(std::move(MetadataAbbrev)); assert((!WritingModule || isysroot.empty()) && "writing module as a relocatable PCH?"); { RecordData::value_type Record[] = { METADATA, VERSION_MAJOR, VERSION_MINOR, CLANG_VERSION_MAJOR, CLANG_VERSION_MINOR, !isysroot.empty(), IncludeTimestamps, Context.getLangOpts().BuildingPCHWithObjectFile, ASTHasCompilerErrors}; Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record, getClangFullRepositoryVersion()); } if (WritingModule) { // Module name auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev)); RecordData::value_type Record[] = {MODULE_NAME}; Stream.EmitRecordWithBlob(AbbrevCode, Record, WritingModule->Name); } if (WritingModule && WritingModule->Directory) { SmallString<128> BaseDir(WritingModule->Directory->getName()); cleanPathForOutput(Context.getSourceManager().getFileManager(), BaseDir); // If the home of the module is the current working directory, then we // want to pick up the cwd of the build process loading the module, not // our cwd, when we load this module. if (!PP.getHeaderSearchInfo() .getHeaderSearchOpts() .ModuleMapFileHomeIsCwd || WritingModule->Directory->getName() != StringRef(".")) { // Module directory. auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(MODULE_DIRECTORY)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Directory unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev)); RecordData::value_type Record[] = {MODULE_DIRECTORY}; Stream.EmitRecordWithBlob(AbbrevCode, Record, BaseDir); } // Write out all other paths relative to the base directory if possible. BaseDirectory.assign(BaseDir.begin(), BaseDir.end()); } else if (!isysroot.empty()) { // Write out paths relative to the sysroot if possible. BaseDirectory = isysroot; } // Module map file if (WritingModule && WritingModule->Kind == Module::ModuleMapModule) { Record.clear(); auto &Map = PP.getHeaderSearchInfo().getModuleMap(); AddPath(WritingModule->PresumedModuleMapFile.empty() ? Map.getModuleMapFileForUniquing(WritingModule)->getName() : StringRef(WritingModule->PresumedModuleMapFile), Record); // Additional module map files. if (auto *AdditionalModMaps = Map.getAdditionalModuleMapFiles(WritingModule)) { Record.push_back(AdditionalModMaps->size()); for (const FileEntry *F : *AdditionalModMaps) AddPath(F->getName(), Record); } else { Record.push_back(0); } Stream.EmitRecord(MODULE_MAP_FILE, Record); } // Imports if (Chain) { serialization::ModuleManager &Mgr = Chain->getModuleManager(); Record.clear(); for (ModuleFile &M : Mgr) { // Skip modules that weren't directly imported. if (!M.isDirectlyImported()) continue; Record.push_back((unsigned)M.Kind); // FIXME: Stable encoding AddSourceLocation(M.ImportLoc, Record); // If we have calculated signature, there is no need to store // the size or timestamp. Record.push_back(M.Signature ? 0 : M.File->getSize()); Record.push_back(M.Signature ? 0 : getTimestampForOutput(M.File)); for (auto I : M.Signature) Record.push_back(I); AddString(M.ModuleName, Record); AddPath(M.FileName, Record); } Stream.EmitRecord(IMPORTS, Record); } // Write the options block. Stream.EnterSubblock(OPTIONS_BLOCK_ID, 4); // Language options. Record.clear(); const LangOptions &LangOpts = Context.getLangOpts(); #define LANGOPT(Name, Bits, Default, Description) \ Record.push_back(LangOpts.Name); #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ Record.push_back(static_cast(LangOpts.get##Name())); #include "clang/Basic/LangOptions.def" #define SANITIZER(NAME, ID) \ Record.push_back(LangOpts.Sanitize.has(SanitizerKind::ID)); #include "clang/Basic/Sanitizers.def" Record.push_back(LangOpts.ModuleFeatures.size()); for (StringRef Feature : LangOpts.ModuleFeatures) AddString(Feature, Record); Record.push_back((unsigned) LangOpts.ObjCRuntime.getKind()); AddVersionTuple(LangOpts.ObjCRuntime.getVersion(), Record); AddString(LangOpts.CurrentModule, Record); // Comment options. Record.push_back(LangOpts.CommentOpts.BlockCommandNames.size()); for (const auto &I : LangOpts.CommentOpts.BlockCommandNames) { AddString(I, Record); } Record.push_back(LangOpts.CommentOpts.ParseAllComments); // OpenMP offloading options. Record.push_back(LangOpts.OMPTargetTriples.size()); for (auto &T : LangOpts.OMPTargetTriples) AddString(T.getTriple(), Record); AddString(LangOpts.OMPHostIRFile, Record); Stream.EmitRecord(LANGUAGE_OPTIONS, Record); // Target options. Record.clear(); const TargetInfo &Target = Context.getTargetInfo(); const TargetOptions &TargetOpts = Target.getTargetOpts(); AddString(TargetOpts.Triple, Record); AddString(TargetOpts.CPU, Record); AddString(TargetOpts.ABI, Record); Record.push_back(TargetOpts.FeaturesAsWritten.size()); for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size(); I != N; ++I) { AddString(TargetOpts.FeaturesAsWritten[I], Record); } Record.push_back(TargetOpts.Features.size()); for (unsigned I = 0, N = TargetOpts.Features.size(); I != N; ++I) { AddString(TargetOpts.Features[I], Record); } Stream.EmitRecord(TARGET_OPTIONS, Record); // File system options. Record.clear(); const FileSystemOptions &FSOpts = Context.getSourceManager().getFileManager().getFileSystemOpts(); AddString(FSOpts.WorkingDir, Record); Stream.EmitRecord(FILE_SYSTEM_OPTIONS, Record); // Header search options. Record.clear(); const HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts(); AddString(HSOpts.Sysroot, Record); // Include entries. Record.push_back(HSOpts.UserEntries.size()); for (unsigned I = 0, N = HSOpts.UserEntries.size(); I != N; ++I) { const HeaderSearchOptions::Entry &Entry = HSOpts.UserEntries[I]; AddString(Entry.Path, Record); Record.push_back(static_cast(Entry.Group)); Record.push_back(Entry.IsFramework); Record.push_back(Entry.IgnoreSysRoot); } // System header prefixes. Record.push_back(HSOpts.SystemHeaderPrefixes.size()); for (unsigned I = 0, N = HSOpts.SystemHeaderPrefixes.size(); I != N; ++I) { AddString(HSOpts.SystemHeaderPrefixes[I].Prefix, Record); Record.push_back(HSOpts.SystemHeaderPrefixes[I].IsSystemHeader); } AddString(HSOpts.ResourceDir, Record); AddString(HSOpts.ModuleCachePath, Record); AddString(HSOpts.ModuleUserBuildPath, Record); Record.push_back(HSOpts.DisableModuleHash); Record.push_back(HSOpts.ImplicitModuleMaps); Record.push_back(HSOpts.ModuleMapFileHomeIsCwd); Record.push_back(HSOpts.UseBuiltinIncludes); Record.push_back(HSOpts.UseStandardSystemIncludes); Record.push_back(HSOpts.UseStandardCXXIncludes); Record.push_back(HSOpts.UseLibcxx); // Write out the specific module cache path that contains the module files. AddString(PP.getHeaderSearchInfo().getModuleCachePath(), Record); Stream.EmitRecord(HEADER_SEARCH_OPTIONS, Record); // Preprocessor options. Record.clear(); const PreprocessorOptions &PPOpts = PP.getPreprocessorOpts(); // Macro definitions. Record.push_back(PPOpts.Macros.size()); for (unsigned I = 0, N = PPOpts.Macros.size(); I != N; ++I) { AddString(PPOpts.Macros[I].first, Record); Record.push_back(PPOpts.Macros[I].second); } // Includes Record.push_back(PPOpts.Includes.size()); for (unsigned I = 0, N = PPOpts.Includes.size(); I != N; ++I) AddString(PPOpts.Includes[I], Record); // Macro includes Record.push_back(PPOpts.MacroIncludes.size()); for (unsigned I = 0, N = PPOpts.MacroIncludes.size(); I != N; ++I) AddString(PPOpts.MacroIncludes[I], Record); Record.push_back(PPOpts.UsePredefines); // Detailed record is important since it is used for the module cache hash. Record.push_back(PPOpts.DetailedRecord); AddString(PPOpts.ImplicitPCHInclude, Record); AddString(PPOpts.ImplicitPTHInclude, Record); Record.push_back(static_cast(PPOpts.ObjCXXARCStandardLibrary)); Stream.EmitRecord(PREPROCESSOR_OPTIONS, Record); // Leave the options block. Stream.ExitBlock(); // Original file name and file ID SourceManager &SM = Context.getSourceManager(); if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { auto FileAbbrev = std::make_shared(); FileAbbrev->Add(BitCodeAbbrevOp(ORIGINAL_FILE)); FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File ID FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name unsigned FileAbbrevCode = Stream.EmitAbbrev(std::move(FileAbbrev)); Record.clear(); Record.push_back(ORIGINAL_FILE); Record.push_back(SM.getMainFileID().getOpaqueValue()); EmitRecordWithPath(FileAbbrevCode, Record, MainFile->getName()); } Record.clear(); Record.push_back(SM.getMainFileID().getOpaqueValue()); Stream.EmitRecord(ORIGINAL_FILE_ID, Record); // Original PCH directory if (!OutputFile.empty() && OutputFile != "-") { auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(ORIGINAL_PCH_DIR)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev)); SmallString<128> OutputPath(OutputFile); SM.getFileManager().makeAbsolutePath(OutputPath); StringRef origDir = llvm::sys::path::parent_path(OutputPath); RecordData::value_type Record[] = {ORIGINAL_PCH_DIR}; Stream.EmitRecordWithBlob(AbbrevCode, Record, origDir); } WriteInputFiles(Context.SourceMgr, PP.getHeaderSearchInfo().getHeaderSearchOpts(), PP.getLangOpts().Modules); Stream.ExitBlock(); } namespace { /// An input file. struct InputFileEntry { const FileEntry *File; bool IsSystemFile; bool IsTransient; bool BufferOverridden; bool IsTopLevelModuleMap; }; } // namespace void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, HeaderSearchOptions &HSOpts, bool Modules) { using namespace llvm; Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4); // Create input-file abbreviation. auto IFAbbrev = std::make_shared(); IFAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE)); IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Overridden IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Transient IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Module map IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name unsigned IFAbbrevCode = Stream.EmitAbbrev(std::move(IFAbbrev)); // Get all ContentCache objects for files, sorted by whether the file is a // system one or not. System files go at the back, users files at the front. std::deque SortedFiles; for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size(); I != N; ++I) { // Get this source location entry. const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I); assert(&SourceMgr.getSLocEntry(FileID::get(I)) == SLoc); // We only care about file entries that were not overridden. if (!SLoc->isFile()) continue; const SrcMgr::FileInfo &File = SLoc->getFile(); const SrcMgr::ContentCache *Cache = File.getContentCache(); if (!Cache->OrigEntry) continue; InputFileEntry Entry; Entry.File = Cache->OrigEntry; Entry.IsSystemFile = Cache->IsSystemFile; Entry.IsTransient = Cache->IsTransient; Entry.BufferOverridden = Cache->BufferOverridden; Entry.IsTopLevelModuleMap = isModuleMap(File.getFileCharacteristic()) && File.getIncludeLoc().isInvalid(); if (Cache->IsSystemFile) SortedFiles.push_back(Entry); else SortedFiles.push_front(Entry); } unsigned UserFilesNum = 0; // Write out all of the input files. std::vector InputFileOffsets; for (const auto &Entry : SortedFiles) { uint32_t &InputFileID = InputFileIDs[Entry.File]; if (InputFileID != 0) continue; // already recorded this file. // Record this entry's offset. InputFileOffsets.push_back(Stream.GetCurrentBitNo()); InputFileID = InputFileOffsets.size(); if (!Entry.IsSystemFile) ++UserFilesNum; // Emit size/modification time for this file. // And whether this file was overridden. RecordData::value_type Record[] = { INPUT_FILE, InputFileOffsets.size(), (uint64_t)Entry.File->getSize(), (uint64_t)getTimestampForOutput(Entry.File), Entry.BufferOverridden, Entry.IsTransient, Entry.IsTopLevelModuleMap}; EmitRecordWithPath(IFAbbrevCode, Record, Entry.File->getName()); } Stream.ExitBlock(); // Create input file offsets abbreviation. auto OffsetsAbbrev = std::make_shared(); OffsetsAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE_OFFSETS)); OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # input files OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # non-system // input files OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Array unsigned OffsetsAbbrevCode = Stream.EmitAbbrev(std::move(OffsetsAbbrev)); // Write input file offsets. RecordData::value_type Record[] = {INPUT_FILE_OFFSETS, InputFileOffsets.size(), UserFilesNum}; Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, bytes(InputFileOffsets)); } //===----------------------------------------------------------------------===// // Source Manager Serialization //===----------------------------------------------------------------------===// /// Create an abbreviation for the SLocEntry that refers to a /// file. static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) { using namespace llvm; auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_FILE_ENTRY)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Characteristic Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives // FileEntry fields. Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Input File ID Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumCreatedFIDs Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 24)); // FirstDeclIndex Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumDecls return Stream.EmitAbbrev(std::move(Abbrev)); } /// Create an abbreviation for the SLocEntry that refers to a /// buffer. static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) { using namespace llvm; auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_BUFFER_ENTRY)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Characteristic Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob return Stream.EmitAbbrev(std::move(Abbrev)); } /// Create an abbreviation for the SLocEntry that refers to a /// buffer's blob. static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream, bool Compressed) { using namespace llvm; auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(Compressed ? SM_SLOC_BUFFER_BLOB_COMPRESSED : SM_SLOC_BUFFER_BLOB)); if (Compressed) Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Uncompressed size Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob return Stream.EmitAbbrev(std::move(Abbrev)); } /// Create an abbreviation for the SLocEntry that refers to a macro /// expansion. static unsigned CreateSLocExpansionAbbrev(llvm::BitstreamWriter &Stream) { using namespace llvm; auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_EXPANSION_ENTRY)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // End location Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Is token range Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length return Stream.EmitAbbrev(std::move(Abbrev)); } namespace { // Trait used for the on-disk hash table of header search information. class HeaderFileInfoTrait { ASTWriter &Writer; // Keep track of the framework names we've used during serialization. SmallVector FrameworkStringData; llvm::StringMap FrameworkNameOffset; public: HeaderFileInfoTrait(ASTWriter &Writer) : Writer(Writer) {} struct key_type { StringRef Filename; off_t Size; time_t ModTime; }; using key_type_ref = const key_type &; using UnresolvedModule = llvm::PointerIntPair; struct data_type { const HeaderFileInfo &HFI; ArrayRef KnownHeaders; UnresolvedModule Unresolved; }; using data_type_ref = const data_type &; using hash_value_type = unsigned; using offset_type = unsigned; hash_value_type ComputeHash(key_type_ref key) { // The hash is based only on size/time of the file, so that the reader can // match even when symlinking or excess path elements ("foo/../", "../") // change the form of the name. However, complete path is still the key. return llvm::hash_combine(key.Size, key.ModTime); } std::pair EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) { using namespace llvm::support; endian::Writer LE(Out, little); unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write(KeyLen); unsigned DataLen = 1 + 2 + 4 + 4; for (auto ModInfo : Data.KnownHeaders) if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule())) DataLen += 4; if (Data.Unresolved.getPointer()) DataLen += 4; LE.write(DataLen); return std::make_pair(KeyLen, DataLen); } void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) { using namespace llvm::support; endian::Writer LE(Out, little); LE.write(key.Size); KeyLen -= 8; LE.write(key.ModTime); KeyLen -= 8; Out.write(key.Filename.data(), KeyLen); } void EmitData(raw_ostream &Out, key_type_ref key, data_type_ref Data, unsigned DataLen) { using namespace llvm::support; endian::Writer LE(Out, little); uint64_t Start = Out.tell(); (void)Start; unsigned char Flags = (Data.HFI.isImport << 5) | (Data.HFI.isPragmaOnce << 4) | (Data.HFI.DirInfo << 1) | Data.HFI.IndexHeaderMapHeader; LE.write(Flags); LE.write(Data.HFI.NumIncludes); if (!Data.HFI.ControllingMacro) LE.write(Data.HFI.ControllingMacroID); else LE.write(Writer.getIdentifierRef(Data.HFI.ControllingMacro)); unsigned Offset = 0; if (!Data.HFI.Framework.empty()) { // If this header refers into a framework, save the framework name. llvm::StringMap::iterator Pos = FrameworkNameOffset.find(Data.HFI.Framework); if (Pos == FrameworkNameOffset.end()) { Offset = FrameworkStringData.size() + 1; FrameworkStringData.append(Data.HFI.Framework.begin(), Data.HFI.Framework.end()); FrameworkStringData.push_back(0); FrameworkNameOffset[Data.HFI.Framework] = Offset; } else Offset = Pos->second; } LE.write(Offset); auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; assert((Value >> 2) == ModID && "overflow in header module info"); LE.write(Value); } }; // FIXME: If the header is excluded, we should write out some // record of that fact. for (auto ModInfo : Data.KnownHeaders) EmitModule(ModInfo.getModule(), ModInfo.getRole()); if (Data.Unresolved.getPointer()) EmitModule(Data.Unresolved.getPointer(), Data.Unresolved.getInt()); assert(Out.tell() - Start == DataLen && "Wrong data length"); } const char *strings_begin() const { return FrameworkStringData.begin(); } const char *strings_end() const { return FrameworkStringData.end(); } }; } // namespace /// Write the header search block for the list of files that /// /// \param HS The header search structure to save. void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; unsigned NumHeaderSearchEntries = 0; // Find all unresolved headers for the current module. We generally will // have resolved them before we get here, but not necessarily: we might be // compiling a preprocessed module, where there is no requirement for the // original files to exist any more. const HeaderFileInfo Empty; // So we can take a reference. if (WritingModule) { llvm::SmallVector Worklist(1, WritingModule); while (!Worklist.empty()) { Module *M = Worklist.pop_back_val(); if (!M->isAvailable()) continue; // Map to disk files where possible, to pick up any missing stat // information. This also means we don't need to check the unresolved // headers list when emitting resolved headers in the first loop below. // FIXME: It'd be preferable to avoid doing this if we were given // sufficient stat information in the module map. HS.getModuleMap().resolveHeaderDirectives(M); // If the file didn't exist, we can still create a module if we were given // enough information in the module map. for (auto U : M->MissingHeaders) { // Check that we were given enough information to build a module // without this file existing on disk. if (!U.Size || (!U.ModTime && IncludeTimestamps)) { PP->Diag(U.FileNameLoc, diag::err_module_no_size_mtime_for_header) << WritingModule->getFullModuleName() << U.Size.hasValue() << U.FileName; continue; } // Form the effective relative pathname for the file. SmallString<128> Filename(M->Directory->getName()); llvm::sys::path::append(Filename, U.FileName); PreparePathForOutput(Filename); StringRef FilenameDup = strdup(Filename.c_str()); SavedStrings.push_back(FilenameDup.data()); HeaderFileInfoTrait::key_type Key = { FilenameDup, *U.Size, IncludeTimestamps ? *U.ModTime : 0 }; HeaderFileInfoTrait::data_type Data = { Empty, {}, {M, ModuleMap::headerKindToRole(U.Kind)} }; // FIXME: Deal with cases where there are multiple unresolved header // directives in different submodules for the same header. Generator.insert(Key, Data, GeneratorTrait); ++NumHeaderSearchEntries; } Worklist.append(M->submodule_begin(), M->submodule_end()); } } SmallVector FilesByUID; HS.getFileMgr().GetUniqueIDMapping(FilesByUID); if (FilesByUID.size() > HS.header_file_size()) FilesByUID.resize(HS.header_file_size()); for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) { const FileEntry *File = FilesByUID[UID]; if (!File) continue; // Get the file info. This will load info from the external source if // necessary. Skip emitting this file if we have no information on it // as a header file (in which case HFI will be null) or if it hasn't // changed since it was loaded. Also skip it if it's for a modular header // from a different module; in that case, we rely on the module(s) // containing the header to provide this information. const HeaderFileInfo *HFI = HS.getExistingFileInfo(File, /*WantExternal*/!Chain); if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader)) continue; // Massage the file path into an appropriate form. StringRef Filename = File->getName(); SmallString<128> FilenameTmp(Filename); if (PreparePathForOutput(FilenameTmp)) { // If we performed any translation on the file name at all, we need to // save this string, since the generator will refer to it later. Filename = StringRef(strdup(FilenameTmp.c_str())); SavedStrings.push_back(Filename.data()); } HeaderFileInfoTrait::key_type Key = { Filename, File->getSize(), getTimestampForOutput(File) }; HeaderFileInfoTrait::data_type Data = { *HFI, HS.getModuleMap().findAllModulesForHeader(File), {} }; Generator.insert(Key, Data, GeneratorTrait); ++NumHeaderSearchEntries; } // Create the on-disk hash table in a buffer. SmallString<4096> TableData; uint32_t BucketOffset; { using namespace llvm::support; llvm::raw_svector_ostream Out(TableData); // Make sure that no bucket is at offset 0 endian::write(Out, 0, little); BucketOffset = Generator.Emit(Out, GeneratorTrait); } // Create a blob abbreviation using namespace llvm; auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(HEADER_SEARCH_TABLE)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned TableAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); // Write the header search table RecordData::value_type Record[] = {HEADER_SEARCH_TABLE, BucketOffset, NumHeaderSearchEntries, TableData.size()}; TableData.append(GeneratorTrait.strings_begin(),GeneratorTrait.strings_end()); Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData); // Free all of the strings we had to duplicate. for (unsigned I = 0, N = SavedStrings.size(); I != N; ++I) free(const_cast(SavedStrings[I])); } static void emitBlob(llvm::BitstreamWriter &Stream, StringRef Blob, unsigned SLocBufferBlobCompressedAbbrv, unsigned SLocBufferBlobAbbrv) { using RecordDataType = ASTWriter::RecordData::value_type; // Compress the buffer if possible. We expect that almost all PCM // consumers will not want its contents. SmallString<0> CompressedBuffer; if (llvm::zlib::isAvailable()) { llvm::Error E = llvm::zlib::compress(Blob.drop_back(1), CompressedBuffer); if (!E) { RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB_COMPRESSED, Blob.size() - 1}; Stream.EmitRecordWithBlob(SLocBufferBlobCompressedAbbrv, Record, CompressedBuffer); return; } llvm::consumeError(std::move(E)); } RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB}; Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, Blob); } /// Writes the block containing the serialized form of the /// source manager. /// /// TODO: We should probably use an on-disk hash table (stored in a /// blob), indexed based on the file name, so that we only create /// entries for files that we actually need. In the common case (no /// errors), we probably won't have to create file entries for any of /// the files in the AST. void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, const Preprocessor &PP) { RecordData Record; // Enter the source manager block. Stream.EnterSubblock(SOURCE_MANAGER_BLOCK_ID, 4); // Abbreviations for the various kinds of source-location entries. unsigned SLocFileAbbrv = CreateSLocFileAbbrev(Stream); unsigned SLocBufferAbbrv = CreateSLocBufferAbbrev(Stream); unsigned SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream, false); unsigned SLocBufferBlobCompressedAbbrv = CreateSLocBufferBlobAbbrev(Stream, true); unsigned SLocExpansionAbbrv = CreateSLocExpansionAbbrev(Stream); // Write out the source location entry table. We skip the first // entry, which is always the same dummy entry. std::vector SLocEntryOffsets; RecordData PreloadSLocs; SLocEntryOffsets.reserve(SourceMgr.local_sloc_entry_size() - 1); for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size(); I != N; ++I) { // Get this source location entry. const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I); FileID FID = FileID::get(I); assert(&SourceMgr.getSLocEntry(FID) == SLoc); // Record the offset of this source-location entry. SLocEntryOffsets.push_back(Stream.GetCurrentBitNo()); // Figure out which record code to use. unsigned Code; if (SLoc->isFile()) { const SrcMgr::ContentCache *Cache = SLoc->getFile().getContentCache(); if (Cache->OrigEntry) { Code = SM_SLOC_FILE_ENTRY; } else Code = SM_SLOC_BUFFER_ENTRY; } else Code = SM_SLOC_EXPANSION_ENTRY; Record.clear(); Record.push_back(Code); // Starting offset of this entry within this module, so skip the dummy. Record.push_back(SLoc->getOffset() - 2); if (SLoc->isFile()) { const SrcMgr::FileInfo &File = SLoc->getFile(); AddSourceLocation(File.getIncludeLoc(), Record); Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding Record.push_back(File.hasLineDirectives()); const SrcMgr::ContentCache *Content = File.getContentCache(); bool EmitBlob = false; if (Content->OrigEntry) { assert(Content->OrigEntry == Content->ContentsEntry && "Writing to AST an overridden file is not supported"); // The source location entry is a file. Emit input file ID. assert(InputFileIDs[Content->OrigEntry] != 0 && "Missed file entry"); Record.push_back(InputFileIDs[Content->OrigEntry]); Record.push_back(File.NumCreatedFIDs); FileDeclIDsTy::iterator FDI = FileDeclIDs.find(FID); if (FDI != FileDeclIDs.end()) { Record.push_back(FDI->second->FirstDeclIndex); Record.push_back(FDI->second->DeclIDs.size()); } else { Record.push_back(0); Record.push_back(0); } Stream.EmitRecordWithAbbrev(SLocFileAbbrv, Record); if (Content->BufferOverridden || Content->IsTransient) EmitBlob = true; } else { // The source location entry is a buffer. The blob associated // with this entry contains the contents of the buffer. // We add one to the size so that we capture the trailing NULL // that is required by llvm::MemoryBuffer::getMemBuffer (on // the reader side). const llvm::MemoryBuffer *Buffer = Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager()); StringRef Name = Buffer->getBufferIdentifier(); Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record, StringRef(Name.data(), Name.size() + 1)); EmitBlob = true; if (Name == "") PreloadSLocs.push_back(SLocEntryOffsets.size()); } if (EmitBlob) { // Include the implicit terminating null character in the on-disk buffer // if we're writing it uncompressed. const llvm::MemoryBuffer *Buffer = Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager()); StringRef Blob(Buffer->getBufferStart(), Buffer->getBufferSize() + 1); emitBlob(Stream, Blob, SLocBufferBlobCompressedAbbrv, SLocBufferBlobAbbrv); } } else { // The source location entry is a macro expansion. const SrcMgr::ExpansionInfo &Expansion = SLoc->getExpansion(); AddSourceLocation(Expansion.getSpellingLoc(), Record); AddSourceLocation(Expansion.getExpansionLocStart(), Record); AddSourceLocation(Expansion.isMacroArgExpansion() ? SourceLocation() : Expansion.getExpansionLocEnd(), Record); Record.push_back(Expansion.isExpansionTokenRange()); // Compute the token length for this macro expansion. unsigned NextOffset = SourceMgr.getNextLocalOffset(); if (I + 1 != N) NextOffset = SourceMgr.getLocalSLocEntry(I + 1).getOffset(); Record.push_back(NextOffset - SLoc->getOffset() - 1); Stream.EmitRecordWithAbbrev(SLocExpansionAbbrv, Record); } } Stream.ExitBlock(); if (SLocEntryOffsets.empty()) return; // Write the source-location offsets table into the AST block. This // table is used for lazily loading source-location information. using namespace llvm; auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SOURCE_LOCATION_OFFSETS)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // total size Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); { RecordData::value_type Record[] = { SOURCE_LOCATION_OFFSETS, SLocEntryOffsets.size(), SourceMgr.getNextLocalOffset() - 1 /* skip dummy */}; Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, bytes(SLocEntryOffsets)); } // Write the source location entry preloads array, telling the AST // reader which source locations entries it should load eagerly. Stream.EmitRecord(SOURCE_LOCATION_PRELOADS, PreloadSLocs); // Write the line table. It depends on remapping working, so it must come // after the source location offsets. if (SourceMgr.hasLineTable()) { LineTableInfo &LineTable = SourceMgr.getLineTable(); Record.clear(); // Emit the needed file names. llvm::DenseMap FilenameMap; FilenameMap[-1] = -1; // For unspecified filenames. for (const auto &L : LineTable) { if (L.first.ID < 0) continue; for (auto &LE : L.second) { if (FilenameMap.insert(std::make_pair(LE.FilenameID, FilenameMap.size() - 1)).second) AddPath(LineTable.getFilename(LE.FilenameID), Record); } } Record.push_back(0); // Emit the line entries for (const auto &L : LineTable) { // Only emit entries for local files. if (L.first.ID < 0) continue; // Emit the file ID Record.push_back(L.first.ID); // Emit the line entries Record.push_back(L.second.size()); for (const auto &LE : L.second) { Record.push_back(LE.FileOffset); Record.push_back(LE.LineNo); Record.push_back(FilenameMap[LE.FilenameID]); Record.push_back((unsigned)LE.FileKind); Record.push_back(LE.IncludeOffset); } } Stream.EmitRecord(SOURCE_MANAGER_LINE_TABLE, Record); } } //===----------------------------------------------------------------------===// // Preprocessor Serialization //===----------------------------------------------------------------------===// static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule, const Preprocessor &PP) { if (MacroInfo *MI = MD->getMacroInfo()) if (MI->isBuiltinMacro()) return true; if (IsModule) { SourceLocation Loc = MD->getLocation(); if (Loc.isInvalid()) return true; if (PP.getSourceManager().getFileID(Loc) == PP.getPredefinesFileID()) return true; } return false; } /// Writes the block containing the serialized form of the /// preprocessor. void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { PreprocessingRecord *PPRec = PP.getPreprocessingRecord(); if (PPRec) WritePreprocessorDetail(*PPRec); RecordData Record; RecordData ModuleMacroRecord; // If the preprocessor __COUNTER__ value has been bumped, remember it. if (PP.getCounterValue() != 0) { RecordData::value_type Record[] = {PP.getCounterValue()}; Stream.EmitRecord(PP_COUNTER_VALUE, Record); } if (PP.isRecordingPreamble() && PP.hasRecordedPreamble()) { assert(!IsModule); auto SkipInfo = PP.getPreambleSkipInfo(); if (SkipInfo.hasValue()) { Record.push_back(true); AddSourceLocation(SkipInfo->HashTokenLoc, Record); AddSourceLocation(SkipInfo->IfTokenLoc, Record); Record.push_back(SkipInfo->FoundNonSkipPortion); Record.push_back(SkipInfo->FoundElse); AddSourceLocation(SkipInfo->ElseLoc, Record); } else { Record.push_back(false); } for (const auto &Cond : PP.getPreambleConditionalStack()) { AddSourceLocation(Cond.IfLoc, Record); Record.push_back(Cond.WasSkipping); Record.push_back(Cond.FoundNonSkip); Record.push_back(Cond.FoundElse); } Stream.EmitRecord(PP_CONDITIONAL_STACK, Record); Record.clear(); } // Enter the preprocessor block. Stream.EnterSubblock(PREPROCESSOR_BLOCK_ID, 3); // If the AST file contains __DATE__ or __TIME__ emit a warning about this. // FIXME: Include a location for the use, and say which one was used. if (PP.SawDateOrTime()) PP.Diag(SourceLocation(), diag::warn_module_uses_date_time) << IsModule; // Loop over all the macro directives that are live at the end of the file, // emitting each to the PP section. // Construct the list of identifiers with macro directives that need to be // serialized. SmallVector MacroIdentifiers; for (auto &Id : PP.getIdentifierTable()) if (Id.second->hadMacroDefinition() && (!Id.second->isFromAST() || Id.second->hasChangedSinceDeserialization())) MacroIdentifiers.push_back(Id.second); // Sort the set of macro definitions that need to be serialized by the // name of the macro, to provide a stable ordering. llvm::sort(MacroIdentifiers.begin(), MacroIdentifiers.end(), llvm::less_ptr()); // Emit the macro directives as a list and associate the offset with the // identifier they belong to. for (const IdentifierInfo *Name : MacroIdentifiers) { MacroDirective *MD = PP.getLocalMacroDirectiveHistory(Name); auto StartOffset = Stream.GetCurrentBitNo(); // Emit the macro directives in reverse source order. for (; MD; MD = MD->getPrevious()) { // Once we hit an ignored macro, we're done: the rest of the chain // will all be ignored macros. if (shouldIgnoreMacro(MD, IsModule, PP)) break; AddSourceLocation(MD->getLocation(), Record); Record.push_back(MD->getKind()); if (auto *DefMD = dyn_cast(MD)) { Record.push_back(getMacroRef(DefMD->getInfo(), Name)); } else if (auto *VisMD = dyn_cast(MD)) { Record.push_back(VisMD->isPublic()); } } // Write out any exported module macros. bool EmittedModuleMacros = false; // We write out exported module macros for PCH as well. auto Leafs = PP.getLeafModuleMacros(Name); SmallVector Worklist(Leafs.begin(), Leafs.end()); llvm::DenseMap Visits; while (!Worklist.empty()) { auto *Macro = Worklist.pop_back_val(); // Emit a record indicating this submodule exports this macro. ModuleMacroRecord.push_back( getSubmoduleID(Macro->getOwningModule())); ModuleMacroRecord.push_back(getMacroRef(Macro->getMacroInfo(), Name)); for (auto *M : Macro->overrides()) ModuleMacroRecord.push_back(getSubmoduleID(M->getOwningModule())); Stream.EmitRecord(PP_MODULE_MACRO, ModuleMacroRecord); ModuleMacroRecord.clear(); // Enqueue overridden macros once we've visited all their ancestors. for (auto *M : Macro->overrides()) if (++Visits[M] == M->getNumOverridingMacros()) Worklist.push_back(M); EmittedModuleMacros = true; } if (Record.empty() && !EmittedModuleMacros) continue; IdentMacroDirectivesOffsetMap[Name] = StartOffset; Stream.EmitRecord(PP_MACRO_DIRECTIVE_HISTORY, Record); Record.clear(); } /// Offsets of each of the macros into the bitstream, indexed by /// the local macro ID /// /// For each identifier that is associated with a macro, this map /// provides the offset into the bitstream where that macro is /// defined. std::vector MacroOffsets; for (unsigned I = 0, N = MacroInfosToEmit.size(); I != N; ++I) { const IdentifierInfo *Name = MacroInfosToEmit[I].Name; MacroInfo *MI = MacroInfosToEmit[I].MI; MacroID ID = MacroInfosToEmit[I].ID; if (ID < FirstMacroID) { assert(0 && "Loaded MacroInfo entered MacroInfosToEmit ?"); continue; } // Record the local offset of this macro. unsigned Index = ID - FirstMacroID; if (Index == MacroOffsets.size()) MacroOffsets.push_back(Stream.GetCurrentBitNo()); else { if (Index > MacroOffsets.size()) MacroOffsets.resize(Index + 1); MacroOffsets[Index] = Stream.GetCurrentBitNo(); } AddIdentifierRef(Name, Record); AddSourceLocation(MI->getDefinitionLoc(), Record); AddSourceLocation(MI->getDefinitionEndLoc(), Record); Record.push_back(MI->isUsed()); Record.push_back(MI->isUsedForHeaderGuard()); unsigned Code; if (MI->isObjectLike()) { Code = PP_MACRO_OBJECT_LIKE; } else { Code = PP_MACRO_FUNCTION_LIKE; Record.push_back(MI->isC99Varargs()); Record.push_back(MI->isGNUVarargs()); Record.push_back(MI->hasCommaPasting()); Record.push_back(MI->getNumParams()); for (const IdentifierInfo *Param : MI->params()) AddIdentifierRef(Param, Record); } // If we have a detailed preprocessing record, record the macro definition // ID that corresponds to this macro. if (PPRec) Record.push_back(MacroDefinitions[PPRec->findMacroDefinition(MI)]); Stream.EmitRecord(Code, Record); Record.clear(); // Emit the tokens array. for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) { // Note that we know that the preprocessor does not have any annotation // tokens in it because they are created by the parser, and thus can't // be in a macro definition. const Token &Tok = MI->getReplacementToken(TokNo); AddToken(Tok, Record); Stream.EmitRecord(PP_TOKEN, Record); Record.clear(); } ++NumMacros; } Stream.ExitBlock(); // Write the offsets table for macro IDs. using namespace llvm; auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(MACRO_OFFSET)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macros Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned MacroOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); { RecordData::value_type Record[] = {MACRO_OFFSET, MacroOffsets.size(), FirstMacroID - NUM_PREDEF_MACRO_IDS}; Stream.EmitRecordWithBlob(MacroOffsetAbbrev, Record, bytes(MacroOffsets)); } } void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { if (PPRec.local_begin() == PPRec.local_end()) return; SmallVector PreprocessedEntityOffsets; // Enter the preprocessor block. Stream.EnterSubblock(PREPROCESSOR_DETAIL_BLOCK_ID, 3); // If the preprocessor has a preprocessing record, emit it. unsigned NumPreprocessingRecords = 0; using namespace llvm; // Set up the abbreviation for unsigned InclusionAbbrev = 0; { auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(PPD_INCLUSION_DIRECTIVE)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // filename length Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // in quotes Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // kind Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // imported module Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); InclusionAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); } unsigned FirstPreprocessorEntityID = (Chain ? PPRec.getNumLoadedPreprocessedEntities() : 0) + NUM_PREDEF_PP_ENTITY_IDS; unsigned NextPreprocessorEntityID = FirstPreprocessorEntityID; RecordData Record; for (PreprocessingRecord::iterator E = PPRec.local_begin(), EEnd = PPRec.local_end(); E != EEnd; (void)++E, ++NumPreprocessingRecords, ++NextPreprocessorEntityID) { Record.clear(); PreprocessedEntityOffsets.push_back( PPEntityOffset((*E)->getSourceRange(), Stream.GetCurrentBitNo())); if (auto *MD = dyn_cast(*E)) { // Record this macro definition's ID. MacroDefinitions[MD] = NextPreprocessorEntityID; AddIdentifierRef(MD->getName(), Record); Stream.EmitRecord(PPD_MACRO_DEFINITION, Record); continue; } if (auto *ME = dyn_cast(*E)) { Record.push_back(ME->isBuiltinMacro()); if (ME->isBuiltinMacro()) AddIdentifierRef(ME->getName(), Record); else Record.push_back(MacroDefinitions[ME->getDefinition()]); Stream.EmitRecord(PPD_MACRO_EXPANSION, Record); continue; } if (auto *ID = dyn_cast(*E)) { Record.push_back(PPD_INCLUSION_DIRECTIVE); Record.push_back(ID->getFileName().size()); Record.push_back(ID->wasInQuotes()); Record.push_back(static_cast(ID->getKind())); Record.push_back(ID->importedModule()); SmallString<64> Buffer; Buffer += ID->getFileName(); // Check that the FileEntry is not null because it was not resolved and // we create a PCH even with compiler errors. if (ID->getFile()) Buffer += ID->getFile()->getName(); Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer); continue; } llvm_unreachable("Unhandled PreprocessedEntity in ASTWriter"); } Stream.ExitBlock(); // Write the offsets table for the preprocessing record. if (NumPreprocessingRecords > 0) { assert(PreprocessedEntityOffsets.size() == NumPreprocessingRecords); // Write the offsets table for identifier IDs. using namespace llvm; auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(PPD_ENTITIES_OFFSETS)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first pp entity Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned PPEOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); RecordData::value_type Record[] = {PPD_ENTITIES_OFFSETS, FirstPreprocessorEntityID - NUM_PREDEF_PP_ENTITY_IDS}; Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record, bytes(PreprocessedEntityOffsets)); } // Write the skipped region table for the preprocessing record. ArrayRef SkippedRanges = PPRec.getSkippedRanges(); if (SkippedRanges.size() > 0) { std::vector SerializedSkippedRanges; SerializedSkippedRanges.reserve(SkippedRanges.size()); for (auto const& Range : SkippedRanges) SerializedSkippedRanges.emplace_back(Range); using namespace llvm; auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(PPD_SKIPPED_RANGES)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned PPESkippedRangeAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); Record.clear(); Record.push_back(PPD_SKIPPED_RANGES); Stream.EmitRecordWithBlob(PPESkippedRangeAbbrev, Record, bytes(SerializedSkippedRanges)); } } unsigned ASTWriter::getLocalOrImportedSubmoduleID(Module *Mod) { if (!Mod) return 0; llvm::DenseMap::iterator Known = SubmoduleIDs.find(Mod); if (Known != SubmoduleIDs.end()) return Known->second; auto *Top = Mod->getTopLevelModule(); if (Top != WritingModule && (getLangOpts().CompilingPCH || !Top->fullModuleNameIs(StringRef(getLangOpts().CurrentModule)))) return 0; return SubmoduleIDs[Mod] = NextSubmoduleID++; } unsigned ASTWriter::getSubmoduleID(Module *Mod) { // FIXME: This can easily happen, if we have a reference to a submodule that // did not result in us loading a module file for that submodule. For // instance, a cross-top-level-module 'conflict' declaration will hit this. unsigned ID = getLocalOrImportedSubmoduleID(Mod); assert((ID || !Mod) && "asked for module ID for non-local, non-imported module"); return ID; } /// Compute the number of modules within the given tree (including the /// given module). static unsigned getNumberOfModules(Module *Mod) { unsigned ChildModules = 0; for (auto Sub = Mod->submodule_begin(), SubEnd = Mod->submodule_end(); Sub != SubEnd; ++Sub) ChildModules += getNumberOfModules(*Sub); return ChildModules + 1; } void ASTWriter::WriteSubmodules(Module *WritingModule) { // Enter the submodule description block. Stream.EnterSubblock(SUBMODULE_BLOCK_ID, /*bits for abbreviations*/5); // Write the abbreviations needed for the submodules block. using namespace llvm; auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_DEFINITION)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Kind Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExternC Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferSubmodules... Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit... Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild... Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ConfigMacrosExh... Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ModuleMapIsPriv... Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned DefinitionAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_UMBRELLA_HEADER)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned UmbrellaAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_HEADER)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned HeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_TOPHEADER)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned TopHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_UMBRELLA_DIR)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned UmbrellaDirAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_REQUIRES)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // State Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Feature unsigned RequiresAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_EXCLUDED_HEADER)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned ExcludedHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_TEXTUAL_HEADER)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned TextualHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_HEADER)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned PrivateHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_TEXTUAL_HEADER)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned PrivateTextualHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_LINK_LIBRARY)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name unsigned LinkLibraryAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_CONFIG_MACRO)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Macro name unsigned ConfigMacroAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_CONFLICT)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Other module Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Message unsigned ConflictAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_EXPORT_AS)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Macro name unsigned ExportAsAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); // Write the submodule metadata block. RecordData::value_type Record[] = { getNumberOfModules(WritingModule), FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS}; Stream.EmitRecord(SUBMODULE_METADATA, Record); // Write all of the submodules. std::queue Q; Q.push(WritingModule); while (!Q.empty()) { Module *Mod = Q.front(); Q.pop(); unsigned ID = getSubmoduleID(Mod); uint64_t ParentID = 0; if (Mod->Parent) { assert(SubmoduleIDs[Mod->Parent] && "Submodule parent not written?"); ParentID = SubmoduleIDs[Mod->Parent]; } // Emit the definition of the block. { RecordData::value_type Record[] = {SUBMODULE_DEFINITION, ID, ParentID, (RecordData::value_type)Mod->Kind, Mod->IsFramework, Mod->IsExplicit, Mod->IsSystem, Mod->IsExternC, Mod->InferSubmodules, Mod->InferExplicitSubmodules, Mod->InferExportWildcard, Mod->ConfigMacrosExhaustive, Mod->ModuleMapIsPrivate}; Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name); } // Emit the requirements. for (const auto &R : Mod->Requirements) { RecordData::value_type Record[] = {SUBMODULE_REQUIRES, R.second}; Stream.EmitRecordWithBlob(RequiresAbbrev, Record, R.first); } // Emit the umbrella header, if there is one. if (auto UmbrellaHeader = Mod->getUmbrellaHeader()) { RecordData::value_type Record[] = {SUBMODULE_UMBRELLA_HEADER}; Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record, UmbrellaHeader.NameAsWritten); } else if (auto UmbrellaDir = Mod->getUmbrellaDir()) { RecordData::value_type Record[] = {SUBMODULE_UMBRELLA_DIR}; Stream.EmitRecordWithBlob(UmbrellaDirAbbrev, Record, UmbrellaDir.NameAsWritten); } // Emit the headers. struct { unsigned RecordKind; unsigned Abbrev; Module::HeaderKind HeaderKind; } HeaderLists[] = { {SUBMODULE_HEADER, HeaderAbbrev, Module::HK_Normal}, {SUBMODULE_TEXTUAL_HEADER, TextualHeaderAbbrev, Module::HK_Textual}, {SUBMODULE_PRIVATE_HEADER, PrivateHeaderAbbrev, Module::HK_Private}, {SUBMODULE_PRIVATE_TEXTUAL_HEADER, PrivateTextualHeaderAbbrev, Module::HK_PrivateTextual}, {SUBMODULE_EXCLUDED_HEADER, ExcludedHeaderAbbrev, Module::HK_Excluded} }; for (auto &HL : HeaderLists) { RecordData::value_type Record[] = {HL.RecordKind}; for (auto &H : Mod->Headers[HL.HeaderKind]) Stream.EmitRecordWithBlob(HL.Abbrev, Record, H.NameAsWritten); } // Emit the top headers. { auto TopHeaders = Mod->getTopHeaders(PP->getFileManager()); RecordData::value_type Record[] = {SUBMODULE_TOPHEADER}; for (auto *H : TopHeaders) Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record, H->getName()); } // Emit the imports. if (!Mod->Imports.empty()) { RecordData Record; for (auto *I : Mod->Imports) Record.push_back(getSubmoduleID(I)); Stream.EmitRecord(SUBMODULE_IMPORTS, Record); } // Emit the exports. if (!Mod->Exports.empty()) { RecordData Record; for (const auto &E : Mod->Exports) { // FIXME: This may fail; we don't require that all exported modules // are local or imported. Record.push_back(getSubmoduleID(E.getPointer())); Record.push_back(E.getInt()); } Stream.EmitRecord(SUBMODULE_EXPORTS, Record); } //FIXME: How do we emit the 'use'd modules? They may not be submodules. // Might be unnecessary as use declarations are only used to build the // module itself. // Emit the link libraries. for (const auto &LL : Mod->LinkLibraries) { RecordData::value_type Record[] = {SUBMODULE_LINK_LIBRARY, LL.IsFramework}; Stream.EmitRecordWithBlob(LinkLibraryAbbrev, Record, LL.Library); } // Emit the conflicts. for (const auto &C : Mod->Conflicts) { // FIXME: This may fail; we don't require that all conflicting modules // are local or imported. RecordData::value_type Record[] = {SUBMODULE_CONFLICT, getSubmoduleID(C.Other)}; Stream.EmitRecordWithBlob(ConflictAbbrev, Record, C.Message); } // Emit the configuration macros. for (const auto &CM : Mod->ConfigMacros) { RecordData::value_type Record[] = {SUBMODULE_CONFIG_MACRO}; Stream.EmitRecordWithBlob(ConfigMacroAbbrev, Record, CM); } // Emit the initializers, if any. RecordData Inits; for (Decl *D : Context->getModuleInitializers(Mod)) Inits.push_back(GetDeclRef(D)); if (!Inits.empty()) Stream.EmitRecord(SUBMODULE_INITIALIZERS, Inits); // Emit the name of the re-exported module, if any. if (!Mod->ExportAsModule.empty()) { RecordData::value_type Record[] = {SUBMODULE_EXPORT_AS}; Stream.EmitRecordWithBlob(ExportAsAbbrev, Record, Mod->ExportAsModule); } // Queue up the submodules of this module. for (auto *M : Mod->submodules()) Q.push(M); } Stream.ExitBlock(); assert((NextSubmoduleID - FirstSubmoduleID == getNumberOfModules(WritingModule)) && "Wrong # of submodules; found a reference to a non-local, " "non-imported submodule?"); } void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, bool isModule) { llvm::SmallDenseMap DiagStateIDMap; unsigned CurrID = 0; RecordData Record; auto EncodeDiagStateFlags = [](const DiagnosticsEngine::DiagState *DS) -> unsigned { unsigned Result = (unsigned)DS->ExtBehavior; for (unsigned Val : {(unsigned)DS->IgnoreAllWarnings, (unsigned)DS->EnableAllWarnings, (unsigned)DS->WarningsAsErrors, (unsigned)DS->ErrorsAsFatal, (unsigned)DS->SuppressSystemWarnings}) Result = (Result << 1) | Val; return Result; }; unsigned Flags = EncodeDiagStateFlags(Diag.DiagStatesByLoc.FirstDiagState); Record.push_back(Flags); auto AddDiagState = [&](const DiagnosticsEngine::DiagState *State, bool IncludeNonPragmaStates) { // Ensure that the diagnostic state wasn't modified since it was created. // We will not correctly round-trip this information otherwise. assert(Flags == EncodeDiagStateFlags(State) && "diag state flags vary in single AST file"); unsigned &DiagStateID = DiagStateIDMap[State]; Record.push_back(DiagStateID); if (DiagStateID == 0) { DiagStateID = ++CurrID; // Add a placeholder for the number of mappings. auto SizeIdx = Record.size(); Record.emplace_back(); for (const auto &I : *State) { if (I.second.isPragma() || IncludeNonPragmaStates) { Record.push_back(I.first); Record.push_back(I.second.serialize()); } } // Update the placeholder. Record[SizeIdx] = (Record.size() - SizeIdx) / 2; } }; AddDiagState(Diag.DiagStatesByLoc.FirstDiagState, isModule); // Reserve a spot for the number of locations with state transitions. auto NumLocationsIdx = Record.size(); Record.emplace_back(); // Emit the state transitions. unsigned NumLocations = 0; for (auto &FileIDAndFile : Diag.DiagStatesByLoc.Files) { if (!FileIDAndFile.first.isValid() || !FileIDAndFile.second.HasLocalTransitions) continue; ++NumLocations; SourceLocation Loc = Diag.SourceMgr->getComposedLoc(FileIDAndFile.first, 0); assert(!Loc.isInvalid() && "start loc for valid FileID is invalid"); AddSourceLocation(Loc, Record); Record.push_back(FileIDAndFile.second.StateTransitions.size()); for (auto &StatePoint : FileIDAndFile.second.StateTransitions) { Record.push_back(StatePoint.Offset); AddDiagState(StatePoint.State, false); } } // Backpatch the number of locations. Record[NumLocationsIdx] = NumLocations; // Emit CurDiagStateLoc. Do it last in order to match source order. // // This also protects against a hypothetical corner case with simulating // -Werror settings for implicit modules in the ASTReader, where reading // CurDiagState out of context could change whether warning pragmas are // treated as errors. AddSourceLocation(Diag.DiagStatesByLoc.CurDiagStateLoc, Record); AddDiagState(Diag.DiagStatesByLoc.CurDiagState, false); Stream.EmitRecord(DIAG_PRAGMA_MAPPINGS, Record); } //===----------------------------------------------------------------------===// // Type Serialization //===----------------------------------------------------------------------===// /// Write the representation of a type to the AST stream. void ASTWriter::WriteType(QualType T) { TypeIdx &IdxRef = TypeIdxs[T]; if (IdxRef.getIndex() == 0) // we haven't seen this type before. IdxRef = TypeIdx(NextTypeID++); TypeIdx Idx = IdxRef; assert(Idx.getIndex() >= FirstTypeID && "Re-writing a type from a prior AST"); RecordData Record; // Emit the type's representation. ASTTypeWriter W(*this, Record); W.Visit(T); uint64_t Offset = W.Emit(); // Record the offset for this type. unsigned Index = Idx.getIndex() - FirstTypeID; if (TypeOffsets.size() == Index) TypeOffsets.push_back(Offset); else if (TypeOffsets.size() < Index) { TypeOffsets.resize(Index + 1); TypeOffsets[Index] = Offset; } else { llvm_unreachable("Types emitted in wrong order"); } } //===----------------------------------------------------------------------===// // Declaration Serialization //===----------------------------------------------------------------------===// /// Write the block containing all of the declaration IDs /// lexically declared within the given DeclContext. /// /// \returns the offset of the DECL_CONTEXT_LEXICAL block within the /// bitstream, or 0 if no block was written. uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC) { if (DC->decls_empty()) return 0; uint64_t Offset = Stream.GetCurrentBitNo(); SmallVector KindDeclPairs; for (const auto *D : DC->decls()) { KindDeclPairs.push_back(D->getKind()); KindDeclPairs.push_back(GetDeclRef(D)); } ++NumLexicalDeclContexts; RecordData::value_type Record[] = {DECL_CONTEXT_LEXICAL}; Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, bytes(KindDeclPairs)); return Offset; } void ASTWriter::WriteTypeDeclOffsets() { using namespace llvm; // Write the type offsets array auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(TYPE_OFFSET)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // base type index Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); { RecordData::value_type Record[] = {TYPE_OFFSET, TypeOffsets.size(), FirstTypeID - NUM_PREDEF_TYPE_IDS}; Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, bytes(TypeOffsets)); } // Write the declaration offsets array Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(DECL_OFFSET)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // base decl ID Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); { RecordData::value_type Record[] = {DECL_OFFSET, DeclOffsets.size(), FirstDeclID - NUM_PREDEF_DECL_IDS}; Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, bytes(DeclOffsets)); } } void ASTWriter::WriteFileDeclIDsMap() { using namespace llvm; SmallVector, 64> SortedFileDeclIDs( FileDeclIDs.begin(), FileDeclIDs.end()); llvm::sort(SortedFileDeclIDs.begin(), SortedFileDeclIDs.end(), llvm::less_first()); // Join the vectors of DeclIDs from all files. SmallVector FileGroupedDeclIDs; for (auto &FileDeclEntry : SortedFileDeclIDs) { DeclIDInFileInfo &Info = *FileDeclEntry.second; Info.FirstDeclIndex = FileGroupedDeclIDs.size(); for (auto &LocDeclEntry : Info.DeclIDs) FileGroupedDeclIDs.push_back(LocDeclEntry.second); } auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(FILE_SORTED_DECLS)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev)); RecordData::value_type Record[] = {FILE_SORTED_DECLS, FileGroupedDeclIDs.size()}; Stream.EmitRecordWithBlob(AbbrevCode, Record, bytes(FileGroupedDeclIDs)); } void ASTWriter::WriteComments() { Stream.EnterSubblock(COMMENTS_BLOCK_ID, 3); auto _ = llvm::make_scope_exit([this] { Stream.ExitBlock(); }); if (!PP->getPreprocessorOpts().WriteCommentListToPCH) return; ArrayRef RawComments = Context->Comments.getComments(); RecordData Record; for (const auto *I : RawComments) { Record.clear(); AddSourceRange(I->getSourceRange(), Record); Record.push_back(I->getKind()); Record.push_back(I->isTrailingComment()); Record.push_back(I->isAlmostTrailingComment()); Stream.EmitRecord(COMMENTS_RAW_COMMENT, Record); } } //===----------------------------------------------------------------------===// // Global Method Pool and Selector Serialization //===----------------------------------------------------------------------===// namespace { // Trait used for the on-disk hash table used in the method pool. class ASTMethodPoolTrait { ASTWriter &Writer; public: using key_type = Selector; using key_type_ref = key_type; struct data_type { SelectorID ID; ObjCMethodList Instance, Factory; }; using data_type_ref = const data_type &; using hash_value_type = unsigned; using offset_type = unsigned; explicit ASTMethodPoolTrait(ASTWriter &Writer) : Writer(Writer) {} static hash_value_type ComputeHash(Selector Sel) { return serialization::ComputeHash(Sel); } std::pair EmitKeyDataLength(raw_ostream& Out, Selector Sel, data_type_ref Methods) { using namespace llvm::support; endian::Writer LE(Out, little); unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4); LE.write(KeyLen); unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts for (const ObjCMethodList *Method = &Methods.Instance; Method; Method = Method->getNext()) if (Method->getMethod()) DataLen += 4; for (const ObjCMethodList *Method = &Methods.Factory; Method; Method = Method->getNext()) if (Method->getMethod()) DataLen += 4; LE.write(DataLen); return std::make_pair(KeyLen, DataLen); } void EmitKey(raw_ostream& Out, Selector Sel, unsigned) { using namespace llvm::support; endian::Writer LE(Out, little); uint64_t Start = Out.tell(); assert((Start >> 32) == 0 && "Selector key offset too large"); Writer.SetSelectorOffset(Sel, Start); unsigned N = Sel.getNumArgs(); LE.write(N); if (N == 0) N = 1; for (unsigned I = 0; I != N; ++I) LE.write( Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I))); } void EmitData(raw_ostream& Out, key_type_ref, data_type_ref Methods, unsigned DataLen) { using namespace llvm::support; endian::Writer LE(Out, little); uint64_t Start = Out.tell(); (void)Start; LE.write(Methods.ID); unsigned NumInstanceMethods = 0; for (const ObjCMethodList *Method = &Methods.Instance; Method; Method = Method->getNext()) if (Method->getMethod()) ++NumInstanceMethods; unsigned NumFactoryMethods = 0; for (const ObjCMethodList *Method = &Methods.Factory; Method; Method = Method->getNext()) if (Method->getMethod()) ++NumFactoryMethods; unsigned InstanceBits = Methods.Instance.getBits(); assert(InstanceBits < 4); unsigned InstanceHasMoreThanOneDeclBit = Methods.Instance.hasMoreThanOneDecl(); unsigned FullInstanceBits = (NumInstanceMethods << 3) | (InstanceHasMoreThanOneDeclBit << 2) | InstanceBits; unsigned FactoryBits = Methods.Factory.getBits(); assert(FactoryBits < 4); unsigned FactoryHasMoreThanOneDeclBit = Methods.Factory.hasMoreThanOneDecl(); unsigned FullFactoryBits = (NumFactoryMethods << 3) | (FactoryHasMoreThanOneDeclBit << 2) | FactoryBits; LE.write(FullInstanceBits); LE.write(FullFactoryBits); for (const ObjCMethodList *Method = &Methods.Instance; Method; Method = Method->getNext()) if (Method->getMethod()) LE.write(Writer.getDeclID(Method->getMethod())); for (const ObjCMethodList *Method = &Methods.Factory; Method; Method = Method->getNext()) if (Method->getMethod()) LE.write(Writer.getDeclID(Method->getMethod())); assert(Out.tell() - Start == DataLen && "Data length is wrong"); } }; } // namespace /// Write ObjC data: selectors and the method pool. /// /// The method pool contains both instance and factory methods, stored /// in an on-disk hash table indexed by the selector. The hash table also /// contains an empty entry for every other selector known to Sema. void ASTWriter::WriteSelectors(Sema &SemaRef) { using namespace llvm; // Do we have to do anything at all? if (SemaRef.MethodPool.empty() && SelectorIDs.empty()) return; unsigned NumTableEntries = 0; // Create and write out the blob that contains selectors and the method pool. { llvm::OnDiskChainedHashTableGenerator Generator; ASTMethodPoolTrait Trait(*this); // Create the on-disk hash table representation. We walk through every // selector we've seen and look it up in the method pool. SelectorOffsets.resize(NextSelectorID - FirstSelectorID); for (auto &SelectorAndID : SelectorIDs) { Selector S = SelectorAndID.first; SelectorID ID = SelectorAndID.second; Sema::GlobalMethodPool::iterator F = SemaRef.MethodPool.find(S); ASTMethodPoolTrait::data_type Data = { ID, ObjCMethodList(), ObjCMethodList() }; if (F != SemaRef.MethodPool.end()) { Data.Instance = F->second.first; Data.Factory = F->second.second; } // Only write this selector if it's not in an existing AST or something // changed. if (Chain && ID < FirstSelectorID) { // Selector already exists. Did it change? bool changed = false; for (ObjCMethodList *M = &Data.Instance; !changed && M && M->getMethod(); M = M->getNext()) { if (!M->getMethod()->isFromASTFile()) changed = true; } for (ObjCMethodList *M = &Data.Factory; !changed && M && M->getMethod(); M = M->getNext()) { if (!M->getMethod()->isFromASTFile()) changed = true; } if (!changed) continue; } else if (Data.Instance.getMethod() || Data.Factory.getMethod()) { // A new method pool entry. ++NumTableEntries; } Generator.insert(S, Data, Trait); } // Create the on-disk hash table in a buffer. SmallString<4096> MethodPool; uint32_t BucketOffset; { using namespace llvm::support; ASTMethodPoolTrait Trait(*this); llvm::raw_svector_ostream Out(MethodPool); // Make sure that no bucket is at offset 0 endian::write(Out, 0, little); BucketOffset = Generator.Emit(Out, Trait); } // Create a blob abbreviation auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(METHOD_POOL)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned MethodPoolAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); // Write the method pool { RecordData::value_type Record[] = {METHOD_POOL, BucketOffset, NumTableEntries}; Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool); } // Create a blob abbreviation for the selector table offsets. Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(SELECTOR_OFFSETS)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); // Write the selector offsets table. { RecordData::value_type Record[] = { SELECTOR_OFFSETS, SelectorOffsets.size(), FirstSelectorID - NUM_PREDEF_SELECTOR_IDS}; Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record, bytes(SelectorOffsets)); } } } /// Write the selectors referenced in @selector expression into AST file. void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) { using namespace llvm; if (SemaRef.ReferencedSelectors.empty()) return; RecordData Record; ASTRecordWriter Writer(*this, Record); // Note: this writes out all references even for a dependent AST. But it is // very tricky to fix, and given that @selector shouldn't really appear in // headers, probably not worth it. It's not a correctness issue. for (auto &SelectorAndLocation : SemaRef.ReferencedSelectors) { Selector Sel = SelectorAndLocation.first; SourceLocation Loc = SelectorAndLocation.second; Writer.AddSelectorRef(Sel); Writer.AddSourceLocation(Loc); } Writer.Emit(REFERENCED_SELECTOR_POOL); } //===----------------------------------------------------------------------===// // Identifier Table Serialization //===----------------------------------------------------------------------===// /// Determine the declaration that should be put into the name lookup table to /// represent the given declaration in this module. This is usually D itself, /// but if D was imported and merged into a local declaration, we want the most /// recent local declaration instead. The chosen declaration will be the most /// recent declaration in any module that imports this one. static NamedDecl *getDeclForLocalLookup(const LangOptions &LangOpts, NamedDecl *D) { if (!LangOpts.Modules || !D->isFromASTFile()) return D; if (Decl *Redecl = D->getPreviousDecl()) { // For Redeclarable decls, a prior declaration might be local. for (; Redecl; Redecl = Redecl->getPreviousDecl()) { // If we find a local decl, we're done. if (!Redecl->isFromASTFile()) { // Exception: in very rare cases (for injected-class-names), not all // redeclarations are in the same semantic context. Skip ones in a // different context. They don't go in this lookup table at all. if (!Redecl->getDeclContext()->getRedeclContext()->Equals( D->getDeclContext()->getRedeclContext())) continue; return cast(Redecl); } // If we find a decl from a (chained-)PCH stop since we won't find a // local one. if (Redecl->getOwningModuleID() == 0) break; } } else if (Decl *First = D->getCanonicalDecl()) { // For Mergeable decls, the first decl might be local. if (!First->isFromASTFile()) return cast(First); } // All declarations are imported. Our most recent declaration will also be // the most recent one in anyone who imports us. return D; } namespace { class ASTIdentifierTableTrait { ASTWriter &Writer; Preprocessor &PP; IdentifierResolver &IdResolver; bool IsModule; bool NeedDecls; ASTWriter::RecordData *InterestingIdentifierOffsets; /// Determines whether this is an "interesting" identifier that needs a /// full IdentifierInfo structure written into the hash table. Notably, this /// doesn't check whether the name has macros defined; use PublicMacroIterator /// to check that. bool isInterestingIdentifier(const IdentifierInfo *II, uint64_t MacroOffset) { if (MacroOffset || II->isPoisoned() || (IsModule ? II->hasRevertedBuiltin() : II->getObjCOrBuiltinID()) || II->hasRevertedTokenIDToIdentifier() || (NeedDecls && II->getFETokenInfo())) return true; return false; } public: using key_type = IdentifierInfo *; using key_type_ref = key_type; using data_type = IdentID; using data_type_ref = data_type; using hash_value_type = unsigned; using offset_type = unsigned; ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP, IdentifierResolver &IdResolver, bool IsModule, ASTWriter::RecordData *InterestingIdentifierOffsets) : Writer(Writer), PP(PP), IdResolver(IdResolver), IsModule(IsModule), NeedDecls(!IsModule || !Writer.getLangOpts().CPlusPlus), InterestingIdentifierOffsets(InterestingIdentifierOffsets) {} bool needDecls() const { return NeedDecls; } static hash_value_type ComputeHash(const IdentifierInfo* II) { return llvm::djbHash(II->getName()); } bool isInterestingIdentifier(const IdentifierInfo *II) { auto MacroOffset = Writer.getMacroDirectivesOffset(II); return isInterestingIdentifier(II, MacroOffset); } bool isInterestingNonMacroIdentifier(const IdentifierInfo *II) { return isInterestingIdentifier(II, 0); } std::pair EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) { unsigned KeyLen = II->getLength() + 1; unsigned DataLen = 4; // 4 bytes for the persistent ID << 1 auto MacroOffset = Writer.getMacroDirectivesOffset(II); if (isInterestingIdentifier(II, MacroOffset)) { DataLen += 2; // 2 bytes for builtin ID DataLen += 2; // 2 bytes for flags if (MacroOffset) DataLen += 4; // MacroDirectives offset. if (NeedDecls) { for (IdentifierResolver::iterator D = IdResolver.begin(II), DEnd = IdResolver.end(); D != DEnd; ++D) DataLen += 4; } } using namespace llvm::support; endian::Writer LE(Out, little); assert((uint16_t)DataLen == DataLen && (uint16_t)KeyLen == KeyLen); LE.write(DataLen); // We emit the key length after the data length so that every // string is preceded by a 16-bit length. This matches the PTH // format for storing identifiers. LE.write(KeyLen); return std::make_pair(KeyLen, DataLen); } void EmitKey(raw_ostream& Out, const IdentifierInfo* II, unsigned KeyLen) { // Record the location of the key data. This is used when generating // the mapping from persistent IDs to strings. Writer.SetIdentifierOffset(II, Out.tell()); // Emit the offset of the key/data length information to the interesting // identifiers table if necessary. if (InterestingIdentifierOffsets && isInterestingIdentifier(II)) InterestingIdentifierOffsets->push_back(Out.tell() - 4); Out.write(II->getNameStart(), KeyLen); } void EmitData(raw_ostream& Out, IdentifierInfo* II, IdentID ID, unsigned) { using namespace llvm::support; endian::Writer LE(Out, little); auto MacroOffset = Writer.getMacroDirectivesOffset(II); if (!isInterestingIdentifier(II, MacroOffset)) { LE.write(ID << 1); return; } LE.write((ID << 1) | 0x01); uint32_t Bits = (uint32_t)II->getObjCOrBuiltinID(); assert((Bits & 0xffff) == Bits && "ObjCOrBuiltinID too big for ASTReader."); LE.write(Bits); Bits = 0; bool HadMacroDefinition = MacroOffset != 0; Bits = (Bits << 1) | unsigned(HadMacroDefinition); Bits = (Bits << 1) | unsigned(II->isExtensionToken()); Bits = (Bits << 1) | unsigned(II->isPoisoned()); Bits = (Bits << 1) | unsigned(II->hasRevertedBuiltin()); Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier()); Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword()); LE.write(Bits); if (HadMacroDefinition) LE.write(MacroOffset); if (NeedDecls) { // Emit the declaration IDs in reverse order, because the // IdentifierResolver provides the declarations as they would be // visible (e.g., the function "stat" would come before the struct // "stat"), but the ASTReader adds declarations to the end of the list // (so we need to see the struct "stat" before the function "stat"). // Only emit declarations that aren't from a chained PCH, though. SmallVector Decls(IdResolver.begin(II), IdResolver.end()); for (SmallVectorImpl::reverse_iterator D = Decls.rbegin(), DEnd = Decls.rend(); D != DEnd; ++D) LE.write( Writer.getDeclID(getDeclForLocalLookup(PP.getLangOpts(), *D))); } } }; } // namespace /// Write the identifier table into the AST file. /// /// The identifier table consists of a blob containing string data /// (the actual identifiers themselves) and a separate "offsets" index /// that maps identifier IDs to locations within the blob. void ASTWriter::WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver, bool IsModule) { using namespace llvm; RecordData InterestingIdents; // Create and write out the blob that contains the identifier // strings. { llvm::OnDiskChainedHashTableGenerator Generator; ASTIdentifierTableTrait Trait( *this, PP, IdResolver, IsModule, (getLangOpts().CPlusPlus && IsModule) ? &InterestingIdents : nullptr); // Look for any identifiers that were named while processing the // headers, but are otherwise not needed. We add these to the hash // table to enable checking of the predefines buffer in the case // where the user adds new macro definitions when building the AST // file. SmallVector IIs; for (const auto &ID : PP.getIdentifierTable()) IIs.push_back(ID.second); // Sort the identifiers lexicographically before getting them references so // that their order is stable. llvm::sort(IIs.begin(), IIs.end(), llvm::less_ptr()); for (const IdentifierInfo *II : IIs) if (Trait.isInterestingNonMacroIdentifier(II)) getIdentifierRef(II); // Create the on-disk hash table representation. We only store offsets // for identifiers that appear here for the first time. IdentifierOffsets.resize(NextIdentID - FirstIdentID); for (auto IdentIDPair : IdentifierIDs) { auto *II = const_cast(IdentIDPair.first); IdentID ID = IdentIDPair.second; assert(II && "NULL identifier in identifier table"); // Write out identifiers if either the ID is local or the identifier has // changed since it was loaded. if (ID >= FirstIdentID || !Chain || !II->isFromAST() || II->hasChangedSinceDeserialization() || (Trait.needDecls() && II->hasFETokenInfoChangedSinceDeserialization())) Generator.insert(II, ID, Trait); } // Create the on-disk hash table in a buffer. SmallString<4096> IdentifierTable; uint32_t BucketOffset; { using namespace llvm::support; llvm::raw_svector_ostream Out(IdentifierTable); // Make sure that no bucket is at offset 0 endian::write(Out, 0, little); BucketOffset = Generator.Emit(Out, Trait); } // Create a blob abbreviation auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_TABLE)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned IDTableAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); // Write the identifier table RecordData::value_type Record[] = {IDENTIFIER_TABLE, BucketOffset}; Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable); } // Write the offsets table for identifier IDs. auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_OFFSET)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of identifiers Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned IdentifierOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); #ifndef NDEBUG for (unsigned I = 0, N = IdentifierOffsets.size(); I != N; ++I) assert(IdentifierOffsets[I] && "Missing identifier offset?"); #endif RecordData::value_type Record[] = {IDENTIFIER_OFFSET, IdentifierOffsets.size(), FirstIdentID - NUM_PREDEF_IDENT_IDS}; Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record, bytes(IdentifierOffsets)); // In C++, write the list of interesting identifiers (those that are // defined as macros, poisoned, or similar unusual things). if (!InterestingIdents.empty()) Stream.EmitRecord(INTERESTING_IDENTIFIERS, InterestingIdents); } //===----------------------------------------------------------------------===// // DeclContext's Name Lookup Table Serialization //===----------------------------------------------------------------------===// namespace { // Trait used for the on-disk hash table used in the method pool. class ASTDeclContextNameLookupTrait { ASTWriter &Writer; llvm::SmallVector DeclIDs; public: using key_type = DeclarationNameKey; using key_type_ref = key_type; /// A start and end index into DeclIDs, representing a sequence of decls. using data_type = std::pair; using data_type_ref = const data_type &; using hash_value_type = unsigned; using offset_type = unsigned; explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : Writer(Writer) {} template data_type getData(const Coll &Decls) { unsigned Start = DeclIDs.size(); for (NamedDecl *D : Decls) { DeclIDs.push_back( Writer.GetDeclRef(getDeclForLocalLookup(Writer.getLangOpts(), D))); } return std::make_pair(Start, DeclIDs.size()); } data_type ImportData(const reader::ASTDeclContextNameLookupTrait::data_type &FromReader) { unsigned Start = DeclIDs.size(); for (auto ID : FromReader) DeclIDs.push_back(ID); return std::make_pair(Start, DeclIDs.size()); } static bool EqualKey(key_type_ref a, key_type_ref b) { return a == b; } hash_value_type ComputeHash(DeclarationNameKey Name) { return Name.getHash(); } void EmitFileRef(raw_ostream &Out, ModuleFile *F) const { assert(Writer.hasChain() && "have reference to loaded module file but no chain?"); using namespace llvm::support; endian::write(Out, Writer.getChain()->getModuleFileID(F), little); } std::pair EmitKeyDataLength(raw_ostream &Out, DeclarationNameKey Name, data_type_ref Lookup) { using namespace llvm::support; endian::Writer LE(Out, little); unsigned KeyLen = 1; switch (Name.getKind()) { case DeclarationName::Identifier: case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: case DeclarationName::CXXLiteralOperatorName: case DeclarationName::CXXDeductionGuideName: KeyLen += 4; break; case DeclarationName::CXXOperatorName: KeyLen += 1; break; case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXConversionFunctionName: case DeclarationName::CXXUsingDirective: break; } LE.write(KeyLen); // 4 bytes for each DeclID. unsigned DataLen = 4 * (Lookup.second - Lookup.first); assert(uint16_t(DataLen) == DataLen && "too many decls for serialized lookup result"); LE.write(DataLen); return std::make_pair(KeyLen, DataLen); } void EmitKey(raw_ostream &Out, DeclarationNameKey Name, unsigned) { using namespace llvm::support; endian::Writer LE(Out, little); LE.write(Name.getKind()); switch (Name.getKind()) { case DeclarationName::Identifier: case DeclarationName::CXXLiteralOperatorName: case DeclarationName::CXXDeductionGuideName: LE.write(Writer.getIdentifierRef(Name.getIdentifier())); return; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: LE.write(Writer.getSelectorRef(Name.getSelector())); return; case DeclarationName::CXXOperatorName: assert(Name.getOperatorKind() < NUM_OVERLOADED_OPERATORS && "Invalid operator?"); LE.write(Name.getOperatorKind()); return; case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXConversionFunctionName: case DeclarationName::CXXUsingDirective: return; } llvm_unreachable("Invalid name kind?"); } void EmitData(raw_ostream &Out, key_type_ref, data_type Lookup, unsigned DataLen) { using namespace llvm::support; endian::Writer LE(Out, little); uint64_t Start = Out.tell(); (void)Start; for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I) LE.write(DeclIDs[I]); assert(Out.tell() - Start == DataLen && "Data length is wrong"); } }; } // namespace bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result, DeclContext *DC) { return Result.hasExternalDecls() && DC->NeedToReconcileExternalVisibleStorage; } bool ASTWriter::isLookupResultEntirelyExternal(StoredDeclsList &Result, DeclContext *DC) { for (auto *D : Result.getLookupResult()) if (!getDeclForLocalLookup(getLangOpts(), D)->isFromASTFile()) return false; return true; } void ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC, llvm::SmallVectorImpl &LookupTable) { assert(!ConstDC->HasLazyLocalLexicalLookups && !ConstDC->HasLazyExternalLexicalLookups && "must call buildLookups first"); // FIXME: We need to build the lookups table, which is logically const. auto *DC = const_cast(ConstDC); assert(DC == DC->getPrimaryContext() && "only primary DC has lookup table"); // Create the on-disk hash table representation. MultiOnDiskHashTableGenerator Generator; ASTDeclContextNameLookupTrait Trait(*this); // The first step is to collect the declaration names which we need to // serialize into the name lookup table, and to collect them in a stable // order. SmallVector Names; // We also build up small sets of the constructor and conversion function // names which are visible. llvm::SmallSet ConstructorNameSet, ConversionNameSet; for (auto &Lookup : *DC->buildLookup()) { auto &Name = Lookup.first; auto &Result = Lookup.second; // If there are no local declarations in our lookup result, we // don't need to write an entry for the name at all. If we can't // write out a lookup set without performing more deserialization, // just skip this entry. if (isLookupResultExternal(Result, DC) && isLookupResultEntirelyExternal(Result, DC)) continue; // We also skip empty results. If any of the results could be external and // the currently available results are empty, then all of the results are // external and we skip it above. So the only way we get here with an empty // results is when no results could have been external *and* we have // external results. // // FIXME: While we might want to start emitting on-disk entries for negative // lookups into a decl context as an optimization, today we *have* to skip // them because there are names with empty lookup results in decl contexts // which we can't emit in any stable ordering: we lookup constructors and // conversion functions in the enclosing namespace scope creating empty // results for them. This in almost certainly a bug in Clang's name lookup, // but that is likely to be hard or impossible to fix and so we tolerate it // here by omitting lookups with empty results. if (Lookup.second.getLookupResult().empty()) continue; switch (Lookup.first.getNameKind()) { default: Names.push_back(Lookup.first); break; case DeclarationName::CXXConstructorName: assert(isa(DC) && "Cannot have a constructor name outside of a class!"); ConstructorNameSet.insert(Name); break; case DeclarationName::CXXConversionFunctionName: assert(isa(DC) && "Cannot have a conversion function name outside of a class!"); ConversionNameSet.insert(Name); break; } } // Sort the names into a stable order. llvm::sort(Names.begin(), Names.end()); if (auto *D = dyn_cast(DC)) { // We need to establish an ordering of constructor and conversion function // names, and they don't have an intrinsic ordering. // First we try the easy case by forming the current context's constructor // name and adding that name first. This is a very useful optimization to // avoid walking the lexical declarations in many cases, and it also // handles the only case where a constructor name can come from some other // lexical context -- when that name is an implicit constructor merged from // another declaration in the redecl chain. Any non-implicit constructor or // conversion function which doesn't occur in all the lexical contexts // would be an ODR violation. auto ImplicitCtorName = Context->DeclarationNames.getCXXConstructorName( Context->getCanonicalType(Context->getRecordType(D))); if (ConstructorNameSet.erase(ImplicitCtorName)) Names.push_back(ImplicitCtorName); // If we still have constructors or conversion functions, we walk all the // names in the decl and add the constructors and conversion functions // which are visible in the order they lexically occur within the context. if (!ConstructorNameSet.empty() || !ConversionNameSet.empty()) for (Decl *ChildD : cast(DC)->decls()) if (auto *ChildND = dyn_cast(ChildD)) { auto Name = ChildND->getDeclName(); switch (Name.getNameKind()) { default: continue; case DeclarationName::CXXConstructorName: if (ConstructorNameSet.erase(Name)) Names.push_back(Name); break; case DeclarationName::CXXConversionFunctionName: if (ConversionNameSet.erase(Name)) Names.push_back(Name); break; } if (ConstructorNameSet.empty() && ConversionNameSet.empty()) break; } assert(ConstructorNameSet.empty() && "Failed to find all of the visible " "constructors by walking all the " "lexical members of the context."); assert(ConversionNameSet.empty() && "Failed to find all of the visible " "conversion functions by walking all " "the lexical members of the context."); } // Next we need to do a lookup with each name into this decl context to fully // populate any results from external sources. We don't actually use the // results of these lookups because we only want to use the results after all // results have been loaded and the pointers into them will be stable. for (auto &Name : Names) DC->lookup(Name); // Now we need to insert the results for each name into the hash table. For // constructor names and conversion function names, we actually need to merge // all of the results for them into one list of results each and insert // those. SmallVector ConstructorDecls; SmallVector ConversionDecls; // Now loop over the names, either inserting them or appending for the two // special cases. for (auto &Name : Names) { DeclContext::lookup_result Result = DC->noload_lookup(Name); switch (Name.getNameKind()) { default: Generator.insert(Name, Trait.getData(Result), Trait); break; case DeclarationName::CXXConstructorName: ConstructorDecls.append(Result.begin(), Result.end()); break; case DeclarationName::CXXConversionFunctionName: ConversionDecls.append(Result.begin(), Result.end()); break; } } // Handle our two special cases if we ended up having any. We arbitrarily use // the first declaration's name here because the name itself isn't part of // the key, only the kind of name is used. if (!ConstructorDecls.empty()) Generator.insert(ConstructorDecls.front()->getDeclName(), Trait.getData(ConstructorDecls), Trait); if (!ConversionDecls.empty()) Generator.insert(ConversionDecls.front()->getDeclName(), Trait.getData(ConversionDecls), Trait); // Create the on-disk hash table. Also emit the existing imported and // merged table if there is one. auto *Lookups = Chain ? Chain->getLoadedLookupTables(DC) : nullptr; Generator.emit(LookupTable, Trait, Lookups ? &Lookups->Table : nullptr); } /// Write the block containing all of the declaration IDs /// visible from the given DeclContext. /// /// \returns the offset of the DECL_CONTEXT_VISIBLE block within the /// bitstream, or 0 if no block was written. uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC) { // If we imported a key declaration of this namespace, write the visible // lookup results as an update record for it rather than including them // on this declaration. We will only look at key declarations on reload. if (isa(DC) && Chain && Chain->getKeyDeclaration(cast(DC))->isFromASTFile()) { // Only do this once, for the first local declaration of the namespace. for (auto *Prev = cast(DC)->getPreviousDecl(); Prev; Prev = Prev->getPreviousDecl()) if (!Prev->isFromASTFile()) return 0; // Note that we need to emit an update record for the primary context. UpdatedDeclContexts.insert(DC->getPrimaryContext()); // Make sure all visible decls are written. They will be recorded later. We // do this using a side data structure so we can sort the names into // a deterministic order. StoredDeclsMap *Map = DC->getPrimaryContext()->buildLookup(); SmallVector, 16> LookupResults; if (Map) { LookupResults.reserve(Map->size()); for (auto &Entry : *Map) LookupResults.push_back( std::make_pair(Entry.first, Entry.second.getLookupResult())); } llvm::sort(LookupResults.begin(), LookupResults.end(), llvm::less_first()); for (auto &NameAndResult : LookupResults) { DeclarationName Name = NameAndResult.first; DeclContext::lookup_result Result = NameAndResult.second; if (Name.getNameKind() == DeclarationName::CXXConstructorName || Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { // We have to work around a name lookup bug here where negative lookup // results for these names get cached in namespace lookup tables (these // names should never be looked up in a namespace). assert(Result.empty() && "Cannot have a constructor or conversion " "function name in a namespace!"); continue; } for (NamedDecl *ND : Result) if (!ND->isFromASTFile()) GetDeclRef(ND); } return 0; } if (DC->getPrimaryContext() != DC) return 0; // Skip contexts which don't support name lookup. if (!DC->isLookupContext()) return 0; // If not in C++, we perform name lookup for the translation unit via the // IdentifierInfo chains, don't bother to build a visible-declarations table. if (DC->isTranslationUnit() && !Context.getLangOpts().CPlusPlus) return 0; // Serialize the contents of the mapping used for lookup. Note that, // although we have two very different code paths, the serialized // representation is the same for both cases: a declaration name, // followed by a size, followed by references to the visible // declarations that have that name. uint64_t Offset = Stream.GetCurrentBitNo(); StoredDeclsMap *Map = DC->buildLookup(); if (!Map || Map->empty()) return 0; // Create the on-disk hash table in a buffer. SmallString<4096> LookupTable; GenerateNameLookupTable(DC, LookupTable); // Write the lookup table RecordData::value_type Record[] = {DECL_CONTEXT_VISIBLE}; Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record, LookupTable); ++NumVisibleDeclContexts; return Offset; } /// Write an UPDATE_VISIBLE block for the given context. /// /// UPDATE_VISIBLE blocks contain the declarations that are added to an existing /// DeclContext in a dependent AST file. As such, they only exist for the TU /// (in C++), for namespaces, and for classes with forward-declared unscoped /// enumeration members (in C++11). void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) { StoredDeclsMap *Map = DC->getLookupPtr(); if (!Map || Map->empty()) return; // Create the on-disk hash table in a buffer. SmallString<4096> LookupTable; GenerateNameLookupTable(DC, LookupTable); // If we're updating a namespace, select a key declaration as the key for the // update record; those are the only ones that will be checked on reload. if (isa(DC)) DC = cast(Chain->getKeyDeclaration(cast(DC))); // Write the lookup table RecordData::value_type Record[] = {UPDATE_VISIBLE, getDeclID(cast(DC))}; Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable); } /// Write an FP_PRAGMA_OPTIONS block for the given FPOptions. void ASTWriter::WriteFPPragmaOptions(const FPOptions &Opts) { RecordData::value_type Record[] = {Opts.getInt()}; Stream.EmitRecord(FP_PRAGMA_OPTIONS, Record); } /// Write an OPENCL_EXTENSIONS block for the given OpenCLOptions. void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) { if (!SemaRef.Context.getLangOpts().OpenCL) return; const OpenCLOptions &Opts = SemaRef.getOpenCLOptions(); RecordData Record; for (const auto &I:Opts.OptMap) { AddString(I.getKey(), Record); auto V = I.getValue(); Record.push_back(V.Supported ? 1 : 0); Record.push_back(V.Enabled ? 1 : 0); Record.push_back(V.Avail); Record.push_back(V.Core); } Stream.EmitRecord(OPENCL_EXTENSIONS, Record); } void ASTWriter::WriteOpenCLExtensionTypes(Sema &SemaRef) { if (!SemaRef.Context.getLangOpts().OpenCL) return; RecordData Record; for (const auto &I : SemaRef.OpenCLTypeExtMap) { Record.push_back( static_cast(getTypeID(I.first->getCanonicalTypeInternal()))); Record.push_back(I.second.size()); for (auto Ext : I.second) AddString(Ext, Record); } Stream.EmitRecord(OPENCL_EXTENSION_TYPES, Record); } void ASTWriter::WriteOpenCLExtensionDecls(Sema &SemaRef) { if (!SemaRef.Context.getLangOpts().OpenCL) return; RecordData Record; for (const auto &I : SemaRef.OpenCLDeclExtMap) { Record.push_back(getDeclID(I.first)); Record.push_back(static_cast(I.second.size())); for (auto Ext : I.second) AddString(Ext, Record); } Stream.EmitRecord(OPENCL_EXTENSION_DECLS, Record); } void ASTWriter::WriteCUDAPragmas(Sema &SemaRef) { if (SemaRef.ForceCUDAHostDeviceDepth > 0) { RecordData::value_type Record[] = {SemaRef.ForceCUDAHostDeviceDepth}; Stream.EmitRecord(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH, Record); } } void ASTWriter::WriteObjCCategories() { SmallVector CategoriesMap; RecordData Categories; for (unsigned I = 0, N = ObjCClassesWithCategories.size(); I != N; ++I) { unsigned Size = 0; unsigned StartIndex = Categories.size(); ObjCInterfaceDecl *Class = ObjCClassesWithCategories[I]; // Allocate space for the size. Categories.push_back(0); // Add the categories. for (ObjCInterfaceDecl::known_categories_iterator Cat = Class->known_categories_begin(), CatEnd = Class->known_categories_end(); Cat != CatEnd; ++Cat, ++Size) { assert(getDeclID(*Cat) != 0 && "Bogus category"); AddDeclRef(*Cat, Categories); } // Update the size. Categories[StartIndex] = Size; // Record this interface -> category map. ObjCCategoriesInfo CatInfo = { getDeclID(Class), StartIndex }; CategoriesMap.push_back(CatInfo); } // Sort the categories map by the definition ID, since the reader will be // performing binary searches on this information. llvm::array_pod_sort(CategoriesMap.begin(), CategoriesMap.end()); // Emit the categories map. using namespace llvm; auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(OBJC_CATEGORIES_MAP)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned AbbrevID = Stream.EmitAbbrev(std::move(Abbrev)); RecordData::value_type Record[] = {OBJC_CATEGORIES_MAP, CategoriesMap.size()}; Stream.EmitRecordWithBlob(AbbrevID, Record, reinterpret_cast(CategoriesMap.data()), CategoriesMap.size() * sizeof(ObjCCategoriesInfo)); // Emit the category lists. Stream.EmitRecord(OBJC_CATEGORIES, Categories); } void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) { Sema::LateParsedTemplateMapT &LPTMap = SemaRef.LateParsedTemplateMap; if (LPTMap.empty()) return; RecordData Record; for (auto &LPTMapEntry : LPTMap) { const FunctionDecl *FD = LPTMapEntry.first; LateParsedTemplate &LPT = *LPTMapEntry.second; AddDeclRef(FD, Record); AddDeclRef(LPT.D, Record); Record.push_back(LPT.Toks.size()); for (const auto &Tok : LPT.Toks) { AddToken(Tok, Record); } } Stream.EmitRecord(LATE_PARSED_TEMPLATE, Record); } /// Write the state of 'pragma clang optimize' at the end of the module. void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) { RecordData Record; SourceLocation PragmaLoc = SemaRef.getOptimizeOffPragmaLocation(); AddSourceLocation(PragmaLoc, Record); Stream.EmitRecord(OPTIMIZE_PRAGMA_OPTIONS, Record); } /// Write the state of 'pragma ms_struct' at the end of the module. void ASTWriter::WriteMSStructPragmaOptions(Sema &SemaRef) { RecordData Record; Record.push_back(SemaRef.MSStructPragmaOn ? PMSST_ON : PMSST_OFF); Stream.EmitRecord(MSSTRUCT_PRAGMA_OPTIONS, Record); } /// Write the state of 'pragma pointers_to_members' at the end of the //module. void ASTWriter::WriteMSPointersToMembersPragmaOptions(Sema &SemaRef) { RecordData Record; Record.push_back(SemaRef.MSPointerToMemberRepresentationMethod); AddSourceLocation(SemaRef.ImplicitMSInheritanceAttrLoc, Record); Stream.EmitRecord(POINTERS_TO_MEMBERS_PRAGMA_OPTIONS, Record); } /// Write the state of 'pragma pack' at the end of the module. void ASTWriter::WritePackPragmaOptions(Sema &SemaRef) { // Don't serialize pragma pack state for modules, since it should only take // effect on a per-submodule basis. if (WritingModule) return; RecordData Record; Record.push_back(SemaRef.PackStack.CurrentValue); AddSourceLocation(SemaRef.PackStack.CurrentPragmaLocation, Record); Record.push_back(SemaRef.PackStack.Stack.size()); for (const auto &StackEntry : SemaRef.PackStack.Stack) { Record.push_back(StackEntry.Value); AddSourceLocation(StackEntry.PragmaLocation, Record); AddSourceLocation(StackEntry.PragmaPushLocation, Record); AddString(StackEntry.StackSlotLabel, Record); } Stream.EmitRecord(PACK_PRAGMA_OPTIONS, Record); } void ASTWriter::WriteModuleFileExtension(Sema &SemaRef, ModuleFileExtensionWriter &Writer) { // Enter the extension block. Stream.EnterSubblock(EXTENSION_BLOCK_ID, 4); // Emit the metadata record abbreviation. auto Abv = std::make_shared(); Abv->Add(llvm::BitCodeAbbrevOp(EXTENSION_METADATA)); Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); unsigned Abbrev = Stream.EmitAbbrev(std::move(Abv)); // Emit the metadata record. RecordData Record; auto Metadata = Writer.getExtension()->getExtensionMetadata(); Record.push_back(EXTENSION_METADATA); Record.push_back(Metadata.MajorVersion); Record.push_back(Metadata.MinorVersion); Record.push_back(Metadata.BlockName.size()); Record.push_back(Metadata.UserInfo.size()); SmallString<64> Buffer; Buffer += Metadata.BlockName; Buffer += Metadata.UserInfo; Stream.EmitRecordWithBlob(Abbrev, Record, Buffer); // Emit the contents of the extension block. Writer.writeExtensionContents(SemaRef, Stream); // Exit the extension block. Stream.ExitBlock(); } //===----------------------------------------------------------------------===// // General Serialization Routines //===----------------------------------------------------------------------===// /// Emit the list of attributes to the specified record. void ASTRecordWriter::AddAttributes(ArrayRef Attrs) { auto &Record = *this; Record.push_back(Attrs.size()); for (const auto *A : Attrs) { Record.push_back(A->getKind()); // FIXME: stable encoding, target attrs Record.AddSourceRange(A->getRange()); #include "clang/Serialization/AttrPCHWrite.inc" } } void ASTWriter::AddToken(const Token &Tok, RecordDataImpl &Record) { AddSourceLocation(Tok.getLocation(), Record); Record.push_back(Tok.getLength()); // FIXME: When reading literal tokens, reconstruct the literal pointer // if it is needed. AddIdentifierRef(Tok.getIdentifierInfo(), Record); // FIXME: Should translate token kind to a stable encoding. Record.push_back(Tok.getKind()); // FIXME: Should translate token flags to a stable encoding. Record.push_back(Tok.getFlags()); } void ASTWriter::AddString(StringRef Str, RecordDataImpl &Record) { Record.push_back(Str.size()); Record.insert(Record.end(), Str.begin(), Str.end()); } bool ASTWriter::PreparePathForOutput(SmallVectorImpl &Path) { assert(Context && "should have context when outputting path"); bool Changed = cleanPathForOutput(Context->getSourceManager().getFileManager(), Path); // Remove a prefix to make the path relative, if relevant. const char *PathBegin = Path.data(); const char *PathPtr = adjustFilenameForRelocatableAST(PathBegin, BaseDirectory); if (PathPtr != PathBegin) { Path.erase(Path.begin(), Path.begin() + (PathPtr - PathBegin)); Changed = true; } return Changed; } void ASTWriter::AddPath(StringRef Path, RecordDataImpl &Record) { SmallString<128> FilePath(Path); PreparePathForOutput(FilePath); AddString(FilePath, Record); } void ASTWriter::EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record, StringRef Path) { SmallString<128> FilePath(Path); PreparePathForOutput(FilePath); Stream.EmitRecordWithBlob(Abbrev, Record, FilePath); } void ASTWriter::AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record) { Record.push_back(Version.getMajor()); if (Optional Minor = Version.getMinor()) Record.push_back(*Minor + 1); else Record.push_back(0); if (Optional Subminor = Version.getSubminor()) Record.push_back(*Subminor + 1); else Record.push_back(0); } /// Note that the identifier II occurs at the given offset /// within the identifier table. void ASTWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) { IdentID ID = IdentifierIDs[II]; // Only store offsets new to this AST file. Other identifier names are looked // up earlier in the chain and thus don't need an offset. if (ID >= FirstIdentID) IdentifierOffsets[ID - FirstIdentID] = Offset; } /// Note that the selector Sel occurs at the given offset /// within the method pool/selector table. void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) { unsigned ID = SelectorIDs[Sel]; assert(ID && "Unknown selector"); // Don't record offsets for selectors that are also available in a different // file. if (ID < FirstSelectorID) return; SelectorOffsets[ID - FirstSelectorID] = Offset; } ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl &Buffer, MemoryBufferCache &PCMCache, ArrayRef> Extensions, bool IncludeTimestamps) : Stream(Stream), Buffer(Buffer), PCMCache(PCMCache), IncludeTimestamps(IncludeTimestamps) { for (const auto &Ext : Extensions) { if (auto Writer = Ext->createExtensionWriter(*this)) ModuleFileExtensionWriters.push_back(std::move(Writer)); } } ASTWriter::~ASTWriter() { llvm::DeleteContainerSeconds(FileDeclIDs); } const LangOptions &ASTWriter::getLangOpts() const { assert(WritingAST && "can't determine lang opts when not writing AST"); return Context->getLangOpts(); } time_t ASTWriter::getTimestampForOutput(const FileEntry *E) const { return IncludeTimestamps ? E->getModificationTime() : 0; } ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, const std::string &OutputFile, Module *WritingModule, StringRef isysroot, bool hasErrors) { WritingAST = true; ASTHasCompilerErrors = hasErrors; // Emit the file header. Stream.Emit((unsigned)'C', 8); Stream.Emit((unsigned)'P', 8); Stream.Emit((unsigned)'C', 8); Stream.Emit((unsigned)'H', 8); WriteBlockInfoBlock(); Context = &SemaRef.Context; PP = &SemaRef.PP; this->WritingModule = WritingModule; ASTFileSignature Signature = WriteASTCore(SemaRef, isysroot, OutputFile, WritingModule); Context = nullptr; PP = nullptr; this->WritingModule = nullptr; this->BaseDirectory.clear(); WritingAST = false; if (SemaRef.Context.getLangOpts().ImplicitModules && WritingModule) { // Construct MemoryBuffer and update buffer manager. PCMCache.addBuffer(OutputFile, llvm::MemoryBuffer::getMemBufferCopy( StringRef(Buffer.begin(), Buffer.size()))); } return Signature; } template static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec, ASTWriter::RecordData &Record) { for (typename Vector::iterator I = Vec.begin(nullptr, true), E = Vec.end(); I != E; ++I) { Writer.AddDeclRef(*I, Record); } } ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, const std::string &OutputFile, Module *WritingModule) { using namespace llvm; bool isModule = WritingModule != nullptr; // Make sure that the AST reader knows to finalize itself. if (Chain) Chain->finalizeForWriting(); ASTContext &Context = SemaRef.Context; Preprocessor &PP = SemaRef.PP; // Set up predefined declaration IDs. auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) { if (D) { assert(D->isCanonicalDecl() && "predefined decl is not canonical"); DeclIDs[D] = ID; } }; RegisterPredefDecl(Context.getTranslationUnitDecl(), PREDEF_DECL_TRANSLATION_UNIT_ID); RegisterPredefDecl(Context.ObjCIdDecl, PREDEF_DECL_OBJC_ID_ID); RegisterPredefDecl(Context.ObjCSelDecl, PREDEF_DECL_OBJC_SEL_ID); RegisterPredefDecl(Context.ObjCClassDecl, PREDEF_DECL_OBJC_CLASS_ID); RegisterPredefDecl(Context.ObjCProtocolClassDecl, PREDEF_DECL_OBJC_PROTOCOL_ID); RegisterPredefDecl(Context.Int128Decl, PREDEF_DECL_INT_128_ID); RegisterPredefDecl(Context.UInt128Decl, PREDEF_DECL_UNSIGNED_INT_128_ID); RegisterPredefDecl(Context.ObjCInstanceTypeDecl, PREDEF_DECL_OBJC_INSTANCETYPE_ID); RegisterPredefDecl(Context.BuiltinVaListDecl, PREDEF_DECL_BUILTIN_VA_LIST_ID); RegisterPredefDecl(Context.VaListTagDecl, PREDEF_DECL_VA_LIST_TAG); RegisterPredefDecl(Context.BuiltinMSVaListDecl, PREDEF_DECL_BUILTIN_MS_VA_LIST_ID); RegisterPredefDecl(Context.ExternCContext, PREDEF_DECL_EXTERN_C_CONTEXT_ID); RegisterPredefDecl(Context.MakeIntegerSeqDecl, PREDEF_DECL_MAKE_INTEGER_SEQ_ID); RegisterPredefDecl(Context.CFConstantStringTypeDecl, PREDEF_DECL_CF_CONSTANT_STRING_ID); RegisterPredefDecl(Context.CFConstantStringTagDecl, PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID); RegisterPredefDecl(Context.TypePackElementDecl, PREDEF_DECL_TYPE_PACK_ELEMENT_ID); // Build a record containing all of the tentative definitions in this file, in // TentativeDefinitions order. Generally, this record will be empty for // headers. RecordData TentativeDefinitions; AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions, TentativeDefinitions); // Build a record containing all of the file scoped decls in this file. RecordData UnusedFileScopedDecls; if (!isModule) AddLazyVectorDecls(*this, SemaRef.UnusedFileScopedDecls, UnusedFileScopedDecls); // Build a record containing all of the delegating constructors we still need // to resolve. RecordData DelegatingCtorDecls; if (!isModule) AddLazyVectorDecls(*this, SemaRef.DelegatingCtorDecls, DelegatingCtorDecls); // Write the set of weak, undeclared identifiers. We always write the // entire table, since later PCH files in a PCH chain are only interested in // the results at the end of the chain. RecordData WeakUndeclaredIdentifiers; for (auto &WeakUndeclaredIdentifier : SemaRef.WeakUndeclaredIdentifiers) { IdentifierInfo *II = WeakUndeclaredIdentifier.first; WeakInfo &WI = WeakUndeclaredIdentifier.second; AddIdentifierRef(II, WeakUndeclaredIdentifiers); AddIdentifierRef(WI.getAlias(), WeakUndeclaredIdentifiers); AddSourceLocation(WI.getLocation(), WeakUndeclaredIdentifiers); WeakUndeclaredIdentifiers.push_back(WI.getUsed()); } // Build a record containing all of the ext_vector declarations. RecordData ExtVectorDecls; AddLazyVectorDecls(*this, SemaRef.ExtVectorDecls, ExtVectorDecls); // Build a record containing all of the VTable uses information. RecordData VTableUses; if (!SemaRef.VTableUses.empty()) { for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) { AddDeclRef(SemaRef.VTableUses[I].first, VTableUses); AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses); VTableUses.push_back(SemaRef.VTablesUsed[SemaRef.VTableUses[I].first]); } } // Build a record containing all of the UnusedLocalTypedefNameCandidates. RecordData UnusedLocalTypedefNameCandidates; for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates) AddDeclRef(TD, UnusedLocalTypedefNameCandidates); // Build a record containing all of pending implicit instantiations. RecordData PendingInstantiations; for (const auto &I : SemaRef.PendingInstantiations) { AddDeclRef(I.first, PendingInstantiations); AddSourceLocation(I.second, PendingInstantiations); } assert(SemaRef.PendingLocalImplicitInstantiations.empty() && "There are local ones at end of translation unit!"); // Build a record containing some declaration references. RecordData SemaDeclRefs; if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) { AddDeclRef(SemaRef.getStdNamespace(), SemaDeclRefs); AddDeclRef(SemaRef.getStdBadAlloc(), SemaDeclRefs); AddDeclRef(SemaRef.getStdAlignValT(), SemaDeclRefs); } RecordData CUDASpecialDeclRefs; if (Context.getcudaConfigureCallDecl()) { AddDeclRef(Context.getcudaConfigureCallDecl(), CUDASpecialDeclRefs); } // Build a record containing all of the known namespaces. RecordData KnownNamespaces; for (const auto &I : SemaRef.KnownNamespaces) { if (!I.second) AddDeclRef(I.first, KnownNamespaces); } // Build a record of all used, undefined objects that require definitions. RecordData UndefinedButUsed; SmallVector, 16> Undefined; SemaRef.getUndefinedButUsed(Undefined); for (const auto &I : Undefined) { AddDeclRef(I.first, UndefinedButUsed); AddSourceLocation(I.second, UndefinedButUsed); } // Build a record containing all delete-expressions that we would like to // analyze later in AST. RecordData DeleteExprsToAnalyze; if (!isModule) { for (const auto &DeleteExprsInfo : SemaRef.getMismatchingDeleteExpressions()) { AddDeclRef(DeleteExprsInfo.first, DeleteExprsToAnalyze); DeleteExprsToAnalyze.push_back(DeleteExprsInfo.second.size()); for (const auto &DeleteLoc : DeleteExprsInfo.second) { AddSourceLocation(DeleteLoc.first, DeleteExprsToAnalyze); DeleteExprsToAnalyze.push_back(DeleteLoc.second); } } } // Write the control block WriteControlBlock(PP, Context, isysroot, OutputFile); // Write the remaining AST contents. Stream.EnterSubblock(AST_BLOCK_ID, 5); // This is so that older clang versions, before the introduction // of the control block, can read and reject the newer PCH format. { RecordData Record = {VERSION_MAJOR}; Stream.EmitRecord(METADATA_OLD_FORMAT, Record); } // Create a lexical update block containing all of the declarations in the // translation unit that do not come from other AST files. const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); SmallVector NewGlobalKindDeclPairs; for (const auto *D : TU->noload_decls()) { if (!D->isFromASTFile()) { NewGlobalKindDeclPairs.push_back(D->getKind()); NewGlobalKindDeclPairs.push_back(GetDeclRef(D)); } } auto Abv = std::make_shared(); Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL)); Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv)); { RecordData::value_type Record[] = {TU_UPDATE_LEXICAL}; Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record, bytes(NewGlobalKindDeclPairs)); } // And a visible updates block for the translation unit. Abv = std::make_shared(); Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE)); Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv)); WriteDeclContextVisibleUpdate(TU); // If we have any extern "C" names, write out a visible update for them. if (Context.ExternCContext) WriteDeclContextVisibleUpdate(Context.ExternCContext); // If the translation unit has an anonymous namespace, and we don't already // have an update block for it, write it as an update block. // FIXME: Why do we not do this if there's already an update block? if (NamespaceDecl *NS = TU->getAnonymousNamespace()) { ASTWriter::UpdateRecord &Record = DeclUpdates[TU]; if (Record.empty()) Record.push_back(DeclUpdate(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, NS)); } // Add update records for all mangling numbers and static local numbers. // These aren't really update records, but this is a convenient way of // tagging this rare extra data onto the declarations. for (const auto &Number : Context.MangleNumbers) if (!Number.first->isFromASTFile()) DeclUpdates[Number.first].push_back(DeclUpdate(UPD_MANGLING_NUMBER, Number.second)); for (const auto &Number : Context.StaticLocalNumbers) if (!Number.first->isFromASTFile()) DeclUpdates[Number.first].push_back(DeclUpdate(UPD_STATIC_LOCAL_NUMBER, Number.second)); // Make sure visible decls, added to DeclContexts previously loaded from // an AST file, are registered for serialization. Likewise for template // specializations added to imported templates. for (const auto *I : DeclsToEmitEvenIfUnreferenced) { GetDeclRef(I); } // Make sure all decls associated with an identifier are registered for // serialization, if we're storing decls with identifiers. if (!WritingModule || !getLangOpts().CPlusPlus) { llvm::SmallVector IIs; for (const auto &ID : PP.getIdentifierTable()) { const IdentifierInfo *II = ID.second; if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization()) IIs.push_back(II); } // Sort the identifiers to visit based on their name. llvm::sort(IIs.begin(), IIs.end(), llvm::less_ptr()); for (const IdentifierInfo *II : IIs) { for (IdentifierResolver::iterator D = SemaRef.IdResolver.begin(II), DEnd = SemaRef.IdResolver.end(); D != DEnd; ++D) { GetDeclRef(*D); } } } // For method pool in the module, if it contains an entry for a selector, // the entry should be complete, containing everything introduced by that // module and all modules it imports. It's possible that the entry is out of // date, so we need to pull in the new content here. // It's possible that updateOutOfDateSelector can update SelectorIDs. To be // safe, we copy all selectors out. llvm::SmallVector AllSelectors; for (auto &SelectorAndID : SelectorIDs) AllSelectors.push_back(SelectorAndID.first); for (auto &Selector : AllSelectors) SemaRef.updateOutOfDateSelector(Selector); // Form the record of special types. RecordData SpecialTypes; AddTypeRef(Context.getRawCFConstantStringType(), SpecialTypes); AddTypeRef(Context.getFILEType(), SpecialTypes); AddTypeRef(Context.getjmp_bufType(), SpecialTypes); AddTypeRef(Context.getsigjmp_bufType(), SpecialTypes); AddTypeRef(Context.ObjCIdRedefinitionType, SpecialTypes); AddTypeRef(Context.ObjCClassRedefinitionType, SpecialTypes); AddTypeRef(Context.ObjCSelRedefinitionType, SpecialTypes); AddTypeRef(Context.getucontext_tType(), SpecialTypes); if (Chain) { // Write the mapping information describing our module dependencies and how // each of those modules were mapped into our own offset/ID space, so that // the reader can build the appropriate mapping to its own offset/ID space. // The map consists solely of a blob with the following format: // *(module-kind:i8 // module-name-len:i16 module-name:len*i8 // source-location-offset:i32 // identifier-id:i32 // preprocessed-entity-id:i32 // macro-definition-id:i32 // submodule-id:i32 // selector-id:i32 // declaration-id:i32 // c++-base-specifiers-id:i32 // type-id:i32) // // module-kind is the ModuleKind enum value. If it is MK_PrebuiltModule or // MK_ExplicitModule, then the module-name is the module name. Otherwise, // it is the module file name. auto Abbrev = std::make_shared(); Abbrev->Add(BitCodeAbbrevOp(MODULE_OFFSET_MAP)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned ModuleOffsetMapAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); SmallString<2048> Buffer; { llvm::raw_svector_ostream Out(Buffer); for (ModuleFile &M : Chain->ModuleMgr) { using namespace llvm::support; endian::Writer LE(Out, little); LE.write(static_cast(M.Kind)); StringRef Name = M.Kind == MK_PrebuiltModule || M.Kind == MK_ExplicitModule ? M.ModuleName : M.FileName; LE.write(Name.size()); Out.write(Name.data(), Name.size()); // Note: if a base ID was uint max, it would not be possible to load // another module after it or have more than one entity inside it. uint32_t None = std::numeric_limits::max(); auto writeBaseIDOrNone = [&](uint32_t BaseID, bool ShouldWrite) { assert(BaseID < std::numeric_limits::max() && "base id too high"); if (ShouldWrite) LE.write(BaseID); else LE.write(None); }; // These values should be unique within a chain, since they will be read // as keys into ContinuousRangeMaps. writeBaseIDOrNone(M.SLocEntryBaseOffset, M.LocalNumSLocEntries); writeBaseIDOrNone(M.BaseIdentifierID, M.LocalNumIdentifiers); writeBaseIDOrNone(M.BaseMacroID, M.LocalNumMacros); writeBaseIDOrNone(M.BasePreprocessedEntityID, M.NumPreprocessedEntities); writeBaseIDOrNone(M.BaseSubmoduleID, M.LocalNumSubmodules); writeBaseIDOrNone(M.BaseSelectorID, M.LocalNumSelectors); writeBaseIDOrNone(M.BaseDeclID, M.LocalNumDecls); writeBaseIDOrNone(M.BaseTypeIndex, M.LocalNumTypes); } } RecordData::value_type Record[] = {MODULE_OFFSET_MAP}; Stream.EmitRecordWithBlob(ModuleOffsetMapAbbrev, Record, Buffer.data(), Buffer.size()); } RecordData DeclUpdatesOffsetsRecord; // Keep writing types, declarations, and declaration update records // until we've emitted all of them. Stream.EnterSubblock(DECLTYPES_BLOCK_ID, /*bits for abbreviations*/5); WriteTypeAbbrevs(); WriteDeclAbbrevs(); do { WriteDeclUpdatesBlocks(DeclUpdatesOffsetsRecord); while (!DeclTypesToEmit.empty()) { DeclOrType DOT = DeclTypesToEmit.front(); DeclTypesToEmit.pop(); if (DOT.isType()) WriteType(DOT.getType()); else WriteDecl(Context, DOT.getDecl()); } } while (!DeclUpdates.empty()); Stream.ExitBlock(); DoneWritingDeclsAndTypes = true; // These things can only be done once we've written out decls and types. WriteTypeDeclOffsets(); if (!DeclUpdatesOffsetsRecord.empty()) Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord); WriteFileDeclIDsMap(); WriteSourceManagerBlock(Context.getSourceManager(), PP); WriteComments(); WritePreprocessor(PP, isModule); WriteHeaderSearch(PP.getHeaderSearchInfo()); WriteSelectors(SemaRef); WriteReferencedSelectorsPool(SemaRef); WriteLateParsedTemplates(SemaRef); WriteIdentifierTable(PP, SemaRef.IdResolver, isModule); WriteFPPragmaOptions(SemaRef.getFPOptions()); WriteOpenCLExtensions(SemaRef); WriteOpenCLExtensionTypes(SemaRef); - WriteOpenCLExtensionDecls(SemaRef); WriteCUDAPragmas(SemaRef); // If we're emitting a module, write out the submodule information. if (WritingModule) WriteSubmodules(WritingModule); + + // We need to have information about submodules to correctly deserialize + // decls from OpenCLExtensionDecls block + WriteOpenCLExtensionDecls(SemaRef); Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes); // Write the record containing external, unnamed definitions. if (!EagerlyDeserializedDecls.empty()) Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls); if (!ModularCodegenDecls.empty()) Stream.EmitRecord(MODULAR_CODEGEN_DECLS, ModularCodegenDecls); // Write the record containing tentative definitions. if (!TentativeDefinitions.empty()) Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions); // Write the record containing unused file scoped decls. if (!UnusedFileScopedDecls.empty()) Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls); // Write the record containing weak undeclared identifiers. if (!WeakUndeclaredIdentifiers.empty()) Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS, WeakUndeclaredIdentifiers); // Write the record containing ext_vector type names. if (!ExtVectorDecls.empty()) Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls); // Write the record containing VTable uses information. if (!VTableUses.empty()) Stream.EmitRecord(VTABLE_USES, VTableUses); // Write the record containing potentially unused local typedefs. if (!UnusedLocalTypedefNameCandidates.empty()) Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES, UnusedLocalTypedefNameCandidates); // Write the record containing pending implicit instantiations. if (!PendingInstantiations.empty()) Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations); // Write the record containing declaration references of Sema. if (!SemaDeclRefs.empty()) Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs); // Write the record containing CUDA-specific declaration references. if (!CUDASpecialDeclRefs.empty()) Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs); // Write the delegating constructors. if (!DelegatingCtorDecls.empty()) Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls); // Write the known namespaces. if (!KnownNamespaces.empty()) Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces); // Write the undefined internal functions and variables, and inline functions. if (!UndefinedButUsed.empty()) Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed); if (!DeleteExprsToAnalyze.empty()) Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze); // Write the visible updates to DeclContexts. for (auto *DC : UpdatedDeclContexts) WriteDeclContextVisibleUpdate(DC); if (!WritingModule) { // Write the submodules that were imported, if any. struct ModuleInfo { uint64_t ID; Module *M; ModuleInfo(uint64_t ID, Module *M) : ID(ID), M(M) {} }; llvm::SmallVector Imports; for (const auto *I : Context.local_imports()) { assert(SubmoduleIDs.find(I->getImportedModule()) != SubmoduleIDs.end()); Imports.push_back(ModuleInfo(SubmoduleIDs[I->getImportedModule()], I->getImportedModule())); } if (!Imports.empty()) { auto Cmp = [](const ModuleInfo &A, const ModuleInfo &B) { return A.ID < B.ID; }; auto Eq = [](const ModuleInfo &A, const ModuleInfo &B) { return A.ID == B.ID; }; // Sort and deduplicate module IDs. llvm::sort(Imports.begin(), Imports.end(), Cmp); Imports.erase(std::unique(Imports.begin(), Imports.end(), Eq), Imports.end()); RecordData ImportedModules; for (const auto &Import : Imports) { ImportedModules.push_back(Import.ID); // FIXME: If the module has macros imported then later has declarations // imported, this location won't be the right one as a location for the // declaration imports. AddSourceLocation(PP.getModuleImportLoc(Import.M), ImportedModules); } Stream.EmitRecord(IMPORTED_MODULES, ImportedModules); } } WriteObjCCategories(); if(!WritingModule) { WriteOptimizePragmaOptions(SemaRef); WriteMSStructPragmaOptions(SemaRef); WriteMSPointersToMembersPragmaOptions(SemaRef); } WritePackPragmaOptions(SemaRef); // Some simple statistics RecordData::value_type Record[] = { NumStatements, NumMacros, NumLexicalDeclContexts, NumVisibleDeclContexts}; Stream.EmitRecord(STATISTICS, Record); Stream.ExitBlock(); // Write the module file extension blocks. for (const auto &ExtWriter : ModuleFileExtensionWriters) WriteModuleFileExtension(SemaRef, *ExtWriter); return writeUnhashedControlBlock(PP, Context); } void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { if (DeclUpdates.empty()) return; DeclUpdateMap LocalUpdates; LocalUpdates.swap(DeclUpdates); for (auto &DeclUpdate : LocalUpdates) { const Decl *D = DeclUpdate.first; bool HasUpdatedBody = false; RecordData RecordData; ASTRecordWriter Record(*this, RecordData); for (auto &Update : DeclUpdate.second) { DeclUpdateKind Kind = (DeclUpdateKind)Update.getKind(); // An updated body is emitted last, so that the reader doesn't need // to skip over the lazy body to reach statements for other records. if (Kind == UPD_CXX_ADDED_FUNCTION_DEFINITION) HasUpdatedBody = true; else Record.push_back(Kind); switch (Kind) { case UPD_CXX_ADDED_IMPLICIT_MEMBER: case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: assert(Update.getDecl() && "no decl to add?"); Record.push_back(GetDeclRef(Update.getDecl())); break; case UPD_CXX_ADDED_FUNCTION_DEFINITION: break; case UPD_CXX_POINT_OF_INSTANTIATION: // FIXME: Do we need to also save the template specialization kind here? Record.AddSourceLocation(Update.getLoc()); break; case UPD_CXX_ADDED_VAR_DEFINITION: { const VarDecl *VD = cast(D); Record.push_back(VD->isInline()); Record.push_back(VD->isInlineSpecified()); if (VD->getInit()) { Record.push_back(!VD->isInitKnownICE() ? 1 : (VD->isInitICE() ? 3 : 2)); Record.AddStmt(const_cast(VD->getInit())); } else { Record.push_back(0); } break; } case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: Record.AddStmt(const_cast( cast(Update.getDecl())->getDefaultArg())); break; case UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER: Record.AddStmt( cast(Update.getDecl())->getInClassInitializer()); break; case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: { auto *RD = cast(D); UpdatedDeclContexts.insert(RD->getPrimaryContext()); Record.push_back(RD->isParamDestroyedInCallee()); Record.push_back(RD->getArgPassingRestrictions()); Record.AddCXXDefinitionData(RD); Record.AddOffset(WriteDeclContextLexicalBlock( *Context, const_cast(RD))); // This state is sometimes updated by template instantiation, when we // switch from the specialization referring to the template declaration // to it referring to the template definition. if (auto *MSInfo = RD->getMemberSpecializationInfo()) { Record.push_back(MSInfo->getTemplateSpecializationKind()); Record.AddSourceLocation(MSInfo->getPointOfInstantiation()); } else { auto *Spec = cast(RD); Record.push_back(Spec->getTemplateSpecializationKind()); Record.AddSourceLocation(Spec->getPointOfInstantiation()); // The instantiation might have been resolved to a partial // specialization. If so, record which one. auto From = Spec->getInstantiatedFrom(); if (auto PartialSpec = From.dyn_cast()) { Record.push_back(true); Record.AddDeclRef(PartialSpec); Record.AddTemplateArgumentList( &Spec->getTemplateInstantiationArgs()); } else { Record.push_back(false); } } Record.push_back(RD->getTagKind()); Record.AddSourceLocation(RD->getLocation()); Record.AddSourceLocation(RD->getLocStart()); Record.AddSourceRange(RD->getBraceRange()); // Instantiation may change attributes; write them all out afresh. Record.push_back(D->hasAttrs()); if (D->hasAttrs()) Record.AddAttributes(D->getAttrs()); // FIXME: Ensure we don't get here for explicit instantiations. break; } case UPD_CXX_RESOLVED_DTOR_DELETE: Record.AddDeclRef(Update.getDecl()); Record.AddStmt(cast(D)->getOperatorDeleteThisArg()); break; case UPD_CXX_RESOLVED_EXCEPTION_SPEC: addExceptionSpec( cast(D)->getType()->castAs(), Record); break; case UPD_CXX_DEDUCED_RETURN_TYPE: Record.push_back(GetOrCreateTypeID(Update.getType())); break; case UPD_DECL_MARKED_USED: break; case UPD_MANGLING_NUMBER: case UPD_STATIC_LOCAL_NUMBER: Record.push_back(Update.getNumber()); break; case UPD_DECL_MARKED_OPENMP_THREADPRIVATE: Record.AddSourceRange( D->getAttr()->getRange()); break; case UPD_DECL_MARKED_OPENMP_DECLARETARGET: Record.AddSourceRange( D->getAttr()->getRange()); break; case UPD_DECL_EXPORTED: Record.push_back(getSubmoduleID(Update.getModule())); break; case UPD_ADDED_ATTR_TO_RECORD: Record.AddAttributes(llvm::makeArrayRef(Update.getAttr())); break; } } if (HasUpdatedBody) { const auto *Def = cast(D); Record.push_back(UPD_CXX_ADDED_FUNCTION_DEFINITION); Record.push_back(Def->isInlined()); Record.AddSourceLocation(Def->getInnerLocStart()); Record.AddFunctionDefinition(Def); } OffsetsRecord.push_back(GetDeclRef(D)); OffsetsRecord.push_back(Record.Emit(DECL_UPDATES)); } } void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record) { uint32_t Raw = Loc.getRawEncoding(); Record.push_back((Raw << 1) | (Raw >> 31)); } void ASTWriter::AddSourceRange(SourceRange Range, RecordDataImpl &Record) { AddSourceLocation(Range.getBegin(), Record); AddSourceLocation(Range.getEnd(), Record); } void ASTRecordWriter::AddAPInt(const llvm::APInt &Value) { Record->push_back(Value.getBitWidth()); const uint64_t *Words = Value.getRawData(); Record->append(Words, Words + Value.getNumWords()); } void ASTRecordWriter::AddAPSInt(const llvm::APSInt &Value) { Record->push_back(Value.isUnsigned()); AddAPInt(Value); } void ASTRecordWriter::AddAPFloat(const llvm::APFloat &Value) { AddAPInt(Value.bitcastToAPInt()); } void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record) { Record.push_back(getIdentifierRef(II)); } IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { if (!II) return 0; IdentID &ID = IdentifierIDs[II]; if (ID == 0) ID = NextIdentID++; return ID; } MacroID ASTWriter::getMacroRef(MacroInfo *MI, const IdentifierInfo *Name) { // Don't emit builtin macros like __LINE__ to the AST file unless they // have been redefined by the header (in which case they are not // isBuiltinMacro). if (!MI || MI->isBuiltinMacro()) return 0; MacroID &ID = MacroIDs[MI]; if (ID == 0) { ID = NextMacroID++; MacroInfoToEmitData Info = { Name, MI, ID }; MacroInfosToEmit.push_back(Info); } return ID; } MacroID ASTWriter::getMacroID(MacroInfo *MI) { if (!MI || MI->isBuiltinMacro()) return 0; assert(MacroIDs.find(MI) != MacroIDs.end() && "Macro not emitted!"); return MacroIDs[MI]; } uint64_t ASTWriter::getMacroDirectivesOffset(const IdentifierInfo *Name) { return IdentMacroDirectivesOffsetMap.lookup(Name); } void ASTRecordWriter::AddSelectorRef(const Selector SelRef) { Record->push_back(Writer->getSelectorRef(SelRef)); } SelectorID ASTWriter::getSelectorRef(Selector Sel) { if (Sel.getAsOpaquePtr() == nullptr) { return 0; } SelectorID SID = SelectorIDs[Sel]; if (SID == 0 && Chain) { // This might trigger a ReadSelector callback, which will set the ID for // this selector. Chain->LoadSelector(Sel); SID = SelectorIDs[Sel]; } if (SID == 0) { SID = NextSelectorID++; SelectorIDs[Sel] = SID; } return SID; } void ASTRecordWriter::AddCXXTemporary(const CXXTemporary *Temp) { AddDeclRef(Temp->getDestructor()); } void ASTRecordWriter::AddTemplateArgumentLocInfo( TemplateArgument::ArgKind Kind, const TemplateArgumentLocInfo &Arg) { switch (Kind) { case TemplateArgument::Expression: AddStmt(Arg.getAsExpr()); break; case TemplateArgument::Type: AddTypeSourceInfo(Arg.getAsTypeSourceInfo()); break; case TemplateArgument::Template: AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc()); AddSourceLocation(Arg.getTemplateNameLoc()); break; case TemplateArgument::TemplateExpansion: AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc()); AddSourceLocation(Arg.getTemplateNameLoc()); AddSourceLocation(Arg.getTemplateEllipsisLoc()); break; case TemplateArgument::Null: case TemplateArgument::Integral: case TemplateArgument::Declaration: case TemplateArgument::NullPtr: case TemplateArgument::Pack: // FIXME: Is this right? break; } } void ASTRecordWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg) { AddTemplateArgument(Arg.getArgument()); if (Arg.getArgument().getKind() == TemplateArgument::Expression) { bool InfoHasSameExpr = Arg.getArgument().getAsExpr() == Arg.getLocInfo().getAsExpr(); Record->push_back(InfoHasSameExpr); if (InfoHasSameExpr) return; // Avoid storing the same expr twice. } AddTemplateArgumentLocInfo(Arg.getArgument().getKind(), Arg.getLocInfo()); } void ASTRecordWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo) { if (!TInfo) { AddTypeRef(QualType()); return; } AddTypeRef(TInfo->getType()); AddTypeLoc(TInfo->getTypeLoc()); } void ASTRecordWriter::AddTypeLoc(TypeLoc TL) { TypeLocWriter TLW(*this); for (; !TL.isNull(); TL = TL.getNextTypeLoc()) TLW.Visit(TL); } void ASTWriter::AddTypeRef(QualType T, RecordDataImpl &Record) { Record.push_back(GetOrCreateTypeID(T)); } TypeID ASTWriter::GetOrCreateTypeID(QualType T) { assert(Context); return MakeTypeID(*Context, T, [&](QualType T) -> TypeIdx { if (T.isNull()) return TypeIdx(); assert(!T.getLocalFastQualifiers()); TypeIdx &Idx = TypeIdxs[T]; if (Idx.getIndex() == 0) { if (DoneWritingDeclsAndTypes) { assert(0 && "New type seen after serializing all the types to emit!"); return TypeIdx(); } // We haven't seen this type before. Assign it a new ID and put it // into the queue of types to emit. Idx = TypeIdx(NextTypeID++); DeclTypesToEmit.push(T); } return Idx; }); } TypeID ASTWriter::getTypeID(QualType T) const { assert(Context); return MakeTypeID(*Context, T, [&](QualType T) -> TypeIdx { if (T.isNull()) return TypeIdx(); assert(!T.getLocalFastQualifiers()); TypeIdxMap::const_iterator I = TypeIdxs.find(T); assert(I != TypeIdxs.end() && "Type not emitted!"); return I->second; }); } void ASTWriter::AddDeclRef(const Decl *D, RecordDataImpl &Record) { Record.push_back(GetDeclRef(D)); } DeclID ASTWriter::GetDeclRef(const Decl *D) { assert(WritingAST && "Cannot request a declaration ID before AST writing"); if (!D) { return 0; } // If D comes from an AST file, its declaration ID is already known and // fixed. if (D->isFromASTFile()) return D->getGlobalID(); assert(!(reinterpret_cast(D) & 0x01) && "Invalid decl pointer"); DeclID &ID = DeclIDs[D]; if (ID == 0) { if (DoneWritingDeclsAndTypes) { assert(0 && "New decl seen after serializing all the decls to emit!"); return 0; } // We haven't seen this declaration before. Give it a new ID and // enqueue it in the list of declarations to emit. ID = NextDeclID++; DeclTypesToEmit.push(const_cast(D)); } return ID; } DeclID ASTWriter::getDeclID(const Decl *D) { if (!D) return 0; // If D comes from an AST file, its declaration ID is already known and // fixed. if (D->isFromASTFile()) return D->getGlobalID(); assert(DeclIDs.find(D) != DeclIDs.end() && "Declaration not emitted!"); return DeclIDs[D]; } void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) { assert(ID); assert(D); SourceLocation Loc = D->getLocation(); if (Loc.isInvalid()) return; // We only keep track of the file-level declarations of each file. if (!D->getLexicalDeclContext()->isFileContext()) return; // FIXME: ParmVarDecls that are part of a function type of a parameter of // a function/objc method, should not have TU as lexical context. // TemplateTemplateParmDecls that are part of an alias template, should not // have TU as lexical context. if (isa(D) || isa(D)) return; SourceManager &SM = Context->getSourceManager(); SourceLocation FileLoc = SM.getFileLoc(Loc); assert(SM.isLocalSourceLocation(FileLoc)); FileID FID; unsigned Offset; std::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc); if (FID.isInvalid()) return; assert(SM.getSLocEntry(FID).isFile()); DeclIDInFileInfo *&Info = FileDeclIDs[FID]; if (!Info) Info = new DeclIDInFileInfo(); std::pair LocDecl(Offset, ID); LocDeclIDsTy &Decls = Info->DeclIDs; if (Decls.empty() || Decls.back().first <= Offset) { Decls.push_back(LocDecl); return; } LocDeclIDsTy::iterator I = std::upper_bound(Decls.begin(), Decls.end(), LocDecl, llvm::less_first()); Decls.insert(I, LocDecl); } void ASTRecordWriter::AddDeclarationName(DeclarationName Name) { // FIXME: Emit a stable enum for NameKind. 0 = Identifier etc. Record->push_back(Name.getNameKind()); switch (Name.getNameKind()) { case DeclarationName::Identifier: AddIdentifierRef(Name.getAsIdentifierInfo()); break; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: AddSelectorRef(Name.getObjCSelector()); break; case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXConversionFunctionName: AddTypeRef(Name.getCXXNameType()); break; case DeclarationName::CXXDeductionGuideName: AddDeclRef(Name.getCXXDeductionGuideTemplate()); break; case DeclarationName::CXXOperatorName: Record->push_back(Name.getCXXOverloadedOperator()); break; case DeclarationName::CXXLiteralOperatorName: AddIdentifierRef(Name.getCXXLiteralIdentifier()); break; case DeclarationName::CXXUsingDirective: // No extra data to emit break; } } unsigned ASTWriter::getAnonymousDeclarationNumber(const NamedDecl *D) { assert(needsAnonymousDeclarationNumber(D) && "expected an anonymous declaration"); // Number the anonymous declarations within this context, if we've not // already done so. auto It = AnonymousDeclarationNumbers.find(D); if (It == AnonymousDeclarationNumbers.end()) { auto *DC = D->getLexicalDeclContext(); numberAnonymousDeclsWithin(DC, [&](const NamedDecl *ND, unsigned Number) { AnonymousDeclarationNumbers[ND] = Number; }); It = AnonymousDeclarationNumbers.find(D); assert(It != AnonymousDeclarationNumbers.end() && "declaration not found within its lexical context"); } return It->second; } void ASTRecordWriter::AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc, DeclarationName Name) { switch (Name.getNameKind()) { case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXConversionFunctionName: AddTypeSourceInfo(DNLoc.NamedType.TInfo); break; case DeclarationName::CXXOperatorName: AddSourceLocation(SourceLocation::getFromRawEncoding( DNLoc.CXXOperatorName.BeginOpNameLoc)); AddSourceLocation( SourceLocation::getFromRawEncoding(DNLoc.CXXOperatorName.EndOpNameLoc)); break; case DeclarationName::CXXLiteralOperatorName: AddSourceLocation(SourceLocation::getFromRawEncoding( DNLoc.CXXLiteralOperatorName.OpNameLoc)); break; case DeclarationName::Identifier: case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: case DeclarationName::CXXUsingDirective: case DeclarationName::CXXDeductionGuideName: break; } } void ASTRecordWriter::AddDeclarationNameInfo( const DeclarationNameInfo &NameInfo) { AddDeclarationName(NameInfo.getName()); AddSourceLocation(NameInfo.getLoc()); AddDeclarationNameLoc(NameInfo.getInfo(), NameInfo.getName()); } void ASTRecordWriter::AddQualifierInfo(const QualifierInfo &Info) { AddNestedNameSpecifierLoc(Info.QualifierLoc); Record->push_back(Info.NumTemplParamLists); for (unsigned i = 0, e = Info.NumTemplParamLists; i != e; ++i) AddTemplateParameterList(Info.TemplParamLists[i]); } void ASTRecordWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS) { // Nested name specifiers usually aren't too long. I think that 8 would // typically accommodate the vast majority. SmallVector NestedNames; // Push each of the NNS's onto a stack for serialization in reverse order. while (NNS) { NestedNames.push_back(NNS); NNS = NNS->getPrefix(); } Record->push_back(NestedNames.size()); while(!NestedNames.empty()) { NNS = NestedNames.pop_back_val(); NestedNameSpecifier::SpecifierKind Kind = NNS->getKind(); Record->push_back(Kind); switch (Kind) { case NestedNameSpecifier::Identifier: AddIdentifierRef(NNS->getAsIdentifier()); break; case NestedNameSpecifier::Namespace: AddDeclRef(NNS->getAsNamespace()); break; case NestedNameSpecifier::NamespaceAlias: AddDeclRef(NNS->getAsNamespaceAlias()); break; case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: AddTypeRef(QualType(NNS->getAsType(), 0)); Record->push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate); break; case NestedNameSpecifier::Global: // Don't need to write an associated value. break; case NestedNameSpecifier::Super: AddDeclRef(NNS->getAsRecordDecl()); break; } } } void ASTRecordWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { // Nested name specifiers usually aren't too long. I think that 8 would // typically accommodate the vast majority. SmallVector NestedNames; // Push each of the nested-name-specifiers's onto a stack for // serialization in reverse order. while (NNS) { NestedNames.push_back(NNS); NNS = NNS.getPrefix(); } Record->push_back(NestedNames.size()); while(!NestedNames.empty()) { NNS = NestedNames.pop_back_val(); NestedNameSpecifier::SpecifierKind Kind = NNS.getNestedNameSpecifier()->getKind(); Record->push_back(Kind); switch (Kind) { case NestedNameSpecifier::Identifier: AddIdentifierRef(NNS.getNestedNameSpecifier()->getAsIdentifier()); AddSourceRange(NNS.getLocalSourceRange()); break; case NestedNameSpecifier::Namespace: AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespace()); AddSourceRange(NNS.getLocalSourceRange()); break; case NestedNameSpecifier::NamespaceAlias: AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespaceAlias()); AddSourceRange(NNS.getLocalSourceRange()); break; case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: Record->push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate); AddTypeRef(NNS.getTypeLoc().getType()); AddTypeLoc(NNS.getTypeLoc()); AddSourceLocation(NNS.getLocalSourceRange().getEnd()); break; case NestedNameSpecifier::Global: AddSourceLocation(NNS.getLocalSourceRange().getEnd()); break; case NestedNameSpecifier::Super: AddDeclRef(NNS.getNestedNameSpecifier()->getAsRecordDecl()); AddSourceRange(NNS.getLocalSourceRange()); break; } } } void ASTRecordWriter::AddTemplateName(TemplateName Name) { TemplateName::NameKind Kind = Name.getKind(); Record->push_back(Kind); switch (Kind) { case TemplateName::Template: AddDeclRef(Name.getAsTemplateDecl()); break; case TemplateName::OverloadedTemplate: { OverloadedTemplateStorage *OvT = Name.getAsOverloadedTemplate(); Record->push_back(OvT->size()); for (const auto &I : *OvT) AddDeclRef(I); break; } case TemplateName::QualifiedTemplate: { QualifiedTemplateName *QualT = Name.getAsQualifiedTemplateName(); AddNestedNameSpecifier(QualT->getQualifier()); Record->push_back(QualT->hasTemplateKeyword()); AddDeclRef(QualT->getTemplateDecl()); break; } case TemplateName::DependentTemplate: { DependentTemplateName *DepT = Name.getAsDependentTemplateName(); AddNestedNameSpecifier(DepT->getQualifier()); Record->push_back(DepT->isIdentifier()); if (DepT->isIdentifier()) AddIdentifierRef(DepT->getIdentifier()); else Record->push_back(DepT->getOperator()); break; } case TemplateName::SubstTemplateTemplateParm: { SubstTemplateTemplateParmStorage *subst = Name.getAsSubstTemplateTemplateParm(); AddDeclRef(subst->getParameter()); AddTemplateName(subst->getReplacement()); break; } case TemplateName::SubstTemplateTemplateParmPack: { SubstTemplateTemplateParmPackStorage *SubstPack = Name.getAsSubstTemplateTemplateParmPack(); AddDeclRef(SubstPack->getParameterPack()); AddTemplateArgument(SubstPack->getArgumentPack()); break; } } } void ASTRecordWriter::AddTemplateArgument(const TemplateArgument &Arg) { Record->push_back(Arg.getKind()); switch (Arg.getKind()) { case TemplateArgument::Null: break; case TemplateArgument::Type: AddTypeRef(Arg.getAsType()); break; case TemplateArgument::Declaration: AddDeclRef(Arg.getAsDecl()); AddTypeRef(Arg.getParamTypeForDecl()); break; case TemplateArgument::NullPtr: AddTypeRef(Arg.getNullPtrType()); break; case TemplateArgument::Integral: AddAPSInt(Arg.getAsIntegral()); AddTypeRef(Arg.getIntegralType()); break; case TemplateArgument::Template: AddTemplateName(Arg.getAsTemplateOrTemplatePattern()); break; case TemplateArgument::TemplateExpansion: AddTemplateName(Arg.getAsTemplateOrTemplatePattern()); if (Optional NumExpansions = Arg.getNumTemplateExpansions()) Record->push_back(*NumExpansions + 1); else Record->push_back(0); break; case TemplateArgument::Expression: AddStmt(Arg.getAsExpr()); break; case TemplateArgument::Pack: Record->push_back(Arg.pack_size()); for (const auto &P : Arg.pack_elements()) AddTemplateArgument(P); break; } } void ASTRecordWriter::AddTemplateParameterList( const TemplateParameterList *TemplateParams) { assert(TemplateParams && "No TemplateParams!"); AddSourceLocation(TemplateParams->getTemplateLoc()); AddSourceLocation(TemplateParams->getLAngleLoc()); AddSourceLocation(TemplateParams->getRAngleLoc()); // TODO: Concepts Record->push_back(TemplateParams->size()); for (const auto &P : *TemplateParams) AddDeclRef(P); } /// Emit a template argument list. void ASTRecordWriter::AddTemplateArgumentList( const TemplateArgumentList *TemplateArgs) { assert(TemplateArgs && "No TemplateArgs!"); Record->push_back(TemplateArgs->size()); for (int i = 0, e = TemplateArgs->size(); i != e; ++i) AddTemplateArgument(TemplateArgs->get(i)); } void ASTRecordWriter::AddASTTemplateArgumentListInfo( const ASTTemplateArgumentListInfo *ASTTemplArgList) { assert(ASTTemplArgList && "No ASTTemplArgList!"); AddSourceLocation(ASTTemplArgList->LAngleLoc); AddSourceLocation(ASTTemplArgList->RAngleLoc); Record->push_back(ASTTemplArgList->NumTemplateArgs); const TemplateArgumentLoc *TemplArgs = ASTTemplArgList->getTemplateArgs(); for (int i = 0, e = ASTTemplArgList->NumTemplateArgs; i != e; ++i) AddTemplateArgumentLoc(TemplArgs[i]); } void ASTRecordWriter::AddUnresolvedSet(const ASTUnresolvedSet &Set) { Record->push_back(Set.size()); for (ASTUnresolvedSet::const_iterator I = Set.begin(), E = Set.end(); I != E; ++I) { AddDeclRef(I.getDecl()); Record->push_back(I.getAccess()); } } // FIXME: Move this out of the main ASTRecordWriter interface. void ASTRecordWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base) { Record->push_back(Base.isVirtual()); Record->push_back(Base.isBaseOfClass()); Record->push_back(Base.getAccessSpecifierAsWritten()); Record->push_back(Base.getInheritConstructors()); AddTypeSourceInfo(Base.getTypeSourceInfo()); AddSourceRange(Base.getSourceRange()); AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc() : SourceLocation()); } static uint64_t EmitCXXBaseSpecifiers(ASTWriter &W, ArrayRef Bases) { ASTWriter::RecordData Record; ASTRecordWriter Writer(W, Record); Writer.push_back(Bases.size()); for (auto &Base : Bases) Writer.AddCXXBaseSpecifier(Base); return Writer.Emit(serialization::DECL_CXX_BASE_SPECIFIERS); } // FIXME: Move this out of the main ASTRecordWriter interface. void ASTRecordWriter::AddCXXBaseSpecifiers(ArrayRef Bases) { AddOffset(EmitCXXBaseSpecifiers(*Writer, Bases)); } static uint64_t EmitCXXCtorInitializers(ASTWriter &W, ArrayRef CtorInits) { ASTWriter::RecordData Record; ASTRecordWriter Writer(W, Record); Writer.push_back(CtorInits.size()); for (auto *Init : CtorInits) { if (Init->isBaseInitializer()) { Writer.push_back(CTOR_INITIALIZER_BASE); Writer.AddTypeSourceInfo(Init->getTypeSourceInfo()); Writer.push_back(Init->isBaseVirtual()); } else if (Init->isDelegatingInitializer()) { Writer.push_back(CTOR_INITIALIZER_DELEGATING); Writer.AddTypeSourceInfo(Init->getTypeSourceInfo()); } else if (Init->isMemberInitializer()){ Writer.push_back(CTOR_INITIALIZER_MEMBER); Writer.AddDeclRef(Init->getMember()); } else { Writer.push_back(CTOR_INITIALIZER_INDIRECT_MEMBER); Writer.AddDeclRef(Init->getIndirectMember()); } Writer.AddSourceLocation(Init->getMemberLocation()); Writer.AddStmt(Init->getInit()); Writer.AddSourceLocation(Init->getLParenLoc()); Writer.AddSourceLocation(Init->getRParenLoc()); Writer.push_back(Init->isWritten()); if (Init->isWritten()) Writer.push_back(Init->getSourceOrder()); } return Writer.Emit(serialization::DECL_CXX_CTOR_INITIALIZERS); } // FIXME: Move this out of the main ASTRecordWriter interface. void ASTRecordWriter::AddCXXCtorInitializers( ArrayRef CtorInits) { AddOffset(EmitCXXCtorInitializers(*Writer, CtorInits)); } void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { auto &Data = D->data(); Record->push_back(Data.IsLambda); Record->push_back(Data.UserDeclaredConstructor); Record->push_back(Data.UserDeclaredSpecialMembers); Record->push_back(Data.Aggregate); Record->push_back(Data.PlainOldData); Record->push_back(Data.Empty); Record->push_back(Data.Polymorphic); Record->push_back(Data.Abstract); Record->push_back(Data.IsStandardLayout); Record->push_back(Data.IsCXX11StandardLayout); Record->push_back(Data.HasBasesWithFields); Record->push_back(Data.HasBasesWithNonStaticDataMembers); Record->push_back(Data.HasPrivateFields); Record->push_back(Data.HasProtectedFields); Record->push_back(Data.HasPublicFields); Record->push_back(Data.HasMutableFields); Record->push_back(Data.HasVariantMembers); Record->push_back(Data.HasOnlyCMembers); Record->push_back(Data.HasInClassInitializer); Record->push_back(Data.HasUninitializedReferenceMember); Record->push_back(Data.HasUninitializedFields); Record->push_back(Data.HasInheritedConstructor); Record->push_back(Data.HasInheritedAssignment); Record->push_back(Data.NeedOverloadResolutionForCopyConstructor); Record->push_back(Data.NeedOverloadResolutionForMoveConstructor); Record->push_back(Data.NeedOverloadResolutionForMoveAssignment); Record->push_back(Data.NeedOverloadResolutionForDestructor); Record->push_back(Data.DefaultedCopyConstructorIsDeleted); Record->push_back(Data.DefaultedMoveConstructorIsDeleted); Record->push_back(Data.DefaultedMoveAssignmentIsDeleted); Record->push_back(Data.DefaultedDestructorIsDeleted); Record->push_back(Data.HasTrivialSpecialMembers); Record->push_back(Data.HasTrivialSpecialMembersForCall); Record->push_back(Data.DeclaredNonTrivialSpecialMembers); Record->push_back(Data.DeclaredNonTrivialSpecialMembersForCall); Record->push_back(Data.HasIrrelevantDestructor); Record->push_back(Data.HasConstexprNonCopyMoveConstructor); Record->push_back(Data.HasDefaultedDefaultConstructor); Record->push_back(Data.DefaultedDefaultConstructorIsConstexpr); Record->push_back(Data.HasConstexprDefaultConstructor); Record->push_back(Data.HasNonLiteralTypeFieldsOrBases); Record->push_back(Data.ComputedVisibleConversions); Record->push_back(Data.UserProvidedDefaultConstructor); Record->push_back(Data.DeclaredSpecialMembers); Record->push_back(Data.ImplicitCopyConstructorCanHaveConstParamForVBase); Record->push_back(Data.ImplicitCopyConstructorCanHaveConstParamForNonVBase); Record->push_back(Data.ImplicitCopyAssignmentHasConstParam); Record->push_back(Data.HasDeclaredCopyConstructorWithConstParam); Record->push_back(Data.HasDeclaredCopyAssignmentWithConstParam); // getODRHash will compute the ODRHash if it has not been previously computed. Record->push_back(D->getODRHash()); bool ModulesDebugInfo = Writer->Context->getLangOpts().ModulesDebugInfo && Writer->WritingModule && !D->isDependentType(); Record->push_back(ModulesDebugInfo); if (ModulesDebugInfo) Writer->ModularCodegenDecls.push_back(Writer->GetDeclRef(D)); // IsLambda bit is already saved. Record->push_back(Data.NumBases); if (Data.NumBases > 0) AddCXXBaseSpecifiers(Data.bases()); // FIXME: Make VBases lazily computed when needed to avoid storing them. Record->push_back(Data.NumVBases); if (Data.NumVBases > 0) AddCXXBaseSpecifiers(Data.vbases()); AddUnresolvedSet(Data.Conversions.get(*Writer->Context)); AddUnresolvedSet(Data.VisibleConversions.get(*Writer->Context)); // Data.Definition is the owning decl, no need to write it. AddDeclRef(D->getFirstFriend()); // Add lambda-specific data. if (Data.IsLambda) { auto &Lambda = D->getLambdaData(); Record->push_back(Lambda.Dependent); Record->push_back(Lambda.IsGenericLambda); Record->push_back(Lambda.CaptureDefault); Record->push_back(Lambda.NumCaptures); Record->push_back(Lambda.NumExplicitCaptures); Record->push_back(Lambda.ManglingNumber); AddDeclRef(D->getLambdaContextDecl()); AddTypeSourceInfo(Lambda.MethodTyInfo); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { const LambdaCapture &Capture = Lambda.Captures[I]; AddSourceLocation(Capture.getLocation()); Record->push_back(Capture.isImplicit()); Record->push_back(Capture.getCaptureKind()); switch (Capture.getCaptureKind()) { case LCK_StarThis: case LCK_This: case LCK_VLAType: break; case LCK_ByCopy: case LCK_ByRef: VarDecl *Var = Capture.capturesVariable() ? Capture.getCapturedVar() : nullptr; AddDeclRef(Var); AddSourceLocation(Capture.isPackExpansion() ? Capture.getEllipsisLoc() : SourceLocation()); break; } } } } void ASTWriter::ReaderInitialized(ASTReader *Reader) { assert(Reader && "Cannot remove chain"); assert((!Chain || Chain == Reader) && "Cannot replace chain"); assert(FirstDeclID == NextDeclID && FirstTypeID == NextTypeID && FirstIdentID == NextIdentID && FirstMacroID == NextMacroID && FirstSubmoduleID == NextSubmoduleID && FirstSelectorID == NextSelectorID && "Setting chain after writing has started."); Chain = Reader; // Note, this will get called multiple times, once one the reader starts up // and again each time it's done reading a PCH or module. FirstDeclID = NUM_PREDEF_DECL_IDS + Chain->getTotalNumDecls(); FirstTypeID = NUM_PREDEF_TYPE_IDS + Chain->getTotalNumTypes(); FirstIdentID = NUM_PREDEF_IDENT_IDS + Chain->getTotalNumIdentifiers(); FirstMacroID = NUM_PREDEF_MACRO_IDS + Chain->getTotalNumMacros(); FirstSubmoduleID = NUM_PREDEF_SUBMODULE_IDS + Chain->getTotalNumSubmodules(); FirstSelectorID = NUM_PREDEF_SELECTOR_IDS + Chain->getTotalNumSelectors(); NextDeclID = FirstDeclID; NextTypeID = FirstTypeID; NextIdentID = FirstIdentID; NextMacroID = FirstMacroID; NextSelectorID = FirstSelectorID; NextSubmoduleID = FirstSubmoduleID; } void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) { // Always keep the highest ID. See \p TypeRead() for more information. IdentID &StoredID = IdentifierIDs[II]; if (ID > StoredID) StoredID = ID; } void ASTWriter::MacroRead(serialization::MacroID ID, MacroInfo *MI) { // Always keep the highest ID. See \p TypeRead() for more information. MacroID &StoredID = MacroIDs[MI]; if (ID > StoredID) StoredID = ID; } void ASTWriter::TypeRead(TypeIdx Idx, QualType T) { // Always take the highest-numbered type index. This copes with an interesting // case for chained AST writing where we schedule writing the type and then, // later, deserialize the type from another AST. In this case, we want to // keep the higher-numbered entry so that we can properly write it out to // the AST file. TypeIdx &StoredIdx = TypeIdxs[T]; if (Idx.getIndex() >= StoredIdx.getIndex()) StoredIdx = Idx; } void ASTWriter::SelectorRead(SelectorID ID, Selector S) { // Always keep the highest ID. See \p TypeRead() for more information. SelectorID &StoredID = SelectorIDs[S]; if (ID > StoredID) StoredID = ID; } void ASTWriter::MacroDefinitionRead(serialization::PreprocessedEntityID ID, MacroDefinitionRecord *MD) { assert(MacroDefinitions.find(MD) == MacroDefinitions.end()); MacroDefinitions[MD] = ID; } void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) { assert(SubmoduleIDs.find(Mod) == SubmoduleIDs.end()); SubmoduleIDs[Mod] = ID; } void ASTWriter::CompletedTagDefinition(const TagDecl *D) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(D->isCompleteDefinition()); assert(!WritingAST && "Already writing the AST!"); if (auto *RD = dyn_cast(D)) { // We are interested when a PCH decl is modified. if (RD->isFromASTFile()) { // A forward reference was mutated into a definition. Rewrite it. // FIXME: This happens during template instantiation, should we // have created a new definition decl instead ? assert(isTemplateInstantiation(RD->getTemplateSpecializationKind()) && "completed a tag from another module but not by instantiation?"); DeclUpdates[RD].push_back( DeclUpdate(UPD_CXX_INSTANTIATED_CLASS_DEFINITION)); } } } static bool isImportedDeclContext(ASTReader *Chain, const Decl *D) { if (D->isFromASTFile()) return true; // The predefined __va_list_tag struct is imported if we imported any decls. // FIXME: This is a gross hack. return D == D->getASTContext().getVaListTagDecl(); } void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(DC->isLookupContext() && "Should not add lookup results to non-lookup contexts!"); // TU is handled elsewhere. if (isa(DC)) return; // Namespaces are handled elsewhere, except for template instantiations of // FunctionTemplateDecls in namespaces. We are interested in cases where the // local instantiations are added to an imported context. Only happens when // adding ADL lookup candidates, for example templated friends. if (isa(DC) && D->getFriendObjectKind() == Decl::FOK_None && !isa(D)) return; // We're only interested in cases where a local declaration is added to an // imported context. if (D->isFromASTFile() || !isImportedDeclContext(Chain, cast(DC))) return; assert(DC == DC->getPrimaryContext() && "added to non-primary context"); assert(!getDefinitiveDeclContext(DC) && "DeclContext not definitive!"); assert(!WritingAST && "Already writing the AST!"); if (UpdatedDeclContexts.insert(DC) && !cast(DC)->isFromASTFile()) { // We're adding a visible declaration to a predefined decl context. Ensure // that we write out all of its lookup results so we don't get a nasty // surprise when we try to emit its lookup table. for (auto *Child : DC->decls()) DeclsToEmitEvenIfUnreferenced.push_back(Child); } DeclsToEmitEvenIfUnreferenced.push_back(D); } void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(D->isImplicit()); // We're only interested in cases where a local declaration is added to an // imported context. if (D->isFromASTFile() || !isImportedDeclContext(Chain, RD)) return; if (!isa(D)) return; // A decl coming from PCH was modified. assert(RD->isCompleteDefinition()); assert(!WritingAST && "Already writing the AST!"); DeclUpdates[RD].push_back(DeclUpdate(UPD_CXX_ADDED_IMPLICIT_MEMBER, D)); } void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!DoneWritingDeclsAndTypes && "Already done writing updates!"); if (!Chain) return; Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) { // If we don't already know the exception specification for this redecl // chain, add an update record for it. if (isUnresolvedExceptionSpec(cast(D) ->getType() ->castAs() ->getExceptionSpecType())) DeclUpdates[D].push_back(UPD_CXX_RESOLVED_EXCEPTION_SPEC); }); } void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!WritingAST && "Already writing the AST!"); if (!Chain) return; Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) { DeclUpdates[D].push_back( DeclUpdate(UPD_CXX_DEDUCED_RETURN_TYPE, ReturnType)); }); } void ASTWriter::ResolvedOperatorDelete(const CXXDestructorDecl *DD, const FunctionDecl *Delete, Expr *ThisArg) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!WritingAST && "Already writing the AST!"); assert(Delete && "Not given an operator delete"); if (!Chain) return; Chain->forEachImportedKeyDecl(DD, [&](const Decl *D) { DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_RESOLVED_DTOR_DELETE, Delete)); }); } void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!WritingAST && "Already writing the AST!"); if (!D->isFromASTFile()) return; // Declaration not imported from PCH. // Implicit function decl from a PCH was defined. DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION)); } void ASTWriter::VariableDefinitionInstantiated(const VarDecl *D) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!WritingAST && "Already writing the AST!"); if (!D->isFromASTFile()) return; DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_VAR_DEFINITION)); } void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!WritingAST && "Already writing the AST!"); if (!D->isFromASTFile()) return; DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION)); } void ASTWriter::InstantiationRequested(const ValueDecl *D) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!WritingAST && "Already writing the AST!"); if (!D->isFromASTFile()) return; // Since the actual instantiation is delayed, this really means that we need // to update the instantiation location. SourceLocation POI; if (auto *VD = dyn_cast(D)) POI = VD->getPointOfInstantiation(); else POI = cast(D)->getPointOfInstantiation(); DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_POINT_OF_INSTANTIATION, POI)); } void ASTWriter::DefaultArgumentInstantiated(const ParmVarDecl *D) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!WritingAST && "Already writing the AST!"); if (!D->isFromASTFile()) return; DeclUpdates[D].push_back( DeclUpdate(UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT, D)); } void ASTWriter::DefaultMemberInitializerInstantiated(const FieldDecl *D) { assert(!WritingAST && "Already writing the AST!"); if (!D->isFromASTFile()) return; DeclUpdates[D].push_back( DeclUpdate(UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER, D)); } void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!WritingAST && "Already writing the AST!"); if (!IFD->isFromASTFile()) return; // Declaration not imported from PCH. assert(IFD->getDefinition() && "Category on a class without a definition?"); ObjCClassesWithCategories.insert( const_cast(IFD->getDefinition())); } void ASTWriter::DeclarationMarkedUsed(const Decl *D) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!WritingAST && "Already writing the AST!"); // If there is *any* declaration of the entity that's not from an AST file, // we can skip writing the update record. We make sure that isUsed() triggers // completion of the redeclaration chain of the entity. for (auto Prev = D->getMostRecentDecl(); Prev; Prev = Prev->getPreviousDecl()) if (IsLocalDecl(Prev)) return; DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_USED)); } void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!WritingAST && "Already writing the AST!"); if (!D->isFromASTFile()) return; DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_THREADPRIVATE)); } void ASTWriter::DeclarationMarkedOpenMPDeclareTarget(const Decl *D, const Attr *Attr) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!WritingAST && "Already writing the AST!"); if (!D->isFromASTFile()) return; DeclUpdates[D].push_back( DeclUpdate(UPD_DECL_MARKED_OPENMP_DECLARETARGET, Attr)); } void ASTWriter::RedefinedHiddenDefinition(const NamedDecl *D, Module *M) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!WritingAST && "Already writing the AST!"); assert(D->isHidden() && "expected a hidden declaration"); DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_EXPORTED, M)); } void ASTWriter::AddedAttributeToRecord(const Attr *Attr, const RecordDecl *Record) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!WritingAST && "Already writing the AST!"); if (!Record->isFromASTFile()) return; DeclUpdates[Record].push_back(DeclUpdate(UPD_ADDED_ATTR_TO_RECORD, Attr)); } void ASTWriter::AddedCXXTemplateSpecialization( const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) { assert(!WritingAST && "Already writing the AST!"); if (!TD->getFirstDecl()->isFromASTFile()) return; if (Chain && Chain->isProcessingUpdateRecords()) return; DeclsToEmitEvenIfUnreferenced.push_back(D); } void ASTWriter::AddedCXXTemplateSpecialization( const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) { assert(!WritingAST && "Already writing the AST!"); if (!TD->getFirstDecl()->isFromASTFile()) return; if (Chain && Chain->isProcessingUpdateRecords()) return; DeclsToEmitEvenIfUnreferenced.push_back(D); } void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, const FunctionDecl *D) { assert(!WritingAST && "Already writing the AST!"); if (!TD->getFirstDecl()->isFromASTFile()) return; if (Chain && Chain->isProcessingUpdateRecords()) return; DeclsToEmitEvenIfUnreferenced.push_back(D); } Index: vendor/clang/dist-release_70/test/CodeGen/builtins-ppc-altivec.c =================================================================== --- vendor/clang/dist-release_70/test/CodeGen/builtins-ppc-altivec.c (revision 341366) +++ vendor/clang/dist-release_70/test/CodeGen/builtins-ppc-altivec.c (revision 341367) @@ -1,9474 +1,9474 @@ // REQUIRES: powerpc-registered-target // RUN: %clang_cc1 -target-feature +altivec -triple powerpc-unknown-unknown -emit-llvm %s \ // RUN: -o - | FileCheck %s // RUN: %clang_cc1 -target-feature +altivec -triple powerpc64-unknown-unknown -emit-llvm %s \ // RUN: -o - | FileCheck %s // RUN: %clang_cc1 -target-feature +altivec -triple powerpc64le-unknown-unknown -emit-llvm %s \ // RUN: -o - | FileCheck %s -check-prefix=CHECK-LE // RUN: not %clang_cc1 -triple powerpc64le-unknown-unknown -emit-llvm %s \ // RUN: -ferror-limit 0 -DNO_ALTIVEC -o - 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-NOALTIVEC #ifndef NO_ALTIVEC #include #endif vector bool char vbc = { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 }; vector signed char vsc = { 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12, 13, -14, 15, -16 }; vector unsigned char vuc = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; vector bool short vbs = { 1, 0, 1, 0, 1, 0, 1, 0 }; vector short vs = { -1, 2, -3, 4, -5, 6, -7, 8 }; vector unsigned short vus = { 1, 2, 3, 4, 5, 6, 7, 8 }; vector pixel vp = { 1, 2, 3, 4, 5, 6, 7, 8 }; vector bool int vbi = { 1, 0, 1, 0 }; vector int vi = { -1, 2, -3, 4 }; vector unsigned int vui = { 1, 2, 3, 4 }; vector float vf = { -1.5, 2.5, -3.5, 4.5 }; vector bool char res_vbc; vector signed char res_vsc; vector unsigned char res_vuc; vector bool short res_vbs; vector short res_vs; vector unsigned short res_vus; vector pixel res_vp; vector bool int res_vbi; vector int res_vi; vector unsigned int res_vui; vector float res_vf; // CHECK-NOALTIVEC: error: unknown type name 'vector' signed char param_sc; unsigned char param_uc; short param_s; unsigned short param_us; int param_i; unsigned int param_ui; float param_f; signed long long param_sll; int res_sc; int res_uc; int res_s; int res_us; int res_i; int res_ui; int res_f; // CHECK-LABEL: define void @test1 void test1() { /* vec_abs */ vsc = vec_abs(vsc); // CHECK: sub <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vmaxsb // CHECK-LE: sub <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vmaxsb vs = vec_abs(vs); // CHECK: sub <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vmaxsh // CHECK-LE: sub <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vmaxsh vi = vec_abs(vi); // CHECK: sub <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vmaxsw // CHECK-LE: sub <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vmaxsw vf = vec_abs(vf); // CHECK: bitcast <4 x float> %{{.*}} to <4 x i32> // CHECK: and <4 x i32> {{.*}}, // CHECK: bitcast <4 x i32> %{{.*}} to <4 x float> // CHECK: store <4 x float> %{{.*}}, <4 x float>* @vf // CHECK-LE: bitcast <4 x float> %{{.*}} to <4 x i32> // CHECK-LE: and <4 x i32> {{.*}}, // CHECK-LE: bitcast <4 x i32> %{{.*}} to <4 x float> // CHECK-LE: store <4 x float> %{{.*}}, <4 x float>* @vf // CHECK-NOALTIVEC: error: use of undeclared identifier 'vf' // CHECK-NOALTIVEC: vf = vec_abs(vf) vsc = vec_nabs(vsc); // CHECK: sub <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vminsb // CHECK-LE: sub <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vminsb vs = vec_nabs(vs); // CHECK: sub <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vminsh // CHECK-LE: sub <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vminsh vi = vec_nabs(vi); // CHECK: sub <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vminsw // CHECK-LE: sub <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vminsw res_vi = vec_neg(vi); // CHECK: sub <4 x i32> zeroinitializer, {{%[0-9]+}} // CHECK-LE: sub <4 x i32> zeroinitializer, {{%[0-9]+}} // CHECK-NOALTIVEC: error: use of undeclared identifier 'vi' // CHECK-NOALTIVEC: vi = vec_neg(vi); res_vs = vec_neg(vs); // CHECK: sub <8 x i16> zeroinitializer, {{%[0-9]+}} // CHECK-LE: sub <8 x i16> zeroinitializer, {{%[0-9]+}} // CHECK-NOALTIVEC: error: use of undeclared identifier 'vs' // CHECK-NOALTIVEC: res_vs = vec_neg(vs); res_vsc = vec_neg(vsc); // CHECK: sub <16 x i8> zeroinitializer, {{%[0-9]+}} // CHECK-LE: sub <16 x i8> zeroinitializer, {{%[0-9]+}} // CHECK-NOALTIVEC: error: use of undeclared identifier 'vsc' // CHECK-NOALTIVEC: res_vsc = vec_neg(vsc); /* vec_abs */ vsc = vec_abss(vsc); // CHECK: @llvm.ppc.altivec.vsubsbs // CHECK: @llvm.ppc.altivec.vmaxsb // CHECK-LE: @llvm.ppc.altivec.vsubsbs // CHECK-LE: @llvm.ppc.altivec.vmaxsb vs = vec_abss(vs); // CHECK: @llvm.ppc.altivec.vsubshs // CHECK: @llvm.ppc.altivec.vmaxsh // CHECK-LE: @llvm.ppc.altivec.vsubshs // CHECK-LE: @llvm.ppc.altivec.vmaxsh vi = vec_abss(vi); // CHECK: @llvm.ppc.altivec.vsubsws // CHECK: @llvm.ppc.altivec.vmaxsw // CHECK-LE: @llvm.ppc.altivec.vsubsws // CHECK-LE: @llvm.ppc.altivec.vmaxsw /* vec_add */ res_vsc = vec_add(vsc, vsc); // CHECK: add <16 x i8> // CHECK-LE: add <16 x i8> res_vsc = vec_add(vbc, vsc); // CHECK: add <16 x i8> // CHECK-LE: add <16 x i8> res_vsc = vec_add(vsc, vbc); // CHECK: add <16 x i8> // CHECK-LE: add <16 x i8> res_vuc = vec_add(vuc, vuc); // CHECK: add <16 x i8> // CHECK-LE: add <16 x i8> res_vuc = vec_add(vbc, vuc); // CHECK: add <16 x i8> // CHECK-LE: add <16 x i8> res_vuc = vec_add(vuc, vbc); // CHECK: add <16 x i8> // CHECK-LE: add <16 x i8> res_vs = vec_add(vs, vs); // CHECK: add <8 x i16> // CHECK-LE: add <8 x i16> res_vs = vec_add(vbs, vs); // CHECK: add <8 x i16> // CHECK-LE: add <8 x i16> res_vs = vec_add(vs, vbs); // CHECK: add <8 x i16> // CHECK-LE: add <8 x i16> res_vus = vec_add(vus, vus); // CHECK: add <8 x i16> // CHECK-LE: add <8 x i16> res_vus = vec_add(vbs, vus); // CHECK: add <8 x i16> // CHECK-LE: add <8 x i16> res_vus = vec_add(vus, vbs); // CHECK: add <8 x i16> // CHECK-LE: add <8 x i16> res_vi = vec_add(vi, vi); // CHECK: add <4 x i32> // CHECK-LE: add <4 x i32> res_vi = vec_add(vbi, vi); // CHECK: add <4 x i32> // CHECK-LE: add <4 x i32> res_vi = vec_add(vi, vbi); // CHECK: add <4 x i32> // CHECK-LE: add <4 x i32> res_vui = vec_add(vui, vui); // CHECK: add <4 x i32> // CHECK-LE: add <4 x i32> res_vui = vec_add(vbi, vui); // CHECK: add <4 x i32> // CHECK-LE: add <4 x i32> res_vui = vec_add(vui, vbi); // CHECK: add <4 x i32> // CHECK-LE: add <4 x i32> res_vf = vec_add(vf, vf); // CHECK: fadd <4 x float> // CHECK-LE: fadd <4 x float> res_vi = vec_adde(vi, vi, vi); // CHECK: and <4 x i32> // CHECK: add <4 x i32> // CHECK: add <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: add <4 x i32> // CHECK-LE: add <4 x i32> res_vui = vec_adde(vui, vui, vui); // CHECK: and <4 x i32> // CHECK: add <4 x i32> // CHECK: add <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: add <4 x i32> // CHECK-LE: add <4 x i32> res_vsc = vec_vaddubm(vsc, vsc); // CHECK: add <16 x i8> // CHECK-LE: add <16 x i8> res_vsc = vec_vaddubm(vbc, vsc); // CHECK: add <16 x i8> // CHECK-LE: add <16 x i8> res_vsc = vec_vaddubm(vsc, vbc); // CHECK: add <16 x i8> // CHECK-LE: add <16 x i8> res_vuc = vec_vaddubm(vuc, vuc); // CHECK: add <16 x i8> // CHECK-LE: add <16 x i8> res_vuc = vec_vaddubm(vbc, vuc); // CHECK: add <16 x i8> // CHECK-LE: add <16 x i8> res_vuc = vec_vaddubm(vuc, vbc); // CHECK: add <16 x i8> // CHECK-LE: add <16 x i8> res_vs = vec_vadduhm(vs, vs); // CHECK: add <8 x i16> // CHECK-LE: add <8 x i16> res_vs = vec_vadduhm(vbs, vs); // CHECK: add <8 x i16> // CHECK-LE: add <8 x i16> res_vs = vec_vadduhm(vs, vbs); // CHECK: add <8 x i16> // CHECK-LE: add <8 x i16> res_vus = vec_vadduhm(vus, vus); // CHECK: add <8 x i16> // CHECK-LE: add <8 x i16> res_vus = vec_vadduhm(vbs, vus); // CHECK: add <8 x i16> // CHECK-LE: add <8 x i16> res_vus = vec_vadduhm(vus, vbs); // CHECK: add <8 x i16> // CHECK-LE: add <8 x i16> res_vi = vec_vadduwm(vi, vi); // CHECK: add <4 x i32> // CHECK-LE: add <4 x i32> res_vi = vec_vadduwm(vbi, vi); // CHECK: add <4 x i32> // CHECK-LE: add <4 x i32> res_vi = vec_vadduwm(vi, vbi); // CHECK: add <4 x i32> // CHECK-LE: add <4 x i32> res_vui = vec_vadduwm(vui, vui); // CHECK: add <4 x i32> // CHECK-LE: add <4 x i32> res_vui = vec_vadduwm(vbi, vui); // CHECK: add <4 x i32> // CHECK-LE: add <4 x i32> res_vui = vec_vadduwm(vui, vbi); // CHECK: add <4 x i32> // CHECK-LE: add <4 x i32> res_vf = vec_vaddfp(vf, vf); // CHECK: fadd <4 x float> // CHECK-LE: fadd <4 x float> /* vec_addc */ res_vui = vec_addc(vui, vui); // CHECK: @llvm.ppc.altivec.vaddcuw // CHECK-LE: @llvm.ppc.altivec.vaddcuw res_vui = vec_vaddcuw(vui, vui); // CHECK: @llvm.ppc.altivec.vaddcuw // CHECK-LE: @llvm.ppc.altivec.vaddcuw /* vec_adds */ res_vsc = vec_adds(vsc, vsc); // CHECK: @llvm.ppc.altivec.vaddsbs // CHECK-LE: @llvm.ppc.altivec.vaddsbs res_vsc = vec_adds(vbc, vsc); // CHECK: @llvm.ppc.altivec.vaddsbs // CHECK-LE: @llvm.ppc.altivec.vaddsbs res_vsc = vec_adds(vsc, vbc); // CHECK: @llvm.ppc.altivec.vaddsbs // CHECK-LE: @llvm.ppc.altivec.vaddsbs res_vuc = vec_adds(vuc, vuc); // CHECK: @llvm.ppc.altivec.vaddubs // CHECK-LE: @llvm.ppc.altivec.vaddubs res_vuc = vec_adds(vbc, vuc); // CHECK: @llvm.ppc.altivec.vaddubs // CHECK-LE: @llvm.ppc.altivec.vaddubs res_vuc = vec_adds(vuc, vbc); // CHECK: @llvm.ppc.altivec.vaddubs // CHECK-LE: @llvm.ppc.altivec.vaddubs res_vs = vec_adds(vs, vs); // CHECK: @llvm.ppc.altivec.vaddshs // CHECK-LE: @llvm.ppc.altivec.vaddshs res_vs = vec_adds(vbs, vs); // CHECK: @llvm.ppc.altivec.vaddshs // CHECK-LE: @llvm.ppc.altivec.vaddshs res_vs = vec_adds(vs, vbs); // CHECK: @llvm.ppc.altivec.vaddshs // CHECK-LE: @llvm.ppc.altivec.vaddshs res_vus = vec_adds(vus, vus); // CHECK: @llvm.ppc.altivec.vadduhs // CHECK-LE: @llvm.ppc.altivec.vadduhs res_vus = vec_adds(vbs, vus); // CHECK: @llvm.ppc.altivec.vadduhs // CHECK-LE: @llvm.ppc.altivec.vadduhs res_vus = vec_adds(vus, vbs); // CHECK: @llvm.ppc.altivec.vadduhs // CHECK-LE: @llvm.ppc.altivec.vadduhs res_vi = vec_adds(vi, vi); // CHECK: @llvm.ppc.altivec.vaddsws // CHECK-LE: @llvm.ppc.altivec.vaddsws res_vi = vec_adds(vbi, vi); // CHECK: @llvm.ppc.altivec.vaddsws // CHECK-LE: @llvm.ppc.altivec.vaddsws res_vi = vec_adds(vi, vbi); // CHECK: @llvm.ppc.altivec.vaddsws // CHECK-LE: @llvm.ppc.altivec.vaddsws res_vui = vec_adds(vui, vui); // CHECK: @llvm.ppc.altivec.vadduws // CHECK-LE: @llvm.ppc.altivec.vadduws res_vui = vec_adds(vbi, vui); // CHECK: @llvm.ppc.altivec.vadduws // CHECK-LE: @llvm.ppc.altivec.vadduws res_vui = vec_adds(vui, vbi); // CHECK: @llvm.ppc.altivec.vadduws // CHECK-LE: @llvm.ppc.altivec.vadduws res_vsc = vec_vaddsbs(vsc, vsc); // CHECK: @llvm.ppc.altivec.vaddsbs // CHECK-LE: @llvm.ppc.altivec.vaddsbs res_vsc = vec_vaddsbs(vbc, vsc); // CHECK: @llvm.ppc.altivec.vaddsbs // CHECK-LE: @llvm.ppc.altivec.vaddsbs res_vsc = vec_vaddsbs(vsc, vbc); // CHECK: @llvm.ppc.altivec.vaddsbs // CHECK-LE: @llvm.ppc.altivec.vaddsbs res_vuc = vec_vaddubs(vuc, vuc); // CHECK: @llvm.ppc.altivec.vaddubs // CHECK-LE: @llvm.ppc.altivec.vaddubs res_vuc = vec_vaddubs(vbc, vuc); // CHECK: @llvm.ppc.altivec.vaddubs // CHECK-LE: @llvm.ppc.altivec.vaddubs res_vuc = vec_vaddubs(vuc, vbc); // CHECK: @llvm.ppc.altivec.vaddubs // CHECK-LE: @llvm.ppc.altivec.vaddubs res_vs = vec_vaddshs(vs, vs); // CHECK: @llvm.ppc.altivec.vaddshs // CHECK-LE: @llvm.ppc.altivec.vaddshs res_vs = vec_vaddshs(vbs, vs); // CHECK: @llvm.ppc.altivec.vaddshs // CHECK-LE: @llvm.ppc.altivec.vaddshs res_vs = vec_vaddshs(vs, vbs); // CHECK: @llvm.ppc.altivec.vaddshs // CHECK-LE: @llvm.ppc.altivec.vaddshs res_vus = vec_vadduhs(vus, vus); // CHECK: @llvm.ppc.altivec.vadduhs // CHECK-LE: @llvm.ppc.altivec.vadduhs res_vus = vec_vadduhs(vbs, vus); // CHECK: @llvm.ppc.altivec.vadduhs // CHECK-LE: @llvm.ppc.altivec.vadduhs res_vus = vec_vadduhs(vus, vbs); // CHECK: @llvm.ppc.altivec.vadduhs // CHECK-LE: @llvm.ppc.altivec.vadduhs res_vi = vec_vaddsws(vi, vi); // CHECK: @llvm.ppc.altivec.vaddsws // CHECK-LE: @llvm.ppc.altivec.vaddsws res_vi = vec_vaddsws(vbi, vi); // CHECK: @llvm.ppc.altivec.vaddsws // CHECK-LE: @llvm.ppc.altivec.vaddsws res_vi = vec_vaddsws(vi, vbi); // CHECK: @llvm.ppc.altivec.vaddsws // CHECK-LE: @llvm.ppc.altivec.vaddsws res_vui = vec_vadduws(vui, vui); // CHECK: @llvm.ppc.altivec.vadduws // CHECK-LE: @llvm.ppc.altivec.vadduws res_vui = vec_vadduws(vbi, vui); // CHECK: @llvm.ppc.altivec.vadduws // CHECK-LE: @llvm.ppc.altivec.vadduws res_vui = vec_vadduws(vui, vbi); // CHECK: @llvm.ppc.altivec.vadduws // CHECK-LE: @llvm.ppc.altivec.vadduws /* vec_and */ res_vsc = vec_and(vsc, vsc); // CHECK: and <16 x i8> // CHECK-LE: and <16 x i8> res_vsc = vec_and(vbc, vsc); // CHECK: and <16 x i8> // CHECK-LE: and <16 x i8> res_vsc = vec_and(vsc, vbc); // CHECK: and <16 x i8> // CHECK-LE: and <16 x i8> res_vuc = vec_and(vuc, vuc); // CHECK: and <16 x i8> // CHECK-LE: and <16 x i8> res_vuc = vec_and(vbc, vuc); // CHECK: and <16 x i8> // CHECK-LE: and <16 x i8> res_vuc = vec_and(vuc, vbc); // CHECK: and <16 x i8> // CHECK-LE: and <16 x i8> res_vbc = vec_and(vbc, vbc); // CHECK: and <16 x i8> // CHECK-LE: and <16 x i8> res_vs = vec_and(vs, vs); // CHECK: and <8 x i16> // CHECK-LE: and <8 x i16> res_vs = vec_and(vbs, vs); // CHECK: and <8 x i16> // CHECK-LE: and <8 x i16> res_vs = vec_and(vs, vbs); // CHECK: and <8 x i16> // CHECK-LE: and <8 x i16> res_vus = vec_and(vus, vus); // CHECK: and <8 x i16> // CHECK-LE: and <8 x i16> res_vus = vec_and(vbs, vus); // CHECK: and <8 x i16> // CHECK-LE: and <8 x i16> res_vus = vec_and(vus, vbs); // CHECK: and <8 x i16> // CHECK-LE: and <8 x i16> res_vbs = vec_and(vbs, vbs); // CHECK: and <8 x i16> // CHECK-LE: and <8 x i16> res_vi = vec_and(vi, vi); // CHECK: and <4 x i32> // CHECK-LE: and <4 x i32> res_vi = vec_and(vbi, vi); // CHECK: and <4 x i32> // CHECK-le: and <4 x i32> res_vi = vec_and(vi, vbi); // CHECK: and <4 x i32> // CHECK-LE: and <4 x i32> res_vui = vec_and(vui, vui); // CHECK: and <4 x i32> // CHECK-LE: and <4 x i32> res_vui = vec_and(vbi, vui); // CHECK: and <4 x i32> // CHECK-LE: and <4 x i32> res_vui = vec_and(vui, vbi); // CHECK: and <4 x i32> // CHECK-LE: and <4 x i32> res_vbi = vec_and(vbi, vbi); // CHECK: and <4 x i32> // CHECK-LE: and <4 x i32> res_vsc = vec_vand(vsc, vsc); // CHECK: and <16 x i8> // CHECK-LE: and <16 x i8> res_vsc = vec_vand(vbc, vsc); // CHECK: and <16 x i8> // CHECK-LE: and <16 x i8> res_vsc = vec_vand(vsc, vbc); // CHECK: and <16 x i8> // CHECK-LE: and <16 x i8> res_vuc = vec_vand(vuc, vuc); // CHECK: and <16 x i8> // CHECK-LE: and <16 x i8> res_vuc = vec_vand(vbc, vuc); // CHECK: and <16 x i8> // CHECK-LE: and <16 x i8> res_vuc = vec_vand(vuc, vbc); // CHECK: and <16 x i8> // CHECK-LE: and <16 x i8> res_vbc = vec_vand(vbc, vbc); // CHECK: and <16 x i8> // CHECK-LE: and <16 x i8> res_vs = vec_vand(vs, vs); // CHECK: and <8 x i16> // CHECK-LE: and <8 x i16> res_vs = vec_vand(vbs, vs); // CHECK: and <8 x i16> // CHECK-LE: and <8 x i16> res_vs = vec_vand(vs, vbs); // CHECK: and <8 x i16> // CHECK-LE: and <8 x i16> res_vus = vec_vand(vus, vus); // CHECK: and <8 x i16> // CHECK-LE: and <8 x i16> res_vus = vec_vand(vbs, vus); // CHECK: and <8 x i16> // CHECK-LE: and <8 x i16> res_vus = vec_vand(vus, vbs); // CHECK: and <8 x i16> // CHECK-LE: and <8 x i16> res_vbs = vec_vand(vbs, vbs); // CHECK: and <8 x i16> // CHECK-LE: and <8 x i16> res_vi = vec_vand(vi, vi); // CHECK: and <4 x i32> // CHECK-LE: and <4 x i32> res_vi = vec_vand(vbi, vi); // CHECK: and <4 x i32> // CHECK-LE: and <4 x i32> res_vi = vec_vand(vi, vbi); // CHECK: and <4 x i32> // CHECK-LE: and <4 x i32> res_vui = vec_vand(vui, vui); // CHECK: and <4 x i32> // CHECK-LE: and <4 x i32> res_vui = vec_vand(vbi, vui); // CHECK: and <4 x i32> // CHECK-LE: and <4 x i32> res_vui = vec_vand(vui, vbi); // CHECK: and <4 x i32> // CHECK-LE: and <4 x i32> res_vbi = vec_vand(vbi, vbi); // CHECK: and <4 x i32> // CHECK-LE: and <4 x i32> /* vec_andc */ res_vsc = vec_andc(vsc, vsc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> res_vsc = vec_andc(vbc, vsc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> res_vsc = vec_andc(vsc, vbc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> res_vuc = vec_andc(vuc, vuc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> res_vuc = vec_andc(vbc, vuc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> res_vuc = vec_andc(vuc, vbc); // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> res_vbc = vec_andc(vbc, vbc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> res_vs = vec_andc(vs, vs); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> res_vs = vec_andc(vbs, vs); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> res_vs = vec_andc(vs, vbs); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> res_vus = vec_andc(vus, vus); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> res_vus = vec_andc(vbs, vus); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> res_vus = vec_andc(vus, vbs); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> res_vbs = vec_andc(vbs, vbs); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> res_vi = vec_andc(vi, vi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vi = vec_andc(vbi, vi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vi = vec_andc(vi, vbi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vui = vec_andc(vui, vui); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vui = vec_andc(vbi, vui); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vui = vec_andc(vui, vbi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vf = vec_andc(vf, vf); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vf = vec_andc(vbi, vf); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vf = vec_andc(vf, vbi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vsc = vec_vandc(vsc, vsc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> res_vsc = vec_vandc(vbc, vsc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> res_vsc = vec_vandc(vsc, vbc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> res_vuc = vec_vandc(vuc, vuc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> res_vuc = vec_vandc(vbc, vuc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> res_vuc = vec_vandc(vuc, vbc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> res_vbc = vec_vandc(vbc, vbc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> res_vs = vec_vandc(vs, vs); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> res_vs = vec_vandc(vbs, vs); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> res_vs = vec_vandc(vs, vbs); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> res_vus = vec_vandc(vus, vus); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> res_vus = vec_vandc(vbs, vus); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> res_vus = vec_vandc(vus, vbs); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> res_vbs = vec_vandc(vbs, vbs); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> res_vi = vec_vandc(vi, vi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vi = vec_vandc(vbi, vi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vi = vec_vandc(vi, vbi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vui = vec_vandc(vui, vui); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vui = vec_vandc(vbi, vui); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vui = vec_vandc(vui, vbi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vf = vec_vandc(vf, vf); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vf = vec_vandc(vbi, vf); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> res_vf = vec_vandc(vf, vbi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> } // CHECK-LABEL: define void @test2 void test2() { /* vec_avg */ res_vsc = vec_avg(vsc, vsc); // CHECK: @llvm.ppc.altivec.vavgsb // CHECK-LE: @llvm.ppc.altivec.vavgsb res_vuc = vec_avg(vuc, vuc); // CHECK: @llvm.ppc.altivec.vavgub // CHECK-LE: @llvm.ppc.altivec.vavgub res_vs = vec_avg(vs, vs); // CHECK: @llvm.ppc.altivec.vavgsh // CHECK-LE: @llvm.ppc.altivec.vavgsh res_vus = vec_avg(vus, vus); // CHECK: @llvm.ppc.altivec.vavguh // CHECK-LE: @llvm.ppc.altivec.vavguh res_vi = vec_avg(vi, vi); // CHECK: @llvm.ppc.altivec.vavgsw // CHECK-LE: @llvm.ppc.altivec.vavgsw res_vui = vec_avg(vui, vui); // CHECK: @llvm.ppc.altivec.vavguw // CHECK-LE: @llvm.ppc.altivec.vavguw res_vsc = vec_vavgsb(vsc, vsc); // CHECK: @llvm.ppc.altivec.vavgsb // CHECK-LE: @llvm.ppc.altivec.vavgsb res_vuc = vec_vavgub(vuc, vuc); // CHECK: @llvm.ppc.altivec.vavgub // CHECK-LE: @llvm.ppc.altivec.vavgub res_vs = vec_vavgsh(vs, vs); // CHECK: @llvm.ppc.altivec.vavgsh // CHECK-LE: @llvm.ppc.altivec.vavgsh res_vus = vec_vavguh(vus, vus); // CHECK: @llvm.ppc.altivec.vavguh // CHECK-LE: @llvm.ppc.altivec.vavguh res_vi = vec_vavgsw(vi, vi); // CHECK: @llvm.ppc.altivec.vavgsw // CHECK-LE: @llvm.ppc.altivec.vavgsw res_vui = vec_vavguw(vui, vui); // CHECK: @llvm.ppc.altivec.vavguw // CHECK-LE: @llvm.ppc.altivec.vavguw /* vec_ceil */ res_vf = vec_ceil(vf); // CHECK: @llvm.ppc.altivec.vrfip // CHECK-LE: @llvm.ppc.altivec.vrfip res_vf = vec_vrfip(vf); // CHECK: @llvm.ppc.altivec.vrfip // CHECK-LE: @llvm.ppc.altivec.vrfip /* vec_cmpb */ res_vi = vec_cmpb(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpbfp // CHECK-LE: @llvm.ppc.altivec.vcmpbfp res_vi = vec_vcmpbfp(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpbfp // CHECK-LE: @llvm.ppc.altivec.vcmpbfp /* vec_cmpeq */ res_vbc = vec_cmpeq(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb // CHECK-LE: @llvm.ppc.altivec.vcmpequb res_vbc = vec_cmpeq(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb // CHECK-LE: @llvm.ppc.altivec.vcmpequb res_vbc = vec_cmpeq(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb // CHECK-LE: @llvm.ppc.altivec.vcmpequb res_vbc = vec_cmpeq(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb // CHECK-LE: @llvm.ppc.altivec.vcmpequb res_vbs = vec_cmpeq(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh // CHECK-LE: @llvm.ppc.altivec.vcmpequh res_vbs = vec_cmpeq(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpequh // CHECK-LE: @llvm.ppc.altivec.vcmpequh res_vbs = vec_cmpeq(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh // CHECK-LE: @llvm.ppc.altivec.vcmpequh res_vbs = vec_cmpeq(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh // CHECK-LE: @llvm.ppc.altivec.vcmpequh res_vbi = vec_cmpeq(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw // CHECK-LE: @llvm.ppc.altivec.vcmpequw res_vbi = vec_cmpeq(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpequw // CHECK-LE: @llvm.ppc.altivec.vcmpequw res_vbi = vec_cmpeq(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw // CHECK-LE: @llvm.ppc.altivec.vcmpequw res_vbi = vec_cmpeq(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw // CHECK-LE: @llvm.ppc.altivec.vcmpequw res_vbi = vec_cmpeq(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpeqfp // CHECK-LE: @llvm.ppc.altivec.vcmpeqfp /* vec_cmpge */ res_vbc = vec_cmpge(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb res_vbc = vec_cmpge(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub // CHECK-LE: @llvm.ppc.altivec.vcmpgtub res_vbs = vec_cmpge(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh res_vbs = vec_cmpge(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh res_vbi = vec_cmpge(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw res_vbi = vec_cmpge(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw res_vbi = vec_cmpge(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp // CHECK-LE: @llvm.ppc.altivec.vcmpgefp res_vbi = vec_vcmpgefp(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp // CHECK-LE: @llvm.ppc.altivec.vcmpgefp } // CHECK-LABEL: define void @test5 void test5() { /* vec_cmpgt */ res_vbc = vec_cmpgt(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb res_vbc = vec_cmpgt(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub // CHECK-LE: @llvm.ppc.altivec.vcmpgtub res_vbs = vec_cmpgt(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh res_vbs = vec_cmpgt(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh res_vbi = vec_cmpgt(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw res_vbi = vec_cmpgt(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw res_vbi = vec_cmpgt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp // CHECK-LE: @llvm.ppc.altivec.vcmpgtfp res_vbc = vec_vcmpgtsb(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb res_vbc = vec_vcmpgtub(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub // CHECK-LE: @llvm.ppc.altivec.vcmpgtub res_vbs = vec_vcmpgtsh(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh res_vbs = vec_vcmpgtuh(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh res_vbi = vec_vcmpgtsw(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw res_vbi = vec_vcmpgtuw(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw res_vbi = vec_vcmpgtfp(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp // CHECK-LE: @llvm.ppc.altivec.vcmpgtfp /* vec_cmple */ res_vbc = vec_cmple(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb res_vbc = vec_cmple(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub // CHECK-LE: @llvm.ppc.altivec.vcmpgtub res_vbs = vec_cmple(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh res_vbs = vec_cmple(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh res_vbi = vec_cmple(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw res_vbi = vec_cmple(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw res_vbi = vec_cmple(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp // CHECK-LE: @llvm.ppc.altivec.vcmpgefp } // CHECK-LABEL: define void @test6 void test6() { /* vec_cmplt */ res_vbc = vec_cmplt(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb res_vbc = vec_cmplt(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub // CHECK-LE: @llvm.ppc.altivec.vcmpgtub res_vbs = vec_cmplt(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh res_vbs = vec_cmplt(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh res_vbi = vec_cmplt(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw res_vbi = vec_cmplt(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw res_vbi = vec_cmplt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp // CHECK-LE: @llvm.ppc.altivec.vcmpgtfp /* vec_ctf */ res_vf = vec_ctf(vi, 0); // CHECK: @llvm.ppc.altivec.vcfsx // CHECK-LE: @llvm.ppc.altivec.vcfsx res_vf = vec_ctf(vui, 0); // CHECK: @llvm.ppc.altivec.vcfux // CHECK-LE: @llvm.ppc.altivec.vcfux res_vf = vec_vcfsx(vi, 0); // CHECK: @llvm.ppc.altivec.vcfsx // CHECK-LE: @llvm.ppc.altivec.vcfsx res_vf = vec_vcfux(vui, 0); // CHECK: @llvm.ppc.altivec.vcfux // CHECK-LE: @llvm.ppc.altivec.vcfux /* vec_cts */ res_vi = vec_cts(vf, 0); // CHECK: @llvm.ppc.altivec.vctsxs // CHECK-LE: @llvm.ppc.altivec.vctsxs res_vi = vec_vctsxs(vf, 0); // CHECK: @llvm.ppc.altivec.vctsxs // CHECK-LE: @llvm.ppc.altivec.vctsxs /* vec_ctu */ res_vui = vec_ctu(vf, 0); // CHECK: @llvm.ppc.altivec.vctuxs // CHECK-LE: @llvm.ppc.altivec.vctuxs res_vui = vec_vctuxs(vf, 0); // CHECK: @llvm.ppc.altivec.vctuxs // CHECK-LE: @llvm.ppc.altivec.vctuxs res_vi = vec_signed(vf); // CHECK: fptosi <4 x float> // CHECK-LE: fptosi <4 x float> res_vui = vec_unsigned(vf); // CHECK: fptoui <4 x float> // CHECK-LE: fptoui <4 x float> res_vf = vec_float(vi); // CHECK: sitofp <4 x i32> // CHECK-LE: sitofp <4 x i32> res_vf = vec_float(vui); // CHECK: uitofp <4 x i32> // CHECK-LE: uitofp <4 x i32> /* vec_div */ res_vsc = vec_div(vsc, vsc); // CHECK: sdiv <16 x i8> // CHECK-LE: sdiv <16 x i8> res_vuc = vec_div(vuc, vuc); // CHECK: udiv <16 x i8> // CHECK-LE: udiv <16 x i8> res_vs = vec_div(vs, vs); // CHECK: sdiv <8 x i16> // CHECK-LE: sdiv <8 x i16> res_vus = vec_div(vus, vus); // CHECK: udiv <8 x i16> // CHECK-LE: udiv <8 x i16> res_vi = vec_div(vi, vi); // CHECK: sdiv <4 x i32> // CHECK-LE: sdiv <4 x i32> res_vui = vec_div(vui, vui); // CHECK: udiv <4 x i32> // CHECK-LE: udiv <4 x i32> /* vec_dss */ vec_dss(0); // CHECK: @llvm.ppc.altivec.dss // CHECK-LE: @llvm.ppc.altivec.dss /* vec_dssall */ vec_dssall(); // CHECK: @llvm.ppc.altivec.dssall // CHECK-LE: @llvm.ppc.altivec.dssall /* vec_dst */ vec_dst(&vsc, 0, 0); // CHECK: @llvm.ppc.altivec.dst // CHECK-LE: @llvm.ppc.altivec.dst /* vec_dstst */ vec_dstst(&vs, 0, 0); // CHECK: @llvm.ppc.altivec.dstst // CHECK-LE: @llvm.ppc.altivec.dstst /* vec_dststt */ vec_dststt(¶m_i, 0, 0); // CHECK: @llvm.ppc.altivec.dststt // CHECK-LE: @llvm.ppc.altivec.dststt /* vec_dstt */ vec_dstt(&vf, 0, 0); // CHECK: @llvm.ppc.altivec.dstt // CHECK-LE: @llvm.ppc.altivec.dstt /* vec_expte */ res_vf = vec_expte(vf); // CHECK: @llvm.ppc.altivec.vexptefp // CHECK-LE: @llvm.ppc.altivec.vexptefp res_vf = vec_vexptefp(vf); // CHECK: @llvm.ppc.altivec.vexptefp // CHECK-LE: @llvm.ppc.altivec.vexptefp /* vec_floor */ res_vf = vec_floor(vf); // CHECK: @llvm.ppc.altivec.vrfim // CHECK-LE: @llvm.ppc.altivec.vrfim res_vf = vec_vrfim(vf); // CHECK: @llvm.ppc.altivec.vrfim // CHECK-LE: @llvm.ppc.altivec.vrfim /* vec_ld */ res_vsc = vec_ld(0, &vsc); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vsc = vec_ld(0, ¶m_sc); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vuc = vec_ld(0, &vuc); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vuc = vec_ld(0, ¶m_uc); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vbc = vec_ld(0, &vbc); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vs = vec_ld(0, &vs); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vs = vec_ld(0, ¶m_s); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vus = vec_ld(0, &vus); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vus = vec_ld(0, ¶m_us); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vbs = vec_ld(0, &vbs); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vp = vec_ld(0, &vp); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vi = vec_ld(0, &vi); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vi = vec_ld(0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vui = vec_ld(0, &vui); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vui = vec_ld(0, ¶m_ui); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vbi = vec_ld(0, &vbi); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vf = vec_ld(0, &vf); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vf = vec_ld(0, ¶m_f); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vsc = vec_lvx(0, &vsc); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vsc = vec_lvx(0, ¶m_sc); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vuc = vec_lvx(0, &vuc); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vuc = vec_lvx(0, ¶m_uc); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vbc = vec_lvx(0, &vbc); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vs = vec_lvx(0, &vs); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vs = vec_lvx(0, ¶m_s); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vus = vec_lvx(0, &vus); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vus = vec_lvx(0, ¶m_us); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vbs = vec_lvx(0, &vbs); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vp = vec_lvx(0, &vp); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vi = vec_lvx(0, &vi); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vi = vec_lvx(0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vui = vec_lvx(0, &vui); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vui = vec_lvx(0, ¶m_ui); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vbi = vec_lvx(0, &vbi); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vf = vec_lvx(0, &vf); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx res_vf = vec_lvx(0, ¶m_f); // CHECK: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvx /* vec_lde */ res_vsc = vec_lde(0, ¶m_sc); // CHECK: @llvm.ppc.altivec.lvebx // CHECK-LE: @llvm.ppc.altivec.lvebx res_vuc = vec_lde(0, ¶m_uc); // CHECK: @llvm.ppc.altivec.lvebx // CHECK-LE: @llvm.ppc.altivec.lvebx res_vs = vec_lde(0, ¶m_s); // CHECK: @llvm.ppc.altivec.lvehx // CHECK-LE: @llvm.ppc.altivec.lvehx res_vus = vec_lde(0, ¶m_us); // CHECK: @llvm.ppc.altivec.lvehx // CHECK-LE: @llvm.ppc.altivec.lvehx res_vi = vec_lde(0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvewx // CHECK-LE: @llvm.ppc.altivec.lvewx res_vui = vec_lde(0, ¶m_ui); // CHECK: @llvm.ppc.altivec.lvewx // CHECK-LE: @llvm.ppc.altivec.lvewx res_vf = vec_lde(0, ¶m_f); // CHECK: @llvm.ppc.altivec.lvewx // CHECK-LE: @llvm.ppc.altivec.lvewx res_vsc = vec_lvebx(0, ¶m_sc); // CHECK: @llvm.ppc.altivec.lvebx // CHECK-LE: @llvm.ppc.altivec.lvebx res_vuc = vec_lvebx(0, ¶m_uc); // CHECK: @llvm.ppc.altivec.lvebx // CHECK-LE: @llvm.ppc.altivec.lvebx res_vs = vec_lvehx(0, ¶m_s); // CHECK: @llvm.ppc.altivec.lvehx // CHECK-LE: @llvm.ppc.altivec.lvehx res_vus = vec_lvehx(0, ¶m_us); // CHECK: @llvm.ppc.altivec.lvehx // CHECK-LE: @llvm.ppc.altivec.lvehx res_vi = vec_lvewx(0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvewx // CHECK-LE: @llvm.ppc.altivec.lvewx res_vui = vec_lvewx(0, ¶m_ui); // CHECK: @llvm.ppc.altivec.lvewx // CHECK-LE: @llvm.ppc.altivec.lvewx res_vf = vec_lvewx(0, ¶m_f); // CHECK: @llvm.ppc.altivec.lvewx // CHECK-LE: @llvm.ppc.altivec.lvewx /* vec_ldl */ res_vsc = vec_ldl(0, &vsc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vsc = vec_ldl(0, ¶m_sc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vuc = vec_ldl(0, &vuc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vuc = vec_ldl(0, ¶m_uc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vbc = vec_ldl(0, &vbc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vs = vec_ldl(0, &vs); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vs = vec_ldl(0, ¶m_s); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vus = vec_ldl(0, &vus); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vus = vec_ldl(0, ¶m_us); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vbs = vec_ldl(0, &vbs); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vp = vec_ldl(0, &vp); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vi = vec_ldl(0, &vi); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vi = vec_ldl(0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vui = vec_ldl(0, &vui); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vui = vec_ldl(0, ¶m_ui); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vbi = vec_ldl(0, &vbi); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vf = vec_ldl(0, &vf); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vf = vec_ldl(0, ¶m_f); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vsc = vec_lvxl(0, &vsc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vsc = vec_lvxl(0, ¶m_sc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vuc = vec_lvxl(0, &vuc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vbc = vec_lvxl(0, &vbc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vuc = vec_lvxl(0, ¶m_uc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vs = vec_lvxl(0, &vs); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vs = vec_lvxl(0, ¶m_s); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vus = vec_lvxl(0, &vus); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vus = vec_lvxl(0, ¶m_us); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vbs = vec_lvxl(0, &vbs); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vp = vec_lvxl(0, &vp); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vi = vec_lvxl(0, &vi); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vi = vec_lvxl(0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vui = vec_lvxl(0, &vui); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vui = vec_lvxl(0, ¶m_ui); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vbi = vec_lvxl(0, &vbi); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vf = vec_lvxl(0, &vf); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl res_vf = vec_lvxl(0, ¶m_f); // CHECK: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvxl /* vec_loge */ res_vf = vec_loge(vf); // CHECK: @llvm.ppc.altivec.vlogefp // CHECK-LE: @llvm.ppc.altivec.vlogefp res_vf = vec_vlogefp(vf); // CHECK: @llvm.ppc.altivec.vlogefp // CHECK-LE: @llvm.ppc.altivec.vlogefp /* vec_lvsl */ res_vuc = vec_lvsl(0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.lvsl /* vec_lvsr */ res_vuc = vec_lvsr(0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.lvsr /* vec_madd */ res_vf =vec_madd(vf, vf, vf); // CHECK: @llvm.ppc.altivec.vmaddfp // CHECK-LE: @llvm.ppc.altivec.vmaddfp res_vf = vec_vmaddfp(vf, vf, vf); // CHECK: @llvm.ppc.altivec.vmaddfp // CHECK-LE: @llvm.ppc.altivec.vmaddfp /* vec_madds */ res_vs = vec_madds(vs, vs, vs); // CHECK: @llvm.ppc.altivec.vmhaddshs // CHECK-LE: @llvm.ppc.altivec.vmhaddshs res_vs = vec_vmhaddshs(vs, vs, vs); // CHECK: @llvm.ppc.altivec.vmhaddshs // CHECK-LE: @llvm.ppc.altivec.vmhaddshs /* vec_max */ res_vsc = vec_max(vsc, vsc); // CHECK: @llvm.ppc.altivec.vmaxsb // CHECK-LE: @llvm.ppc.altivec.vmaxsb res_vsc = vec_max(vbc, vsc); // CHECK: @llvm.ppc.altivec.vmaxsb // CHECK-LE: @llvm.ppc.altivec.vmaxsb res_vsc = vec_max(vsc, vbc); // CHECK: @llvm.ppc.altivec.vmaxsb // CHECK-LE: @llvm.ppc.altivec.vmaxsb res_vuc = vec_max(vuc, vuc); // CHECK: @llvm.ppc.altivec.vmaxub // CHECK-LE: @llvm.ppc.altivec.vmaxub res_vuc = vec_max(vbc, vuc); // CHECK: @llvm.ppc.altivec.vmaxub // CHECK-LE: @llvm.ppc.altivec.vmaxub res_vuc = vec_max(vuc, vbc); // CHECK: @llvm.ppc.altivec.vmaxub // CHECK-LE: @llvm.ppc.altivec.vmaxub res_vs = vec_max(vs, vs); // CHECK: @llvm.ppc.altivec.vmaxsh // CHECK-LE: @llvm.ppc.altivec.vmaxsh res_vs = vec_max(vbs, vs); // CHECK: @llvm.ppc.altivec.vmaxsh // CHECK-LE: @llvm.ppc.altivec.vmaxsh res_vs = vec_max(vs, vbs); // CHECK: @llvm.ppc.altivec.vmaxsh // CHECK-LE: @llvm.ppc.altivec.vmaxsh res_vus = vec_max(vus, vus); // CHECK: @llvm.ppc.altivec.vmaxuh // CHECK-LE: @llvm.ppc.altivec.vmaxuh res_vus = vec_max(vbs, vus); // CHECK: @llvm.ppc.altivec.vmaxuh // CHECK-LE: @llvm.ppc.altivec.vmaxuh res_vus = vec_max(vus, vbs); // CHECK: @llvm.ppc.altivec.vmaxuh // CHECK-LE: @llvm.ppc.altivec.vmaxuh res_vi = vec_max(vi, vi); // CHECK: @llvm.ppc.altivec.vmaxsw // CHECK-LE: @llvm.ppc.altivec.vmaxsw res_vi = vec_max(vbi, vi); // CHECK: @llvm.ppc.altivec.vmaxsw // CHECK-LE: @llvm.ppc.altivec.vmaxsw res_vi = vec_max(vi, vbi); // CHECK: @llvm.ppc.altivec.vmaxsw // CHECK-LE: @llvm.ppc.altivec.vmaxsw res_vui = vec_max(vui, vui); // CHECK: @llvm.ppc.altivec.vmaxuw // CHECK-LE: @llvm.ppc.altivec.vmaxuw res_vui = vec_max(vbi, vui); // CHECK: @llvm.ppc.altivec.vmaxuw // CHECK-LE: @llvm.ppc.altivec.vmaxuw res_vui = vec_max(vui, vbi); // CHECK: @llvm.ppc.altivec.vmaxuw // CHECK-LE: @llvm.ppc.altivec.vmaxuw res_vf = vec_max(vf, vf); // CHECK: @llvm.ppc.altivec.vmaxfp // CHECK-LE: @llvm.ppc.altivec.vmaxfp res_vsc = vec_vmaxsb(vsc, vsc); // CHECK: @llvm.ppc.altivec.vmaxsb // CHECK-LE: @llvm.ppc.altivec.vmaxsb res_vsc = vec_vmaxsb(vbc, vsc); // CHECK: @llvm.ppc.altivec.vmaxsb // CHECK-LE: @llvm.ppc.altivec.vmaxsb res_vsc = vec_vmaxsb(vsc, vbc); // CHECK: @llvm.ppc.altivec.vmaxsb // CHECK-LE: @llvm.ppc.altivec.vmaxsb res_vuc = vec_vmaxub(vuc, vuc); // CHECK: @llvm.ppc.altivec.vmaxub // CHECK-LE: @llvm.ppc.altivec.vmaxub res_vuc = vec_vmaxub(vbc, vuc); // CHECK: @llvm.ppc.altivec.vmaxub // CHECK-LE: @llvm.ppc.altivec.vmaxub res_vuc = vec_vmaxub(vuc, vbc); // CHECK: @llvm.ppc.altivec.vmaxub // CHECK-LE: @llvm.ppc.altivec.vmaxub res_vs = vec_vmaxsh(vs, vs); // CHECK: @llvm.ppc.altivec.vmaxsh // CHECK-LE: @llvm.ppc.altivec.vmaxsh res_vs = vec_vmaxsh(vbs, vs); // CHECK: @llvm.ppc.altivec.vmaxsh // CHECK-LE: @llvm.ppc.altivec.vmaxsh res_vs = vec_vmaxsh(vs, vbs); // CHECK: @llvm.ppc.altivec.vmaxsh // CHECK-LE: @llvm.ppc.altivec.vmaxsh res_vus = vec_vmaxuh(vus, vus); // CHECK: @llvm.ppc.altivec.vmaxuh // CHECK-LE: @llvm.ppc.altivec.vmaxuh res_vus = vec_vmaxuh(vbs, vus); // CHECK: @llvm.ppc.altivec.vmaxuh // CHECK-LE: @llvm.ppc.altivec.vmaxuh res_vus = vec_vmaxuh(vus, vbs); // CHECK: @llvm.ppc.altivec.vmaxuh // CHECK-LE: @llvm.ppc.altivec.vmaxuh res_vi = vec_vmaxsw(vi, vi); // CHECK: @llvm.ppc.altivec.vmaxsw // CHECK-LE: @llvm.ppc.altivec.vmaxsw res_vi = vec_vmaxsw(vbi, vi); // CHECK: @llvm.ppc.altivec.vmaxsw // CHECK-LE: @llvm.ppc.altivec.vmaxsw res_vi = vec_vmaxsw(vi, vbi); // CHECK: @llvm.ppc.altivec.vmaxsw // CHECK-LE: @llvm.ppc.altivec.vmaxsw res_vui = vec_vmaxuw(vui, vui); // CHECK: @llvm.ppc.altivec.vmaxuw // CHECK-LE: @llvm.ppc.altivec.vmaxuw res_vui = vec_vmaxuw(vbi, vui); // CHECK: @llvm.ppc.altivec.vmaxuw // CHECK-LE: @llvm.ppc.altivec.vmaxuw res_vui = vec_vmaxuw(vui, vbi); // CHECK: @llvm.ppc.altivec.vmaxuw // CHECK-LE: @llvm.ppc.altivec.vmaxuw res_vf = vec_vmaxfp(vf, vf); // CHECK: @llvm.ppc.altivec.vmaxfp // CHECK-LE: @llvm.ppc.altivec.vmaxfp /* vec_mergeh */ res_vsc = vec_mergeh(vsc, vsc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_mergeh(vuc, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbc = vec_mergeh(vbc, vbc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_mergeh(vs, vs); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vp = vec_mergeh(vp, vp); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_mergeh(vus, vus); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbs = vec_mergeh(vbs, vbs); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_mergeh(vi, vi); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_mergeh(vui, vui); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbi = vec_mergeh(vbi, vbi); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vf = vec_mergeh(vf, vf); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vsc = vec_vmrghb(vsc, vsc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_vmrghb(vuc, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbc = vec_vmrghb(vbc, vbc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_vmrghh(vs, vs); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vp = vec_vmrghh(vp, vp); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_vmrghh(vus, vus); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbs = vec_vmrghh(vbs, vbs); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_vmrghw(vi, vi); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_vmrghw(vui, vui); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbi = vec_vmrghw(vbi, vbi); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vf = vec_vmrghw(vf, vf); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm /* vec_mergel */ res_vsc = vec_mergel(vsc, vsc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_mergel(vuc, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbc = vec_mergel(vbc, vbc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_mergel(vs, vs); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vp = vec_mergeh(vp, vp); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_mergel(vus, vus); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbs = vec_mergel(vbs, vbs); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_mergel(vi, vi); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_mergel(vui, vui); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbi = vec_mergel(vbi, vbi); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vf = vec_mergel(vf, vf); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vsc = vec_vmrglb(vsc, vsc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_vmrglb(vuc, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbc = vec_vmrglb(vbc, vbc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_vmrglh(vs, vs); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vp = vec_vmrglh(vp, vp); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_vmrglh(vus, vus); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbs = vec_vmrglh(vbs, vbs); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_vmrglw(vi, vi); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_vmrglw(vui, vui); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbi = vec_vmrglw(vbi, vbi); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vf = vec_vmrglw(vf, vf); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm /* vec_mfvscr */ vus = vec_mfvscr(); // CHECK: @llvm.ppc.altivec.mfvscr // CHECK-LE: @llvm.ppc.altivec.mfvscr /* vec_min */ res_vsc = vec_min(vsc, vsc); // CHECK: @llvm.ppc.altivec.vminsb // CHECK-LE: @llvm.ppc.altivec.vminsb res_vsc = vec_min(vbc, vsc); // CHECK: @llvm.ppc.altivec.vminsb // CHECK-LE: @llvm.ppc.altivec.vminsb res_vsc = vec_min(vsc, vbc); // CHECK: @llvm.ppc.altivec.vminsb // CHECK-LE: @llvm.ppc.altivec.vminsb res_vuc = vec_min(vuc, vuc); // CHECK: @llvm.ppc.altivec.vminub // CHECK-LE: @llvm.ppc.altivec.vminub res_vuc = vec_min(vbc, vuc); // CHECK: @llvm.ppc.altivec.vminub // CHECK-LE: @llvm.ppc.altivec.vminub res_vuc = vec_min(vuc, vbc); // CHECK: @llvm.ppc.altivec.vminub // CHECK-LE: @llvm.ppc.altivec.vminub res_vs = vec_min(vs, vs); // CHECK: @llvm.ppc.altivec.vminsh // CHECK-LE: @llvm.ppc.altivec.vminsh res_vs = vec_min(vbs, vs); // CHECK: @llvm.ppc.altivec.vminsh // CHECK-LE: @llvm.ppc.altivec.vminsh res_vs = vec_min(vs, vbs); // CHECK: @llvm.ppc.altivec.vminsh // CHECK-LE: @llvm.ppc.altivec.vminsh res_vus = vec_min(vus, vus); // CHECK: @llvm.ppc.altivec.vminuh // CHECK-LE: @llvm.ppc.altivec.vminuh res_vus = vec_min(vbs, vus); // CHECK: @llvm.ppc.altivec.vminuh // CHECK-LE: @llvm.ppc.altivec.vminuh res_vus = vec_min(vus, vbs); // CHECK: @llvm.ppc.altivec.vminuh // CHECK-LE: @llvm.ppc.altivec.vminuh res_vi = vec_min(vi, vi); // CHECK: @llvm.ppc.altivec.vminsw // CHECK-LE: @llvm.ppc.altivec.vminsw res_vi = vec_min(vbi, vi); // CHECK: @llvm.ppc.altivec.vminsw // CHECK-LE: @llvm.ppc.altivec.vminsw res_vi = vec_min(vi, vbi); // CHECK: @llvm.ppc.altivec.vminsw // CHECK-LE: @llvm.ppc.altivec.vminsw res_vui = vec_min(vui, vui); // CHECK: @llvm.ppc.altivec.vminuw // CHECK-LE: @llvm.ppc.altivec.vminuw res_vui = vec_min(vbi, vui); // CHECK: @llvm.ppc.altivec.vminuw // CHECK-LE: @llvm.ppc.altivec.vminuw res_vui = vec_min(vui, vbi); // CHECK: @llvm.ppc.altivec.vminuw // CHECK-LE: @llvm.ppc.altivec.vminuw res_vf = vec_min(vf, vf); // CHECK: @llvm.ppc.altivec.vminfp // CHECK-LE: @llvm.ppc.altivec.vminfp res_vsc = vec_vminsb(vsc, vsc); // CHECK: @llvm.ppc.altivec.vminsb // CHECK-LE: @llvm.ppc.altivec.vminsb res_vsc = vec_vminsb(vbc, vsc); // CHECK: @llvm.ppc.altivec.vminsb // CHECK-LE: @llvm.ppc.altivec.vminsb res_vsc = vec_vminsb(vsc, vbc); // CHECK: @llvm.ppc.altivec.vminsb // CHECK-LE: @llvm.ppc.altivec.vminsb res_vuc = vec_vminub(vuc, vuc); // CHECK: @llvm.ppc.altivec.vminub // CHECK-LE: @llvm.ppc.altivec.vminub res_vuc = vec_vminub(vbc, vuc); // CHECK: @llvm.ppc.altivec.vminub // CHECK-LE: @llvm.ppc.altivec.vminub res_vuc = vec_vminub(vuc, vbc); // CHECK: @llvm.ppc.altivec.vminub // CHECK-LE: @llvm.ppc.altivec.vminub res_vs = vec_vminsh(vs, vs); // CHECK: @llvm.ppc.altivec.vminsh // CHECK-LE: @llvm.ppc.altivec.vminsh res_vs = vec_vminsh(vbs, vs); // CHECK: @llvm.ppc.altivec.vminsh // CHECK-LE: @llvm.ppc.altivec.vminsh res_vs = vec_vminsh(vs, vbs); // CHECK: @llvm.ppc.altivec.vminsh // CHECK-LE: @llvm.ppc.altivec.vminsh res_vus = vec_vminuh(vus, vus); // CHECK: @llvm.ppc.altivec.vminuh // CHECK-LE: @llvm.ppc.altivec.vminuh res_vus = vec_vminuh(vbs, vus); // CHECK: @llvm.ppc.altivec.vminuh // CHECK-LE: @llvm.ppc.altivec.vminuh res_vus = vec_vminuh(vus, vbs); // CHECK: @llvm.ppc.altivec.vminuh // CHECK-LE: @llvm.ppc.altivec.vminuh res_vi = vec_vminsw(vi, vi); // CHECK: @llvm.ppc.altivec.vminsw // CHECK-LE: @llvm.ppc.altivec.vminsw res_vi = vec_vminsw(vbi, vi); // CHECK: @llvm.ppc.altivec.vminsw // CHECK-LE: @llvm.ppc.altivec.vminsw res_vi = vec_vminsw(vi, vbi); // CHECK: @llvm.ppc.altivec.vminsw // CHECK-LE: @llvm.ppc.altivec.vminsw res_vui = vec_vminuw(vui, vui); // CHECK: @llvm.ppc.altivec.vminuw // CHECK-LE: @llvm.ppc.altivec.vminuw res_vui = vec_vminuw(vbi, vui); // CHECK: @llvm.ppc.altivec.vminuw // CHECK-LE: @llvm.ppc.altivec.vminuw res_vui = vec_vminuw(vui, vbi); // CHECK: @llvm.ppc.altivec.vminuw // CHECK-LE: @llvm.ppc.altivec.vminuw res_vf = vec_vminfp(vf, vf); // CHECK: @llvm.ppc.altivec.vminfp // CHECK-LE: @llvm.ppc.altivec.vminfp /* vec_mladd */ res_vus = vec_mladd(vus, vus, vus); // CHECK: mul <8 x i16> // CHECK: add <8 x i16> // CHECK-LE: mul <8 x i16> // CHECK-LE: add <8 x i16> res_vs = vec_mladd(vus, vs, vs); // CHECK: mul <8 x i16> // CHECK: add <8 x i16> // CHECK-LE: mul <8 x i16> // CHECK-LE: add <8 x i16> res_vs = vec_mladd(vs, vus, vus); // CHECK: mul <8 x i16> // CHECK: add <8 x i16> // CHECK-LE: mul <8 x i16> // CHECK-LE: add <8 x i16> res_vs = vec_mladd(vs, vs, vs); // CHECK: mul <8 x i16> // CHECK: add <8 x i16> // CHECK-LE: mul <8 x i16> // CHECK-LE: add <8 x i16> /* vec_mradds */ res_vs = vec_mradds(vs, vs, vs); // CHECK: @llvm.ppc.altivec.vmhraddshs // CHECK-LE: @llvm.ppc.altivec.vmhraddshs res_vs = vec_vmhraddshs(vs, vs, vs); // CHECK: @llvm.ppc.altivec.vmhraddshs // CHECK-LE: @llvm.ppc.altivec.vmhraddshs /* vec_msum */ res_vi = vec_msum(vsc, vuc, vi); // CHECK: @llvm.ppc.altivec.vmsummbm // CHECK-LE: @llvm.ppc.altivec.vmsummbm res_vui = vec_msum(vuc, vuc, vui); // CHECK: @llvm.ppc.altivec.vmsumubm // CHECK-LE: @llvm.ppc.altivec.vmsumubm res_vi = vec_msum(vs, vs, vi); // CHECK: @llvm.ppc.altivec.vmsumshm // CHECK-LE: @llvm.ppc.altivec.vmsumshm res_vui = vec_msum(vus, vus, vui); // CHECK: @llvm.ppc.altivec.vmsumuhm // CHECK-LE: @llvm.ppc.altivec.vmsumuhm res_vi = vec_vmsummbm(vsc, vuc, vi); // CHECK: @llvm.ppc.altivec.vmsummbm // CHECK-LE: @llvm.ppc.altivec.vmsummbm res_vui = vec_vmsumubm(vuc, vuc, vui); // CHECK: @llvm.ppc.altivec.vmsumubm // CHECK-LE: @llvm.ppc.altivec.vmsumubm res_vi = vec_vmsumshm(vs, vs, vi); // CHECK: @llvm.ppc.altivec.vmsumshm // CHECK-LE: @llvm.ppc.altivec.vmsumshm res_vui = vec_vmsumuhm(vus, vus, vui); // CHECK: @llvm.ppc.altivec.vmsumuhm // CHECK-LE: @llvm.ppc.altivec.vmsumuhm /* vec_msums */ res_vi = vec_msums(vs, vs, vi); // CHECK: @llvm.ppc.altivec.vmsumshs // CHECK-LE: @llvm.ppc.altivec.vmsumshs res_vui = vec_msums(vus, vus, vui); // CHECK: @llvm.ppc.altivec.vmsumuhs // CHECK-LE: @llvm.ppc.altivec.vmsumuhs res_vi = vec_vmsumshs(vs, vs, vi); // CHECK: @llvm.ppc.altivec.vmsumshs // CHECK-LE: @llvm.ppc.altivec.vmsumshs res_vui = vec_vmsumuhs(vus, vus, vui); // CHECK: @llvm.ppc.altivec.vmsumuhs // CHECK-LE: @llvm.ppc.altivec.vmsumuhs /* vec_mtvscr */ vec_mtvscr(vsc); // CHECK: @llvm.ppc.altivec.mtvscr // CHECK-LE: @llvm.ppc.altivec.mtvscr vec_mtvscr(vuc); // CHECK: @llvm.ppc.altivec.mtvscr // CHECK-LE: @llvm.ppc.altivec.mtvscr vec_mtvscr(vbc); // CHECK: @llvm.ppc.altivec.mtvscr // CHECK-LE: @llvm.ppc.altivec.mtvscr vec_mtvscr(vs); // CHECK: @llvm.ppc.altivec.mtvscr // CHECK-LE: @llvm.ppc.altivec.mtvscr vec_mtvscr(vus); // CHECK: @llvm.ppc.altivec.mtvscr // CHECK-LE: @llvm.ppc.altivec.mtvscr vec_mtvscr(vbs); // CHECK: @llvm.ppc.altivec.mtvscr // CHECK-LE: @llvm.ppc.altivec.mtvscr vec_mtvscr(vp); // CHECK: @llvm.ppc.altivec.mtvscr // CHECK-LE: @llvm.ppc.altivec.mtvscr vec_mtvscr(vi); // CHECK: @llvm.ppc.altivec.mtvscr // CHECK-LE: @llvm.ppc.altivec.mtvscr vec_mtvscr(vui); // CHECK: @llvm.ppc.altivec.mtvscr // CHECK-LE: @llvm.ppc.altivec.mtvscr vec_mtvscr(vbi); // CHECK: @llvm.ppc.altivec.mtvscr // CHECK-LE: @llvm.ppc.altivec.mtvscr /* vec_mul */ res_vsc = vec_mul(vsc, vsc); // CHECK: mul <16 x i8> // CHECK-LE: mul <16 x i8> res_vuc = vec_mul(vuc, vuc); // CHECK: mul <16 x i8> // CHECK-LE: mul <16 x i8> res_vs = vec_mul(vs, vs); // CHECK: mul <8 x i16> // CHECK-LE: mul <8 x i16> res_vus = vec_mul(vus, vus); // CHECK: mul <8 x i16> // CHECK-LE: mul <8 x i16> res_vi = vec_mul(vi, vi); // CHECK: mul <4 x i32> // CHECK-LE: mul <4 x i32> res_vui = vec_mul(vui, vui); // CHECK: mul <4 x i32> // CHECK-LE: mul <4 x i32> /* vec_mule */ res_vs = vec_mule(vsc, vsc); // CHECK: @llvm.ppc.altivec.vmulesb // CHECK-LE: @llvm.ppc.altivec.vmulosb res_vus = vec_mule(vuc, vuc); // CHECK: @llvm.ppc.altivec.vmuleub // CHECK-LE: @llvm.ppc.altivec.vmuloub res_vi = vec_mule(vs, vs); // CHECK: @llvm.ppc.altivec.vmulesh // CHECK-LE: @llvm.ppc.altivec.vmulosh res_vui = vec_mule(vus, vus); // CHECK: @llvm.ppc.altivec.vmuleuh // CHECK-LE: @llvm.ppc.altivec.vmulouh res_vs = vec_vmulesb(vsc, vsc); // CHECK: @llvm.ppc.altivec.vmulesb // CHECK-LE: @llvm.ppc.altivec.vmulosb res_vus = vec_vmuleub(vuc, vuc); // CHECK: @llvm.ppc.altivec.vmuleub // CHECK-LE: @llvm.ppc.altivec.vmuloub res_vi = vec_vmulesh(vs, vs); // CHECK: @llvm.ppc.altivec.vmulesh // CHECK-LE: @llvm.ppc.altivec.vmulosh res_vui = vec_vmuleuh(vus, vus); // CHECK: @llvm.ppc.altivec.vmuleuh // CHECK-LE: @llvm.ppc.altivec.vmulouh /* vec_mulo */ res_vs = vec_mulo(vsc, vsc); // CHECK: @llvm.ppc.altivec.vmulosb // CHECK-LE: @llvm.ppc.altivec.vmulesb res_vus = vec_mulo(vuc, vuc); // CHECK: @llvm.ppc.altivec.vmuloub // CHECK-LE: @llvm.ppc.altivec.vmuleub res_vi = vec_mulo(vs, vs); // CHECK: @llvm.ppc.altivec.vmulosh // CHECK-LE: @llvm.ppc.altivec.vmulesh res_vui = vec_mulo(vus, vus); // CHECK: @llvm.ppc.altivec.vmulouh // CHECK-LE: @llvm.ppc.altivec.vmuleuh res_vs = vec_vmulosb(vsc, vsc); // CHECK: @llvm.ppc.altivec.vmulosb // CHECK-LE: @llvm.ppc.altivec.vmulesb res_vus = vec_vmuloub(vuc, vuc); // CHECK: @llvm.ppc.altivec.vmuloub // CHECK-LE: @llvm.ppc.altivec.vmuleub res_vi = vec_vmulosh(vs, vs); // CHECK: @llvm.ppc.altivec.vmulosh // CHECK-LE: @llvm.ppc.altivec.vmulesh res_vui = vec_vmulouh(vus, vus); // CHECK: @llvm.ppc.altivec.vmulouh // CHECK-LE: @llvm.ppc.altivec.vmuleuh /* vec_nmsub */ res_vf = vec_nmsub(vf, vf, vf); // CHECK: @llvm.ppc.altivec.vnmsubfp // CHECK-LE: @llvm.ppc.altivec.vnmsubfp res_vf = vec_vnmsubfp(vf, vf, vf); // CHECK: @llvm.ppc.altivec.vnmsubfp // CHECK-LE: @llvm.ppc.altivec.vnmsubfp /* vec_nor */ res_vsc = vec_nor(vsc, vsc); // CHECK: or <16 x i8> // CHECK: xor <16 x i8> // CHECK-LE: or <16 x i8> // CHECK-LE: xor <16 x i8> res_vuc = vec_nor(vuc, vuc); // CHECK: or <16 x i8> // CHECK: xor <16 x i8> // CHECK-LE: or <16 x i8> // CHECK-LE: xor <16 x i8> res_vuc = vec_nor(vbc, vbc); // CHECK: or <16 x i8> // CHECK: xor <16 x i8> // CHECK-LE: or <16 x i8> // CHECK-LE: xor <16 x i8> res_vs = vec_nor(vs, vs); // CHECK: or <8 x i16> // CHECK: xor <8 x i16> // CHECK-LE: or <8 x i16> // CHECK-LE: xor <8 x i16> res_vus = vec_nor(vus, vus); // CHECK: or <8 x i16> // CHECK: xor <8 x i16> // CHECK-LE: or <8 x i16> // CHECK-LE: xor <8 x i16> res_vus = vec_nor(vbs, vbs); // CHECK: or <8 x i16> // CHECK: xor <8 x i16> // CHECK-LE: or <8 x i16> // CHECK-LE: xor <8 x i16> res_vi = vec_nor(vi, vi); // CHECK: or <4 x i32> // CHECK: xor <4 x i32> // CHECK-LE: or <4 x i32> // CHECK-LE: xor <4 x i32> res_vui = vec_nor(vui, vui); // CHECK: or <4 x i32> // CHECK: xor <4 x i32> // CHECK-LE: or <4 x i32> // CHECK-LE: xor <4 x i32> res_vui = vec_nor(vbi, vbi); // CHECK: or <4 x i32> // CHECK: xor <4 x i32> // CHECK-LE: or <4 x i32> // CHECK-LE: xor <4 x i32> res_vf = vec_nor(vf, vf); // CHECK: or <4 x i32> // CHECK: xor <4 x i32> // CHECK-LE: or <4 x i32> // CHECK-LE: xor <4 x i32> res_vsc = vec_vnor(vsc, vsc); // CHECK: or <16 x i8> // CHECK: xor <16 x i8> // CHECK-LE: or <16 x i8> // CHECK-LE: xor <16 x i8> res_vuc = vec_vnor(vuc, vuc); // CHECK: or <16 x i8> // CHECK: xor <16 x i8> // CHECK-LE: or <16 x i8> // CHECK-LE: xor <16 x i8> res_vuc = vec_vnor(vbc, vbc); // CHECK: or <16 x i8> // CHECK: xor <16 x i8> // CHECK-LE: or <16 x i8> // CHECK-LE: xor <16 x i8> res_vs = vec_vnor(vs, vs); // CHECK: or <8 x i16> // CHECK: xor <8 x i16> // CHECK-LE: or <8 x i16> // CHECK-LE: xor <8 x i16> res_vus = vec_vnor(vus, vus); // CHECK: or <8 x i16> // CHECK: xor <8 x i16> // CHECK-LE: or <8 x i16> // CHECK-LE: xor <8 x i16> res_vus = vec_vnor(vbs, vbs); // CHECK: or <8 x i16> // CHECK: xor <8 x i16> // CHECK-LE: or <8 x i16> // CHECK-LE: xor <8 x i16> res_vi = vec_vnor(vi, vi); // CHECK: or <4 x i32> // CHECK: xor <4 x i32> // CHECK-LE: or <4 x i32> // CHECK-LE: xor <4 x i32> res_vui = vec_vnor(vui, vui); // CHECK: or <4 x i32> // CHECK: xor <4 x i32> // CHECK-LE: or <4 x i32> // CHECK-LE: xor <4 x i32> res_vui = vec_vnor(vbi, vbi); // CHECK: or <4 x i32> // CHECK: xor <4 x i32> // CHECK-LE: or <4 x i32> // CHECK-LE: xor <4 x i32> res_vf = vec_vnor(vf, vf); // CHECK: or <4 x i32> // CHECK: xor <4 x i32> // CHECK-LE: or <4 x i32> // CHECK-LE: xor <4 x i32> /* vec_or */ res_vsc = vec_or(vsc, vsc); // CHECK: or <16 x i8> // CHECK-LE: or <16 x i8> res_vsc = vec_or(vbc, vsc); // CHECK: or <16 x i8> // CHECK-LE: or <16 x i8> res_vsc = vec_or(vsc, vbc); // CHECK: or <16 x i8> // CHECK-LE: or <16 x i8> res_vuc = vec_or(vuc, vuc); // CHECK: or <16 x i8> // CHECK-LE: or <16 x i8> res_vuc = vec_or(vbc, vuc); // CHECK: or <16 x i8> // CHECK-LE: or <16 x i8> res_vuc = vec_or(vuc, vbc); // CHECK: or <16 x i8> // CHECK-LE: or <16 x i8> res_vbc = vec_or(vbc, vbc); // CHECK: or <16 x i8> // CHECK-LE: or <16 x i8> res_vs = vec_or(vs, vs); // CHECK: or <8 x i16> // CHECK-LE: or <8 x i16> res_vs = vec_or(vbs, vs); // CHECK: or <8 x i16> // CHECK-LE: or <8 x i16> res_vs = vec_or(vs, vbs); // CHECK: or <8 x i16> // CHECK-LE: or <8 x i16> res_vus = vec_or(vus, vus); // CHECK: or <8 x i16> // CHECK-LE: or <8 x i16> res_vus = vec_or(vbs, vus); // CHECK: or <8 x i16> // CHECK-LE: or <8 x i16> res_vus = vec_or(vus, vbs); // CHECK: or <8 x i16> // CHECK-LE: or <8 x i16> res_vbs = vec_or(vbs, vbs); // CHECK: or <8 x i16> // CHECK-LE: or <8 x i16> res_vi = vec_or(vi, vi); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vi = vec_or(vbi, vi); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vi = vec_or(vi, vbi); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vui = vec_or(vui, vui); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vui = vec_or(vbi, vui); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vui = vec_or(vui, vbi); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vbi = vec_or(vbi, vbi); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vf = vec_or(vf, vf); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vf = vec_or(vbi, vf); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vf = vec_or(vf, vbi); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vsc = vec_vor(vsc, vsc); // CHECK: or <16 x i8> // CHECK-LE: or <16 x i8> res_vsc = vec_vor(vbc, vsc); // CHECK: or <16 x i8> // CHECK-LE: or <16 x i8> res_vsc = vec_vor(vsc, vbc); // CHECK: or <16 x i8> // CHECK-LE: or <16 x i8> res_vuc = vec_vor(vuc, vuc); // CHECK: or <16 x i8> // CHECK-LE: or <16 x i8> res_vuc = vec_vor(vbc, vuc); // CHECK: or <16 x i8> // CHECK-LE: or <16 x i8> res_vuc = vec_vor(vuc, vbc); // CHECK: or <16 x i8> // CHECK-LE: or <16 x i8> res_vbc = vec_vor(vbc, vbc); // CHECK: or <16 x i8> // CHECK-LE: or <16 x i8> res_vs = vec_vor(vs, vs); // CHECK: or <8 x i16> // CHECK-LE: or <8 x i16> res_vs = vec_vor(vbs, vs); // CHECK: or <8 x i16> // CHECK-LE: or <8 x i16> res_vs = vec_vor(vs, vbs); // CHECK: or <8 x i16> // CHECK-LE: or <8 x i16> res_vus = vec_vor(vus, vus); // CHECK: or <8 x i16> // CHECK-LE: or <8 x i16> res_vus = vec_vor(vbs, vus); // CHECK: or <8 x i16> // CHECK-LE: or <8 x i16> res_vus = vec_vor(vus, vbs); // CHECK: or <8 x i16> // CHECK-LE: or <8 x i16> res_vbs = vec_vor(vbs, vbs); // CHECK: or <8 x i16> // CHECK-LE: or <8 x i16> res_vi = vec_vor(vi, vi); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vi = vec_vor(vbi, vi); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vi = vec_vor(vi, vbi); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vui = vec_vor(vui, vui); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vui = vec_vor(vbi, vui); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vui = vec_vor(vui, vbi); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vbi = vec_vor(vbi, vbi); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vf = vec_vor(vf, vf); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vf = vec_vor(vbi, vf); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> res_vf = vec_vor(vf, vbi); // CHECK: or <4 x i32> // CHECK-LE: or <4 x i32> /* vec_pack */ res_vsc = vec_pack(vs, vs); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_pack(vus, vus); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbc = vec_pack(vbs, vbs); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_pack(vi, vi); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_pack(vui, vui); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbs = vec_pack(vbi, vbi); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vsc = vec_vpkuhum(vs, vs); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_vpkuhum(vus, vus); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbc = vec_vpkuhum(vbs, vbs); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_vpkuwum(vi, vi); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_vpkuwum(vui, vui); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbs = vec_vpkuwum(vbi, vbi); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm /* vec_packpx */ res_vp = vec_packpx(vui, vui); // CHECK: @llvm.ppc.altivec.vpkpx // CHECK-LE: @llvm.ppc.altivec.vpkpx res_vp = vec_vpkpx(vui, vui); // CHECK: @llvm.ppc.altivec.vpkpx // CHECK-LE: @llvm.ppc.altivec.vpkpx /* vec_packs */ res_vsc = vec_packs(vs, vs); // CHECK: @llvm.ppc.altivec.vpkshss // CHECK-LE: @llvm.ppc.altivec.vpkshss res_vuc = vec_packs(vus, vus); // CHECK: @llvm.ppc.altivec.vpkuhus // CHECK-LE: @llvm.ppc.altivec.vpkuhus res_vs = vec_packs(vi, vi); // CHECK: @llvm.ppc.altivec.vpkswss // CHECK-LE: @llvm.ppc.altivec.vpkswss res_vus = vec_packs(vui, vui); // CHECK: @llvm.ppc.altivec.vpkuwus // CHECK-LE: @llvm.ppc.altivec.vpkuwus res_vsc = vec_vpkshss(vs, vs); // CHECK: @llvm.ppc.altivec.vpkshss // CHECK-LE: @llvm.ppc.altivec.vpkshss res_vuc = vec_vpkuhus(vus, vus); // CHECK: @llvm.ppc.altivec.vpkuhus // CHECK-LE: @llvm.ppc.altivec.vpkuhus res_vs = vec_vpkswss(vi, vi); // CHECK: @llvm.ppc.altivec.vpkswss // CHECK-LE: @llvm.ppc.altivec.vpkswss res_vus = vec_vpkuwus(vui, vui); // CHECK: @llvm.ppc.altivec.vpkuwus // CHECK-LE: @llvm.ppc.altivec.vpkuwus /* vec_packsu */ res_vuc = vec_packsu(vs, vs); // CHECK: @llvm.ppc.altivec.vpkshus // CHECK-LE: @llvm.ppc.altivec.vpkshus res_vuc = vec_packsu(vus, vus); // CHECK: @llvm.ppc.altivec.vpkuhus // CHECK-LE: @llvm.ppc.altivec.vpkuhus res_vus = vec_packsu(vi, vi); // CHECK: @llvm.ppc.altivec.vpkswus // CHECK-LE: @llvm.ppc.altivec.vpkswus res_vus = vec_packsu(vui, vui); // CHECK: @llvm.ppc.altivec.vpkuwus // CHECK-LE: @llvm.ppc.altivec.vpkuwus res_vuc = vec_vpkshus(vs, vs); // CHECK: @llvm.ppc.altivec.vpkshus // CHECK-LE: @llvm.ppc.altivec.vpkshus res_vuc = vec_vpkshus(vus, vus); // CHECK: @llvm.ppc.altivec.vpkuhus // CHECK-LE: @llvm.ppc.altivec.vpkuhus res_vus = vec_vpkswus(vi, vi); // CHECK: @llvm.ppc.altivec.vpkswus // CHECK-LE: @llvm.ppc.altivec.vpkswus res_vus = vec_vpkswus(vui, vui); // CHECK: @llvm.ppc.altivec.vpkuwus // CHECK-LE: @llvm.ppc.altivec.vpkuwus /* vec_perm */ res_vsc = vec_perm(vsc, vsc, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_perm(vuc, vuc, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbc = vec_perm(vbc, vbc, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_perm(vs, vs, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_perm(vus, vus, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbs = vec_perm(vbs, vbs, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vp = vec_perm(vp, vp, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_perm(vi, vi, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_perm(vui, vui, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbi = vec_perm(vbi, vbi, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vf = vec_perm(vf, vf, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vsc = vec_vperm(vsc, vsc, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_vperm(vuc, vuc, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbc = vec_vperm(vbc, vbc, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_vperm(vs, vs, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_vperm(vus, vus, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbs = vec_vperm(vbs, vbs, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vp = vec_vperm(vp, vp, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_vperm(vi, vi, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_vperm(vui, vui, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbi = vec_vperm(vbi, vbi, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vf = vec_vperm(vf, vf, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm /* vec_re */ res_vf = vec_re(vf); // CHECK: @llvm.ppc.altivec.vrefp // CHECK-LE: @llvm.ppc.altivec.vrefp res_vf = vec_vrefp(vf); // CHECK: @llvm.ppc.altivec.vrefp // CHECK-LE: @llvm.ppc.altivec.vrefp /* vec_rl */ res_vsc = vec_rl(vsc, vuc); // CHECK: @llvm.ppc.altivec.vrlb // CHECK-LE: @llvm.ppc.altivec.vrlb res_vuc = vec_rl(vuc, vuc); // CHECK: @llvm.ppc.altivec.vrlb // CHECK-LE: @llvm.ppc.altivec.vrlb res_vs = vec_rl(vs, vus); // CHECK: @llvm.ppc.altivec.vrlh // CHECK-LE: @llvm.ppc.altivec.vrlh res_vus = vec_rl(vus, vus); // CHECK: @llvm.ppc.altivec.vrlh // CHECK-LE: @llvm.ppc.altivec.vrlh res_vi = vec_rl(vi, vui); // CHECK: @llvm.ppc.altivec.vrlw // CHECK-LE: @llvm.ppc.altivec.vrlw res_vui = vec_rl(vui, vui); // CHECK: @llvm.ppc.altivec.vrlw // CHECK-LE: @llvm.ppc.altivec.vrlw res_vsc = vec_vrlb(vsc, vuc); // CHECK: @llvm.ppc.altivec.vrlb // CHECK-LE: @llvm.ppc.altivec.vrlb res_vuc = vec_vrlb(vuc, vuc); // CHECK: @llvm.ppc.altivec.vrlb // CHECK-LE: @llvm.ppc.altivec.vrlb res_vs = vec_vrlh(vs, vus); // CHECK: @llvm.ppc.altivec.vrlh // CHECK-LE: @llvm.ppc.altivec.vrlh res_vus = vec_vrlh(vus, vus); // CHECK: @llvm.ppc.altivec.vrlh // CHECK-LE: @llvm.ppc.altivec.vrlh res_vi = vec_vrlw(vi, vui); // CHECK: @llvm.ppc.altivec.vrlw // CHECK-LE: @llvm.ppc.altivec.vrlw res_vui = vec_vrlw(vui, vui); // CHECK: @llvm.ppc.altivec.vrlw // CHECK-LE: @llvm.ppc.altivec.vrlw /* vec_round */ res_vf = vec_round(vf); // CHECK: @llvm.ppc.altivec.vrfin // CHECK-LE: @llvm.ppc.altivec.vrfin res_vf = vec_vrfin(vf); // CHECK: @llvm.ppc.altivec.vrfin // CHECK-LE: @llvm.ppc.altivec.vrfin /* vec_rsqrte */ res_vf = vec_rsqrte(vf); // CHECK: @llvm.ppc.altivec.vrsqrtefp // CHECK-LE: @llvm.ppc.altivec.vrsqrtefp res_vf = vec_vrsqrtefp(vf); // CHECK: @llvm.ppc.altivec.vrsqrtefp // CHECK-LE: @llvm.ppc.altivec.vrsqrtefp /* vec_sel */ res_vsc = vec_sel(vsc, vsc, vuc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK: and <16 x i8> // CHECK: or <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: or <16 x i8> res_vsc = vec_sel(vsc, vsc, vbc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK: and <16 x i8> // CHECK: or <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: or <16 x i8> res_vuc = vec_sel(vuc, vuc, vuc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK: and <16 x i8> // CHECK: or <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: or <16 x i8> res_vuc = vec_sel(vuc, vuc, vbc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK: and <16 x i8> // CHECK: or <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: or <16 x i8> res_vbc = vec_sel(vbc, vbc, vuc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK: and <16 x i8> // CHECK: or <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: or <16 x i8> res_vbc = vec_sel(vbc, vbc, vbc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK: and <16 x i8> // CHECK: or <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: or <16 x i8> res_vs = vec_sel(vs, vs, vus); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK: and <8 x i16> // CHECK: or <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: or <8 x i16> res_vs = vec_sel(vs, vs, vbs); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK: and <8 x i16> // CHECK: or <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: or <8 x i16> res_vus = vec_sel(vus, vus, vus); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK: and <8 x i16> // CHECK: or <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: or <8 x i16> res_vus = vec_sel(vus, vus, vbs); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK: and <8 x i16> // CHECK: or <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: or <8 x i16> res_vbs = vec_sel(vbs, vbs, vus); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK: and <8 x i16> // CHECK: or <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: or <8 x i16> res_vbs = vec_sel(vbs, vbs, vbs); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK: and <8 x i16> // CHECK: or <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: or <8 x i16> res_vi = vec_sel(vi, vi, vui); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK: and <4 x i32> // CHECK: or <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: or <4 x i32> res_vi = vec_sel(vi, vi, vbi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK: and <4 x i32> // CHECK: or <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: or <4 x i32> res_vui = vec_sel(vui, vui, vui); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK: and <4 x i32> // CHECK: or <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: or <4 x i32> res_vui = vec_sel(vui, vui, vbi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK: and <4 x i32> // CHECK: or <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: or <4 x i32> res_vbi = vec_sel(vbi, vbi, vui); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK: and <4 x i32> // CHECK: or <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: or <4 x i32> res_vbi = vec_sel(vbi, vbi, vbi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK: and <4 x i32> // CHECK: or <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: or <4 x i32> res_vf = vec_sel(vf, vf, vui); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK: and <4 x i32> // CHECK: or <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: or <4 x i32> res_vf = vec_sel(vf, vf, vbi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK: and <4 x i32> // CHECK: or <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: or <4 x i32> res_vsc = vec_vsel(vsc, vsc, vuc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK: and <16 x i8> // CHECK: or <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: or <16 x i8> res_vsc = vec_vsel(vsc, vsc, vbc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK: and <16 x i8> // CHECK: or <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: or <16 x i8> res_vuc = vec_vsel(vuc, vuc, vuc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK: and <16 x i8> // CHECK: or <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: or <16 x i8> res_vuc = vec_vsel(vuc, vuc, vbc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK: and <16 x i8> // CHECK: or <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: or <16 x i8> res_vbc = vec_vsel(vbc, vbc, vuc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK: and <16 x i8> // CHECK: or <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: or <16 x i8> res_vbc = vec_vsel(vbc, vbc, vbc); // CHECK: xor <16 x i8> // CHECK: and <16 x i8> // CHECK: and <16 x i8> // CHECK: or <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: and <16 x i8> // CHECK-LE: or <16 x i8> res_vs = vec_vsel(vs, vs, vus); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK: and <8 x i16> // CHECK: or <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: or <8 x i16> res_vs = vec_vsel(vs, vs, vbs); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK: and <8 x i16> // CHECK: or <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: or <8 x i16> res_vus = vec_vsel(vus, vus, vus); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK: and <8 x i16> // CHECK: or <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: or <8 x i16> res_vus = vec_vsel(vus, vus, vbs); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK: and <8 x i16> // CHECK: or <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: or <8 x i16> res_vbs = vec_vsel(vbs, vbs, vus); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK: and <8 x i16> // CHECK: or <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: or <8 x i16> res_vbs = vec_vsel(vbs, vbs, vbs); // CHECK: xor <8 x i16> // CHECK: and <8 x i16> // CHECK: and <8 x i16> // CHECK: or <8 x i16> // CHECK-LE: xor <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: and <8 x i16> // CHECK-LE: or <8 x i16> res_vi = vec_vsel(vi, vi, vui); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK: and <4 x i32> // CHECK: or <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: or <4 x i32> res_vi = vec_vsel(vi, vi, vbi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK: and <4 x i32> // CHECK: or <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: or <4 x i32> res_vui = vec_vsel(vui, vui, vui); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK: and <4 x i32> // CHECK: or <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: or <4 x i32> res_vui = vec_vsel(vui, vui, vbi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK: and <4 x i32> // CHECK: or <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: or <4 x i32> res_vbi = vec_vsel(vbi, vbi, vui); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK: and <4 x i32> // CHECK: or <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: or <4 x i32> res_vbi = vec_vsel(vbi, vbi, vbi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK: and <4 x i32> // CHECK: or <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: or <4 x i32> res_vf = vec_vsel(vf, vf, vui); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK: and <4 x i32> // CHECK: or <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: or <4 x i32> res_vf = vec_vsel(vf, vf, vbi); // CHECK: xor <4 x i32> // CHECK: and <4 x i32> // CHECK: and <4 x i32> // CHECK: or <4 x i32> // CHECK-LE: xor <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: or <4 x i32> /* vec_sl */ res_vsc = vec_sl(vsc, vuc); // CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <16 x i8> {{[0-9a-zA-Z%.]+}}, // CHECK: shl <16 x i8> {{[0-9a-zA-Z%.]+}}, [[UREM]] // CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <16 x i8> {{[0-9a-zA-Z%.]+}}, // CHECK-LE: shl <16 x i8> {{[0-9a-zA-Z%.]+}}, [[UREM]] res_vuc = vec_sl(vuc, vuc); // CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <16 x i8> {{[0-9a-zA-Z%.]+}}, // CHECK: shl <16 x i8> {{[0-9a-zA-Z%.]+}}, [[UREM]] // CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <16 x i8> {{[0-9a-zA-Z%.]+}}, // CHECK-LE: shl <16 x i8> {{[0-9a-zA-Z%.]+}}, [[UREM]] res_vs = vec_sl(vs, vus); // CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <8 x i16> {{[0-9a-zA-Z%.]+}}, // CHECK: shl <8 x i16> {{[0-9a-zA-Z%.]+}}, [[UREM]] // CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <8 x i16> {{[0-9a-zA-Z%.]+}}, // CHECK-LE: shl <8 x i16> {{[0-9a-zA-Z%.]+}}, [[UREM]] res_vus = vec_sl(vus, vus); // CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <8 x i16> {{[0-9a-zA-Z%.]+}}, // CHECK: shl <8 x i16> {{[0-9a-zA-Z%.]+}}, [[UREM]] // CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <8 x i16> {{[0-9a-zA-Z%.]+}}, // CHECK-LE: shl <8 x i16> {{[0-9a-zA-Z%.]+}}, [[UREM]] res_vi = vec_sl(vi, vui); // CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <4 x i32> {{[0-9a-zA-Z%.]+}}, // CHECK: shl <4 x i32> {{[0-9a-zA-Z%.]+}}, [[UREM]] // CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <4 x i32> {{[0-9a-zA-Z%.]+}}, // CHECK-LE: shl <4 x i32> {{[0-9a-zA-Z%.]+}}, [[UREM]] res_vui = vec_sl(vui, vui); // CHECK: [[UREM:[0-9a-zA-Z%.]+]] = urem <4 x i32> {{[0-9a-zA-Z%.]+}}, // CHECK: shl <4 x i32> {{[0-9a-zA-Z%.]+}}, [[UREM]] // CHECK-LE: [[UREM:[0-9a-zA-Z%.]+]] = urem <4 x i32> {{[0-9a-zA-Z%.]+}}, // CHECK-LE: shl <4 x i32> {{[0-9a-zA-Z%.]+}}, [[UREM]] res_vsc = vec_vslb(vsc, vuc); // CHECK: shl <16 x i8> // CHECK-LE: shl <16 x i8> res_vuc = vec_vslb(vuc, vuc); // CHECK: shl <16 x i8> // CHECK-LE: shl <16 x i8> res_vs = vec_vslh(vs, vus); // CHECK: shl <8 x i16> // CHECK-LE: shl <8 x i16> res_vus = vec_vslh(vus, vus); // CHECK: shl <8 x i16> // CHECK-LE: shl <8 x i16> res_vi = vec_vslw(vi, vui); // CHECK: shl <4 x i32> // CHECK-LE: shl <4 x i32> res_vui = vec_vslw(vui, vui); // CHECK: shl <4 x i32> // CHECK-LE: shl <4 x i32> /* vec_sld */ res_vsc = vec_sld(vsc, vsc, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_sld(vuc, vuc, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_sld(vs, vs, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_sld(vus, vus, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vbs = vec_sld(vbs, vbs, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: [[T1:%.+]] = bitcast <8 x i16> {{.+}} to <4 x i32> // CHECK: [[T2:%.+]] = bitcast <8 x i16> {{.+}} to <4 x i32> // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> [[T1]], <4 x i32> [[T2]], <16 x i8> // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: xor <16 x i8> // CHECK-LE: [[T1:%.+]] = bitcast <8 x i16> {{.+}} to <4 x i32> // CHECK-LE: [[T2:%.+]] = bitcast <8 x i16> {{.+}} to <4 x i32> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> [[T1]], <4 x i32> [[T2]], <16 x i8> res_vp = vec_sld(vp, vp, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_sld(vi, vi, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_sld(vui, vui, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vbi = vec_sld(vbi, vbi, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{.+}}, <4 x i32> {{.+}}, <16 x i8> // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: xor <16 x i8> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{.+}}, <4 x i32> {{.+}}, <16 x i8> res_vf = vec_sld(vf, vf, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm /* vec_sldw */ res_vsc = vec_sldw(vsc, vsc, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_sldw(vuc, vuc, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_sldw(vi, vi, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_sldw(vui, vui, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_sldw(vs, vs, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_sldw(vus, vus, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vsc = vec_vsldoi(vsc, vsc, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_vsldoi(vuc, vuc, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_vsldoi(vs, vs, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_vsldoi(vus, vus, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vp = vec_vsldoi(vp, vp, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_vsldoi(vi, vi, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_vsldoi(vui, vui, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vf = vec_vsldoi(vf, vf, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm /* vec_sll */ res_vsc = vec_sll(vsc, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vsc = vec_sll(vsc, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vsc = vec_sll(vsc, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vuc = vec_sll(vuc, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vuc = vec_sll(vuc, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vuc = vec_sll(vuc, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbc = vec_sll(vbc, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbc = vec_sll(vbc, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbc = vec_sll(vbc, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vs = vec_sll(vs, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vs = vec_sll(vs, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vs = vec_sll(vs, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vus = vec_sll(vus, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vus = vec_sll(vus, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vus = vec_sll(vus, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbs = vec_sll(vbs, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbs = vec_sll(vbs, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbs = vec_sll(vbs, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vp = vec_sll(vp, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vp = vec_sll(vp, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vp = vec_sll(vp, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vi = vec_sll(vi, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vi = vec_sll(vi, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vi = vec_sll(vi, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vui = vec_sll(vui, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vui = vec_sll(vui, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vui = vec_sll(vui, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbi = vec_sll(vbi, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbi = vec_sll(vbi, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbi = vec_sll(vbi, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vsc = vec_vsl(vsc, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vsc = vec_vsl(vsc, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vsc = vec_vsl(vsc, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vuc = vec_vsl(vuc, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vuc = vec_vsl(vuc, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vuc = vec_vsl(vuc, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbc = vec_vsl(vbc, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbc = vec_vsl(vbc, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbc = vec_vsl(vbc, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vs = vec_vsl(vs, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vs = vec_vsl(vs, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vs = vec_vsl(vs, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vus = vec_vsl(vus, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vus = vec_vsl(vus, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vus = vec_vsl(vus, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbs = vec_vsl(vbs, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbs = vec_vsl(vbs, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbs = vec_vsl(vbs, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vp = vec_vsl(vp, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vp = vec_vsl(vp, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vp = vec_vsl(vp, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vi = vec_vsl(vi, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vi = vec_vsl(vi, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vi = vec_vsl(vi, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vui = vec_vsl(vui, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vui = vec_vsl(vui, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vui = vec_vsl(vui, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbi = vec_vsl(vbi, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbi = vec_vsl(vbi, vus); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vbi = vec_vsl(vbi, vui); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl /* vec_slo */ res_vsc = vec_slo(vsc, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vsc = vec_slo(vsc, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vuc = vec_slo(vuc, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vuc = vec_slo(vuc, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vs = vec_slo(vs, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vs = vec_slo(vs, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vus = vec_slo(vus, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vus = vec_slo(vus, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vp = vec_slo(vp, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vp = vec_slo(vp, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vi = vec_slo(vi, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vi = vec_slo(vi, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vui = vec_slo(vui, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vui = vec_slo(vui, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vf = vec_slo(vf, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vf = vec_slo(vf, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vsc = vec_vslo(vsc, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vsc = vec_vslo(vsc, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vuc = vec_vslo(vuc, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vuc = vec_vslo(vuc, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vs = vec_vslo(vs, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vs = vec_vslo(vs, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vus = vec_vslo(vus, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vus = vec_vslo(vus, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vp = vec_vslo(vp, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vp = vec_vslo(vp, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vi = vec_vslo(vi, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vi = vec_vslo(vi, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vui = vec_vslo(vui, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vui = vec_vslo(vui, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vf = vec_vslo(vf, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vf = vec_vslo(vf, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo /* vec_splat */ res_vsc = vec_splat(vsc, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_splat(vuc, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbc = vec_splat(vbc, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_splat(vs, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_splat(vus, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbs = vec_splat(vbs, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vp = vec_splat(vp, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_splat(vi, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_splat(vui, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbi = vec_splat(vbi, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vf = vec_splat(vf, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vsc = vec_vspltb(vsc, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_vspltb(vuc, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbc = vec_vspltb(vbc, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_vsplth(vs, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_vsplth(vus, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbs = vec_vsplth(vbs, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vp = vec_vsplth(vp, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_vspltw(vi, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_vspltw(vui, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbi = vec_vspltw(vbi, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vf = vec_vspltw(vf, 0); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm /* vec_splat_s8 */ res_vsc = vec_splat_s8(0x09); // TODO: add check res_vsc = vec_vspltisb(0x09); // TODO: add check /* vec_splat_s16 */ res_vs = vec_splat_s16(0x09); // TODO: add check res_vs = vec_vspltish(0x09); // TODO: add check /* vec_splat_s32 */ res_vi = vec_splat_s32(0x09); // TODO: add check res_vi = vec_vspltisw(0x09); // TODO: add check /* vec_splat_u8 */ res_vuc = vec_splat_u8(0x09); // TODO: add check /* vec_splat_u16 */ res_vus = vec_splat_u16(0x09); // TODO: add check /* vec_splat_u32 */ res_vui = vec_splat_u32(0x09); // TODO: add check /* vec_sr */ res_vsc = vec_sr(vsc, vuc); // CHECK: lshr <16 x i8> // CHECK-LE: lshr <16 x i8> res_vuc = vec_sr(vuc, vuc); // CHECK: lshr <16 x i8> // CHECK-LE: lshr <16 x i8> res_vs = vec_sr(vs, vus); // CHECK: lshr <8 x i16> // CHECK-LE: lshr <8 x i16> res_vus = vec_sr(vus, vus); // CHECK: lshr <8 x i16> // CHECK-LE: lshr <8 x i16> res_vi = vec_sr(vi, vui); // CHECK: lshr <4 x i32> // CHECK-LE: lshr <4 x i32> res_vui = vec_sr(vui, vui); // CHECK: lshr <4 x i32> // CHECK-LE: lshr <4 x i32> res_vsc = vec_vsrb(vsc, vuc); // CHECK: shr <16 x i8> // CHECK-LE: shr <16 x i8> res_vuc = vec_vsrb(vuc, vuc); // CHECK: shr <16 x i8> // CHECK-LE: shr <16 x i8> res_vs = vec_vsrh(vs, vus); // CHECK: shr <8 x i16> // CHECK-LE: shr <8 x i16> res_vus = vec_vsrh(vus, vus); // CHECK: shr <8 x i16> // CHECK-LE: shr <8 x i16> res_vi = vec_vsrw(vi, vui); // CHECK: shr <4 x i32> // CHECK-LE: shr <4 x i32> res_vui = vec_vsrw(vui, vui); // CHECK: shr <4 x i32> // CHECK-LE: shr <4 x i32> /* vec_sra */ res_vsc = vec_sra(vsc, vuc); // CHECK: @llvm.ppc.altivec.vsrab // CHECK-LE: @llvm.ppc.altivec.vsrab res_vuc = vec_sra(vuc, vuc); // CHECK: @llvm.ppc.altivec.vsrab // CHECK-LE: @llvm.ppc.altivec.vsrab res_vs = vec_sra(vs, vus); // CHECK: @llvm.ppc.altivec.vsrah // CHECK-LE: @llvm.ppc.altivec.vsrah res_vus = vec_sra(vus, vus); // CHECK: @llvm.ppc.altivec.vsrah // CHECK-LE: @llvm.ppc.altivec.vsrah res_vi = vec_sra(vi, vui); // CHECK: @llvm.ppc.altivec.vsraw // CHECK-LE: @llvm.ppc.altivec.vsraw res_vui = vec_sra(vui, vui); // CHECK: @llvm.ppc.altivec.vsraw // CHECK-LE: @llvm.ppc.altivec.vsraw res_vsc = vec_vsrab(vsc, vuc); // CHECK: @llvm.ppc.altivec.vsrab // CHECK-LE: @llvm.ppc.altivec.vsrab res_vuc = vec_vsrab(vuc, vuc); // CHECK: @llvm.ppc.altivec.vsrab // CHECK-LE: @llvm.ppc.altivec.vsrab res_vs = vec_vsrah(vs, vus); // CHECK: @llvm.ppc.altivec.vsrah // CHECK-LE: @llvm.ppc.altivec.vsrah res_vus = vec_vsrah(vus, vus); // CHECK: @llvm.ppc.altivec.vsrah // CHECK-LE: @llvm.ppc.altivec.vsrah res_vi = vec_vsraw(vi, vui); // CHECK: @llvm.ppc.altivec.vsraw // CHECK-LE: @llvm.ppc.altivec.vsraw res_vui = vec_vsraw(vui, vui); // CHECK: @llvm.ppc.altivec.vsraw // CHECK-LE: @llvm.ppc.altivec.vsraw /* vec_srl */ res_vsc = vec_srl(vsc, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vsc = vec_srl(vsc, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vsc = vec_srl(vsc, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vuc = vec_srl(vuc, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vuc = vec_srl(vuc, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vuc = vec_srl(vuc, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbc = vec_srl(vbc, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbc = vec_srl(vbc, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbc = vec_srl(vbc, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vs = vec_srl(vs, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vs = vec_srl(vs, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vs = vec_srl(vs, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vus = vec_srl(vus, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vus = vec_srl(vus, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vus = vec_srl(vus, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbs = vec_srl(vbs, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbs = vec_srl(vbs, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbs = vec_srl(vbs, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vp = vec_srl(vp, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vp = vec_srl(vp, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vp = vec_srl(vp, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vi = vec_srl(vi, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vi = vec_srl(vi, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vi = vec_srl(vi, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vui = vec_srl(vui, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vui = vec_srl(vui, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vui = vec_srl(vui, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbi = vec_srl(vbi, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbi = vec_srl(vbi, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbi = vec_srl(vbi, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vsc = vec_vsr(vsc, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vsc = vec_vsr(vsc, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vsc = vec_vsr(vsc, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vuc = vec_vsr(vuc, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vuc = vec_vsr(vuc, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vuc = vec_vsr(vuc, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbc = vec_vsr(vbc, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbc = vec_vsr(vbc, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbc = vec_vsr(vbc, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vs = vec_vsr(vs, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vs = vec_vsr(vs, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vs = vec_vsr(vs, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vus = vec_vsr(vus, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vus = vec_vsr(vus, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vus = vec_vsr(vus, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbs = vec_vsr(vbs, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbs = vec_vsr(vbs, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbs = vec_vsr(vbs, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vp = vec_vsr(vp, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vp = vec_vsr(vp, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vp = vec_vsr(vp, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vi = vec_vsr(vi, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vi = vec_vsr(vi, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vi = vec_vsr(vi, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vui = vec_vsr(vui, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vui = vec_vsr(vui, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vui = vec_vsr(vui, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbi = vec_vsr(vbi, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbi = vec_vsr(vbi, vus); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vbi = vec_vsr(vbi, vui); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr /* vec_sro */ res_vsc = vec_sro(vsc, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vsc = vec_sro(vsc, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vuc = vec_sro(vuc, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vuc = vec_sro(vuc, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vs = vec_sro(vs, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vs = vec_sro(vs, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vus = vec_sro(vus, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vus = vec_sro(vus, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vp = vec_sro(vp, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vp = vec_sro(vp, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vi = vec_sro(vi, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vi = vec_sro(vi, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vui = vec_sro(vui, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vui = vec_sro(vui, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vf = vec_sro(vf, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vf = vec_sro(vf, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vsc = vec_vsro(vsc, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vsc = vec_vsro(vsc, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vuc = vec_vsro(vuc, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vuc = vec_vsro(vuc, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vs = vec_vsro(vs, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vs = vec_vsro(vs, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vus = vec_vsro(vus, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vus = vec_vsro(vus, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vp = vec_vsro(vp, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vp = vec_vsro(vp, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vi = vec_vsro(vi, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vi = vec_vsro(vi, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vui = vec_vsro(vui, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vui = vec_vsro(vui, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vf = vec_vsro(vf, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vf = vec_vsro(vf, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro /* vec_st */ vec_st(vsc, 0, &vsc); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vsc, 0, ¶m_sc); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vuc, 0, &vuc); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vuc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vbc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vbc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vbc, 0, &vbc); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vs, 0, &vs); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vs, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vus, 0, &vus); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vus, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vbs, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vbs, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vbs, 0, &vbs); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vp, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vp, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vp, 0, &vp); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vi, 0, &vi); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vi, 0, ¶m_i); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vui, 0, &vui); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vui, 0, ¶m_ui); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vbi, 0, ¶m_i); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vbi, 0, ¶m_ui); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vbi, 0, &vbi); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vf, 0, &vf); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_st(vf, 0, ¶m_f); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vsc, 0, &vsc); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vsc, 0, ¶m_sc); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vuc, 0, &vuc); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vuc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vbc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vbc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vbc, 0, &vbc); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vs, 0, &vs); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vs, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vus, 0, &vus); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vus, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vbs, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vbs, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vbs, 0, &vbs); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vp, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vp, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vp, 0, &vp); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vi, 0, &vi); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vi, 0, ¶m_i); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vui, 0, &vui); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vui, 0, ¶m_ui); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vbi, 0, ¶m_i); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vbi, 0, ¶m_ui); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vbi, 0, &vbi); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vf, 0, &vf); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvx(vf, 0, ¶m_f); // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.stvx /* vec_ste */ vec_ste(vsc, 0, ¶m_sc); // CHECK: @llvm.ppc.altivec.stvebx // CHECK-LE: @llvm.ppc.altivec.stvebx vec_ste(vuc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.stvebx // CHECK-LE: @llvm.ppc.altivec.stvebx vec_ste(vbc, 0, ¶m_sc); // CHECK: @llvm.ppc.altivec.stvebx // CHECK-LE: @llvm.ppc.altivec.stvebx vec_ste(vbc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.stvebx // CHECK-LE: @llvm.ppc.altivec.stvebx vec_ste(vs, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvehx // CHECK-LE: @llvm.ppc.altivec.stvehx vec_ste(vus, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvehx // CHECK-LE: @llvm.ppc.altivec.stvehx vec_ste(vbs, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvehx // CHECK-LE: @llvm.ppc.altivec.stvehx vec_ste(vbs, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvehx // CHECK-LE: @llvm.ppc.altivec.stvehx vec_ste(vp, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvehx // CHECK-LE: @llvm.ppc.altivec.stvehx vec_ste(vp, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvehx // CHECK-LE: @llvm.ppc.altivec.stvehx vec_ste(vi, 0, ¶m_i); // CHECK: @llvm.ppc.altivec.stvewx // CHECK-LE: @llvm.ppc.altivec.stvewx vec_ste(vui, 0, ¶m_ui); // CHECK: @llvm.ppc.altivec.stvewx // CHECK-LE: @llvm.ppc.altivec.stvewx vec_ste(vbi, 0, ¶m_i); // CHECK: @llvm.ppc.altivec.stvewx // CHECK-LE: @llvm.ppc.altivec.stvewx vec_ste(vbi, 0, ¶m_ui); // CHECK: @llvm.ppc.altivec.stvewx // CHECK-LE: @llvm.ppc.altivec.stvewx vec_ste(vf, 0, ¶m_f); // CHECK: @llvm.ppc.altivec.stvewx // CHECK-LE: @llvm.ppc.altivec.stvewx vec_stvebx(vsc, 0, ¶m_sc); // CHECK: @llvm.ppc.altivec.stvebx // CHECK-LE: @llvm.ppc.altivec.stvebx vec_stvebx(vuc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.stvebx // CHECK-LE: @llvm.ppc.altivec.stvebx vec_stvebx(vbc, 0, ¶m_sc); // CHECK: @llvm.ppc.altivec.stvebx // CHECK-LE: @llvm.ppc.altivec.stvebx vec_stvebx(vbc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.stvebx // CHECK-LE: @llvm.ppc.altivec.stvebx vec_stvehx(vs, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvehx // CHECK-LE: @llvm.ppc.altivec.stvehx vec_stvehx(vus, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvehx // CHECK-LE: @llvm.ppc.altivec.stvehx vec_stvehx(vbs, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvehx // CHECK-LE: @llvm.ppc.altivec.stvehx vec_stvehx(vbs, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvehx // CHECK-LE: @llvm.ppc.altivec.stvehx vec_stvehx(vp, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvehx // CHECK-LE: @llvm.ppc.altivec.stvehx vec_stvehx(vp, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvehx // CHECK-LE: @llvm.ppc.altivec.stvehx vec_stvewx(vi, 0, ¶m_i); // CHECK: @llvm.ppc.altivec.stvewx // CHECK-LE: @llvm.ppc.altivec.stvewx vec_stvewx(vui, 0, ¶m_ui); // CHECK: @llvm.ppc.altivec.stvewx // CHECK-LE: @llvm.ppc.altivec.stvewx vec_stvewx(vbi, 0, ¶m_i); // CHECK: @llvm.ppc.altivec.stvewx // CHECK-LE: @llvm.ppc.altivec.stvewx vec_stvewx(vbi, 0, ¶m_ui); // CHECK: @llvm.ppc.altivec.stvewx // CHECK-LE: @llvm.ppc.altivec.stvewx vec_stvewx(vf, 0, ¶m_f); // CHECK: @llvm.ppc.altivec.stvewx // CHECK-LE: @llvm.ppc.altivec.stvewx /* vec_stl */ vec_stl(vsc, 0, &vsc); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vsc, 0, ¶m_sc); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vuc, 0, &vuc); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vuc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vbc, 0, ¶m_sc); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vbc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vbc, 0, &vbc); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vs, 0, &vs); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vs, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vus, 0, &vus); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vus, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vbs, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vbs, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vbs, 0, &vbs); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vp, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vp, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vp, 0, &vp); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vi, 0, &vi); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vi, 0, ¶m_i); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vui, 0, &vui); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vui, 0, ¶m_ui); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vbi, 0, ¶m_i); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vbi, 0, ¶m_ui); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vbi, 0, &vbi); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vf, 0, &vf); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stl(vf, 0, ¶m_f); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vsc, 0, &vsc); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vsc, 0, ¶m_sc); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vuc, 0, &vuc); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vuc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vbc, 0, ¶m_sc); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vbc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vbc, 0, &vbc); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vs, 0, &vs); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vs, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vus, 0, &vus); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vus, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vbs, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vbs, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vbs, 0, &vbs); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vp, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vp, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vp, 0, &vp); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vi, 0, &vi); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vi, 0, ¶m_i); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vui, 0, &vui); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vui, 0, ¶m_ui); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vbi, 0, ¶m_i); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vbi, 0, ¶m_ui); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vbi, 0, &vbi); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vf, 0, &vf); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvxl(vf, 0, ¶m_f); // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.stvxl /* vec_sub */ res_vsc = vec_sub(vsc, vsc); // CHECK: sub <16 x i8> // CHECK-LE: sub <16 x i8> res_vsc = vec_sub(vbc, vsc); // CHECK: sub <16 x i8> // CHECK-LE: sub <16 x i8> res_vsc = vec_sub(vsc, vbc); // CHECK: sub <16 x i8> // CHECK-LE: sub <16 x i8> res_vuc = vec_sub(vuc, vuc); // CHECK: sub <16 x i8> // CHECK-LE: sub <16 x i8> res_vuc = vec_sub(vbc, vuc); // CHECK: sub <16 x i8> // CHECK-LE: sub <16 x i8> res_vuc = vec_sub(vuc, vbc); // CHECK: sub <16 x i8> // CHECK-LE: sub <16 x i8> res_vs = vec_sub(vs, vs); // CHECK: sub <8 x i16> // CHECK-LE: sub <8 x i16> res_vs = vec_sub(vbs, vs); // CHECK: sub <8 x i16> // CHECK-LE: sub <8 x i16> res_vs = vec_sub(vs, vbs); // CHECK: sub <8 x i16> // CHECK-LE: sub <8 x i16> res_vus = vec_sub(vus, vus); // CHECK: sub <8 x i16> // CHECK-LE: sub <8 x i16> res_vus = vec_sub(vbs, vus); // CHECK: sub <8 x i16> // CHECK-LE: sub <8 x i16> res_vus = vec_sub(vus, vbs); // CHECK: sub <8 x i16> // CHECK-LE: sub <8 x i16> res_vi = vec_sub(vi, vi); // CHECK: sub <4 x i32> // CHECK-LE: sub <4 x i32> res_vi = vec_sub(vbi, vi); // CHECK: sub <4 x i32> // CHECK-LE: sub <4 x i32> res_vi = vec_sub(vi, vbi); // CHECK: sub <4 x i32> // CHECK-LE: sub <4 x i32> res_vui = vec_sub(vui, vui); // CHECK: sub <4 x i32> // CHECK-LE: sub <4 x i32> res_vui = vec_sub(vbi, vui); // CHECK: sub <4 x i32> // CHECK-LE: sub <4 x i32> res_vui = vec_sub(vui, vbi); // CHECK: sub <4 x i32> // CHECK-LE: sub <4 x i32> res_vf = vec_sub(vf, vf); // CHECK: fsub <4 x float> // CHECK-LE: fsub <4 x float> res_vsc = vec_vsububm(vsc, vsc); // CHECK: sub <16 x i8> // CHECK-LE: sub <16 x i8> res_vsc = vec_vsububm(vbc, vsc); // CHECK: sub <16 x i8> // CHECK-LE: sub <16 x i8> res_vsc = vec_vsububm(vsc, vbc); // CHECK: sub <16 x i8> // CHECK-LE: sub <16 x i8> res_vuc = vec_vsububm(vuc, vuc); // CHECK: sub <16 x i8> // CHECK-LE: sub <16 x i8> res_vuc = vec_vsububm(vbc, vuc); // CHECK: sub <16 x i8> // CHECK-LE: sub <16 x i8> res_vuc = vec_vsububm(vuc, vbc); // CHECK: sub <16 x i8> // CHECK-LE: sub <16 x i8> res_vs = vec_vsubuhm(vs, vs); // CHECK: sub <8 x i16> // CHECK-LE: sub <8 x i16> res_vs = vec_vsubuhm(vbs, vus); // CHECK: sub <8 x i16> // CHECK-LE: sub <8 x i16> res_vs = vec_vsubuhm(vus, vbs); // CHECK: sub <8 x i16> // CHECK-LE: sub <8 x i16> res_vus = vec_vsubuhm(vus, vus); // CHECK: sub <8 x i16> // CHECK-LE: sub <8 x i16> res_vus = vec_vsubuhm(vbs, vus); // CHECK: sub <8 x i16> // CHECK-LE: sub <8 x i16> res_vus = vec_vsubuhm(vus, vbs); // CHECK: sub <8 x i16> // CHECK-LE: sub <8 x i16> res_vi = vec_vsubuwm(vi, vi); // CHECK: sub <4 x i32> // CHECK-LE: sub <4 x i32> res_vi = vec_vsubuwm(vbi, vi); // CHECK: sub <4 x i32> // CHECK-LE: sub <4 x i32> res_vi = vec_vsubuwm(vi, vbi); // CHECK: sub <4 x i32> // CHECK-LE: sub <4 x i32> res_vui = vec_vsubuwm(vui, vui); // CHECK: sub <4 x i32> // CHECK-LE: sub <4 x i32> res_vui = vec_vsubuwm(vbi, vui); // CHECK: sub <4 x i32> // CHECK-LE: sub <4 x i32> res_vui = vec_vsubuwm(vui, vbi); // CHECK: sub <4 x i32> // CHECK-LE: sub <4 x i32> res_vf = vec_vsubfp(vf, vf); // CHECK: fsub <4 x float> // CHECK-LE: fsub <4 x float> /* vec_subc */ res_vui = vec_subc(vui, vui); // CHECK: @llvm.ppc.altivec.vsubcuw // CHECK-LE: @llvm.ppc.altivec.vsubcuw res_vi = vec_subc(vi, vi); // CHECK: @llvm.ppc.altivec.vsubcuw // CHECK-LE: @llvm.ppc.altivec.vsubcuw res_vui = vec_vsubcuw(vui, vui); // CHECK: @llvm.ppc.altivec.vsubcuw // CHECK-LE: @llvm.ppc.altivec.vsubcuw /* vec_subs */ res_vsc = vec_subs(vsc, vsc); // CHECK: @llvm.ppc.altivec.vsubsbs // CHECK-LE: @llvm.ppc.altivec.vsubsbs res_vsc = vec_subs(vbc, vsc); // CHECK: @llvm.ppc.altivec.vsubsbs // CHECK-LE: @llvm.ppc.altivec.vsubsbs res_vsc = vec_subs(vsc, vbc); // CHECK: @llvm.ppc.altivec.vsubsbs // CHECK-LE: @llvm.ppc.altivec.vsubsbs res_vuc = vec_subs(vuc, vuc); // CHECK: @llvm.ppc.altivec.vsububs // CHECK-LE: @llvm.ppc.altivec.vsububs res_vuc = vec_subs(vbc, vuc); // CHECK: @llvm.ppc.altivec.vsububs // CHECK-LE: @llvm.ppc.altivec.vsububs res_vuc = vec_subs(vuc, vbc); // CHECK: @llvm.ppc.altivec.vsububs // CHECK-LE: @llvm.ppc.altivec.vsububs res_vs = vec_subs(vs, vs); // CHECK: @llvm.ppc.altivec.vsubshs // CHECK-LE: @llvm.ppc.altivec.vsubshs res_vs = vec_subs(vbs, vs); // CHECK: @llvm.ppc.altivec.vsubshs // CHECK-LE: @llvm.ppc.altivec.vsubshs res_vs = vec_subs(vs, vbs); // CHECK: @llvm.ppc.altivec.vsubshs // CHECK-LE: @llvm.ppc.altivec.vsubshs res_vus = vec_subs(vus, vus); // CHECK: @llvm.ppc.altivec.vsubuhs // CHECK-LE: @llvm.ppc.altivec.vsubuhs res_vus = vec_subs(vbs, vus); // CHECK: @llvm.ppc.altivec.vsubuhs // CHECK-LE: @llvm.ppc.altivec.vsubuhs res_vus = vec_subs(vus, vbs); // CHECK: @llvm.ppc.altivec.vsubuhs // CHECK-LE: @llvm.ppc.altivec.vsubuhs res_vi = vec_subs(vi, vi); // CHECK: @llvm.ppc.altivec.vsubsws // CHECK-LE: @llvm.ppc.altivec.vsubsws res_vi = vec_subs(vbi, vi); // CHECK: @llvm.ppc.altivec.vsubsws // CHECK-LE: @llvm.ppc.altivec.vsubsws res_vi = vec_subs(vi, vbi); // CHECK: @llvm.ppc.altivec.vsubsws // CHECK-LE: @llvm.ppc.altivec.vsubsws res_vui = vec_subs(vui, vui); // CHECK: @llvm.ppc.altivec.vsubuws // CHECK-LE: @llvm.ppc.altivec.vsubuws res_vui = vec_subs(vbi, vui); // CHECK: @llvm.ppc.altivec.vsubuws // CHECK-LE: @llvm.ppc.altivec.vsubuws res_vui = vec_subs(vui, vbi); // CHECK: @llvm.ppc.altivec.vsubuws // CHECK-LE: @llvm.ppc.altivec.vsubuws res_vi = vec_sube(vi, vi, vi); // CHECK: and <4 x i32> // CHECK: xor <4 x i32> {{%[0-9]+}}, // CHECK: add <4 x i32> // CHECK: add <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: xor <4 x i32> {{%[0-9]+}}, // CHECK-LE: add <4 x i32> // CHECK-LE: add <4 x i32> res_vui = vec_sube(vui, vui, vui); // CHECK: and <4 x i32> // CHECK: xor <4 x i32> {{%[0-9]+}}, // CHECK: add <4 x i32> // CHECK: add <4 x i32> // CHECK-LE: and <4 x i32> // CHECK-LE: xor <4 x i32> {{%[0-9]+}}, // CHECK-LE: add <4 x i32> // CHECK-LE: add <4 x i32> res_vsc = vec_vsubsbs(vsc, vsc); // CHECK: @llvm.ppc.altivec.vsubsbs // CHECK-LE: @llvm.ppc.altivec.vsubsbs res_vsc = vec_vsubsbs(vbc, vsc); // CHECK: @llvm.ppc.altivec.vsubsbs // CHECK-LE: @llvm.ppc.altivec.vsubsbs res_vsc = vec_vsubsbs(vsc, vbc); // CHECK: @llvm.ppc.altivec.vsubsbs // CHECK-LE: @llvm.ppc.altivec.vsubsbs res_vuc = vec_vsububs(vuc, vuc); // CHECK: @llvm.ppc.altivec.vsububs // CHECK-LE: @llvm.ppc.altivec.vsububs res_vuc = vec_vsububs(vbc, vuc); // CHECK: @llvm.ppc.altivec.vsububs // CHECK-LE: @llvm.ppc.altivec.vsububs res_vuc = vec_vsububs(vuc, vbc); // CHECK: @llvm.ppc.altivec.vsububs // CHECK-LE: @llvm.ppc.altivec.vsububs res_vs = vec_vsubshs(vs, vs); // CHECK: @llvm.ppc.altivec.vsubshs // CHECK-LE: @llvm.ppc.altivec.vsubshs res_vs = vec_vsubshs(vbs, vs); // CHECK: @llvm.ppc.altivec.vsubshs // CHECK-LE: @llvm.ppc.altivec.vsubshs res_vs = vec_vsubshs(vs, vbs); // CHECK: @llvm.ppc.altivec.vsubshs // CHECK-LE: @llvm.ppc.altivec.vsubshs res_vus = vec_vsubuhs(vus, vus); // CHECK: @llvm.ppc.altivec.vsubuhs // CHECK-LE: @llvm.ppc.altivec.vsubuhs res_vus = vec_vsubuhs(vbs, vus); // CHECK: @llvm.ppc.altivec.vsubuhs // CHECK-LE: @llvm.ppc.altivec.vsubuhs res_vus = vec_vsubuhs(vus, vbs); // CHECK: @llvm.ppc.altivec.vsubuhs // CHECK-LE: @llvm.ppc.altivec.vsubuhs res_vi = vec_vsubsws(vi, vi); // CHECK: @llvm.ppc.altivec.vsubsws // CHECK-LE: @llvm.ppc.altivec.vsubsws res_vi = vec_vsubsws(vbi, vi); // CHECK: @llvm.ppc.altivec.vsubsws // CHECK-LE: @llvm.ppc.altivec.vsubsws res_vi = vec_vsubsws(vi, vbi); // CHECK: @llvm.ppc.altivec.vsubsws // CHECK-LE: @llvm.ppc.altivec.vsubsws res_vui = vec_vsubuws(vui, vui); // CHECK: @llvm.ppc.altivec.vsubuws // CHECK-LE: @llvm.ppc.altivec.vsubuws res_vui = vec_vsubuws(vbi, vui); // CHECK: @llvm.ppc.altivec.vsubuws // CHECK-LE: @llvm.ppc.altivec.vsubuws res_vui = vec_vsubuws(vui, vbi); // CHECK: @llvm.ppc.altivec.vsubuws // CHECK-LE: @llvm.ppc.altivec.vsubuws /* vec_sum4s */ res_vi = vec_sum4s(vsc, vi); // CHECK: @llvm.ppc.altivec.vsum4sbs // CHECK-LE: @llvm.ppc.altivec.vsum4sbs res_vui = vec_sum4s(vuc, vui); // CHECK: @llvm.ppc.altivec.vsum4ubs // CHECK-LE: @llvm.ppc.altivec.vsum4ubs res_vi = vec_sum4s(vs, vi); // CHECK: @llvm.ppc.altivec.vsum4shs // CHECK-LE: @llvm.ppc.altivec.vsum4shs res_vi = vec_vsum4sbs(vsc, vi); // CHECK: @llvm.ppc.altivec.vsum4sbs // CHECK-LE: @llvm.ppc.altivec.vsum4sbs res_vui = vec_vsum4ubs(vuc, vui); // CHECK: @llvm.ppc.altivec.vsum4ubs // CHECK-LE: @llvm.ppc.altivec.vsum4ubs res_vi = vec_vsum4shs(vs, vi); // CHECK: @llvm.ppc.altivec.vsum4shs // CHECK-LE: @llvm.ppc.altivec.vsum4shs /* vec_sum2s */ res_vi = vec_sum2s(vi, vi); // CHECK: @llvm.ppc.altivec.vsum2sws // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vsum2sws // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_vsum2sws(vi, vi); // CHECK: @llvm.ppc.altivec.vsum2sws // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vsum2sws // CHECK-LE: @llvm.ppc.altivec.vperm /* vec_sums */ res_vi = vec_sums(vi, vi); // CHECK: @llvm.ppc.altivec.vsumsws // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vsumsws res_vi = vec_vsumsws(vi, vi); // CHECK: @llvm.ppc.altivec.vsumsws // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vsumsws /* vec_trunc */ res_vf = vec_trunc(vf); // CHECK: @llvm.ppc.altivec.vrfiz // CHECK-LE: @llvm.ppc.altivec.vrfiz res_vf = vec_vrfiz(vf); // CHECK: @llvm.ppc.altivec.vrfiz // CHECK-LE: @llvm.ppc.altivec.vrfiz /* vec_unpackh */ res_vs = vec_unpackh(vsc); // CHECK: @llvm.ppc.altivec.vupkhsb // CHECK-LE: @llvm.ppc.altivec.vupklsb res_vbs = vec_unpackh(vbc); // CHECK: @llvm.ppc.altivec.vupkhsb // CHECK-LE: @llvm.ppc.altivec.vupklsb res_vi = vec_unpackh(vs); // CHECK: @llvm.ppc.altivec.vupkhsh // CHECK-LE: @llvm.ppc.altivec.vupklsh res_vbi = vec_unpackh(vbs); // CHECK: @llvm.ppc.altivec.vupkhsh // CHECK-LE: @llvm.ppc.altivec.vupklsh res_vui = vec_unpackh(vp); // CHECK: @llvm.ppc.altivec.vupkhpx // CHECK-LE: @llvm.ppc.altivec.vupklpx res_vs = vec_vupkhsb(vsc); // CHECK: @llvm.ppc.altivec.vupkhsb // CHECK-LE: @llvm.ppc.altivec.vupklsb res_vbs = vec_vupkhsb(vbc); // CHECK: @llvm.ppc.altivec.vupkhsb // CHECK-LE: @llvm.ppc.altivec.vupklsb res_vi = vec_vupkhsh(vs); // CHECK: @llvm.ppc.altivec.vupkhsh // CHECK-LE: @llvm.ppc.altivec.vupklsh res_vbi = vec_vupkhsh(vbs); // CHECK: @llvm.ppc.altivec.vupkhsh // CHECK-LE: @llvm.ppc.altivec.vupklsh res_vui = vec_vupkhsh(vp); // CHECK: @llvm.ppc.altivec.vupkhpx // CHECK-LE: @llvm.ppc.altivec.vupklpx /* vec_unpackl */ res_vs = vec_unpackl(vsc); // CHECK: @llvm.ppc.altivec.vupklsb // CHECK-LE: @llvm.ppc.altivec.vupkhsb res_vbs = vec_unpackl(vbc); // CHECK: @llvm.ppc.altivec.vupklsb // CHECK-LE: @llvm.ppc.altivec.vupkhsb res_vi = vec_unpackl(vs); // CHECK: @llvm.ppc.altivec.vupklsh // CHECK-LE: @llvm.ppc.altivec.vupkhsh res_vbi = vec_unpackl(vbs); // CHECK: @llvm.ppc.altivec.vupklsh // CHECK-LE: @llvm.ppc.altivec.vupkhsh res_vui = vec_unpackl(vp); // CHECK: @llvm.ppc.altivec.vupklpx // CHECK-LE: @llvm.ppc.altivec.vupkhpx res_vs = vec_vupklsb(vsc); // CHECK: @llvm.ppc.altivec.vupklsb // CHECK-LE: @llvm.ppc.altivec.vupkhsb res_vbs = vec_vupklsb(vbc); // CHECK: @llvm.ppc.altivec.vupklsb // CHECK-LE: @llvm.ppc.altivec.vupkhsb res_vi = vec_vupklsh(vs); // CHECK: @llvm.ppc.altivec.vupklsh // CHECK-LE: @llvm.ppc.altivec.vupkhsh res_vbi = vec_vupklsh(vbs); // CHECK: @llvm.ppc.altivec.vupklsh // CHECK-LE: @llvm.ppc.altivec.vupkhsh res_vui = vec_vupklsh(vp); // CHECK: @llvm.ppc.altivec.vupklpx // CHECK-LE: @llvm.ppc.altivec.vupkhpx /* vec_xor */ res_vsc = vec_xor(vsc, vsc); // CHECK: xor <16 x i8> // CHECK-LE: xor <16 x i8> res_vsc = vec_xor(vbc, vsc); // CHECK: xor <16 x i8> // CHECK-LE: xor <16 x i8> res_vsc = vec_xor(vsc, vbc); // CHECK: xor <16 x i8> // CHECK-LE: xor <16 x i8> res_vuc = vec_xor(vuc, vuc); // CHECK: xor <16 x i8> // CHECK-LE: xor <16 x i8> res_vuc = vec_xor(vbc, vuc); // CHECK: xor <16 x i8> // CHECK-LE: xor <16 x i8> res_vuc = vec_xor(vuc, vbc); // CHECK: xor <16 x i8> // CHECK-LE: xor <16 x i8> res_vbc = vec_xor(vbc, vbc); // CHECK: xor <16 x i8> // CHECK-LE: xor <16 x i8> res_vs = vec_xor(vs, vs); // CHECK: xor <8 x i16> // CHECK-LE: xor <8 x i16> res_vs = vec_xor(vbs, vs); // CHECK: xor <8 x i16> // CHECK-LE: xor <8 x i16> res_vs = vec_xor(vs, vbs); // CHECK: xor <8 x i16> // CHECK-LE: xor <8 x i16> res_vus = vec_xor(vus, vus); // CHECK: xor <8 x i16> // CHECK-LE: xor <8 x i16> res_vus = vec_xor(vbs, vus); // CHECK: xor <8 x i16> // CHECK-LE: xor <8 x i16> res_vus = vec_xor(vus, vbs); // CHECK: xor <8 x i16> // CHECK-LE: xor <8 x i16> res_vbs = vec_xor(vbs, vbs); // CHECK: xor <8 x i16> // CHECK-LE: xor <8 x i16> res_vi = vec_xor(vi, vi); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vi = vec_xor(vbi, vi); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vi = vec_xor(vi, vbi); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vui = vec_xor(vui, vui); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vui = vec_xor(vbi, vui); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vui = vec_xor(vui, vbi); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vbi = vec_xor(vbi, vbi); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vf = vec_xor(vf, vf); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vf = vec_xor(vbi, vf); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vf = vec_xor(vf, vbi); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vsc = vec_vxor(vsc, vsc); // CHECK: xor <16 x i8> // CHECK-LE: xor <16 x i8> res_vsc = vec_vxor(vbc, vsc); // CHECK: xor <16 x i8> // CHECK-LE: xor <16 x i8> res_vsc = vec_vxor(vsc, vbc); // CHECK: xor <16 x i8> // CHECK-LE: xor <16 x i8> res_vuc = vec_vxor(vuc, vuc); // CHECK: xor <16 x i8> // CHECK-LE: xor <16 x i8> res_vuc = vec_vxor(vbc, vuc); // CHECK: xor <16 x i8> // CHECK-LE: xor <16 x i8> res_vuc = vec_vxor(vuc, vbc); // CHECK: xor <16 x i8> // CHECK-LE: xor <16 x i8> res_vbc = vec_vxor(vbc, vbc); // CHECK: xor <16 x i8> // CHECK-LE: xor <16 x i8> res_vs = vec_vxor(vs, vs); // CHECK: xor <8 x i16> // CHECK-LE: xor <8 x i16> res_vs = vec_vxor(vbs, vs); // CHECK: xor <8 x i16> // CHECK-LE: xor <8 x i16> res_vs = vec_vxor(vs, vbs); // CHECK: xor <8 x i16> // CHECK-LE: xor <8 x i16> res_vus = vec_vxor(vus, vus); // CHECK: xor <8 x i16> // CHECK-LE: xor <8 x i16> res_vus = vec_vxor(vbs, vus); // CHECK: xor <8 x i16> // CHECK-LE: xor <8 x i16> res_vus = vec_vxor(vus, vbs); // CHECK: xor <8 x i16> // CHECK-LE: xor <8 x i16> res_vbs = vec_vxor(vbs, vbs); // CHECK: xor <8 x i16> // CHECK-LE: xor <8 x i16> res_vi = vec_vxor(vi, vi); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vi = vec_vxor(vbi, vi); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vi = vec_vxor(vi, vbi); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vui = vec_vxor(vui, vui); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vui = vec_vxor(vbi, vui); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vui = vec_vxor(vui, vbi); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vbi = vec_vxor(vbi, vbi); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vf = vec_vxor(vf, vf); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vf = vec_vxor(vbi, vf); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> res_vf = vec_vxor(vf, vbi); // CHECK: xor <4 x i32> // CHECK-LE: xor <4 x i32> /* ------------------------------ extensions -------------------------------------- */ /* vec_extract */ res_sc = vec_extract(vsc, param_i); // CHECK: extractelement <16 x i8> // CHECK-LE: extractelement <16 x i8> res_uc = vec_extract(vuc, param_i); // CHECK: extractelement <16 x i8> // CHECK-LE: extractelement <16 x i8> res_uc = vec_extract(vbc, param_i); // CHECK: extractelement <16 x i8> // CHECK-LE: extractelement <16 x i8> res_s = vec_extract(vs, param_i); // CHECK: extractelement <8 x i16> // CHECK-LE: extractelement <8 x i16> res_us = vec_extract(vus, param_i); // CHECK: extractelement <8 x i16> // CHECK-LE: extractelement <8 x i16> res_us = vec_extract(vbs, param_i); // CHECK: extractelement <8 x i16> // CHECK-LE: extractelement <8 x i16> res_i = vec_extract(vi, param_i); // CHECK: extractelement <4 x i32> // CHECK-LE: extractelement <4 x i32> res_ui = vec_extract(vui, param_i); // CHECK: extractelement <4 x i32> // CHECK-LE: extractelement <4 x i32> res_ui = vec_extract(vbi, param_i); // CHECK: extractelement <4 x i32> // CHECK-LE: extractelement <4 x i32> res_f = vec_extract(vf, param_i); // CHECK: extractelement <4 x float> // CHECK-LE: extractelement <4 x float> /* vec_insert */ res_vsc = vec_insert(param_sc, vsc, param_i); // CHECK: insertelement <16 x i8> // CHECK-LE: insertelement <16 x i8> res_vuc = vec_insert(param_uc, vuc, param_i); // CHECK: insertelement <16 x i8> // CHECK-LE: insertelement <16 x i8> res_vbc = vec_insert(param_uc, vbc, param_i); // CHECK: insertelement <16 x i8> // CHECK-LE: insertelement <16 x i8> res_vs = vec_insert(param_s, vs, param_i); // CHECK: insertelement <8 x i16> // CHECK-LE: insertelement <8 x i16> res_vus = vec_insert(param_us, vus, param_i); // CHECK: insertelement <8 x i16> // CHECK-LE: insertelement <8 x i16> res_vbs = vec_insert(param_us, vbs, param_i); // CHECK: insertelement <8 x i16> // CHECK-LE: insertelement <8 x i16> res_vi = vec_insert(param_i, vi, param_i); // CHECK: insertelement <4 x i32> // CHECK-LE: insertelement <4 x i32> res_vui = vec_insert(param_ui, vui, param_i); // CHECK: insertelement <4 x i32> // CHECK-LE: insertelement <4 x i32> res_vbi = vec_insert(param_ui, vbi, param_i); // CHECK: insertelement <4 x i32> // CHECK-LE: insertelement <4 x i32> res_vf = vec_insert(param_f, vf, param_i); // CHECK: insertelement <4 x float> // CHECK-LE: insertelement <4 x float> /* vec_lvlx */ res_vsc = vec_lvlx(0, ¶m_sc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vsc = vec_lvlx(0, &vsc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_lvlx(0, ¶m_uc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_lvlx(0, &vuc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vbc = vec_lvlx(0, &vbc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_lvlx(0, ¶m_s); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_lvlx(0, &vs); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_lvlx(0, ¶m_us); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_lvlx(0, &vus); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vbs = vec_lvlx(0, &vbs); // CHECK: @llvm.ppc.altivec.lvx // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm res_vp = vec_lvlx(0, &vp); // CHECK: @llvm.ppc.altivec.lvx // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_lvlx(0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_lvlx(0, &vi); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_lvlx(0, ¶m_ui); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_lvlx(0, &vui); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vbi = vec_lvlx(0, &vbi); // CHECK: @llvm.ppc.altivec.lvx // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm res_vf = vec_lvlx(0, &vf); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x float> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x float> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm /* vec_lvlxl */ res_vsc = vec_lvlxl(0, ¶m_sc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vsc = vec_lvlxl(0, &vsc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_lvlxl(0, ¶m_uc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_lvlxl(0, &vuc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vbc = vec_lvlxl(0, &vbc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_lvlxl(0, ¶m_s); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_lvlxl(0, &vs); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_lvlxl(0, ¶m_us); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_lvlxl(0, &vus); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vbs = vec_lvlxl(0, &vbs); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm res_vp = vec_lvlxl(0, &vp); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_lvlxl(0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_lvlxl(0, &vi); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_lvlxl(0, ¶m_ui); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_lvlxl(0, &vui); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vbi = vec_lvlxl(0, &vbi); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm res_vf = vec_lvlxl(0, &vf); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x float> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x float> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm /* vec_lvrx */ res_vsc = vec_lvrx(0, ¶m_sc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vsc = vec_lvrx(0, &vsc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_lvrx(0, ¶m_uc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_lvrx(0, &vuc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vbc = vec_lvrx(0, &vbc); // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_lvrx(0, ¶m_s); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_lvrx(0, &vs); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_lvrx(0, ¶m_us); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_lvrx(0, &vus); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vbs = vec_lvrx(0, &vbs); // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm res_vp = vec_lvrx(0, &vp); // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_lvrx(0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_lvrx(0, &vi); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_lvrx(0, ¶m_ui); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_lvrx(0, &vui); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vbi = vec_lvrx(0, &vbi); // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm res_vf = vec_lvrx(0, &vf); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x float> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x float> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm /* vec_lvrxl */ res_vsc = vec_lvrxl(0, ¶m_sc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vsc = vec_lvrxl(0, &vsc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_lvrxl(0, ¶m_uc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vuc = vec_lvrxl(0, &vuc); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vbc = vec_lvrxl(0, &vbc); // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_lvrxl(0, ¶m_s); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vs = vec_lvrxl(0, &vs); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_lvrxl(0, ¶m_us); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vus = vec_lvrxl(0, &vus); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vbs = vec_lvrxl(0, &vbs); // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm res_vp = vec_lvrxl(0, &vp); // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_lvrxl(0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vi = vec_lvrxl(0, &vi); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_lvrxl(0, ¶m_ui); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_lvrxl(0, &vui); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm res_vbi = vec_lvrxl(0, &vbi); // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm res_vf = vec_lvrxl(0, &vf); // CHECK: @llvm.ppc.altivec.lvxl // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x float> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvxl // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x float> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm /* vec_stvlx */ vec_stvlx(vsc, 0, ¶m_sc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvlx(vsc, 0, &vsc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvlx(vuc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvlx(vuc, 0, &vuc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvlx(vbc, 0, &vbc); // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvlx(vs, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvlx(vs, 0, &vs); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvlx(vus, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvlx(vus, 0, &vus); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvlx(vbs, 0, &vbs); // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvlx(vp, 0, &vp); // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvlx(vi, 0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvlx(vi, 0, &vi); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvlx(vui, 0, ¶m_ui); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvlx(vui, 0, &vui); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvlx(vbi, 0, &vbi); // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvlx(vf, 0, &vf); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x float> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x float> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx /* vec_stvlxl */ vec_stvlxl(vsc, 0, ¶m_sc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvlxl(vsc, 0, &vsc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvlxl(vuc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvlxl(vuc, 0, &vuc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvlxl(vbc, 0, &vbc); // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvlxl(vs, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvlxl(vs, 0, &vs); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvlxl(vus, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvlxl(vus, 0, &vus); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvlxl(vbs, 0, &vbs); // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvlxl(vp, 0, &vp); // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvlxl(vi, 0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvlxl(vi, 0, &vi); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvlxl(vui, 0, ¶m_ui); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvlxl(vui, 0, &vui); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvlxl(vbi, 0, &vbi); // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvlxl(vf, 0, &vf); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x float> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x float> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl /* vec_stvrx */ vec_stvrx(vsc, 0, ¶m_sc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvrx(vsc, 0, &vsc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvrx(vuc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvrx(vuc, 0, &vuc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvrx(vbc, 0, &vbc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvrx(vs, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvrx(vs, 0, &vs); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvrx(vus, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvrx(vus, 0, &vus); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvrx(vbs, 0, &vbs); // CHECK: @llvm.ppc.altivec.lvx // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvrx(vp, 0, &vp); // CHECK: @llvm.ppc.altivec.lvx // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvrx(vi, 0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvrx(vi, 0, &vi); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvrx(vui, 0, ¶m_ui); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvrx(vui, 0, &vui); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvrx(vbi, 0, &vbi); // CHECK: @llvm.ppc.altivec.lvx // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx vec_stvrx(vf, 0, &vf); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x float> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvx // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x float> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvx /* vec_stvrxl */ vec_stvrxl(vsc, 0, ¶m_sc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvrxl(vsc, 0, &vsc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvrxl(vuc, 0, ¶m_uc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvrxl(vuc, 0, &vuc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvrxl(vbc, 0, &vbc); // CHECK: @llvm.ppc.altivec.lvx // CHECK: store <16 x i8> zeroinitializer // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvrxl(vs, 0, ¶m_s); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvrxl(vs, 0, &vs); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvrxl(vus, 0, ¶m_us); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvrxl(vus, 0, &vus); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvrxl(vbs, 0, &vbs); // CHECK: @llvm.ppc.altivec.lvx // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvrxl(vp, 0, &vp); // CHECK: @llvm.ppc.altivec.lvx // CHECK: store <8 x i16> zeroinitializer // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvrxl(vi, 0, ¶m_i); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvrxl(vi, 0, &vi); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvrxl(vui, 0, ¶m_ui); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvrxl(vui, 0, &vui); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvrxl(vbi, 0, &vbi); // CHECK: @llvm.ppc.altivec.lvx // CHECK: store <4 x i32> zeroinitializer // CHECK: @llvm.ppc.altivec.lvsl // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl vec_stvrxl(vf, 0, &vf); // CHECK: @llvm.ppc.altivec.lvx // CHECK: @llvm.ppc.altivec.lvsl // CHECK: store <4 x float> zeroinitializer // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.lvsr // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.altivec.stvxl // CHECK-LE: @llvm.ppc.altivec.lvx // CHECK-LE: @llvm.ppc.altivec.lvsl // CHECK-LE: store <4 x float> zeroinitializer // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.lvsr // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.stvxl /* vec_promote */ res_vsc = vec_promote(param_sc, 0); // CHECK: store <16 x i8> zeroinitializer // CHECK: insertelement <16 x i8> // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: insertelement <16 x i8> res_vuc = vec_promote(param_uc, 0); // CHECK: store <16 x i8> zeroinitializer // CHECK: insertelement <16 x i8> // CHECK-LE: store <16 x i8> zeroinitializer // CHECK-LE: insertelement <16 x i8> res_vs = vec_promote(param_s, 0); // CHECK: store <8 x i16> zeroinitializer // CHECK: insertelement <8 x i16> // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: insertelement <8 x i16> res_vus = vec_promote(param_us, 0); // CHECK: store <8 x i16> zeroinitializer // CHECK: insertelement <8 x i16> // CHECK-LE: store <8 x i16> zeroinitializer // CHECK-LE: insertelement <8 x i16> res_vi = vec_promote(param_i, 0); // CHECK: store <4 x i32> zeroinitializer // CHECK: insertelement <4 x i32> // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: insertelement <4 x i32> res_vui = vec_promote(param_ui, 0); // CHECK: store <4 x i32> zeroinitializer // CHECK: insertelement <4 x i32> // CHECK-LE: store <4 x i32> zeroinitializer // CHECK-LE: insertelement <4 x i32> res_vf = vec_promote(param_f, 0); // CHECK: store <4 x float> zeroinitializer // CHECK: insertelement <4 x float> // CHECK-LE: store <4 x float> zeroinitializer // CHECK-LE: insertelement <4 x float> /* vec_splats */ res_vsc = vec_splats(param_sc); // CHECK: insertelement <16 x i8> // CHECK-LE: insertelement <16 x i8> res_vuc = vec_splats(param_uc); // CHECK: insertelement <16 x i8> // CHECK-LE: insertelement <16 x i8> res_vs = vec_splats(param_s); // CHECK: insertelement <8 x i16> // CHECK-LE: insertelement <8 x i16> res_vus = vec_splats(param_us); // CHECK: insertelement <8 x i16> // CHECK-LE: insertelement <8 x i16> res_vi = vec_splats(param_i); // CHECK: insertelement <4 x i32> // CHECK-LE: insertelement <4 x i32> res_vui = vec_splats(param_ui); // CHECK: insertelement <4 x i32> // CHECK-LE: insertelement <4 x i32> res_vf = vec_splats(param_f); // CHECK: insertelement <4 x float> // CHECK-LE: insertelement <4 x float> /* ------------------------------ predicates -------------------------------------- */ /* vec_all_eq */ res_i = vec_all_eq(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_all_eq(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_all_eq(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_all_eq(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_all_eq(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_all_eq(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_all_eq(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_all_eq(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_all_eq(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_all_eq(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_all_eq(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_all_eq(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_all_eq(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_all_eq(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_all_eq(vp, vp); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_all_eq(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_all_eq(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_all_eq(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_all_eq(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_all_eq(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_all_eq(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_all_eq(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_all_eq(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpeqfp.p /* vec_all_ge */ res_i = vec_all_ge(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_all_ge(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_all_ge(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_ge(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_ge(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_ge(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_ge(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_ge(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_all_ge(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_all_ge(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_ge(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_ge(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_ge(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_ge(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_ge(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_all_ge(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_all_ge(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_ge(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_ge(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_ge(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_ge(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_ge(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp.p // CHECK-LE: @llvm.ppc.altivec.vcmpgefp.p /* vec_all_gt */ res_i = vec_all_gt(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_all_gt(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_all_gt(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_gt(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_gt(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_gt(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_gt(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_gt(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_all_gt(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_all_gt(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_gt(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_gt(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_gt(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_gt(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_gt(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_all_gt(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_all_gt(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_gt(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_gt(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_gt(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_gt(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_gt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtfp.p /* vec_all_in */ res_i = vec_all_in(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpbfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpbfp.p /* vec_all_le */ res_i = vec_all_le(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_all_le(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_all_le(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_le(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_le(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_le(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_le(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_le(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_all_le(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_all_le(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_le(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_le(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_le(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_le(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_le(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_all_le(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_all_le(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_le(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_le(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_le(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_le(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_le(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp.p // CHECK-LE: @llvm.ppc.altivec.vcmpgefp.p /* vec_all_lt */ res_i = vec_all_lt(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_all_lt(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_all_lt(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_lt(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_lt(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_lt(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_lt(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_lt(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_all_lt(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_all_lt(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_lt(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_lt(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_lt(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_lt(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_lt(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_all_lt(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_all_lt(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_lt(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_lt(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_lt(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_lt(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_lt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtfp.p /* vec_all_nan */ res_i = vec_all_nan(vf); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpeqfp.p /* vec_all_ne */ res_i = vec_all_ne(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_all_ne(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_all_ne(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_all_ne(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_all_ne(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_all_ne(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_all_ne(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_all_ne(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_all_ne(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_all_ne(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_all_ne(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_all_ne(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_all_ne(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_all_ne(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_all_ne(vp, vp); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_all_ne(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_all_ne(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_all_ne(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_all_ne(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_all_ne(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_all_ne(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_all_ne(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_all_ne(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpeqfp.p /* vec_all_nge */ res_i = vec_all_nge(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp.p // CHECK-LE: @llvm.ppc.altivec.vcmpgefp.p /* vec_all_ngt */ res_i = vec_all_ngt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtfp.p /* vec_all_nle */ res_i = vec_all_nle(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp.p // CHECK-LE: @llvm.ppc.altivec.vcmpgefp.p /* vec_all_nlt */ res_i = vec_all_nlt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtfp.p /* vec_all_numeric */ res_i = vec_all_numeric(vf); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpeqfp.p /* vec_any_eq */ res_i = vec_any_eq(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_any_eq(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_any_eq(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_any_eq(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_any_eq(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_any_eq(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_any_eq(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_any_eq(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_any_eq(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_any_eq(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_any_eq(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_any_eq(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_any_eq(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_any_eq(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_any_eq(vp, vp); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_any_eq(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_any_eq(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_any_eq(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_any_eq(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_any_eq(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_any_eq(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_any_eq(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_any_eq(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpeqfp.p /* vec_any_ge */ res_i = vec_any_ge(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_any_ge(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_any_ge(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_ge(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_ge(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_ge(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_ge(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_ge(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_any_ge(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_any_ge(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_ge(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_ge(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_ge(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_ge(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_ge(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_any_ge(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_any_ge(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_ge(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_ge(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_ge(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_ge(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_ge(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp.p // CHECK-LE: @llvm.ppc.altivec.vcmpgefp.p /* vec_any_gt */ res_i = vec_any_gt(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_any_gt(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_any_gt(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_gt(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_gt(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_gt(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_gt(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_gt(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_any_gt(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_any_gt(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_gt(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_gt(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_gt(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_gt(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_gt(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_any_gt(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_any_gt(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_gt(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_gt(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_gt(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_gt(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_gt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtfp.p /* vec_any_le */ res_i = vec_any_le(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_any_le(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_any_le(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_le(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_le(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_le(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_le(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_le(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_any_le(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_any_le(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_le(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_le(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_le(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_le(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_le(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_any_le(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_any_le(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_le(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_le(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_le(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_le(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_le(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp.p // CHECK-LE: @llvm.ppc.altivec.vcmpgefp.p /* vec_any_lt */ res_i = vec_any_lt(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_any_lt(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_any_lt(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_lt(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_lt(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_lt(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_lt(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_lt(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_any_lt(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_any_lt(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_lt(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_lt(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_lt(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_lt(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_lt(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_any_lt(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_any_lt(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_lt(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_lt(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_lt(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_lt(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_lt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtfp.p /* vec_any_nan */ res_i = vec_any_nan(vf); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpeqfp.p /* vec_any_ne */ res_i = vec_any_ne(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_any_ne(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_any_ne(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_any_ne(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_any_ne(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_any_ne(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_any_ne(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p res_i = vec_any_ne(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_any_ne(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_any_ne(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_any_ne(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_any_ne(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_any_ne(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_any_ne(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_any_ne(vp, vp); // CHECK: @llvm.ppc.altivec.vcmpequh.p // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p res_i = vec_any_ne(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_any_ne(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_any_ne(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_any_ne(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_any_ne(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_any_ne(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_any_ne(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p res_i = vec_any_ne(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpeqfp.p /* vec_any_nge */ res_i = vec_any_nge(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp.p // CHECK-LE: @llvm.ppc.altivec.vcmpgefp.p /* vec_any_ngt */ res_i = vec_any_ngt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtfp.p /* vec_any_nle */ res_i = vec_any_nle(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp.p // CHECK-LE: @llvm.ppc.altivec.vcmpgefp.p /* vec_any_nlt */ res_i = vec_any_nlt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpgtfp.p /* vec_any_numeric */ res_i = vec_any_numeric(vf); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpeqfp.p /* vec_any_out */ res_i = vec_any_out(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpbfp.p // CHECK-LE: @llvm.ppc.altivec.vcmpbfp.p } /* ------------------------------ Relational Operators ------------------------------ */ // CHECK-LABEL: define void @test7 void test7() { vector signed char vsc1 = (vector signed char)(-1); vector signed char vsc2 = (vector signed char)(-2); res_i = (vsc1 == vsc2); // CHECK: @llvm.ppc.altivec.vcmpequb.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p(i32 2 res_i = (vsc1 != vsc2); // CHECK: @llvm.ppc.altivec.vcmpequb.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p(i32 0 res_i = (vsc1 < vsc2); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p(i32 2 res_i = (vsc1 > vsc2); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p(i32 2 res_i = (vsc1 <= vsc2); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p(i32 0 res_i = (vsc1 >= vsc2); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p(i32 0 vector unsigned char vuc1 = (vector unsigned char)(1); vector unsigned char vuc2 = (vector unsigned char)(2); res_i = (vuc1 == vuc2); // CHECK: @llvm.ppc.altivec.vcmpequb.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p(i32 2 res_i = (vuc1 != vuc2); // CHECK: @llvm.ppc.altivec.vcmpequb.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpequb.p(i32 0 res_i = (vuc1 < vuc2); // CHECK: @llvm.ppc.altivec.vcmpgtub.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p(i32 2 res_i = (vuc1 > vuc2); // CHECK: @llvm.ppc.altivec.vcmpgtub.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p(i32 2 res_i = (vuc1 <= vuc2); // CHECK: @llvm.ppc.altivec.vcmpgtub.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p(i32 0 res_i = (vuc1 >= vuc2); // CHECK: @llvm.ppc.altivec.vcmpgtub.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p(i32 0 vector short vs1 = (vector short)(-1); vector short vs2 = (vector short)(-2); res_i = (vs1 == vs2); // CHECK: @llvm.ppc.altivec.vcmpequh.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p(i32 2 res_i = (vs1 != vs2); // CHECK: @llvm.ppc.altivec.vcmpequh.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p(i32 0 res_i = (vs1 < vs2); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p(i32 2 res_i = (vs1 > vs2); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p(i32 2 res_i = (vs1 <= vs2); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p(i32 0 res_i = (vs1 >= vs2); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p(i32 0 vector unsigned short vus1 = (vector unsigned short)(1); vector unsigned short vus2 = (vector unsigned short)(2); res_i = (vus1 == vus2); // CHECK: @llvm.ppc.altivec.vcmpequh.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p(i32 2 res_i = (vus1 != vus2); // CHECK: @llvm.ppc.altivec.vcmpequh.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpequh.p(i32 0 res_i = (vus1 < vus2); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p(i32 2 res_i = (vus1 > vus2); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p(i32 2 res_i = (vus1 <= vus2); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p(i32 0 res_i = (vus1 >= vus2); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p(i32 0 vector int vi1 = (vector int)(-1); vector int vi2 = (vector int)(-2); res_i = (vi1 == vi2); // CHECK: @llvm.ppc.altivec.vcmpequw.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p(i32 2 res_i = (vi1 != vi2); // CHECK: @llvm.ppc.altivec.vcmpequw.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p(i32 0 res_i = (vi1 < vi2); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p(i32 2 res_i = (vi1 > vi2); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p(i32 2 res_i = (vi1 <= vi2); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p(i32 0 res_i = (vi1 >= vi2); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p(i32 0 vector unsigned int vui1 = (vector unsigned int)(1); vector unsigned int vui2 = (vector unsigned int)(2); res_i = (vui1 == vui2); // CHECK: @llvm.ppc.altivec.vcmpequw.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p(i32 2 res_i = (vui1 != vui2); // CHECK: @llvm.ppc.altivec.vcmpequw.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpequw.p(i32 0 res_i = (vui1 < vui2); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p(i32 2 res_i = (vui1 > vui2); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p(i32 2 res_i = (vui1 <= vui2); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p(i32 0 res_i = (vui1 >= vui2); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p(i32 0 vector float vf1 = (vector float)(1.0); vector float vf2 = (vector float)(2.0); res_i = (vf1 == vf2); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpeqfp.p(i32 2 res_i = (vf1 != vf2); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p(i32 0 // CHECK-LE: @llvm.ppc.altivec.vcmpeqfp.p(i32 0 res_i = (vf1 < vf2); // CHECK: @llvm.ppc.altivec.vcmpgtfp.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpgtfp.p(i32 2 res_i = (vf1 > vf2); // CHECK: @llvm.ppc.altivec.vcmpgtfp.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpgtfp.p(i32 2 res_i = (vf1 <= vf2); // CHECK: @llvm.ppc.altivec.vcmpgefp.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpgefp.p(i32 2 res_i = (vf1 >= vf2); // CHECK: @llvm.ppc.altivec.vcmpgefp.p(i32 2 // CHECK-LE: @llvm.ppc.altivec.vcmpgefp.p(i32 2 } /* ------------------------------ optional ---------------------------------- */ void test8() { // CHECK-LABEL: define void @test8 // CHECK-LE-LABEL: define void @test8 res_vbc = vec_reve(vbc); // CHECK: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> // CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> res_vsc = vec_reve(vsc); // CHECK: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> // CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> res_vuc = vec_reve(vuc); // CHECK: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> // CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> res_vbi = vec_reve(vbi); // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> // CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> res_vi = vec_reve(vi); // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> // CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> res_vui = vec_reve(vui); // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> // CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> res_vbs = vec_reve(vbs); // CHECK: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> // CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> res_vbs = vec_reve(vs); // CHECK: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> // CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> res_vbs = vec_reve(vus); // CHECK: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> // CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> res_vf = vec_reve(vf); // CHECK: shufflevector <4 x float> %{{[0-9]+}}, <4 x float> %{{[0-9]+}}, <4 x i32> // CHECK-LE: shufflevector <4 x float> %{{[0-9]+}}, <4 x float> %{{[0-9]+}}, <4 x i32> res_vbc = vec_revb(vbc); // CHECK: [[T1:%.+]] = load <16 x i8>, <16 x i8>* @vbc, align 16 // CHECK: store <16 x i8> [[T1]], <16 x i8>* [[T2:%.+]], align 16 // CHECK: [[T3:%.+]] = load <16 x i8>, <16 x i8>* [[T2]], align 16 // CHECK: store <16 x i8> [[T3]], <16 x i8>* @res_vbc, align 16 // CHECK-LE: [[T1:%.+]] = load <16 x i8>, <16 x i8>* @vbc, align 16 // CHECK-LE: store <16 x i8> [[T1]], <16 x i8>* [[T2:%.+]], align 16 // CHECK-LE: [[T3:%.+]] = load <16 x i8>, <16 x i8>* [[T2]], align 16 // CHECK-LE: store <16 x i8> [[T3]], <16 x i8>* @res_vbc, align 16 res_vsc = vec_revb(vsc); // CHECK: [[T1:%.+]] = load <16 x i8>, <16 x i8>* @vsc, align 16 // CHECK: store <16 x i8> [[T1]], <16 x i8>* [[T2:%.+]], align 16 // CHECK: [[T3:%.+]] = load <16 x i8>, <16 x i8>* [[T2]], align 16 // CHECK: store <16 x i8> [[T3]], <16 x i8>* @res_vsc, align 16 // CHECK-LE: [[T1:%.+]] = load <16 x i8>, <16 x i8>* @vsc, align 16 // CHECK-LE: store <16 x i8> [[T1]], <16 x i8>* [[T2:%.+]], align 16 // CHECK-LE: [[T3:%.+]] = load <16 x i8>, <16 x i8>* [[T2]], align 16 // CHECK-LE: store <16 x i8> [[T3]], <16 x i8>* @res_vsc, align 16 res_vuc = vec_revb(vuc); // CHECK: [[T1:%.+]] = load <16 x i8>, <16 x i8>* @vuc, align 16 // CHECK: store <16 x i8> [[T1]], <16 x i8>* [[T2:%.+]], align 16 // CHECK: [[T3:%.+]] = load <16 x i8>, <16 x i8>* [[T2]], align 16 // CHECK: store <16 x i8> [[T3]], <16 x i8>* @res_vuc, align 16 // CHECK-LE: [[T1:%.+]] = load <16 x i8>, <16 x i8>* @vuc, align 16 // CHECK-LE: store <16 x i8> [[T1]], <16 x i8>* [[T2:%.+]], align 16 // CHECK-LE: [[T3:%.+]] = load <16 x i8>, <16 x i8>* [[T2]], align 16 // CHECK-LE: store <16 x i8> [[T3]], <16 x i8>* @res_vuc, align 16 res_vbs = vec_revb(vbs); // CHECK: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: xor <16 x i8> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) res_vs = vec_revb(vs); // CHECK: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: xor <16 x i8> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) res_vus = vec_revb(vus); // CHECK: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: xor <16 x i8> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) res_vbi = vec_revb(vbi); // CHECK: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: xor <16 x i8> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) res_vi = vec_revb(vi); // CHECK: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: xor <16 x i8> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) res_vui = vec_revb(vui); // CHECK: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: xor <16 x i8> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) res_vf = vec_revb(vf); // CHECK: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: xor <16 x i8> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) } /* ------------------------------ vec_xl ------------------------------------ */ void test9() { // CHECK-LABEL: define void @test9 // CHECK-LE-LABEL: define void @test9 res_vsc = vec_xl(param_sll, ¶m_sc); - // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16 - // CHECK-LE: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16 + // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 1 + // CHECK-LE: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 1 res_vuc = vec_xl(param_sll, ¶m_uc); - // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16 - // CHECK-LE: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16 + // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 1 + // CHECK-LE: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 1 res_vs = vec_xl(param_sll, ¶m_s); - // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16 - // CHECK-LE: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16 + // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 1 + // CHECK-LE: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 1 res_vus = vec_xl(param_sll, ¶m_us); - // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16 - // CHECK-LE: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16 + // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 1 + // CHECK-LE: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 1 res_vi = vec_xl(param_sll, ¶m_i); - // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16 - // CHECK-LE: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16 + // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 1 + // CHECK-LE: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 1 res_vui = vec_xl(param_sll, ¶m_ui); - // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16 - // CHECK-LE: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16 + // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 1 + // CHECK-LE: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 1 res_vf = vec_xl(param_sll, ¶m_f); - // CHECK: load <4 x float>, <4 x float>* %{{[0-9]+}}, align 16 - // CHECK-LE: load <4 x float>, <4 x float>* %{{[0-9]+}}, align 16 + // CHECK: load <4 x float>, <4 x float>* %{{[0-9]+}}, align 1 + // CHECK-LE: load <4 x float>, <4 x float>* %{{[0-9]+}}, align 1 } /* ------------------------------ vec_xst ----------------------------------- */ void test10() { // CHECK-LABEL: define void @test10 // CHECK-LE-LABEL: define void @test10 vec_xst(vsc, param_sll, ¶m_sc); - // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16 - // CHECK-LE: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16 + // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 1 + // CHECK-LE: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 1 vec_xst(vuc, param_sll, ¶m_uc); - // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16 - // CHECK-LE: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16 + // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 1 + // CHECK-LE: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 1 vec_xst(vs, param_sll, ¶m_s); - // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16 - // CHECK-LE: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16 + // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 1 + // CHECK-LE: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 1 vec_xst(vus, param_sll, ¶m_us); - // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16 - // CHECK-LE: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16 + // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 1 + // CHECK-LE: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 1 vec_xst(vi, param_sll, ¶m_i); - // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16 - // CHECK-LE: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16 + // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 1 + // CHECK-LE: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 1 vec_xst(vui, param_sll, ¶m_ui); - // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16 - // CHECK-LE: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16 + // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 1 + // CHECK-LE: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 1 vec_xst(vf, param_sll, ¶m_f); - // CHECK: store <4 x float> %{{[0-9]+}}, <4 x float>* %{{[0-9]+}}, align 16 - // CHECK-LE: store <4 x float> %{{[0-9]+}}, <4 x float>* %{{[0-9]+}}, align 16 + // CHECK: store <4 x float> %{{[0-9]+}}, <4 x float>* %{{[0-9]+}}, align 1 + // CHECK-LE: store <4 x float> %{{[0-9]+}}, <4 x float>* %{{[0-9]+}}, align 1 } /* ----------------------------- vec_xl_be ---------------------------------- */ void test11() { // CHECK-LABEL: define void @test11 // CHECK-LE-LABEL: define void @test11 res_vsc = vec_xl_be(param_sll, ¶m_sc); - // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16 + // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 1 // CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}}) // CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> res_vuc = vec_xl_be(param_sll, ¶m_uc); - // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16 + // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 1 // CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}}) // CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> res_vs = vec_xl_be(param_sll, ¶m_s); - // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16 + // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 1 // CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}}) // CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> res_vus = vec_xl_be(param_sll, ¶m_us); - // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16 + // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 1 // CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}}) // CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> res_vi = vec_xl_be(param_sll, ¶m_i); - // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16 + // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 1 // CHECK-LE: call <4 x i32> @llvm.ppc.vsx.lxvw4x.be(i8* %{{[0-9]+}}) res_vui = vec_xl_be(param_sll, ¶m_ui); - // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16 + // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 1 // CHECK-LE: call <4 x i32> @llvm.ppc.vsx.lxvw4x.be(i8* %{{[0-9]+}}) res_vf = vec_xl_be(param_sll, ¶m_f); - // CHECK: load <4 x float>, <4 x float>* %{{[0-9]+}}, align 16 + // CHECK: load <4 x float>, <4 x float>* %{{[0-9]+}}, align 1 // CHECK-LE: call <4 x i32> @llvm.ppc.vsx.lxvw4x.be(i8* %{{[0-9]+}}) } /* ----------------------------- vec_xst_be --------------------------------- */ void test12() { // CHECK-LABEL: define void @test12 // CHECK-LE-LABEL: define void @test12 vec_xst_be(vsc, param_sll, ¶m_sc); - // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16 + // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 1 // CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> // CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}}) vec_xst_be(vuc, param_sll, ¶m_uc); - // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16 + // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 1 // CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> // CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}}) vec_xst_be(vs, param_sll, ¶m_s); - // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16 + // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 1 // CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> // CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}}) vec_xst_be(vus, param_sll, ¶m_us); - // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16 + // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 1 // CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> // CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}}) vec_xst_be(vi, param_sll, ¶m_i); - // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16 + // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 1 // CHECK-LE: call void @llvm.ppc.vsx.stxvw4x.be(<4 x i32> %{{[0-9]+}}, i8* %{{[0-9]+}}) vec_xst_be(vui, param_sll, ¶m_ui); - // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16 + // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 1 // CHECK-LE: call void @llvm.ppc.vsx.stxvw4x.be(<4 x i32> %{{[0-9]+}}, i8* %{{[0-9]+}}) vec_xst_be(vf, param_sll, ¶m_f); - // CHECK: store <4 x float> %{{[0-9]+}}, <4 x float>* %{{[0-9]+}}, align 16 + // CHECK: store <4 x float> %{{[0-9]+}}, <4 x float>* %{{[0-9]+}}, align 1 // CHECK-LE: call void @llvm.ppc.vsx.stxvw4x.be(<4 x i32> %{{[0-9]+}}, i8* %{{[0-9]+}}) } Index: vendor/clang/dist-release_70/test/CodeGen/builtins-ppc-quadword.c =================================================================== --- vendor/clang/dist-release_70/test/CodeGen/builtins-ppc-quadword.c (revision 341366) +++ vendor/clang/dist-release_70/test/CodeGen/builtins-ppc-quadword.c (revision 341367) @@ -1,249 +1,249 @@ // REQUIRES: powerpc-registered-target // RUN: %clang_cc1 -target-feature +altivec -target-feature +power8-vector \ // RUN: -triple powerpc64-unknown-unknown -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -target-feature +altivec -target-feature +power8-vector \ // RUN: -triple powerpc64le-unknown-unknown -emit-llvm %s -o - \ // RUN: | FileCheck %s -check-prefix=CHECK-LE // RUN: not %clang_cc1 -target-feature +altivec -triple powerpc-unknown-unknown \ // RUN: -emit-llvm %s -o - 2>&1 | FileCheck %s -check-prefix=CHECK-PPC #include // CHECK-PPC: error: __int128 is not supported on this target vector signed __int128 vlll = { -1 }; // CHECK-PPC: error: __int128 is not supported on this target vector unsigned __int128 vulll = { 1 }; signed long long param_sll; // CHECK-PPC: error: __int128 is not supported on this target signed __int128 param_lll; // CHECK-PPC: error: __int128 is not supported on this target unsigned __int128 param_ulll; // CHECK-PPC: error: __int128 is not supported on this target vector signed __int128 res_vlll; // CHECK-PPC: error: __int128 is not supported on this target vector unsigned __int128 res_vulll; // CHECK-LABEL: define void @test1 void test1() { /* vec_add */ res_vlll = vec_add(vlll, vlll); // CHECK: add <1 x i128> // CHECK-LE: add <1 x i128> // CHECK-PPC: error: call to 'vec_add' is ambiguous res_vulll = vec_add(vulll, vulll); // CHECK: add <1 x i128> // CHECK-LE: add <1 x i128> // CHECK-PPC: error: call to 'vec_add' is ambiguous /* vec_vadduqm */ res_vlll = vec_vadduqm(vlll, vlll); // CHECK: add <1 x i128> // CHECK-LE: add <1 x i128> // CHECK-PPC: error: assigning to '__vector __int128' (vector of 1 '__int128' value) from incompatible type 'int' res_vulll = vec_vadduqm(vulll, vulll); // CHECK: add <1 x i128> // CHECK-LE: add <1 x i128> // CHECK-PPC: error: assigning to '__vector unsigned __int128' (vector of 1 'unsigned __int128' value) from incompatible type 'int' /* vec_vaddeuqm */ res_vlll = vec_vaddeuqm(vlll, vlll, vlll); // CHECK: @llvm.ppc.altivec.vaddeuqm // CHECK-LE: @llvm.ppc.altivec.vaddeuqm // CHECK-PPC: error: assigning to '__vector __int128' (vector of 1 '__int128' value) from incompatible type 'int' res_vulll = vec_vaddeuqm(vulll, vulll, vulll); // CHECK: @llvm.ppc.altivec.vaddeuqm // CHECK-LE: @llvm.ppc.altivec.vaddeuqm // CHECK-PPC: error: assigning to '__vector unsigned __int128' (vector of 1 'unsigned __int128' value) from incompatible type 'int' /* vec_addc */ res_vlll = vec_addc(vlll, vlll); // CHECK: @llvm.ppc.altivec.vaddcuq // CHECK-LE: @llvm.ppc.altivec.vaddcuq // KCHECK-PPC: error: call to 'vec_addc' is ambiguous res_vulll = vec_addc(vulll, vulll); // CHECK: @llvm.ppc.altivec.vaddcuq // CHECK-LE: @llvm.ppc.altivec.vaddcuq // KCHECK-PPC: error: call to 'vec_addc' is ambiguous /* vec_vaddcuq */ res_vlll = vec_vaddcuq(vlll, vlll); // CHECK: @llvm.ppc.altivec.vaddcuq // CHECK-LE: @llvm.ppc.altivec.vaddcuq // CHECK-PPC: error: assigning to '__vector __int128' (vector of 1 '__int128' value) from incompatible type 'int' res_vulll = vec_vaddcuq(vulll, vulll); // CHECK: @llvm.ppc.altivec.vaddcuq // CHECK-LE: @llvm.ppc.altivec.vaddcuq // CHECK-PPC: error: assigning to '__vector unsigned __int128' (vector of 1 'unsigned __int128' value) from incompatible type 'int' /* vec_vaddecuq */ res_vlll = vec_vaddecuq(vlll, vlll, vlll); // CHECK: @llvm.ppc.altivec.vaddecuq // CHECK-LE: @llvm.ppc.altivec.vaddecuq // CHECK-PPC: error: assigning to '__vector __int128' (vector of 1 '__int128' value) from incompatible type 'int' res_vulll = vec_vaddecuq(vulll, vulll, vulll); // CHECK: @llvm.ppc.altivec.vaddecuq // CHECK-LE: @llvm.ppc.altivec.vaddecuq // CHECK-PPC: error: assigning to '__vector unsigned __int128' (vector of 1 'unsigned __int128' value) from incompatible type 'int' /* vec_sub */ res_vlll = vec_sub(vlll, vlll); // CHECK: sub <1 x i128> // CHECK-LE: sub <1 x i128> // CHECK-PPC: error: call to 'vec_sub' is ambiguous res_vulll = vec_sub(vulll, vulll); // CHECK: sub <1 x i128> // CHECK-LE: sub <1 x i128> // CHECK-PPC: error: call to 'vec_sub' is ambiguous /* vec_vsubuqm */ res_vlll = vec_vsubuqm(vlll, vlll); // CHECK: sub <1 x i128> // CHECK-LE: sub <1 x i128> // CHECK-PPC: error: assigning to '__vector __int128' (vector of 1 '__int128' value) from incompatible type 'int' res_vulll = vec_vsubuqm(vulll, vulll); // CHECK: sub <1 x i128> // CHECK-LE: sub <1 x i128> // CHECK-PPC: error: assigning to '__vector unsigned __int128' (vector of 1 'unsigned __int128' value) from incompatible type 'int' /* vec_vsubeuqm */ res_vlll = vec_vsubeuqm(vlll, vlll, vlll); // CHECK: @llvm.ppc.altivec.vsubeuqm // CHECK-LE: @llvm.ppc.altivec.vsubeuqm // CHECK-PPC: error: assigning to '__vector __int128' (vector of 1 '__int128' value) from incompatible type 'int' /* vec_sube */ res_vlll = vec_sube(vlll, vlll, vlll); // CHECK: @llvm.ppc.altivec.vsubeuqm // CHECK-LE: @llvm.ppc.altivec.vsubeuqm // CHECK-PPC: error: call to 'vec_sube' is ambiguous res_vulll = vec_sube(vulll, vulll, vulll); // CHECK: @llvm.ppc.altivec.vsubeuqm // CHECK-LE: @llvm.ppc.altivec.vsubeuqm // CHECK-PPC: error: call to 'vec_sube' is ambiguous res_vlll = vec_sube(vlll, vlll, vlll); // CHECK: @llvm.ppc.altivec.vsubeuqm // CHECK-LE: @llvm.ppc.altivec.vsubeuqm // CHECK-PPC: error: call to 'vec_sube' is ambiguous res_vulll = vec_vsubeuqm(vulll, vulll, vulll); // CHECK: @llvm.ppc.altivec.vsubeuqm // CHECK-LE: @llvm.ppc.altivec.vsubeuqm // CHECK-PPC: error: assigning to '__vector unsigned __int128' (vector of 1 'unsigned __int128' value) from incompatible type 'int' res_vulll = vec_sube(vulll, vulll, vulll); // CHECK: @llvm.ppc.altivec.vsubeuqm // CHECK-LE: @llvm.ppc.altivec.vsubeuqm // CHECK-PPC: error: call to 'vec_sube' is ambiguous /* vec_subc */ res_vlll = vec_subc(vlll, vlll); // CHECK: @llvm.ppc.altivec.vsubcuq // CHECK-LE: @llvm.ppc.altivec.vsubcuq // KCHECK-PPC: error: call to 'vec_subc' is ambiguous res_vulll = vec_subc(vulll, vulll); // CHECK: @llvm.ppc.altivec.vsubcuq // CHECK-LE: @llvm.ppc.altivec.vsubcuq // KCHECK-PPC: error: call to 'vec_subc' is ambiguous /* vec_vsubcuq */ res_vlll = vec_vsubcuq(vlll, vlll); // CHECK: @llvm.ppc.altivec.vsubcuq // CHECK-LE: @llvm.ppc.altivec.vsubcuq // CHECK-PPC: error: assigning to '__vector __int128' (vector of 1 '__int128' value) from incompatible type 'int' res_vulll = vec_vsubcuq(vulll, vulll); // CHECK: @llvm.ppc.altivec.vsubcuq // CHECK-LE: @llvm.ppc.altivec.vsubcuq // CHECK-PPC: error: assigning to '__vector unsigned __int128' (vector of 1 'unsigned __int128' value) from incompatible type 'int' /* vec_vsubecuq */ res_vlll = vec_vsubecuq(vlll, vlll, vlll); // CHECK: @llvm.ppc.altivec.vsubecuq // CHECK-LE: @llvm.ppc.altivec.vsubecuq // CHECK-PPC: error: assigning to '__vector __int128' (vector of 1 '__int128' value) from incompatible type 'int' res_vulll = vec_vsubecuq(vulll, vulll, vulll); // CHECK: @llvm.ppc.altivec.vsubecuq // CHECK-LE: @llvm.ppc.altivec.vsubecuq // CHECK-PPC: error: assigning to '__vector unsigned __int128' (vector of 1 'unsigned __int128' value) from incompatible type 'int' res_vlll = vec_subec(vlll, vlll, vlll); // CHECK: @llvm.ppc.altivec.vsubecuq // CHECK-LE: @llvm.ppc.altivec.vsubecuq // CHECK-PPC: error: assigning to '__vector __int128' (vector of 1 '__int128' value) from incompatible type 'int' res_vulll = vec_subec(vulll, vulll, vulll); // CHECK: @llvm.ppc.altivec.vsubecuq // CHECK-LE: @llvm.ppc.altivec.vsubecuq // CHECK-PPC: error: assigning to '__vector unsigned __int128' (vector of 1 'unsigned __int128' value) from incompatible type 'int' res_vulll = vec_revb(vulll); // CHECK: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: xor <16 x i8> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) // CHECK_PPC: error: call to 'vec_revb' is ambiguous /* vec_xl */ res_vlll = vec_xl(param_sll, ¶m_lll); - // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16 - // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16 + // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 1 + // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 1 // CHECK-PPC: error: call to 'vec_xl' is ambiguous res_vulll = vec_xl(param_sll, ¶m_ulll); - // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16 - // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16 + // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 1 + // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 1 // CHECK-PPC: error: call to 'vec_xl' is ambiguous /* vec_xst */ vec_xst(vlll, param_sll, ¶m_lll); - // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16 - // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16 + // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 1 + // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 1 // CHECK-PPC: error: call to 'vec_xst' is ambiguous vec_xst(vulll, param_sll, ¶m_ulll); - // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16 - // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16 + // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 1 + // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 1 // CHECK-PPC: error: call to 'vec_xst' is ambiguous /* vec_xl_be */ res_vlll = vec_xl_be(param_sll, ¶m_lll); - // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16 - // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16 + // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 1 + // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 1 // CHECK-PPC: error: call to 'vec_xl' is ambiguous res_vulll = vec_xl_be(param_sll, ¶m_ulll); - // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16 - // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16 + // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 1 + // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 1 // CHECK-PPC: error: call to 'vec_xl' is ambiguous /* vec_xst_be */ vec_xst_be(vlll, param_sll, ¶m_lll); - // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16 - // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16 + // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 1 + // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 1 // CHECK-PPC: error: call to 'vec_xst' is ambiguous vec_xst_be(vulll, param_sll, ¶m_ulll); - // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16 - // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16 + // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 1 + // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 1 // CHECK-PPC: error: call to 'vec_xst' is ambiguous } Index: vendor/clang/dist-release_70/test/CodeGen/builtins-ppc-vsx.c =================================================================== --- vendor/clang/dist-release_70/test/CodeGen/builtins-ppc-vsx.c (revision 341366) +++ vendor/clang/dist-release_70/test/CodeGen/builtins-ppc-vsx.c (revision 341367) @@ -1,1805 +1,1805 @@ // REQUIRES: powerpc-registered-target // RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx -triple powerpc64-unknown-unknown -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-LE #include vector bool char vbc = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }; vector signed char vsc = { -8, 9, -10, 11, -12, 13, -14, 15, -0, 1, -2, 3, -4, 5, -6, 7}; vector unsigned char vuc = { 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7}; vector float vf = { -1.5, 2.5, -3.5, 4.5 }; vector double vd = { 3.5, -7.5 }; vector bool short vbs = { 0, 1, 0, 1, 0, 1, 0, 1 }; vector signed short vss = { -1, 2, -3, 4, -5, 6, -7, 8 }; vector unsigned short vus = { 0, 1, 2, 3, 4, 5, 6, 7 }; vector bool int vbi = { 0, 1, 0, 1 }; vector signed int vsi = { -1, 2, -3, 4 }; vector unsigned int vui = { 0, 1, 2, 3 }; vector bool long long vbll = { 1, 0 }; vector signed long long vsll = { 255LL, -937LL }; vector unsigned long long vull = { 1447LL, 2894LL }; double d = 23.4; signed long long sll = 618LL; float af[4] = {23.4f, 56.7f, 89.0f, 12.3f}; double ad[2] = {23.4, 56.7}; signed char asc[16] = { -8, 9, -10, 11, -12, 13, -14, 15, -0, 1, -2, 3, -4, 5, -6, 7}; unsigned char auc[16] = { 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7}; signed short ass[8] = { -1, 2, -3, 4, -5, 6, -7, 8 }; unsigned short aus[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; signed int asi[4] = { -1, 2, -3, 4 }; unsigned int aui[4] = { 0, 1, 2, 3 }; signed long long asll[2] = { -1L, 2L }; unsigned long long aull[2] = { 1L, 2L }; vector float res_vf; vector double res_vd; vector bool char res_vbc; vector signed char res_vsc; vector unsigned char res_vuc; vector bool short res_vbs; vector signed short res_vss; vector unsigned short res_vus; vector bool int res_vbi; vector signed int res_vsi; vector unsigned int res_vui; vector bool long long res_vbll; vector signed long long res_vsll; vector unsigned long long res_vull; double res_d; float res_af[4]; double res_ad[2]; signed char res_asc[16]; unsigned char res_auc[16]; signed short res_ass[8]; unsigned short res_aus[8]; signed int res_asi[4]; unsigned int res_aui[4]; void dummy() { } void test1() { // CHECK-LABEL: define void @test1 // CHECK-LE-LABEL: define void @test1 res_vf = vec_abs(vf); // CHECK: call <4 x float> @llvm.fabs.v4f32(<4 x float> %{{[0-9]*}}) // CHECK-LE: call <4 x float> @llvm.fabs.v4f32(<4 x float> %{{[0-9]*}}) res_vd = vec_abs(vd); // CHECK: call <2 x double> @llvm.fabs.v2f64(<2 x double> %{{[0-9]*}}) // CHECK-LE: call <2 x double> @llvm.fabs.v2f64(<2 x double> %{{[0-9]*}}) res_vf = vec_nabs(vf); // CHECK: [[VEC:%[0-9]+]] = call <4 x float> @llvm.fabs.v4f32(<4 x float> %{{[0-9]*}}) // CHECK-NEXT: fsub <4 x float> , [[VEC]] res_vd = vec_nabs(vd); // CHECK: [[VECD:%[0-9]+]] = call <2 x double> @llvm.fabs.v2f64(<2 x double> %{{[0-9]*}}) // CHECK: fsub <2 x double> , [[VECD]] dummy(); // CHECK: call void @dummy() // CHECK-LE: call void @dummy() res_vd = vec_add(vd, vd); // CHECK: fadd <2 x double> // CHECK-LE: fadd <2 x double> res_vd = vec_and(vbll, vd); // CHECK: and <2 x i64> // CHECK: bitcast <2 x i64> %{{[0-9]*}} to <2 x double> // CHECK-LE: and <2 x i64> // CHECK-LE: bitcast <2 x i64> %{{[0-9]*}} to <2 x double> res_vd = vec_and(vd, vbll); // CHECK: and <2 x i64> // CHECK: bitcast <2 x i64> %{{[0-9]*}} to <2 x double> // CHECK-LE: and <2 x i64> // CHECK-LE: bitcast <2 x i64> %{{[0-9]*}} to <2 x double> res_vd = vec_and(vd, vd); // CHECK: and <2 x i64> // CHECK: bitcast <2 x i64> %{{[0-9]*}} to <2 x double> // CHECK-LE: and <2 x i64> // CHECK-LE: bitcast <2 x i64> %{{[0-9]*}} to <2 x double> dummy(); // CHECK: call void @dummy() // CHECK-LE: call void @dummy() res_vd = vec_andc(vbll, vd); // CHECK: bitcast <2 x double> %{{[0-9]*}} to <2 x i64> // CHECK: xor <2 x i64> %{{[0-9]*}}, // CHECK: and <2 x i64> // CHECK: bitcast <2 x i64> %{{[0-9]*}} to <2 x double> // CHECK-LE: bitcast <2 x double> %{{[0-9]*}} to <2 x i64> // CHECK-LE: xor <2 x i64> %{{[0-9]*}}, // CHECK-LE: and <2 x i64> // CHECK-LE: bitcast <2 x i64> %{{[0-9]*}} to <2 x double> dummy(); // CHECK: call void @dummy() // CHECK-LE: call void @dummy() res_vd = vec_andc(vd, vbll); // CHECK: bitcast <2 x double> %{{[0-9]*}} to <2 x i64> // CHECK: xor <2 x i64> %{{[0-9]*}}, // CHECK: and <2 x i64> // CHECK: bitcast <2 x i64> %{{[0-9]*}} to <2 x double> // CHECK-LE: bitcast <2 x double> %{{[0-9]*}} to <2 x i64> // CHECK-LE: xor <2 x i64> %{{[0-9]*}}, // CHECK-LE: and <2 x i64> // CHECK-LE: bitcast <2 x i64> %{{[0-9]*}} to <2 x double> dummy(); // CHECK: call void @dummy() res_vd = vec_andc(vd, vd); // CHECK: bitcast <2 x double> %{{[0-9]*}} to <2 x i64> // CHECK: xor <2 x i64> %{{[0-9]*}}, // CHECK: and <2 x i64> // CHECK: bitcast <2 x i64> %{{[0-9]*}} to <2 x double> dummy(); // CHECK: call void @dummy() // CHECK-LE: call void @dummy() res_vd = vec_ceil(vd); // CHECK: call <2 x double> @llvm.ceil.v2f64(<2 x double> %{{[0-9]*}}) // CHECK-LE: call <2 x double> @llvm.ceil.v2f64(<2 x double> %{{[0-9]*}}) res_vf = vec_ceil(vf); // CHECK: call <4 x float> @llvm.ceil.v4f32(<4 x float> %{{[0-9]*}}) // CHECK-LE: call <4 x float> @llvm.ceil.v4f32(<4 x float> %{{[0-9]*}}) res_vbll = vec_cmpeq(vd, vd); // CHECK: call <2 x i64> @llvm.ppc.vsx.xvcmpeqdp(<2 x double> %{{[0-9]*}}, <2 x double> %{{[0-9]*}}) // CHECK-LE: call <2 x i64> @llvm.ppc.vsx.xvcmpeqdp(<2 x double> %{{[0-9]*}}, <2 x double> %{{[0-9]*}}) res_vbi = vec_cmpeq(vf, vf); // CHECK: call <4 x i32> @llvm.ppc.vsx.xvcmpeqsp(<4 x float> %{{[0-9]*}}, <4 x float> %{{[0-9]*}}) // CHECK-LE: call <4 x i32> @llvm.ppc.vsx.xvcmpeqsp(<4 x float> %{{[0-9]*}}, <4 x float> %{{[0-9]*}}) res_vbll = vec_cmpge(vd, vd); // CHECK: call <2 x i64> @llvm.ppc.vsx.xvcmpgedp(<2 x double> %{{[0-9]*}}, <2 x double> %{{[0-9]*}}) // CHECK-LE: call <2 x i64> @llvm.ppc.vsx.xvcmpgedp(<2 x double> %{{[0-9]*}}, <2 x double> %{{[0-9]*}}) res_vbi = vec_cmpge(vf, vf); // CHECK: call <4 x i32> @llvm.ppc.vsx.xvcmpgesp(<4 x float> %{{[0-9]*}}, <4 x float> %{{[0-9]*}}) // CHECK-LE: call <4 x i32> @llvm.ppc.vsx.xvcmpgesp(<4 x float> %{{[0-9]*}}, <4 x float> %{{[0-9]*}}) res_vbll = vec_cmpgt(vd, vd); // CHECK: call <2 x i64> @llvm.ppc.vsx.xvcmpgtdp(<2 x double> %{{[0-9]*}}, <2 x double> %{{[0-9]*}}) // CHECK-LE: call <2 x i64> @llvm.ppc.vsx.xvcmpgtdp(<2 x double> %{{[0-9]*}}, <2 x double> %{{[0-9]*}}) res_vbi = vec_cmpgt(vf, vf); // CHECK: call <4 x i32> @llvm.ppc.vsx.xvcmpgtsp(<4 x float> %{{[0-9]*}}, <4 x float> %{{[0-9]*}}) // CHECK-LE: call <4 x i32> @llvm.ppc.vsx.xvcmpgtsp(<4 x float> %{{[0-9]*}}, <4 x float> %{{[0-9]*}}) res_vbll = vec_cmple(vd, vd); // CHECK: call <2 x i64> @llvm.ppc.vsx.xvcmpgedp(<2 x double> %{{[0-9]*}}, <2 x double> %{{[0-9]*}}) // CHECK-LE: call <2 x i64> @llvm.ppc.vsx.xvcmpgedp(<2 x double> %{{[0-9]*}}, <2 x double> %{{[0-9]*}}) res_vbi = vec_cmple(vf, vf); // CHECK: call <4 x i32> @llvm.ppc.vsx.xvcmpgesp(<4 x float> %{{[0-9]*}}, <4 x float> %{{[0-9]*}}) // CHECK-LE: call <4 x i32> @llvm.ppc.vsx.xvcmpgesp(<4 x float> %{{[0-9]*}}, <4 x float> %{{[0-9]*}}) res_vbll = vec_cmplt(vd, vd); // CHECK: call <2 x i64> @llvm.ppc.vsx.xvcmpgtdp(<2 x double> %{{[0-9]*}}, <2 x double> %{{[0-9]*}}) // CHECK-LE: call <2 x i64> @llvm.ppc.vsx.xvcmpgtdp(<2 x double> %{{[0-9]*}}, <2 x double> %{{[0-9]*}}) res_vbi = vec_cmplt(vf, vf); // CHECK: call <4 x i32> @llvm.ppc.vsx.xvcmpgtsp(<4 x float> %{{[0-9]*}}, <4 x float> %{{[0-9]*}}) // CHECK-LE: call <4 x i32> @llvm.ppc.vsx.xvcmpgtsp(<4 x float> %{{[0-9]*}}, <4 x float> %{{[0-9]*}}) /* vec_cpsgn */ res_vf = vec_cpsgn(vf, vf); // CHECK: call <4 x float> @llvm.copysign.v4f32(<4 x float> %{{.+}}, <4 x float> %{{.+}}) // CHECK-LE: call <4 x float> @llvm.copysign.v4f32(<4 x float> %{{.+}}, <4 x float> %{{.+}}) res_vd = vec_cpsgn(vd, vd); // CHECK: call <2 x double> @llvm.copysign.v2f64(<2 x double> %{{.+}}, <2 x double> %{{.+}}) // CHECK-LE: call <2 x double> @llvm.copysign.v2f64(<2 x double> %{{.+}}, <2 x double> %{{.+}}) /* vec_div */ res_vsll = vec_div(vsll, vsll); // CHECK: sdiv <2 x i64> // CHECK-LE: sdiv <2 x i64> res_vull = vec_div(vull, vull); // CHECK: udiv <2 x i64> // CHECK-LE: udiv <2 x i64> res_vf = vec_div(vf, vf); // CHECK: fdiv <4 x float> // CHECK-LE: fdiv <4 x float> res_vd = vec_div(vd, vd); // CHECK: fdiv <2 x double> // CHECK-LE: fdiv <2 x double> /* vec_max */ res_vf = vec_max(vf, vf); // CHECK: @llvm.ppc.vsx.xvmaxsp // CHECK-LE: @llvm.ppc.vsx.xvmaxsp res_vd = vec_max(vd, vd); // CHECK: @llvm.ppc.vsx.xvmaxdp // CHECK-LE: @llvm.ppc.vsx.xvmaxdp res_vf = vec_vmaxfp(vf, vf); // CHECK: @llvm.ppc.vsx.xvmaxsp // CHECK-LE: @llvm.ppc.vsx.xvmaxsp /* vec_min */ res_vf = vec_min(vf, vf); // CHECK: @llvm.ppc.vsx.xvminsp // CHECK-LE: @llvm.ppc.vsx.xvminsp res_vd = vec_min(vd, vd); // CHECK: @llvm.ppc.vsx.xvmindp // CHECK-LE: @llvm.ppc.vsx.xvmindp res_vf = vec_vminfp(vf, vf); // CHECK: @llvm.ppc.vsx.xvminsp // CHECK-LE: @llvm.ppc.vsx.xvminsp res_d = __builtin_vsx_xsmaxdp(d, d); // CHECK: @llvm.ppc.vsx.xsmaxdp // CHECK-LE: @llvm.ppc.vsx.xsmaxdp res_d = __builtin_vsx_xsmindp(d, d); // CHECK: @llvm.ppc.vsx.xsmindp // CHECK-LE: @llvm.ppc.vsx.xsmindp /* vec_perm */ res_vsll = vec_perm(vsll, vsll, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vull = vec_perm(vull, vull, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbll = vec_perm(vbll, vbll, vuc); // CHECK: [[T1:%.+]] = bitcast <2 x i64> {{.+}} to <4 x i32> // CHECK: [[T2:%.+]] = bitcast <2 x i64> {{.+}} to <4 x i32> // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> [[T1]], <4 x i32> [[T2]], <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: [[T1:%.+]] = bitcast <2 x i64> {{.+}} to <4 x i32> // CHECK-LE: [[T2:%.+]] = bitcast <2 x i64> {{.+}} to <4 x i32> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> [[T1]], <4 x i32> [[T2]], <16 x i8> res_vf = vec_round(vf); // CHECK: call <4 x float> @llvm.round.v4f32(<4 x float> // CHECK-LE: call <4 x float> @llvm.round.v4f32(<4 x float> res_vd = vec_round(vd); // CHECK: call <2 x double> @llvm.round.v2f64(<2 x double> // CHECK-LE: call <2 x double> @llvm.round.v2f64(<2 x double> res_vd = vec_perm(vd, vd, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vd = vec_splat(vd, 1); // CHECK: [[T1:%.+]] = bitcast <2 x double> {{.+}} to <4 x i32> // CHECK: [[T2:%.+]] = bitcast <2 x double> {{.+}} to <4 x i32> // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> [[T1]], <4 x i32> [[T2]], <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: [[T1:%.+]] = bitcast <2 x double> {{.+}} to <4 x i32> // CHECK-LE: [[T2:%.+]] = bitcast <2 x double> {{.+}} to <4 x i32> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> [[T1]], <4 x i32> [[T2]], <16 x i8> res_vbll = vec_splat(vbll, 1); // CHECK: [[T1:%.+]] = bitcast <2 x i64> {{.+}} to <4 x i32> // CHECK: [[T2:%.+]] = bitcast <2 x i64> {{.+}} to <4 x i32> // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> [[T1]], <4 x i32> [[T2]], <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: [[T1:%.+]] = bitcast <2 x i64> {{.+}} to <4 x i32> // CHECK-LE: [[T2:%.+]] = bitcast <2 x i64> {{.+}} to <4 x i32> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> [[T1]], <4 x i32> [[T2]], <16 x i8> res_vsll = vec_splat(vsll, 1); // CHECK: [[T1:%.+]] = bitcast <2 x i64> {{.+}} to <4 x i32> // CHECK: [[T2:%.+]] = bitcast <2 x i64> {{.+}} to <4 x i32> // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> [[T1]], <4 x i32> [[T2]], <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: [[T1:%.+]] = bitcast <2 x i64> {{.+}} to <4 x i32> // CHECK-LE: [[T2:%.+]] = bitcast <2 x i64> {{.+}} to <4 x i32> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> [[T1]], <4 x i32> [[T2]], <16 x i8> res_vull = vec_splat(vull, 1); // CHECK: [[T1:%.+]] = bitcast <2 x i64> {{.+}} to <4 x i32> // CHECK: [[T2:%.+]] = bitcast <2 x i64> {{.+}} to <4 x i32> // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> [[T1]], <4 x i32> [[T2]], <16 x i8> // CHECK-LE: xor <16 x i8> // CHECK-LE: [[T1:%.+]] = bitcast <2 x i64> {{.+}} to <4 x i32> // CHECK-LE: [[T2:%.+]] = bitcast <2 x i64> {{.+}} to <4 x i32> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> [[T1]], <4 x i32> [[T2]], <16 x i8> res_vsi = vec_pack(vsll, vsll); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_pack(vull, vull); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vbi = vec_pack(vbll, vbll); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vsll = vec_vperm(vsll, vsll, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vull = vec_vperm(vull, vull, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vd = vec_vperm(vd, vd, vuc); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm /* vec_vsx_ld */ res_vbi = vec_vsx_ld(0, &vbi); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x res_vsi = vec_vsx_ld(0, &vsi); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x res_vsi = vec_vsx_ld(0, asi); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x res_vui = vec_vsx_ld(0, &vui); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x res_vui = vec_vsx_ld(0, aui); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x res_vf = vec_vsx_ld (0, &vf); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x res_vf = vec_vsx_ld (0, af); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x res_vsll = vec_vsx_ld(0, &vsll); // CHECK: @llvm.ppc.vsx.lxvd2x // CHECK-LE: @llvm.ppc.vsx.lxvd2x res_vull = vec_vsx_ld(0, &vull); // CHECK: @llvm.ppc.vsx.lxvd2x // CHECK-LE: @llvm.ppc.vsx.lxvd2x res_vd = vec_vsx_ld(0, &vd); // CHECK: @llvm.ppc.vsx.lxvd2x // CHECK-LE: @llvm.ppc.vsx.lxvd2x res_vd = vec_vsx_ld(0, ad); // CHECK: @llvm.ppc.vsx.lxvd2x // CHECK-LE: @llvm.ppc.vsx.lxvd2x res_vbs = vec_vsx_ld(0, &vbs); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x res_vss = vec_vsx_ld(0, &vss); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x res_vss = vec_vsx_ld(0, ass); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x res_vus = vec_vsx_ld(0, &vus); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x res_vus = vec_vsx_ld(0, aus); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x res_vbc = vec_vsx_ld(0, &vbc); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x res_vsc = vec_vsx_ld(0, &vsc); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x res_vuc = vec_vsx_ld(0, &vuc); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x res_vsc = vec_vsx_ld(0, asc); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x res_vuc = vec_vsx_ld(0, auc); // CHECK: @llvm.ppc.vsx.lxvw4x // CHECK-LE: @llvm.ppc.vsx.lxvw4x /* vec_vsx_st */ vec_vsx_st(vbi, 0, &res_vbi); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vbi, 0, res_aui); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vbi, 0, res_asi); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vsi, 0, &res_vsi); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vsi, 0, res_asi); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vui, 0, &res_vui); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vui, 0, res_aui); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vf, 0, &res_vf); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vf, 0, res_af); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vsll, 0, &res_vsll); // CHECK: @llvm.ppc.vsx.stxvd2x // CHECK-LE: @llvm.ppc.vsx.stxvd2x vec_vsx_st(vull, 0, &res_vull); // CHECK: @llvm.ppc.vsx.stxvd2x // CHECK-LE: @llvm.ppc.vsx.stxvd2x vec_vsx_st(vd, 0, &res_vd); // CHECK: @llvm.ppc.vsx.stxvd2x // CHECK-LE: @llvm.ppc.vsx.stxvd2x vec_vsx_st(vd, 0, res_ad); // CHECK: @llvm.ppc.vsx.stxvd2x // CHECK-LE: @llvm.ppc.vsx.stxvd2x vec_vsx_st(vbs, 0, &res_vbs); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vbs, 0, res_aus); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vbs, 0, res_ass); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vss, 0, &res_vss); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vss, 0, res_ass); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vus, 0, &res_vus); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vus, 0, res_aus); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vsc, 0, &res_vsc); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vsc, 0, res_asc); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vuc, 0, &res_vuc); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vuc, 0, res_auc); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vbc, 0, &res_vbc); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vbc, 0, res_asc); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x vec_vsx_st(vbc, 0, res_auc); // CHECK: @llvm.ppc.vsx.stxvw4x // CHECK-LE: @llvm.ppc.vsx.stxvw4x /* vec_and */ res_vsll = vec_and(vsll, vsll); // CHECK: and <2 x i64> // CHECK-LE: and <2 x i64> res_vsll = vec_and(vbll, vsll); // CHECK: and <2 x i64> // CHECK-LE: and <2 x i64> res_vsll = vec_and(vsll, vbll); // CHECK: and <2 x i64> // CHECK-LE: and <2 x i64> res_vull = vec_and(vull, vull); // CHECK: and <2 x i64> // CHECK-LE: and <2 x i64> res_vull = vec_and(vbll, vull); // CHECK: and <2 x i64> // CHECK-LE: and <2 x i64> res_vull = vec_and(vull, vbll); // CHECK: and <2 x i64> // CHECK-LE: and <2 x i64> res_vbll = vec_and(vbll, vbll); // CHECK: and <2 x i64> // CHECK-LE: and <2 x i64> /* vec_vand */ res_vsll = vec_vand(vsll, vsll); // CHECK: and <2 x i64> // CHECK-LE: and <2 x i64> res_vsll = vec_vand(vbll, vsll); // CHECK: and <2 x i64> // CHECK-LE: and <2 x i64> res_vsll = vec_vand(vsll, vbll); // CHECK: and <2 x i64> // CHECK-LE: and <2 x i64> res_vull = vec_vand(vull, vull); // CHECK: and <2 x i64> // CHECK-LE: and <2 x i64> res_vull = vec_vand(vbll, vull); // CHECK: and <2 x i64> // CHECK-LE: and <2 x i64> res_vull = vec_vand(vull, vbll); // CHECK: and <2 x i64> // CHECK-LE: and <2 x i64> res_vbll = vec_vand(vbll, vbll); // CHECK: and <2 x i64> // CHECK-LE: and <2 x i64> /* vec_andc */ res_vsll = vec_andc(vsll, vsll); // CHECK: xor <2 x i64> // CHECK: and <2 x i64> // CHECK-LE: xor <2 x i64> // CHECK-LE: and <2 x i64> res_vsll = vec_andc(vbll, vsll); // CHECK: xor <2 x i64> // CHECK: and <2 x i64> // CHECK-LE: xor <2 x i64> // CHECK-LE: and <2 x i64> res_vsll = vec_andc(vsll, vbll); // CHECK: xor <2 x i64> // CHECK: and <2 x i64> // CHECK-LE: xor <2 x i64> // CHECK-LE: and <2 x i64> res_vull = vec_andc(vull, vull); // CHECK: xor <2 x i64> // CHECK: and <2 x i64> // CHECK-LE: xor <2 x i64> // CHECK-LE: and <2 x i64> res_vull = vec_andc(vbll, vull); // CHECK: xor <2 x i64> // CHECK: and <2 x i64> // CHECK-LE: xor <2 x i64> // CHECK-LE: and <2 x i64> res_vull = vec_andc(vull, vbll); // CHECK: xor <2 x i64> // CHECK: and <2 x i64> // CHECK-LE: xor <2 x i64> // CHECK-LE: and <2 x i64> res_vbll = vec_andc(vbll, vbll); // CHECK: xor <2 x i64> // CHECK: and <2 x i64> // CHECK-LE: xor <2 x i64> // CHECK-LE: and <2 x i64> res_vf = vec_floor(vf); // CHECK: call <4 x float> @llvm.floor.v4f32(<4 x float> %{{[0-9]+}}) // CHECK-LE: call <4 x float> @llvm.floor.v4f32(<4 x float> %{{[0-9]+}}) res_vd = vec_floor(vd); // CHECK: call <2 x double> @llvm.floor.v2f64(<2 x double> %{{[0-9]+}}) // CHECK-LE: call <2 x double> @llvm.floor.v2f64(<2 x double> %{{[0-9]+}}) res_vf = vec_madd(vf, vf, vf); // CHECK: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{[0-9]+}}, <4 x float> %{{[0-9]+}}, <4 x float> %{{[0-9]+}}) // CHECK-LE: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{[0-9]+}}, <4 x float> %{{[0-9]+}}, <4 x float> %{{[0-9]+}}) res_vd = vec_madd(vd, vd, vd); // CHECK: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{[0-9]+}}, <2 x double> %{{[0-9]+}}, <2 x double> %{{[0-9]+}}) // CHECK-LE: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{[0-9]+}}, <2 x double> %{{[0-9]+}}, <2 x double> %{{[0-9]+}}) /* vec_mergeh */ res_vsll = vec_mergeh(vsll, vsll); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vsll = vec_mergeh(vsll, vbll); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vsll = vec_mergeh(vbll, vsll); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vull = vec_mergeh(vull, vull); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vull = vec_mergeh(vull, vbll); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vull = vec_mergeh(vbll, vull); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm /* vec_mergel */ res_vsll = vec_mergel(vsll, vsll); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vsll = vec_mergel(vsll, vbll); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vsll = vec_mergel(vbll, vsll); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vull = vec_mergel(vull, vull); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vull = vec_mergel(vull, vbll); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm res_vull = vec_mergel(vbll, vull); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm /* vec_msub */ res_vf = vec_msub(vf, vf, vf); // CHECK: fsub <4 x float> , %{{[0-9]+}} // CHECK-NEXT: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{[0-9]+}}, <4 x float> %{{[0-9]+}}, <4 x float> // CHECK-LE: fsub <4 x float> , %{{[0-9]+}} // CHECK-LE-NEXT: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{[0-9]+}}, <4 x float> %{{[0-9]+}}, <4 x float> res_vd = vec_msub(vd, vd, vd); // CHECK: fsub <2 x double> , %{{[0-9]+}} // CHECK-NEXT: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{[0-9]+}}, <2 x double> %{{[0-9]+}}, <2 x double> // CHECK-LE: fsub <2 x double> , %{{[0-9]+}} // CHECK-LE-NEXT: call <2 x double> @llvm.fma.v2f64(<2 x double> %{{[0-9]+}}, <2 x double> %{{[0-9]+}}, <2 x double> res_vsll = vec_mul(vsll, vsll); // CHECK: mul <2 x i64> // CHECK-LE: mul <2 x i64> res_vull = vec_mul(vull, vull); // CHECK: mul <2 x i64> // CHECK-LE: mul <2 x i64> res_vf = vec_mul(vf, vf); // CHECK: fmul <4 x float> %{{[0-9]+}}, %{{[0-9]+}} // CHECK-LE: fmul <4 x float> %{{[0-9]+}}, %{{[0-9]+}} res_vd = vec_mul(vd, vd); // CHECK: fmul <2 x double> %{{[0-9]+}}, %{{[0-9]+}} // CHECK-LE: fmul <2 x double> %{{[0-9]+}}, %{{[0-9]+}} res_vf = vec_nearbyint(vf); // CHECK: call <4 x float> @llvm.round.v4f32(<4 x float> %{{[0-9]+}}) // CHECK-LE: call <4 x float> @llvm.round.v4f32(<4 x float> %{{[0-9]+}}) res_vd = vec_nearbyint(vd); // CHECK: call <2 x double> @llvm.round.v2f64(<2 x double> %{{[0-9]+}}) // CHECK-LE: call <2 x double> @llvm.round.v2f64(<2 x double> %{{[0-9]+}}) res_vf = vec_nmadd(vf, vf, vf); // CHECK: [[FM:[0-9]+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{[0-9]+}}, <4 x float> %{{[0-9]+}}, <4 x float> %{{[0-9]+}}) // CHECK-NEXT: fsub <4 x float> , %[[FM]] // CHECK-LE: [[FM:[0-9]+]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %{{[0-9]+}}, <4 x float> %{{[0-9]+}}, <4 x float> %{{[0-9]+}}) // CHECK-LE-NEXT: fsub <4 x float> , %[[FM]] res_vd = vec_nmadd(vd, vd, vd); // CHECK: [[FM:[0-9]+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{[0-9]+}}, <2 x double> %{{[0-9]+}}, <2 x double> %{{[0-9]+}}) // CHECK-NEXT: fsub <2 x double> , %[[FM]] // CHECK-LE: [[FM:[0-9]+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{[0-9]+}}, <2 x double> %{{[0-9]+}}, <2 x double> %{{[0-9]+}}) // CHECK-LE-NEXT: fsub <2 x double> , %[[FM]] res_vf = vec_nmsub(vf, vf, vf); // CHECK: fsub <4 x float> , %{{[0-9]+}} // CHECK-NEXT: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{[0-9]+}}, <4 x float> %{{[0-9]+}}, <4 x float> // CHECK: fsub <4 x float> , %{{[0-9]+}} // CHECK-LE: fsub <4 x float> , %{{[0-9]+}} // CHECK-LE-NEXT: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{[0-9]+}}, <4 x float> %{{[0-9]+}}, <4 x float> // CHECK-LE: fsub <4 x float> , %{{[0-9]+}} res_vd = vec_nmsub(vd, vd, vd); // CHECK: fsub <2 x double> , %{{[0-9]+}} // CHECK-NEXT: [[FM:[0-9]+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{[0-9]+}}, <2 x double> %{{[0-9]+}}, <2 x double> // CHECK-NEXT: fsub <2 x double> , %[[FM]] // CHECK-LE: fsub <2 x double> , %{{[0-9]+}} // CHECK-LE-NEXT: [[FM:[0-9]+]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %{{[0-9]+}}, <2 x double> %{{[0-9]+}}, <2 x double> // CHECK-LE-NEXT: fsub <2 x double> , %[[FM]] /* vec_nor */ res_vsll = vec_nor(vsll, vsll); // CHECK: or <2 x i64> // CHECK: xor <2 x i64> // CHECK-LE: or <2 x i64> // CHECK-LE: xor <2 x i64> res_vull = vec_nor(vull, vull); // CHECK: or <2 x i64> // CHECK: xor <2 x i64> // CHECK-LE: or <2 x i64> // CHECK-LE: xor <2 x i64> res_vull = vec_nor(vbll, vbll); // CHECK: or <2 x i64> // CHECK: xor <2 x i64> // CHECK-LE: or <2 x i64> // CHECK-LE: xor <2 x i64> res_vd = vec_nor(vd, vd); // CHECK: bitcast <2 x double> %{{[0-9]+}} to <2 x i64> // CHECK: [[OR:%.+]] = or <2 x i64> %{{[0-9]+}}, %{{[0-9]+}} // CHECK-NEXT: xor <2 x i64> [[OR]], // CHECK-LE: bitcast <2 x double> %{{[0-9]+}} to <2 x i64> // CHECK-LE: [[OR:%.+]] = or <2 x i64> %{{[0-9]+}}, %{{[0-9]+}} // CHECK-LE-NEXT: xor <2 x i64> [[OR]], /* vec_or */ res_vsll = vec_or(vsll, vsll); // CHECK: or <2 x i64> // CHECK-LE: or <2 x i64> res_vsll = vec_or(vbll, vsll); // CHECK: or <2 x i64> // CHECK-LE: or <2 x i64> res_vsll = vec_or(vsll, vbll); // CHECK: or <2 x i64> // CHECK-LE: or <2 x i64> res_vull = vec_or(vull, vull); // CHECK: or <2 x i64> // CHECK-LE: or <2 x i64> res_vull = vec_or(vbll, vull); // CHECK: or <2 x i64> // CHECK-LE: or <2 x i64> res_vull = vec_or(vull, vbll); // CHECK: or <2 x i64> // CHECK-LE: or <2 x i64> res_vbll = vec_or(vbll, vbll); // CHECK: or <2 x i64> // CHECK-LE: or <2 x i64> res_vd = vec_or(vd, vd); // CHECK: bitcast <2 x double> %{{[0-9]+}} to <2 x i64> // CHECK: or <2 x i64> %{{[0-9]+}}, %{{[0-9]+}} // CHECK-LE: bitcast <2 x double> %{{[0-9]+}} to <2 x i64> // CHECK-LE: or <2 x i64> %{{[0-9]+}}, %{{[0-9]+}} res_vd = vec_or(vbll, vd); // CHECK: [[T1:%.+]] = bitcast <2 x double> %{{[0-9]+}} to <2 x i64> // CHECK: [[T2:%.+]] = or <2 x i64> %{{[0-9]+}}, [[T1]] // CHECK: bitcast <2 x i64> [[T2]] to <2 x double> // CHECK-LE: [[T1:%.+]] = bitcast <2 x double> %{{[0-9]+}} to <2 x i64> // CHECK-LE: [[T2:%.+]] = or <2 x i64> %{{[0-9]+}}, [[T1]] // CHECK-LE: bitcast <2 x i64> [[T2]] to <2 x double> res_vd = vec_or(vd, vbll); // CHECK: [[T1:%.+]] = bitcast <2 x double> %{{[0-9]+}} to <2 x i64> // CHECK: [[T2:%.+]] = or <2 x i64> [[T1]], %{{[0-9]+}} // CHECK: bitcast <2 x i64> [[T2]] to <2 x double> // CHECK-LE: [[T1:%.+]] = bitcast <2 x double> %{{[0-9]+}} to <2 x i64> // CHECK-LE: [[T2:%.+]] = or <2 x i64> [[T1]], %{{[0-9]+}} // CHECK-LE: bitcast <2 x i64> [[T2]] to <2 x double> res_vf = vec_re(vf); // CHECK: call <4 x float> @llvm.ppc.vsx.xvresp(<4 x float> // CHECK-LE: call <4 x float> @llvm.ppc.vsx.xvresp(<4 x float> res_vd = vec_re(vd); // CHECK: call <2 x double> @llvm.ppc.vsx.xvredp(<2 x double> // CHECK-LE: call <2 x double> @llvm.ppc.vsx.xvredp(<2 x double> res_vf = vec_rint(vf); // CHECK: call <4 x float> @llvm.nearbyint.v4f32(<4 x float> %{{[0-9]+}}) // CHECK-LE: call <4 x float> @llvm.nearbyint.v4f32(<4 x float> %{{[0-9]+}}) res_vd = vec_rint(vd); // CHECK: call <2 x double> @llvm.nearbyint.v2f64(<2 x double> %{{[0-9]+}}) // CHECK-LE: call <2 x double> @llvm.nearbyint.v2f64(<2 x double> %{{[0-9]+}}) res_vf = vec_rsqrte(vf); // CHECK: call <4 x float> @llvm.ppc.vsx.xvrsqrtesp(<4 x float> %{{[0-9]+}}) // CHECK-LE: call <4 x float> @llvm.ppc.vsx.xvrsqrtesp(<4 x float> %{{[0-9]+}}) res_vd = vec_rsqrte(vd); // CHECK: call <2 x double> @llvm.ppc.vsx.xvrsqrtedp(<2 x double> %{{[0-9]+}}) // CHECK-LE: call <2 x double> @llvm.ppc.vsx.xvrsqrtedp(<2 x double> %{{[0-9]+}}) dummy(); // CHECK: call void @dummy() // CHECK-LE: call void @dummy() res_vf = vec_sel(vd, vd, vbll); // CHECK: xor <2 x i64> %{{[0-9]+}}, // CHECK: and <2 x i64> %{{[0-9]+}}, // CHECK: and <2 x i64> %{{[0-9]+}}, %{{[0-9]+}} // CHECK: or <2 x i64> // CHECK: bitcast <2 x i64> %{{[0-9]+}} to <2 x double> // CHECK-LE: xor <2 x i64> %{{[0-9]+}}, // CHECK-LE: and <2 x i64> %{{[0-9]+}}, // CHECK-LE: and <2 x i64> %{{[0-9]+}}, %{{[0-9]+}} // CHECK-LE: or <2 x i64> // CHECK-LE: bitcast <2 x i64> %{{[0-9]+}} to <2 x double> dummy(); // CHECK: call void @dummy() // CHECK-LE: call void @dummy() res_vd = vec_sel(vd, vd, vull); // CHECK: xor <2 x i64> %{{[0-9]+}}, // CHECK: and <2 x i64> %{{[0-9]+}}, // CHECK: and <2 x i64> %{{[0-9]+}}, %{{[0-9]+}} // CHECK: or <2 x i64> // CHECK: bitcast <2 x i64> %{{[0-9]+}} to <2 x double> // CHECK-LE: xor <2 x i64> %{{[0-9]+}}, // CHECK-LE: and <2 x i64> %{{[0-9]+}}, // CHECK-LE: and <2 x i64> %{{[0-9]+}}, %{{[0-9]+}} // CHECK-LE: or <2 x i64> // CHECK-LE: bitcast <2 x i64> %{{[0-9]+}} to <2 x double> res_vf = vec_sqrt(vf); // CHECK: call <4 x float> @llvm.sqrt.v4f32(<4 x float> %{{[0-9]+}}) // CHECK-LE: call <4 x float> @llvm.sqrt.v4f32(<4 x float> %{{[0-9]+}}) res_vd = vec_sqrt(vd); // CHECK: call <2 x double> @llvm.sqrt.v2f64(<2 x double> %{{[0-9]+}}) // CHECK-LE: call <2 x double> @llvm.sqrt.v2f64(<2 x double> %{{[0-9]+}}) res_vd = vec_sub(vd, vd); // CHECK: fsub <2 x double> %{{[0-9]+}}, %{{[0-9]+}} // CHECK-LE: fsub <2 x double> %{{[0-9]+}}, %{{[0-9]+}} res_vf = vec_trunc(vf); // CHECK: call <4 x float> @llvm.trunc.v4f32(<4 x float> %{{[0-9]+}}) // CHECK-LE: call <4 x float> @llvm.trunc.v4f32(<4 x float> %{{[0-9]+}}) res_vd = vec_trunc(vd); // CHECK: call <2 x double> @llvm.trunc.v2f64(<2 x double> %{{[0-9]+}}) // CHECK-LE: call <2 x double> @llvm.trunc.v2f64(<2 x double> %{{[0-9]+}}) /* vec_vor */ res_vsll = vec_vor(vsll, vsll); // CHECK: or <2 x i64> // CHECK-LE: or <2 x i64> res_vsll = vec_vor(vbll, vsll); // CHECK: or <2 x i64> // CHECK-LE: or <2 x i64> res_vsll = vec_vor(vsll, vbll); // CHECK: or <2 x i64> // CHECK-LE: or <2 x i64> res_vull = vec_vor(vull, vull); // CHECK: or <2 x i64> // CHECK-LE: or <2 x i64> res_vull = vec_vor(vbll, vull); // CHECK: or <2 x i64> // CHECK-LE: or <2 x i64> res_vull = vec_vor(vull, vbll); // CHECK: or <2 x i64> // CHECK-LE: or <2 x i64> res_vbll = vec_vor(vbll, vbll); // CHECK: or <2 x i64> // CHECK-LE: or <2 x i64> /* vec_xor */ res_vsll = vec_xor(vsll, vsll); // CHECK: xor <2 x i64> // CHECK-LE: xor <2 x i64> res_vsll = vec_xor(vbll, vsll); // CHECK: xor <2 x i64> // CHECK-LE: xor <2 x i64> res_vsll = vec_xor(vsll, vbll); // CHECK: xor <2 x i64> // CHECK-LE: xor <2 x i64> res_vull = vec_xor(vull, vull); // CHECK: xor <2 x i64> // CHECK-LE: xor <2 x i64> res_vull = vec_xor(vbll, vull); // CHECK: xor <2 x i64> // CHECK-LE: xor <2 x i64> res_vull = vec_xor(vull, vbll); // CHECK: xor <2 x i64> // CHECK-LE: xor <2 x i64> res_vbll = vec_xor(vbll, vbll); // CHECK: xor <2 x i64> // CHECK-LE: xor <2 x i64> dummy(); // CHECK: call void @dummy() // CHECK-LE: call void @dummy() res_vd = vec_xor(vd, vd); // CHECK: [[X1:%.+]] = xor <2 x i64> %{{[0-9]+}}, %{{[0-9]+}} // CHECK: bitcast <2 x i64> [[X1]] to <2 x double> // CHECK-LE: [[X1:%.+]] = xor <2 x i64> %{{[0-9]+}}, %{{[0-9]+}} // CHECK-LE: bitcast <2 x i64> [[X1]] to <2 x double> dummy(); // CHECK: call void @dummy() // CHECK-LE: call void @dummy() res_vd = vec_xor(vd, vbll); // CHECK: [[X1:%.+]] = xor <2 x i64> %{{[0-9]+}}, %{{[0-9]+}} // CHECK: bitcast <2 x i64> [[X1]] to <2 x double> // CHECK-LE: [[X1:%.+]] = xor <2 x i64> %{{[0-9]+}}, %{{[0-9]+}} // CHECK-LE: bitcast <2 x i64> [[X1]] to <2 x double> dummy(); // CHECK: call void @dummy() // CHECK-LE: call void @dummy() res_vd = vec_xor(vbll, vd); // CHECK: [[X1:%.+]] = xor <2 x i64> %{{[0-9]+}}, %{{[0-9]+}} // CHECK: bitcast <2 x i64> [[X1]] to <2 x double> // CHECK-LE: [[X1:%.+]] = xor <2 x i64> %{{[0-9]+}}, %{{[0-9]+}} // CHECK-LE: bitcast <2 x i64> [[X1]] to <2 x double> /* vec_vxor */ res_vsll = vec_vxor(vsll, vsll); // CHECK: xor <2 x i64> // CHECK-LE: xor <2 x i64> res_vsll = vec_vxor(vbll, vsll); // CHECK: xor <2 x i64> // CHECK-LE: xor <2 x i64> res_vsll = vec_vxor(vsll, vbll); // CHECK: xor <2 x i64> // CHECK-LE: xor <2 x i64> res_vull = vec_vxor(vull, vull); // CHECK: xor <2 x i64> // CHECK-LE: xor <2 x i64> res_vull = vec_vxor(vbll, vull); // CHECK: xor <2 x i64> // CHECK-LE: xor <2 x i64> res_vull = vec_vxor(vull, vbll); // CHECK: xor <2 x i64> // CHECK-LE: xor <2 x i64> res_vbll = vec_vxor(vbll, vbll); // CHECK: xor <2 x i64> // CHECK-LE: xor <2 x i64> res_vsll = vec_cts(vd, 0); // CHECK: fmul <2 x double> // CHECK: fptosi <2 x double> %{{.*}} to <2 x i64> // CHECK-LE: fmul <2 x double> // CHECK-LE: fptosi <2 x double> %{{.*}} to <2 x i64> res_vsll = vec_cts(vd, 31); // CHECK: fmul <2 x double> // CHECK: fptosi <2 x double> %{{.*}} to <2 x i64> // CHECK-LE: fmul <2 x double> // CHECK-LE: fptosi <2 x double> %{{.*}} to <2 x i64> res_vsll = vec_ctu(vd, 0); // CHECK: fmul <2 x double> // CHECK: fptoui <2 x double> %{{.*}} to <2 x i64> // CHECK-LE: fmul <2 x double> // CHECK-LE: fptoui <2 x double> %{{.*}} to <2 x i64> res_vsll = vec_ctu(vd, 31); // CHECK: fmul <2 x double> // CHECK: fptoui <2 x double> %{{.*}} to <2 x i64> // CHECK-LE: fmul <2 x double> // CHECK-LE: fptoui <2 x double> %{{.*}} to <2 x i64> res_vd = vec_ctf(vsll, 0); // CHECK: sitofp <2 x i64> %{{.*}} to <2 x double> // CHECK: fmul <2 x double> // CHECK-LE: sitofp <2 x i64> %{{.*}} to <2 x double> // CHECK-LE: fmul <2 x double> res_vd = vec_ctf(vsll, 31); // CHECK: sitofp <2 x i64> %{{.*}} to <2 x double> // CHECK: fmul <2 x double> // CHECK-LE: sitofp <2 x i64> %{{.*}} to <2 x double> // CHECK-LE: fmul <2 x double> res_vd = vec_ctf(vull, 0); // CHECK: uitofp <2 x i64> %{{.*}} to <2 x double> // CHECK: fmul <2 x double> // CHECK-LE: uitofp <2 x i64> %{{.*}} to <2 x double> // CHECK-LE: fmul <2 x double> res_vd = vec_ctf(vull, 31); // CHECK: uitofp <2 x i64> %{{.*}} to <2 x double> // CHECK: fmul <2 x double> // CHECK-LE: uitofp <2 x i64> %{{.*}} to <2 x double> // CHECK-LE: fmul <2 x double> res_vsll = vec_signed(vd); // CHECK: fptosi <2 x double> // CHECK-LE: fptosi <2 x double> res_vsi = vec_signed2(vd, vd); // CHECK: extractelement <2 x double> // CHECK: fptosi double // CHECK: insertelement <4 x i32> // CHECK: extractelement <2 x double> // CHECK: fptosi double // CHECK: insertelement <4 x i32> // CHECK: extractelement <2 x double> // CHECK: fptosi double // CHECK: insertelement <4 x i32> // CHECK: extractelement <2 x double> // CHECK: fptosi double // CHECK: insertelement <4 x i32> // CHECK-LE: extractelement <2 x double> // CHECK-LE: fptosi double // CHECK-LE: insertelement <4 x i32> // CHECK-LE: extractelement <2 x double> // CHECK-LE: fptosi double // CHECK-LE: insertelement <4 x i32> // CHECK-LE: extractelement <2 x double> // CHECK-LE: fptosi double // CHECK-LE: insertelement <4 x i32> // CHECK-LE: extractelement <2 x double> // CHECK-LE: fptosi double // CHECK-LE: insertelement <4 x i32> res_vsi = vec_signede(vd); // CHECK: @llvm.ppc.vsx.xvcvdpsxws(<2 x double> // CHECK-LE: @llvm.ppc.vsx.xvcvdpsxws(<2 x double> // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vsi = vec_signedo(vd); // CHECK: @llvm.ppc.vsx.xvcvdpsxws(<2 x double> // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.vsx.xvcvdpsxws(<2 x double> res_vull = vec_unsigned(vd); // CHECK: fptoui <2 x double> // CHECK-LE: fptoui <2 x double> res_vui = vec_unsigned2(vd, vd); // CHECK: extractelement <2 x double> // CHECK: fptoui double // CHECK: insertelement <4 x i32> // CHECK: extractelement <2 x double> // CHECK: fptoui double // CHECK: insertelement <4 x i32> // CHECK: extractelement <2 x double> // CHECK: fptoui double // CHECK: insertelement <4 x i32> // CHECK: extractelement <2 x double> // CHECK: fptoui double // CHECK: insertelement <4 x i32> // CHECK-LE: extractelement <2 x double> // CHECK-LE: fptoui double // CHECK-LE: insertelement <4 x i32> // CHECK-LE: extractelement <2 x double> // CHECK-LE: fptoui double // CHECK-LE: insertelement <4 x i32> // CHECK-LE: extractelement <2 x double> // CHECK-LE: fptoui double // CHECK-LE: insertelement <4 x i32> // CHECK-LE: extractelement <2 x double> // CHECK-LE: fptoui double // CHECK-LE: insertelement <4 x i32> res_vui = vec_unsignede(vd); // CHECK: @llvm.ppc.vsx.xvcvdpuxws(<2 x double> // CHECK-LE: @llvm.ppc.vsx.xvcvdpuxws(<2 x double> // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vui = vec_unsignedo(vd); // CHECK: @llvm.ppc.vsx.xvcvdpuxws(<2 x double> // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.vsx.xvcvdpuxws(<2 x double> res_vf = vec_float2(vsll, vsll); // CHECK: extractelement <2 x i64> // CHECK: sitofp i64 // CHECK: insertelement <4 x float> // CHECK: extractelement <2 x i64> // CHECK: sitofp i64 // CHECK: insertelement <4 x float> // CHECK: extractelement <2 x i64> // CHECK: sitofp i64 // CHECK: insertelement <4 x float> // CHECK: extractelement <2 x i64> // CHECK: sitofp i64 // CHECK: insertelement <4 x float> // CHECK-LE: extractelement <2 x i64> // CHECK-LE: sitofp i64 // CHECK-LE: insertelement <4 x float> // CHECK-LE: extractelement <2 x i64> // CHECK-LE: sitofp i64 // CHECK-LE: insertelement <4 x float> // CHECK-LE: extractelement <2 x i64> // CHECK-LE: sitofp i64 // CHECK-LE: insertelement <4 x float> // CHECK-LE: extractelement <2 x i64> // CHECK-LE: sitofp i64 // CHECK-LE: insertelement <4 x float> res_vf = vec_float2(vull, vull); // CHECK: extractelement <2 x i64> // CHECK: uitofp i64 // CHECK: insertelement <4 x float> // CHECK: extractelement <2 x i64> // CHECK: uitofp i64 // CHECK: insertelement <4 x float> // CHECK: extractelement <2 x i64> // CHECK: uitofp i64 // CHECK: insertelement <4 x float> // CHECK: extractelement <2 x i64> // CHECK: uitofp i64 // CHECK: insertelement <4 x float> // CHECK-LE: extractelement <2 x i64> // CHECK-LE: uitofp i64 // CHECK-LE: insertelement <4 x float> // CHECK-LE: extractelement <2 x i64> // CHECK-LE: uitofp i64 // CHECK-LE: insertelement <4 x float> // CHECK-LE: extractelement <2 x i64> // CHECK-LE: uitofp i64 // CHECK-LE: insertelement <4 x float> // CHECK-LE: extractelement <2 x i64> // CHECK-LE: uitofp i64 // CHECK-LE: insertelement <4 x float> res_vf = vec_float2(vd, vd); // CHECK: extractelement <2 x double> // CHECK: fptrunc double // CHECK: insertelement <4 x float> // CHECK: extractelement <2 x double> // CHECK: fptrunc double // CHECK: insertelement <4 x float> // CHECK: extractelement <2 x double> // CHECK: fptrunc double // CHECK: insertelement <4 x float> // CHECK: extractelement <2 x double> // CHECK: fptrunc double // CHECK: insertelement <4 x float> // CHECK-LE: extractelement <2 x double> // CHECK-LE: fptrunc double // CHECK-LE: insertelement <4 x float> // CHECK-LE: extractelement <2 x double> // CHECK-LE: fptrunc double // CHECK-LE: insertelement <4 x float> // CHECK-LE: extractelement <2 x double> // CHECK-LE: fptrunc double // CHECK-LE: insertelement <4 x float> // CHECK-LE: extractelement <2 x double> // CHECK-LE: fptrunc double // CHECK-LE: insertelement <4 x float> res_vf = vec_floate(vsll); // CHECK: @llvm.ppc.vsx.xvcvsxdsp // CHECK-LE: @llvm.ppc.vsx.xvcvsxdsp // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vf = vec_floate(vull); // CHECK: @llvm.ppc.vsx.xvcvuxdsp // CHECK-LE: @llvm.ppc.vsx.xvcvuxdsp // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vf = vec_floate(vd); // CHECK: @llvm.ppc.vsx.xvcvdpsp // CHECK-LE: @llvm.ppc.vsx.xvcvdpsp // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vf = vec_floato(vsll); // CHECK: @llvm.ppc.vsx.xvcvsxdsp // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.vsx.xvcvsxdsp res_vf = vec_floato(vull); // CHECK: @llvm.ppc.vsx.xvcvuxdsp // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.vsx.xvcvuxdsp res_vf = vec_floato(vd); // CHECK: @llvm.ppc.vsx.xvcvdpsp // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.vsx.xvcvdpsp res_vd = vec_double(vsll); // CHECK: sitofp <2 x i64> // CHECK-LE: sitofp <2 x i64> res_vd = vec_double(vull); // CHECK: uitofp <2 x i64> // CHECK-LE: uitofp <2 x i64> res_vd = vec_doublee(vsi); // CHECK: @llvm.ppc.vsx.xvcvsxwdp(<4 x i32 // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.vsx.xvcvsxwdp(<4 x i32 res_vd = vec_doublee(vui); // CHECK: @llvm.ppc.vsx.xvcvuxwdp(<4 x i32 // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.vsx.xvcvuxwdp(<4 x i32 res_vd = vec_doublee(vf); // CHECK: @llvm.ppc.vsx.xvcvspdp(<4 x float // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.vsx.xvcvspdp(<4 x float res_vd = vec_doubleh(vsi); // CHECK: extractelement <4 x i32> // CHECK: sitofp i32 // CHECK: insertelement <2 x double> // CHECK: extractelement <4 x i32> // CHECK: sitofp i32 // CHECK: insertelement <2 x double> // CHECK-LE: extractelement <4 x i32> // CHECK-LE: sitofp i32 // CHECK-LE: insertelement <2 x double> // CHECK-LE: extractelement <4 x i32> // CHECK-LE: sitofp i32 // CHECK-LE: insertelement <2 x double> res_vd = vec_doubleh(vui); // CHECK: extractelement <4 x i32> // CHECK: uitofp i32 // CHECK: insertelement <2 x double> // CHECK: extractelement <4 x i32> // CHECK: uitofp i32 // CHECK: insertelement <2 x double> // CHECK-LE: extractelement <4 x i32> // CHECK-LE: uitofp i32 // CHECK-LE: insertelement <2 x double> // CHECK-LE: extractelement <4 x i32> // CHECK-LE: uitofp i32 // CHECK-LE: insertelement <2 x double> res_vd = vec_doubleh(vf); // CHECK: extractelement <4 x float> // CHECK: fpext float // CHECK: insertelement <2 x double> // CHECK: extractelement <4 x float> // CHECK: fpext float // CHECK: insertelement <2 x double> // CHECK-LE: extractelement <4 x float> // CHECK-LE: fpext float // CHECK-LE: insertelement <2 x double> // CHECK-LE: extractelement <4 x float> // CHECK-LE: fpext float // CHECK-LE: insertelement <2 x double> res_vd = vec_doublel(vsi); // CHECK: extractelement <4 x i32> // CHECK: sitofp i32 // CHECK: insertelement <2 x double> // CHECK: extractelement <4 x i32> // CHECK: sitofp i32 // CHECK: insertelement <2 x double> // CHECK-LE: extractelement <4 x i32> // CHECK-LE: sitofp i32 // CHECK-LE: insertelement <2 x double> // CHECK-LE: extractelement <4 x i32> // CHECK-LE: sitofp i32 // CHECK-LE: insertelement <2 x double> res_vd = vec_doublel(vui); // CHECK: extractelement <4 x i32> // CHECK: uitofp i32 // CHECK: insertelement <2 x double> // CHECK: extractelement <4 x i32> // CHECK: uitofp i32 // CHECK: insertelement <2 x double> // CHECK-LE: extractelement <4 x i32> // CHECK-LE: uitofp i32 // CHECK-LE: insertelement <2 x double> // CHECK-LE: extractelement <4 x i32> // CHECK-LE: uitofp i32 // CHECK-LE: insertelement <2 x double> res_vd = vec_doublel(vf); // CHECK: extractelement <4 x float> // CHECK: fpext float // CHECK: insertelement <2 x double> // CHECK: extractelement <4 x float> // CHECK: fpext float // CHECK: insertelement <2 x double> // CHECK-LE: extractelement <4 x float> // CHECK-LE: fpext float // CHECK-LE: insertelement <2 x double> // CHECK-LE: extractelement <4 x float> // CHECK-LE: fpext float // CHECK-LE: insertelement <2 x double> res_vd = vec_doubleo(vsi); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.vsx.xvcvsxwdp(<4 x i32> // CHECK-LE: @llvm.ppc.vsx.xvcvsxwdp(<4 x i32> res_vd = vec_doubleo(vui); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.vsx.xvcvuxwdp(<4 x i32> // CHECK-LE: @llvm.ppc.vsx.xvcvuxwdp(<4 x i32> res_vd = vec_doubleo(vf); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK: @llvm.ppc.vsx.xvcvspdp(<4 x float> // CHECK-LE: @llvm.ppc.vsx.xvcvspdp(<4 x float> res_vbll = vec_reve(vbll); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vsll = vec_reve(vsll); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vull = vec_reve(vull); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vd = vec_reve(vd); // CHECK: shufflevector <2 x double> %{{[0-9]+}}, <2 x double> %{{[0-9]+}}, <2 x i32> // CHECK-LE: shufflevector <2 x double> %{{[0-9]+}}, <2 x double> %{{[0-9]+}}, <2 x i32> res_vbll = vec_revb(vbll); // CHECK: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: xor <16 x i8> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) res_vsll = vec_revb(vsll); // CHECK: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: xor <16 x i8> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) res_vull = vec_revb(vull); // CHECK: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: xor <16 x i8> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) res_vd = vec_revb(vd); // CHECK: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: store <16 x i8> , <16 x i8>* {{%.+}}, align 16 // CHECK-LE: xor <16 x i8> // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}}) res_vbll = vec_sld(vbll, vbll, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vsll = vec_sld(vsll, vsll, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vull = vec_sld(vull, vull, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vd = vec_sld(vd, vd, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vsll = vec_sldw(vsll, vsll, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vull = vec_sldw(vull, vull, 0); // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3 // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15 // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: sub nsw i32 16 // CHECK-LE: sub nsw i32 17 // CHECK-LE: sub nsw i32 18 // CHECK-LE: sub nsw i32 31 // CHECK-LE: @llvm.ppc.altivec.vperm res_vsll = vec_sll(vsll, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vull = vec_sll(vull, vuc); // CHECK: @llvm.ppc.altivec.vsl // CHECK-LE: @llvm.ppc.altivec.vsl res_vsll = vec_slo(vsll, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vsll = vec_slo(vsll, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vull = vec_slo(vull, vsc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vull = vec_slo(vull, vuc); // CHECK: @llvm.ppc.altivec.vslo // CHECK-LE: @llvm.ppc.altivec.vslo res_vsll = vec_srl(vsll, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vull = vec_srl(vull, vuc); // CHECK: @llvm.ppc.altivec.vsr // CHECK-LE: @llvm.ppc.altivec.vsr res_vsll = vec_sro(vsll, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vsll = vec_sro(vsll, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vull = vec_sro(vull, vsc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vull = vec_sro(vull, vuc); // CHECK: @llvm.ppc.altivec.vsro // CHECK-LE: @llvm.ppc.altivec.vsro res_vsll = vec_xl(sll, asll); -// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16 -// CHECK-LE: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16 +// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 1 +// CHECK-LE: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 1 res_vull = vec_xl(sll, aull); -// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16 -// CHECK-LE: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16 +// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 1 +// CHECK-LE: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 1 res_vd = vec_xl(sll, ad); -// CHECK: load <2 x double>, <2 x double>* %{{[0-9]+}}, align 16 -// CHECK-LE: load <2 x double>, <2 x double>* %{{[0-9]+}}, align 16 +// CHECK: load <2 x double>, <2 x double>* %{{[0-9]+}}, align 1 +// CHECK-LE: load <2 x double>, <2 x double>* %{{[0-9]+}}, align 1 vec_xst(vsll, sll, asll); -// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16 -// CHECK-LE: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16 +// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 1 +// CHECK-LE: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 1 vec_xst(vull, sll, aull); -// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16 -// CHECK-LE: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16 +// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 1 +// CHECK-LE: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 1 vec_xst(vd, sll, ad); -// CHECK: store <2 x double> %{{[0-9]+}}, <2 x double>* %{{[0-9]+}}, align 16 -// CHECK-LE: store <2 x double> %{{[0-9]+}}, <2 x double>* %{{[0-9]+}}, align 16 +// CHECK: store <2 x double> %{{[0-9]+}}, <2 x double>* %{{[0-9]+}}, align 1 +// CHECK-LE: store <2 x double> %{{[0-9]+}}, <2 x double>* %{{[0-9]+}}, align 1 res_vsll = vec_xl_be(sll, asll); -// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16 +// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 1 // CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}}) res_vull = vec_xl_be(sll, aull); -// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16 +// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 1 // CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}}) res_vd = vec_xl_be(sll, ad); -// CHECK: load <2 x double>, <2 x double>* %{{[0-9]+}}, align 16 +// CHECK: load <2 x double>, <2 x double>* %{{[0-9]+}}, align 1 // CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}}) vec_xst_be(vsll, sll, asll); -// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16 +// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 1 // CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}}) vec_xst_be(vull, sll, aull); -// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16 +// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 1 // CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}}) vec_xst_be(vd, sll, ad); -// CHECK: store <2 x double> %{{[0-9]+}}, <2 x double>* %{{[0-9]+}}, align 16 +// CHECK: store <2 x double> %{{[0-9]+}}, <2 x double>* %{{[0-9]+}}, align 1 // CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}}) res_vf = vec_neg(vf); // CHECK: fsub <4 x float> , {{%[0-9]+}} // CHECK-LE: fsub <4 x float> , {{%[0-9]+}} res_vd = vec_neg(vd); // CHECK: fsub <2 x double> , {{%[0-9]+}} // CHECK-LE: fsub <2 x double> , {{%[0-9]+}} res_vd = vec_xxpermdi(vd, vd, 0); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vf = vec_xxpermdi(vf, vf, 1); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vsll = vec_xxpermdi(vsll, vsll, 2); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vull = vec_xxpermdi(vull, vull, 3); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vsi = vec_xxpermdi(vsi, vsi, 0); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vui = vec_xxpermdi(vui, vui, 1); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vss = vec_xxpermdi(vss, vss, 2); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vus = vec_xxpermdi(vus, vus, 3); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vsc = vec_xxpermdi(vsc, vsc, 0); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vuc = vec_xxpermdi(vuc, vuc, 1); // CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> res_vd = vec_xxsldwi(vd, vd, 0); // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> // CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> res_vf = vec_xxsldwi(vf, vf, 1); // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> // CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> res_vsll = vec_xxsldwi(vsll, vsll, 2); // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> // CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> res_vull = vec_xxsldwi(vull, vull, 3); // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> // CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> res_vsi = vec_xxsldwi(vsi, vsi, 0); // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> // CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> res_vui = vec_xxsldwi(vui, vui, 1); // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> // CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> res_vss = vec_xxsldwi(vss, vss, 2); // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> // CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> res_vus = vec_xxsldwi(vus, vus, 3); // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> // CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> res_vsc = vec_xxsldwi(vsc, vsc, 0); // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> // CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> res_vuc = vec_xxsldwi(vuc, vuc, 1); // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> // CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> } // The return type of the call expression may be different from the return type of the shufflevector. // Wrong implementation could crash the compiler, add this test case to check that and avoid ICE. vector int xxpermdi_should_not_assert(vector int a, vector int b) { return vec_xxpermdi(a, b, 0); // CHECK-LABEL: xxpermdi_should_not_assert // CHECK: bitcast <4 x i32> %{{[0-9]+}} to <2 x i64> // CHECK-NEXT: bitcast <4 x i32> %{{[0-9]+}} to <2 x i64> // CHECK-NEXT: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-NEXT: bitcast <2 x i64> %{{[0-9]+}} to <4 x i32> // CHECK-LE: bitcast <4 x i32> %{{[0-9]+}} to <2 x i64> // CHECK-LE-NEXT: bitcast <4 x i32> %{{[0-9]+}} to <2 x i64> // CHECK-LE-NEXT: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> // CHECK-LE-NEXT: bitcast <2 x i64> %{{[0-9]+}} to <4 x i32> } vector double xxsldwi_should_not_assert(vector double a, vector double b) { return vec_xxsldwi(a, b, 0); // CHECK-LABEL: xxsldwi_should_not_assert // CHECK: bitcast <2 x double> %{{[0-9]+}} to <4 x i32> // CHECK-NEXT: bitcast <2 x double> %{{[0-9]+}} to <4 x i32> // CHECK-NEXT: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> // CHECK-NEXT: bitcast <4 x i32> %{{[0-9]+}} to <2 x double> // CHECK-LE: bitcast <2 x double> %{{[0-9]+}} to <4 x i32> // CHECK-NEXT-LE: bitcast <2 x double> %{{[0-9]+}} to <4 x i32> // CHECK-NEXT-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> // CHECK-NEXT-LE: bitcast <4 x i32> %{{[0-9]+}} to <2 x double> } Index: vendor/clang/dist-release_70/test/CoverageMapping/macros.c =================================================================== --- vendor/clang/dist-release_70/test/CoverageMapping/macros.c (revision 341366) +++ vendor/clang/dist-release_70/test/CoverageMapping/macros.c (revision 341367) @@ -1,64 +1,74 @@ // RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name macros.c %s | FileCheck %s #define MACRO return; bar() #define MACRO_2 bar() #define MACRO_1 return; MACRO_2 #define MACRO_3 MACRO_2 +#define GOTO goto void bar() {} // CHECK: func void func() { // CHECK-NEXT: File 0, [[@LINE]]:13 -> [[@LINE+5]]:2 = #0 int i = 0; // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = #0 MACRO; // CHECK-NEXT: File 0, [[@LINE]]:8 -> [[@LINE+2]]:2 = 0 i = 2; } // CHECK-NEXT: File 1, 3:15 -> 3:28 = #0 // CHECK-NEXT: File 1, 3:23 -> 3:28 = 0 // CHECK-NEXT: func2 void func2() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+5]]:2 = #0 int i = 0; // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:10 = #0 MACRO_1; // CHECK-NEXT: File 0, [[@LINE]]:10 -> [[@LINE+2]]:2 = 0 i = 2; } // CHECK-NEXT: File 1, 5:17 -> 5:32 = #0 // CHECK-NEXT: Expansion,File 1, 5:25 -> 5:32 = 0 // CHECK-NEXT: File 2, 4:17 -> 4:22 = 0 // CHECK-NEXT: func3 void func3() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+3]]:2 = #0 MACRO_2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:3 -> [[@LINE]]:10 = #0 MACRO_2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:3 -> [[@LINE]]:10 = #0 } // CHECK-NEXT: File 1, 4:17 -> 4:22 = #0 // CHECK-NEXT: File 2, 4:17 -> 4:22 = #0 // CHECK-NEXT: func4 void func4() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+6]]:2 = #0 int i = 0; while (i++ < 10) // CHECK-NEXT: File 0, [[@LINE]]:10 -> [[@LINE]]:18 = (#0 + #1) if (i < 5) // CHECK: File 0, [[@LINE]]:5 -> [[@LINE+2]]:14 = #1 // CHECK-NEXT: File 0, [[@LINE-1]]:9 -> [[@LINE-1]]:14 = #1 MACRO_2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:7 -> [[@LINE]]:14 = #2 } // CHECK-NEXT: File 1, 4:17 -> 4:22 = #2 // CHECK-NOT: File 1 // CHECK-NEXT: func5 void func5() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+4]]:2 = #0 int i = 0; if (i > 5) // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:12 = #0 MACRO_3; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:5 -> [[@LINE]]:12 = #1 } // CHECK-NEXT: Expansion,File 1, 6:17 -> 6:24 = #1 // CHECK-NEXT: File 2, 4:17 -> 4:22 = #1 + +// CHECK-NEXT: func6 +void func6(unsigned count) { // CHECK-NEXT: File 0, [[@LINE]]:28 -> [[@LINE+4]]:2 = #0 +begin: // CHECK-NEXT: File 0, [[@LINE]]:1 -> [[@LINE+3]]:2 = #1 + if (count--) // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:16 = #1 + GOTO begin; // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:19 = #2 +} +// CHECK-NEXT: Expansion,File 0, [[@LINE-2]]:9 -> [[@LINE-2]]:13 = #2 +// CHECK-NEXT: File 1, 7:14 -> 7:18 = #2 int main(int argc, const char *argv[]) { func(); func2(); func3(); func4(); } Index: vendor/clang/dist-release_70/test/Driver/openbsd.c =================================================================== --- vendor/clang/dist-release_70/test/Driver/openbsd.c (revision 341366) +++ vendor/clang/dist-release_70/test/Driver/openbsd.c (revision 341367) @@ -1,114 +1,119 @@ // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD %s // CHECK-LD: clang{{.*}}" "-cc1" "-triple" "i686-pc-openbsd" // CHECK-LD: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "{{.*}}.o" "-lgcc" "-lc" "-lgcc" "{{.*}}crtend.o" // Check for --eh-frame-hdr being passed with static linking // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -static %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD-STATIC-EH %s // CHECK-LD-STATIC-EH: clang{{.*}}" "-cc1" "-triple" "i686-pc-openbsd" // CHECK-LD-STATIC-EH: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bstatic" "-o" "a.out" "{{.*}}rcrt0.o" "{{.*}}crtbegin.o" "{{.*}}.o" "-lgcc" "-lc" "-lgcc" "{{.*}}crtend.o" // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -pg -pthread %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-PG %s // CHECK-PG: clang{{.*}}" "-cc1" "-triple" "i686-pc-openbsd" // CHECK-PG: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}gcrt0.o" "{{.*}}crtbegin.o" "{{.*}}.o" "-lgcc" "-lpthread_p" "-lc_p" "-lgcc" "{{.*}}crtend.o" // Check CPU type for MIPS64 // RUN: %clang -target mips64-unknown-openbsd -### -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-MIPS64-CPU %s // RUN: %clang -target mips64el-unknown-openbsd -### -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-MIPS64EL-CPU %s // CHECK-MIPS64-CPU: "-target-cpu" "mips3" // CHECK-MIPS64EL-CPU: "-target-cpu" "mips3" // Check that the new linker flags are passed to OpenBSD // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -r %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD-R %s // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -s %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD-S %s // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -t %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD-T %s // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -Z %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD-Z %s // RUN: %clang -no-canonical-prefixes -target mips64-unknown-openbsd %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-MIPS64-LD %s // RUN: %clang -no-canonical-prefixes -target mips64el-unknown-openbsd %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-MIPS64EL-LD %s // CHECK-LD-R: clang{{.*}}" "-cc1" "-triple" "i686-pc-openbsd" // CHECK-LD-R: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "-r" "{{.*}}.o" "-lgcc" "-lc" "-lgcc" "{{.*}}crtend.o" // CHECK-LD-S: clang{{.*}}" "-cc1" "-triple" "i686-pc-openbsd" // CHECK-LD-S: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "-s" "{{.*}}.o" "-lgcc" "-lc" "-lgcc" "{{.*}}crtend.o" // CHECK-LD-T: clang{{.*}}" "-cc1" "-triple" "i686-pc-openbsd" // CHECK-LD-T: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "-t" "{{.*}}.o" "-lgcc" "-lc" "-lgcc" "{{.*}}crtend.o" // CHECK-LD-Z: clang{{.*}}" "-cc1" "-triple" "i686-pc-openbsd" // CHECK-LD-Z: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "-Z" "{{.*}}.o" "-lgcc" "-lc" "-lgcc" "{{.*}}crtend.o" // CHECK-MIPS64-LD: clang{{.*}}" "-cc1" "-triple" "mips64-unknown-openbsd" // CHECK-MIPS64-LD: ld{{.*}}" "-EB" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "{{.*}}.o" "-lgcc" "-lc" "-lgcc" "{{.*}}crtend.o" // CHECK-MIPS64EL-LD: clang{{.*}}" "-cc1" "-triple" "mips64el-unknown-openbsd" // CHECK-MIPS64EL-LD: ld{{.*}}" "-EL" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}crt0.o" "{{.*}}crtbegin.o" "-L{{.*}}" "{{.*}}.o" "-lgcc" "-lc" "-lgcc" "{{.*}}crtend.o" // Check passing options to the assembler for various OpenBSD targets // RUN: %clang -target amd64-pc-openbsd -m32 -### -no-integrated-as -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-AMD64-M32 %s // RUN: %clang -target powerpc-unknown-openbsd -### -no-integrated-as -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-POWERPC %s // RUN: %clang -target sparc-unknown-openbsd -### -no-integrated-as -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-SPARC %s // RUN: %clang -target sparc64-unknown-openbsd -### -no-integrated-as -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-SPARC64 %s // RUN: %clang -target mips64-unknown-openbsd -### -no-integrated-as -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-MIPS64 %s // RUN: %clang -target mips64-unknown-openbsd -fPIC -### -no-integrated-as -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-MIPS64-PIC %s // RUN: %clang -target mips64el-unknown-openbsd -### -no-integrated-as -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-MIPS64EL %s // RUN: %clang -target mips64el-unknown-openbsd -fPIC -### -no-integrated-as -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-MIPS64EL-PIC %s // CHECK-AMD64-M32: as{{.*}}" "--32" // CHECK-POWERPC: as{{.*}}" "-mppc" "-many" // CHECK-SPARC: as{{.*}}" "-32" "-Av8" // CHECK-SPARC64: as{{.*}}" "-64" "-Av9" // CHECK-MIPS64: as{{.*}}" "-mabi" "64" "-EB" // CHECK-MIPS64-PIC: as{{.*}}" "-mabi" "64" "-EB" "-KPIC" // CHECK-MIPS64EL: as{{.*}}" "-mabi" "64" "-EL" // CHECK-MIPS64EL-PIC: as{{.*}}" "-mabi" "64" "-EL" "-KPIC" // Check that the integrated assembler is enabled for MIPS64 // RUN: %clang -target mips64-unknown-openbsd -### -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-MIPS64-AS %s // RUN: %clang -target mips64el-unknown-openbsd -### -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-MIPS64-AS %s // CHECK-MIPS64-AS-NOT: "-no-integrated-as" // Check linking against correct startup code when (not) using PIE // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-PIE %s // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -pie %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-PIE-FLAG %s // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -fno-pie %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-PIE %s // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -static %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-STATIC-PIE %s // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -static -fno-pie %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-STATIC-PIE %s // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -nopie %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-NOPIE %s // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -fno-pie -nopie %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-NOPIE %s // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -static -nopie %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-NOPIE %s // RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -fno-pie -static -nopie %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-NOPIE %s // CHECK-PIE: "{{.*}}crt0.o" // CHECK-PIE-NOT: "-nopie" // CHECK-PIE-FLAG: "-pie" // CHECK-STATIC-PIE: "{{.*}}rcrt0.o" // CHECK-STATIC-PIE-NOT: "-nopie" // CHECK-NOPIE: "-nopie" "{{.*}}crt0.o" // Check ARM float ABI // RUN: %clang -target arm-unknown-openbsd -### -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-ARM-FLOAT-ABI %s // CHECK-ARM-FLOAT-ABI-NOT: "-target-feature" "+soft-float" // CHECK-ARM-FLOAT-ABI: "-target-feature" "+soft-float-abi" + +// Check PowerPC for Secure PLT +// RUN: %clang -target powerpc-unknown-openbsd -### -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-POWERPC-SECUREPLT %s +// CHECK-POWERPC-SECUREPLT: "-target-feature" "+secure-plt" Index: vendor/clang/dist-release_70/test/Frontend/warning-stdlibcxx-darwin.cpp =================================================================== --- vendor/clang/dist-release_70/test/Frontend/warning-stdlibcxx-darwin.cpp (revision 341366) +++ vendor/clang/dist-release_70/test/Frontend/warning-stdlibcxx-darwin.cpp (revision 341367) @@ -1,5 +1,5 @@ // RUN: %clang -cc1 -triple arm64-apple-ios6.0.0 -isysroot %S/doesnotexist %s 2>&1 | FileCheck %s // RUN: %clang -cc1 -triple arm64-apple-ios6.0.0 -isysroot %S/doesnotexist -stdlib=libc++ %s -verify -// CHECK: include path for stdlibc++ headers not found; pass '-std=libc++' on the command line to use the libc++ standard library instead +// CHECK: include path for stdlibc++ headers not found; pass '-stdlib=libc++' on the command line to use the libc++ standard library instead // expected-no-diagnostics Index: vendor/clang/dist-release_70/test/Sema/attr-ifunc.c =================================================================== --- vendor/clang/dist-release_70/test/Sema/attr-ifunc.c (revision 341366) +++ vendor/clang/dist-release_70/test/Sema/attr-ifunc.c (revision 341367) @@ -1,47 +1,43 @@ // RUN: %clang_cc1 -triple x86_64-windows -fsyntax-only -verify %s // RUN: %clang_cc1 -triple x86_64-linux -fsyntax-only -verify -emit-llvm-only -DCHECK_ALIASES %s // RUN: %clang_cc1 -triple x86_64-linux -fsyntax-only -verify -emit-llvm-only %s #if defined(_WIN32) void foo() {} void bar() __attribute__((ifunc("foo"))); //expected-warning@-1 {{unknown attribute 'ifunc' ignored}} #else #if defined(CHECK_ALIASES) void* f1_ifunc(); void f1() __attribute__((ifunc("f1_ifunc"))); //expected-error@-1 {{ifunc must point to a defined function}} void* f2_a() __attribute__((ifunc("f2_b"))); //expected-error@-1 {{ifunc definition is part of a cycle}} void* f2_b() __attribute__((ifunc("f2_a"))); //expected-error@-1 {{ifunc definition is part of a cycle}} void* f3_a() __attribute__((ifunc("f3_b"))); //expected-warning@-1 {{ifunc will always resolve to f3_c even if weak definition of f3_b is overridden}} void* f3_b() __attribute__((weak, alias("f3_c"))); void* f3_c() { return 0; } void f4_ifunc() {} void f4() __attribute__((ifunc("f4_ifunc"))); //expected-error@-1 {{ifunc resolver function must return a pointer}} -void* f5_ifunc(int i) { return 0; } -void f5() __attribute__((ifunc("f5_ifunc"))); -//expected-error@-1 {{ifunc resolver function must have no parameters}} - #else void f1a() __asm("f1"); void f1a() {} //expected-note@-1 {{previous definition is here}} void f1() __attribute__((ifunc("f1_ifunc"))); //expected-error@-1 {{definition with same mangled name 'f1' as another definition}} void* f1_ifunc() { return 0; } void* f6_ifunc(int i); void __attribute__((ifunc("f6_ifunc"))) f6() {} //expected-error@-1 {{definition 'f6' cannot also be an ifunc}} #endif #endif Index: vendor/clang/dist-release_70/test/SemaCXX/sourceranges.cpp =================================================================== --- vendor/clang/dist-release_70/test/SemaCXX/sourceranges.cpp (revision 341366) +++ vendor/clang/dist-release_70/test/SemaCXX/sourceranges.cpp (revision 341367) @@ -1,139 +1,146 @@ // RUN: %clang_cc1 -triple i686-mingw32 -ast-dump %s | FileCheck %s // RUN: %clang_cc1 -triple i686-mingw32 -std=c++1z -ast-dump %s | FileCheck %s -check-prefix=CHECK-1Z template class P { public: P(T* t) {} }; namespace foo { class A { public: A(int = 0) {} }; enum B {}; typedef int C; } // CHECK: VarDecl {{0x[0-9a-fA-F]+}} col:15 ImplicitConstrArray 'foo::A [2]' static foo::A ImplicitConstrArray[2]; int main() { // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} 'foo::A *' P p14 = new foo::A; // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} 'foo::B *' P p24 = new foo::B; // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} 'foo::C *' P pr4 = new foo::C; } foo::A getName() { // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} 'foo::A' return foo::A(); } void destruct(foo::A *a1, foo::A *a2, P *p1) { // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} '' ->~A a1->~A(); // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} '' ->~A a2->foo::A::~A(); // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} '' ->~P p1->~P(); } struct D { D(int); ~D(); }; void construct() { using namespace foo; A a = A(12); // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} 'foo::A' 'void (int){{( __attribute__\(\(thiscall\)\))?}}' D d = D(12); // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} 'D' 'void (int){{( __attribute__\(\(thiscall\)\))?}}' } +namespace PR38987 { +struct A { A(); }; +template void f() { T{}; } +template void f(); +// CHECK: CXXTemporaryObjectExpr {{.*}} 'PR38987::A':'PR38987::A' +} + void abort() __attribute__((noreturn)); namespace std { typedef decltype(sizeof(int)) size_t; template struct initializer_list { const E *p; size_t n; initializer_list(const E *p, size_t n) : p(p), n(n) {} }; template struct pair { F f; S s; pair(const F &f, const S &s) : f(f), s(s) {} }; struct string { const char *str; string() { abort(); } string(const char *S) : str(S) {} ~string() { abort(); } }; template struct map { using T = pair; map(initializer_list i, const string &s = string()) {} ~map() { abort(); } }; }; // namespace std #if __cplusplus >= 201703L // CHECK-1Z: FunctionDecl {{.*}} construct_with_init_list std::map construct_with_init_list() { // CHECK-1Z-NEXT: CompoundStmt // CHECK-1Z-NEXT: ReturnStmt {{.*}} {{0, 0}}; } // CHECK-1Z: NamespaceDecl {{.*}} in_class_init namespace in_class_init { struct A {}; // CHECK-1Z: CXXRecordDecl {{.*}} struct B definition struct B { // CHECK-1Z: FieldDecl {{.*}} a 'in_class_init::A' // CHECK-1Z-NEXT: InitListExpr {{.*}} 0, # Verbose output from this script. AnalyzeHeaders => 0, OutputDir => undef, # Parent directory to store HTML files. HtmlTitle => basename($CurrentDir)." - scan-build results", IgnoreErrors => 0, # Ignore build errors. KeepCC => 0, # Do not override CC and CXX make variables ViewResults => 0, # View results when the build terminates. ExitStatusFoundBugs => 0, # Exit status reflects whether bugs were found ShowDescription => 0, # Display the description of the defect in the list KeepEmpty => 0, # Don't remove output directory even with 0 results. EnableCheckers => {}, DisableCheckers => {}, UseCC => undef, # C compiler to use for compilation. UseCXX => undef, # C++ compiler to use for compilation. AnalyzerTarget => undef, StoreModel => undef, ConstraintsModel => undef, InternalStats => undef, OutputFormat => "html", ConfigOptions => [], # Options to pass through to the analyzer's -analyzer-config flag. ReportFailures => undef, AnalyzerStats => 0, MaxLoop => 0, PluginsToLoad => [], AnalyzerDiscoveryMethod => undef, OverrideCompiler => 0, # The flag corresponding to the --override-compiler command line option. ForceAnalyzeDebugCode => 0 ); lock_keys(%Options); ##----------------------------------------------------------------------------## # Diagnostics ##----------------------------------------------------------------------------## sub Diag { if ($UseColor) { print BOLD, MAGENTA "$Prog: @_"; print RESET; } else { print "$Prog: @_"; } } sub ErrorDiag { if ($UseColor) { print STDERR BOLD, RED "$Prog: "; print STDERR RESET, RED @_; print STDERR RESET; } else { print STDERR "$Prog: @_"; } } sub DiagCrashes { my $Dir = shift; Diag ("The analyzer encountered problems on some source files.\n"); Diag ("Preprocessed versions of these sources were deposited in '$Dir/failures'.\n"); Diag ("Please consider submitting a bug report using these files:\n"); Diag (" http://clang-analyzer.llvm.org/filing_bugs.html\n") } sub DieDiag { if ($UseColor) { print STDERR BOLD, RED "$Prog: "; print STDERR RESET, RED @_; print STDERR RESET; } else { print STDERR "$Prog: ", @_; } exit 1; } ##----------------------------------------------------------------------------## # Print default checker names ##----------------------------------------------------------------------------## if (grep /^--help-checkers$/, @ARGV) { my @options = qx($0 -h); foreach (@options) { next unless /^ \+/; s/^\s*//; my ($sign, $name, @text) = split ' ', $_; print $name, $/ if $sign eq '+'; } exit 0; } ##----------------------------------------------------------------------------## # Declaration of Clang options. Populated later. ##----------------------------------------------------------------------------## my $Clang; my $ClangSB; my $ClangCXX; my $ClangVersion; ##----------------------------------------------------------------------------## # GetHTMLRunDir - Construct an HTML directory name for the current sub-run. ##----------------------------------------------------------------------------## sub GetHTMLRunDir { die "Not enough arguments." if (@_ == 0); my $Dir = shift @_; my $TmpMode = 0; if (!defined $Dir) { $Dir = $ENV{'TMPDIR'} || $ENV{'TEMP'} || $ENV{'TMP'} || "/tmp"; $TmpMode = 1; } # Chop off any trailing '/' characters. while ($Dir =~ /\/$/) { chop $Dir; } # Get current date and time. my @CurrentTime = localtime(); my $year = $CurrentTime[5] + 1900; my $day = $CurrentTime[3]; my $month = $CurrentTime[4] + 1; my $hour = $CurrentTime[2]; my $min = $CurrentTime[1]; my $sec = $CurrentTime[0]; my $TimeString = sprintf("%02d%02d%02d", $hour, $min, $sec); my $DateString = sprintf("%d-%02d-%02d-%s-$$", $year, $month, $day, $TimeString); # Determine the run number. my $RunNumber; if (-d $Dir) { if (! -r $Dir) { DieDiag("directory '$Dir' exists but is not readable.\n"); } # Iterate over all files in the specified directory. my $max = 0; opendir(DIR, $Dir); my @FILES = grep { -d "$Dir/$_" } readdir(DIR); closedir(DIR); foreach my $f (@FILES) { # Strip the prefix '$Prog-' if we are dumping files to /tmp. if ($TmpMode) { next if (!($f =~ /^$Prog-(.+)/)); $f = $1; } my @x = split/-/, $f; next if (scalar(@x) != 4); next if ($x[0] != $year); next if ($x[1] != $month); next if ($x[2] != $day); next if ($x[3] != $TimeString); next if ($x[4] != $$); if ($x[5] > $max) { $max = $x[5]; } } $RunNumber = $max + 1; } else { if (-x $Dir) { DieDiag("'$Dir' exists but is not a directory.\n"); } if ($TmpMode) { DieDiag("The directory '/tmp' does not exist or cannot be accessed.\n"); } # $Dir does not exist. It will be automatically created by the # clang driver. Set the run number to 1. $RunNumber = 1; } die "RunNumber must be defined!" if (!defined $RunNumber); # Append the run number. my $NewDir; if ($TmpMode) { $NewDir = "$Dir/$Prog-$DateString-$RunNumber"; } else { $NewDir = "$Dir/$DateString-$RunNumber"; } # Make sure that the directory does not exist in order to avoid hijack. if (-e $NewDir) { DieDiag("The directory '$NewDir' already exists.\n"); } mkpath($NewDir); return $NewDir; } sub SetHtmlEnv { die "Wrong number of arguments." if (scalar(@_) != 2); my $Args = shift; my $Dir = shift; die "No build command." if (scalar(@$Args) == 0); my $Cmd = $$Args[0]; if ($Cmd =~ /configure/ || $Cmd =~ /autogen/) { return; } if ($Options{Verbose}) { Diag("Emitting reports for this run to '$Dir'.\n"); } $ENV{'CCC_ANALYZER_HTML'} = $Dir; } ##----------------------------------------------------------------------------## # ComputeDigest - Compute a digest of the specified file. ##----------------------------------------------------------------------------## sub ComputeDigest { my $FName = shift; DieDiag("Cannot read $FName to compute Digest.\n") if (! -r $FName); # Use Digest::MD5. We don't have to be cryptographically secure. We're # just looking for duplicate files that come from a non-malicious source. # We use Digest::MD5 because it is a standard Perl module that should # come bundled on most systems. open(FILE, $FName) or DieDiag("Cannot open $FName when computing Digest.\n"); binmode FILE; my $Result = Digest::MD5->new->addfile(*FILE)->hexdigest; close(FILE); # Return the digest. return $Result; } ##----------------------------------------------------------------------------## # UpdatePrefix - Compute the common prefix of files. ##----------------------------------------------------------------------------## my $Prefix; sub UpdatePrefix { my $x = shift; my $y = basename($x); $x =~ s/\Q$y\E$//; if (!defined $Prefix) { $Prefix = $x; return; } chop $Prefix while (!($x =~ /^\Q$Prefix/)); } sub GetPrefix { return $Prefix; } ##----------------------------------------------------------------------------## # UpdateInFilePath - Update the path in the report file. ##----------------------------------------------------------------------------## sub UpdateInFilePath { my $fname = shift; my $regex = shift; my $newtext = shift; open (RIN, $fname) or die "cannot open $fname"; open (ROUT, ">", "$fname.tmp") or die "cannot open $fname.tmp"; while () { s/$regex/$newtext/; print ROUT $_; } close (ROUT); close (RIN); rename("$fname.tmp", $fname) } ##----------------------------------------------------------------------------## # AddStatLine - Decode and insert a statistics line into the database. ##----------------------------------------------------------------------------## sub AddStatLine { my $Line = shift; my $Stats = shift; my $File = shift; print $Line . "\n"; my $Regex = qr/(.*?)\ ->\ Total\ CFGBlocks:\ (\d+)\ \|\ Unreachable \ CFGBlocks:\ (\d+)\ \|\ Exhausted\ Block:\ (yes|no)\ \|\ Empty\ WorkList: \ (yes|no)/x; if ($Line !~ $Regex) { return; } # Create a hash of the interesting fields my $Row = { Filename => $File, Function => $1, Total => $2, Unreachable => $3, Aborted => $4, Empty => $5 }; # Add them to the stats array push @$Stats, $Row; } ##----------------------------------------------------------------------------## # ScanFile - Scan a report file for various identifying attributes. ##----------------------------------------------------------------------------## # Sometimes a source file is scanned more than once, and thus produces # multiple error reports. We use a cache to solve this problem. my %AlreadyScanned; sub ScanFile { my $Index = shift; my $Dir = shift; my $FName = shift; my $Stats = shift; # Compute a digest for the report file. Determine if we have already # scanned a file that looks just like it. my $digest = ComputeDigest("$Dir/$FName"); if (defined $AlreadyScanned{$digest}) { # Redundant file. Remove it. unlink("$Dir/$FName"); return; } $AlreadyScanned{$digest} = 1; # At this point the report file is not world readable. Make it happen. chmod(0644, "$Dir/$FName"); # Scan the report file for tags. open(IN, "$Dir/$FName") or DieDiag("Cannot open '$Dir/$FName'\n"); my $BugType = ""; my $BugFile = ""; my $BugFunction = ""; my $BugCategory = ""; my $BugDescription = ""; my $BugPathLength = 1; my $BugLine = 0; while () { last if (//); if (/$/) { $BugType = $1; } elsif (/$/) { $BugFile = abs_path($1); if (!defined $BugFile) { # The file no longer exists: use the original path. $BugFile = $1; } UpdatePrefix($BugFile); } elsif (/$/) { $BugPathLength = $1; } elsif (/$/) { $BugLine = $1; } elsif (/$/) { $BugCategory = $1; } elsif (/$/) { $BugDescription = $1; } elsif (/$/) { $BugFunction = $1; } } close(IN); if (!defined $BugCategory) { $BugCategory = "Other"; } # Don't add internal statistics to the bug reports if ($BugCategory =~ /statistics/i) { AddStatLine($BugDescription, $Stats, $BugFile); return; } push @$Index,[ $FName, $BugCategory, $BugType, $BugFile, $BugFunction, $BugLine, $BugPathLength ]; if ($Options{ShowDescription}) { push @{ $Index->[-1] }, $BugDescription } } ##----------------------------------------------------------------------------## # CopyFiles - Copy resource files to target directory. ##----------------------------------------------------------------------------## sub CopyFiles { my $Dir = shift; my $JS = Cwd::realpath("$RealBin/../share/scan-build/sorttable.js"); DieDiag("Cannot find 'sorttable.js'.\n") if (! -r $JS); copy($JS, "$Dir"); DieDiag("Could not copy 'sorttable.js' to '$Dir'.\n") if (! -r "$Dir/sorttable.js"); my $CSS = Cwd::realpath("$RealBin/../share/scan-build/scanview.css"); DieDiag("Cannot find 'scanview.css'.\n") if (! -r $CSS); copy($CSS, "$Dir"); DieDiag("Could not copy 'scanview.css' to '$Dir'.\n") if (! -r $CSS); } ##----------------------------------------------------------------------------## # CalcStats - Calculates visitation statistics and returns the string. ##----------------------------------------------------------------------------## sub CalcStats { my $Stats = shift; my $TotalBlocks = 0; my $UnreachedBlocks = 0; my $TotalFunctions = scalar(@$Stats); my $BlockAborted = 0; my $WorkListAborted = 0; my $Aborted = 0; # Calculate the unique files my $FilesHash = {}; foreach my $Row (@$Stats) { $FilesHash->{$Row->{Filename}} = 1; $TotalBlocks += $Row->{Total}; $UnreachedBlocks += $Row->{Unreachable}; $BlockAborted++ if $Row->{Aborted} eq 'yes'; $WorkListAborted++ if $Row->{Empty} eq 'no'; $Aborted++ if $Row->{Aborted} eq 'yes' || $Row->{Empty} eq 'no'; } my $TotalFiles = scalar(keys(%$FilesHash)); # Calculations my $PercentAborted = sprintf("%.2f", $Aborted / $TotalFunctions * 100); my $PercentBlockAborted = sprintf("%.2f", $BlockAborted / $TotalFunctions * 100); my $PercentWorkListAborted = sprintf("%.2f", $WorkListAborted / $TotalFunctions * 100); my $PercentBlocksUnreached = sprintf("%.2f", $UnreachedBlocks / $TotalBlocks * 100); my $StatsString = "Analyzed $TotalBlocks blocks in $TotalFunctions functions" . " in $TotalFiles files\n" . "$Aborted functions aborted early ($PercentAborted%)\n" . "$BlockAborted had aborted blocks ($PercentBlockAborted%)\n" . "$WorkListAborted had unfinished worklists ($PercentWorkListAborted%)\n" . "$UnreachedBlocks blocks were never reached ($PercentBlocksUnreached%)\n"; return $StatsString; } ##----------------------------------------------------------------------------## # Postprocess - Postprocess the results of an analysis scan. ##----------------------------------------------------------------------------## my @filesFound; my $baseDir; sub FileWanted { my $baseDirRegEx = quotemeta $baseDir; my $file = $File::Find::name; # The name of the file is generated by clang binary (HTMLDiagnostics.cpp) if ($file =~ /report-.*\.html$/) { my $relative_file = $file; $relative_file =~ s/$baseDirRegEx//g; push @filesFound, $relative_file; } } sub Postprocess { my $Dir = shift; my $BaseDir = shift; my $AnalyzerStats = shift; my $KeepEmpty = shift; die "No directory specified." if (!defined $Dir); if (! -d $Dir) { Diag("No bugs found.\n"); return 0; } $baseDir = $Dir . "/"; find({ wanted => \&FileWanted, follow => 0}, $Dir); if (scalar(@filesFound) == 0 and ! -e "$Dir/failures") { if (! $KeepEmpty) { Diag("Removing directory '$Dir' because it contains no reports.\n"); rmtree($Dir) or die "Cannot rmtree '$Dir' : $!"; } Diag("No bugs found.\n"); return 0; } # Scan each report file and build an index. my @Index; my @Stats; foreach my $file (@filesFound) { ScanFile(\@Index, $Dir, $file, \@Stats); } # Scan the failures directory and use the information in the .info files # to update the common prefix directory. my @failures; my @attributes_ignored; if (-d "$Dir/failures") { opendir(DIR, "$Dir/failures"); @failures = grep { /[.]info.txt$/ && !/attribute_ignored/; } readdir(DIR); closedir(DIR); opendir(DIR, "$Dir/failures"); @attributes_ignored = grep { /^attribute_ignored/; } readdir(DIR); closedir(DIR); foreach my $file (@failures) { open IN, "$Dir/failures/$file" or DieDiag("cannot open $file\n"); my $Path = ; if (defined $Path) { UpdatePrefix($Path); } close IN; } } # Generate an index.html file. my $FName = "$Dir/index.html"; open(OUT, ">", $FName) or DieDiag("Cannot create file '$FName'\n"); # Print out the header. print OUT < ${Options{HtmlTitle}}

${Options{HtmlTitle}}

ENDTEXT print OUT "\n" if (defined($BuildName) && defined($BuildDate)); print OUT < ENDTEXT if (scalar(@filesFound)) { # Print out the summary table. my %Totals; for my $row ( @Index ) { my $bug_type = ($row->[2]); my $bug_category = ($row->[1]); my $key = "$bug_category:$bug_type"; if (!defined $Totals{$key}) { $Totals{$key} = [1,$bug_category,$bug_type]; } else { $Totals{$key}->[0]++; } } print OUT "

Bug Summary

"; if (defined $BuildName) { print OUT "\n

Results in this analysis run are based on analyzer build $BuildName.

\n" } my $TotalBugs = scalar(@Index); print OUT <
ENDTEXT my $last_category; for my $key ( sort { my $x = $Totals{$a}; my $y = $Totals{$b}; my $res = $x->[1] cmp $y->[1]; $res = $x->[2] cmp $y->[2] if ($res == 0); $res } keys %Totals ) { my $val = $Totals{$key}; my $category = $val->[1]; if (!defined $last_category or $last_category ne $category) { $last_category = $category; print OUT "\n"; } my $x = lc $key; $x =~ s/[ ,'":\/()]+/_/g; print OUT "\n"; } # Print out the table of errors. print OUT <

Reports

User:${UserName}\@${HostName}
Working Directory:${CurrentDir}
Command Line:${CmdArgs}
Clang Version:${ClangVersion}
Date:${Date}
Version:${BuildName} (${BuildDate})
Bug TypeQuantityDisplay?
All Bugs$TotalBugs
$category
"; print OUT $val->[2]; print OUT ""; print OUT $val->[0]; print OUT "
ENDTEXT if ($Options{ShowDescription}) { print OUT <Description ENDTEXT } print OUT < ENDTEXT my $prefix = GetPrefix(); my $regex; my $InFileRegex; my $InFilePrefix = "File:"; print OUT ""; print OUT ""; # Update the file prefix. my $fname = $row->[3]; if (defined $regex) { $fname =~ s/$regex//; UpdateInFilePath("$Dir/$ReportFile", $InFileRegex, $InFilePrefix) } print OUT ""; print OUT ""; # Print out the quantities. for my $j ( 5 .. 6 ) { # Line & Path length print OUT ""; } # Print the rest of the columns. for (my $j = 7; $j <= $#{$row}; ++$j) { print OUT "" } # Emit the "View" link. print OUT ""; # Emit REPORTBUG markers. print OUT "\n\n"; # End the row. print OUT "\n"; } print OUT "\n
Bug Group Bug Type ▾ File Function/Method Line Path Length
"; if (defined $prefix) { $regex = qr/^\Q$prefix\E/is; $InFileRegex = qr/\Q$InFilePrefix$prefix\E/is; } for my $row ( sort { $a->[2] cmp $b->[2] } @Index ) { my $x = "$row->[1]:$row->[2]"; $x = lc $x; $x =~ s/[ ,'":\/()]+/_/g; my $ReportFile = $row->[0]; print OUT "
"; print OUT $row->[1]; # $BugCategory print OUT ""; print OUT $row->[2]; # $BugType print OUT ""; my @fname = split /\//,$fname; if ($#fname > 0) { while ($#fname >= 0) { my $x = shift @fname; print OUT $x; if ($#fname >= 0) { print OUT "/"; } } } else { print OUT $fname; } print OUT ""; print OUT $row->[4]; # Function print OUT "$row->[$j]$row->[$j]View Report
\n\n"; } if (scalar (@failures) || scalar(@attributes_ignored)) { print OUT "

Analyzer Failures

\n"; if (scalar @attributes_ignored) { print OUT "The analyzer's parser ignored the following attributes:

\n"; print OUT "\n"; print OUT "\n"; foreach my $file (sort @attributes_ignored) { die "cannot demangle attribute name\n" if (! ($file =~ /^attribute_ignored_(.+).txt/)); my $attribute = $1; # Open the attribute file to get the first file that failed. next if (!open (ATTR, "$Dir/failures/$file")); my $ppfile = ; chomp $ppfile; close ATTR; next if (! -e "$Dir/failures/$ppfile"); # Open the info file and get the name of the source file. open (INFO, "$Dir/failures/$ppfile.info.txt") or die "Cannot open $Dir/failures/$ppfile.info.txt\n"; my $srcfile = ; chomp $srcfile; close (INFO); # Print the information in the table. my $prefix = GetPrefix(); if (defined $prefix) { $srcfile =~ s/^\Q$prefix//; } print OUT "\n"; my $ppfile_clang = $ppfile; $ppfile_clang =~ s/[.](.+)$/.clang.$1/; print OUT " \n"; } print OUT "
AttributeSource FilePreprocessed FileSTDERR Output
$attribute$srcfile$ppfile$ppfile.stderr.txt
\n"; } if (scalar @failures) { print OUT "

The analyzer had problems processing the following files:

\n"; print OUT "\n"; print OUT "\n"; foreach my $file (sort @failures) { $file =~ /(.+).info.txt$/; # Get the preprocessed file. my $ppfile = $1; # Open the info file and get the name of the source file. open (INFO, "$Dir/failures/$file") or die "Cannot open $Dir/failures/$file\n"; my $srcfile = ; chomp $srcfile; my $problem = ; chomp $problem; close (INFO); # Print the information in the table. my $prefix = GetPrefix(); if (defined $prefix) { $srcfile =~ s/^\Q$prefix//; } print OUT "\n"; my $ppfile_clang = $ppfile; $ppfile_clang =~ s/[.](.+)$/.clang.$1/; print OUT " \n"; } print OUT "
ProblemSource FilePreprocessed FileSTDERR Output
$problem$srcfile$ppfile$ppfile.stderr.txt
\n"; } print OUT "

Please consider submitting preprocessed files as bug reports.

\n"; } print OUT "\n"; close(OUT); CopyFiles($Dir); # Make sure $Dir and $BaseDir are world readable/executable. chmod(0755, $Dir); if (defined $BaseDir) { chmod(0755, $BaseDir); } # Print statistics print CalcStats(\@Stats) if $AnalyzerStats; my $Num = scalar(@Index); if ($Num == 1) { Diag("$Num bug found.\n"); } else { Diag("$Num bugs found.\n"); } if ($Num > 0 && -r "$Dir/index.html") { Diag("Run 'scan-view $Dir' to examine bug reports.\n"); } DiagCrashes($Dir) if (scalar @failures || scalar @attributes_ignored); return $Num; } ##----------------------------------------------------------------------------## # RunBuildCommand - Run the build command. ##----------------------------------------------------------------------------## sub AddIfNotPresent { my $Args = shift; my $Arg = shift; my $found = 0; foreach my $k (@$Args) { if ($k eq $Arg) { $found = 1; last; } } if ($found == 0) { push @$Args, $Arg; } } sub SetEnv { my $EnvVars = shift @_; foreach my $var ('CC', 'CXX', 'CLANG', 'CLANG_CXX', 'CCC_ANALYZER_ANALYSIS', 'CCC_ANALYZER_PLUGINS', 'CCC_ANALYZER_CONFIG') { die "$var is undefined\n" if (!defined $var); $ENV{$var} = $EnvVars->{$var}; } foreach my $var ('CCC_ANALYZER_STORE_MODEL', 'CCC_ANALYZER_CONSTRAINTS_MODEL', 'CCC_ANALYZER_INTERNAL_STATS', 'CCC_ANALYZER_OUTPUT_FORMAT', 'CCC_CC', 'CCC_CXX', 'CCC_REPORT_FAILURES', 'CLANG_ANALYZER_TARGET', 'CCC_ANALYZER_FORCE_ANALYZE_DEBUG_CODE') { my $x = $EnvVars->{$var}; if (defined $x) { $ENV{$var} = $x } } my $Verbose = $EnvVars->{'VERBOSE'}; if ($Verbose >= 2) { $ENV{'CCC_ANALYZER_VERBOSE'} = 1; } if ($Verbose >= 3) { $ENV{'CCC_ANALYZER_LOG'} = 1; } } sub RunXcodebuild { my $Args = shift; my $IgnoreErrors = shift; my $CCAnalyzer = shift; my $CXXAnalyzer = shift; my $EnvVars = shift; if ($IgnoreErrors) { AddIfNotPresent($Args,"-PBXBuildsContinueAfterErrors=YES"); } # Detect the version of Xcode. If Xcode 4.6 or higher, use new # in situ support for analyzer interposition without needed to override # the compiler. open(DETECT_XCODE, "-|", $Args->[0], "-version") or die "error: cannot detect version of xcodebuild\n"; my $oldBehavior = 1; while() { if (/^Xcode (.+)$/) { my $ver = $1; if ($ver =~ /^([0-9]+[.][0-9]+)[^0-9]?/) { if ($1 >= 4.6) { $oldBehavior = 0; last; } } } } close(DETECT_XCODE); # If --override-compiler is explicitly requested, resort to the old # behavior regardless of Xcode version. if ($Options{OverrideCompiler}) { $oldBehavior = 1; } if ($oldBehavior == 0) { my $OutputDir = $EnvVars->{"OUTPUT_DIR"}; my $CLANG = $EnvVars->{"CLANG"}; my $OtherFlags = $EnvVars->{"CCC_ANALYZER_ANALYSIS"}; push @$Args, "RUN_CLANG_STATIC_ANALYZER=YES", "CLANG_ANALYZER_OUTPUT=plist-html", "CLANG_ANALYZER_EXEC=$CLANG", "CLANG_ANALYZER_OUTPUT_DIR=$OutputDir", "CLANG_ANALYZER_OTHER_FLAGS=$OtherFlags"; return (system(@$Args) >> 8); } # Default to old behavior where we insert a bogus compiler. SetEnv($EnvVars); # Check if using iPhone SDK 3.0 (simulator). If so the compiler being # used should be gcc-4.2. if (!defined $ENV{"CCC_CC"}) { for (my $i = 0 ; $i < scalar(@$Args); ++$i) { if ($Args->[$i] eq "-sdk" && $i + 1 < scalar(@$Args)) { if (@$Args[$i+1] =~ /^iphonesimulator3/) { $ENV{"CCC_CC"} = "gcc-4.2"; $ENV{"CCC_CXX"} = "g++-4.2"; } } } } # Disable PCH files until clang supports them. AddIfNotPresent($Args,"GCC_PRECOMPILE_PREFIX_HEADER=NO"); # When 'CC' is set, xcodebuild uses it to do all linking, even if we are # linking C++ object files. Set 'LDPLUSPLUS' so that xcodebuild uses 'g++' # (via c++-analyzer) when linking such files. $ENV{"LDPLUSPLUS"} = $CXXAnalyzer; return (system(@$Args) >> 8); } sub RunBuildCommand { my $Args = shift; my $IgnoreErrors = shift; my $KeepCC = shift; my $Cmd = $Args->[0]; my $CCAnalyzer = shift; my $CXXAnalyzer = shift; my $EnvVars = shift; if ($Cmd =~ /\bxcodebuild$/) { return RunXcodebuild($Args, $IgnoreErrors, $CCAnalyzer, $CXXAnalyzer, $EnvVars); } # Setup the environment. SetEnv($EnvVars); if ($Cmd =~ /(.*\/?gcc[^\/]*$)/ or $Cmd =~ /(.*\/?cc[^\/]*$)/ or $Cmd =~ /(.*\/?llvm-gcc[^\/]*$)/ or $Cmd =~ /(.*\/?clang$)/ or $Cmd =~ /(.*\/?ccc-analyzer[^\/]*$)/) { if (!($Cmd =~ /ccc-analyzer/) and !defined $ENV{"CCC_CC"}) { $ENV{"CCC_CC"} = $1; } shift @$Args; unshift @$Args, $CCAnalyzer; } elsif ($Cmd =~ /(.*\/?g\+\+[^\/]*$)/ or $Cmd =~ /(.*\/?c\+\+[^\/]*$)/ or $Cmd =~ /(.*\/?llvm-g\+\+[^\/]*$)/ or $Cmd =~ /(.*\/?clang\+\+$)/ or $Cmd =~ /(.*\/?c\+\+-analyzer[^\/]*$)/) { if (!($Cmd =~ /c\+\+-analyzer/) and !defined $ENV{"CCC_CXX"}) { $ENV{"CCC_CXX"} = $1; } shift @$Args; unshift @$Args, $CXXAnalyzer; } elsif ($Cmd eq "make" or $Cmd eq "gmake" or $Cmd eq "mingw32-make") { if (!$KeepCC) { AddIfNotPresent($Args, "CC=$CCAnalyzer"); AddIfNotPresent($Args, "CXX=$CXXAnalyzer"); } if ($IgnoreErrors) { AddIfNotPresent($Args,"-k"); AddIfNotPresent($Args,"-i"); } } return (system(@$Args) >> 8); } ##----------------------------------------------------------------------------## # DisplayHelp - Utility function to display all help options. ##----------------------------------------------------------------------------## sub DisplayHelp { my $ArgClangNotFoundErrMsg = shift; print < [build options] ENDTEXT if (defined $BuildName) { print "ANALYZER BUILD: $BuildName ($BuildDate)\n\n"; } print < Specifies the output directory for analyzer reports. Subdirectories will be created as needed to represent separate "runs" of the analyzer. If this option is not specified, a directory is created in /tmp (TMPDIR on Mac OS X) to store the reports. -h --help Display this message. -k --keep-going Add a "keep on going" option to the specified build command. This option currently supports make and xcodebuild. This is a convenience option; one can specify this behavior directly using build options. --keep-cc Do not override CC and CXX make variables. Useful when running make in autoconf-based (and similar) projects where configure can add extra flags to those variables. --html-title [title] --html-title=[title] Specify the title used on generated HTML pages. If not specified, a default title will be used. --show-description Display the description of defects in the list -plist By default the output of scan-build is a set of HTML files. This option outputs the results as a set of .plist files. -plist-html By default the output of scan-build is a set of HTML files. This option outputs the results as a set of HTML and .plist files. --status-bugs By default, the exit status of scan-build is the same as the executed build command. Specifying this option causes the exit status of scan-build to be 1 - if it found potential bugs and 0 otherwise. + if it found potential bugs and the exit status of the build itself otherwise. --use-cc [compiler path] --use-cc=[compiler path] scan-build analyzes a project by interposing a "fake compiler", which executes a real compiler for compilation and the static analyzer for analysis. Because of the current implementation of interposition, scan-build does not know what compiler your project normally uses. Instead, it simply overrides the CC environment variable, and guesses your default compiler. In the future, this interposition mechanism to be improved, but if you need scan-build to use a specific compiler for *compilation* then you can use this option to specify a path to that compiler. If the given compiler is a cross compiler, you may also need to provide --analyzer-target option to properly analyze the source code because static analyzer runs as if the code is compiled for the host machine by default. --use-c++ [compiler path] --use-c++=[compiler path] This is the same as "--use-cc" but for C++ code. --analyzer-target [target triple name for analysis] --analyzer-target=[target triple name for analysis] This provides target triple information to clang static analyzer. It only changes the target for analysis but doesn't change the target of a real compiler given by --use-cc and --use-c++ options. -v Enable verbose output from scan-build. A second and third '-v' increases verbosity. -V --view View analysis results in a web browser when the build completes. ADVANCED OPTIONS: -no-failure-reports Do not create a 'failures' subdirectory that includes analyzer crash reports and preprocessed source files. -stats Generates visitation statistics for the project being analyzed. -maxloop Specify the number of times a block can be visited before giving up. Default is 4. Increase for more comprehensive coverage at a cost of speed. -internal-stats Generate internal analyzer statistics. --use-analyzer [Xcode|path to clang] --use-analyzer=[Xcode|path to clang] scan-build uses the 'clang' executable relative to itself for static analysis. One can override this behavior with this option by using the 'clang' packaged with Xcode (on OS X) or from the PATH. --keep-empty Don't remove the build results directory even if no issues were reported. --override-compiler Always resort to the ccc-analyzer even when better interposition methods are available. -analyzer-config Provide options to pass through to the analyzer's -analyzer-config flag. Several options are separated with comma: 'key1=val1,key2=val2' Available options: * stable-report-filename=true or false (default) Switch the page naming to: report---.html instead of report-XXXXXX.html CONTROLLING CHECKERS: A default group of checkers are always run unless explicitly disabled. Checkers may be enabled/disabled using the following options: -enable-checker [checker name] -disable-checker [checker name] LOADING CHECKERS: Loading external checkers using the clang plugin interface: -load-plugin [plugin library] ENDTEXT if (defined $Clang && -x $Clang) { # Query clang for list of checkers that are enabled. # create a list to load the plugins via the 'Xclang' command line # argument my @PluginLoadCommandline_xclang; foreach my $param ( @{$Options{PluginsToLoad}} ) { push ( @PluginLoadCommandline_xclang, "-Xclang" ); push ( @PluginLoadCommandline_xclang, "-load" ); push ( @PluginLoadCommandline_xclang, "-Xclang" ); push ( @PluginLoadCommandline_xclang, $param ); } my %EnabledCheckers; foreach my $lang ("c", "objective-c", "objective-c++", "c++") { my $ExecLine = join(' ', qq/"$Clang"/, @PluginLoadCommandline_xclang, "--analyze", "-x", $lang, "-", "-###", "2>&1", "|"); open(PS, $ExecLine); while () { foreach my $val (split /\s+/) { $val =~ s/\"//g; if ($val =~ /-analyzer-checker\=([^\s]+)/) { $EnabledCheckers{$1} = 1; } } } } # Query clang for complete list of checkers. my @PluginLoadCommandline; foreach my $param ( @{$Options{PluginsToLoad}} ) { push ( @PluginLoadCommandline, "-load" ); push ( @PluginLoadCommandline, $param ); } my $ExecLine = join(' ', qq/"$Clang"/, "-cc1", @PluginLoadCommandline, "-analyzer-checker-help", "2>&1", "|"); open(PS, $ExecLine); my $foundCheckers = 0; while () { if (/CHECKERS:/) { $foundCheckers = 1; last; } } if (!$foundCheckers) { print " *** Could not query Clang for the list of available checkers."; } else { print("\nAVAILABLE CHECKERS:\n\n"); my $skip = 0; while() { if (/experimental/) { $skip = 1; next; } if ($skip) { next if (!/^\s\s[^\s]/); $skip = 0; } s/^\s\s//; if (/^([^\s]+)/) { # Is the checker enabled? my $checker = $1; my $enabled = 0; my $aggregate = ""; foreach my $domain (split /\./, $checker) { $aggregate .= $domain; if ($EnabledCheckers{$aggregate}) { $enabled =1; last; } # append a dot, if an additional domain is added in the next iteration $aggregate .= "."; } if ($enabled) { print " + "; } else { print " "; } } else { print " "; } print $_; } print "\nNOTE: \"+\" indicates that an analysis is enabled by default.\n"; } close PS; } else { print " *** Could not query Clang for the list of available checkers.\n"; if (defined $ArgClangNotFoundErrMsg) { print " *** Reason: $ArgClangNotFoundErrMsg\n"; } } print </>/g; return $tmp; } ##----------------------------------------------------------------------------## # ShellEscape - backslash escape characters that are special to the shell ##----------------------------------------------------------------------------## sub ShellEscape { # copy argument to new variable so we don't clobber the original my $arg = shift || ''; if ($arg =~ /["\s]/) { return "'" . $arg . "'"; } return $arg; } ##----------------------------------------------------------------------------## # FindClang - searches for 'clang' executable. ##----------------------------------------------------------------------------## sub FindClang { if (!defined $Options{AnalyzerDiscoveryMethod}) { $Clang = Cwd::realpath("$RealBin/bin/clang") if (-f "$RealBin/bin/clang"); if (!defined $Clang || ! -x $Clang) { $Clang = Cwd::realpath("$RealBin/clang") if (-f "$RealBin/clang"); } if (!defined $Clang || ! -x $Clang) { return "error: Cannot find an executable 'clang' relative to" . " scan-build. Consider using --use-analyzer to pick a version of" . " 'clang' to use for static analysis.\n"; } } else { if ($Options{AnalyzerDiscoveryMethod} =~ /^[Xx]code$/) { my $xcrun = `which xcrun`; chomp $xcrun; if ($xcrun eq "") { return "Cannot find 'xcrun' to find 'clang' for analysis.\n"; } $Clang = `$xcrun -toolchain XcodeDefault -find clang`; chomp $Clang; if ($Clang eq "") { return "No 'clang' executable found by 'xcrun'\n"; } } else { $Clang = $Options{AnalyzerDiscoveryMethod}; if (!defined $Clang or not -x $Clang) { return "Cannot find an executable clang at '$Options{AnalyzerDiscoveryMethod}'\n"; } } } return undef; } ##----------------------------------------------------------------------------## # Process command-line arguments. ##----------------------------------------------------------------------------## my $RequestDisplayHelp = 0; my $ForceDisplayHelp = 0; sub ProcessArgs { my $Args = shift; my $NumArgs = 0; while (@$Args) { $NumArgs++; # Scan for options we recognize. my $arg = $Args->[0]; if ($arg eq "-h" or $arg eq "--help") { $RequestDisplayHelp = 1; shift @$Args; next; } if ($arg eq '-analyze-headers') { shift @$Args; $Options{AnalyzeHeaders} = 1; next; } if ($arg eq "-o") { shift @$Args; if (!@$Args) { DieDiag("'-o' option requires a target directory name.\n"); } # Construct an absolute path. Uses the current working directory # as a base if the original path was not absolute. my $OutDir = shift @$Args; mkpath($OutDir) unless (-e $OutDir); # abs_path wants existing dir $Options{OutputDir} = abs_path($OutDir); next; } if ($arg =~ /^--html-title(=(.+))?$/) { shift @$Args; if (!defined $2 || $2 eq '') { if (!@$Args) { DieDiag("'--html-title' option requires a string.\n"); } $Options{HtmlTitle} = shift @$Args; } else { $Options{HtmlTitle} = $2; } next; } if ($arg eq "-k" or $arg eq "--keep-going") { shift @$Args; $Options{IgnoreErrors} = 1; next; } if ($arg eq "--keep-cc") { shift @$Args; $Options{KeepCC} = 1; next; } if ($arg =~ /^--use-cc(=(.+))?$/) { shift @$Args; my $cc; if (!defined $2 || $2 eq "") { if (!@$Args) { DieDiag("'--use-cc' option requires a compiler executable name.\n"); } $cc = shift @$Args; } else { $cc = $2; } $Options{UseCC} = $cc; next; } if ($arg =~ /^--use-c\+\+(=(.+))?$/) { shift @$Args; my $cxx; if (!defined $2 || $2 eq "") { if (!@$Args) { DieDiag("'--use-c++' option requires a compiler executable name.\n"); } $cxx = shift @$Args; } else { $cxx = $2; } $Options{UseCXX} = $cxx; next; } if ($arg =~ /^--analyzer-target(=(.+))?$/) { shift @ARGV; my $AnalyzerTarget; if (!defined $2 || $2 eq "") { if (!@ARGV) { DieDiag("'--analyzer-target' option requires a target triple name.\n"); } $AnalyzerTarget = shift @ARGV; } else { $AnalyzerTarget = $2; } $Options{AnalyzerTarget} = $AnalyzerTarget; next; } if ($arg eq "-v") { shift @$Args; $Options{Verbose}++; next; } if ($arg eq "-V" or $arg eq "--view") { shift @$Args; $Options{ViewResults} = 1; next; } if ($arg eq "--status-bugs") { shift @$Args; $Options{ExitStatusFoundBugs} = 1; next; } if ($arg eq "--show-description") { shift @$Args; $Options{ShowDescription} = 1; next; } if ($arg eq "-store") { shift @$Args; $Options{StoreModel} = shift @$Args; next; } if ($arg eq "-constraints") { shift @$Args; $Options{ConstraintsModel} = shift @$Args; next; } if ($arg eq "-internal-stats") { shift @$Args; $Options{InternalStats} = 1; next; } if ($arg eq "-plist") { shift @$Args; $Options{OutputFormat} = "plist"; next; } if ($arg eq "-plist-html") { shift @$Args; $Options{OutputFormat} = "plist-html"; next; } if ($arg eq "-analyzer-config") { shift @$Args; push @{$Options{ConfigOptions}}, shift @$Args; next; } if ($arg eq "-no-failure-reports") { shift @$Args; $Options{ReportFailures} = 0; next; } if ($arg eq "-stats") { shift @$Args; $Options{AnalyzerStats} = 1; next; } if ($arg eq "-maxloop") { shift @$Args; $Options{MaxLoop} = shift @$Args; next; } if ($arg eq "-enable-checker") { shift @$Args; my $Checker = shift @$Args; # Store $NumArgs to preserve the order the checkers were enabled. $Options{EnableCheckers}{$Checker} = $NumArgs; delete $Options{DisableCheckers}{$Checker}; next; } if ($arg eq "-disable-checker") { shift @$Args; my $Checker = shift @$Args; # Store $NumArgs to preserve the order the checkers were disabled. $Options{DisableCheckers}{$Checker} = $NumArgs; delete $Options{EnableCheckers}{$Checker}; next; } if ($arg eq "-load-plugin") { shift @$Args; push @{$Options{PluginsToLoad}}, shift @$Args; next; } if ($arg eq "--use-analyzer") { shift @$Args; $Options{AnalyzerDiscoveryMethod} = shift @$Args; next; } if ($arg =~ /^--use-analyzer=(.+)$/) { shift @$Args; $Options{AnalyzerDiscoveryMethod} = $1; next; } if ($arg eq "--keep-empty") { shift @$Args; $Options{KeepEmpty} = 1; next; } if ($arg eq "--override-compiler") { shift @$Args; $Options{OverrideCompiler} = 1; next; } if ($arg eq "--force-analyze-debug-code") { shift @$Args; $Options{ForceAnalyzeDebugCode} = 1; next; } DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/); $NumArgs--; last; } return $NumArgs; } if (!@ARGV) { $ForceDisplayHelp = 1 } ProcessArgs(\@ARGV); # All arguments are now shifted from @ARGV. The rest is a build command, if any. if (!@ARGV and !$RequestDisplayHelp) { ErrorDiag("No build command specified.\n\n"); $ForceDisplayHelp = 1; } my $ClangNotFoundErrMsg = FindClang(); if ($ForceDisplayHelp || $RequestDisplayHelp) { DisplayHelp($ClangNotFoundErrMsg); exit $ForceDisplayHelp; } DieDiag($ClangNotFoundErrMsg) if (defined $ClangNotFoundErrMsg); $ClangCXX = $Clang; if ($Clang !~ /\+\+(\.exe)?$/) { # If $Clang holds the name of the clang++ executable then we leave # $ClangCXX and $Clang equal, otherwise construct the name of the clang++ # executable from the clang executable name. # Determine operating system under which this copy of Perl was built. my $IsWinBuild = ($^O =~/msys|cygwin|MSWin32/); if($IsWinBuild) { $ClangCXX =~ s/.exe$/++.exe/; } else { $ClangCXX =~ s/\-\d+\.\d+$//; $ClangCXX .= "++"; } } # Make sure to use "" to handle paths with spaces. $ClangVersion = HtmlEscape(`"$Clang" --version`); # Determine where results go. $CmdArgs = HtmlEscape(join(' ', map(ShellEscape($_), @ARGV))); # Determine the output directory for the HTML reports. my $BaseDir = $Options{OutputDir}; $Options{OutputDir} = GetHTMLRunDir($Options{OutputDir}); # Determine the location of ccc-analyzer. my $AbsRealBin = Cwd::realpath($RealBin); my $Cmd = "$AbsRealBin/../libexec/ccc-analyzer"; my $CmdCXX = "$AbsRealBin/../libexec/c++-analyzer"; # Portability: use less strict but portable check -e (file exists) instead of # non-portable -x (file is executable). On some windows ports -x just checks # file extension to determine if a file is executable (see Perl language # reference, perlport) if (!defined $Cmd || ! -e $Cmd) { $Cmd = "$AbsRealBin/ccc-analyzer"; DieDiag("'ccc-analyzer' does not exist at '$Cmd'\n") if(! -e $Cmd); } if (!defined $CmdCXX || ! -e $CmdCXX) { $CmdCXX = "$AbsRealBin/c++-analyzer"; DieDiag("'c++-analyzer' does not exist at '$CmdCXX'\n") if(! -e $CmdCXX); } Diag("Using '$Clang' for static analysis\n"); SetHtmlEnv(\@ARGV, $Options{OutputDir}); my @AnalysesToRun; foreach (sort { $Options{EnableCheckers}{$a} <=> $Options{EnableCheckers}{$b} } keys %{$Options{EnableCheckers}}) { # Push checkers in order they were enabled. push @AnalysesToRun, "-analyzer-checker", $_; } foreach (sort { $Options{DisableCheckers}{$a} <=> $Options{DisableCheckers}{$b} } keys %{$Options{DisableCheckers}}) { # Push checkers in order they were disabled. push @AnalysesToRun, "-analyzer-disable-checker", $_; } if ($Options{AnalyzeHeaders}) { push @AnalysesToRun, "-analyzer-opt-analyze-headers"; } if ($Options{AnalyzerStats}) { push @AnalysesToRun, '-analyzer-checker=debug.Stats'; } if ($Options{MaxLoop} > 0) { push @AnalysesToRun, "-analyzer-max-loop $Options{MaxLoop}"; } # Delay setting up other environment variables in case we can do true # interposition. my $CCC_ANALYZER_ANALYSIS = join ' ', @AnalysesToRun; my $CCC_ANALYZER_PLUGINS = join ' ', map { "-load ".$_ } @{$Options{PluginsToLoad}}; my $CCC_ANALYZER_CONFIG = join ' ', map { "-analyzer-config ".$_ } @{$Options{ConfigOptions}}; my %EnvVars = ( 'CC' => $Cmd, 'CXX' => $CmdCXX, 'CLANG' => $Clang, 'CLANG_CXX' => $ClangCXX, 'VERBOSE' => $Options{Verbose}, 'CCC_ANALYZER_ANALYSIS' => $CCC_ANALYZER_ANALYSIS, 'CCC_ANALYZER_PLUGINS' => $CCC_ANALYZER_PLUGINS, 'CCC_ANALYZER_CONFIG' => $CCC_ANALYZER_CONFIG, 'OUTPUT_DIR' => $Options{OutputDir}, 'CCC_CC' => $Options{UseCC}, 'CCC_CXX' => $Options{UseCXX}, 'CCC_REPORT_FAILURES' => $Options{ReportFailures}, 'CCC_ANALYZER_STORE_MODEL' => $Options{StoreModel}, 'CCC_ANALYZER_CONSTRAINTS_MODEL' => $Options{ConstraintsModel}, 'CCC_ANALYZER_INTERNAL_STATS' => $Options{InternalStats}, 'CCC_ANALYZER_OUTPUT_FORMAT' => $Options{OutputFormat}, 'CLANG_ANALYZER_TARGET' => $Options{AnalyzerTarget}, 'CCC_ANALYZER_FORCE_ANALYZE_DEBUG_CODE' => $Options{ForceAnalyzeDebugCode} ); # Run the build. my $ExitStatus = RunBuildCommand(\@ARGV, $Options{IgnoreErrors}, $Options{KeepCC}, $Cmd, $CmdCXX, \%EnvVars); if (defined $Options{OutputFormat}) { if ($Options{OutputFormat} =~ /plist/) { Diag "Analysis run complete.\n"; Diag "Analysis results (plist files) deposited in '$Options{OutputDir}'\n"; } if ($Options{OutputFormat} =~ /html/) { # Postprocess the HTML directory. my $NumBugs = Postprocess($Options{OutputDir}, $BaseDir, $Options{AnalyzerStats}, $Options{KeepEmpty}); if ($Options{ViewResults} and -r "$Options{OutputDir}/index.html") { Diag "Analysis run complete.\n"; Diag "Viewing analysis results in '$Options{OutputDir}' using scan-view.\n"; my $ScanView = Cwd::realpath("$RealBin/scan-view"); if (! -x $ScanView) { $ScanView = "scan-view"; } if (! -x $ScanView) { $ScanView = Cwd::realpath("$RealBin/../../scan-view/bin/scan-view"); } exec $ScanView, "$Options{OutputDir}"; } if ($Options{ExitStatusFoundBugs}) { exit 1 if ($NumBugs > 0); - exit 0; + exit $ExitStatus; } } } exit $ExitStatus;