[clang] [CIR] Upstream global initialization for ArrayType (PR #131657)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 17 11:43:08 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Amr Hesham (AmrDeveloper)
<details>
<summary>Changes</summary>
This change adds global initialization for ArrayType
Issue #<!-- -->130197
---
Patch is 32.77 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/131657.diff
13 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/IR/CIRAttrs.td (+42)
- (modified) clang/lib/CIR/CodeGen/CIRGenBuilder.h (+34)
- (modified) clang/lib/CIR/CodeGen/CIRGenConstantEmitter.h (+4-2)
- (modified) clang/lib/CIR/CodeGen/CIRGenDecl.cpp (-1)
- (modified) clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp (+112-10)
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+5-33)
- (modified) clang/lib/CIR/Dialect/IR/CIRAttrs.cpp (+109)
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+9)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+71-4)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h (+6)
- (modified) clang/test/CIR/CodeGen/array.cpp (+20-5)
- (modified) clang/test/CIR/IR/array.cir (+18-6)
- (modified) clang/test/CIR/Lowering/array.cpp (+23-6)
``````````diff
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 7b3741de29075..3680ded4afafe 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -154,6 +154,48 @@ def FPAttr : CIR_Attr<"FP", "fp", [TypedAttrInterface]> {
}];
}
+
+//===----------------------------------------------------------------------===//
+// ConstArrayAttr
+//===----------------------------------------------------------------------===//
+
+def ConstArrayAttr : CIR_Attr<"ConstArray", "const_array", [TypedAttrInterface]> {
+ let summary = "A constant array from ArrayAttr or StringRefAttr";
+ let description = [{
+ An CIR array attribute is an array of literals of the specified attr types.
+ }];
+
+ let parameters = (ins AttributeSelfTypeParameter<"">:$type,
+ "mlir::Attribute":$elts,
+ "int":$trailingZerosNum);
+
+ // Define a custom builder for the type; that removes the need to pass
+ // in an MLIRContext instance, as it can be infered from the `type`.
+ let builders = [
+ AttrBuilderWithInferredContext<(ins "cir::ArrayType":$type,
+ "mlir::Attribute":$elts), [{
+ int zeros = 0;
+ auto typeSize = mlir::cast<cir::ArrayType>(type).getSize();
+ if (auto str = mlir::dyn_cast<mlir::StringAttr>(elts))
+ zeros = typeSize - str.size();
+ else
+ zeros = typeSize - mlir::cast<mlir::ArrayAttr>(elts).size();
+
+ return $_get(type.getContext(), type, elts, zeros);
+ }]>
+ ];
+
+ // Printing and parsing available in CIRDialect.cpp
+ let hasCustomAssemblyFormat = 1;
+
+ // Enable verifier.
+ let genVerifyDecl = 1;
+
+ let extraClassDeclaration = [{
+ bool hasTrailingZeros() const { return getTrailingZerosNum() != 0; };
+ }];
+}
+
//===----------------------------------------------------------------------===//
// ConstPtrAttr
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 260ee25719be1..a2a75148ee884 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -43,6 +43,40 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
assert(!cir::MissingFeatures::unsizedTypes());
return false;
}
+
+ bool isNullValue(mlir::Attribute attr) const {
+ if (mlir::isa<cir::ZeroAttr>(attr))
+ return true;
+
+ if (const auto ptrVal = mlir::dyn_cast<cir::ConstPtrAttr>(attr))
+ return ptrVal.isNullValue();
+
+ if (const auto intVal = mlir::dyn_cast<cir::IntAttr>(attr))
+ return intVal.isNullValue();
+
+ if (const auto boolVal = mlir::dyn_cast<cir::BoolAttr>(attr))
+ return !boolVal.getValue();
+
+ if (auto fpAttr = mlir::dyn_cast<cir::FPAttr>(attr)) {
+ auto fpVal = fpAttr.getValue();
+ bool ignored;
+ llvm::APFloat fv(+0.0);
+ fv.convert(fpVal.getSemantics(), llvm::APFloat::rmNearestTiesToEven,
+ &ignored);
+ return fv.bitwiseIsEqual(fpVal);
+ }
+
+ if (const auto arrayVal = mlir::dyn_cast<cir::ConstArrayAttr>(attr)) {
+ if (mlir::isa<mlir::StringAttr>(arrayVal.getElts()))
+ return false;
+ for (const auto elt : mlir::cast<mlir::ArrayAttr>(arrayVal.getElts())) {
+ if (!isNullValue(elt))
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
};
} // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenConstantEmitter.h b/clang/lib/CIR/CodeGen/CIRGenConstantEmitter.h
index 5b22a8e59908d..ca4e607992bbc 100644
--- a/clang/lib/CIR/CodeGen/CIRGenConstantEmitter.h
+++ b/clang/lib/CIR/CodeGen/CIRGenConstantEmitter.h
@@ -20,7 +20,6 @@
#include "CIRGenFunction.h"
#include "CIRGenModule.h"
-#include "llvm/ADT/SmallVector.h"
namespace clang::CIRGen {
@@ -41,6 +40,9 @@ class ConstantEmitter {
/// block addresses or PredefinedExprs.
ConstantEmitter(CIRGenFunction &cgf) : cgm(cgf.cgm), cgf(&cgf) {}
+ ConstantEmitter(CIRGenModule &cgm, CIRGenFunction *cgf = nullptr)
+ : cgm(cgm), cgf(cgf) {}
+
ConstantEmitter(const ConstantEmitter &other) = delete;
ConstantEmitter &operator=(const ConstantEmitter &other) = delete;
@@ -66,7 +68,7 @@ class ConstantEmitter {
mlir::Attribute emitAbstract(SourceLocation loc, const APValue &value,
QualType t);
- mlir::Attribute tryEmitConstantExpr(const ConstantExpr *CE);
+ mlir::Attribute tryEmitConstantExpr(const ConstantExpr *ce);
// These are private helper routines of the constant emitter that
// can't actually be private because things are split out into helper
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index 27ed0113a4f55..a93e8dbcb42de 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -225,7 +225,6 @@ void CIRGenFunction::emitScalarInit(const Expr *init, mlir::Location loc,
}
assert(!cir::MissingFeatures::emitNullabilityCheck());
emitStoreThroughLValue(RValue::get(value), lvalue, true);
- return;
}
void CIRGenFunction::emitExprAsInit(const Expr *init, const ValueDecl *d,
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index 1ea7f6212766c..d3c22f54127c5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -158,13 +158,56 @@ class ConstExprEmitter
// TODO(cir): this can be shared with LLVM's codegen
static QualType getNonMemoryType(CIRGenModule &cgm, QualType type) {
- if (auto at = type->getAs<AtomicType>()) {
+ if (const auto *at = type->getAs<AtomicType>()) {
return cgm.getASTContext().getQualifiedType(at->getValueType(),
type.getQualifiers());
}
return type;
}
+static mlir::Attribute
+emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,
+ mlir::Type commonElementType, unsigned arrayBound,
+ SmallVectorImpl<mlir::TypedAttr> &elements,
+ mlir::TypedAttr filter) {
+ const auto &builder = cgm.getBuilder();
+
+ unsigned nonzeroLength = arrayBound;
+ if (elements.size() < nonzeroLength && builder.isNullValue(filter))
+ nonzeroLength = elements.size();
+
+ if (nonzeroLength == elements.size()) {
+ while (nonzeroLength > 0 &&
+ builder.isNullValue(elements[nonzeroLength - 1]))
+ --nonzeroLength;
+ }
+
+ if (nonzeroLength == 0)
+ return cir::ZeroAttr::get(builder.getContext(), desiredType);
+
+ const unsigned trailingZeroes = arrayBound - nonzeroLength;
+ if (trailingZeroes >= 8) {
+ if (elements.size() < nonzeroLength)
+ cgm.errorNYI("missing initializer for non-zero element");
+ } else if (elements.size() != arrayBound) {
+ elements.resize(arrayBound, filter);
+
+ if (filter.getType() != commonElementType)
+ cgm.errorNYI(
+ "array filter type should always be the same as element type");
+ }
+
+ SmallVector<mlir::Attribute, 4> eles;
+ eles.reserve(elements.size());
+
+ for (const auto &element : elements)
+ eles.push_back(element);
+
+ return cir::ConstArrayAttr::get(
+ cir::ArrayType::get(builder.getContext(), commonElementType, arrayBound),
+ mlir::ArrayAttr::get(builder.getContext(), eles));
+}
+
//===----------------------------------------------------------------------===//
// ConstantEmitter
//===----------------------------------------------------------------------===//
@@ -271,16 +314,61 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
cgm.getASTContext().getTargetInfo().useFP16ConversionIntrinsics()) {
cgm.errorNYI("ConstExprEmitter::tryEmitPrivate half");
return {};
- } else {
- mlir::Type ty = cgm.convertType(destType);
- assert(mlir::isa<cir::CIRFPTypeInterface>(ty) &&
- "expected floating-point type");
- return cgm.getBuilder().getAttr<cir::FPAttr>(ty, init);
}
+
+ mlir::Type ty = cgm.convertType(destType);
+ assert(mlir::isa<cir::CIRFPTypeInterface>(ty) &&
+ "expected floating-point type");
+ return cgm.getBuilder().getAttr<cir::FPAttr>(ty, init);
}
case APValue::Array: {
- cgm.errorNYI("ConstExprEmitter::tryEmitPrivate array");
- return {};
+ const ArrayType *arrayTy = cgm.getASTContext().getAsArrayType(destType);
+ const QualType arrayElementTy = arrayTy->getElementType();
+ const unsigned numElements = value.getArraySize();
+ const unsigned numInitElts = value.getArrayInitializedElts();
+
+ mlir::Attribute filter;
+ if (value.hasArrayFiller()) {
+ filter =
+ tryEmitPrivate(value.getArrayFiller(), arrayTy->getElementType());
+ if (!filter)
+ return {};
+ }
+
+ SmallVector<mlir::TypedAttr, 16> elements;
+ if (filter && builder.isNullValue(filter))
+ elements.reserve(numInitElts + 1);
+ else
+ elements.reserve(numInitElts);
+
+ mlir::Type commonElementType;
+ for (unsigned i = 0; i < numInitElts; ++i) {
+ const APValue &arrayElement = value.getArrayInitializedElt(i);
+ const mlir::Attribute element =
+ tryEmitPrivateForMemory(arrayElement, arrayElementTy);
+ if (!element)
+ return {};
+
+ const mlir::TypedAttr elementTyped = mlir::cast<mlir::TypedAttr>(element);
+ if (i == 0)
+ commonElementType = elementTyped.getType();
+ else if (elementTyped.getType() != commonElementType) {
+ cgm.errorNYI("ConstExprEmitter::tryEmitPrivate Array without common "
+ "element type");
+ return {};
+ }
+
+ elements.push_back(elementTyped);
+ }
+
+ mlir::TypedAttr typedFilter =
+ llvm::dyn_cast_or_null<mlir::TypedAttr>(filter);
+ if (filter && !typedFilter)
+ cgm.errorNYI("array filter should always be typed");
+
+ mlir::Type desiredType = cgm.convertType(destType);
+ return emitArrayConstant(cgm, desiredType, commonElementType, numElements,
+ elements, typedFilter);
}
case APValue::Vector: {
cgm.errorNYI("ConstExprEmitter::tryEmitPrivate vector");
@@ -290,9 +378,23 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
cgm.errorNYI("ConstExprEmitter::tryEmitPrivate member pointer");
return {};
}
- case APValue::LValue:
- cgm.errorNYI("ConstExprEmitter::tryEmitPrivate lvalue");
+ case APValue::LValue: {
+
+ if (value.getLValueBase()) {
+ cgm.errorNYI("non-null pointer initialization");
+ } else {
+
+ mlir::Type desiredType = cgm.convertType(destType);
+ if (const cir::PointerType ptrType =
+ mlir::dyn_cast<cir::PointerType>(desiredType)) {
+ return builder.getConstPtrAttr(ptrType,
+ value.getLValueOffset().getQuantity());
+ } else {
+ llvm_unreachable("non-pointer variable initialized with a pointer");
+ }
+ }
return {};
+ }
case APValue::Struct:
case APValue::Union:
cgm.errorNYI("ConstExprEmitter::tryEmitPrivate struct or union");
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 0e3e15ca2cadc..c7620a8355b2f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "CIRGenModule.h"
+#include "CIRGenConstantEmitter.h"
#include "CIRGenFunction.h"
#include "clang/AST/ASTContext.h"
@@ -127,7 +128,8 @@ void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,
void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
bool isTentative) {
- mlir::Type type = convertType(vd->getType());
+ const QualType astTy = vd->getType();
+ const mlir::Type type = convertType(vd->getType());
if (clang::IdentifierInfo *identifier = vd->getIdentifier()) {
auto varOp = builder.create<cir::GlobalOp>(getLoc(vd->getSourceRange()),
identifier->getName(), type);
@@ -140,38 +142,8 @@ void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
if (initExpr) {
mlir::Attribute initializer;
if (APValue *value = initDecl->evaluateValue()) {
- switch (value->getKind()) {
- case APValue::Int: {
- if (mlir::isa<cir::BoolType>(type))
- initializer =
- builder.getCIRBoolAttr(value->getInt().getZExtValue());
- else
- initializer = builder.getAttr<cir::IntAttr>(type, value->getInt());
- break;
- }
- case APValue::Float: {
- initializer = builder.getAttr<cir::FPAttr>(type, value->getFloat());
- break;
- }
- case APValue::LValue: {
- if (value->getLValueBase()) {
- errorNYI(initExpr->getSourceRange(),
- "non-null pointer initialization");
- } else {
- if (auto ptrType = mlir::dyn_cast<cir::PointerType>(type)) {
- initializer = builder.getConstPtrAttr(
- ptrType, value->getLValueOffset().getQuantity());
- } else {
- llvm_unreachable(
- "non-pointer variable initialized with a pointer");
- }
- }
- break;
- }
- default:
- errorNYI(initExpr->getSourceRange(), "unsupported initializer kind");
- break;
- }
+ ConstantEmitter emitter(*this);
+ initializer = emitter.tryEmitPrivateForMemory(*value, astTy);
} else {
errorNYI(initExpr->getSourceRange(), "non-constant initializer");
}
diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
index 8e8f7d5b7d7cb..8dfe56b75a47b 100644
--- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
@@ -190,6 +190,115 @@ LogicalResult FPAttr::verify(function_ref<InFlightDiagnostic()> emitError,
return success();
}
+//===----------------------------------------------------------------------===//
+// CIR ConstArrayAttr
+//===----------------------------------------------------------------------===//
+
+LogicalResult
+ConstArrayAttr::verify(function_ref<::mlir::InFlightDiagnostic()> emitError,
+ Type type, Attribute elts, int trailingZerosNum) {
+
+ if (!(mlir::isa<ArrayAttr>(elts) || mlir::isa<StringAttr>(elts)))
+ return emitError() << "constant array expects ArrayAttr or StringAttr";
+
+ if (StringAttr strAttr = mlir::dyn_cast<StringAttr>(elts)) {
+ ArrayType arrayTy = mlir::cast<ArrayType>(type);
+ IntType intTy = mlir::dyn_cast<IntType>(arrayTy.getEltType());
+
+ // TODO: add CIR type for char.
+ if (!intTy || intTy.getWidth() != 8) {
+ emitError() << "constant array element for string literals expects "
+ "!cir.int<u, 8> element type";
+ return failure();
+ }
+ return success();
+ }
+
+ assert(mlir::isa<ArrayAttr>(elts));
+ ArrayAttr arrayAttr = mlir::cast<mlir::ArrayAttr>(elts);
+ ArrayType arrayTy = mlir::cast<ArrayType>(type);
+
+ // Make sure both number of elements and subelement types match type.
+ if (arrayTy.getSize() != arrayAttr.size() + trailingZerosNum)
+ return emitError() << "constant array size should match type size";
+ return success();
+}
+
+Attribute ConstArrayAttr::parse(AsmParser &parser, Type type) {
+ ::mlir::FailureOr<Type> resultTy;
+ ::mlir::FailureOr<Attribute> resultVal;
+ ::llvm::SMLoc loc = parser.getCurrentLocation();
+ (void)loc;
+ // Parse literal '<'
+ if (parser.parseLess())
+ return {};
+
+ // Parse variable 'value'
+ resultVal = FieldParser<Attribute>::parse(parser);
+ if (failed(resultVal)) {
+ parser.emitError(
+ parser.getCurrentLocation(),
+ "failed to parse ConstArrayAttr parameter 'value' which is "
+ "to be a `Attribute`");
+ return {};
+ }
+
+ // ArrayAttrrs have per-element type, not the type of the array...
+ if (mlir::dyn_cast<ArrayAttr>(*resultVal)) {
+ // Array has implicit type: infer from const array type.
+ if (parser.parseOptionalColon().failed()) {
+ resultTy = type;
+ } else { // Array has explicit type: parse it.
+ resultTy = FieldParser<Type>::parse(parser);
+ if (failed(resultTy)) {
+ parser.emitError(
+ parser.getCurrentLocation(),
+ "failed to parse ConstArrayAttr parameter 'type' which is "
+ "to be a `::mlir::Type`");
+ return {};
+ }
+ }
+ } else {
+ assert(mlir::isa<TypedAttr>(*resultVal) && "IDK");
+ auto ta = mlir::cast<TypedAttr>(*resultVal);
+ resultTy = ta.getType();
+ if (mlir::isa<mlir::NoneType>(*resultTy)) {
+ parser.emitError(parser.getCurrentLocation(),
+ "expected type declaration for string literal");
+ return {};
+ }
+ }
+
+ auto zeros = 0;
+ if (parser.parseOptionalComma().succeeded()) {
+ if (parser.parseOptionalKeyword("trailing_zeros").succeeded()) {
+ auto typeSize = mlir::cast<cir::ArrayType>(resultTy.value()).getSize();
+ auto elts = resultVal.value();
+ if (auto str = mlir::dyn_cast<mlir::StringAttr>(elts))
+ zeros = typeSize - str.size();
+ else
+ zeros = typeSize - mlir::cast<mlir::ArrayAttr>(elts).size();
+ } else {
+ return {};
+ }
+ }
+
+ // Parse literal '>'
+ if (parser.parseGreater())
+ return {};
+
+ return parser.getChecked<ConstArrayAttr>(
+ loc, parser.getContext(), resultTy.value(), resultVal.value(), zeros);
+}
+
+void ConstArrayAttr::print(AsmPrinter &printer) const {
+ printer << "<";
+ printer.printStrippedAttrOrType(getElts());
+ if (getTrailingZerosNum())
+ printer << ", trailing_zeros";
+ printer << ">";
+}
+
//===----------------------------------------------------------------------===//
// CIR Dialect
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index d041791770d82..467e6237ef01a 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -149,6 +149,12 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
return success();
}
+ if (isa<cir::ZeroAttr>(attrType)) {
+ if (::mlir::isa<cir::ArrayType>(opType))
+ return success();
+ return op->emitOpError("zero expects struct or array type");
+ }
+
if (mlir::isa<cir::BoolAttr>(attrType)) {
if (!mlir::isa<cir::BoolType>(opType))
return op->emitOpError("result type (")
@@ -166,6 +172,9 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
return success();
}
+ if (mlir::isa<cir::ConstArrayAttr>(attrType))
+ return success();
+
assert(isa<TypedAttr>(attrType) && "What else could we be looking at here?");
return op->emitOpError("global with type ")
<< cast<TypedAttr>(attrType).getType() << " not yet supported";
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 0cd27ecf1a3bd..f0b9986a9efaf 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -113,6 +113,21 @@ static mlir::Value emitToMemory(mlir::ConversionPatternRewriter &rewriter,
return value;
}
+static mlir::Value
+emitCirAttrToMemory(mlir::Operation *parentOp, mlir::Attribute attr,
+ mlir::ConversionPatternRewriter &rewriter,
+ const mlir::TypeConverter *converter,
+ mlir::DataLayout const &dataLayout) {
+
+ mlir::Value loweredValue =
+ lowerCirAttrAsValue(parentOp, attr, rewriter, converter);
+ if (auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr)) {
+ return emitToMemory(rewriter, dataLayout, boolAttr.getType(), loweredValue);
+ }
+
+ return loweredValue;
+}
+
mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage) {
using CIR = cir::GlobalLinkageKind;
using LLVM = mlir::LLVM::Linkage;
@@ -151,14 +166,1...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/131657
More information about the cfe-commits
mailing list