To make rebasing the incubator project easier, we've been trying to
place upstreamed code in the same order in which it appears in the
incubator project. However, while the upstream implementation is still
relatively sparse, it is often difficult to find points of reference for
placement of new declarations. To help with that, I refactored
CIRGenFunction.h in the incubator to put all the emit* functions in one
place and sort them alphabetically.
This change reorganizes the upstream CIRGenFunction.h to match the new
incubator ordering.
Lowering of int-to-bool casts had been left as NYI because the incubator
implemented it by lowering to cir.cmp, which hasn't been upstreamed yet,
but there is no reason this cast can't be lowered directly to LLVM's
compare operation when we're lowering directly to the LLVM dialect.
This change lowers the cast directly to an LLVM compare to zero.
Alloca operations were being emitted into the entry block of the current
function unconditionally, even if the variable they represented was
declared in a different scope. This change upstreams the code for
handling
insertion of the alloca into the proper lexcial scope. It also adds a
CIR-to-CIR transformation to hoist allocas to the function entry block,
which is necessary to produce the expected LLVM IR during lowering.
This patch adds upstreams support for BinOp including lvalue
assignments. Note that this does not include ternary ops,
BinOpOverflowOp, pointer arithmetic, ShiftOp and SelectOp which are
required for logical binary operators.
---------
Co-authored-by: Morris Hafner <mhafner@nvidia.com>
Co-authored-by: Andy Kaylor <akaylor@nvidia.com>
This change adds support for empty for-loops. This will be the
infrastructre needed for complete for loops, but that depends on compare
operations, which have not been upstreamed yet.
Unary ops had previously been omitted from the list of ops handled in
the CIRCanonicalizePass. Although the incubator code doesn't use them
directly, the mlir folding code does.
This change enables folding of unary ops by adding them to the list.
Upstream the parts of class `CIRGenFunction::LexicalScope` that
implement function return values. There is a bit of other functionality
in here, such as the implicit `cir.yield` at the end of a non-function
scope, but this is mostly about function returns.
The parts of `LexicalScope` that handle calling destructors, switch
statements, ternary expressions, and exception handling still need to be
upstreamed.
There is a change in the generated ClangIR (which is why many of the
tests needed updating). Return values are stored in the
compiler-generated variable `__retval` rather than being passed to the
`cir.return` op directly. But there should be no change in the behavior
of the generated code.
This change introduces the cir-canonicalize pass. This is a simple
cir-to-cir transformation that eliminates empty scopes and redundant
branches. It will be expanded in future changes to simplify other
redundant instruction sequences.
MLIR verification and mlir-specific command-line option handling is also
introduced here.
This patch upstreams ClangIR's CastOp with the following exceptions:
- No Fixed/FP conversions
- No casts between value categories
- No complex casts
- No array_to_ptrdecay
- No address_space
- No casts involving record types (member pointers, base/derived casts)
- No casts specific to ObjC or OpenCL
---------
Co-authored-by: Morris Hafner <mhafner@nvidia.com>
Co-authored-by: Erich Keane <ekeane@nvidia.com>
This adds support for emitting ClangIR for statements whose value is
ignored. The test case being added (CIR/CodeGen/basic.c) tests a few
more things. The "f1" test case is the only part that's immediately
relevant to this change, but the other cases were part of the same test
in the incubator and they are supported so I brought in the entire test.
The ClangIR CFG has to be flat before it can be lowered to LLVM IR. That
is, there can be no nested regions and all blocks in a region must
belong to the parent region. Currently only cir.scope operations violate
these rules, so the initial implementation of the cir-flatten-cfg pass
only has to transform scope operations.
GCC, unlike clang, issues a warning when one virtual function is
overridden in a derived class but one or more other virtual functions
with the same name and different signature from a base class are not
overridden. This leads to many warnings in the MLIR and ClangIR code
when using the OpenConversionPattern<>::matchAndRewrite() function in
the ordinary way. The "hiding" behavior is what we want, so we're just
disabling the warning here.
Local variable initialization was previously being ignored. This change
adds support for initialization of scalar variables with constant values
and introduces the constant emitter framework.
This change implements variable linkage types in ClangIR except for
common linkage which requires Comdat support.
---------
Co-authored-by: Morris Hafner <mhafner@nvidia.com>
Co-authored-by: Henrich Lauko <xlauko@mail.muni.cz>
Previous CIR commits have introduced a few warnings. This change fixes
those.
There are still warnings present when building with GCC because GCC
warns about virtual functions being hidden in the mlir::OpConversion
classes. A separate discussion will be required to decide what should be
done about those.
The previously upstreamed lowering from ClangIR to LLVM IR diverged from
the incubator implementation, but when the incubator was updated to
incorporate these changes some issues arose which require the upstream
implementation to be modified to re-align with the incubator.
First, in the earlier upstream implementation a CIRAttrVisitor class was
introduced with the intention that an mlir-tblgen based extension would
be created to automatically add all CIR attributes to the visitor. When
I proposed this in mlir-tblgen a reviewer suggested that what I wanted
could be better accomplished with TypeSwitch.
See https://github.com/llvm/llvm-project/pull/126332
This was done in the incubator, and here I am bringing that
implementation upstream.
The other issue was that the global op initialization in the incubator
had more cases than I had accounted for in my previous upstream
refactoring. I did still refactor the incubator code, but not in quite
the same way as the upstream code. This change re-aligns the two.
When a C or C++ function has a return type of `void`, the function type
is now represented in MLIR as having no return type rather than having a
return type of `!cir.void`. This avoids breaking MLIR invariants that
require the number of return types and the number of return values to
match.
Change the assembly format for `cir::FuncType` from having a leading
return type to having a trailing return type. In other words, change
```
!cir.func<!returnType (!argTypes)>
```
to
```
!cir.func<(!argTypes) -> !returnType)>
```
Unless the function returns `void`, in which case change
```
!cir.func<!cir.void (!argTypes)>
```
to
```
!cir.func<(!argTypes)>
```
In #128754, `DataLayoutTypeInterface` was changed to give
`getPreferredAlignment` a default implemention. As a result, table-gen
no longer declared `getPreferredAlignment` when defining a class that
contained `[DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]` in
the table-gen definition. That means all of the definitions in
`CIRTypes.cpp`, such as `PointerType::getPreferredAligment`, were
compilation errors.
Delete all the definitions of `getPreferredAlignment`. I verified that
the default implementation does the exact same thing as the explicit
overrides that are being deleted.
Support the type `bool` and the literals `true` and `false`. Add the
type `cir::BoolType` and the attribute `cir::BoolAttr` to ClangIR. Add
code in all the necessary places in ClangIR CodeGen to handle and to
recognize the type and the attribute.
Add test cases to existing tests func-simple.cpp and
global-var-simple.cpp.
We need to be able to read in and parse files using the ClangIR dialect
in order to test this part of the functionality.
This change adds the minimum cir-opt tool needed to read and parse cir
files and write them back to text. This tool will later be extended to
add features for lowering from CIR to other MLIR dialects and to run CIR
passes as they are upstreamed.
Enable ClangIR generation for very simple functions. The functions have
to return `void` or an integral type, contain only compound statements
or `return` statements, and `return` statement expressions can only be
integral literals of the correct type. The functions can have
parameters, but those are currently ignored because there is no way to
access them.
This change intentionally focuses on breadth (introducing scopes,
statements, and expressions) rather than depth, because it enables
people to work on upstreaming in parallel without interference.
The new ClangIR ops in this change are `ReturnOp`, `YieldOp`, `ScopeOp`,
and `TrapOp`. These operations are complete (except for the
`ParentOneOf` property) and shouldn't require further upstreaming
changes. Significant additions were made to `FuncOp`, adding a type and
a region, but that operation is still far from complete.
The classes `ScalarExprEmitter` and `CIRGenFunction`, along with the
`emit*` functions in `CIRGenFunction` that generate ClangIR for
statements, are new in this change. All of these are very incomplete and
will be filled out in later upstreaming patches.
Existing test `hello.c` is removed and replaced by the new test
`func-simple.cpp`. This tests all forms of functions that are currently
supported.
Add frontend actions to support emitting assembly, bitcode, and object
files when compiling with ClangIR. This change also correctly sets and
propagates the target triple in the MLIR and LLVM modules, which was a
necessary prerequisite for emitting assembly and object files.
This change introduces lowering from CIR to LLVM IR of global integer
and floating-point variables, using defaults for attributes that aren't yet
implemented.
This adds a .clang-tidy file to the clang/lib/CIR/FrontendAction
directory, moves and updates the incorrectly located
include/clang/CIR/FrontendAction .clang-tidy file, and updates two files
from a recent commit to bring them into conformance with previously
agreed upon rules for where to use LLVM naming conventions and where to
use MLIR naming conventions.
Create the skeleton framework for lowering from ClangIR to LLVM IR. This
initial implementation just creates an empty LLVM IR module. Actual
lowering of even minimal ClangIR is deferred to a later patch.
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.
Upstream ClangIR support for `void` type, floating-point types, pointer
types, and function types.
Floating-point support is missing the IBM double-double format, because
that hasn't been implemented in the incubator project yet.
Pointer types do not yet support address spaces.
Function type support includes only the return type and the parameter
types. The many other properties and attributes of function types will
be upstreamed later.
ClangIR CodeGen code uses both `mlir::MLIRContext` and
`clang::ASTContext` objects extensively. Refering to either of those as
just "context" can be confusing.
Change the names of all variables, parameters, and fields in
`clang/lib/CIR/CodeGen` that refer to `MLIRContext` or an `ASTContext`
to be either `mlirContext` or `astContext`.
This change is only the renaming of variables/parameters/fields. There
are no behavior changes. So there are no new tests or changes to
existing tests. This change mimics a recent change in the ClangIR
incubator repository.
Small infrastructure and background changes to ClangIR.
Create class `CIRGenBuilderTy` and its base class `CIRBaseBuilderTy`.
These are mostly empty for now, except for what is inherited from
`mlir::OpBuilder`. But they will fill up quickly as more ClangIR code
gen is upstreamed. `CIRGenModule` and `CIRGenTypes` are changed to use
`CIRGenBuilderTy`.
Add cached types to struct `CIRGenTypeCache` for the integral types that
are currently supported. Initialize those cached types in the
`CIRGenModule` constructor. The first uses of those types (well, one of
them) is in `CIRGenTypes::convertType`.
Have `CIRGenTypes::convertType` cache its results in a map from
`clang::Type` to `mlir::Type`, saving it from having to convert the same
type again and again.
There are no new tests or changed tests in this commit. There are no
changes to behavior, just improvements to how the existing behavior is
implemented.
Add integral types to ClangIR. These are the first ClangIR types, so the
change includes some infrastructure for managing ClangIR types.
So that the integral types can be used somewhere, generate ClangIR for
global variables using the new `cir.global` op. As with the current
support for functions, global variables are just a stub at the moment.
The only properties that global variables have are a name and a type.
Add a new ClangIR code gen test global-var-simple.cpp, which defines
global variables with most of the integral types.
(Part of upstreaming the ClangIR incubator project into LLVM.)
Fix a compiler warning in `CIRGenConsumer::HandleTranslationUnit` in
`clang/lib/CIR/FrontendAction/CIRGenAction.cpp`. The warning was about a
`default:` section in a switch statement that already covered all the
values of an enum. Delete the `default:` section.
Building `MLIRCIR` will report an error `CIROpsDialect.h.inc` not found.
This is because `MLIRCIR` hasn't declared its dependence on the tablegen
target `MLIRCIROpsIncGen`. This patch fixes the issue.
The buildX naming convention originated when the CIRGen implementation
was planned to be substantially different from original CodeGen. CIRGen
is now a much closer adaption of CodeGen, and the emitX to buildX
renaming just makes things more confusing, since CodeGen also has some
helper functions whose names start with build or Build, so it's not
immediately clear which CodeGen function corresponds to a CIRGen buildX
function. Rename the buildX functions back to emitX to fix this.
https://github.com/llvm/clangir/issues/1025 discusses the motivation.
The mechanical parts of this change were done via:
find clang \( -name '*.h' -o -name '*.cpp' -o -name '*.td' \) -print0 |
xargs -0 perl -pi -e 's/mlir::cir/cir/g'
find clang \( -name '*.h' -o -name '*.cpp' \) -print0 | xargs -0 perl
-pi -e 's/::cir/cir/g'
There were some manual fixups and a clang-format run afterwards.
https://github.com/llvm/clangir/issues/1025 explains why we want to move
the CIR dialect from the `mlir::cir` to the `cir` namespace. To avoid
overloading the `cir` namespace too much afterwards, move all symbols
whose equivalents live inside the `clang::CodeGen` namespace to a new
`clang::CIRGen` namespace, so that we match the original CodeGen's
structure more closely.