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