Skip to content

[CIR] Integral types; simple global variables #118743

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 6, 2024
Merged
Changes from all 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
35 changes: 33 additions & 2 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
#define LLVM_CLANG_CIR_DIALECT_IR_CIROPS

include "clang/CIR/Dialect/IR/CIRDialect.td"
include "clang/CIR/Dialect/IR/CIRTypes.td"

include "mlir/IR/BuiltinAttributeInterfaces.td"
include "mlir/IR/EnumAttr.td"
@@ -74,6 +75,35 @@ class LLVMLoweringInfo {
class CIR_Op<string mnemonic, list<Trait> traits = []> :
Op<CIR_Dialect, mnemonic, traits>, LLVMLoweringInfo;

//===----------------------------------------------------------------------===//
// GlobalOp
//===----------------------------------------------------------------------===//

// TODO(CIR): For starters, cir.global has only name and type. The other
// properties of a global variable will be added over time as more of ClangIR
// is upstreamed.

def GlobalOp : CIR_Op<"global"> {
let summary = "Declare or define a global variable";
let description = [{
The `cir.global` operation declares or defines a named global variable.

The backing memory for the variable is allocated statically and is
described by the type of the variable.
}];

let arguments = (ins SymbolNameAttr:$sym_name, TypeAttr:$sym_type);

let assemblyFormat = [{ $sym_name `:` $sym_type attr-dict }];

let skipDefaultBuilders = 1;

let builders = [OpBuilder<(ins "llvm::StringRef":$sym_name,
"mlir::Type":$sym_type)>];

let hasVerifier = 1;
}

//===----------------------------------------------------------------------===//
// FuncOp
//===----------------------------------------------------------------------===//
@@ -85,14 +115,15 @@ class CIR_Op<string mnemonic, list<Trait> traits = []> :
def FuncOp : CIR_Op<"func"> {
let summary = "Declare or define a function";
let description = [{
... lots of text to be added later ...
The `cir.func` operation defines a function, similar to the `mlir::FuncOp`
built-in.
}];

let arguments = (ins SymbolNameAttr:$sym_name);

let skipDefaultBuilders = 1;

let builders = [OpBuilder<(ins "llvm::StringRef":$name)>];
let builders = [OpBuilder<(ins "llvm::StringRef":$sym_name)>];

let hasCustomAssemblyFormat = 1;
let hasVerifier = 1;
27 changes: 27 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRTypes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//===----------------------------------------------------------------------===//
//
// 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 declares the types in the CIR dialect.
//
//===----------------------------------------------------------------------===//

#ifndef MLIR_DIALECT_CIR_IR_CIRTYPES_H_
#define MLIR_DIALECT_CIR_IR_CIRTYPES_H_

#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/Types.h"
#include "mlir/Interfaces/DataLayoutInterfaces.h"

//===----------------------------------------------------------------------===//
// CIR Dialect Tablegen'd Types
//===----------------------------------------------------------------------===//

#define GET_TYPEDEF_CLASSES
#include "clang/CIR/Dialect/IR/CIROpsTypes.h.inc"

#endif // MLIR_DIALECT_CIR_IR_CIRTYPES_H_
132 changes: 132 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRTypes.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
//===- CIRTypes.td - CIR dialect types ---------------------*- tablegen -*-===//
//
// 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 declares the CIR dialect types.
//
//===----------------------------------------------------------------------===//

#ifndef MLIR_CIR_DIALECT_CIR_TYPES
#define MLIR_CIR_DIALECT_CIR_TYPES

include "clang/CIR/Dialect/IR/CIRDialect.td"
include "mlir/Interfaces/DataLayoutInterfaces.td"
include "mlir/IR/AttrTypeBase.td"

//===----------------------------------------------------------------------===//
// CIR Types
//===----------------------------------------------------------------------===//

class CIR_Type<string name, string typeMnemonic, list<Trait> traits = [],
string baseCppClass = "::mlir::Type">
: TypeDef<CIR_Dialect, name, traits, baseCppClass> {
let mnemonic = typeMnemonic;
}

//===----------------------------------------------------------------------===//
// IntType
//===----------------------------------------------------------------------===//

def CIR_IntType : CIR_Type<"Int", "int",
[DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {
let summary = "Integer type with arbitrary precision up to a fixed limit";
let description = [{
CIR type that represents integer types with arbitrary precision, including
standard integral types such as `int` and `long`, extended integral types
such as `__int128`, and arbitrary width types such as `_BitInt(n)`.

Those integer types that are directly available in C/C++ standard are called
primitive integer types. Said types are: `signed char`, `short`, `int`,
`long`, `long long`, and their unsigned variations.
}];
let parameters = (ins "unsigned":$width, "bool":$isSigned);
let hasCustomAssemblyFormat = 1;
let extraClassDeclaration = [{
/// Return true if this is a signed integer type.
bool isSigned() const { return getIsSigned(); }
/// Return true if this is an unsigned integer type.
bool isUnsigned() const { return !getIsSigned(); }
/// Return type alias.
std::string getAlias() const {
return (isSigned() ? 's' : 'u') + std::to_string(getWidth()) + 'i';
}
/// Return true if this is a primitive integer type (i.e. signed or unsigned
/// integer types whose bit width is 8, 16, 32, or 64).
bool isPrimitive() const {
return isValidPrimitiveIntBitwidth(getWidth());
}
bool isSignedPrimitive() const {
return isPrimitive() && isSigned();
}

/// Returns a minimum bitwidth of cir::IntType
static unsigned minBitwidth() { return 1; }
/// Returns a maximum bitwidth of cir::IntType
static unsigned maxBitwidth() { return 128; }

/// Returns true if cir::IntType that represents a primitive integer type
/// can be constructed from the provided bitwidth.
static bool isValidPrimitiveIntBitwidth(unsigned width) {
return width == 8 || width == 16 || width == 32 || width == 64;
}
}];
let genVerifyDecl = 1;
}

// Constraints

// Unsigned integer type of a specific width.
class UInt<int width>
: Type<And<[
CPred<"::mlir::isa<::cir::IntType>($_self)">,
CPred<"::mlir::cast<::cir::IntType>($_self).isUnsigned()">,
CPred<"::mlir::cast<::cir::IntType>($_self).getWidth() == " # width>
]>, width # "-bit unsigned integer", "::cir::IntType">,
BuildableType<
"cir::IntType::get($_builder.getContext(), "
# width # ", /*isSigned=*/false)"> {
int bitwidth = width;
}

def UInt1 : UInt<1>;
def UInt8 : UInt<8>;
def UInt16 : UInt<16>;
def UInt32 : UInt<32>;
def UInt64 : UInt<64>;

// Signed integer type of a specific width.
class SInt<int width>
: Type<And<[
CPred<"::mlir::isa<::cir::IntType>($_self)">,
CPred<"::mlir::cast<::cir::IntType>($_self).isSigned()">,
CPred<"::mlir::cast<::cir::IntType>($_self).getWidth() == " # width>
]>, width # "-bit signed integer", "::cir::IntType">,
BuildableType<
"cir::IntType::get($_builder.getContext(), "
# width # ", /*isSigned=*/true)"> {
int bitwidth = width;
}

def SInt1 : SInt<1>;
def SInt8 : SInt<8>;
def SInt16 : SInt<16>;
def SInt32 : SInt<32>;
def SInt64 : SInt<64>;

def PrimitiveUInt
: AnyTypeOf<[UInt8, UInt16, UInt32, UInt64], "primitive unsigned int",
"::cir::IntType">;

def PrimitiveSInt
: AnyTypeOf<[SInt8, SInt16, SInt32, SInt64], "primitive signed int",
"::cir::IntType">;

def PrimitiveInt
: AnyTypeOf<[UInt8, UInt16, UInt32, UInt64, SInt8, SInt16, SInt32, SInt64],
"primitive int", "::cir::IntType">;

#endif // MLIR_CIR_DIALECT_CIR_TYPES
58 changes: 33 additions & 25 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context,
DiagnosticsEngine &diags)
: builder(&context), astCtx(astctx), langOpts(astctx.getLangOpts()),
theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&context))},
diags(diags), target(astCtx.getTargetInfo()) {}
diags(diags), target(astCtx.getTargetInfo()), genTypes(*this) {}

mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) {
assert(cLoc.isValid() && "expected valid source location");
@@ -67,7 +67,8 @@ void CIRGenModule::emitGlobal(clang::GlobalDecl gd) {
return;
}
} else {
errorNYI(global->getSourceRange(), "global variable declaration");
assert(cast<VarDecl>(global)->isFileVarDecl() &&
"Cannot emit local var decl as global");
}

// TODO(CIR): Defer emitting some global definitions until later
@@ -77,9 +78,27 @@ void CIRGenModule::emitGlobal(clang::GlobalDecl gd) {
void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,
mlir::Operation *op) {
auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());
auto funcOp = builder.create<cir::FuncOp>(
getLoc(funcDecl->getSourceRange()), funcDecl->getIdentifier()->getName());
theModule.push_back(funcOp);
if (clang::IdentifierInfo *identifier = funcDecl->getIdentifier()) {
auto funcOp = builder.create<cir::FuncOp>(
getLoc(funcDecl->getSourceRange()), identifier->getName());
theModule.push_back(funcOp);
} else {
errorNYI(funcDecl->getSourceRange().getBegin(),
"function definition with a non-identifier for a name");
}
}

void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
bool isTentative) {
mlir::Type type = getTypes().convertType(vd->getType());
if (clang::IdentifierInfo *identifier = vd->getIdentifier()) {
auto varOp = builder.create<cir::GlobalOp>(getLoc(vd->getSourceRange()),
identifier->getName(), type);
theModule.push_back(varOp);
} else {
errorNYI(vd->getSourceRange().getBegin(),
"variable definition with a non-identifier for a name");
}
}

