clang 24.0.0git
CIRABIRewriteContext.h
Go to the documentation of this file.
1//===- CIRABIRewriteContext.h - CIR ABI rewrite context ---------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Defines CIRABIRewriteContext, the CIR dialect's implementation of the
10// generic mlir::abi::ABIRewriteContext. Given a FunctionClassification it
11// rewrites a cir.func signature, the function body, and call sites to match
12// the ABI-lowered shape.
13//
14// This file handles Direct (pass-through and coerce-in-registers), Extend,
15// Ignore, Indirect (sret return, byval and non-byval arguments), and Expand
16// (struct flattening into scalar fields).
17//
18//===----------------------------------------------------------------------===//
19
20#ifndef CLANG_LIB_CIR_DIALECT_TRANSFORMS_TARGETLOWERING_CIRABIREWRITECONTEXT_H
21#define CLANG_LIB_CIR_DIALECT_TRANSFORMS_TARGETLOWERING_CIRABIREWRITECONTEXT_H
22
23#include "mlir/ABI/ABIRewriteContext.h"
24#include "mlir/Analysis/AliasAnalysis.h"
25#include "mlir/IR/BuiltinOps.h"
26#include "mlir/Interfaces/DataLayoutInterfaces.h"
30#include "llvm/ADT/SmallVector.h"
31#include <cassert>
32#include <utility>
33
34namespace cir {
35
36/// CIR-specific implementation of mlir::abi::ABIRewriteContext.
37///
38/// The driver pass (CallConvLoweringPass) computes a FunctionClassification
39/// for each cir.func / cir.call and dispatches to this class to perform the
40/// actual IR rewriting using cir dialect operations.
41///
42/// Holds a reference to the module's DataLayout for coercion alignment
43/// queries. The DataLayout must outlive the rewrite context.
45public:
46 CIRABIRewriteContext(mlir::ModuleOp module, const mlir::DataLayout &dl)
47 : module(module), dl(dl), cirDataLayout(module), aliasAnalysis(module) {
48 cir::registerCIRAliasAnalyses(aliasAnalysis, module);
49 }
50
52 assert(pendingParamSlots.empty() &&
53 "finalizeParameterSlots must run before the rewrite context dies");
54 }
55
56 mlir::LogicalResult
57 rewriteFunctionDefinition(mlir::FunctionOpInterface funcOp,
58 const mlir::abi::FunctionClassification &fc,
59 mlir::OpBuilder &builder) override;
60
61 mlir::LogicalResult
62 rewriteCallSite(mlir::Operation *callOp,
63 const mlir::abi::FunctionClassification &fc,
64 mlir::OpBuilder &builder) override;
65
66 /// Expand a `cir.va_arg` into the x86-64 SysV register-save-area /
67 /// overflow-area sequence.
68 mlir::LogicalResult rewriteVAArg(mlir::Operation *vaArgOp,
69 const mlir::abi::ArgClassification &ac,
70 mlir::OpBuilder &builder) override;
71
72 /// Retype \p addrOp, which holds the address of \p funcOp, to the signature
73 /// funcOp was rewritten to, and cast it back so existing uses keep the type
74 /// they were built for. A no-op when the ABI left funcOp's type alone.
75 /// Call after funcOp has been rewritten. Not an override, since taking a
76 /// function's address has no counterpart in the generic contract.
77 void rewriteFunctionAddress(cir::GetGlobalOp addrOp, cir::FuncOp funcOp,
78 mlir::OpBuilder &builder);
79
80 /// Bring each non-byval indirect parameter of \p funcOp into the shape the
81 /// rest of the rewrite assumes: the parameter's only use, if it has one, is
82 /// a single store into an alloca of the matching pointer type that no other
83 /// non-byval indirect parameter spills to, and that alloca states the
84 /// alignment the ABI promises rather than the one CIRGen picked for a local
85 /// copy. A use of the parameter as a call argument is routed through a load
86 /// of that slot, so that it names the storage an argument has to name.
87 ///
88 /// Call for every function before any definition or call site is rewritten.
89 /// findParamSpill asserts this shape while the enclosing definition is
90 /// rewritten, and a call is rewritten with its callee rather than with its
91 /// enclosing function and so may be reached first.
92 ///
93 /// A parameter read with no spill to name is given one, since it becomes
94 /// the incoming pointer directly. A parameter spilled twice, spilled to a
95 /// slot another such parameter also spills to, consumed other than as a
96 /// call argument, spilled where the incoming pointer cannot replace the
97 /// storage, or read where the spill does not dominate it gets a diagnostic
98 /// on the operation at fault and failure.
99 ///
100 /// Not an override, since this has no counterpart in the generic contract.
101 mlir::LogicalResult
102 prepareNonByvalParameters(cir::FuncOp funcOp,
103 const mlir::abi::FunctionClassification &fc);
104
105 /// Replace each non-byval indirect parameter's spill slot with the
106 /// incoming pointer, so the body operates on the caller's storage in place.
107 /// Call once, after every function and call site has been rewritten: a call
108 /// forwarding such a parameter reads the slot to recognize it. Not an
109 /// override, since deferring this has no counterpart in the generic
110 /// contract.
112
113 mlir::StringRef getDialectNamespace() const override { return "cir"; }
114
115private:
116 mlir::ModuleOp module;
117 const mlir::DataLayout &dl;
118
119 /// The CIR view of the module's data layout, which provides the store and
120 /// alloc sizes that \c dl does not.
121 cir::CIRDataLayout cirDataLayout;
122
123 /// Alias analysis over the module with the CIR implementations registered.
124 /// rewriteCallSite asks it whether a byval operand's storage is written
125 /// between its load and the call.
126 mlir::AliasAnalysis aliasAnalysis;
127
128 /// Param-slot allocas that non-byval indirect parameters will
129 /// replace, paired with the incoming pointer that replaces them. The
130 /// rewrite retypes the block argument but leaves the slot standing, because
131 /// a call site recognizes a forwardable parameter by the slot its operand
132 /// was loaded from. finalizeParameterSlots does the replacement once every
133 /// call site has been rewritten.
135 pendingParamSlots;
136};
137
138/// The signature the indirect call \p call reaches its callee through.
139cir::FuncType getIndirectCalleeType(cir::CIRCallOpInterface call);
140
141} // namespace cir
142
143#endif // CLANG_LIB_CIR_DIALECT_TRANSFORMS_TARGETLOWERING_CIRABIREWRITECONTEXT_H
void rewriteFunctionAddress(cir::GetGlobalOp addrOp, cir::FuncOp funcOp, mlir::OpBuilder &builder)
Retype addrOp, which holds the address of funcOp, to the signature funcOp was rewritten to,...
mlir::LogicalResult rewriteFunctionDefinition(mlir::FunctionOpInterface funcOp, const mlir::abi::FunctionClassification &fc, mlir::OpBuilder &builder) override
void finalizeParameterSlots()
Replace each non-byval indirect parameter's spill slot with the incoming pointer, so the body operate...
mlir::StringRef getDialectNamespace() const override
mlir::LogicalResult prepareNonByvalParameters(cir::FuncOp funcOp, const mlir::abi::FunctionClassification &fc)
Bring each non-byval indirect parameter of funcOp into the shape the rest of the rewrite assumes: the...
CIRABIRewriteContext(mlir::ModuleOp module, const mlir::DataLayout &dl)
mlir::LogicalResult rewriteVAArg(mlir::Operation *vaArgOp, const mlir::abi::ArgClassification &ac, mlir::OpBuilder &builder) override
Expand a cir.va_arg into the x86-64 SysV register-save-area / overflow-area sequence.
mlir::LogicalResult rewriteCallSite(mlir::Operation *callOp, const mlir::abi::FunctionClassification &fc, mlir::OpBuilder &builder) override
void registerCIRAliasAnalyses(mlir::AliasAnalysis &aa, mlir::Operation *op)
Register all CIR alias analysis implementations with aa, which answers queries about values within op...
cir::FuncType getIndirectCalleeType(cir::CIRCallOpInterface call)
The signature the indirect call call reaches its callee through.