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