-
Notifications
You must be signed in to change notification settings - Fork 14.6k
[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
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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` | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. |
||||||
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; | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
//===- CIRTypes.h - MLIR CIR Types ------------------------------*- C++ -*-===// | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per e2c3d16, we should remove the name and description and C++ from this line now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
// | ||
// 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_ |
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. | ||
erichkeane marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}]; | ||
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; } | ||
erichkeane marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/// 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 |
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 | ||
|
@@ -82,6 +83,14 @@ void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd, | |
theModule.push_back(funcOp); | ||
} | ||
|
||
void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd, | ||
bool isTentative) { | ||
mlir::Type type = getTypes().convertType(vd->getType()); | ||
auto varOp = builder.create<cir::GlobalOp>( | ||
getLoc(vd->getSourceRange()), vd->getIdentifier()->getName(), type); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. The code checks |
||
theModule.push_back(varOp); | ||
} | ||
|
||
void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd, | ||
mlir::Operation *op) { | ||
const auto *decl = cast<ValueDecl>(gd.getDecl()); | ||
|
@@ -103,6 +112,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 +138,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 +154,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; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: the indentation seems off here (which is probably my fault from the namespace renaming)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is new code. It wasn't your fault. The problem is that a couple tab characters made it in there, and VC Code expanded the tabs to a different width than GitHub. I'll fix that. Thanks for noticing that.