xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/CodeGen/PatternInit.cpp (revision 7330f729ccf0bd976a06f95fad452fe774fc7fd1)
1*7330f729Sjoerg //===--- PatternInit.cpp - Pattern Initialization -------------------------===//
2*7330f729Sjoerg //
3*7330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*7330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
5*7330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*7330f729Sjoerg //
7*7330f729Sjoerg //===----------------------------------------------------------------------===//
8*7330f729Sjoerg 
9*7330f729Sjoerg #include "PatternInit.h"
10*7330f729Sjoerg #include "CodeGenModule.h"
11*7330f729Sjoerg #include "llvm/IR/Constant.h"
12*7330f729Sjoerg #include "llvm/IR/Type.h"
13*7330f729Sjoerg 
14*7330f729Sjoerg llvm::Constant *clang::CodeGen::initializationPatternFor(CodeGenModule &CGM,
15*7330f729Sjoerg                                                          llvm::Type *Ty) {
16*7330f729Sjoerg   // The following value is a guaranteed unmappable pointer value and has a
17*7330f729Sjoerg   // repeated byte-pattern which makes it easier to synthesize. We use it for
18*7330f729Sjoerg   // pointers as well as integers so that aggregates are likely to be
19*7330f729Sjoerg   // initialized with this repeated value.
20*7330f729Sjoerg   // For 32-bit platforms it's a bit trickier because, across systems, only the
21*7330f729Sjoerg   // zero page can reasonably be expected to be unmapped. We use max 0xFFFFFFFF
22*7330f729Sjoerg   // assuming that memory access will overlap into zero page.
23*7330f729Sjoerg   const uint64_t IntValue =
24*7330f729Sjoerg       CGM.getContext().getTargetInfo().getMaxPointerWidth() < 64
25*7330f729Sjoerg           ? 0xFFFFFFFFFFFFFFFFull
26*7330f729Sjoerg           : 0xAAAAAAAAAAAAAAAAull;
27*7330f729Sjoerg   // Floating-point values are initialized as NaNs because they propagate. Using
28*7330f729Sjoerg   // a repeated byte pattern means that it will be easier to initialize
29*7330f729Sjoerg   // all-floating-point aggregates and arrays with memset. Further, aggregates
30*7330f729Sjoerg   // which mix integral and a few floats might also initialize with memset
31*7330f729Sjoerg   // followed by a handful of stores for the floats. Using fairly unique NaNs
32*7330f729Sjoerg   // also means they'll be easier to distinguish in a crash.
33*7330f729Sjoerg   constexpr bool NegativeNaN = true;
34*7330f729Sjoerg   constexpr uint64_t NaNPayload = 0xFFFFFFFFFFFFFFFFull;
35*7330f729Sjoerg   if (Ty->isIntOrIntVectorTy()) {
36*7330f729Sjoerg     unsigned BitWidth = cast<llvm::IntegerType>(
37*7330f729Sjoerg                             Ty->isVectorTy() ? Ty->getVectorElementType() : Ty)
38*7330f729Sjoerg                             ->getBitWidth();
39*7330f729Sjoerg     if (BitWidth <= 64)
40*7330f729Sjoerg       return llvm::ConstantInt::get(Ty, IntValue);
41*7330f729Sjoerg     return llvm::ConstantInt::get(
42*7330f729Sjoerg         Ty, llvm::APInt::getSplat(BitWidth, llvm::APInt(64, IntValue)));
43*7330f729Sjoerg   }
44*7330f729Sjoerg   if (Ty->isPtrOrPtrVectorTy()) {
45*7330f729Sjoerg     auto *PtrTy = cast<llvm::PointerType>(
46*7330f729Sjoerg         Ty->isVectorTy() ? Ty->getVectorElementType() : Ty);
47*7330f729Sjoerg     unsigned PtrWidth = CGM.getContext().getTargetInfo().getPointerWidth(
48*7330f729Sjoerg         PtrTy->getAddressSpace());
49*7330f729Sjoerg     if (PtrWidth > 64)
50*7330f729Sjoerg       llvm_unreachable("pattern initialization of unsupported pointer width");
51*7330f729Sjoerg     llvm::Type *IntTy = llvm::IntegerType::get(CGM.getLLVMContext(), PtrWidth);
52*7330f729Sjoerg     auto *Int = llvm::ConstantInt::get(IntTy, IntValue);
53*7330f729Sjoerg     return llvm::ConstantExpr::getIntToPtr(Int, PtrTy);
54*7330f729Sjoerg   }
55*7330f729Sjoerg   if (Ty->isFPOrFPVectorTy()) {
56*7330f729Sjoerg     unsigned BitWidth = llvm::APFloat::semanticsSizeInBits(
57*7330f729Sjoerg         (Ty->isVectorTy() ? Ty->getVectorElementType() : Ty)
58*7330f729Sjoerg             ->getFltSemantics());
59*7330f729Sjoerg     llvm::APInt Payload(64, NaNPayload);
60*7330f729Sjoerg     if (BitWidth >= 64)
61*7330f729Sjoerg       Payload = llvm::APInt::getSplat(BitWidth, Payload);
62*7330f729Sjoerg     return llvm::ConstantFP::getQNaN(Ty, NegativeNaN, &Payload);
63*7330f729Sjoerg   }
64*7330f729Sjoerg   if (Ty->isArrayTy()) {
65*7330f729Sjoerg     // Note: this doesn't touch tail padding (at the end of an object, before
66*7330f729Sjoerg     // the next array object). It is instead handled by replaceUndef.
67*7330f729Sjoerg     auto *ArrTy = cast<llvm::ArrayType>(Ty);
68*7330f729Sjoerg     llvm::SmallVector<llvm::Constant *, 8> Element(
69*7330f729Sjoerg         ArrTy->getNumElements(),
70*7330f729Sjoerg         initializationPatternFor(CGM, ArrTy->getElementType()));
71*7330f729Sjoerg     return llvm::ConstantArray::get(ArrTy, Element);
72*7330f729Sjoerg   }
73*7330f729Sjoerg 
74*7330f729Sjoerg   // Note: this doesn't touch struct padding. It will initialize as much union
75*7330f729Sjoerg   // padding as is required for the largest type in the union. Padding is
76*7330f729Sjoerg   // instead handled by replaceUndef. Stores to structs with volatile members
77*7330f729Sjoerg   // don't have a volatile qualifier when initialized according to C++. This is
78*7330f729Sjoerg   // fine because stack-based volatiles don't really have volatile semantics
79*7330f729Sjoerg   // anyways, and the initialization shouldn't be observable.
80*7330f729Sjoerg   auto *StructTy = cast<llvm::StructType>(Ty);
81*7330f729Sjoerg   llvm::SmallVector<llvm::Constant *, 8> Struct(StructTy->getNumElements());
82*7330f729Sjoerg   for (unsigned El = 0; El != Struct.size(); ++El)
83*7330f729Sjoerg     Struct[El] = initializationPatternFor(CGM, StructTy->getElementType(El));
84*7330f729Sjoerg   return llvm::ConstantStruct::get(StructTy, Struct);
85*7330f729Sjoerg }
86