void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd,
@@ -103,6 +122,9 @@ void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd,
return;
}

if (const auto *vd = dyn_cast<VarDecl>(decl))
return emitGlobalVarDefinition(vd, !vd->hasDefinition());

llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");
}

@@ -126,13 +148,13 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
emitGlobal(fd);
break;
}
}
}

DiagnosticBuilder CIRGenModule::errorNYI(llvm::StringRef feature) {
unsigned diagID = diags.getCustomDiagID(
DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
return diags.Report(diagID) << feature;
case Decl::Var: {
auto *vd = cast<VarDecl>(decl);
emitGlobal(vd);
break;
}
}
}

DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
@@ -142,21 +164,7 @@ DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
return diags.Report(loc, diagID) << feature;
}

DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
llvm::StringRef feature,
llvm::StringRef name) {
unsigned diagID = diags.getCustomDiagID(
DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0: %1");
return diags.Report(loc, diagID) << feature << name;
}

DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
llvm::StringRef feature) {
return errorNYI(loc.getBegin(), feature) << loc;
}

DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
llvm::StringRef feature,
llvm::StringRef name) {
return errorNYI(loc.getBegin(), feature, name) << loc;
}
33 changes: 26 additions & 7 deletions clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
@@ -14,23 +14,22 @@
#define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H

#include "CIRGenTypeCache.h"
#include "CIRGenTypes.h"

#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/MLIRContext.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringRef.h"

