Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
120 changes: 112 additions & 8 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 @@ -639,13 +674,82 @@ 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");
out << ii->getName();
} else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
gd.getKernelReferenceKind() == KernelReferenceKind::Stub) {
out << "__device_stub__" << ii->getName();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should either have tests for this, or just leave this errorNYI.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I don't think we can hit this yet. I'll make it NYI.

} else {
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