mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
170 lines
5.5 KiB
C++
170 lines
5.5 KiB
C++
//===--- ConstantBuilder.h - IR generation for constant structs -*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements IR generation of constant packed LLVM structs.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/ABI/MetadataValues.h"
|
|
#include "llvm/IR/Constants.h"
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
#include "llvm/IR/GlobalVariable.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "clang/CodeGen/ConstantInitBuilder.h"
|
|
|
|
#include "Address.h"
|
|
#include "IRGenModule.h"
|
|
#include "IRGenFunction.h"
|
|
|
|
namespace clang {
|
|
class PointerAuthSchema;
|
|
}
|
|
|
|
namespace swift {
|
|
namespace irgen {
|
|
class PointerAuthEntity;
|
|
|
|
class ConstantAggregateBuilderBase;
|
|
class ConstantStructBuilder;
|
|
class ConstantArrayBuilder;
|
|
class ConstantInitBuilder;
|
|
|
|
struct ConstantInitBuilderTraits {
|
|
using InitBuilder = ConstantInitBuilder;
|
|
using AggregateBuilderBase = ConstantAggregateBuilderBase;
|
|
using ArrayBuilder = ConstantArrayBuilder;
|
|
using StructBuilder = ConstantStructBuilder;
|
|
};
|
|
|
|
/// A Swift customization of Clang's ConstantInitBuilder.
|
|
class ConstantInitBuilder
|
|
: public clang::CodeGen::ConstantInitBuilderTemplateBase<
|
|
ConstantInitBuilderTraits> {
|
|
public:
|
|
IRGenModule &IGM;
|
|
ConstantInitBuilder(IRGenModule &IGM)
|
|
: ConstantInitBuilderTemplateBase(IGM.getClangCGM()),
|
|
IGM(IGM) {}
|
|
};
|
|
|
|
class ConstantAggregateBuilderBase
|
|
: public clang::CodeGen::ConstantAggregateBuilderBase {
|
|
using super = clang::CodeGen::ConstantAggregateBuilderBase;
|
|
protected:
|
|
ConstantAggregateBuilderBase(ConstantInitBuilder &builder,
|
|
ConstantAggregateBuilderBase *parent)
|
|
: super(builder, parent) {}
|
|
|
|
ConstantInitBuilder &getBuilder() const {
|
|
return static_cast<ConstantInitBuilder&>(Builder);
|
|
}
|
|
IRGenModule &IGM() const { return getBuilder().IGM; }
|
|
|
|
public:
|
|
void addInt16(uint16_t value) {
|
|
addInt(IGM().Int16Ty, value);
|
|
}
|
|
|
|
void addInt32(uint32_t value) {
|
|
addInt(IGM().Int32Ty, value);
|
|
}
|
|
|
|
void addRelativeAddressOrNull(llvm::Constant *target) {
|
|
if (target) {
|
|
addRelativeAddress(target);
|
|
} else {
|
|
addInt(IGM().RelativeAddressTy, 0);
|
|
}
|
|
}
|
|
|
|
void addRelativeAddress(llvm::Constant *target) {
|
|
assert(!isa<llvm::ConstantPointerNull>(target));
|
|
addRelativeOffset(IGM().RelativeAddressTy, target);
|
|
}
|
|
|
|
/// Add a tagged relative reference to the given address. The direct
|
|
/// target must be defined within the current image, but it might be
|
|
/// a "GOT-equivalent", i.e. a pointer to an external object; if so,
|
|
/// set the low bit of the offset to indicate that this is true.
|
|
void addRelativeAddress(ConstantReference reference) {
|
|
addTaggedRelativeOffset(IGM().RelativeAddressTy,
|
|
reference.getValue(),
|
|
unsigned(reference.isIndirect()));
|
|
}
|
|
|
|
/// Add an indirect relative reference to the given address.
|
|
/// The target must be a "GOT-equivalent", i.e. a pointer to an
|
|
/// external object.
|
|
void addIndirectRelativeAddress(ConstantReference reference) {
|
|
assert(reference.isIndirect());
|
|
addRelativeOffset(IGM().RelativeAddressTy,
|
|
reference.getValue());
|
|
}
|
|
|
|
Size getNextOffsetFromGlobal() const {
|
|
return Size(super::getNextOffsetFromGlobal().getQuantity());
|
|
}
|
|
|
|
void addAlignmentPadding(Alignment align) {
|
|
auto misalignment = getNextOffsetFromGlobal() % IGM().getPointerAlignment();
|
|
if (misalignment != Size(0))
|
|
add(llvm::ConstantAggregateZero::get(
|
|
llvm::ArrayType::get(IGM().Int8Ty,
|
|
align.getValue() - misalignment.getValue())));
|
|
}
|
|
|
|
using super::addSignedPointer;
|
|
void addSignedPointer(llvm::Constant *pointer,
|
|
const clang::PointerAuthSchema &schema,
|
|
const PointerAuthEntity &entity);
|
|
|
|
void addSignedPointer(llvm::Constant *pointer,
|
|
const clang::PointerAuthSchema &schema,
|
|
uint16_t otherDiscriminator);
|
|
};
|
|
|
|
class ConstantArrayBuilder
|
|
: public clang::CodeGen::ConstantArrayBuilderTemplateBase<
|
|
ConstantInitBuilderTraits> {
|
|
private:
|
|
llvm::Type *EltTy;
|
|
|
|
public:
|
|
ConstantArrayBuilder(InitBuilder &builder,
|
|
AggregateBuilderBase *parent,
|
|
llvm::Type *eltTy)
|
|
: ConstantArrayBuilderTemplateBase(builder, parent, eltTy), EltTy(eltTy) {}
|
|
|
|
void addAlignmentPadding(Alignment align) {
|
|
auto misalignment = getNextOffsetFromGlobal() % align;
|
|
if (misalignment == Size(0))
|
|
return;
|
|
|
|
auto eltSize = IGM().DataLayout.getTypeStoreSize(EltTy);
|
|
assert(misalignment.getValue() % eltSize == 0);
|
|
|
|
for (unsigned i = 0, n = misalignment.getValue() / eltSize; i != n; ++i)
|
|
add(llvm::Constant::getNullValue(EltTy));
|
|
}
|
|
};
|
|
|
|
class ConstantStructBuilder
|
|
: public clang::CodeGen::ConstantStructBuilderTemplateBase<
|
|
ConstantInitBuilderTraits> {
|
|
public:
|
|
template <class... As>
|
|
ConstantStructBuilder(As &&... args)
|
|
: ConstantStructBuilderTemplateBase(std::forward<As>(args)...) {}
|
|
};
|
|
|
|
} // end namespace irgen
|
|
} // end namespace swift
|