Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
118 changes: 110 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,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
26 changes: 13 additions & 13 deletions clang/test/CIR/CodeGen/array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ void func() {
// CIR: %[[TMP:.*]] = cir.load %[[ELE_PTR]] : !cir.ptr<!s32i>, !s32i
// CIR" cir.store %[[TMP]], %[[INIT_2]] : !s32i, !cir.ptr<!s32i>

// LLVM: define void @func()
// LLVM: define void @_Z4funcv()
// LLVM-NEXT: %[[ARR:.*]] = alloca [10 x i32], i64 1, align 16
// LLVM-NEXT: %[[INIT:.*]] = alloca i32, i64 1, align 4
// LLVM-NEXT: %[[INIT_2:.*]] = alloca i32, i64 1, align 4
Expand Down Expand Up @@ -135,7 +135,7 @@ void func2() {
// CIR: %[[ELE_1_PTR:.*]] = cir.ptr_stride(%[[LOAD_1]] : !cir.ptr<!s32i>, %[[OFFSET_1]] : !s64i), !cir.ptr<!s32i>
// CIR: cir.store %[[ELE_1_PTR]], %[[ELE_ALLOCA]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>

// LLVM: define void @func2()
// LLVM: define void @_Z5func2v()
// LLVM: %[[ARR:.*]] = alloca [2 x i32], i64 1, align 4
// LLVM: %[[TMP:.*]] = alloca ptr, i64 1, align 8
// LLVM: %[[ARR_PTR:.*]] = getelementptr i32, ptr %[[ARR]], i32 0
Expand Down Expand Up @@ -175,7 +175,7 @@ void func3() {
// CIR: %[[ELE_TMP:.*]] = cir.load %[[ELE_PTR]] : !cir.ptr<!s32i>, !s32i
// CIR: cir.store %[[ELE_TMP]], %[[INIT]] : !s32i, !cir.ptr<!s32i>

// LLVM: define void @func3()
// LLVM: define void @_Z5func3v()
// LLVM: %[[ARR:.*]] = alloca [2 x i32], i64 1, align 4
// LLVM: %[[IDX:.*]] = alloca i32, i64 1, align 4
// LLVM: %[[INIT:.*]] = alloca i32, i64 1, align 4
Expand Down Expand Up @@ -227,7 +227,7 @@ void func4() {
// CIR: %[[TMP:.*]] = cir.load %[[ELE_0]] : !cir.ptr<!s32i>, !s32i
// CIR: cir.store %[[TMP]], %[[INIT]] : !s32i, !cir.ptr<!s32i>

// LLVM: define void @func4()
// LLVM: define void @_Z5func4v()
// LLVM: %[[ARR:.*]] = alloca [2 x [1 x i32]], i64 1, align 4
// LLVM: %[[INIT:.*]] = alloca i32, i64 1, align 4
// LLVM: %[[ARR_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR]], i32 0
Expand Down Expand Up @@ -271,7 +271,7 @@ void func5() {
// CIR: %10 = cir.ptr_stride(%7 : !cir.ptr<!cir.array<!s32i x 1>>, %[[OFFSET_1]] : !s64i), !cir.ptr<!cir.array<!s32i x 1>>
// CIR: cir.store %10, %[[ARR_PTR]] : !cir.ptr<!cir.array<!s32i x 1>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>>

// LLVM: define void @func5()
// LLVM: define void @_Z5func5v()
// LLVM: %[[ARR:.*]] = alloca [2 x [1 x i32]], i64 1, align 4
// LLVM: %[[TMP:.*]] = alloca ptr, i64 1, align 8
// LLVM: %[[ARR_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR]], i32 0
Expand Down Expand Up @@ -304,7 +304,7 @@ void func6() {
// CIR: %[[V1:.*]] = cir.const #cir.int<5> : !s32i
// CIR: cir.store %[[V1]], %[[ELE_PTR]] : !s32i, !cir.ptr<!s32i>

// LLVM: define void @func6()
// LLVM: define void @_Z5func6v()
// LLVM: %[[VAR:.*]] = alloca i32, i64 1, align 4
// LLVM: %[[ARR:.*]] = alloca [2 x i32], i64 1, align 4
// LLVM: store i32 4, ptr %[[VAR]], align 4
Expand Down Expand Up @@ -337,7 +337,7 @@ void func7() {
// CIR: %[[ELE_PTR:.*]] = cir.ptr_stride(%[[TMP]] : !cir.ptr<!cir.ptr<!s32i>>, %[[OFFSET]] : !s64i), !cir.ptr<!cir.ptr<!s32i>>
// CIR: cir.store %[[ELE_PTR]], %[[ARR_TMP]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>

// LLVM: define void @func7()
// LLVM: define void @_Z5func7v()
// LLVM: %[[ARR:.*]] = alloca [1 x ptr], i64 1, align 8
// LLVM: %[[ALLOCA:.*]] = alloca ptr, i64 1, align 8
// LLVM: %[[ELE_PTR:.*]] = getelementptr ptr, ptr %[[ARR]], i32 0
Expand All @@ -355,7 +355,7 @@ void func8(int arr[10]) {
int e2 = arr[1];
}

// CIR: cir.func @func8(%[[ARG:.*]]: !cir.ptr<!s32i>
// CIR: cir.func @_Z5func8Pi(%[[ARG:.*]]: !cir.ptr<!s32i>
// CIR: %[[ARR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["arr", init]
// CIR: %[[INIT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e", init]
// CIR: %[[INIT_2:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e2", init]
Expand All @@ -371,7 +371,7 @@ void func8(int arr[10]) {
// CIR: %[[TMP_4:.*]] = cir.load %[[ELE_1]] : !cir.ptr<!s32i>, !s32i
// CIR: cir.store %[[TMP_4]], %[[INIT_2]] : !s32i, !cir.ptr<!s32i>

// LLVM: define void @func8(ptr %[[ARG:.*]])
// LLVM: define void @_Z5func8Pi(ptr %[[ARG:.*]])
// LLVM: %[[ARR:.*]] = alloca ptr, i64 1, align 8
// LLVM: %[[INIT:.*]] = alloca i32, i64 1, align 4
// LLVM: %[[INIT_2:.*]] = alloca i32, i64 1, align 4
Expand Down Expand Up @@ -402,7 +402,7 @@ void func9(int arr[10][5]) {
int e = arr[1][2];
}

// CIR: cir.func @func9(%[[ARG:.*]]: !cir.ptr<!cir.array<!s32i x 5>>
// CIR: cir.func @_Z5func9PA5_i(%[[ARG:.*]]: !cir.ptr<!cir.array<!s32i x 5>>
// CIR: %[[ARR:.*]] = cir.alloca !cir.ptr<!cir.array<!s32i x 5>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 5>>>, ["arr", init]
// CIR: %[[INIT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e", init]
// CIR: cir.store %[[ARG]], %[[ARR]] : !cir.ptr<!cir.array<!s32i x 5>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 5>>>
Expand All @@ -415,7 +415,7 @@ void func9(int arr[10][5]) {
// CIR: %[[TMP_2:.*]] = cir.load %[[ARR_1_2]] : !cir.ptr<!s32i>, !s32i
// CIR: cir.store %[[TMP_2]], %[[INIT]] : !s32i, !cir.ptr<!s32i>

// LLVM: define void @func9(ptr %[[ARG:.*]])
// LLVM: define void @_Z5func9PA5_i(ptr %[[ARG:.*]])
// LLVM: %[[ARR:.*]] = alloca ptr, i64 1, align 8
// LLVM: %[[INIT:.*]] = alloca i32, i64 1, align 4
// LLVM: store ptr %[[ARG]], ptr %[[ARR]], align 8
Expand All @@ -439,7 +439,7 @@ void func10(int *a) {
int e = a[5];
}

// CIR: cir.func @func10(%[[ARG:.*]]: !cir.ptr<!s32i>
// CIR: cir.func @_Z6func10Pi(%[[ARG:.*]]: !cir.ptr<!s32i>
// CIR: %[[ARR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["a", init]
// CIR: %[[INIT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e", init]
// CIR: cir.store %[[ARG]], %[[ARR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
Expand All @@ -449,7 +449,7 @@ void func10(int *a) {
// CIR: %[[TMP_2:.*]] = cir.load %[[ELE]] : !cir.ptr<!s32i>, !s32i
// CIR: cir.store %[[TMP_2]], %[[INIT]] : !s32i, !cir.ptr<!s32i>

// LLVM: define void @func10(ptr %[[ARG:.*]]) {
// LLVM: define void @_Z6func10Pi(ptr %[[ARG:.*]]) {
// LLVM: %[[ARR:.*]] = alloca ptr, i64 1, align 8
// LLVM: %[[INIT:.*]] = alloca i32, i64 1, align 4
// LLVM: store ptr %[[ARG]], ptr %[[ARR]], align 8
Expand Down
Loading
Loading