Coding style conventions
This document outlines the coding style conventions for the project. These guidelines are primarily based on the LLVM coding style with a few exceptions and project-specific tweaks. Below are the main rules and conventions:
General conventions for C++ files
File Extensions:
Header files must have the
.hextension.Implementation (library) files must have the
.cppextension.
Include Guards:
All header files must include traditional include guards (e.g.,
#ifndef HEADER_H,#define HEADER_H,#endif).Note: The use of
#pragma onceis not allowed.
Indentation: The code should use 2 spaces for indentation (no tabs).
Naming Conventions:
PascalCase: Used for naming types such as classes, structs, enums, and typedefs. Example:
MyClass,MyEnum.camelCase: Used for variables (local and global), functions, and class members. Example:
myFunction,myVariable.UPPER_SNAKE_CASE: Typically used for macros. Example:
MY_CONSTANT,MAX_BUFFER_SIZE.kebab-case: Not commonly used in code, but may be used in filenames for tests and other resources. Example:
my-test-case.
Namespace Declarations:
After closing a namespace, add a comment
// namespace <namespace_name>. If the namespace is anonymous, omit the name.Note: Do not use
using namespacein header files.
Macro Definitions:
Defining macros in header files is discouraged, unless absolutely necessary.
To define a global constant,
constexprsyntax and camelCase naming should be used.
Include Ordering:
The order of
#includestatements should follow this pattern:Local project includes.
(An empty line).
MLIR/LLVM/Clang includes.
(An empty line).
Standard library includes (
<optional>,<vector>, etc.).
Within each subsection, statements should be sorted alphabetically by file name.
Example:
#include "ascir/Dialect/EmitAsc/IR/EmitAsc.h" #include "ascir/Target/Asc/Utils.h" #include "mlir/IR/Builders.h" #include "mlir/IR/DialectImplementation.h" #include "llvm/ADT/TypeSwitch.h" #include <optional> #include <unordered_map>
Anonymous Namespace: If a class or function is defined and declared in a
.cppfile but not used elsewhere in the project, it should be placed inside an anonymous namespace. It should not be marked asstatic.Template Argument Naming:
Template typename arguments should follow PascalCase. Example:
typename AttrT.Non-type template arguments should follow camelCase. Example:
size_t size.Always use
typenameinstead ofclassfor template arguments.
Conventions for MLIR dialects
Definitions of operations, types, attributes, interfaces, and other entities should be sorted alphabetically within the corresponding TableGen file.
Conventions for MLIR passes
Pass File Organization: Each MLIR pass should be placed in a separate :code:`.cpp` file under the
Transformsdirectory, within the directory corresponding to the specific MLIR dialect.File Naming: The name of the
.cppfile should match the name of the pass without the “Pass” suffix. For example, the file for theFoldVariablePasspass should be namedFoldVariable.cpp.Pass Declarations: In the
Passes.tdfile, inCMakeLists.txt, and in the constructor functions headerPasses.h, pass names should be listed in alphabetical order.
Conventions for LIT tests
Test Directory Structure:
Tests are placed in the
testdirectory.Filenames for test files should use kebab-case. Example:
my-test-case.mlir.
Test File Format: The first line of the test file should generally contain one or more
// RUN:commands that specify how the test should be executed.Test File Organization:
When adding a new MLIR operation, type, or attribute, a test for that feature should be added under the
IRdirectory within the appropriate dialect’s directory.When adding a new MLIR pass, a set of tests (typically multiple
func.funcoperations) should be added under theTransformsdirectory of the corresponding dialect where the pass is introduced. Name of file should correspond to a pass name.For the emission of a new operation, a test should be placed under the
Targetdirectory.End-to-end tests for tools should be located under the
Toolsdirectory.
Additional considerations
Readability: Code should be written for clarity and maintainability, not just brevity. Use meaningful names for functions, variables, and types. Comment complex or non-obvious code to aid future developers.
Refactoring: Refrain from making large, non-essential refactoring changes in areas that are not directly related to the task at hand. Always aim for minimal disruption in the codebase.
Version control:
Since commits are squashed into a single commit during the merge, detailed commit messages are not required. However, if needed, include helpful information about the change.
Merge request titles should be clear and describe the intention behind the changes. Follow conventional commit styles where possible.
Merge request description is optional if the title is sufficiently explanatory. It should be added in case of complex changes to clearly describe what has been implemented.
Make sure the code builds and passes tests locally before committing.
Code formatting and static analysis tools
To help ensure that the code adheres to the coding style conventions automatically, it is strongly recommended using the following tools:
clang-format:
clang-formatis a powerful tool for automatic code formatting, which can be configured to follow the project’s coding style guide.The
.clang-formatconfiguration files are already set up in the project repository, therefore you can format a file withclang-formatby running:clang-format -i <filename>
Integrating
clang-formatinto your IDE or editor can help you format code automatically on save. For example, there is Clang-Format extension for Visual Studio Code.
clang-tidy:
clang-tidyis a static analysis tool that helps catch common issues and enforces coding standards and best practices. It works by checking your code against predefined or custom checks.clang-tidycan help identify issues related to code quality, unused variables, potential bugs, and performance improvements. It is recommended to check an output log of clang-tidy job in open merge request and address issues before merge.
This style guide serves to maintain consistency across the codebase, making it easier to read, maintain, and extend. Adhering to these conventions will improve collaboration, reduce errors, and make it easier for new contributors to get up to speed.