Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,15 @@ struct MissingFeatures {
static bool weakRefReference() { return false; }
static bool hip() { return false; }
static bool setObjCGCLValueClass() { return false; }
static bool mangledNames() { return false; }
static bool setDLLStorageClass() { return false; }
static bool openMP() { return false; }
static bool emitCheckedInBoundsGEP() { return false; }
static bool preservedAccessIndexRegion() { return false; }
static bool bitfields() { return false; }
static bool typeChecks() { return false; }
static bool lambdaFieldToName() { return false; }
static bool targetSpecificCXXABI() { return false; }
static bool moduleNameHash() { return false; }

// Missing types
static bool dataMemberType() { return false; }
Expand Down
46 changes: 46 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenCXXABI.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//===----------------------------------------------------------------------===//
//
// 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 provides an abstract class for C++ code generation. Concrete subclasses
// of this implement code generation for specific C++ ABIs.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_CIR_CIRGENCXXABI_H
#define LLVM_CLANG_LIB_CIR_CIRGENCXXABI_H

#include "CIRGenModule.h"

#include "clang/AST/Mangle.h"

namespace clang::CIRGen {

/// Implements C++ ABI-specific code generation functions.
class CIRGenCXXABI {
protected:
CIRGenModule &cgm;
std::unique_ptr<clang::MangleContext> mangleContext;

public:
// TODO(cir): make this protected when target-specific CIRGenCXXABIs are
// implemented.
CIRGenCXXABI(CIRGenModule &cgm)
: cgm(cgm), mangleContext(cgm.getASTContext().createMangleContext()) {}
~CIRGenCXXABI();

public:
/// Gets the mangle context.
clang::MangleContext &getMangleContext() { return *mangleContext; }
};

/// Creates and Itanium-family ABI
CIRGenCXXABI *CreateCIRGenItaniumCXXABI(CIRGenModule &cgm);

} // namespace clang::CIRGen

#endif
121 changes: 112 additions & 9 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//

#include "CIRGenModule.h"
#include "CIRGenCXXABI.h"
#include "CIRGenConstantEmitter.h"
#include "CIRGenFunction.h"

Expand All @@ -30,14 +31,46 @@
using namespace clang;
using namespace clang::CIRGen;

static CIRGenCXXABI *createCXXABI(CIRGenModule &cgm) {
switch (cgm.getASTContext().getCXXABIKind()) {
case TargetCXXABI::GenericItanium:
case TargetCXXABI::GenericAArch64:
case TargetCXXABI::AppleARM64:
return CreateCIRGenItaniumCXXABI(cgm);

case TargetCXXABI::Fuchsia:
case TargetCXXABI::GenericARM:
case TargetCXXABI::iOS:
case TargetCXXABI::WatchOS:
case TargetCXXABI::GenericMIPS:
case TargetCXXABI::WebAssembly:
case TargetCXXABI::XL:
case TargetCXXABI::Microsoft:
cgm.errorNYI("C++ ABI kind not yet implemented");
return nullptr;
}

llvm_unreachable("invalid C++ ABI kind");
}

namespace clang::CIRGen {
// TODO(cir): Implement target-specific CIRGenCXXABIs
CIRGenCXXABI *CreateCIRGenItaniumCXXABI(CIRGenModule &cgm) {
assert(!cir::MissingFeatures::targetSpecificCXXABI());
return new CIRGenCXXABI(cgm);
}
} // namespace clang::CIRGen
CIRGenCXXABI::~CIRGenCXXABI() {}

CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
clang::ASTContext &astContext,
const clang::CodeGenOptions &cgo,
DiagnosticsEngine &diags)
: builder(mlirContext, *this), astContext(astContext),
langOpts(astContext.getLangOpts()), codeGenOpts(cgo),
theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&mlirContext))},
diags(diags), target(astContext.getTargetInfo()), genTypes(*this) {
diags(diags), target(astContext.getTargetInfo()),
abi(createCXXABI(*this)), genTypes(*this) {

// Initialize cached types
VoidTy = cir::VoidType::get(&getMLIRContext());
Expand Down Expand Up @@ -74,6 +107,8 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
builder.getStringAttr(getTriple().str()));
}

CIRGenModule::~CIRGenModule() = default;

CharUnits CIRGenModule::getNaturalTypeAlignment(QualType t,
LValueBaseInfo *baseInfo) {
assert(!cir::MissingFeatures::opTBAA());
Expand Down Expand Up @@ -301,9 +336,9 @@ CIRGenModule::getOrCreateCIRGlobal(const VarDecl *d, mlir::Type ty,
if (!ty)
ty = getTypes().convertTypeForMem(astTy);

assert(!cir::MissingFeatures::mangledNames());
return getOrCreateCIRGlobal(d->getIdentifier()->getName(), ty,
astTy.getAddressSpace(), d, isForDefinition);
StringRef mangledName = getMangledName(d);
return getOrCreateCIRGlobal(mangledName, ty, astTy.getAddressSpace(), d,
isForDefinition);
}

/// Return the mlir::Value for the address of the given global variable. If
Expand Down Expand Up @@ -332,8 +367,9 @@ void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
const QualType astTy = vd->getType();
const mlir::Type type = convertType(vd->getType());
if (clang::IdentifierInfo *identifier = vd->getIdentifier()) {
StringRef name = getMangledName(GlobalDecl(vd));
auto varOp = builder.create<cir::GlobalOp>(getLoc(vd->getSourceRange()),
identifier->getName(), type);
name, type);
// TODO(CIR): This code for processing initial values is a placeholder
// until class ConstantEmitter is upstreamed and the code for processing
// constant expressions is filled out. Only the most basic handling of
Expand Down Expand Up @@ -639,13 +675,80 @@ cir::FuncOp CIRGenModule::getAddrOfFunction(clang::GlobalDecl gd,
funcType = convertType(fd->getType());
}

assert(!cir::MissingFeatures::mangledNames());
cir::FuncOp func = getOrCreateCIRFunction(
cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName(), funcType, gd,
forVTable, dontDefer, /*isThunk=*/false, isForDefinition);
StringRef mangledName = getMangledName(gd);
cir::FuncOp func =
getOrCreateCIRFunction(mangledName, funcType, gd, forVTable, dontDefer,
/*isThunk=*/false, isForDefinition);
return func;
}

