├── .clang-format
├── .clang-tidy
├── .github
└── workflows
│ ├── build.yml
│ └── deploy-docs.yml
├── .gitignore
├── .gitmodules
├── CMakeLists.txt
├── COPYING
├── LICENSE-Apache
├── LICENSE-FDL
├── README.md
├── cmake
├── FindGCCJIT.cmake
├── FindLLVM.cmake
└── FindMLIR.cmake
├── include
├── CMakeLists.txt
└── mlir-gccjit
│ ├── CMakeLists.txt
│ ├── Conversion
│ ├── Conversions.h
│ └── TypeConverter.h
│ ├── IR
│ ├── CMakeLists.txt
│ ├── GCCJITAttrs.h
│ ├── GCCJITAttrs.td
│ ├── GCCJITDialect.h
│ ├── GCCJITDialect.td
│ ├── GCCJITOps.h
│ ├── GCCJITOps.td
│ ├── GCCJITOpsEnums.h
│ ├── GCCJITTypes.h
│ ├── GCCJITTypes.td
│ └── Interfaces
│ │ ├── CMakeLists.txt
│ │ ├── GCCJITRecordTypeInterface.h
│ │ └── GCCJITRecordTypeInterface.td
│ ├── Passes.h
│ ├── Passes.td
│ └── Translation
│ └── TranslateToGCCJIT.h
├── logo.png
├── run-lit.py
├── src
├── CMakeLists.txt
├── Conversion
│ ├── CMakeLists.txt
│ ├── ConvertArithToGCCJIT.cpp
│ ├── ConvertFuncToGCCJIT.cpp
│ ├── ConvertMemrefToGCCJIT.cpp
│ └── TypeConverter.cpp
├── GCCJITAttrs.cpp
├── GCCJITDialect.cpp
├── GCCJITOps.cpp
├── GCCJITTypes.cpp
├── Interfaces
│ ├── CMakeLists.txt
│ └── GCCJITRecordTypeInterface.cpp
└── Translation
│ ├── CMakeLists.txt
│ ├── Registration.cpp
│ ├── TranslateToGCCJIT.cpp
│ └── TypeTranslation.cpp
├── test
├── CMakeLists.txt
├── compile
│ ├── atomic.mlir
│ ├── bitfield.mlir
│ ├── deref_chain.mlir
│ ├── expression.mlir
│ ├── global.mlir
│ ├── hello_world.mlir
│ ├── lazy_evaluation.mlir
│ ├── unary.mlir
│ ├── union.mlir
│ └── vector.mlir
├── lit.cfg.py
├── lit.site.cfg.py.in
├── lowering
│ ├── alloc.mlir
│ ├── alloca.mlir
│ ├── alloca_sum.c
│ ├── alloca_sum.mlir
│ ├── assume_aligned.mlir
│ ├── dealloc.mlir
│ ├── gemm.c
│ ├── gemm.mlir
│ └── global.mlir
└── syntax
│ ├── basic.mlir
│ ├── branch.mlir
│ ├── extened_asm.mlir
│ ├── floating_point.mlir
│ ├── function_attrs.mlir
│ ├── hello_world.mlir
│ ├── record.mlir
│ └── variables.mlir
├── tools
├── CMakeLists.txt
├── gccjit-opt
│ ├── CMakeLists.txt
│ └── main.cpp
└── gccjit-translate
│ ├── CMakeLists.txt
│ └── main.cpp
└── www
├── .gitignore
├── archetypes
├── attrs.md
├── default.md
├── dialect.md
├── ops.md
├── passes.md
└── types.md
├── content
├── _index.md
└── development
│ ├── _index.md
│ ├── build.md
│ └── compatibility.md
├── hugo.toml
├── link-docs.sh
└── static
└── logo.png
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | Language: Cpp
3 | # BasedOnStyle: LLVM
4 | AccessModifierOffset: -2
5 | AlignAfterOpenBracket: Align
6 | AlignArrayOfStructures: None
7 | AlignConsecutiveAssignments:
8 | Enabled: false
9 | AcrossEmptyLines: false
10 | AcrossComments: false
11 | AlignCompound: false
12 | AlignFunctionPointers: false
13 | PadOperators: true
14 | AlignConsecutiveBitFields:
15 | Enabled: false
16 | AcrossEmptyLines: false
17 | AcrossComments: false
18 | AlignCompound: false
19 | AlignFunctionPointers: false
20 | PadOperators: false
21 | AlignConsecutiveDeclarations:
22 | Enabled: false
23 | AcrossEmptyLines: false
24 | AcrossComments: false
25 | AlignCompound: false
26 | AlignFunctionPointers: false
27 | PadOperators: false
28 | AlignConsecutiveMacros:
29 | Enabled: false
30 | AcrossEmptyLines: false
31 | AcrossComments: false
32 | AlignCompound: false
33 | AlignFunctionPointers: false
34 | PadOperators: false
35 | AlignConsecutiveShortCaseStatements:
36 | Enabled: false
37 | AcrossEmptyLines: false
38 | AcrossComments: false
39 | AlignCaseColons: false
40 | AlignEscapedNewlines: Right
41 | AlignOperands: Align
42 | AlignTrailingComments:
43 | Kind: Always
44 | OverEmptyLines: 0
45 | AllowAllArgumentsOnNextLine: true
46 | AllowAllParametersOfDeclarationOnNextLine: true
47 | AllowBreakBeforeNoexceptSpecifier: Never
48 | AllowShortBlocksOnASingleLine: Never
49 | AllowShortCaseLabelsOnASingleLine: false
50 | AllowShortCompoundRequirementOnASingleLine: true
51 | AllowShortEnumsOnASingleLine: true
52 | AllowShortFunctionsOnASingleLine: All
53 | AllowShortIfStatementsOnASingleLine: Never
54 | AllowShortLambdasOnASingleLine: All
55 | AllowShortLoopsOnASingleLine: false
56 | AlwaysBreakAfterDefinitionReturnType: None
57 | AlwaysBreakAfterReturnType: None
58 | AlwaysBreakBeforeMultilineStrings: false
59 | AlwaysBreakTemplateDeclarations: MultiLine
60 | AttributeMacros:
61 | - __capability
62 | BinPackArguments: true
63 | BinPackParameters: true
64 | BitFieldColonSpacing: Both
65 | BraceWrapping:
66 | AfterCaseLabel: false
67 | AfterClass: false
68 | AfterControlStatement: Never
69 | AfterEnum: false
70 | AfterExternBlock: false
71 | AfterFunction: false
72 | AfterNamespace: false
73 | AfterObjCDeclaration: false
74 | AfterStruct: false
75 | AfterUnion: false
76 | BeforeCatch: false
77 | BeforeElse: false
78 | BeforeLambdaBody: false
79 | BeforeWhile: false
80 | IndentBraces: false
81 | SplitEmptyFunction: true
82 | SplitEmptyRecord: true
83 | SplitEmptyNamespace: true
84 | BreakAdjacentStringLiterals: true
85 | BreakAfterAttributes: Leave
86 | BreakAfterJavaFieldAnnotations: false
87 | BreakArrays: true
88 | BreakBeforeBinaryOperators: None
89 | BreakBeforeConceptDeclarations: Always
90 | BreakBeforeBraces: Attach
91 | BreakBeforeInlineASMColon: OnlyMultiline
92 | BreakBeforeTernaryOperators: true
93 | BreakConstructorInitializers: BeforeColon
94 | BreakInheritanceList: BeforeColon
95 | BreakStringLiterals: true
96 | ColumnLimit: 80
97 | CommentPragmas: '^ IWYU pragma:'
98 | CompactNamespaces: false
99 | ConstructorInitializerIndentWidth: 4
100 | ContinuationIndentWidth: 4
101 | Cpp11BracedListStyle: true
102 | DerivePointerAlignment: false
103 | DisableFormat: false
104 | EmptyLineAfterAccessModifier: Never
105 | EmptyLineBeforeAccessModifier: LogicalBlock
106 | ExperimentalAutoDetectBinPacking: false
107 | FixNamespaceComments: true
108 | ForEachMacros:
109 | - foreach
110 | - Q_FOREACH
111 | - BOOST_FOREACH
112 | IfMacros:
113 | - KJ_IF_MAYBE
114 | IncludeBlocks: Preserve
115 | IncludeCategories:
116 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
117 | Priority: 2
118 | SortPriority: 0
119 | CaseSensitive: false
120 | - Regex: '^(<|"(gtest|gmock|isl|json)/)'
121 | Priority: 3
122 | SortPriority: 0
123 | CaseSensitive: false
124 | - Regex: '.*'
125 | Priority: 1
126 | SortPriority: 0
127 | CaseSensitive: false
128 | IncludeIsMainRegex: '(Test)?$'
129 | IncludeIsMainSourceRegex: ''
130 | IndentAccessModifiers: false
131 | IndentCaseBlocks: false
132 | IndentCaseLabels: false
133 | IndentExternBlock: AfterExternBlock
134 | IndentGotoLabels: true
135 | IndentPPDirectives: None
136 | IndentRequiresClause: true
137 | IndentWidth: 2
138 | IndentWrappedFunctionNames: false
139 | InsertBraces: false
140 | InsertNewlineAtEOF: false
141 | InsertTrailingCommas: None
142 | IntegerLiteralSeparator:
143 | Binary: 0
144 | BinaryMinDigits: 0
145 | Decimal: 0
146 | DecimalMinDigits: 0
147 | Hex: 0
148 | HexMinDigits: 0
149 | JavaScriptQuotes: Leave
150 | JavaScriptWrapImports: true
151 | KeepEmptyLinesAtTheStartOfBlocks: true
152 | KeepEmptyLinesAtEOF: false
153 | LambdaBodyIndentation: Signature
154 | LineEnding: DeriveLF
155 | MacroBlockBegin: ''
156 | MacroBlockEnd: ''
157 | MaxEmptyLinesToKeep: 1
158 | NamespaceIndentation: None
159 | ObjCBinPackProtocolList: Auto
160 | ObjCBlockIndentWidth: 2
161 | ObjCBreakBeforeNestedBlockParam: true
162 | ObjCSpaceAfterProperty: false
163 | ObjCSpaceBeforeProtocolList: true
164 | PackConstructorInitializers: BinPack
165 | PenaltyBreakAssignment: 2
166 | PenaltyBreakBeforeFirstCallParameter: 19
167 | PenaltyBreakComment: 300
168 | PenaltyBreakFirstLessLess: 120
169 | PenaltyBreakOpenParenthesis: 0
170 | PenaltyBreakScopeResolution: 500
171 | PenaltyBreakString: 1000
172 | PenaltyBreakTemplateDeclaration: 10
173 | PenaltyExcessCharacter: 1000000
174 | PenaltyIndentedWhitespace: 0
175 | PenaltyReturnTypeOnItsOwnLine: 60
176 | PointerAlignment: Right
177 | PPIndentWidth: -1
178 | QualifierAlignment: Leave
179 | ReferenceAlignment: Pointer
180 | ReflowComments: true
181 | RemoveBracesLLVM: false
182 | RemoveParentheses: Leave
183 | RemoveSemicolon: false
184 | RequiresClausePosition: OwnLine
185 | RequiresExpressionIndentation: OuterScope
186 | SeparateDefinitionBlocks: Leave
187 | ShortNamespaceLines: 1
188 | SkipMacroDefinitionBody: false
189 | SortIncludes: CaseSensitive
190 | SortJavaStaticImport: Before
191 | SortUsingDeclarations: LexicographicNumeric
192 | SpaceAfterCStyleCast: false
193 | SpaceAfterLogicalNot: false
194 | SpaceAfterTemplateKeyword: true
195 | SpaceAroundPointerQualifiers: Default
196 | SpaceBeforeAssignmentOperators: true
197 | SpaceBeforeCaseColon: false
198 | SpaceBeforeCpp11BracedList: false
199 | SpaceBeforeCtorInitializerColon: true
200 | SpaceBeforeInheritanceColon: true
201 | SpaceBeforeJsonColon: false
202 | SpaceBeforeParens: ControlStatements
203 | SpaceBeforeParensOptions:
204 | AfterControlStatements: true
205 | AfterForeachMacros: true
206 | AfterFunctionDefinitionName: false
207 | AfterFunctionDeclarationName: false
208 | AfterIfMacros: true
209 | AfterOverloadedOperator: false
210 | AfterPlacementOperator: true
211 | AfterRequiresInClause: false
212 | AfterRequiresInExpression: false
213 | BeforeNonEmptyParentheses: false
214 | SpaceBeforeRangeBasedForLoopColon: true
215 | SpaceBeforeSquareBrackets: false
216 | SpaceInEmptyBlock: false
217 | SpacesBeforeTrailingComments: 1
218 | SpacesInAngles: Never
219 | SpacesInContainerLiterals: true
220 | SpacesInLineCommentPrefix:
221 | Minimum: 1
222 | Maximum: -1
223 | SpacesInParens: Never
224 | SpacesInParensOptions:
225 | InCStyleCasts: false
226 | InConditionalStatements: false
227 | InEmptyParentheses: false
228 | Other: false
229 | SpacesInSquareBrackets: false
230 | Standard: Latest
231 | StatementAttributeLikeMacros:
232 | - Q_EMIT
233 | StatementMacros:
234 | - Q_UNUSED
235 | - QT_REQUIRE_VERSION
236 | TabWidth: 8
237 | UseTab: Never
238 | VerilogBreakBetweenInstancePorts: true
239 | WhitespaceSensitiveMacros:
240 | - BOOST_PP_STRINGIZE
241 | - CF_SWIFT_NAME
242 | - NS_SWIFT_NAME
243 | - PP_STRINGIZE
244 | - STRINGIZE
245 | ...
246 |
247 |
--------------------------------------------------------------------------------
/.clang-tidy:
--------------------------------------------------------------------------------
1 | # Copied from llvm/llvm-project
2 | Checks: '-*,clang-diagnostic-*,llvm-*,misc-*,-misc-const-correctness,-misc-unused-parameters,-misc-non-private-member-variables-in-classes,-misc-no-recursion,-misc-use-anonymous-namespace,readability-identifier-naming,-misc-include-cleaner'
3 | CheckOptions:
4 | - key: readability-identifier-naming.ClassCase
5 | value: CamelCase
6 | - key: readability-identifier-naming.EnumCase
7 | value: CamelCase
8 | - key: readability-identifier-naming.FunctionCase
9 | value: camelBack
10 | # Exclude from scanning as this is an exported symbol used for fuzzing
11 | # throughout the code base.
12 | - key: readability-identifier-naming.FunctionIgnoredRegexp
13 | value: "LLVMFuzzerTestOneInput"
14 | - key: readability-identifier-naming.MemberCase
15 | value: camelBack
16 | - key: readability-identifier-naming.ParameterCase
17 | value: camelBack
18 | - key: readability-identifier-naming.UnionCase
19 | value: CamelCase
20 | - key: readability-identifier-naming.VariableCase
21 | value: camelBack
22 | - key: readability-identifier-naming.IgnoreMainLikeFunctions
23 | value: 1
24 | - key: readability-redundant-member-init.IgnoreBaseInCopyConstructors
25 | value: 1
26 | - key: modernize-use-default-member-init.UseAssignment
27 | value: 1
28 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 | on: [push, pull_request]
3 |
4 | jobs:
5 | build:
6 | runs-on: ubuntu-24.04
7 | env:
8 | LLVM_DIR: /usr/lib/llvm-18/cmake
9 | steps:
10 | - uses: actions/checkout@v4
11 |
12 | - name: Install build tools and libraries
13 | run: |
14 | sudo apt-get update
15 | sudo apt-get install -y gcc-14 g++-14 cmake ninja-build llvm-18-dev llvm-18-tools \
16 | libmlir-18-dev libgccjit-14-dev mlir-18-tools python3 python3-pip
17 | pip install lit
18 |
19 | - name: Build
20 | run: |
21 | cmake -B build -G Ninja -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 .
22 | cmake --build build
23 | cmake --build build --target gccjit-tools
24 |
25 | - name: Run tests
26 | run: |
27 | cmake --build build --target check
28 |
--------------------------------------------------------------------------------
/.github/workflows/deploy-docs.yml:
--------------------------------------------------------------------------------
1 | name: Deploy Documentation Pages
2 | on:
3 | push:
4 | branches: [main]
5 |
6 | jobs:
7 | build:
8 | runs-on: ubuntu-24.04
9 | env:
10 | LLVM_DIR: /usr/lib/llvm-18/cmake
11 | steps:
12 | - uses: actions/checkout@v4
13 | with:
14 | submodules: recursive
15 |
16 | - name: Install build tools and libraries
17 | run: |
18 | sudo apt-get update
19 | sudo apt-get install -y gcc-14 g++-14 cmake hugo ninja-build llvm-18-dev llvm-18-tools \
20 | libmlir-18-dev libgccjit-14-dev mlir-18-tools
21 |
22 | - name: Build and link MLIR documentation
23 | run: |
24 | cmake -B build -G Ninja -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 .
25 | cmake --build build --target mlir-doc
26 | cmake --build build --target link-mlir-docs
27 |
28 | - name: Build hugo site
29 | run: |
30 | cd www
31 | hugo
32 |
33 | - name: Upload hugo site artifacts
34 | id: deployment
35 | uses: actions/upload-pages-artifact@v3
36 | with:
37 | path: www/public
38 |
39 | deploy:
40 | needs: build
41 | runs-on: ubuntu-latest
42 | environment:
43 | name: github-pages
44 | url: ${{ steps.deployment.outputs.page_url }}
45 | permissions:
46 | pages: write
47 | id-token: write
48 | steps:
49 | - name: Deploy hugo site to GitHub pages
50 | id: deployment
51 | uses: actions/deploy-pages@v4
52 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # macOS specific files
2 | .DS_Store
3 |
4 | # Build directories
5 | /build*
6 | /cmake-build*
7 |
8 | # Temp files created by most editors
9 | *~
10 |
11 | # vim swap files
12 | .*.sw?
13 |
14 | # JetBrains IDE files
15 | .idea
16 |
17 | # Visual Studio and vscode files
18 | .vs
19 | .vscode
20 |
21 | # clangd index and compilation databases
22 | .clangd
23 | .cache
24 | compile_commands.json
25 | compile_flags.txt
26 |
27 | # CMake user presets
28 | CMakeUserPresets.json
29 |
30 | # Python virtual environments.
31 | /venv*
32 |
33 | mlir-gccjit-*
34 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "www/themes/hugo-theme-techdoc"]
2 | path = www/themes/hugo-theme-techdoc
3 | url = https://github.com/thingsym/hugo-theme-techdoc.git
4 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.22)
2 | project(mlir-gccjit
3 | LANGUAGES C CXX
4 | )
5 |
6 | option(MLIR_GCCJIT_BUILD_TOOLS "Build mlir-gccjit tools" ON)
7 | option(MLIR_GCCJIT_ENABLE_TEST "Enable test targets in build" ON)
8 |
9 | set(LLVM_BUILD_TOOLS ${MLIR_GCCJIT_BUILD_TOOLS})
10 |
11 | include(cmake/FindLLVM.cmake)
12 | include(cmake/FindMLIR.cmake)
13 | include(cmake/FindGCCJIT.cmake)
14 |
15 | set(CMAKE_CXX_STANDARD 17)
16 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
17 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
18 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
19 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
20 | include_directories(
21 | ${CMAKE_SOURCE_DIR}/include
22 | ${CMAKE_BINARY_DIR}/include
23 | ${MLIR_INCLUDE_DIRS}
24 | ${LLVM_INCLUDE_DIRS}
25 | )
26 | link_directories(${LLVM_BUILD_LIBRARY_DIR})
27 | add_definitions(${LLVM_DEFINITIONS})
28 |
29 | add_subdirectory(include)
30 | add_subdirectory(src)
31 |
32 | add_subdirectory(tools)
33 |
34 | if (MLIR_GCCJIT_ENABLE_TEST)
35 | add_subdirectory(test)
36 | endif ()
37 |
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | # Copying Information
2 |
3 | - The logo of the project is licensed under GNU Free Documentation License v1.3. It is modified from the original GCC logo, which is licensed under GNU Free Documentation License v1.2.
4 | - Other contents of the project are licensed under Apache License 2.0, if not otherwise specified.
5 |
--------------------------------------------------------------------------------
/LICENSE-Apache:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > "There is one who could unite them, one who could reclaim the throne of Gondor." (Gandalf)
2 |
3 |
4 |
5 | # mlir-gccjit
6 |
7 | MLIR dialect for [`libgccjit`](https://gcc.gnu.org/onlinedocs/jit/).
8 |
9 | ## Discussion
10 |
11 | If you have any questions about this project, check out the
12 | [discussion area](https://github.com/Lancern/mlir-gccjit/discussions).
13 | If you couldn't find satisfying answers there, feel free to
14 | [open a new discussion](https://github.com/Lancern/mlir-gccjit/discussions/new/choose).
15 |
16 | ## Contribution
17 |
18 | We warmly welcome any kind of contributions including but not restricted to bug
19 | reports, feature requests, and pull requests. Please
20 | [open an issue](https://github.com/Lancern/mlir-gccjit/issues/new) if you have
21 | found a bug or want to request a new feature. Feel free to open a pull request
22 | if you have made any improvements to the project!
23 |
24 | ## License
25 |
26 | Please refer to [COPYING](COPYING) for more information.
27 |
--------------------------------------------------------------------------------
/cmake/FindGCCJIT.cmake:
--------------------------------------------------------------------------------
1 | include_guard(GLOBAL)
2 |
3 | set(GCCJIT_ROOT "" CACHE PATH "Path to GCCJIT installation")
4 | set(GCCJIT_INCLUDE_DIR "" CACHE PATH "Path to GCCJIT include directory")
5 |
6 | if (GCCJIT_ROOT)
7 | message(STATUS "Using GCCJIT from ${GCCJIT_ROOT}")
8 |
9 | if (NOT GCCJIT_INCLUDE_DIR)
10 | set(GCCJIT_INCLUDE_DIR ${GCCJIT_ROOT}/include)
11 | endif ()
12 |
13 | set(GCCJIT_LIB_DIRS ${GCCJIT_ROOT})
14 | if (EXISTS ${GCCJIT_ROOT}/lib)
15 | list(APPEND GCCJIT_LIB_DIRS ${GCCJIT_ROOT}/lib)
16 | endif()
17 | if (EXISTS ${GCCJIT_ROOT}/lib/gcc/current)
18 | list(APPEND GCCJIT_LIB_DIRS ${GCCJIT_ROOT}/lib/gcc/current)
19 | endif ()
20 | endif ()
21 |
22 | if (GCCJIT_INCLUDE_DIR)
23 | list(APPEND CMAKE_REQUIRED_INCLUDES ${GCCJIT_INCLUDE_DIR})
24 | endif ()
25 |
26 | include(CheckIncludeFileCXX)
27 | CHECK_INCLUDE_FILE_CXX(libgccjit.h LIBGCCJIT_H_EXIST)
28 | if (NOT LIBGCCJIT_H_EXIST)
29 | message(FATAL_ERROR "could not find libgccjit.h in system headers (CMAKE_REQUIRED_INCLUDES: ${CMAKE_REQUIRED_INCLUDES})")
30 | endif ()
31 |
32 | if (GCCJIT_LIB_DIRS OR GCCJIT_LIBRARY)
33 | find_library(GCCJIT_LIBRARY NAMES gccjit PATHS ${GCCJIT_LIB_DIRS})
34 | if (NOT GCCJIT_LIBRARY)
35 | message(FATAL_ERROR "could not find gccjit library file at ${GCCJIT_LIB_DIRS}")
36 | elseif (NOT EXISTS ${GCCJIT_LIBRARY})
37 | message(FATAL_ERROR "could not find gccjit library file at ${GCCJIT_LIBRARY}")
38 | endif()
39 |
40 | add_library(libgccjit SHARED IMPORTED)
41 | set_target_properties(libgccjit PROPERTIES
42 | IMPORTED_LOCATION ${GCCJIT_LIBRARY}
43 | )
44 | else ()
45 | add_library(libgccjit INTERFACE)
46 | target_link_libraries(libgccjit INTERFACE gccjit)
47 | endif ()
48 |
49 | if (GCCJIT_INCLUDE_DIR)
50 | target_include_directories(libgccjit INTERFACE ${GCCJIT_INCLUDE_DIR})
51 | endif ()
52 |
--------------------------------------------------------------------------------
/cmake/FindLLVM.cmake:
--------------------------------------------------------------------------------
1 | include_guard(GLOBAL)
2 |
3 | find_package(LLVM REQUIRED CONFIG)
4 | message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION} at ${LLVM_DIR}")
5 |
6 | include(${LLVM_DIR}/AddLLVM.cmake)
7 | include(${LLVM_DIR}/TableGen.cmake)
8 | include(${LLVM_DIR}/HandleLLVMOptions.cmake)
9 |
10 | # Try to find the FileCheck utility.
11 | if (TARGET FileCheck)
12 | get_target_property(LLVM_FILE_CHECK_EXE FileCheck IMPORTED_LOCATION)
13 | endif ()
14 |
15 | if (NOT LLVM_FILE_CHECK_EXE)
16 | unset(LLVM_FILE_CHECK_EXE)
17 | if (MLIR_GCCJIT_ENABLE_TEST)
18 | set(filecheck_required_param REQUIRED)
19 | endif ()
20 | find_program(LLVM_FILE_CHECK_EXE
21 | FileCheck
22 | NAMES FileCheck-${LLVM_VERSION_MAJOR}
23 | HINTS
24 | "${LLVM_DIR}/../../../bin"
25 | "${LLVM_DIR}/../bin"
26 | ${filecheck_required_param}
27 | )
28 | endif ()
29 |
30 | if (LLVM_FILE_CHECK_EXE)
31 | message(STATUS "Found FileCheck utility at ${LLVM_FILE_CHECK_EXE}")
32 | elseif (MLIR_GCCJIT_ENABLE_TEST)
33 | message(FATAL_ERROR "Could not find FileCheck utility")
34 | endif ()
35 |
--------------------------------------------------------------------------------
/cmake/FindMLIR.cmake:
--------------------------------------------------------------------------------
1 | include_guard(GLOBAL)
2 |
3 | set(find_mlir_hints)
4 | if (LLVM_DIR)
5 | list(APPEND find_mlir_hints "${LLVM_DIR}/..")
6 | endif ()
7 |
8 | find_package(MLIR
9 | REQUIRED CONFIG
10 | HINTS ${find_mlir_hints}
11 | )
12 | message(STATUS "Found MLIR ${MLIR_PACKAGE_VERSION} at ${MLIR_DIR}")
13 |
14 | include(${MLIR_DIR}/AddMLIR.cmake)
15 |
--------------------------------------------------------------------------------
/include/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_subdirectory(mlir-gccjit)
2 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | function(add_mlir_gccjit_doc doc_filename output_file output_directory command)
2 | set(LLVM_TARGET_DEFINITIONS ${doc_filename}.td)
3 | tablegen(MLIR ${output_file}.md ${command} ${ARGN})
4 | set(GEN_DOC_FILE ${PROJECT_BINARY_DIR}/docs/${output_directory}${output_file}.md)
5 | add_custom_command(
6 | OUTPUT ${GEN_DOC_FILE}
7 | COMMAND ${CMAKE_COMMAND} -E copy
8 | ${CMAKE_CURRENT_BINARY_DIR}/${output_file}.md
9 | ${GEN_DOC_FILE}
10 | DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${output_file}.md)
11 | add_custom_target(${output_file}DocGen DEPENDS ${GEN_DOC_FILE})
12 | add_dependencies(mlir-doc ${output_file}DocGen)
13 | endfunction()
14 |
15 | add_subdirectory(IR)
16 |
17 | set(LLVM_TARGET_DEFINITIONS Passes.td)
18 | mlir_tablegen(Passes.h.inc -gen-pass-decls -name GCCJIT)
19 | mlir_tablegen(Passes.capi.h.inc -gen-pass-capi-header --prefix GCCJIT)
20 | mlir_tablegen(Passes.capi.cpp.inc -gen-pass-capi-impl --prefix GCCJIT)
21 | add_public_tablegen_target(MLIRGCCJITPassIncGen)
22 |
23 | add_mlir_gccjit_doc(Passes GCCJITPasses gccjit/ -gen-pass-doc)
24 |
25 | add_custom_target(link-mlir-docs
26 | COMMAND ${PROJECT_SOURCE_DIR}/www/link-docs.sh ${PROJECT_BINARY_DIR}
27 | DEPENDS mlir-doc
28 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/www
29 | )
30 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/Conversion/Conversions.h:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Schrodinger ZHU Yifan
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MLIR_GCCJIT_CONVERSION_CONVERTIONS_H
16 | #define MLIR_GCCJIT_CONVERSION_CONVERTIONS_H
17 |
18 | #include
19 |
20 | #include "mlir-gccjit/Conversion/TypeConverter.h"
21 |
22 | namespace mlir::gccjit {
23 | void populateFuncToGCCJITPatterns(MLIRContext *context,
24 | GCCJITTypeConverter &typeConverter,
25 | RewritePatternSet &patterns,
26 | SymbolTable &symbolTable);
27 | } // namespace mlir::gccjit
28 |
29 | #endif
30 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/Conversion/TypeConverter.h:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Schrodinger ZHU Yifan
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MLIR_GCCJIT_CONVERSION_TYPECONVERTER_H
16 | #define MLIR_GCCJIT_CONVERSION_TYPECONVERTER_H
17 |
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | #include "mlir-gccjit/IR/GCCJITAttrs.h"
25 | #include "mlir-gccjit/IR/GCCJITTypes.h"
26 |
27 | namespace mlir::gccjit {
28 | class GCCJITTypeConverter : public TypeConverter {
29 |
30 | public:
31 | GCCJITTypeConverter();
32 | ~GCCJITTypeConverter();
33 | // integral types
34 | gccjit::IntType convertIndexType(mlir::IndexType type) const;
35 | gccjit::IntType makeSigned(gccjit::IntType type) const;
36 | gccjit::IntType makeUnsigned(gccjit::IntType type) const;
37 | bool isSigned(gccjit::IntType type) const;
38 | gccjit::IntType convertIntegerType(mlir::IntegerType type) const;
39 | gccjit::IntAttr convertIntegerAttr(mlir::IntegerAttr attr) const;
40 |
41 | // floating point types
42 | gccjit::FloatType convertFloatType(mlir::FloatType type) const;
43 | gccjit::FloatAttr convertFloatAttr(mlir::FloatAttr attr) const;
44 |
45 | // special composite types
46 | gccjit::ComplexType convertComplexType(mlir::ComplexType type) const;
47 | gccjit::VectorType convertVectorType(mlir::VectorType type) const;
48 |
49 | // function prototype
50 | gccjit::FuncType convertFunctionType(mlir::FunctionType type,
51 | bool isVarArg) const;
52 |
53 | // function type to function pointer
54 | gccjit::PointerType convertFunctionTypeAsPtr(mlir::FunctionType type,
55 | bool isVarArg) const;
56 |
57 | // memref type
58 | gccjit::StructType getMemrefDescriptorType(mlir::MemRefType type) const;
59 | gccjit::StructType
60 | getUnrankedMemrefDescriptorType(mlir::UnrankedMemRefType type) const;
61 |
62 | Type convertAndPackTypesIfNonSingleton(TypeRange types, MLIRContext *) const;
63 | };
64 | } // namespace mlir::gccjit
65 | #endif // MLIR_GCCJIT_CONVERSION_TYPECONVERTER_H
66 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/IR/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_mlir_dialect(GCCJITOps gccjit)
2 |
3 | # Generate extra headers for custom enum and attrs.
4 | set(LLVM_TARGET_DEFINITIONS GCCJITOps.td)
5 | mlir_tablegen(GCCJITOpsEnums.h.inc -gen-enum-decls)
6 | mlir_tablegen(GCCJITOpsEnums.cpp.inc -gen-enum-defs)
7 | mlir_tablegen(GCCJITOpsAttributes.h.inc -gen-attrdef-decls)
8 | mlir_tablegen(GCCJITOpsAttributes.cpp.inc -gen-attrdef-defs)
9 | add_public_tablegen_target(MLIRGCCJITEnumsGen)
10 | add_dependencies(mlir-headers MLIRGCCJITEnumsGen)
11 |
12 | add_mlir_gccjit_doc(GCCJITDialect GCCJITDialect gccjit/ -gen-dialect-doc)
13 | add_mlir_gccjit_doc(GCCJITOps GCCJITOps gccjit/ -gen-op-doc)
14 | add_mlir_gccjit_doc(GCCJITAttrs GCCJITAttrs gccjit/ -gen-attrdef-doc)
15 | add_mlir_gccjit_doc(GCCJITTypes GCCJITTypes gccjit/ -gen-typedef-doc)
16 |
17 | add_subdirectory(Interfaces)
18 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/IR/GCCJITAttrs.h:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Schrodinger ZHU Yifan
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MLIR_GCCJIT_IR_GCCJIT_OPS_ATTRS_H
16 | #define MLIR_GCCJIT_IR_GCCJIT_OPS_ATTRS_H
17 |
18 | #include "mlir-gccjit/IR/GCCJITOpsEnums.h"
19 |
20 | namespace mlir::gccjit {
21 | class IntType;
22 | class FloatType;
23 | class PointerType;
24 | } // namespace mlir::gccjit
25 |
26 | #define GET_ATTRDEF_CLASSES
27 | #include "mlir-gccjit/IR/GCCJITOpsAttributes.h.inc"
28 |
29 | namespace mlir::gccjit {
30 | inline bool isUnitFnAttr(FnAttrEnum attr) {
31 | switch (attr) {
32 | case FnAttrEnum::AlwaysInline:
33 | case FnAttrEnum::Inline:
34 | case FnAttrEnum::NoInline:
35 | case FnAttrEnum::Used:
36 | case FnAttrEnum::Cold:
37 | case FnAttrEnum::ReturnsTwice:
38 | case FnAttrEnum::Pure:
39 | case FnAttrEnum::Const:
40 | case FnAttrEnum::Weak:
41 | return true;
42 | default:
43 | return false;
44 | }
45 | }
46 | inline bool isStringFnAttr(FnAttrEnum attr) {
47 | switch (attr) {
48 | case FnAttrEnum::Alias:
49 | case FnAttrEnum::Target:
50 | return true;
51 | default:
52 | return false;
53 | }
54 | }
55 |
56 | inline bool isIntArrayFnAttr(FnAttrEnum attr) {
57 | switch (attr) {
58 | case FnAttrEnum::Nonnull:
59 | return true;
60 | default:
61 | return false;
62 | }
63 | }
64 | } // namespace mlir::gccjit
65 |
66 | #endif // MLIR_GCCJIT_IR_GCCJIT_OPS_ATTRS_H
67 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/IR/GCCJITAttrs.td:
--------------------------------------------------------------------------------
1 | #ifndef MLIR_GCCJIT_IR_GCCJIT_ATTRS
2 | #define MLIR_GCCJIT_IR_GCCJIT_ATTRS
3 |
4 | include "mlir/IR/BuiltinAttributeInterfaces.td"
5 | include "mlir/IR/EnumAttr.td"
6 | include "mlir-gccjit/IR/GCCJITDialect.td"
7 |
8 | //===----------------------------------------------------------------------===//
9 | // GCCJIT Attrs
10 | //===----------------------------------------------------------------------===//
11 |
12 | class GCCJIT_Attr traits = []>
13 | : AttrDef {
14 | let mnemonic = attrMnemonic;
15 | }
16 |
17 | class GCCJIT_UnitAttr traits = []>
18 | : GCCJIT_Attr {
19 | let returnType = "bool";
20 | let defaultValue = "false";
21 | let valueType = NoneType;
22 | let isOptional = 1;
23 | }
24 |
25 | //===----------------------------------------------------------------------===//
26 | // TLS Model Attrs
27 | //===----------------------------------------------------------------------===//
28 |
29 | def TLSModel_None : I32EnumAttrCase<"None", 0, "none">;
30 | def TLSModel_GlobalDynamic : I32EnumAttrCase<"GlobalDynamic", 1,
31 | "global_dynamic">;
32 | def TLSModel_LocalDynamic : I32EnumAttrCase<"LocalDynamic", 2, "local_dynamic">;
33 | def TLSModel_InitialExec : I32EnumAttrCase<"InitialExec", 3, "initial_exec">;
34 | def TLSModel_LocalExec : I32EnumAttrCase<"LocalExec", 4, "local_exec">;
35 |
36 | def TLSModelEnum : I32EnumAttr<"TLSModelEnum", "TLS model",
37 | [TLSModel_None, TLSModel_GlobalDynamic,
38 | TLSModel_LocalDynamic, TLSModel_InitialExec,
39 | TLSModel_LocalExec]> {
40 | let cppNamespace = "mlir::gccjit";
41 | }
42 |
43 | def TLSModelAttr : GCCJIT_Attr<"TLSModel", "tls_model"> {
44 | let summary = "Thread Local Storage model";
45 | let parameters = (ins "TLSModelEnumAttr":$model);
46 | let description = [{
47 | Represents the Thread Local Storage model for the lvalue.
48 | }];
49 | let hasCustomAssemblyFormat = 1;
50 | let extraClassDeclaration = [{
51 | bool isNone() const { return getModel().getValue() == TLSModelEnum::None; }
52 | bool isGlobalDynamic() const {
53 | return getModel().getValue() == TLSModelEnum::GlobalDynamic;
54 | }
55 | bool isLocalDynamic() const {
56 | return getModel().getValue() == TLSModelEnum::LocalDynamic;
57 | }
58 | bool isInitialExec() const {
59 | return getModel().getValue() == TLSModelEnum::InitialExec;
60 | }
61 | bool isLocalExec() const {
62 | return getModel().getValue() == TLSModelEnum::LocalExec;
63 | }
64 | }];
65 | let genVerifyDecl = 0;
66 | }
67 |
68 | //===----------------------------------------------------------------------===//
69 | // Integer Attrs
70 | //===----------------------------------------------------------------------===//
71 | def IntAttr : GCCJIT_Attr<"Int", "int", [TypedAttrInterface]> {
72 | let summary = "An attribute containing a integer value";
73 | let description = [{
74 | An `#gccjit.int` attribute represents a constant integer value of some
75 | libgccjit integer type.
76 |
77 | Example:
78 | ```mlir
79 | #gccjit.int<42>
80 | ```
81 | }];
82 | let parameters = (ins
83 | AttributeSelfTypeParameter<"", "mlir::gccjit::IntType">:$type,
84 | "::mlir::APInt":$value
85 | );
86 | let hasCustomAssemblyFormat = 1;
87 | }
88 |
89 | //===----------------------------------------------------------------------===//
90 | // Floating-point Attrs
91 | //===----------------------------------------------------------------------===//
92 | def FloatAttr : GCCJIT_Attr<"Float", "float", [TypedAttrInterface]> {
93 | let summary = "An attribute containing a constant floating-point value";
94 | let description = [{
95 | A `#gccjit.float` attribute represents a constant floating-point value of
96 | some libgccjit floating-point type.
97 |
98 | Example:
99 | ```mlir
100 | #gccjit.float<42.0>
101 | ```
102 | }];
103 |
104 | let parameters = (ins
105 | AttributeSelfTypeParameter<"", "mlir::gccjit::FloatType">:$type,
106 | "::mlir::APFloat":$value
107 | );
108 | let hasCustomAssemblyFormat = 1;
109 | }
110 |
111 | //===----------------------------------------------------------------------===//
112 | // Special constant attributes
113 | //===----------------------------------------------------------------------===//
114 |
115 | def ZeroAttr : GCCJIT_Attr<"Zero", "zero", [TypedAttrInterface]> {
116 | let summary = "An attribute containing a constant zero";
117 | let description = [{
118 | A `#gccjit.zero` attribute represents a constant zero value of some
119 | libgccjit integer or floating-point type.
120 | }];
121 |
122 | let parameters = (ins AttributeSelfTypeParameter<"">:$type);
123 |
124 | let assemblyFormat = "";
125 | let genVerifyDecl = 1;
126 | }
127 |
128 | def OneAttr : GCCJIT_Attr<"One", "one", [TypedAttrInterface]> {
129 | let summary = "An attribute containing a constant one";
130 | let description = [{
131 | A `#gccjit.one` attribute represents a constant one value of some
132 | libgccjit integer or floating-point type.
133 | }];
134 |
135 | let parameters = (ins AttributeSelfTypeParameter<"">:$type);
136 |
137 | let assemblyFormat = "";
138 | let genVerifyDecl = 1;
139 | }
140 |
141 | def NullAttr : GCCJIT_Attr<"Null", "null", [TypedAttrInterface]> {
142 | let summary = "An attribute containing a null pointer constant";
143 | let description = [{
144 | A `#gccjit.null` attribute represents a constant null pointer value of some
145 | libgccjit pointer type.
146 | }];
147 |
148 | let parameters = (ins
149 | AttributeSelfTypeParameter<"", "mlir::gccjit::PointerType">:$type);
150 |
151 | let assemblyFormat = "";
152 | }
153 |
154 | //===----------------------------------------------------------------------===//
155 | // SourceLoc Attr
156 | //===----------------------------------------------------------------------===//
157 |
158 | def SourceLocAttr : GCCJIT_Attr<"SourceLoc", "loc"> {
159 | let summary = "Source location";
160 | let description = [{
161 | Represent a source location in GCCJIT.
162 | }];
163 | let parameters = (ins "mlir::StringAttr":$filename, "int":$line,
164 | "int":$column);
165 | let assemblyFormat = [{
166 | `<` $filename `:` $line `:` $column `>`
167 | }];
168 | }
169 |
170 | //===----------------------------------------------------------------------===//
171 | // Record field attribute
172 | //===----------------------------------------------------------------------===//
173 |
174 | def FieldAttr : GCCJIT_Attr<"Field", "field"> {
175 | let summary = "A field within a struct or a union";
176 | let description = [{
177 | The `#gccjit.field` attribute represents a field within a record (i.e. a
178 | record or a union).
179 |
180 | When the `bitWidth` parameter is present, the attribute represents a
181 | bitfield. The `bitWidth` parameter gives the width of the bitfield.
182 | }];
183 |
184 | let parameters = (ins
185 | "mlir::StringAttr":$name, "mlir::Type":$type,
186 | OptionalParameter<"std::optional">:$bitWidth,
187 | OptionalParameter<"std::optional">:$loc
188 | );
189 |
190 | let builders = [
191 | AttrBuilder<(ins "mlir::StringAttr":$name, "mlir::Type":$type), [{
192 | return get($_ctxt, name, type, std::nullopt, std::nullopt);
193 | }]>,
194 | AttrBuilder<(ins "mlir::StringAttr":$name, "mlir::Type":$type,
195 | "unsigned":$bitWidth), [{
196 | return get($_ctxt, name, type, bitWidth, std::nullopt);
197 | }]>,
198 | AttrBuilder<(ins "mlir::StringAttr":$name, "mlir::Type":$type,
199 | "mlir::gccjit::SourceLocAttr":$loc), [{
200 | return get($_ctxt, name, type, std::nullopt, loc);
201 | }]>,
202 | ];
203 |
204 | // attribute can eat up the `:` separator, so we need to move the name to the
205 | // front
206 | let assemblyFormat = [{
207 | `<` $name $type (`:` $bitWidth^)? ($loc^)? `>`
208 | }];
209 | }
210 |
211 | //===----------------------------------------------------------------------===//
212 | // OptLevel Attr
213 | //===----------------------------------------------------------------------===//
214 |
215 | def OptLevel_0 : I32EnumAttrCase<"O0", 0, "O0">;
216 | def OptLevel_1 : I32EnumAttrCase<"O1", 1, "O1">;
217 | def OptLevel_2 : I32EnumAttrCase<"O2", 2, "O2">;
218 | def OptLevel_3 : I32EnumAttrCase<"O3", 3, "O3">;
219 | def OptLevelEnum : I32EnumAttr<"OptLevelEnum", "Optimization level",
220 | [OptLevel_0, OptLevel_1, OptLevel_2, OptLevel_3]> {
221 | let cppNamespace = "mlir::gccjit";
222 | }
223 | def OptLevelAttr : GCCJIT_Attr<"OptLevel", "opt_level"> {
224 | let summary = "Optimization level";
225 | let parameters = (ins "OptLevelEnumAttr":$level);
226 | let description = [{
227 | Represents the optimization level.
228 | }];
229 | let hasCustomAssemblyFormat = 1;
230 | let extraClassDeclaration = [{
231 | bool isO0() const { return getLevel().getValue() == OptLevelEnum::O0; }
232 | bool isO1() const { return getLevel().getValue() == OptLevelEnum::O1; }
233 | bool isO2() const { return getLevel().getValue() == OptLevelEnum::O2; }
234 | bool isO3() const { return getLevel().getValue() == OptLevelEnum::O3; }
235 | }];
236 | let genVerifyDecl = 0;
237 | }
238 |
239 | //===----------------------------------------------------------------------===//
240 | // Function Attributes
241 | //===----------------------------------------------------------------------===//
242 | def FnAttr_Alias : I32EnumAttrCase<"Alias", 0, "alias">;
243 | def FnAttr_AlwaysInline : I32EnumAttrCase<"AlwaysInline", 1, "always_inline">;
244 | def FnAttr_Inline : I32EnumAttrCase<"Inline", 2, "inline">;
245 | def FnAttr_NoInline : I32EnumAttrCase<"NoInline", 3, "noinline">;
246 | def FnAttr_Target : I32EnumAttrCase<"Target", 4, "target">;
247 | def FnAttr_Used : I32EnumAttrCase<"Used", 5, "used">;
248 | def FnAttr_Visibility : I32EnumAttrCase<"Visibility", 6, "visibility">;
249 | def FnAttr_Cold : I32EnumAttrCase<"Cold", 7, "cold">;
250 | def FnAttr_ReturnsTwice : I32EnumAttrCase<"ReturnsTwice", 8, "returns_twice">;
251 | def FnAttr_Pure : I32EnumAttrCase<"Pure", 9, "pure">;
252 | def FnAttr_Const : I32EnumAttrCase<"Const", 10, "const">;
253 | def FnAttr_Weak : I32EnumAttrCase<"Weak", 11, "weak">;
254 | def FnAttr_Nonnull : I32EnumAttrCase<"Nonnull", 12, "nonnull">;
255 | def FnAttrEnum : I32EnumAttr<"FnAttrEnum", "Function attribute",
256 | [FnAttr_Alias, FnAttr_AlwaysInline, FnAttr_Inline,
257 | FnAttr_NoInline, FnAttr_Target, FnAttr_Used,
258 | FnAttr_Visibility, FnAttr_Cold, FnAttr_ReturnsTwice,
259 | FnAttr_Pure, FnAttr_Const, FnAttr_Weak,
260 | FnAttr_Nonnull]> {
261 | let cppNamespace = "mlir::gccjit";
262 | }
263 |
264 | def FnAttr : GCCJIT_Attr<"Function", "fn_attr"> {
265 | let summary = "Function Attribute";
266 | let description = [{
267 | A `#gccjit.fn_attr` attribute represents a function attribute.
268 | There three types of function attributes:
269 | - unit attributes: those without a value.
270 | - string attributes: those with a string value.
271 | - integer array attributes: those with an array of integers.
272 | }];
273 |
274 | let parameters = (ins
275 | "FnAttrEnumAttr":$attr,
276 | OptionalParameter<"std::optional">:$strValue,
277 | OptionalParameter<"std::optional">:$intArrayValue
278 | );
279 |
280 | let hasCustomAssemblyFormat = 1;
281 | let genVerifyDecl = 0;
282 | }
283 |
284 | //===----------------------------------------------------------------------===//
285 | // ByteArrayInitializer Attr
286 | //===----------------------------------------------------------------------===//
287 | def ByteArrayInitializerAttr : GCCJIT_Attr<"ByteArrayInitializer",
288 | "byte_array"> {
289 | let summary = "Byte array initializer";
290 | let parameters = (ins "DenseI8ArrayAttr":$initializer);
291 | let description = [{
292 | Represents the byte array initializer.
293 | }];
294 | let assemblyFormat = [{
295 | `<` $initializer `>`
296 | }];
297 | }
298 | #endif // MLIR_GCCJIT_IR_GCCJIT_ATTRS
299 |
300 |
301 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/IR/GCCJITDialect.h:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Sirui Mu
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MLIR_GCCJIT_IR_GCCJIT_DIALECT_H
16 | #define MLIR_GCCJIT_IR_GCCJIT_DIALECT_H
17 |
18 | #include
19 |
20 | #include "mlir-gccjit/IR/GCCJITOpsDialect.h.inc"
21 |
22 | #endif // MLIR_GCCJIT_IR_GCCJIT_DIALECT_H
23 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/IR/GCCJITDialect.td:
--------------------------------------------------------------------------------
1 | #ifndef GCCJIT_DIALECT
2 | #define GCCJIT_DIALECT
3 |
4 | include "mlir/IR/OpBase.td"
5 |
6 | def GCCJIT_Dialect : Dialect {
7 | let name = "gccjit";
8 |
9 | let summary = "Dialect for libgccjit";
10 | let description = [{
11 | The gccjit dialect allows you to generate code with libgccjit through MLIR.
12 | }];
13 |
14 | let cppNamespace = "::mlir::gccjit";
15 |
16 | let useDefaultAttributePrinterParser = 0;
17 | let useDefaultTypePrinterParser = 0;
18 |
19 | let dependentDialects = [
20 | "::mlir::BuiltinDialect",
21 | "::mlir::func::FuncDialect",
22 | ];
23 |
24 | let extraClassDeclaration = [{
25 | void registerTypes();
26 | void registerAttributes();
27 | Type parseType(DialectAsmParser &parser) const override;
28 | void printType(Type type, DialectAsmPrinter &printer) const override;
29 | Attribute parseAttribute(DialectAsmParser &parser,
30 | Type type) const override;
31 |
32 | void printAttribute(Attribute attr, DialectAsmPrinter &os) const override;
33 | }];
34 | }
35 |
36 | class GCCJIT_Op traits = []>
37 | : Op;
38 |
39 | #endif // GCCJIT_DIALECT
40 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/IR/GCCJITOps.h:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Sirui Mu
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MLIR_GCCJIT_IR_GCCJIT_OPS_H
16 | #define MLIR_GCCJIT_IR_GCCJIT_OPS_H
17 |
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 |
31 | #include "mlir-gccjit/IR/GCCJITAttrs.h"
32 | #include "mlir-gccjit/IR/GCCJITOpsEnums.h"
33 | #include "mlir-gccjit/IR/GCCJITTypes.h"
34 |
35 | #define GET_OP_CLASSES
36 | #include "mlir-gccjit/IR/GCCJITOps.h.inc"
37 |
38 | #endif // MLIR_GCCJIT_IR_GCCJIT_OPS_H
39 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/IR/GCCJITOpsEnums.h:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Schrodinger ZHU Yifan
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MLIR_GCCJIT_IR_GCCJIT_OPS_ENUMS_H
16 | #define MLIR_GCCJIT_IR_GCCJIT_OPS_ENUMS_H
17 |
18 | #include
19 |
20 | #include "mlir-gccjit/IR/GCCJITOpsEnums.h.inc"
21 |
22 | #endif // MLIR_GCCJIT_IR_GCCJIT_OPS_ENUMS_H
23 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/IR/GCCJITTypes.h:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Sirui Mu
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MLIR_GCCJIT_IR_GCCJIT_TYPES_H
16 | #define MLIR_GCCJIT_IR_GCCJIT_TYPES_H
17 |
18 | #include
19 | #include
20 | #include
21 |
22 | #include "mlir-gccjit/IR/GCCJITAttrs.h"
23 | #include "mlir-gccjit/IR/Interfaces/GCCJITRecordTypeInterface.h"
24 |
25 | namespace mlir::gccjit {
26 | class FieldAttr;
27 | class SourceLocAttr;
28 | } // namespace mlir::gccjit
29 |
30 | #define GET_TYPEDEF_CLASSES
31 | #include "mlir-gccjit/IR/GCCJITOpsTypes.h.inc"
32 |
33 | //===----------------------------------------------------------------------===//
34 | // GCCJIT Custom Parser/Printer Signatures
35 | //===----------------------------------------------------------------------===//
36 | namespace mlir::gccjit {
37 | mlir::ParseResult parseFuncTypeArgs(mlir::AsmParser &p,
38 | llvm::SmallVector ¶ms,
39 | bool &isVarArg);
40 | void printFuncTypeArgs(mlir::AsmPrinter &p, mlir::ArrayRef params,
41 | bool isVarArg);
42 |
43 | inline bool isIntegral(mlir::Type type) {
44 | if (auto qualified = dyn_cast(type))
45 | return isIntegral(qualified.getElementType());
46 |
47 | return isa(type);
48 | }
49 |
50 | inline bool isIntegralOrPointer(mlir::Type type) {
51 | if (auto qualified = dyn_cast(type))
52 | return isIntegralOrPointer(qualified.getElementType());
53 | return isa(type) || isa(type);
54 | }
55 |
56 | inline bool isPointer(mlir::Type type) {
57 | if (auto qualified = dyn_cast(type))
58 | return isPointer(qualified.getElementType());
59 | return isa(type);
60 | }
61 |
62 | inline bool isArithmetc(mlir::Type type) {
63 | if (auto qualified = dyn_cast(type))
64 | return isArithmetc(qualified.getElementType());
65 | return isa(type) || isa(type);
66 | }
67 |
68 | inline bool isArithmetcOrPointer(mlir::Type type) {
69 | if (auto qualified = dyn_cast(type))
70 | return isArithmetcOrPointer(qualified.getElementType());
71 | return isa(type) || isa(type) || isa(type);
72 | }
73 | } // namespace mlir::gccjit
74 |
75 | #endif // MLIR_GCCJIT_IR_GCCJIT_TYPES_H
76 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/IR/GCCJITTypes.td:
--------------------------------------------------------------------------------
1 | #ifndef GCCJIT_TYPES
2 | #define GCCJIT_TYPES
3 |
4 | include "mlir/IR/AttrTypeBase.td"
5 |
6 | include "mlir-gccjit/IR/GCCJITDialect.td"
7 | include "mlir-gccjit/IR/Interfaces/GCCJITRecordTypeInterface.td"
8 |
9 | class GCCJIT_Type traits = []>
10 | : TypeDef {
11 | let mnemonic = typeMnemonic;
12 | }
13 |
14 | def GCCJIT_LValueType : GCCJIT_Type<"LValue", "lvalue"> {
15 | let summary = "LValue type";
16 | let description = [{
17 | `gccjit.lvalue` represents a lvalue in the meaning of C. It behaves
18 | like a reference to a mutable memory location. Lvalues are addressable,
19 | so one can get a pointer from them. Lvalue's subfield can be projected as
20 | a new lvalue, while rvalue's subfield can be projected as a new rvalue.
21 | There are generally three ways to obtain an lvalue:
22 | 1. create a local lvalue with respect to current function
23 | 2. create a global lvalue with respect to current module
24 | 3. function parameters in gimple are also lvalues
25 |
26 | See also [`gccjit::lvalue`](https://gcc.gnu.org/onlinedocs/jit/cp/topics/expressions.html#_CPPv4N6gccjit6lvalueE).
27 | }];
28 | let parameters = (ins "mlir::Type":$innerType);
29 | let assemblyFormat = [{
30 | `<` $innerType `>`
31 | }];
32 | }
33 |
34 | //===----------------------------------------------------------------------===//
35 | // FuncType
36 | //===----------------------------------------------------------------------===//
37 |
38 | def GCCJIT_FuncType : GCCJIT_Type<"Func", "func"> {
39 | let summary = "GCCJIT function type";
40 | let description = [{
41 | The `!gccjit.func` is a function type. It consists of a single return type,
42 | a list of parameter types and can optionally be variadic.
43 | }];
44 |
45 | let parameters = (ins ArrayRefParameter<"Type">:$inputs, "Type":$returnType,
46 | "bool":$varArg);
47 | let assemblyFormat = [{
48 | `<` $returnType ` ` `(` custom($inputs, $varArg) `>`
49 | }];
50 |
51 | let builders = [
52 | TypeBuilderWithInferredContext<(ins
53 | "ArrayRef":$inputs, "Type":$returnType,
54 | CArg<"bool", "false">:$isVarArg), [{
55 | return $_get(returnType.getContext(), inputs, returnType, isVarArg);
56 | }]>
57 | ];
58 |
59 | let extraClassDeclaration = [{
60 | /// Returns whether the function is variadic.
61 | bool isVarArg() const { return getVarArg(); }
62 |
63 | /// Returns the `i`th input operand type. Asserts if out of bounds.
64 | Type getInput(unsigned i) const { return getInputs()[i]; }
65 |
66 | /// Returns the number of arguments to the function.
67 | unsigned getNumInputs() const { return getInputs().size(); }
68 |
69 | /// Returns the result type of the function as an ArrayRef, enabling better
70 | /// integration with generic MLIR utilities.
71 | ArrayRef getReturnTypes() const;
72 |
73 | /// Returns whether the function is returns void.
74 | bool isVoid() const;
75 |
76 | /// Returns a clone of this function type with the given argument
77 | /// and result types.
78 | FuncType clone(TypeRange inputs, TypeRange results) const;
79 | }];
80 | }
81 |
82 | //===----------------------------------------------------------------------===//
83 | // Void type
84 | //===----------------------------------------------------------------------===//
85 |
86 | def GCCJIT_VoidType : GCCJIT_Type<"Void", "void"> {
87 | let summary = "GCCJIT void type";
88 | let description = [{
89 | The `!gccjit.void` type represents the C/C++ `void` type.
90 | }];
91 | let extraClassDeclaration = [{
92 | /// Returns a clone of this type with the given context.
93 | std::string getAlias() const { return "void"; };
94 | }];
95 | }
96 |
97 | //===----------------------------------------------------------------------===//
98 | // Pointer type
99 | //===----------------------------------------------------------------------===//
100 |
101 | def GCCJIT_PointerType : GCCJIT_Type<"Pointer", "ptr"> {
102 | let summary = "GCCJIT pointer type";
103 | let description = [{
104 | The `!gccjit.ptr` type represents a pointer type. It consists of a single
105 | element type.
106 | }];
107 | let parameters = (ins "mlir::Type":$elementType);
108 | let assemblyFormat = [{
109 | `<` $elementType `>`
110 | }];
111 | }
112 |
113 | //===----------------------------------------------------------------------===//
114 | // Qualified type
115 | //===----------------------------------------------------------------------===//
116 |
117 | def GCCJIT_QualifiedType : GCCJIT_Type<"Qualified", "qualified"> {
118 | let summary = "GCCJIT qualified type";
119 | let description = [{
120 | GCCJIT type can be qualified with `const`, `restrict`, `volatile`.
121 | }];
122 | let parameters = (ins "mlir::Type":$elementType, "bool":$isConst,
123 | "bool":$isRestrict, "bool":$isVolatile);
124 | let hasCustomAssemblyFormat = 1;
125 | }
126 |
127 | //===----------------------------------------------------------------------===//
128 | // Integer type
129 | //===----------------------------------------------------------------------===//
130 |
131 | def GCCJIT_IntType : GCCJIT_Type<"Int", "int"> {
132 | let summary = "Integer type";
133 | let description = [{
134 | GCCJIT type that represents integer types with arbitrary precision:
135 | - GCCJIT type can be either explicitly sized or not.
136 | - GCCJIT type can be either signed or unsigned.
137 | }];
138 |
139 | let parameters = (ins "::gcc_jit_types":$kind);
140 | let hasCustomAssemblyFormat = 1;
141 | }
142 |
143 | class SpecificInt
144 | : Type($_self)">,
146 | CPred<"::mlir::cast<::mlir::gccjit::IntType>($_self).getKind() == "
147 | # enumValue>
148 | ]>, "integer with " #enumValue, "::mlir::gccjit::IntType">,
149 | BuildableType<
150 | "mlir::gccjit::IntType::get($_builder.getContext(), "
151 | # enumValue # ")"> {
152 | }
153 |
154 | def GCCJIT_BoolType : SpecificInt<"GCC_JIT_TYPE_BOOL">;
155 |
156 | //===----------------------------------------------------------------------===//
157 | // Float type
158 | //===----------------------------------------------------------------------===//
159 |
160 | def GCCJIT_FloatType : GCCJIT_Type<"Float", "fp"> {
161 | let summary = "Floating point type";
162 | let description = [{
163 | GCCJIT type that represents floating point types
164 | }];
165 |
166 | let parameters = (ins "::gcc_jit_types":$kind);
167 | let hasCustomAssemblyFormat = 1;
168 | }
169 |
170 | //===----------------------------------------------------------------------===//
171 | // Complex type
172 | //===----------------------------------------------------------------------===//
173 |
174 | def GCCJIT_ComplexType : GCCJIT_Type<"Complex", "complex"> {
175 | let summary = "Complex type";
176 | let description = [{
177 | GCCJIT type that represents complex types
178 | }];
179 |
180 | let parameters = (ins "::gcc_jit_types":$kind);
181 | let hasCustomAssemblyFormat = 1;
182 | }
183 |
184 | //===----------------------------------------------------------------------===//
185 | // Array type
186 | //===----------------------------------------------------------------------===//
187 | def GCCJIT_ArrayType : GCCJIT_Type<"Array", "array"> {
188 | let summary = "GCCJIT array type";
189 | let description = [{
190 | The `!gccjit.array` type represents an array type. It consists of a single
191 | element type and a constant length.
192 | }];
193 | let parameters = (ins "mlir::Type":$elementType, "unsigned":$size);
194 | let assemblyFormat = [{
195 | `<` $elementType `,` $size `>`
196 | }];
197 | }
198 |
199 | //===----------------------------------------------------------------------===//
200 | // Vector type
201 | //===----------------------------------------------------------------------===//
202 | def GCCJIT_VectorType : GCCJIT_Type<"Vector", "vector"> {
203 | let summary = "GCCJIT vector type";
204 | let description = [{
205 | The `!gccjit.vector` type represents a vector type. It consists of a single
206 | element type and a constant length.
207 | }];
208 | let parameters = (ins "mlir::Type":$elementType, "unsigned":$numUnits);
209 | let assemblyFormat = [{
210 | `<` $elementType `,` $numUnits `>`
211 | }];
212 | }
213 |
214 | //===----------------------------------------------------------------------===//
215 | // Struct and union type
216 | //===----------------------------------------------------------------------===//
217 | class GCCJIT_RecordType
218 | : GCCJIT_Type
220 | ]> {
221 | let parameters = (ins
222 | "mlir::StringAttr":$name,
223 | "mlir::ArrayAttr":$fields,
224 | OptionalParameter<"std::optional">:$loc
225 | );
226 | let assemblyFormat = [{
227 | `<` custom($name, $fields, $loc) `>`
228 | }];
229 |
230 | let builders = [
231 | TypeBuilder<(ins "mlir::StringAttr":$name,
232 | "mlir::ArrayAttr":$fields), [{
233 | return get($_ctxt, name, fields, std::nullopt);
234 | }]>,
235 | TypeBuilder<(ins "llvm::StringRef":$name,
236 | "llvm::ArrayRef":$fields), [{
237 | auto nameAttr = StringAttr::get($_ctxt, name);
238 | auto fieldsAttr = ArrayAttr::get(
239 | $_ctxt, llvm::SmallVector(fields.begin(), fields.end()));
240 | return get($_ctxt, nameAttr, fieldsAttr);
241 | }]>,
242 | TypeBuilder<(ins "llvm::StringRef":$name,
243 | "llvm::ArrayRef":$fields,
244 | "mlir::gccjit::SourceLocAttr":$loc), [{
245 | auto nameAttr = StringAttr::get($_ctxt, name);
246 | auto fieldsAttr = ArrayAttr::get(
247 | $_ctxt, llvm::SmallVector(fields.begin(), fields.end()));
248 | return get($_ctxt, nameAttr, fieldsAttr, loc);
249 | }]>
250 | ];
251 |
252 | let genVerifyDecl = 1;
253 | }
254 |
255 | def GCCJIT_StructType : GCCJIT_RecordType<"Struct", "struct"> {
256 | let summary = "GCCJIT struct type";
257 | let description = [{
258 | The `!gccjit.struct` type represents a GCCJIT struct type.
259 | }];
260 | }
261 |
262 | def GCCJIT_UnionType : GCCJIT_RecordType<"Union", "union"> {
263 | let summary = "GCCJIT union type";
264 | let description = [{
265 | The `!gccjit.union` type represents a GCCJIT union type.
266 | }];
267 | }
268 |
269 | #endif // GCCJIT_TYPES
270 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/IR/Interfaces/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | function(add_gccjit_mlir_attr_interface interface)
2 | set(LLVM_TARGET_DEFINITIONS ${interface}.td)
3 | mlir_tablegen(${interface}.h.inc -gen-attr-interface-decls)
4 | mlir_tablegen(${interface}.cpp.inc -gen-attr-interface-defs)
5 | add_public_tablegen_target(MLIRCIR${interface}IncGen)
6 | add_dependencies(mlir-headers MLIRCIR${interface}IncGen)
7 | endfunction()
8 |
9 | function(add_gccjit_mlir_op_interface interface)
10 | set(LLVM_TARGET_DEFINITIONS ${interface}.td)
11 | mlir_tablegen(${interface}.h.inc -gen-op-interface-decls)
12 | mlir_tablegen(${interface}.cpp.inc -gen-op-interface-defs)
13 | add_public_tablegen_target(MLIR${interface}IncGen)
14 | add_dependencies(mlir-headers MLIR${interface}IncGen)
15 | endfunction()
16 |
17 | function(add_gccjit_mlir_type_interface interface)
18 | set(LLVM_TARGET_DEFINITIONS ${interface}.td)
19 | mlir_tablegen(${interface}.h.inc -gen-type-interface-decls)
20 | mlir_tablegen(${interface}.cpp.inc -gen-type-interface-defs)
21 | add_public_tablegen_target(MLIR${interface}IncGen)
22 | add_dependencies(mlir-headers MLIR${interface}IncGen)
23 | endfunction()
24 |
25 | add_gccjit_mlir_type_interface(GCCJITRecordTypeInterface)
26 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/IR/Interfaces/GCCJITRecordTypeInterface.h:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Sirui Mu
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef CLANG_INTERFACES_CIR_CIR_FPTYPEINTERFACE_H
16 | #define CLANG_INTERFACES_CIR_CIR_FPTYPEINTERFACE_H
17 |
18 | #include
19 | #include
20 |
21 | #include "mlir-gccjit/IR/GCCJITAttrs.h"
22 |
23 | /// Include the tablegen'd interface declarations.
24 | #include "mlir-gccjit/IR/Interfaces/GCCJITRecordTypeInterface.h.inc"
25 |
26 | #endif // CLANG_INTERFACES_CIR_CIR_FPTYPEINTERFACE_H
--------------------------------------------------------------------------------
/include/mlir-gccjit/IR/Interfaces/GCCJITRecordTypeInterface.td:
--------------------------------------------------------------------------------
1 | #ifndef MLIR_GCCJIT_IR_INTERFACES_GCCJIT_RECORD_TYPE_INTERFACE
2 | #define MLIR_GCCJIT_IR_INTERFACES_GCCJIT_RECORD_TYPE_INTERFACE
3 |
4 | include "mlir/IR/OpBase.td"
5 |
6 | def GCCJITRecordTypeInterface : TypeInterface<"GCCJITRecordTypeInterface"> {
7 | let description = [{
8 | Contains helper functions to query properties about a GCCJIT record type.
9 |
10 | A record type is either a struct type or a union type.
11 | }];
12 | let cppNamespace = "::mlir::gccjit";
13 |
14 | let methods = [
15 | InterfaceMethod<
16 | "Determine whether this record is a union",
17 | /*retTy=*/"bool",
18 | /*methodName=*/"isUnion"
19 | >,
20 | InterfaceMethod<
21 | "Get the name of this record",
22 | /*retTy=*/"llvm::StringRef",
23 | /*methodName=*/"getRecordName"
24 | >,
25 | InterfaceMethod<
26 | [{
27 | Get the fields in this record, as an ArrayAttr attribute whose elements
28 | are FieldAttr attributes.
29 | }],
30 | /*retTy=*/"ArrayAttr",
31 | /*methodName=*/"getRecordFields"
32 | >,
33 | InterfaceMethod<
34 | [{
35 | Get the source location of this record.
36 | }],
37 | /*retTy=*/"mlir::gccjit::SourceLocAttr",
38 | /*methodName=*/"getRecordLoc"
39 | >
40 | ];
41 | }
42 |
43 | #endif // MLIR_GCCJIT_IR_INTERFACES_GCCJIT_RECORD_TYPE_INTERFACE
44 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/Passes.h:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Schrodinger ZHU Yifan
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MLIR_GCCJIT_PASSES_H
16 | #define MLIR_GCCJIT_PASSES_H
17 |
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | #include "mlir-gccjit/IR/GCCJITDialect.h"
27 |
28 | namespace mlir::gccjit {
29 |
30 | std::unique_ptr createConvertFuncToGCCJITPass();
31 | std::unique_ptr createConvertArithToGCCJITPass();
32 | std::unique_ptr createConvertMemrefToGCCJITPass();
33 |
34 | #define GEN_PASS_CLASSES
35 | #define GEN_PASS_REGISTRATION
36 | #define GEN_PASS_DECL
37 | #include "mlir-gccjit/Passes.h.inc"
38 |
39 | } // namespace mlir::gccjit
40 |
41 | #endif // MLIR_GCCJIT_PASSES_H
42 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/Passes.td:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Schrodinger ZHU Yifan
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MLIR_GCCJIT_PASSES
16 | #define MLIR_GCCJIT_PASSES
17 |
18 | include "mlir/Pass/PassBase.td"
19 |
20 | def ConvertFuncToGCCJIT : Pass<"convert-func-to-gccjit", "::mlir::ModuleOp"> {
21 | let summary = "Convert Functions and control flows to GCCJIT Dialect";
22 | let description = [{
23 | This pass converts function operations and control flow operations to GCCJIT
24 | dialect.
25 | }];
26 | let constructor = "::mlir::gccjit::createConvertFuncToGCCJITPass()";
27 | let dependentDialects = [
28 | "::mlir::gccjit::GCCJITDialect",
29 | "::mlir::func::FuncDialect",
30 | "::mlir::BuiltinDialect",
31 | "::mlir::cf::ControlFlowDialect"
32 | ];
33 | }
34 |
35 | def ConvertArithToGCCJIT : Pass<"convert-arith-to-gccjit", "::mlir::ModuleOp"> {
36 | let summary = "Convert Arithmetic Operations to GCCJIT Dialect";
37 | let description = [{
38 | `-convert-arith-to-gccjit` converts arithmetic operations to GCCJIT dialect.
39 | }];
40 | let constructor = "::mlir::gccjit::createConvertArithToGCCJITPass()";
41 | let dependentDialects = [
42 | "::mlir::gccjit::GCCJITDialect",
43 | "::mlir::arith::ArithDialect"
44 | ];
45 | }
46 |
47 | def ConvertMemrefToGCCJIT : Pass<"convert-memref-to-gccjit",
48 | "::mlir::ModuleOp"> {
49 | let summary = "Convert Memref Operations to GCCJIT Dialect";
50 | let description = [{
51 | `-convert-memref-to-gccjit` converts memref operations to GCCJIT dialect.
52 | }];
53 | let constructor = "::mlir::gccjit::createConvertMemrefToGCCJITPass()";
54 | let dependentDialects = [
55 | "::mlir::gccjit::GCCJITDialect",
56 | "::mlir::memref::MemRefDialect"
57 | ];
58 | }
59 |
60 | #endif // MLIR_GCCJIT_PASSES
61 |
--------------------------------------------------------------------------------
/include/mlir-gccjit/Translation/TranslateToGCCJIT.h:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Schrodinger ZHU Yifan
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef MLIR_GCCJIT_TRANSLATION_TRANSLATETOGCCJIT_H
16 | #define MLIR_GCCJIT_TRANSLATION_TRANSLATETOGCCJIT_H
17 |
18 | #include
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | #include
27 |
28 | #include "mlir-gccjit/IR/GCCJITAttrs.h"
29 | #include "mlir-gccjit/IR/GCCJITTypes.h"
30 |
31 | namespace mlir::gccjit {
32 |
33 | void registerToGCCJITGimpleTranslation();
34 | void registerToGCCJITReproducerTranslation();
35 | void registerToGCCJITAssemblyTranslation();
36 | void registerToGCCJITObjectTranslation();
37 | void registerToGCCJITExecutableTranslation();
38 | void registerToGCCJITDylibTranslation();
39 |
40 | struct GCCJITContextDeleter {
41 | void operator()(gcc_jit_context *ctxt) const;
42 | };
43 | using GCCJITContext = std::unique_ptr;
44 |
45 | class GCCJITTranslation {
46 | class FunctionEntry;
47 | class StructEntry;
48 | class UnionEntry;
49 |
50 | public:
51 | GCCJITTranslation();
52 | ~GCCJITTranslation();
53 |
54 | gcc_jit_context *getContext() const;
55 | GCCJITContext takeContext();
56 |
57 | MLIRContext *getMLIRContext() const { return moduleOp->getContext(); }
58 |
59 | void translateModuleToGCCJIT(ModuleOp op);
60 |
61 | size_t getTypeSize(Type type);
62 |
63 | gcc_jit_type *convertType(Type type);
64 | void convertTypes(TypeRange types, llvm::SmallVector &result);
65 |
66 | gcc_jit_location *getLocation(LocationAttr loc);
67 | gcc_jit_location *convertLocation(SourceLocAttr loc);
68 |
69 | gcc_jit_lvalue *getGlobalLValue(SymbolRefAttr symbol);
70 | FunctionEntry getFunction(SymbolRefAttr symbol);
71 |
72 | private:
73 | class FunctionEntry {
74 | gcc_jit_function *fnHandle;
75 |
76 | public:
77 | FunctionEntry() : fnHandle(nullptr) {}
78 | FunctionEntry(gcc_jit_function *fnHandle) : fnHandle(fnHandle) {}
79 | operator gcc_jit_function *() const { return fnHandle; }
80 | size_t getParamCount() const {
81 | assert(fnHandle);
82 | return gcc_jit_function_get_param_count(fnHandle);
83 | }
84 | gcc_jit_param *operator[](size_t index) const {
85 | assert(fnHandle);
86 | return gcc_jit_function_get_param(fnHandle, index);
87 | }
88 | };
89 |
90 | class StructEntry {
91 | gcc_jit_struct *structHandle;
92 |
93 | public:
94 | StructEntry(gcc_jit_struct *structHandle) : structHandle(structHandle) {}
95 | gcc_jit_struct *getRawHandle() const { return structHandle; }
96 | size_t getFieldCount() const {
97 | return gcc_jit_struct_get_field_count(structHandle);
98 | }
99 | gcc_jit_field *operator[](size_t index) const {
100 | return gcc_jit_struct_get_field(structHandle, index);
101 | }
102 | gcc_jit_type *getTypeHandle() const {
103 | return gcc_jit_struct_as_type(structHandle);
104 | }
105 | };
106 |
107 | class UnionEntry {
108 | gcc_jit_type *unionHandle;
109 | llvm::SmallVector fields;
110 |
111 | public:
112 | UnionEntry(gcc_jit_type *unionHandle, ArrayRef fields)
113 | : unionHandle(unionHandle), fields(fields) {}
114 | gcc_jit_type *getRawHandle() const { return unionHandle; }
115 | size_t getFieldCount() const { return fields.size(); }
116 | gcc_jit_field *operator[](size_t index) const { return fields[index]; }
117 | gcc_jit_type *getTypeHandle() const { return unionHandle; }
118 | };
119 |
120 | class GCCJITRecord : public llvm::PointerUnion {
121 | public:
122 | using PointerUnion::PointerUnion;
123 | gcc_jit_struct *getAsStruct() const {
124 | return this->get()->getRawHandle();
125 | }
126 | gcc_jit_type *getAsType() const {
127 | return this->is() ? get()->getTypeHandle()
128 | : get()->getRawHandle();
129 | }
130 | gcc_jit_field *operator[](size_t index) const {
131 | if (this->is())
132 | return get()->operator[](index);
133 | return get()->operator[](index);
134 | }
135 | size_t getFieldCount() const {
136 | return this->is() ? get()->getFieldCount()
137 | : get()->getFieldCount();
138 | }
139 | bool isStruct() const { return this->is(); }
140 | bool isUnion() const { return this->is(); }
141 | };
142 |
143 | gcc_jit_context *ctxt;
144 | ModuleOp moduleOp;
145 | llvm::DenseMap functionMap;
146 | llvm::DenseMap globalMap;
147 | llvm::DenseMap typeMap;
148 | llvm::DenseMap structMap;
149 | llvm::DenseMap unionMap;
150 |
151 | void populateGCCJITModuleOptions();
152 | void declareAllFunctionAndGlobals();
153 | void translateGlobalInitializers();
154 | void translateFunctions();
155 |
156 | private:
157 | StructEntry &getOrCreateStructEntry(StructType type);
158 | UnionEntry &getOrCreateUnionEntry(UnionType type);
159 |
160 | public:
161 | GCCJITRecord getOrCreateRecordEntry(Type type);
162 | };
163 |
164 | llvm::Expected translateModuleToGCCJIT(ModuleOp op);
165 |
166 | } // namespace mlir::gccjit
167 |
168 | #endif // MLIR_GCCJIT_TRANSLATION_TRANSLATETOGCCJIT_H
169 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lancern/mlir-gccjit/f981c8510688f2152c26882c95858d2ff039a2fd/logo.png
--------------------------------------------------------------------------------
/run-lit.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from lit.main import main
4 |
5 | if __name__ == "__main__":
6 | main()
7 |
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_mlir_dialect_library(MLIRGCCJIT
2 | GCCJITAttrs.cpp
3 | GCCJITDialect.cpp
4 | GCCJITOps.cpp
5 | GCCJITTypes.cpp
6 |
7 | ADDITIONAL_HEADER_DIRS
8 | ${PROJECT_SOURCE_DIR}/include/mlir-gccjit
9 |
10 | DEPENDS
11 | MLIRGCCJITOpsIncGen
12 | MLIRGCCJITEnumsGen
13 |
14 | LINK_LIBS PUBLIC
15 | MLIRIR
16 | libgccjit
17 |
18 | LINK_COMPONENTS
19 | Core
20 | )
21 |
22 | add_subdirectory(Interfaces)
23 | add_subdirectory(Translation)
24 | add_subdirectory(Conversion)
25 |
--------------------------------------------------------------------------------
/src/Conversion/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_mlir_conversion_library(MLIRGCCJITConversion
2 | TypeConverter.cpp
3 | ConvertFuncToGCCJIT.cpp
4 | ConvertArithToGCCJIT.cpp
5 | ConvertMemrefToGCCJIT.cpp
6 |
7 | DEPENDS
8 | MLIRGCCJIT
9 | MLIRGCCJITPassIncGen
10 |
11 | LINK_LIBS PUBLIC
12 | MLIRIR
13 | MLIRGCCJIT
14 | libgccjit
15 |
16 | LINK_COMPONENTS
17 | Core
18 | )
19 |
--------------------------------------------------------------------------------
/src/Conversion/ConvertArithToGCCJIT.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Schrodinger ZHU Yifan
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | #include "mlir-gccjit/Conversion/Conversions.h"
21 | #include "mlir-gccjit/Conversion/TypeConverter.h"
22 | #include "mlir-gccjit/IR/GCCJITAttrs.h"
23 | #include "mlir-gccjit/IR/GCCJITOps.h"
24 | #include "mlir-gccjit/IR/GCCJITOpsEnums.h"
25 | #include "mlir-gccjit/IR/GCCJITTypes.h"
26 | #include "mlir-gccjit/Passes.h"
27 |
28 | using namespace mlir;
29 | using namespace mlir::gccjit;
30 |
31 | namespace {
32 | struct ConvertArithToGCCJITPass
33 | : public ConvertArithToGCCJITBase {
34 | using ConvertArithToGCCJITBase::ConvertArithToGCCJITBase;
35 | void runOnOperation() override final;
36 | };
37 |
38 | template
39 | class GCCJITLoweringPattern : public mlir::OpConversionPattern {
40 | protected:
41 | const GCCJITTypeConverter *getTypeConverter() const {
42 | return static_cast(this->typeConverter);
43 | }
44 |
45 | public:
46 | using OpConversionPattern::OpConversionPattern;
47 | };
48 |
49 | class ConstantOpLowering : public GCCJITLoweringPattern {
50 | public:
51 | using GCCJITLoweringPattern::GCCJITLoweringPattern;
52 | mlir::LogicalResult
53 | matchAndRewrite(arith::ConstantOp op, OpAdaptor adaptor,
54 | mlir::ConversionPatternRewriter &rewriter) const override {
55 | auto attr = op.getValue();
56 |
57 | if (auto value = dyn_cast(attr)) {
58 | rewriter.replaceOpWithNewOp(
59 | op, getTypeConverter()->convertIntegerAttr(value));
60 | return mlir::success();
61 | }
62 |
63 | if (auto value = dyn_cast(attr)) {
64 | rewriter.replaceOpWithNewOp(
65 | op, getTypeConverter()->convertFloatAttr(value));
66 | return mlir::success();
67 | }
68 |
69 | return mlir::failure();
70 | }
71 | };
72 |
73 | class CmpIOpLowering : public GCCJITLoweringPattern {
74 | void getComparison(gccjit::CmpOp &kind, bool &signedness,
75 | arith::CmpIPredicate pred) const {
76 | signedness = false;
77 | switch (pred) {
78 | case arith::CmpIPredicate::eq:
79 | kind = gccjit::CmpOp::Eq;
80 | break;
81 | case arith::CmpIPredicate::ne:
82 | kind = gccjit::CmpOp::Ne;
83 | break;
84 |
85 | case arith::CmpIPredicate::slt:
86 | signedness = true;
87 | [[fallthrough]];
88 | case arith::CmpIPredicate::ult:
89 | kind = gccjit::CmpOp::Lt;
90 | break;
91 |
92 | case arith::CmpIPredicate::sle:
93 | signedness = true;
94 | [[fallthrough]];
95 | case arith::CmpIPredicate::ule:
96 | kind = gccjit::CmpOp::Le;
97 | break;
98 |
99 | case arith::CmpIPredicate::sgt:
100 | signedness = true;
101 | [[fallthrough]];
102 | case arith::CmpIPredicate::ugt:
103 | kind = gccjit::CmpOp::Gt;
104 | break;
105 |
106 | case arith::CmpIPredicate::sge:
107 | signedness = true;
108 | [[fallthrough]];
109 | case arith::CmpIPredicate::uge:
110 | kind = gccjit::CmpOp::Ge;
111 | break;
112 | }
113 | }
114 |
115 | public:
116 | using GCCJITLoweringPattern::GCCJITLoweringPattern;
117 | mlir::LogicalResult
118 | matchAndRewrite(arith::CmpIOp op, OpAdaptor adaptor,
119 | mlir::ConversionPatternRewriter &rewriter) const override {
120 | auto lhs = adaptor.getLhs();
121 | auto rhs = adaptor.getRhs();
122 | auto inputTy = cast(lhs.getType());
123 | auto pred = adaptor.getPredicate();
124 | gccjit::CmpOp kind;
125 | bool signedness;
126 | getComparison(kind, signedness, pred);
127 | auto i1 = getTypeConverter()->convertType(op.getResult().getType());
128 | if (signedness && !getTypeConverter()->isSigned(inputTy)) {
129 | auto signedType = getTypeConverter()->makeSigned(inputTy);
130 | lhs = rewriter.create(op.getLoc(), signedType, lhs);
131 | rhs = rewriter.create(op.getLoc(), signedType, rhs);
132 | }
133 | auto cmpAttr = CmpOpAttr::get(op.getContext(), kind);
134 | rewriter.replaceOpWithNewOp(op, i1, cmpAttr, lhs, rhs);
135 | return mlir::success();
136 | }
137 | };
138 | template
139 | class TrivialBinOpConversion : public GCCJITLoweringPattern {
140 | using GCCJITLoweringPattern::GCCJITLoweringPattern;
141 | mlir::LogicalResult
142 | matchAndRewrite(Op op, typename GCCJITLoweringPattern::OpAdaptor adaptor,
143 | mlir::ConversionPatternRewriter &rewriter) const override {
144 | auto lhs = adaptor.getLhs();
145 | auto rhs = adaptor.getRhs();
146 | auto resultTy = lhs.getType();
147 | auto kind = BOpAttr::get(op.getContext(), Kind);
148 | rewriter.replaceOpWithNewOp(op, resultTy, kind, lhs, rhs);
149 | return mlir::success();
150 | }
151 | };
152 |
153 | using AddIOpLowering = TrivialBinOpConversion;
154 | using AddFOpLowering = TrivialBinOpConversion;
155 | using MulFOpLowering = TrivialBinOpConversion;
156 |
157 | void ConvertArithToGCCJITPass::runOnOperation() {
158 | auto moduleOp = getOperation();
159 | auto typeConverter = GCCJITTypeConverter();
160 | // unrealized conversions
161 | auto materializeAsUnrealizedCast = [](OpBuilder &builder, Type resultType,
162 | ValueRange inputs,
163 | Location loc) -> Value {
164 | if (inputs.size() != 1)
165 | return Value();
166 |
167 | return builder.create(loc, resultType, inputs)
168 | .getResult(0);
169 | };
170 | typeConverter.addTargetMaterialization(materializeAsUnrealizedCast);
171 | typeConverter.addSourceMaterialization(materializeAsUnrealizedCast);
172 | mlir::RewritePatternSet patterns(&getContext());
173 | patterns.add(typeConverter, &getContext());
175 | mlir::ConversionTarget target(getContext());
176 | target.addLegalDialect();
177 | target.addIllegalDialect();
178 | llvm::SmallVector ops;
179 | for (auto func : moduleOp.getOps())
180 | ops.push_back(func);
181 | for (auto func : moduleOp.getOps())
182 | ops.push_back(func);
183 | if (failed(applyPartialConversion(ops, target, std::move(patterns))))
184 | signalPassFailure();
185 | }
186 | } // namespace
187 |
188 | std::unique_ptr mlir::gccjit::createConvertArithToGCCJITPass() {
189 | return std::make_unique();
190 | }
191 |
--------------------------------------------------------------------------------
/src/Conversion/TypeConverter.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Schrodinger ZHU Yifan
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "mlir-gccjit/Conversion/TypeConverter.h"
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 |
23 | #include "mlir-gccjit/IR/GCCJITAttrs.h"
24 | #include "mlir-gccjit/IR/GCCJITTypes.h"
25 |
26 | using namespace mlir;
27 | using namespace mlir::gccjit;
28 |
29 | GCCJITTypeConverter::GCCJITTypeConverter() : TypeConverter() {
30 | addConversion([&](mlir::IndexType type) { return convertIndexType(type); });
31 | addConversion(
32 | [&](mlir::IntegerType type) { return convertIntegerType(type); });
33 | addConversion([&](mlir::FloatType type) { return convertFloatType(type); });
34 | addConversion(
35 | [&](mlir::ComplexType type) { return convertComplexType(type); });
36 | addConversion([&](mlir::VectorType type) { return convertVectorType(type); });
37 | addConversion([&](mlir::FunctionType type) {
38 | return convertFunctionTypeAsPtr(type, false);
39 | });
40 | addConversion(
41 | [&](mlir::MemRefType type) { return getMemrefDescriptorType(type); });
42 | }
43 |
44 | // Nothing to do for now
45 | GCCJITTypeConverter::~GCCJITTypeConverter() {}
46 |
47 | gccjit::IntType
48 | GCCJITTypeConverter::convertIndexType(mlir::IndexType type) const {
49 | return IntType::get(type.getContext(), GCC_JIT_TYPE_SIZE_T);
50 | }
51 |
52 | gccjit::IntType
53 | GCCJITTypeConverter::convertIntegerType(mlir::IntegerType type) const {
54 | // gccjit always translates bitwidth to specific types
55 | // https://github.com/gcc-mirror/gcc/blob/ae0dbea896b77686fcd1c890e5b7c5fed6197767/gcc/jit/jit-recording.cc#L796
56 | switch (type.getWidth()) {
57 | case 1:
58 | return IntType::get(type.getContext(), GCC_JIT_TYPE_BOOL);
59 | case 8:
60 | return IntType::get(type.getContext(), type.isSigned()
61 | ? GCC_JIT_TYPE_INT8_T
62 | : GCC_JIT_TYPE_UINT8_T);
63 | case 16:
64 | return IntType::get(type.getContext(), type.isSigned()
65 | ? GCC_JIT_TYPE_INT16_T
66 | : GCC_JIT_TYPE_UINT16_T);
67 | case 32:
68 | return IntType::get(type.getContext(), type.isSigned()
69 | ? GCC_JIT_TYPE_INT32_T
70 | : GCC_JIT_TYPE_UINT32_T);
71 | case 64:
72 | return IntType::get(type.getContext(), type.isSigned()
73 | ? GCC_JIT_TYPE_INT64_T
74 | : GCC_JIT_TYPE_UINT64_T);
75 | case 128:
76 | return IntType::get(type.getContext(), type.isSigned()
77 | ? GCC_JIT_TYPE_INT128_T
78 | : GCC_JIT_TYPE_UINT128_T);
79 | default:
80 | return {};
81 | }
82 | }
83 |
84 | gccjit::IntAttr
85 | GCCJITTypeConverter::convertIntegerAttr(mlir::IntegerAttr attr) const {
86 | auto value = attr.getValue();
87 | if (auto intType = dyn_cast(attr.getType())) {
88 | auto type = convertIntegerType(intType);
89 | return IntAttr::get(attr.getContext(), type, value);
90 | }
91 |
92 | if (auto indexType = dyn_cast(attr.getType())) {
93 | auto type = convertIndexType(indexType);
94 | return IntAttr::get(attr.getContext(), type, value);
95 | }
96 |
97 | return {};
98 | }
99 |
100 | gccjit::FloatType
101 | GCCJITTypeConverter::convertFloatType(mlir::FloatType type) const {
102 | if (type.isF32())
103 | return FloatType::get(type.getContext(), GCC_JIT_TYPE_FLOAT);
104 | if (type.isF64())
105 | return FloatType::get(type.getContext(), GCC_JIT_TYPE_DOUBLE);
106 |
107 | // FIXME: we cannot really distinguish between f80 and f128 for GCCJIT, maybe
108 | // we need target information.
109 | if (type.isF80() || type.isF128())
110 | return FloatType::get(type.getContext(), GCC_JIT_TYPE_LONG_DOUBLE);
111 |
112 | return {};
113 | }
114 |
115 | gccjit::FloatAttr
116 | GCCJITTypeConverter::convertFloatAttr(mlir::FloatAttr attr) const {
117 | auto value = attr.getValue();
118 | auto type = convertFloatType(cast(attr.getType()));
119 | return FloatAttr::get(attr.getContext(), type, value);
120 | }
121 |
122 | gccjit::ComplexType
123 | GCCJITTypeConverter::convertComplexType(mlir::ComplexType type) const {
124 | auto elementType = type.getElementType();
125 | if (elementType.isF32())
126 | return ComplexType::get(type.getContext(), GCC_JIT_TYPE_COMPLEX_FLOAT);
127 | if (elementType.isF64())
128 | return ComplexType::get(type.getContext(), GCC_JIT_TYPE_COMPLEX_DOUBLE);
129 | if (elementType.isF80() || elementType.isF128())
130 | return ComplexType::get(type.getContext(),
131 | GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE);
132 | return {};
133 | }
134 |
135 | gccjit::VectorType
136 | GCCJITTypeConverter::convertVectorType(mlir::VectorType type) const {
137 | auto elementType = convertType(type.getElementType());
138 | auto size = type.getNumElements();
139 | return VectorType::get(type.getContext(), elementType, size);
140 | }
141 |
142 | gccjit::FuncType
143 | GCCJITTypeConverter::convertFunctionType(mlir::FunctionType type,
144 | bool isVarArg) const {
145 | llvm::SmallVector argTypes;
146 | argTypes.reserve(type.getNumInputs());
147 | if (convertTypes(type.getInputs(), argTypes).failed())
148 | return {};
149 | auto resultType =
150 | convertAndPackTypesIfNonSingleton(type.getResults(), type.getContext());
151 | return FuncType::get(type.getContext(), argTypes, resultType, isVarArg);
152 | }
153 |
154 | gccjit::PointerType
155 | GCCJITTypeConverter::convertFunctionTypeAsPtr(mlir::FunctionType type,
156 | bool isVarArg) const {
157 | auto funcType = convertFunctionType(type, isVarArg);
158 | return PointerType::get(type.getContext(), funcType);
159 | }
160 |
161 | gccjit::StructType
162 | GCCJITTypeConverter::getMemrefDescriptorType(mlir::MemRefType type) const {
163 | std::string name;
164 | llvm::raw_string_ostream os(name);
165 | type.print(os);
166 | os.flush();
167 | auto nameAttr = StringAttr::get(type.getContext(), name);
168 | auto elementType = convertType(type.getElementType());
169 | auto elementPtrType = PointerType::get(type.getContext(), elementType);
170 | auto indexType = IntType::get(type.getContext(), GCC_JIT_TYPE_SIZE_T);
171 | auto rank = type.getRank();
172 | auto dimOrStrideType =
173 | gccjit::ArrayType::get(type.getContext(), indexType, rank);
174 | SmallVector fields;
175 | llvm::StringRef names[]{
176 | "base", "aligned", "offset", "sizes", "strides",
177 | };
178 | for (auto [idx, field] :
179 | llvm::enumerate(ArrayRef{elementPtrType, elementPtrType, indexType,
180 | dimOrStrideType, dimOrStrideType})) {
181 | auto nameAttr = StringAttr::get(type.getContext(), names[idx]);
182 | fields.push_back(FieldAttr::get(type.getContext(), nameAttr, field));
183 | }
184 | auto fieldsAttr = ArrayAttr::get(type.getContext(), fields);
185 | return StructType::get(type.getContext(), nameAttr, fieldsAttr);
186 | }
187 |
188 | gccjit::StructType GCCJITTypeConverter::getUnrankedMemrefDescriptorType(
189 | mlir::UnrankedMemRefType type) const {
190 |
191 | auto name =
192 | Twine("__unranked_memref_")
193 | .concat(Twine(reinterpret_cast(type.getAsOpaquePointer())))
194 | .str();
195 | auto nameAttr = StringAttr::get(type.getContext(), name);
196 | auto indexType = IntType::get(type.getContext(), GCC_JIT_TYPE_SIZE_T);
197 | auto opaquePtrType = PointerType::get(
198 | type.getContext(), IntType::get(type.getContext(), GCC_JIT_TYPE_VOID));
199 | SmallVector fields;
200 | for (auto [idx, field] :
201 | llvm::enumerate(ArrayRef{indexType, opaquePtrType})) {
202 | auto name = Twine("__field_").concat(Twine(idx)).str();
203 | auto nameAttr = StringAttr::get(type.getContext(), name);
204 | fields.push_back(FieldAttr::get(type.getContext(), nameAttr, field));
205 | }
206 | auto fieldsAttr = ArrayAttr::get(type.getContext(), fields);
207 | return StructType::get(type.getContext(), nameAttr, fieldsAttr);
208 | }
209 |
210 | Type GCCJITTypeConverter::convertAndPackTypesIfNonSingleton(
211 | TypeRange types, MLIRContext *ctx) const {
212 | if (types.size() == 0)
213 | return VoidType::get(ctx);
214 | if (types.size() == 1)
215 | return convertType(types.front());
216 |
217 | auto *name = "__return_pack";
218 | SmallVector fields;
219 | for (auto [idx, type] : llvm::enumerate(types)) {
220 | auto name = Twine("__field_").concat(Twine(idx)).str();
221 | auto nameAttr = StringAttr::get(ctx, name);
222 | fields.push_back(FieldAttr::get(type.getContext(), nameAttr, type));
223 | }
224 | auto nameAttr = StringAttr::get(ctx, name);
225 | auto fieldsAttr = ArrayAttr::get(ctx, fields);
226 | return StructType::get(ctx, nameAttr, fieldsAttr);
227 | }
228 |
229 | bool GCCJITTypeConverter::isSigned(gccjit::IntType type) const {
230 | switch (type.getKind()) {
231 | case GCC_JIT_TYPE_UNSIGNED_INT:
232 | case GCC_JIT_TYPE_UNSIGNED_LONG:
233 | case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
234 | case GCC_JIT_TYPE_UINT8_T:
235 | case GCC_JIT_TYPE_UINT16_T:
236 | case GCC_JIT_TYPE_UINT32_T:
237 | case GCC_JIT_TYPE_UINT64_T:
238 | case GCC_JIT_TYPE_UINT128_T:
239 | return false;
240 | default:
241 | return true;
242 | }
243 | }
244 |
245 | gccjit::IntType GCCJITTypeConverter::makeSigned(gccjit::IntType type) const {
246 | switch (type.getKind()) {
247 | case GCC_JIT_TYPE_UNSIGNED_INT:
248 | return IntType::get(type.getContext(), GCC_JIT_TYPE_INT);
249 | case GCC_JIT_TYPE_UNSIGNED_LONG:
250 | return IntType::get(type.getContext(), GCC_JIT_TYPE_LONG);
251 | case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
252 | return IntType::get(type.getContext(), GCC_JIT_TYPE_LONG_LONG);
253 | case GCC_JIT_TYPE_UINT8_T:
254 | return IntType::get(type.getContext(), GCC_JIT_TYPE_INT8_T);
255 | case GCC_JIT_TYPE_UINT16_T:
256 | return IntType::get(type.getContext(), GCC_JIT_TYPE_INT16_T);
257 | case GCC_JIT_TYPE_UINT32_T:
258 | return IntType::get(type.getContext(), GCC_JIT_TYPE_INT32_T);
259 | case GCC_JIT_TYPE_UINT64_T:
260 | return IntType::get(type.getContext(), GCC_JIT_TYPE_INT64_T);
261 | case GCC_JIT_TYPE_UINT128_T:
262 | return IntType::get(type.getContext(), GCC_JIT_TYPE_INT128_T);
263 | default:
264 | return type;
265 | }
266 | }
267 |
268 | // the counterpart of makeSigned
269 | gccjit::IntType GCCJITTypeConverter::makeUnsigned(gccjit::IntType type) const {
270 | switch (type.getKind()) {
271 | case GCC_JIT_TYPE_INT:
272 | return IntType::get(type.getContext(), GCC_JIT_TYPE_UNSIGNED_INT);
273 | case GCC_JIT_TYPE_LONG:
274 | return IntType::get(type.getContext(), GCC_JIT_TYPE_UNSIGNED_LONG);
275 | case GCC_JIT_TYPE_LONG_LONG:
276 | return IntType::get(type.getContext(), GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
277 | case GCC_JIT_TYPE_INT8_T:
278 | return IntType::get(type.getContext(), GCC_JIT_TYPE_UINT8_T);
279 | case GCC_JIT_TYPE_INT16_T:
280 | return IntType::get(type.getContext(), GCC_JIT_TYPE_UINT16_T);
281 | case GCC_JIT_TYPE_INT32_T:
282 | return IntType::get(type.getContext(), GCC_JIT_TYPE_UINT32_T);
283 | case GCC_JIT_TYPE_INT64_T:
284 | return IntType::get(type.getContext(), GCC_JIT_TYPE_UINT64_T);
285 | case GCC_JIT_TYPE_INT128_T:
286 | return IntType::get(type.getContext(), GCC_JIT_TYPE_UINT128_T);
287 | default:
288 | return type;
289 | }
290 | }
291 |
--------------------------------------------------------------------------------
/src/GCCJITAttrs.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Schrodinger ZHU Yifan
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include
26 |
27 | #include "mlir-gccjit/IR/GCCJITAttrs.h"
28 | #include "mlir-gccjit/IR/GCCJITDialect.h"
29 | #include "mlir-gccjit/IR/GCCJITOpsEnums.h"
30 | #include "mlir-gccjit/IR/GCCJITTypes.h"
31 |
32 | #include "mlir-gccjit/IR/GCCJITOpsEnums.cpp.inc"
33 |
34 | #define GET_ATTRDEF_CLASSES
35 | #include "mlir-gccjit/IR/GCCJITOpsAttributes.cpp.inc"
36 |
37 | namespace mlir::gccjit {
38 | //===----------------------------------------------------------------------===//
39 | // General GCCJIT parsing / printing
40 | //===----------------------------------------------------------------------===//
41 | Attribute GCCJITDialect::parseAttribute(DialectAsmParser &parser,
42 | Type type) const {
43 | llvm::SMLoc typeLoc = parser.getCurrentLocation();
44 | StringRef mnemonic;
45 | Attribute genAttr;
46 | OptionalParseResult parseResult =
47 | generatedAttributeParser(parser, &mnemonic, type, genAttr);
48 | if (parseResult.has_value())
49 | return genAttr;
50 | parser.emitError(typeLoc, "unknown attribute in GCCJIT dialect");
51 | return Attribute();
52 | }
53 |
54 | void GCCJITDialect::printAttribute(Attribute attr,
55 | DialectAsmPrinter &os) const {
56 | if (failed(generatedAttributePrinter(attr, os)))
57 | llvm_unreachable("unexpected GCCJIT attribute");
58 | }
59 |
60 | //===----------------------------------------------------------------------===//
61 | // TLSModelAttr definitions
62 | //===----------------------------------------------------------------------===//
63 |
64 | Attribute TLSModelAttr::parse(AsmParser &parser, Type odsType) {
65 | auto loc = parser.getCurrentLocation();
66 | if (parser.parseLess())
67 | return {};
68 |
69 | // Parse variable 'lang'.
70 | llvm::StringRef model;
71 | if (parser.parseKeyword(&model))
72 | return {};
73 |
74 | // Check if parsed value is a valid language.
75 | auto modelEnum = symbolizeTLSModelEnum(model);
76 | if (!modelEnum.has_value()) {
77 | parser.emitError(loc) << "invalid TLS model keyword '" << model << "'";
78 | return {};
79 | }
80 |
81 | if (parser.parseGreater())
82 | return {};
83 |
84 | return get(parser.getContext(),
85 | TLSModelEnumAttr::get(parser.getContext(), modelEnum.value()));
86 | }
87 |
88 | void TLSModelAttr::print(AsmPrinter &printer) const {
89 | printer << "<" << getModel().getValue() << '>';
90 | }
91 |
92 | //===----------------------------------------------------------------------===//
93 | // IntAttr definitions
94 | //===----------------------------------------------------------------------===//
95 |
96 | Attribute IntAttr::parse(AsmParser &parser, Type odsType) {
97 | auto intType = mlir::dyn_cast_if_present(odsType);
98 |
99 | if (!intType) {
100 | parser.emitError(parser.getCurrentLocation(),
101 | "expected integer type for #gccjit.int attribute");
102 | return {};
103 | }
104 |
105 | // Consume the '<' symbol.
106 | if (parser.parseLess())
107 | return {};
108 |
109 | // Fetch arbitrary precision integer value.
110 | long value;
111 | if (parser.parseInteger(value))
112 | parser.emitError(parser.getCurrentLocation(), "expected integer value");
113 | mlir::APInt storage(sizeof(long) * 8, value, true);
114 | if (storage.getSExtValue() != value)
115 | parser.emitError(parser.getCurrentLocation(),
116 | "integer value too large for the given type");
117 |
118 | // Consume the '>' symbol.
119 | if (parser.parseGreater())
120 | return {};
121 |
122 | return IntAttr::get(parser.getContext(), intType, storage);
123 | }
124 |
125 | void IntAttr::print(AsmPrinter &printer) const {
126 | printer << '<' << getValue() << '>';
127 | }
128 |
129 | //===----------------------------------------------------------------------===//
130 | // FloatAttr definitions
131 | //===----------------------------------------------------------------------===//
132 |
133 | Attribute FloatAttr::parse(AsmParser &parser, Type odsType) {
134 | auto floatType = mlir::dyn_cast_if_present(odsType);
135 | if (!floatType) {
136 | parser.emitError(
137 | parser.getCurrentLocation(),
138 | "expected floating-point type for #gccjit.float attribute");
139 | return {};
140 | }
141 |
142 | // Consume the '<' symbol.
143 | if (parser.parseLess())
144 | return {};
145 |
146 | // Fetch floating-point value.
147 | double value;
148 | if (parser.parseFloat(value))
149 | parser.emitError(parser.getCurrentLocation(),
150 | "expected floating-point value");
151 |
152 | // Consume the '>' symbol.
153 | if (parser.parseGreater())
154 | return {};
155 |
156 | return FloatAttr::get(parser.getContext(), floatType, mlir::APFloat(value));
157 | }
158 |
159 | void FloatAttr::print(AsmPrinter &printer) const {
160 | printer << '<' << getValue() << '>';
161 | }
162 |
163 | //===----------------------------------------------------------------------===//
164 | // Special value attribute definitions
165 | //===----------------------------------------------------------------------===//
166 |
167 | LogicalResult
168 | ZeroAttr::verify(llvm::function_ref emitError,
169 | Type type) {
170 | if (!mlir::isa(type))
171 | return emitError()
172 | << "#gccjit.zero must be of integer or floating-point type";
173 | return success();
174 | }
175 |
176 | LogicalResult
177 | OneAttr::verify(llvm::function_ref emitError, Type type) {
178 | if (!mlir::isa(type))
179 | return emitError()
180 | << "#gccjit.one must be of integer or floating-point type";
181 | return success();
182 | }
183 |
184 | //===----------------------------------------------------------------------===//
185 | // OptLevelAttr definitions
186 | //===----------------------------------------------------------------------===//
187 | Attribute OptLevelAttr::parse(AsmParser &parser, Type odsType) {
188 | llvm::SMLoc loc = parser.getCurrentLocation();
189 | if (parser.parseLess())
190 | return {};
191 |
192 | // Parse variable 'level'.
193 | llvm::StringRef level;
194 | if (parser.parseKeyword(&level))
195 | return {};
196 |
197 | // Check if parsed value is a valid optimization level.
198 | auto optLevelEnum = symbolizeOptLevelEnum(level);
199 | if (!optLevelEnum.has_value()) {
200 | parser.emitError(loc) << "invalid optimization level keyword '" << level
201 | << "'";
202 | return {};
203 | }
204 |
205 | if (parser.parseGreater())
206 | return {};
207 |
208 | return get(parser.getContext(),
209 | OptLevelEnumAttr::get(parser.getContext(), optLevelEnum.value()));
210 | }
211 |
212 | void OptLevelAttr::print(AsmPrinter &printer) const {
213 | printer << "<" << getLevel().getValue() << '>';
214 | }
215 |
216 | //===----------------------------------------------------------------------===//
217 | // FunctionAttr definitions
218 | //===----------------------------------------------------------------------===//
219 | Attribute FunctionAttr::parse(AsmParser &parser, Type odsType) {
220 | llvm::SMLoc loc = parser.getCurrentLocation();
221 | if (parser.parseLess())
222 | return {};
223 |
224 | std::string keyword;
225 | if (parser.parseKeywordOrString(&keyword)) {
226 | parser.emitError(loc) << "expected attribute kind";
227 | return {};
228 | }
229 |
230 | std::optional kind = symbolizeFnAttrEnum(keyword);
231 | if (!kind.has_value()) {
232 | parser.emitError(loc) << "unknown function attribute kind: " << keyword;
233 | return {};
234 | }
235 |
236 | auto kindAttr = FnAttrEnumAttr::get(parser.getContext(), kind.value());
237 |
238 | if (isUnitFnAttr(kindAttr.getValue())) {
239 | if (parser.parseGreater())
240 | return {};
241 | return FunctionAttr::get(parser.getContext(), kindAttr, {}, {});
242 | }
243 |
244 | if (parser.parseComma())
245 | return {};
246 |
247 | if (isStringFnAttr(kindAttr.getValue())) {
248 | StringAttr strValue;
249 | if (parser.parseAttribute(strValue))
250 | return {};
251 | if (parser.parseGreater())
252 | return {};
253 | return FunctionAttr::get(parser.getContext(), kindAttr, strValue, {});
254 | }
255 |
256 | assert(isIntArrayFnAttr(kindAttr.getValue()));
257 | DenseI32ArrayAttr intArrayValue;
258 | if (parser.parseAttribute(intArrayValue))
259 | return {};
260 | if (parser.parseGreater())
261 | return {};
262 | return FunctionAttr::get(parser.getContext(), kindAttr, {}, intArrayValue);
263 | }
264 |
265 | void FunctionAttr::print(AsmPrinter &printer) const {
266 | printer << "<" << getAttr().getValue();
267 | if (isStringFnAttr(getAttr().getValue())) {
268 | printer << ", ";
269 | printer.printAttribute(getStrValue().value());
270 | } else if (isIntArrayFnAttr(getAttr().getValue())) {
271 | printer << ", ";
272 | printer.printAttribute(getIntArrayValue().value());
273 | }
274 | printer << ">";
275 | }
276 |
277 | //===----------------------------------------------------------------------===//
278 | // GCCJIT Dialect
279 | //===----------------------------------------------------------------------===//
280 |
281 | void GCCJITDialect::registerAttributes() {
282 | addAttributes<
283 | #define GET_ATTRDEF_LIST
284 | #include "mlir-gccjit/IR/GCCJITOpsAttributes.cpp.inc"
285 | >();
286 | }
287 |
288 | } // namespace mlir::gccjit
289 |
--------------------------------------------------------------------------------
/src/GCCJITDialect.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Sirui Mu
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "mlir-gccjit/IR/GCCJITDialect.h"
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 |
37 | #include "mlir-gccjit/IR/GCCJITOps.h"
38 | #include "mlir-gccjit/IR/GCCJITTypes.h"
39 |
40 | using namespace mlir;
41 | using namespace mlir::gccjit;
42 |
43 | #include "mlir-gccjit/IR/GCCJITOpsDialect.cpp.inc"
44 |
45 | void GCCJITDialect::initialize() {
46 | registerTypes();
47 | registerAttributes();
48 | addOperations<
49 | #define GET_OP_LIST
50 | #include "mlir-gccjit/IR/GCCJITOps.cpp.inc"
51 | >();
52 | }
53 |
--------------------------------------------------------------------------------
/src/Interfaces/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_mlir_dialect_library(MLIRGCCJITInterfaces
2 | GCCJITRecordTypeInterface.cpp
3 | DEPENDS
4 | MLIRGCCJIT
5 | MLIRGCCJITRecordTypeInterfaceIncGen
6 | LINK_COMPONENTS
7 | Core
8 | LINK_LIBS PUBLIC
9 | MLIRGCCJIT
10 | )
11 |
--------------------------------------------------------------------------------
/src/Interfaces/GCCJITRecordTypeInterface.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Sirui Mu
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "mlir-gccjit/IR/Interfaces/GCCJITRecordTypeInterface.h"
16 |
17 | using namespace mlir;
18 | using namespace mlir::gccjit;
19 |
20 | #include "mlir-gccjit/IR/Interfaces/GCCJITRecordTypeInterface.cpp.inc"
21 |
--------------------------------------------------------------------------------
/src/Translation/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_mlir_dialect_library(MLIRTranslateToGCCJIT
2 | TranslateToGCCJIT.cpp
3 | Registration.cpp
4 | TypeTranslation.cpp
5 |
6 | DEPENDS
7 | MLIRGCCJIT
8 | MLIRGCCJITInterfaces
9 |
10 | LINK_LIBS PUBLIC
11 | MLIRIR
12 | MLIRGCCJIT
13 | MLIRGCCJITInterfaces
14 | libgccjit
15 |
16 | LINK_COMPONENTS
17 | Core
18 | )
19 |
--------------------------------------------------------------------------------
/src/Translation/Registration.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Schrodinger ZHU Yifan
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | #include
25 |
26 | #include "mlir-gccjit/IR/GCCJITDialect.h"
27 | #include "mlir-gccjit/Translation/TranslateToGCCJIT.h"
28 |
29 | namespace mlir::gccjit {
30 | namespace {
31 | enum class OutputType {
32 | Gimple,
33 | Reproducer,
34 | Assembly,
35 | Object,
36 | Executable,
37 | Dylib
38 | };
39 |
40 | llvm::Expected>
41 | dumpContextToTempfile(gcc_jit_context *ctxt, OutputType type) {
42 | StringRef suffix;
43 | llvm::SmallString<128> path;
44 | switch (type) {
45 | case OutputType::Gimple:
46 | suffix = ".gimple";
47 | break;
48 | case OutputType::Reproducer:
49 | suffix = ".c";
50 | break;
51 | case OutputType::Assembly:
52 | suffix = ".s";
53 | break;
54 | case OutputType::Object:
55 | suffix = ".o";
56 | break;
57 | case OutputType::Executable:
58 | suffix = ".exe";
59 | break;
60 | case OutputType::Dylib:
61 | suffix = ".so";
62 | break;
63 | }
64 | auto err = llvm::sys::fs::createTemporaryFile("mlir-gccjit", suffix, path);
65 | if (err)
66 | return llvm::createStringError(err, "failed to create temporary file");
67 | switch (type) {
68 | case OutputType::Gimple:
69 | gcc_jit_context_dump_to_file(ctxt, path.c_str(), false);
70 | break;
71 | case OutputType::Reproducer:
72 | gcc_jit_context_dump_reproducer_to_file(ctxt, path.c_str());
73 | break;
74 | case OutputType::Assembly:
75 | gcc_jit_context_compile_to_file(ctxt, GCC_JIT_OUTPUT_KIND_ASSEMBLER,
76 | path.c_str());
77 | break;
78 | case OutputType::Object:
79 | gcc_jit_context_compile_to_file(ctxt, GCC_JIT_OUTPUT_KIND_OBJECT_FILE,
80 | path.c_str());
81 | break;
82 | case OutputType::Executable:
83 | gcc_jit_context_compile_to_file(ctxt, GCC_JIT_OUTPUT_KIND_EXECUTABLE,
84 | path.c_str());
85 | break;
86 | case OutputType::Dylib:
87 | gcc_jit_context_compile_to_file(ctxt, GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY,
88 | path.c_str());
89 | break;
90 | }
91 | if (const char *err = gcc_jit_context_get_last_error(ctxt))
92 | return llvm::createStringError(llvm::inconvertibleErrorCode(), err);
93 | return path;
94 | }
95 |
96 | LogicalResult copyFileToStream(const llvm::SmallString<128> &path,
97 | llvm::raw_ostream &os) {
98 | os.flush();
99 | llvm::ErrorOr> buffer =
100 | llvm::MemoryBuffer::getFile(path);
101 | if (!buffer)
102 | return failure();
103 | os << buffer.get()->getBuffer();
104 | return success();
105 | }
106 |
107 | void registerTranslation(llvm::StringRef name, llvm::StringRef desc,
108 | OutputType type) {
109 | TranslateFromMLIRRegistration registration(
110 | name, desc,
111 | [type](Operation *op, raw_ostream &output) {
112 | auto module = dyn_cast(op);
113 | if (!module) {
114 | op->emitError("expected 'module' operation");
115 | return failure();
116 | }
117 | auto context = translateModuleToGCCJIT(module);
118 | if (!context) {
119 | op->emitError("failed to translate to GCCJIT context");
120 | return failure();
121 | }
122 | auto file = dumpContextToTempfile(context.get().get(), type);
123 | if (!file) {
124 | op->emitError("failed to dump GCCJIT context to tempfile");
125 | return failure();
126 | }
127 | return copyFileToStream(std::move(*file), output);
128 | },
129 | [](DialectRegistry ®istry) {
130 | registry.insert();
131 | });
132 | }
133 |
134 | } // namespace
135 |
136 | void registerToGCCJITGimpleTranslation() {
137 | registerTranslation("mlir-to-gccjit-gimple",
138 | "Translate MLIR to GCCJIT's GIMPLE format",
139 | OutputType::Gimple);
140 | }
141 |
142 | void registerToGCCJITReproducerTranslation() {
143 | registerTranslation("mlir-to-gccjit-reproducer",
144 | "Translate MLIR to GCCJIT's reproducer format",
145 | OutputType::Reproducer);
146 | }
147 |
148 | void registerToGCCJITAssemblyTranslation() {
149 | registerTranslation("mlir-to-gccjit-assembly",
150 | "Translate MLIR to GCCJIT's assembly format",
151 | OutputType::Assembly);
152 | }
153 |
154 | void registerToGCCJITObjectTranslation() {
155 | registerTranslation("mlir-to-gccjit-object",
156 | "Translate MLIR to GCCJIT's object file format",
157 | OutputType::Object);
158 | }
159 |
160 | void registerToGCCJITExecutableTranslation() {
161 | registerTranslation("mlir-to-gccjit-executable",
162 | "Translate MLIR to GCCJIT's executable format",
163 | OutputType::Executable);
164 | }
165 | void registerToGCCJITDylibTranslation() {
166 | registerTranslation("mlir-to-gccjit-dylib",
167 | "Translate MLIR to GCCJIT's dynamic library format",
168 | OutputType::Dylib);
169 | }
170 | } // namespace mlir::gccjit
171 |
--------------------------------------------------------------------------------
/src/Translation/TypeTranslation.cpp:
--------------------------------------------------------------------------------
1 | #include "mlir-gccjit/Translation/TranslateToGCCJIT.h"
2 |
3 | #include
4 | #include
5 |
6 | #include
7 | #include
8 |
9 | #include
10 |
11 | #include "mlir-gccjit/IR/GCCJITTypes.h"
12 | #include "llvm/Support/ErrorHandling.h"
13 |
14 | namespace mlir::gccjit {
15 |
16 | size_t GCCJITTranslation::getTypeSize(Type type) {
17 | // gcc_jit_type_get_size only works for integer types now.
18 | if (mlir::isa(type))
19 | return gcc_jit_type_get_size(convertType(type));
20 |
21 | if (mlir::isa(type)) {
22 | // Let's pray size_t and pointers have the same size on users' machines.
23 | gcc_jit_type *sizeType =
24 | gcc_jit_context_get_type(ctxt, GCC_JIT_TYPE_SIZE_T);
25 | return gcc_jit_type_get_size(sizeType);
26 | }
27 |
28 | if (auto floatTy = mlir::dyn_cast(type)) {
29 | switch (floatTy.getKind()) {
30 | case GCC_JIT_TYPE_FLOAT:
31 | return 4;
32 | case GCC_JIT_TYPE_DOUBLE:
33 | return 8;
34 | // TODO: add getTypeSize support for long double type.
35 | default:
36 | llvm_unreachable("unsupported gccjit float type");
37 | }
38 | }
39 | if (mlir::isa(type))
40 | return 2;
41 | if (mlir::isa(type))
42 | return 4;
43 | if (mlir::isa(type))
44 | return 8;
45 |
46 | // TODO: add getTypeSize support for struct type and union type.
47 |
48 | llvm_unreachable("unsupported gccjit object type");
49 | }
50 |
51 | void GCCJITTranslation::convertTypes(
52 | mlir::TypeRange types, llvm::SmallVector &result) {
53 | for (auto type : types)
54 | result.push_back(convertType(type));
55 | }
56 |
57 | gcc_jit_type *GCCJITTranslation::convertType(mlir::Type type) {
58 | if (auto it = typeMap.find(type); it != typeMap.end())
59 | return it->second;
60 | auto *res =
61 | llvm::TypeSwitch(type)
62 | .Case([&](gccjit::LValueType t) {
63 | return convertType(t.getInnerType());
64 | })
65 | .Case([&](gccjit::PointerType t) {
66 | auto *pointee = convertType(t.getElementType());
67 | if (isa(t.getElementType()))
68 | return pointee;
69 | if (auto qualified =
70 | dyn_cast(t.getElementType())) {
71 | if (qualified.getIsConst())
72 | if (auto intType =
73 | dyn_cast(qualified.getElementType()))
74 | if (intType.getKind() == GCC_JIT_TYPE_CHAR)
75 | return gcc_jit_context_get_type(
76 | ctxt, GCC_JIT_TYPE_CONST_CHAR_PTR);
77 | }
78 | return gcc_jit_type_get_pointer(pointee);
79 | })
80 | .Case([&](gccjit::FuncType t) {
81 | llvm::SmallVector paramTypes;
82 | convertTypes(t.getInputs(), paramTypes);
83 | auto *returnType = convertType(t.getReturnType());
84 | return gcc_jit_context_new_function_ptr_type(
85 | ctxt, nullptr, returnType, paramTypes.size(), paramTypes.data(),
86 | t.isVarArg());
87 | })
88 | .Case([&](gccjit::QualifiedType t) {
89 | auto *res = convertType(t.getElementType());
90 | if (t.getIsConst())
91 | res = gcc_jit_type_get_const(res);
92 | if (t.getIsRestrict())
93 | res = gcc_jit_type_get_restrict(res);
94 | if (t.getIsVolatile())
95 | res = gcc_jit_type_get_volatile(res);
96 | return res;
97 | })
98 | .Case([&](gccjit::IntType t) {
99 | auto kind = t.getKind();
100 | return gcc_jit_context_get_type(ctxt, kind);
101 | })
102 | .Case([&](mlir::IntegerType t) {
103 | assert(!t.isSignless() && "signless integer type is not supported");
104 | return gcc_jit_context_get_int_type(ctxt, t.getWidth() / CHAR_BIT,
105 | t.isSigned());
106 | })
107 | .Case([&](mlir::IndexType) {
108 | return gcc_jit_context_get_type(ctxt, GCC_JIT_TYPE_SIZE_T);
109 | })
110 | .Case([&](gccjit::FloatType t) {
111 | auto kind = t.getKind();
112 | return gcc_jit_context_get_type(ctxt, kind);
113 | })
114 | .Case([&](mlir::Float32Type) {
115 | return gcc_jit_context_get_type(ctxt, GCC_JIT_TYPE_FLOAT);
116 | })
117 | .Case([&](mlir::Float64Type) {
118 | return gcc_jit_context_get_type(ctxt, GCC_JIT_TYPE_DOUBLE);
119 | })
120 | .Case([&](gccjit::ComplexType t) {
121 | auto kind = t.getKind();
122 | return gcc_jit_context_get_type(ctxt, kind);
123 | })
124 | .Case([&](mlir::ComplexType t) {
125 | mlir::Type elementTy = t.getElementType();
126 | if (mlir::isa(elementTy))
127 | return gcc_jit_context_get_type(ctxt, GCC_JIT_TYPE_COMPLEX_FLOAT);
128 | if (mlir::isa(elementTy))
129 | return gcc_jit_context_get_type(ctxt,
130 | GCC_JIT_TYPE_COMPLEX_DOUBLE);
131 | if (auto floatTy = mlir::dyn_cast(elementTy)) {
132 | switch (floatTy.getKind()) {
133 | case GCC_JIT_TYPE_FLOAT:
134 | return gcc_jit_context_get_type(ctxt,
135 | GCC_JIT_TYPE_COMPLEX_FLOAT);
136 | case GCC_JIT_TYPE_DOUBLE:
137 | return gcc_jit_context_get_type(ctxt,
138 | GCC_JIT_TYPE_COMPLEX_DOUBLE);
139 | default:
140 | break;
141 | }
142 | }
143 | llvm_unreachable("unsupported complex element type");
144 | })
145 | .Case([&](gccjit::VoidType t) {
146 | return gcc_jit_context_get_type(ctxt, GCC_JIT_TYPE_VOID);
147 | })
148 | .Case([&](gccjit::ArrayType t) {
149 | auto *elemType = convertType(t.getElementType());
150 | auto size = t.getSize();
151 | return gcc_jit_context_new_array_type(ctxt, nullptr, elemType,
152 | size);
153 | })
154 | .Case([&](gccjit::VectorType t) {
155 | auto *elemType = convertType(t.getElementType());
156 | auto size = t.getNumUnits();
157 | return gcc_jit_type_get_vector(elemType, size);
158 | })
159 | .Case([&](mlir::VectorType t) {
160 | assert(!t.isScalable() &&
161 | "scalable vector types are not supported");
162 | auto *elemType = convertType(t.getElementType());
163 | auto size = t.getNumElements();
164 | return gcc_jit_type_get_vector(elemType, size);
165 | })
166 | .Case([&](gccjit::StructType t) -> gcc_jit_type * {
167 | gcc_jit_struct *rawType = getOrCreateStructEntry(t).getRawHandle();
168 | return gcc_jit_struct_as_type(rawType);
169 | })
170 | .Case([&](gccjit::UnionType t) -> gcc_jit_type * {
171 | return getOrCreateUnionEntry(t).getRawHandle();
172 | })
173 | .Default([](mlir::Type) -> gcc_jit_type * {
174 | llvm_unreachable("unsupported type for gccjit translation");
175 | });
176 | typeMap[type] = res;
177 | return res;
178 | }
179 |
180 | template
181 | static auto
182 | convertRecordType(GCCJITTranslation &translation,
183 | GCCJITRecordTypeInterface type,
184 | llvm::SmallVector &convertedFields,
185 | RawCreator &&rawHandleCreator) {
186 | static_assert(
187 | std::is_invocable_v);
189 |
190 | // TODO: handle opaque struct type.
191 |
192 | convertedFields.clear();
193 | convertedFields.reserve(type.getRecordFields().size());
194 | for (Attribute fieldOpaqueAttr : type.getRecordFields()) {
195 | auto fieldAttr = cast(fieldOpaqueAttr);
196 |
197 | int fieldBitWidth = fieldAttr.getBitWidth().value_or(0);
198 | std::string fieldName = fieldAttr.getName().str();
199 | gcc_jit_type *fieldType = translation.convertType(fieldAttr.getType());
200 |
201 | gcc_jit_location *loc = nullptr;
202 | if (auto fieldLoc = fieldAttr.getLoc())
203 | loc = translation.convertLocation(*fieldLoc);
204 |
205 | gcc_jit_field *field =
206 | fieldAttr.getBitWidth()
207 | ? gcc_jit_context_new_bitfield(translation.getContext(), loc,
208 | fieldType, fieldBitWidth,
209 | fieldName.c_str())
210 | : gcc_jit_context_new_field(translation.getContext(), loc,
211 | fieldType, fieldName.c_str());
212 | convertedFields.push_back(field);
213 | }
214 |
215 | std::string recordName = type.getRecordName().str();
216 |
217 | gcc_jit_location *loc = nullptr;
218 | if (SourceLocAttr recordLoc = type.getRecordLoc())
219 | loc = translation.convertLocation(recordLoc);
220 |
221 | return std::invoke(std::forward(rawHandleCreator),
222 | translation.getContext(), loc, recordName.c_str(),
223 | convertedFields.size(), convertedFields.data());
224 | }
225 |
226 | GCCJITTranslation::StructEntry &
227 | GCCJITTranslation::getOrCreateStructEntry(StructType type) {
228 | auto structMapIter = structMap.find(type);
229 | if (structMapIter == structMap.end()) {
230 | llvm::SmallVector convertedFields;
231 | gcc_jit_struct *rawType = convertRecordType(
232 | *this, type, convertedFields, gcc_jit_context_new_struct_type);
233 | structMapIter = structMap.insert({type, StructEntry(rawType)}).first;
234 | }
235 |
236 | return structMapIter->second;
237 | }
238 |
239 | GCCJITTranslation::UnionEntry &
240 | GCCJITTranslation::getOrCreateUnionEntry(UnionType type) {
241 | auto unionMapIter = unionMap.find(type);
242 | if (unionMapIter == unionMap.end()) {
243 | llvm::SmallVector convertedFields;
244 | gcc_jit_type *rawType = convertRecordType(*this, type, convertedFields,
245 | gcc_jit_context_new_union_type);
246 | unionMapIter =
247 | unionMap.insert({type, UnionEntry(rawType, std::move(convertedFields))})
248 | .first;
249 | }
250 |
251 | return unionMapIter->second;
252 | }
253 |
254 | } // namespace mlir::gccjit
255 |
--------------------------------------------------------------------------------
/test/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | configure_file(lit.site.cfg.py.in lit.site.cfg.py @ONLY)
2 |
3 | add_custom_target(check
4 | COMMAND "${PROJECT_SOURCE_DIR}/run-lit.py" -v ${CMAKE_CURRENT_BINARY_DIR}
5 | DEPENDS gccjit-tools
6 | )
7 |
--------------------------------------------------------------------------------
/test/compile/atomic.mlir:
--------------------------------------------------------------------------------
1 | // RUN: %gccjit-translate -o %t.gimple %s -mlir-to-gccjit-gimple
2 | // RUN: %filecheck --input-file=%t.gimple %s
3 |
4 | !bool = !gccjit.int
5 | !i32 = !gccjit.int
6 | !f32 = !gccjit.fp
7 | !pi32 = !gccjit.ptr
8 | !pf32 = !gccjit.ptr
9 | !ppi32 = !gccjit.ptr
10 |
11 | module @test attributes {
12 | gccjit.opt_level = #gccjit.opt_level,
13 | gccjit.prog_name = "test",
14 | gccjit.allow_unreachable = false,
15 | gccjit.debug_info = true
16 | } {
17 | // CHECK-LABEL: atomic_load_int
18 | gccjit.func exported @atomic_load_int(!pi32) -> !i32 {
19 | ^entry(%arg : !gccjit.lvalue):
20 | %0 = gccjit.as_rvalue %arg : !gccjit.lvalue to !pi32
21 | // CHECK: %{{.+}} = __atomic_load_4 (((volatile const void *)%{{.+}}), (int)0);
22 | %1 = gccjit.atomic.load relaxed (%0 : !pi32) : !i32
23 | gccjit.return %1 : !i32
24 | }
25 |
26 | // CHECK-LABEL: atomic_load_float
27 | gccjit.func exported @atomic_load_float(!pf32) -> !f32 {
28 | ^entry(%arg : !gccjit.lvalue):
29 | %0 = gccjit.as_rvalue %arg : !gccjit.lvalue to !pf32
30 | // CHECK: %{{.+}} = bitcast(__atomic_load_4 (((volatile const void *)%{{.+}}), (int)0), float);
31 | %1 = gccjit.atomic.load relaxed (%0 : !pf32) : !f32
32 | gccjit.return %1 : !f32
33 | }
34 |
35 | // CHECK-LABEL: atomic_load_ptr
36 | gccjit.func exported @atomic_load_ptr(!ppi32) -> !pi32 {
37 | ^entry(%arg : !gccjit.lvalue):
38 | %0 = gccjit.as_rvalue %arg : !gccjit.lvalue to !ppi32
39 | // CHECK: %{{.+}} = bitcast(__atomic_load_8 (((volatile const void *)%{{.+}}), (int)0), __int32_t *);
40 | %1 = gccjit.atomic.load relaxed (%0 : !ppi32) : !pi32
41 | gccjit.return %1 : !pi32
42 | }
43 |
44 | // CHECK-LABEL: atomic_store_int
45 | gccjit.func exported @atomic_store_int(!pi32, !i32) {
46 | ^entry(%arg0 : !gccjit.lvalue, %arg1 : !gccjit.lvalue):
47 | %0 = gccjit.as_rvalue %arg0 : !gccjit.lvalue to !pi32
48 | %1 = gccjit.as_rvalue %arg1 : !gccjit.lvalue to !i32
49 | // CHECK: (void)__atomic_store_4 (((volatile void *)%{{.+}}), %{{.+}}, (int)0);
50 | gccjit.atomic.store relaxed (%0 : !pi32, %1 : !i32)
51 | gccjit.return
52 | }
53 |
54 | // CHECK-LABEL: atomic_store_float
55 | gccjit.func exported @atomic_store_float(!pf32, !f32) {
56 | ^entry(%arg0 : !gccjit.lvalue, %arg1 : !gccjit.lvalue):
57 | %0 = gccjit.as_rvalue %arg0 : !gccjit.lvalue to !pf32
58 | %1 = gccjit.as_rvalue %arg1 : !gccjit.lvalue to !f32
59 | // CHECK: (void)__atomic_store_4 (((volatile void *)%{{.+}}), (bitcast(%{{.+}}, int)), (int)0);
60 | gccjit.atomic.store relaxed (%0 : !pf32, %1 : !f32)
61 | gccjit.return
62 | }
63 |
64 | // CHECK-LABEL: atomic_store_ptr
65 | gccjit.func exported @atomic_store_ptr(!ppi32, !pi32) {
66 | ^entry(%arg0 : !gccjit.lvalue, %arg1 : !gccjit.lvalue):
67 | %0 = gccjit.as_rvalue %arg0 : !gccjit.lvalue to !ppi32
68 | %1 = gccjit.as_rvalue %arg1 : !gccjit.lvalue to !pi32
69 | // CHECK: (void)__atomic_store_8 (((volatile void *)%{{.+}}), (bitcast(%{{.+}}, {{long long|long}})), (int)0);
70 | gccjit.atomic.store relaxed (%0 : !ppi32, %1 : !pi32)
71 | gccjit.return
72 | }
73 |
74 | // CHECK-LABEL: atomic_rmw_int
75 | gccjit.func exported @atomic_rmw_int(!pi32, !i32) -> !i32 {
76 | ^entry(%arg0 : !gccjit.lvalue, %arg1 : !gccjit.lvalue):
77 | %0 = gccjit.as_rvalue %arg0 : !gccjit.lvalue to !pi32
78 | %1 = gccjit.as_rvalue %arg1 : !gccjit.lvalue to !i32
79 | // CHECK: %{{.+}} = __atomic_fetch_add_4 (((volatile void *)%{{.+}}), %{{.+}}, (int)0);
80 | %2 = gccjit.atomic.rmw relaxed fetch_add (%0 : !pi32, %1 : !i32) : !i32
81 | gccjit.return %2 : !i32
82 | }
83 |
84 | // CHECK-LABEL: atomic_rmw_float
85 | gccjit.func exported @atomic_rmw_float(!pf32, !f32) -> !f32 {
86 | ^entry(%arg0 : !gccjit.lvalue, %arg1 : !gccjit.lvalue):
87 | %0 = gccjit.as_rvalue %arg0 : !gccjit.lvalue to !pf32
88 | %1 = gccjit.as_rvalue %arg1 : !gccjit.lvalue to !f32
89 | // CHECK: %{{.+}} = bitcast(__atomic_fetch_add_4 (((volatile void *)%{{.+}}), (bitcast(%{{.+}}, int)), (int)0), float);
90 | %2 = gccjit.atomic.rmw relaxed fetch_add (%0 : !pf32, %1 : !f32) : !f32
91 | gccjit.return %2 : !f32
92 | }
93 |
94 | // CHECK-LABEL: atomic_rmw_ptr
95 | gccjit.func exported @atomic_rmw_ptr(!ppi32, !pi32) -> !pi32 {
96 | ^entry(%arg0 : !gccjit.lvalue, %arg1 : !gccjit.lvalue):
97 | %0 = gccjit.as_rvalue %arg0 : !gccjit.lvalue to !ppi32
98 | %1 = gccjit.as_rvalue %arg1 : !gccjit.lvalue to !pi32
99 | // CHECK: %{{.+}} = bitcast(__atomic_fetch_add_8 (((volatile void *)%{{.+}}), (bitcast(%{{.+}}, {{long long|long}})), (int)0), __int32_t *);
100 | %2 = gccjit.atomic.rmw relaxed fetch_add (%0 : !ppi32, %1 : !pi32) : !pi32
101 | gccjit.return %2 : !pi32
102 | }
103 |
104 | // CHECK-LABEL: atomic_cmpxchg_int
105 | gccjit.func exported @atomic_cmpxchg_int(!pi32, !pi32, !i32) -> !bool {
106 | ^entry(%arg0 : !gccjit.lvalue, %arg1 : !gccjit.lvalue, %arg2 : !gccjit.lvalue):
107 | %0 = gccjit.as_rvalue %arg0 : !gccjit.lvalue to !pi32
108 | %1 = gccjit.as_rvalue %arg1 : !gccjit.lvalue to !pi32
109 | %2 = gccjit.as_rvalue %arg2 : !gccjit.lvalue to !i32
110 | // CHECK: %{{.+}} = __atomic_compare_exchange_4 (((volatile void *)%{{.+}}), ((volatile const void *)%{{.+}}), %{{.+}}, (bool)1, (int)4, (int)0);
111 | %3 = gccjit.atomic.cmpxchg weak success(acq_rel) failure(relaxed) (%0 : !pi32, %1 : !pi32, %2 : !i32) : !bool
112 | gccjit.return %3 : !bool
113 | }
114 |
115 | // CHECK-LABEL: atomic_cmpxchg_float
116 | gccjit.func exported @atomic_cmpxchg_float(!pf32, !pf32, !f32) -> !bool {
117 | ^entry(%arg0 : !gccjit.lvalue, %arg1 : !gccjit.lvalue, %arg2 : !gccjit.lvalue):
118 | %0 = gccjit.as_rvalue %arg0 : !gccjit.lvalue to !pf32
119 | %1 = gccjit.as_rvalue %arg1 : !gccjit.lvalue to !pf32
120 | %2 = gccjit.as_rvalue %arg2 : !gccjit.lvalue to !f32
121 | // CHECK: %{{.+}} = __atomic_compare_exchange_4 (((volatile void *)%{{.+}}), ((volatile const void *)%{{.+}}), (bitcast(%{{.+}}, int)), (bool)1, (int)4, (int)0);
122 | %3 = gccjit.atomic.cmpxchg weak success(acq_rel) failure(relaxed) (%0 : !pf32, %1 : !pf32, %2 : !f32) : !bool
123 | gccjit.return %3 : !bool
124 | }
125 |
126 | // CHECK-LABEL: atomic_cmpxchg_ptr
127 | gccjit.func exported @atomic_cmpxchg_ptr(!ppi32, !ppi32, !pi32) -> !bool {
128 | ^entry(%arg0 : !gccjit.lvalue, %arg1 : !gccjit.lvalue, %arg2 : !gccjit.lvalue):
129 | %0 = gccjit.as_rvalue %arg0 : !gccjit.lvalue to !ppi32
130 | %1 = gccjit.as_rvalue %arg1 : !gccjit.lvalue to !ppi32
131 | %2 = gccjit.as_rvalue %arg2 : !gccjit.lvalue to !pi32
132 | // CHECK: %{{.+}} = __atomic_compare_exchange_8 (((volatile void *)%{{.+}}), ((volatile const void *)%{{.+}}), (bitcast(%{{.+}}, {{long long|long}})), (bool)1, (int)4, (int)0);
133 | %3 = gccjit.atomic.cmpxchg weak success(acq_rel) failure(relaxed) (%0 : !ppi32, %1 : !ppi32, %2 : !pi32) : !bool
134 | gccjit.return %3 : !bool
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/test/compile/bitfield.mlir:
--------------------------------------------------------------------------------
1 | // RUN: %gccjit-translate -o %t.gimple %s -mlir-to-gccjit-gimple
2 | // RUN: %filecheck --input-file=%t.gimple %s
3 | // RUN: %gccjit-translate -o %t.exe %s -mlir-to-gccjit-executable && chmod +x %t.exe && %t.exe
4 |
5 | !int = !gccjit.int
6 | !ilv = !gccjit.lvalue
7 | !bool = !gccjit.int
8 | !bitfields = !gccjit.struct<"Int" {
9 | #gccjit.field<"A" !int : 17>,
10 | #gccjit.field<"B" !int : 5>,
11 | #gccjit.field<"C" !int : 10>
12 | }>
13 |
14 |
15 | module attributes { gccjit.opt_level = #gccjit.opt_level, gccjit.allow_unreachable = true } {
16 | gccjit.func exported @from_int_to_bitfield (!int, !int, !int, !int) {
17 | ^entry(%arg0: !ilv, %arg1: !ilv, %arg2: !ilv, %arg3: !ilv):
18 | %0 = gccjit.as_rvalue %arg0 : !ilv to !int
19 | %1 = gccjit.as_rvalue %arg1 : !ilv to !int
20 | %2 = gccjit.as_rvalue %arg2 : !ilv to !int
21 | %3 = gccjit.as_rvalue %arg3 : !ilv to !int
22 | // CHECK: %[[V:[0-9]+]] = bitcast(%{{[0-9]+}}, struct Int);
23 | // CHECK: %{{[0-9]+}} = %[[V]].A:17;
24 | // CHECK: %{{[0-9]+}} = %[[V]].B:5;
25 | // CHECK: %{{[0-9]+}} = %[[V]].C:10;
26 | %4 = gccjit.bitcast %0 : !int to !bitfields
27 | %5 = gccjit.access_field %4[0] : !bitfields -> !int
28 | %6 = gccjit.access_field %4[1] : !bitfields -> !int
29 | %7 = gccjit.access_field %4[2] : !bitfields -> !int
30 | %eq0 = gccjit.compare eq (%5 : !int, %1 : !int) : !bool
31 | %eq1 = gccjit.compare eq (%6 : !int, %2 : !int) : !bool
32 | %eq2 = gccjit.compare eq (%7 : !int, %3 : !int) : !bool
33 | %and0 = gccjit.binary logical_and (%eq0 : !bool, %eq1 : !bool) : !bool
34 | %and1 = gccjit.binary logical_and (%and0 : !bool, %eq2 : !bool) : !bool
35 | gccjit.conditional (%and1 : !bool), ^return, ^trap
36 |
37 | ^return:
38 | gccjit.return
39 |
40 | ^trap:
41 | gccjit.call builtin @__builtin_trap() : () -> !gccjit.void
42 | gccjit.jump ^trap
43 | }
44 | gccjit.func exported @func_bitfield_to_int(!int, !int, !int, !int) {
45 | ^entry(%arg0: !ilv, %arg1: !ilv, %arg2: !ilv, %arg3: !ilv):
46 | %0 = gccjit.as_rvalue %arg0 : !ilv to !int
47 | %1 = gccjit.as_rvalue %arg1 : !ilv to !int
48 | %2 = gccjit.as_rvalue %arg2 : !ilv to !int
49 | %3 = gccjit.as_rvalue %arg3 : !ilv to !int
50 | // CHECK: (struct Int) {.A:17=%{{[0-9]+}}, .B:5=%{{[0-9]+}}, .C:10=%{{[0-9]+}}};
51 | %4 = gccjit.new_struct [0, 1, 2] [%0, %1, %2] : (!int, !int, !int) -> !bitfields
52 | %5 = gccjit.bitcast %4 : !bitfields to !int
53 | %eq = gccjit.compare eq (%5 : !int, %3 : !int) : !bool
54 | gccjit.conditional (%eq : !bool), ^return, ^trap
55 |
56 | ^return:
57 | gccjit.return
58 |
59 | ^trap:
60 | gccjit.call builtin @__builtin_trap() : () -> !gccjit.void
61 | gccjit.jump ^trap
62 | }
63 |
64 | gccjit.func exported @main() -> !int {
65 | ^entry:
66 | %0 = gccjit.const #gccjit.int<-559038737> : !int
67 | %1 = gccjit.const #gccjit.int<-16657> : !int
68 | %2 = gccjit.const #gccjit.int<-10> : !int
69 | %3 = gccjit.const #gccjit.int<-134> : !int
70 | gccjit.call @from_int_to_bitfield(%0, %1, %2, %3) : (!int, !int, !int, !int) -> ()
71 | gccjit.call @func_bitfield_to_int(%1, %2, %3, %0) : (!int, !int, !int, !int) -> ()
72 |
73 | %ret = gccjit.const #gccjit.zero : !int
74 | gccjit.return %ret : !int
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/test/compile/deref_chain.mlir:
--------------------------------------------------------------------------------
1 | // RUN: %gccjit-translate -o %t.gimple %s -mlir-to-gccjit-gimple
2 | // RUN: %filecheck --input-file=%t.gimple %s --check-prefix=CHECK-GIMPLE
3 | // RUN: %gccjit-translate -o %t.exe %s -mlir-to-gccjit-executable && chmod +x %t.exe
4 | // RUN: %t.exe | %filecheck %s --check-prefix=CHECK-OUTPUT
5 |
6 | !int = !gccjit.int
7 | !bool = !gccjit.int
8 | !ilv = !gccjit.lvalue
9 | !vptr = !gccjit.ptr
10 | !size_t = !gccjit.int
11 | !cell = !gccjit.struct<"Cell" {
12 | #gccjit.field<"prev" !vptr>,
13 | #gccjit.field<"next" !vptr>,
14 | #gccjit.field<"data" !int>
15 | }>
16 | !str = !gccjit.ptr, const>>
17 |
18 | !list = !gccjit.struct<"List" {#gccjit.field<"dummy" !cell>}>
19 |
20 | !cptr = !gccjit.ptr
21 | !lptr = !gccjit.ptr
22 | !visitor = !gccjit.ptr>
23 |
24 | // CHECK-OUTPUT: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
25 | module @test attributes {
26 | gccjit.opt_level = #gccjit.opt_level