namespace clang {
class ASTContext;
class CodeGenOptions;
class Decl;
class DiagnosticBuilder;
class DiagnosticsEngine;
class GlobalDecl;
class LangOptions;
class SourceLocation;
class SourceRange;
class TargetInfo;
class VarDecl;

namespace CIRGen {

@@ -64,8 +63,13 @@ class CIRGenModule : public CIRGenTypeCache {

const clang::TargetInfo &target;

CIRGenTypes genTypes;

public:
mlir::ModuleOp getModule() const { return theModule; }
mlir::OpBuilder &getBuilder() { return builder; }
clang::ASTContext &getASTContext() const { return astCtx; }
CIRGenTypes &getTypes() { return genTypes; }

/// Helpers to convert the presumed location of Clang's SourceLocation to an
/// MLIR Location.
@@ -81,13 +85,28 @@ class CIRGenModule : public CIRGenTypeCache {
void emitGlobalDefinition(clang::GlobalDecl gd,
mlir::Operation *op = nullptr);
void emitGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op);
void emitGlobalVarDefinition(const clang::VarDecl *vd,
bool isTentative = false);

/// Helpers to emit "not yet implemented" error diagnostics
DiagnosticBuilder errorNYI(llvm::StringRef);
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef);
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef, llvm::StringRef);

template <typename T>
DiagnosticBuilder errorNYI(SourceLocation loc, llvm::StringRef feature,
const T &name) {
unsigned diagID =
diags.getCustomDiagID(DiagnosticsEngine::Error,
"ClangIR code gen Not Yet Implemented: %0: %1");
return diags.Report(loc, diagID) << feature << name;
}

DiagnosticBuilder errorNYI(SourceRange, llvm::StringRef);
DiagnosticBuilder errorNYI(SourceRange, llvm::StringRef, llvm::StringRef);

template <typename T>
DiagnosticBuilder errorNYI(SourceRange loc, llvm::StringRef feature,
const T &name) {
return errorNYI(loc.getBegin(), feature, name) << loc;
}
};
} // namespace CIRGen

87 changes: 87 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenTypes.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include "CIRGenTypes.h"

#include "CIRGenModule.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"

using namespace clang;
using namespace clang::CIRGen;

CIRGenTypes::CIRGenTypes(CIRGenModule &genModule)
: cgm(genModule), context(genModule.getASTContext()) {}

CIRGenTypes::~CIRGenTypes() {}

mlir::Type CIRGenTypes::convertType(QualType type) {
type = context.getCanonicalType(type);
const Type *ty = type.getTypePtr();

// For types that haven't been implemented yet or are otherwise unsupported,
// report an error and return 'int'.

mlir::Type resultType = nullptr;
switch (ty->getTypeClass()) {
case Type::Builtin: {
switch (cast<BuiltinType>(ty)->getKind()) {
// Signed types.
case BuiltinType::Char_S:
case BuiltinType::Int:
case BuiltinType::Int128:
case BuiltinType::Long:
case BuiltinType::LongLong:
case BuiltinType::SChar:
case BuiltinType::Short:
case BuiltinType::WChar_S:
resultType = cir::IntType::get(cgm.getBuilder().getContext(),
context.getTypeSize(ty),
/*isSigned=*/true);
break;
// Unsigned types.
case BuiltinType::Char8:
case BuiltinType::Char16:
case BuiltinType::Char32:
case BuiltinType::Char_U:
case BuiltinType::UChar:
case BuiltinType::UInt:
case BuiltinType::UInt128:
case BuiltinType::ULong:
case BuiltinType::ULongLong:
case BuiltinType::UShort:
case BuiltinType::WChar_U:
resultType = cir::IntType::get(cgm.getBuilder().getContext(),
context.getTypeSize(ty),
/*isSigned=*/false);
break;
default:
cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
resultType = cir::IntType::get(cgm.getBuilder().getContext(), 32,
/*isSigned=*/true);
break;
}
break;
}
case Type::BitInt: {
const auto *bitIntTy = cast<BitIntType>(type);
if (bitIntTy->getNumBits() > cir::IntType::maxBitwidth()) {
cgm.errorNYI(SourceLocation(), "large _BitInt type", type);
resultType = cir::IntType::get(cgm.getBuilder().getContext(), 32,
/*isSigned=*/true);
} else {
resultType =
cir::IntType::get(cgm.getBuilder().getContext(),
bitIntTy->getNumBits(), bitIntTy->isSigned());
}
break;
}
default:
cgm.errorNYI(SourceLocation(), "processing of type", type);
resultType =
cir::IntType::get(cgm.getBuilder().getContext(), 32, /*isSigned=*/true);
break;
}

assert(resultType && "Type conversion not yet implemented");

return resultType;
}
47 changes: 47 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenTypes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//===--- CIRGenTypes.h - Type translation for CIR CodeGen -------*- C++ -*-===//
//
// 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 is the code that handles AST -> CIR type lowering.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H
#define LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H

#include "clang/CIR/Dialect/IR/CIRTypes.h"

