blob: 56941b2aa51e7a02b1f353393317faf84021a58b [file] [edit]
//====- LowerToLLVM.h- Lowering from CIR to LLVM --------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares an interface for converting CIR modules to LLVM IR.
//
//===----------------------------------------------------------------------===//
#ifndef CLANG_CIR_LOWERTOLLVM_H
#define CLANG_CIR_LOWERTOLLVM_H
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Transforms/DialectConversion.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Interfaces/CIROpInterfaces.h"
namespace cir {
namespace direct {
struct LLVMBlockAddressInfo;
/// Convert a CIR attribute to an LLVM attribute. May use the datalayout for
/// lowering attributes to-be-stored in memory. When the attribute may contain
/// block address attributes, `blockInfoAddr` is used to resolve them.
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, mlir::Attribute attr,
mlir::ConversionPatternRewriter &rewriter,
mlir::SymbolTableCollection &symbolTables,
const mlir::TypeConverter *converter,
LLVMBlockAddressInfo *blockInfoAddr = nullptr);
mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage);
struct LLVMBlockAddressInfo {
// Get the next tag index
uint32_t getTagIndex() { return blockTagOpIndex++; }
void mapBlockTag(cir::BlockAddrInfoAttr info, mlir::LLVM::BlockTagOp tagOp) {
[[maybe_unused]] auto result = blockInfoToTagOp.try_emplace(info, tagOp);
assert(result.second &&
"attempting to map a BlockTag operation that is already mapped");
}
// Lookup a BlockTagOp, may return nullptr if not yet registered.
mlir::LLVM::BlockTagOp lookupBlockTag(cir::BlockAddrInfoAttr info) const {
return blockInfoToTagOp.lookup(info);
}
// Record an unresolved BlockAddressOp that needs patching later.
void addUnresolvedBlockAddress(mlir::LLVM::BlockAddressOp op,
cir::BlockAddrInfoAttr info) {
unresolvedBlockAddressOp.try_emplace(op, info);
}
void clearUnresolvedMap() { unresolvedBlockAddressOp.clear(); }
llvm::DenseMap<mlir::LLVM::BlockAddressOp, cir::BlockAddrInfoAttr> &
getUnresolvedBlockAddress() {
return unresolvedBlockAddressOp;
}
private:
// Maps a (function name, label name) pair to the corresponding BlockTagOp.
// Used to resolve CIR LabelOps into their LLVM BlockTagOp.
llvm::DenseMap<cir::BlockAddrInfoAttr, mlir::LLVM::BlockTagOp>
blockInfoToTagOp;
// Tracks BlockAddressOps that could not yet be fully resolved because
// their BlockTagOp was not available at the time of lowering. The map
// stores the unresolved BlockAddressOp along with its (function name, label
// name) pair so it can be patched later.
llvm::DenseMap<mlir::LLVM::BlockAddressOp, cir::BlockAddrInfoAttr>
unresolvedBlockAddressOp;
int32_t blockTagOpIndex;
};
mlir::LogicalResult lowerToConstrainedFPIntrinsic(
mlir::Operation *op, mlir::ValueRange operands, cir::FenvAttr fenv,
mlir::Type llvmResTy, mlir::ConversionPatternRewriter &rewriter,
llvm::StringRef constrainedMnemonic, bool hasRoundingMode,
mlir::LLVM::FastmathFlags fastmathFlags = {});
template <typename LLVMOp>
mlir::LogicalResult lowerConstrainableFPOp(
mlir::Operation *op, mlir::ValueRange operands, cir::FenvAttr fenv,
const mlir::TypeConverter &typeConverter,
mlir::ConversionPatternRewriter &rewriter,
llvm::StringRef constrainedMnemonic, bool hasRoundingMode);
#define GET_LLVM_LOWERING_PATTERNS
#include "clang/CIR/Dialect/IR/CIRLowering.inc"
#undef GET_LLVM_LOWERING_PATTERNS
} // namespace direct
} // namespace cir
#endif // CLANG_CIR_LOWERTOLLVM_H