Files
clang-p2996/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
David Olsen 8e32959331 [CIR] Upstream initial attribute support (#121069)
Upstream several ClangIR-specific MLIR attributes, in particular
attributes for integer, floating-point, and null pointer constants.
These are the first ClangIR attributes to be upstreamed, so
infrastructure changes are included, such as the table-gen file
`CIRAttrs.td`.

Attributes can be used as the initial values for global variables. The
existing automated test global-var-simple.cpp includes initial values
for some of the global variables in the test.
2024-12-28 14:02:15 -08:00

203 lines
6.5 KiB
C++

//===- CIRAttrs.cpp - MLIR CIR Attributes ---------------------------------===//
//
// 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 file defines the attributes in the CIR dialect.
//
//===----------------------------------------------------------------------===//
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "mlir/IR/DialectImplementation.h"
#include "llvm/ADT/TypeSwitch.h"
static void printFloatLiteral(mlir::AsmPrinter &p, llvm::APFloat value,
mlir::Type ty);
static mlir::ParseResult
parseFloatLiteral(mlir::AsmParser &parser,
mlir::FailureOr<llvm::APFloat> &value,
cir::CIRFPTypeInterface fpType);
static mlir::ParseResult parseConstPtr(mlir::AsmParser &parser,
mlir::IntegerAttr &value);
static void printConstPtr(mlir::AsmPrinter &p, mlir::IntegerAttr value);
#define GET_ATTRDEF_CLASSES
#include "clang/CIR/Dialect/IR/CIROpsAttributes.cpp.inc"
using namespace mlir;
using namespace cir;
//===----------------------------------------------------------------------===//
// General CIR parsing / printing
//===----------------------------------------------------------------------===//
Attribute CIRDialect::parseAttribute(DialectAsmParser &parser,
Type type) const {
llvm::SMLoc typeLoc = parser.getCurrentLocation();
llvm::StringRef mnemonic;
Attribute genAttr;
OptionalParseResult parseResult =
generatedAttributeParser(parser, &mnemonic, type, genAttr);
if (parseResult.has_value())
return genAttr;
parser.emitError(typeLoc, "unknown attribute in CIR dialect");
return Attribute();
}
void CIRDialect::printAttribute(Attribute attr, DialectAsmPrinter &os) const {
if (failed(generatedAttributePrinter(attr, os)))
llvm_unreachable("unexpected CIR type kind");
}
//===----------------------------------------------------------------------===//
// ConstPtrAttr definitions
//===----------------------------------------------------------------------===//
// TODO(CIR): Consider encoding the null value differently and use conditional
// assembly format instead of custom parsing/printing.
static ParseResult parseConstPtr(AsmParser &parser, mlir::IntegerAttr &value) {
if (parser.parseOptionalKeyword("null").succeeded()) {
value = mlir::IntegerAttr::get(
mlir::IntegerType::get(parser.getContext(), 64), 0);
return success();
}
return parser.parseAttribute(value);
}
static void printConstPtr(AsmPrinter &p, mlir::IntegerAttr value) {
if (!value.getInt())
p << "null";
else
p << value;
}
//===----------------------------------------------------------------------===//
// IntAttr definitions
//===----------------------------------------------------------------------===//
Attribute IntAttr::parse(AsmParser &parser, Type odsType) {
mlir::APInt apValue;
if (!mlir::isa<IntType>(odsType))
return {};
auto type = mlir::cast<IntType>(odsType);
// Consume the '<' symbol.
if (parser.parseLess())
return {};
// Fetch arbitrary precision integer value.
if (type.isSigned()) {
int64_t value = 0;
if (parser.parseInteger(value)) {
parser.emitError(parser.getCurrentLocation(), "expected integer value");
} else {
apValue = mlir::APInt(type.getWidth(), value, type.isSigned(),
/*implicitTrunc=*/true);
if (apValue.getSExtValue() != value)
parser.emitError(parser.getCurrentLocation(),
"integer value too large for the given type");
}
} else {
uint64_t value = 0;
if (parser.parseInteger(value)) {
parser.emitError(parser.getCurrentLocation(), "expected integer value");
} else {
apValue = mlir::APInt(type.getWidth(), value, type.isSigned(),
/*implicitTrunc=*/true);
if (apValue.getZExtValue() != value)
parser.emitError(parser.getCurrentLocation(),
"integer value too large for the given type");
}
}
// Consume the '>' symbol.
if (parser.parseGreater())
return {};
return IntAttr::get(type, apValue);
}
void IntAttr::print(AsmPrinter &printer) const {
auto type = mlir::cast<IntType>(getType());
printer << '<';
if (type.isSigned())
printer << getSInt();
else
printer << getUInt();
printer << '>';
}
LogicalResult IntAttr::verify(function_ref<InFlightDiagnostic()> emitError,
Type type, APInt value) {
if (!mlir::isa<IntType>(type)) {
emitError() << "expected 'simple.int' type";
return failure();
}
auto intType = mlir::cast<IntType>(type);
if (value.getBitWidth() != intType.getWidth()) {
emitError() << "type and value bitwidth mismatch: " << intType.getWidth()
<< " != " << value.getBitWidth();
return failure();
}
return success();
}
//===----------------------------------------------------------------------===//
// FPAttr definitions
//===----------------------------------------------------------------------===//
static void printFloatLiteral(AsmPrinter &p, APFloat value, Type ty) {
p << value;
}
static ParseResult parseFloatLiteral(AsmParser &parser,
FailureOr<APFloat> &value,
CIRFPTypeInterface fpType) {
APFloat parsedValue(0.0);
if (parser.parseFloat(fpType.getFloatSemantics(), parsedValue))
return failure();
value.emplace(parsedValue);
return success();
}
FPAttr FPAttr::getZero(Type type) {
return get(type,
APFloat::getZero(
mlir::cast<CIRFPTypeInterface>(type).getFloatSemantics()));
}
LogicalResult FPAttr::verify(function_ref<InFlightDiagnostic()> emitError,
CIRFPTypeInterface fpType, APFloat value) {
if (APFloat::SemanticsToEnum(fpType.getFloatSemantics()) !=
APFloat::SemanticsToEnum(value.getSemantics())) {
emitError() << "floating-point semantics mismatch";
return failure();
}
return success();
}
//===----------------------------------------------------------------------===//
// CIR Dialect
//===----------------------------------------------------------------------===//
void CIRDialect::registerAttributes() {
addAttributes<
#define GET_ATTRDEF_LIST
#include "clang/CIR/Dialect/IR/CIROpsAttributes.cpp.inc"
>();
}