namespace clang {
class ASTContext;
class QualType;
} // namespace clang

namespace mlir {
class Type;
}

namespace clang::CIRGen {

class CIRGenModule;

/// This class organizes the cross-module state that is used while lowering
/// AST types to CIR types.
class CIRGenTypes {
CIRGenModule &cgm;
clang::ASTContext &context;

public:
CIRGenTypes(CIRGenModule &cgm);
~CIRGenTypes();

/// Convert a Clang type into a mlir::Type.
mlir::Type convertType(clang::QualType type);
};

} // namespace clang::CIRGen

#endif
1 change: 1 addition & 0 deletions clang/lib/CIR/CodeGen/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
add_clang_library(clangCIR
CIRGenerator.cpp
CIRGenModule.cpp
CIRGenTypes.cpp

DEPENDS
MLIRCIR
18 changes: 18 additions & 0 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
@@ -32,6 +32,22 @@ void cir::CIRDialect::initialize() {
>();
}

//===----------------------------------------------------------------------===//
// GlobalOp
//===----------------------------------------------------------------------===//

// TODO(CIR): The properties of global variables that require verification
// haven't been implemented yet.
mlir::LogicalResult cir::GlobalOp::verify() { return success(); }

void cir::GlobalOp::build(OpBuilder &odsBuilder, OperationState &odsState,
llvm::StringRef sym_name, mlir::Type sym_type) {
odsState.addAttribute(getSymNameAttrName(odsState.name),
odsBuilder.getStringAttr(sym_name));
odsState.addAttribute(getSymTypeAttrName(odsState.name),
mlir::TypeAttr::get(sym_type));
}

//===----------------------------------------------------------------------===//
// FuncOp
//===----------------------------------------------------------------------===//
@@ -56,6 +72,8 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
p.printSymbolName(getSymName());
}

// TODO(CIR): The properties of functions that require verification haven't
// been implemented yet.
mlir::LogicalResult cir::FuncOp::verify() { return success(); }

//===----------------------------------------------------------------------===//
120 changes: 116 additions & 4 deletions clang/lib/CIR/Dialect/IR/CIRTypes.cpp
Original file line number Diff line number Diff line change
@@ -10,7 +10,18 @@
//
//===----------------------------------------------------------------------===//

#include "clang/CIR/Dialect/IR/CIRTypes.h"

#include "mlir/IR/DialectImplementation.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "llvm/ADT/TypeSwitch.h"

//===----------------------------------------------------------------------===//
// Get autogenerated stuff
//===----------------------------------------------------------------------===//

#define GET_TYPEDEF_CLASSES
#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"

using namespace mlir;
using namespace cir;
@@ -20,18 +31,119 @@ using namespace cir;
//===----------------------------------------------------------------------===//

Type CIRDialect::parseType(DialectAsmParser &parser) const {
// No types yet to parse
return Type{};
llvm::SMLoc typeLoc = parser.getCurrentLocation();
llvm::StringRef mnemonic;
Type genType;

// Try to parse as a tablegen'd type.
OptionalParseResult parseResult =
generatedTypeParser(parser, &mnemonic, genType);
if (parseResult.has_value())
return genType;

// TODO(CIR) Attempt to parse as a raw C++ type.
parser.emitError(typeLoc) << "unknown CIR type: " << mnemonic;
return Type();
}

void CIRDialect::printType(Type type, DialectAsmPrinter &os) const {
// No types yet to print
// Try to print as a tablegen'd type.
if (generatedTypePrinter(type, os).succeeded())
return;

// TODO(CIR) Attempt to print as a raw C++ type.
llvm::report_fatal_error("printer is missing a handler for this type");
}

//===----------------------------------------------------------------------===//
// IntType Definitions
//===----------------------------------------------------------------------===//

