Path: blob/main/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenModule.h
213799 views
//===--- CIRGenModule.h - Per-Module state for CIR gen ----------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This is the internal per-translation-unit state used for CIR translation.9//10//===----------------------------------------------------------------------===//1112#ifndef LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H13#define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H1415#include "CIRGenBuilder.h"16#include "CIRGenCall.h"17#include "CIRGenTypeCache.h"18#include "CIRGenTypes.h"19#include "CIRGenValue.h"2021#include "clang/AST/CharUnits.h"22#include "clang/CIR/Dialect/IR/CIRDataLayout.h"23#include "clang/CIR/Dialect/IR/CIRDialect.h"2425#include "TargetInfo.h"26#include "mlir/IR/Builders.h"27#include "mlir/IR/BuiltinOps.h"28#include "mlir/IR/MLIRContext.h"29#include "clang/AST/Decl.h"30#include "clang/Basic/SourceManager.h"31#include "clang/Basic/TargetInfo.h"32#include "clang/CIR/Dialect/IR/CIROpsEnums.h"33#include "llvm/ADT/StringRef.h"34#include "llvm/TargetParser/Triple.h"3536namespace clang {37class ASTContext;38class CodeGenOptions;39class Decl;40class GlobalDecl;41class LangOptions;42class TargetInfo;43class VarDecl;4445namespace CIRGen {4647class CIRGenFunction;48class CIRGenCXXABI;4950enum ForDefinition_t : bool { NotForDefinition = false, ForDefinition = true };5152/// This class organizes the cross-function state that is used while generating53/// CIR code.54class CIRGenModule : public CIRGenTypeCache {55CIRGenModule(CIRGenModule &) = delete;56CIRGenModule &operator=(CIRGenModule &) = delete;5758public:59CIRGenModule(mlir::MLIRContext &mlirContext, clang::ASTContext &astContext,60const clang::CodeGenOptions &cgo,61clang::DiagnosticsEngine &diags);6263~CIRGenModule();6465private:66mutable std::unique_ptr<TargetCIRGenInfo> theTargetCIRGenInfo;6768CIRGenBuilderTy builder;6970/// Hold Clang AST information.71clang::ASTContext &astContext;7273const clang::LangOptions &langOpts;7475const clang::CodeGenOptions &codeGenOpts;7677/// A "module" matches a c/cpp source file: containing a list of functions.78mlir::ModuleOp theModule;7980clang::DiagnosticsEngine &diags;8182const clang::TargetInfo ⌖8384std::unique_ptr<CIRGenCXXABI> abi;8586CIRGenTypes genTypes;8788/// Per-function codegen information. Updated everytime emitCIR is called89/// for FunctionDecls's.90CIRGenFunction *curCGF = nullptr;9192public:93mlir::ModuleOp getModule() const { return theModule; }94CIRGenBuilderTy &getBuilder() { return builder; }95clang::ASTContext &getASTContext() const { return astContext; }96const clang::TargetInfo &getTarget() const { return target; }97const clang::CodeGenOptions &getCodeGenOpts() const { return codeGenOpts; }98CIRGenTypes &getTypes() { return genTypes; }99const clang::LangOptions &getLangOpts() const { return langOpts; }100101CIRGenCXXABI &getCXXABI() const { return *abi; }102mlir::MLIRContext &getMLIRContext() { return *builder.getContext(); }103104const cir::CIRDataLayout getDataLayout() const {105// FIXME(cir): instead of creating a CIRDataLayout every time, set it as an106// attribute for the CIRModule class.107return cir::CIRDataLayout(theModule);108}109110/// -------111/// Handling globals112/// -------113114mlir::Operation *lastGlobalOp = nullptr;115116llvm::DenseMap<const Decl *, cir::GlobalOp> staticLocalDeclMap;117118mlir::Operation *getGlobalValue(llvm::StringRef ref);119120cir::GlobalOp getStaticLocalDeclAddress(const VarDecl *d) {121return staticLocalDeclMap[d];122}123124void setStaticLocalDeclAddress(const VarDecl *d, cir::GlobalOp c) {125staticLocalDeclMap[d] = c;126}127128cir::GlobalOp getOrCreateStaticVarDecl(const VarDecl &d,129cir::GlobalLinkageKind linkage);130131/// If the specified mangled name is not in the module, create and return an132/// mlir::GlobalOp value133cir::GlobalOp getOrCreateCIRGlobal(llvm::StringRef mangledName, mlir::Type ty,134LangAS langAS, const VarDecl *d,135ForDefinition_t isForDefinition);136137cir::GlobalOp getOrCreateCIRGlobal(const VarDecl *d, mlir::Type ty,138ForDefinition_t isForDefinition);139140static cir::GlobalOp createGlobalOp(CIRGenModule &cgm, mlir::Location loc,141llvm::StringRef name, mlir::Type t,142mlir::Operation *insertPoint = nullptr);143144llvm::StringMap<unsigned> cgGlobalNames;145std::string getUniqueGlobalName(const std::string &baseName);146147/// Return the mlir::Value for the address of the given global variable.148/// If Ty is non-null and if the global doesn't exist, then it will be created149/// with the specified type instead of whatever the normal requested type150/// would be. If IsForDefinition is true, it is guaranteed that an actual151/// global with type Ty will be returned, not conversion of a variable with152/// the same mangled name but some other type.153mlir::Value154getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty = {},155ForDefinition_t isForDefinition = NotForDefinition);156157CharUnits computeNonVirtualBaseClassOffset(158const CXXRecordDecl *derivedClass,159llvm::iterator_range<CastExpr::path_const_iterator> path);160161/// Get the CIR attributes and calling convention to use for a particular162/// function type.163///164/// \param calleeInfo - The callee information these attributes are being165/// constructed for. If valid, the attributes applied to this decl may166/// contribute to the function attributes and calling convention.167void constructAttributeList(CIRGenCalleeInfo calleeInfo,168mlir::NamedAttrList &attrs);169170/// Return a constant array for the given string.171mlir::Attribute getConstantArrayFromStringLiteral(const StringLiteral *e);172173/// Return a global symbol reference to a constant array for the given string174/// literal.175cir::GlobalOp getGlobalForStringLiteral(const StringLiteral *s,176llvm::StringRef name = ".str");177178/// Set attributes which are common to any form of a global definition (alias,179/// Objective-C method, function, global variable).180///181/// NOTE: This should only be called for definitions.182void setCommonAttributes(GlobalDecl gd, mlir::Operation *op);183184const TargetCIRGenInfo &getTargetCIRGenInfo();185186/// Helpers to convert the presumed location of Clang's SourceLocation to an187/// MLIR Location.188mlir::Location getLoc(clang::SourceLocation cLoc);189mlir::Location getLoc(clang::SourceRange cRange);190191/// Return the best known alignment for an unknown pointer to a192/// particular class.193clang::CharUnits getClassPointerAlignment(const clang::CXXRecordDecl *rd);194195/// FIXME: this could likely be a common helper and not necessarily related196/// with codegen.197clang::CharUnits getNaturalTypeAlignment(clang::QualType t,198LValueBaseInfo *baseInfo);199200cir::FuncOp201getAddrOfCXXStructor(clang::GlobalDecl gd,202const CIRGenFunctionInfo *fnInfo = nullptr,203cir::FuncType fnType = nullptr, bool dontDefer = false,204ForDefinition_t isForDefinition = NotForDefinition) {205return getAddrAndTypeOfCXXStructor(gd, fnInfo, fnType, dontDefer,206isForDefinition)207.second;208}209210std::pair<cir::FuncType, cir::FuncOp> getAddrAndTypeOfCXXStructor(211clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo = nullptr,212cir::FuncType fnType = nullptr, bool dontDefer = false,213ForDefinition_t isForDefinition = NotForDefinition);214215/// This contains all the decls which have definitions but which are deferred216/// for emission and therefore should only be output if they are actually217/// used. If a decl is in this, then it is known to have not been referenced218/// yet.219std::map<llvm::StringRef, clang::GlobalDecl> deferredDecls;220221// This is a list of deferred decls which we have seen that *are* actually222// referenced. These get code generated when the module is done.223std::vector<clang::GlobalDecl> deferredDeclsToEmit;224void addDeferredDeclToEmit(clang::GlobalDecl GD) {225deferredDeclsToEmit.emplace_back(GD);226}227228void emitTopLevelDecl(clang::Decl *decl);229230/// Determine whether the definition must be emitted; if this returns \c231/// false, the definition can be emitted lazily if it's used.232bool mustBeEmitted(const clang::ValueDecl *d);233234/// Determine whether the definition can be emitted eagerly, or should be235/// delayed until the end of the translation unit. This is relevant for236/// definitions whose linkage can change, e.g. implicit function237/// instantiations which may later be explicitly instantiated.238bool mayBeEmittedEagerly(const clang::ValueDecl *d);239240bool verifyModule() const;241242/// Return the address of the given function. If funcType is non-null, then243/// this function will use the specified type if it has to create it.244// TODO: this is a bit weird as `GetAddr` given we give back a FuncOp?245cir::FuncOp246getAddrOfFunction(clang::GlobalDecl gd, mlir::Type funcType = nullptr,247bool forVTable = false, bool dontDefer = false,248ForDefinition_t isForDefinition = NotForDefinition);249250mlir::Operation *251getAddrOfGlobal(clang::GlobalDecl gd,252ForDefinition_t isForDefinition = NotForDefinition);253254/// Emit code for a single global function or variable declaration. Forward255/// declarations are emitted lazily.256void emitGlobal(clang::GlobalDecl gd);257258void emitAliasForGlobal(llvm::StringRef mangledName, mlir::Operation *op,259GlobalDecl aliasGD, cir::FuncOp aliasee,260cir::GlobalLinkageKind linkage);261262mlir::Type convertType(clang::QualType type);263264/// Set the visibility for the given global.265void setGlobalVisibility(mlir::Operation *op, const NamedDecl *d) const;266void setDSOLocal(mlir::Operation *op) const;267void setDSOLocal(cir::CIRGlobalValueInterface gv) const;268269/// Set visibility, dllimport/dllexport and dso_local.270/// This must be called after dllimport/dllexport is set.271void setGVProperties(mlir::Operation *op, const NamedDecl *d) const;272void setGVPropertiesAux(mlir::Operation *op, const NamedDecl *d) const;273274/// Set function attributes for a function declaration.275void setFunctionAttributes(GlobalDecl gd, cir::FuncOp f,276bool isIncompleteFunction, bool isThunk);277278void emitGlobalDefinition(clang::GlobalDecl gd,279mlir::Operation *op = nullptr);280void emitGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op);281void emitGlobalVarDefinition(const clang::VarDecl *vd,282bool isTentative = false);283284void emitGlobalOpenACCDecl(const clang::OpenACCConstructDecl *cd);285286// C++ related functions.287void emitDeclContext(const DeclContext *dc);288289/// Return the result of value-initializing the given type, i.e. a null290/// expression of the given type.291mlir::Value emitNullConstant(QualType t, mlir::Location loc);292293llvm::StringRef getMangledName(clang::GlobalDecl gd);294295void emitTentativeDefinition(const VarDecl *d);296297// Make sure that this type is translated.298void updateCompletedType(const clang::TagDecl *td);299300// Produce code for this constructor/destructor. This method doesn't try to301// apply any ABI rules about which other constructors/destructors are needed302// or if they are alias to each other.303cir::FuncOp codegenCXXStructor(clang::GlobalDecl gd);304305bool supportsCOMDAT() const;306void maybeSetTrivialComdat(const clang::Decl &d, mlir::Operation *op);307308static void setInitializer(cir::GlobalOp &op, mlir::Attribute value);309310cir::FuncOp311getOrCreateCIRFunction(llvm::StringRef mangledName, mlir::Type funcType,312clang::GlobalDecl gd, bool forVTable,313bool dontDefer = false, bool isThunk = false,314ForDefinition_t isForDefinition = NotForDefinition,315mlir::ArrayAttr extraAttrs = {});316317cir::FuncOp createCIRFunction(mlir::Location loc, llvm::StringRef name,318cir::FuncType funcType,319const clang::FunctionDecl *funcDecl);320321/// Given a builtin id for a function like "__builtin_fabsf", return a322/// Function* for "fabsf".323cir::FuncOp getBuiltinLibFunction(const FunctionDecl *fd, unsigned builtinID);324325mlir::IntegerAttr getSize(CharUnits size) {326return builder.getSizeFromCharUnits(size);327}328329/// Emit any needed decls for which code generation was deferred.330void emitDeferred();331332/// Helper for `emitDeferred` to apply actual codegen.333void emitGlobalDecl(const clang::GlobalDecl &d);334335const llvm::Triple &getTriple() const { return target.getTriple(); }336337// Finalize CIR code generation.338void release();339340/// -------341/// Visibility and Linkage342/// -------343344static mlir::SymbolTable::Visibility345getMLIRVisibilityFromCIRLinkage(cir::GlobalLinkageKind GLK);346static cir::VisibilityKind getGlobalVisibilityKindFromClangVisibility(347clang::VisibilityAttr::VisibilityType visibility);348cir::VisibilityAttr getGlobalVisibilityAttrFromDecl(const Decl *decl);349static mlir::SymbolTable::Visibility getMLIRVisibility(cir::GlobalOp op);350cir::GlobalLinkageKind getFunctionLinkage(GlobalDecl gd);351cir::GlobalLinkageKind getCIRLinkageForDeclarator(const DeclaratorDecl *dd,352GVALinkage linkage,353bool isConstantVariable);354void setFunctionLinkage(GlobalDecl gd, cir::FuncOp f) {355cir::GlobalLinkageKind l = getFunctionLinkage(gd);356f.setLinkageAttr(cir::GlobalLinkageKindAttr::get(&getMLIRContext(), l));357mlir::SymbolTable::setSymbolVisibility(f,358getMLIRVisibilityFromCIRLinkage(l));359}360361cir::GlobalLinkageKind getCIRLinkageVarDefinition(const VarDecl *vd,362bool isConstant);363364void addReplacement(llvm::StringRef name, mlir::Operation *op);365366/// Helpers to emit "not yet implemented" error diagnostics367DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef);368369template <typename T>370DiagnosticBuilder errorNYI(SourceLocation loc, llvm::StringRef feature,371const T &name) {372unsigned diagID =373diags.getCustomDiagID(DiagnosticsEngine::Error,374"ClangIR code gen Not Yet Implemented: %0: %1");375return diags.Report(loc, diagID) << feature << name;376}377378DiagnosticBuilder errorNYI(mlir::Location loc, llvm::StringRef feature) {379// TODO: Convert the location to a SourceLocation380unsigned diagID = diags.getCustomDiagID(381DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");382return diags.Report(diagID) << feature;383}384385DiagnosticBuilder errorNYI(llvm::StringRef feature) const {386// TODO: Make a default location? currSrcLoc?387unsigned diagID = diags.getCustomDiagID(388DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");389return diags.Report(diagID) << feature;390}391392DiagnosticBuilder errorNYI(SourceRange, llvm::StringRef);393394template <typename T>395DiagnosticBuilder errorNYI(SourceRange loc, llvm::StringRef feature,396const T &name) {397return errorNYI(loc.getBegin(), feature, name) << loc;398}399400private:401// An ordered map of canonical GlobalDecls to their mangled names.402llvm::MapVector<clang::GlobalDecl, llvm::StringRef> mangledDeclNames;403llvm::StringMap<clang::GlobalDecl, llvm::BumpPtrAllocator> manglings;404405// FIXME: should we use llvm::TrackingVH<mlir::Operation> here?406typedef llvm::StringMap<mlir::Operation *> ReplacementsTy;407ReplacementsTy replacements;408/// Call replaceAllUsesWith on all pairs in replacements.409void applyReplacements();410411/// A helper function to replace all uses of OldF to NewF that replace412/// the type of pointer arguments. This is not needed to tradtional413/// pipeline since LLVM has opaque pointers but CIR not.414void replacePointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF);415416void setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op);417};418} // namespace CIRGen419420} // namespace clang421422#endif // LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H423424425