aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CIR
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CIR')
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp26
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp82
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExpr.cpp24
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenFunction.cpp5
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenFunction.h23
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenModule.cpp62
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenModule.h9
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenStmt.cpp1
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenTypeCache.h7
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenTypes.cpp2
-rw-r--r--clang/lib/CIR/CodeGen/CMakeLists.txt1
-rw-r--r--clang/lib/CIR/CodeGen/TargetInfo.h6
-rw-r--r--clang/lib/CIR/Dialect/IR/CIRAttrs.cpp10
-rw-r--r--clang/lib/CIR/Dialect/IR/CIRDialect.cpp13
-rw-r--r--clang/lib/CIR/Dialect/IR/CIRTypes.cpp81
-rw-r--r--clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp9
16 files changed, 309 insertions, 52 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index cf17de1..4cfa91e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -428,6 +428,32 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
return emitUnaryFPBuiltin<cir::ATanOp>(*this, *e);
case Builtin::BI__builtin_elementwise_cos:
return emitUnaryFPBuiltin<cir::CosOp>(*this, *e);
+ case Builtin::BI__builtin_coro_id:
+ case Builtin::BI__builtin_coro_promise:
+ case Builtin::BI__builtin_coro_resume:
+ case Builtin::BI__builtin_coro_noop:
+ case Builtin::BI__builtin_coro_destroy:
+ case Builtin::BI__builtin_coro_done:
+ case Builtin::BI__builtin_coro_alloc:
+ case Builtin::BI__builtin_coro_begin:
+ case Builtin::BI__builtin_coro_end:
+ case Builtin::BI__builtin_coro_suspend:
+ case Builtin::BI__builtin_coro_align:
+ cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_id like NYI");
+ return getUndefRValue(e->getType());
+
+ case Builtin::BI__builtin_coro_frame: {
+ cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_frame NYI");
+ assert(!cir::MissingFeatures::coroutineFrame());
+ return getUndefRValue(e->getType());
+ }
+ case Builtin::BI__builtin_coro_free:
+ case Builtin::BI__builtin_coro_size: {
+ cgm.errorNYI(e->getSourceRange(),
+ "BI__builtin_coro_free, BI__builtin_coro_size NYI");
+ assert(!cir::MissingFeatures::coroSizeBuiltinCall());
+ return getUndefRValue(e->getType());
+ }
}
// If this is an alias for a lib function (e.g. __builtin_sin), emit
diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
new file mode 100644
index 0000000..c25cce4
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
@@ -0,0 +1,82 @@
+//===----- CGCoroutine.cpp - Emit CIR Code for C++ coroutines -------------===//
+//
+// 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 contains code dealing with C++ code generation of coroutines.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenFunction.h"
+#include "mlir/Support/LLVM.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/CIR/Dialect/IR/CIRTypes.h"
+
+using namespace clang;
+using namespace clang::CIRGen;
+
+struct clang::CIRGen::CGCoroData {
+ // Stores the __builtin_coro_id emitted in the function so that we can supply
+ // it as the first argument to other builtins.
+ cir::CallOp coroId = nullptr;
+};
+
+// Defining these here allows to keep CGCoroData private to this file.
+CIRGenFunction::CGCoroInfo::CGCoroInfo() {}
+CIRGenFunction::CGCoroInfo::~CGCoroInfo() {}
+
+static void createCoroData(CIRGenFunction &cgf,
+ CIRGenFunction::CGCoroInfo &curCoro,
+ cir::CallOp coroId) {
+ assert(!curCoro.data && "EmitCoroutineBodyStatement called twice?");
+
+ curCoro.data = std::make_unique<CGCoroData>();
+ curCoro.data->coroId = coroId;
+}
+
+cir::CallOp CIRGenFunction::emitCoroIDBuiltinCall(mlir::Location loc,
+ mlir::Value nullPtr) {
+ cir::IntType int32Ty = builder.getUInt32Ty();
+
+ const TargetInfo &ti = cgm.getASTContext().getTargetInfo();
+ unsigned newAlign = ti.getNewAlign() / ti.getCharWidth();
+
+ mlir::Operation *builtin = cgm.getGlobalValue(cgm.builtinCoroId);
+
+ cir::FuncOp fnOp;
+ if (!builtin) {
+ fnOp = cgm.createCIRBuiltinFunction(
+ loc, cgm.builtinCoroId,
+ cir::FuncType::get({int32Ty, VoidPtrTy, VoidPtrTy, VoidPtrTy}, int32Ty),
+ /*FD=*/nullptr);
+ assert(fnOp && "should always succeed");
+ } else {
+ fnOp = cast<cir::FuncOp>(builtin);
+ }
+
+ return builder.createCallOp(loc, fnOp,
+ mlir::ValueRange{builder.getUInt32(newAlign, loc),
+ nullPtr, nullPtr, nullPtr});
+}
+
+mlir::LogicalResult
+CIRGenFunction::emitCoroutineBody(const CoroutineBodyStmt &s) {
+ mlir::Location openCurlyLoc = getLoc(s.getBeginLoc());
+ cir::ConstantOp nullPtrCst = builder.getNullPtr(VoidPtrTy, openCurlyLoc);
+
+ auto fn = mlir::cast<cir::FuncOp>(curFn);
+ fn.setCoroutine(true);
+ cir::CallOp coroId = emitCoroIDBuiltinCall(openCurlyLoc, nullPtrCst);
+ createCoroData(*this, curCoro, coroId);
+
+ assert(!cir::MissingFeatures::coroAllocBuiltinCall());
+
+ assert(!cir::MissingFeatures::coroBeginBuiltinCall());
+
+ assert(!cir::MissingFeatures::generateDebugInfo());
+ return mlir::success();
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index fa68ad9..be94890 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -1108,8 +1108,9 @@ CIRGenFunction::emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e) {
return lv;
}
-LValue CIRGenFunction::emitStringLiteralLValue(const StringLiteral *e) {
- cir::GlobalOp globalOp = cgm.getGlobalForStringLiteral(e);
+LValue CIRGenFunction::emitStringLiteralLValue(const StringLiteral *e,
+ llvm::StringRef name) {
+ cir::GlobalOp globalOp = cgm.getGlobalForStringLiteral(e, name);
assert(globalOp.getAlignment() && "expected alignment for string literal");
unsigned align = *(globalOp.getAlignment());
mlir::Value addr =
@@ -2052,8 +2053,8 @@ mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
// CIR uses its own alloca address space rather than follow the target data
// layout like original CodeGen. The data layout awareness should be done in
// the lowering pass instead.
- assert(!cir::MissingFeatures::addressSpace());
- cir::PointerType localVarPtrTy = builder.getPointerTo(ty);
+ cir::PointerType localVarPtrTy =
+ builder.getPointerTo(ty, getCIRAllocaAddressSpace());
mlir::IntegerAttr alignIntAttr = cgm.getSize(alignment);
mlir::Value addr;
@@ -2372,6 +2373,21 @@ mlir::Value CIRGenFunction::emitScalarConstant(
return builder.getConstant(getLoc(e->getSourceRange()), constant.getValue());
}
+LValue CIRGenFunction::emitPredefinedLValue(const PredefinedExpr *e) {
+ const StringLiteral *sl = e->getFunctionName();
+ assert(sl != nullptr && "No StringLiteral name in PredefinedExpr");
+ auto fn = cast<cir::FuncOp>(curFn);
+ StringRef fnName = fn.getName();
+ fnName.consume_front("\01");
+ std::array<StringRef, 2> nameItems = {
+ PredefinedExpr::getIdentKindName(e->getIdentKind()), fnName};
+ std::string gvName = llvm::join(nameItems, ".");
+ if (isa_and_nonnull<BlockDecl>(curCodeDecl))
+ cgm.errorNYI(e->getSourceRange(), "predefined lvalue in block");
+
+ return emitStringLiteralLValue(sl, gvName);
+}
+
/// An LValue is a candidate for having its loads and stores be made atomic if
/// we are operating under /volatile:ms *and* the LValue itself is volatile and
/// performing such an operation can be performed without a libcall.
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index b26b4f2..52fb0d7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -342,6 +342,9 @@ void CIRGenFunction::LexicalScope::cleanup() {
cir::ReturnOp CIRGenFunction::LexicalScope::emitReturn(mlir::Location loc) {
CIRGenBuilderTy &builder = cgf.getBuilder();
+ // If we are on a coroutine, add the coro_end builtin call.
+ assert(!cir::MissingFeatures::coroEndBuiltinCall());
+
auto fn = dyn_cast<cir::FuncOp>(cgf.curFn);
assert(fn && "emitReturn from non-function");
if (!fn.getFunctionType().hasVoidReturn()) {
@@ -815,6 +818,8 @@ LValue CIRGenFunction::emitLValue(const Expr *e) {
return emitMemberExpr(cast<MemberExpr>(e));
case Expr::CompoundLiteralExprClass:
return emitCompoundLiteralLValue(cast<CompoundLiteralExpr>(e));
+ case Expr::PredefinedExprClass:
+ return emitPredefinedLValue(cast<PredefinedExpr>(e));
case Expr::BinaryOperatorClass:
return emitBinaryOperatorLValue(cast<BinaryOperator>(e));
case Expr::CompoundAssignOperatorClass: {
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index cb7cf98..dfd9d2c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -47,6 +47,8 @@ class LoopOp;
namespace clang::CIRGen {
+struct CGCoroData;
+
class CIRGenFunction : public CIRGenTypeCache {
public:
CIRGenModule &cgm;
@@ -66,6 +68,18 @@ public:
/// The compiler-generated variable that holds the return value.
std::optional<mlir::Value> fnRetAlloca;
+ // Holds coroutine data if the current function is a coroutine. We use a
+ // wrapper to manage its lifetime, so that we don't have to define CGCoroData
+ // in this header.
+ struct CGCoroInfo {
+ std::unique_ptr<CGCoroData> data;
+ CGCoroInfo();
+ ~CGCoroInfo();
+ };
+ CGCoroInfo curCoro;
+
+ bool isCoroutine() const { return curCoro.data != nullptr; }
+
/// The temporary alloca to hold the return value. This is
/// invalid iff the function has no return value.
Address returnValue = Address::invalid();
@@ -1174,6 +1188,10 @@ public:
void emitConstructorBody(FunctionArgList &args);
+ mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s);
+ cir::CallOp emitCoroEndBuiltinCall(mlir::Location loc, mlir::Value nullPtr);
+ cir::CallOp emitCoroIDBuiltinCall(mlir::Location loc, mlir::Value nullPtr);
+
void emitDestroy(Address addr, QualType type, Destroyer *destroyer);
void emitDestructorBody(FunctionArgList &args);
@@ -1279,6 +1297,8 @@ public:
void emitInitializerForField(clang::FieldDecl *field, LValue lhs,
clang::Expr *init);
+ LValue emitPredefinedLValue(const PredefinedExpr *e);
+
mlir::Value emitPromotedComplexExpr(const Expr *e, QualType promotionType);
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType);
@@ -1473,7 +1493,8 @@ public:
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult);
- LValue emitStringLiteralLValue(const StringLiteral *e);
+ LValue emitStringLiteralLValue(const StringLiteral *e,
+ llvm::StringRef name = ".str");
mlir::LogicalResult emitSwitchBody(const clang::Stmt *s);
mlir::LogicalResult emitSwitchCase(const clang::SwitchCase &s,
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 2bd2729..910c8a9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -76,6 +76,7 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
SInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/true);
UInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);
UInt8PtrTy = cir::PointerType::get(UInt8Ty);
+ cirAllocaAddressSpace = getTargetCIRGenInfo().getCIRAllocaAddressSpace();
UInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/false);
UInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/false);
UInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/false);
@@ -1343,32 +1344,36 @@ cir::GlobalOp CIRGenModule::getGlobalForStringLiteral(const StringLiteral *s,
mlir::Attribute c = getConstantArrayFromStringLiteral(s);
- if (getLangOpts().WritableStrings) {
- errorNYI(s->getSourceRange(),
- "getGlobalForStringLiteral: Writable strings");
- }
-
- // Mangle the string literal if that's how the ABI merges duplicate strings.
- // Don't do it if they are writable, since we don't want writes in one TU to
- // affect strings in another.
- if (getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
- !getLangOpts().WritableStrings) {
- errorNYI(s->getSourceRange(),
- "getGlobalForStringLiteral: mangle string literals");
- }
-
- // Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
- // we need to do that explicitly.
- std::string uniqueName = getUniqueGlobalName(name.str());
- mlir::Location loc = getLoc(s->getSourceRange());
- auto typedC = llvm::cast<mlir::TypedAttr>(c);
- cir::GlobalOp gv =
- generateStringLiteral(loc, typedC, cir::GlobalLinkageKind::PrivateLinkage,
- *this, uniqueName, alignment);
- setDSOLocal(static_cast<mlir::Operation *>(gv));
+ cir::GlobalOp gv;
+ if (!getLangOpts().WritableStrings && constantStringMap.count(c)) {
+ gv = constantStringMap[c];
+ // The bigger alignment always wins.
+ if (!gv.getAlignment() ||
+ uint64_t(alignment.getQuantity()) > *gv.getAlignment())
+ gv.setAlignmentAttr(getSize(alignment));
+ } else {
+ // Mangle the string literal if that's how the ABI merges duplicate strings.
+ // Don't do it if they are writable, since we don't want writes in one TU to
+ // affect strings in another.
+ if (getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
+ !getLangOpts().WritableStrings) {
+ errorNYI(s->getSourceRange(),
+ "getGlobalForStringLiteral: mangle string literals");
+ }
- assert(!cir::MissingFeatures::sanitizers());
+ // Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
+ // we need to do that explicitly.
+ std::string uniqueName = getUniqueGlobalName(name.str());
+ mlir::Location loc = getLoc(s->getSourceRange());
+ auto typedC = llvm::cast<mlir::TypedAttr>(c);
+ gv = generateStringLiteral(loc, typedC,
+ cir::GlobalLinkageKind::PrivateLinkage, *this,
+ uniqueName, alignment);
+ setDSOLocal(static_cast<mlir::Operation *>(gv));
+ constantStringMap[c] = gv;
+ assert(!cir::MissingFeatures::sanitizers());
+ }
return gv;
}
@@ -2065,6 +2070,15 @@ CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
return func;
}
+cir::FuncOp
+CIRGenModule::createCIRBuiltinFunction(mlir::Location loc, StringRef name,
+ cir::FuncType ty,
+ const clang::FunctionDecl *fd) {
+ cir::FuncOp fnOp = createCIRFunction(loc, name, ty, fd);
+ fnOp.setBuiltin(true);
+ return fnOp;
+}
+
mlir::SymbolTable::Visibility
CIRGenModule::getMLIRVisibility(cir::GlobalOp op) {
// MLIR doesn't accept public symbols declarations (only
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index 2c4c6dd..c6a6681 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -274,6 +274,8 @@ public:
llvm_unreachable("unknown visibility!");
}
+ llvm::DenseMap<mlir::Attribute, cir::GlobalOp> constantStringMap;
+
/// Return a constant array for the given string.
mlir::Attribute getConstantArrayFromStringLiteral(const StringLiteral *e);
@@ -473,6 +475,13 @@ public:
cir::FuncType funcType,
const clang::FunctionDecl *funcDecl);
+ /// Create a CIR function with builtin attribute set.
+ cir::FuncOp createCIRBuiltinFunction(mlir::Location loc, llvm::StringRef name,
+ cir::FuncType ty,
+ const clang::FunctionDecl *fd);
+
+ static constexpr const char *builtinCoroId = "__builtin_coro_id";
+
/// Given a builtin id for a function like "__builtin_fabsf", return a
/// Function* for "fabsf".
cir::FuncOp getBuiltinLibFunction(const FunctionDecl *fd, unsigned builtinID);
diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
index 644c383..0b8f8bf 100644
--- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
@@ -197,6 +197,7 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s,
case Stmt::SEHLeaveStmtClass:
case Stmt::SYCLKernelCallStmtClass:
case Stmt::CoroutineBodyStmtClass:
+ return emitCoroutineBody(cast<CoroutineBodyStmt>(*s));
case Stmt::CoreturnStmtClass:
case Stmt::CXXTryStmtClass:
case Stmt::IndirectGotoStmtClass:
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
index cc3ce09..273ec7f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
+++ b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
@@ -14,6 +14,7 @@
#define LLVM_CLANG_LIB_CIR_CIRGENTYPECACHE_H
#include "clang/AST/CharUnits.h"
+#include "clang/Basic/AddressSpaces.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
namespace clang::CIRGen {
@@ -73,6 +74,8 @@ struct CIRGenTypeCache {
/// The alignment of size_t.
unsigned char SizeAlignInBytes;
+ cir::TargetAddressSpaceAttr cirAllocaAddressSpace;
+
clang::CharUnits getSizeAlign() const {
return clang::CharUnits::fromQuantity(SizeAlignInBytes);
}
@@ -80,6 +83,10 @@ struct CIRGenTypeCache {
clang::CharUnits getPointerAlign() const {
return clang::CharUnits::fromQuantity(PointerAlignInBytes);
}
+
+ cir::TargetAddressSpaceAttr getCIRAllocaAddressSpace() const {
+ return cirAllocaAddressSpace;
+ }
};
} // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index bb24933..e65896a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -417,7 +417,7 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
mlir::Type pointeeType = convertType(elemTy);
- resultType = builder.getPointerTo(pointeeType);
+ resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
break;
}
diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt b/clang/lib/CIR/CodeGen/CMakeLists.txt
index 3ebf460..36db4bd 100644
--- a/clang/lib/CIR/CodeGen/CMakeLists.txt
+++ b/clang/lib/CIR/CodeGen/CMakeLists.txt
@@ -14,6 +14,7 @@ add_clang_library(clangCIR
CIRGenCall.cpp
CIRGenClass.cpp
CIRGenCleanup.cpp
+ CIRGenCoroutine.cpp
CIRGenCXX.cpp
CIRGenCXXABI.cpp
CIRGenBuiltin.cpp
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.h b/clang/lib/CIR/CodeGen/TargetInfo.h
index a5c548a..dbb0312 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.h
+++ b/clang/lib/CIR/CodeGen/TargetInfo.h
@@ -16,6 +16,7 @@
#include "ABIInfo.h"
#include "CIRGenTypes.h"
+#include "clang/Basic/AddressSpaces.h"
#include <memory>
#include <utility>
@@ -43,6 +44,11 @@ public:
/// Returns ABI info helper for the target.
const ABIInfo &getABIInfo() const { return *info; }
+ /// Get the address space for alloca.
+ virtual cir::TargetAddressSpaceAttr getCIRAllocaAddressSpace() const {
+ return {};
+ }
+
/// Determine whether a call to an unprototyped functions under
/// the given calling convention should use the variadic
/// convention or the non-variadic convention.
diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
index 95faad6..3484c59 100644
--- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
@@ -43,6 +43,16 @@ parseFloatLiteral(mlir::AsmParser &parser,
mlir::FailureOr<llvm::APFloat> &value,
cir::FPTypeInterface fpType);
+//===----------------------------------------------------------------------===//
+// AddressSpaceAttr
+//===----------------------------------------------------------------------===//
+
+mlir::ParseResult parseTargetAddressSpace(mlir::AsmParser &p,
+ cir::TargetAddressSpaceAttr &attr);
+
+void printTargetAddressSpace(mlir::AsmPrinter &p,
+ cir::TargetAddressSpaceAttr attr);
+
static mlir::ParseResult parseConstPtr(mlir::AsmParser &parser,
mlir::IntegerAttr &value);
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 6b5cc80..fba094f 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -1632,12 +1632,19 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
llvm::SMLoc loc = parser.getCurrentLocation();
mlir::Builder &builder = parser.getBuilder();
+ mlir::StringAttr builtinNameAttr = getBuiltinAttrName(state.name);
+ mlir::StringAttr coroutineNameAttr = getCoroutineAttrName(state.name);
mlir::StringAttr lambdaNameAttr = getLambdaAttrName(state.name);
mlir::StringAttr noProtoNameAttr = getNoProtoAttrName(state.name);
mlir::StringAttr visNameAttr = getSymVisibilityAttrName(state.name);
mlir::StringAttr visibilityNameAttr = getGlobalVisibilityAttrName(state.name);
mlir::StringAttr dsoLocalNameAttr = getDsoLocalAttrName(state.name);
+ if (::mlir::succeeded(parser.parseOptionalKeyword(builtinNameAttr.strref())))
+ state.addAttribute(builtinNameAttr, parser.getBuilder().getUnitAttr());
+ if (::mlir::succeeded(
+ parser.parseOptionalKeyword(coroutineNameAttr.strref())))
+ state.addAttribute(coroutineNameAttr, parser.getBuilder().getUnitAttr());
if (::mlir::succeeded(parser.parseOptionalKeyword(lambdaNameAttr.strref())))
state.addAttribute(lambdaNameAttr, parser.getBuilder().getUnitAttr());
if (parser.parseOptionalKeyword(noProtoNameAttr).succeeded())
@@ -1747,6 +1754,12 @@ mlir::Region *cir::FuncOp::getCallableRegion() {
}
void cir::FuncOp::print(OpAsmPrinter &p) {
+ if (getBuiltin())
+ p << " builtin";
+
+ if (getCoroutine())
+ p << " coroutine";
+
if (getLambda())
p << " lambda";
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 35b4513..58973528 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -13,6 +13,7 @@
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "mlir/IR/DialectImplementation.h"
+#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/IR/CIRTypesDetails.h"
#include "clang/CIR/MissingFeatures.h"
@@ -38,6 +39,27 @@ parseFuncTypeParams(mlir::AsmParser &p, llvm::SmallVector<mlir::Type> &params,
static void printFuncTypeParams(mlir::AsmPrinter &p,
mlir::ArrayRef<mlir::Type> params,
bool isVarArg);
+//===----------------------------------------------------------------------===//
+// CIR Custom Parser/Printer Signatures
+//===----------------------------------------------------------------------===//
+
+static mlir::ParseResult
+parseFuncTypeParams(mlir::AsmParser &p, llvm::SmallVector<mlir::Type> &params,
+ bool &isVarArg);
+
+static void printFuncTypeParams(mlir::AsmPrinter &p,
+ mlir::ArrayRef<mlir::Type> params,
+ bool isVarArg);
+
+//===----------------------------------------------------------------------===//
+// AddressSpace
+//===----------------------------------------------------------------------===//
+
+mlir::ParseResult parseTargetAddressSpace(mlir::AsmParser &p,
+ cir::TargetAddressSpaceAttr &attr);
+
+void printTargetAddressSpace(mlir::AsmPrinter &p,
+ cir::TargetAddressSpaceAttr attr);
//===----------------------------------------------------------------------===//
// Get autogenerated stuff
@@ -298,6 +320,22 @@ bool RecordType::isLayoutIdentical(const RecordType &other) {
//===----------------------------------------------------------------------===//
llvm::TypeSize
+PointerType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
+ ::mlir::DataLayoutEntryListRef params) const {
+ // FIXME: improve this in face of address spaces
+ assert(!cir::MissingFeatures::dataLayoutPtrHandlingBasedOnLangAS());
+ return llvm::TypeSize::getFixed(64);
+}
+
+uint64_t
+PointerType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
+ ::mlir::DataLayoutEntryListRef params) const {
+ // FIXME: improve this in face of address spaces
+ assert(!cir::MissingFeatures::dataLayoutPtrHandlingBasedOnLangAS());
+ return 8;
+}
+
+llvm::TypeSize
RecordType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
mlir::DataLayoutEntryListRef params) const {
if (isUnion())
@@ -766,30 +804,39 @@ mlir::LogicalResult cir::VectorType::verify(
}
//===----------------------------------------------------------------------===//
-// PointerType Definitions
+// TargetAddressSpace definitions
//===----------------------------------------------------------------------===//
-llvm::TypeSize
-PointerType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
- ::mlir::DataLayoutEntryListRef params) const {
- // FIXME: improve this in face of address spaces
- return llvm::TypeSize::getFixed(64);
-}
+mlir::ParseResult parseTargetAddressSpace(mlir::AsmParser &p,
+ cir::TargetAddressSpaceAttr &attr) {
+ if (failed(p.parseKeyword("target_address_space")))
+ return mlir::failure();
-uint64_t
-PointerType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
- ::mlir::DataLayoutEntryListRef params) const {
- // FIXME: improve this in face of address spaces
- return 8;
-}
+ if (failed(p.parseLParen()))
+ return mlir::failure();
-mlir::LogicalResult
-PointerType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
- mlir::Type pointee) {
- // TODO(CIR): Verification of the address space goes here.
+ int32_t targetValue;
+ if (failed(p.parseInteger(targetValue)))
+ return p.emitError(p.getCurrentLocation(),
+ "expected integer address space value");
+
+ if (failed(p.parseRParen()))
+ return p.emitError(p.getCurrentLocation(),
+ "expected ')' after address space value");
+
+ mlir::MLIRContext *context = p.getBuilder().getContext();
+ attr = cir::TargetAddressSpaceAttr::get(
+ context, p.getBuilder().getUI32IntegerAttr(targetValue));
return mlir::success();
}
+// The custom printer for the `addrspace` parameter in `!cir.ptr`.
+// in the format of `target_address_space(N)`.
+void printTargetAddressSpace(mlir::AsmPrinter &p,
+ cir::TargetAddressSpaceAttr attr) {
+ p << "target_address_space(" << attr.getValue().getUInt() << ")";
+}
+
//===----------------------------------------------------------------------===//
// CIR Dialect
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 4bc7783..bfb1262 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -32,6 +32,7 @@
#include "mlir/Transforms/DialectConversion.h"
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/Dialect/Passes.h"
#include "clang/CIR/LoweringHelpers.h"
#include "clang/CIR/MissingFeatures.h"
@@ -2308,11 +2309,9 @@ mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite(
static void prepareTypeConverter(mlir::LLVMTypeConverter &converter,
mlir::DataLayout &dataLayout) {
converter.addConversion([&](cir::PointerType type) -> mlir::Type {
- // Drop pointee type since LLVM dialect only allows opaque pointers.
- assert(!cir::MissingFeatures::addressSpace());
- unsigned targetAS = 0;
-
- return mlir::LLVM::LLVMPointerType::get(type.getContext(), targetAS);
+ unsigned addrSpace =
+ type.getAddrSpace() ? type.getAddrSpace().getValue().getUInt() : 0;
+ return mlir::LLVM::LLVMPointerType::get(type.getContext(), addrSpace);
});
converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
assert(!cir::MissingFeatures::addressSpace());