static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd,
const NamedDecl *nd) {
SmallString<256> buffer;

llvm::raw_svector_ostream out(buffer);
MangleContext &mc = cgm.getCXXABI().getMangleContext();

assert(!cir::MissingFeatures::moduleNameHash());

if (mc.shouldMangleDeclName(nd)) {
mc.mangleName(gd.getWithDecl(nd), out);
} else {
IdentifierInfo *ii = nd->getIdentifier();
assert(ii && "Attempt to mangle unnamed decl.");

const auto *fd = dyn_cast<FunctionDecl>(nd);
if (fd &&
fd->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) {
cgm.errorNYI(nd->getSourceRange(), "getMangledName: X86RegCall");
} else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
gd.getKernelReferenceKind() == KernelReferenceKind::Stub) {
cgm.errorNYI(nd->getSourceRange(), "getMangledName: CUDA device stub");
}
out << ii->getName();
}

// Check if the module name hash should be appended for internal linkage
// symbols. This should come before multi-version target suffixes are
// appendded. This is to keep the name and module hash suffix of the internal
// linkage function together. The unique suffix should only be added when name
// mangling is done to make sure that the final name can be properly
// demangled. For example, for C functions without prototypes, name mangling
// is not done and the unique suffix should not be appended then.
assert(!cir::MissingFeatures::moduleNameHash());

if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {
if (fd->isMultiVersion()) {
cgm.errorNYI(nd->getSourceRange(),
"getMangledName: multi-version functions");
}
}
if (cgm.getLangOpts().GPURelocatableDeviceCode) {
cgm.errorNYI(nd->getSourceRange(),
"getMangledName: GPU relocatable device code");
}

return std::string(out.str());
}

StringRef CIRGenModule::getMangledName(GlobalDecl gd) {
GlobalDecl canonicalGd = gd.getCanonicalDecl();

// Some ABIs don't have constructor variants. Make sure that base and complete
// constructors get mangled the same.
if (const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.getDecl())) {
errorNYI(cd->getSourceRange(), "getMangledName: C++ constructor");
return cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName();
}

// Keep the first result in the case of a mangling collision.
const auto *nd = cast<NamedDecl>(gd.getDecl());
std::string mangledName = getMangledNameImpl(*this, gd, nd);

auto result = manglings.insert(std::make_pair(mangledName, gd));
return mangledDeclNames[canonicalGd] = result.first->first();
}

cir::FuncOp CIRGenModule::getOrCreateCIRFunction(
StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,
bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,
Expand Down
14 changes: 13 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class VarDecl;
namespace CIRGen {

class CIRGenFunction;
class CIRGenCXXABI;

enum ForDefinition_t : bool { NotForDefinition = false, ForDefinition = true };

Expand All @@ -59,7 +60,7 @@ class CIRGenModule : public CIRGenTypeCache {
const clang::CodeGenOptions &cgo,
clang::DiagnosticsEngine &diags);

~CIRGenModule() = default;
~CIRGenModule();

private:
mutable std::unique_ptr<TargetCIRGenInfo> theTargetCIRGenInfo;
Expand All @@ -80,6 +81,8 @@ class CIRGenModule : public CIRGenTypeCache {

const clang::TargetInfo &target;

std::unique_ptr<CIRGenCXXABI> abi;

CIRGenTypes genTypes;

/// Per-function codegen information. Updated everytime emitCIR is called
Expand All @@ -94,6 +97,8 @@ class CIRGenModule : public CIRGenTypeCache {
const clang::CodeGenOptions &getCodeGenOpts() const { return codeGenOpts; }
CIRGenTypes &getTypes() { return genTypes; }
const clang::LangOptions &getLangOpts() const { return langOpts; }

CIRGenCXXABI &getCXXABI() const { return *abi; }
mlir::MLIRContext &getMLIRContext() { return *builder.getContext(); }

const cir::CIRDataLayout getDataLayout() const {
Expand Down Expand Up @@ -169,6 +174,8 @@ class CIRGenModule : public CIRGenTypeCache {
/// expression of the given type.
mlir::Value emitNullConstant(QualType t, mlir::Location loc);

llvm::StringRef getMangledName(clang::GlobalDecl gd);

cir::FuncOp
getOrCreateCIRFunction(llvm::StringRef mangledName, mlir::Type funcType,
clang::GlobalDecl gd, bool forVTable,
Expand Down Expand Up @@ -226,6 +233,11 @@ class CIRGenModule : public CIRGenTypeCache {
const T &name) {
return errorNYI(loc.getBegin(), feature, name) << loc;
}

private:
// An ordered map of canonical GlobalDecls to their mangled names.
llvm::MapVector<clang::GlobalDecl, llvm::StringRef> mangledDeclNames;
llvm::StringMap<clang::GlobalDecl, llvm::BumpPtrAllocator> manglings;
};
} // namespace CIRGen

Expand Down
Loading
Loading