Type IntType::parse(mlir::AsmParser &parser) {
mlir::MLIRContext *context = parser.getBuilder().getContext();
llvm::SMLoc loc = parser.getCurrentLocation();
bool isSigned;
unsigned width;

if (parser.parseLess())
return {};

// Fetch integer sign.
llvm::StringRef sign;
if (parser.parseKeyword(&sign))
return {};
if (sign == "s")
isSigned = true;
else if (sign == "u")
isSigned = false;
else {
parser.emitError(loc, "expected 's' or 'u'");
return {};
}

if (parser.parseComma())
return {};

// Fetch integer size.
if (parser.parseInteger(width))
return {};
if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) {
parser.emitError(loc, "expected integer width to be from ")
<< IntType::minBitwidth() << " up to " << IntType::maxBitwidth();
return {};
}

if (parser.parseGreater())
return {};

return IntType::get(context, width, isSigned);
}

void IntType::print(mlir::AsmPrinter &printer) const {
char sign = isSigned() ? 's' : 'u';
printer << '<' << sign << ", " << getWidth() << '>';
}

llvm::TypeSize
IntType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
mlir::DataLayoutEntryListRef params) const {
return llvm::TypeSize::getFixed(getWidth());
}

uint64_t IntType::getABIAlignment(const mlir::DataLayout &dataLayout,
mlir::DataLayoutEntryListRef params) const {
return (uint64_t)(getWidth() / 8);
}

uint64_t
IntType::getPreferredAlignment(const ::mlir::DataLayout &dataLayout,
::mlir::DataLayoutEntryListRef params) const {
return (uint64_t)(getWidth() / 8);
}

mlir::LogicalResult
IntType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
unsigned width, bool isSigned) {
if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) {
emitError() << "IntType only supports widths from "
<< IntType::minBitwidth() << " up to "
<< IntType::maxBitwidth();
return mlir::failure();
}
return mlir::success();
}

//===----------------------------------------------------------------------===//
// CIR Dialect
//===----------------------------------------------------------------------===//

void CIRDialect::registerTypes() {
// No types yet to register
// Register tablegen'd types.
addTypes<
#define GET_TYPEDEF_LIST
#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"
>();

// Register raw C++ types.
// TODO(CIR) addTypes<StructType>();
}
4 changes: 4 additions & 0 deletions clang/lib/CIR/Dialect/IR/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -8,4 +8,8 @@ add_clang_library(MLIRCIR

LINK_LIBS PUBLIC
MLIRIR
MLIRDLTIDialect
MLIRDataLayoutInterfaces
MLIRFuncDialect
clangAST
)
59 changes: 59 additions & 0 deletions clang/test/CIR/global-var-simple.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Global variables of intergal types
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s

char c;
// CHECK: cir.global @c : !cir.int<s, 8>

signed char sc;
// CHECK: cir.global @sc : !cir.int<s, 8>

unsigned char uc;
// CHECK: cir.global @uc : !cir.int<u, 8>

short ss;
// CHECK: cir.global @ss : !cir.int<s, 16>

unsigned short us;
// CHECK: cir.global @us : !cir.int<u, 16>

int si;
// CHECK: cir.global @si : !cir.int<s, 32>

unsigned ui;
// CHECK: cir.global @ui : !cir.int<u, 32>

long sl;
// CHECK: cir.global @sl : !cir.int<s, 64>

unsigned long ul;
// CHECK: cir.global @ul : !cir.int<u, 64>

long long sll;
// CHECK: cir.global @sll : !cir.int<s, 64>

unsigned long long ull;
// CHECK: cir.global @ull : !cir.int<u, 64>

__int128 s128;
// CHECK: cir.global @s128 : !cir.int<s, 128>

unsigned __int128 u128;
// CHECK: cir.global @u128 : !cir.int<u, 128>

wchar_t wc;
// CHECK: cir.global @wc : !cir.int<s, 32>

char8_t c8;
// CHECK: cir.global @c8 : !cir.int<u, 8>

char16_t c16;
// CHECK: cir.global @c16 : !cir.int<u, 16>

char32_t c32;
// CHECK: cir.global @c32 : !cir.int<u, 32>

_BitInt(20) sb20;
// CHECK: cir.global @sb20 : !cir.int<s, 20>

unsigned _BitInt(48) ub48;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would also like a test for 'absurdly large bitint' here, since they can be up to ~1.9 million bits in length.

// CHECK: cir.global @ub48 : !cir.int<u, 48>