Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CIR][NFC] Organize emit functions in CIRGenFunction.h #133017

Merged
merged 2 commits into from
Mar 26, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
261 changes: 137 additions & 124 deletions clang/lib/CIR/CodeGen/CIRGenFunction.h
Original file line number Diff line number Diff line change
@@ -108,15 +108,6 @@ class CIRGenFunction : public CIRGenTypeCache {
bool isParam = false);

public:
mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
mlir::Location loc, clang::CharUnits alignment,
bool insertIntoFnEntryBlock,
mlir::Value arraySize = nullptr);
mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
mlir::Location loc, clang::CharUnits alignment,
mlir::OpBuilder::InsertPoint ip,
mlir::Value arraySize = nullptr);

mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt);

private:
@@ -139,9 +130,6 @@ class CIRGenFunction : public CIRGenTypeCache {
~VarDeclContext() { restore(); }
};

void emitAndUpdateRetAlloca(clang::QualType type, mlir::Location loc,
clang::CharUnits alignment);

public:
/// Use to track source locations across nested visitor traversals.
/// Always use a `SourceLocRAIIObject` to change currSrcLoc.
@@ -170,88 +158,12 @@ class CIRGenFunction : public CIRGenTypeCache {

const clang::LangOptions &getLangOpts() const { return cgm.getLangOpts(); }

/// Emit code to compute the specified expression which can have any type. The
/// result is returned as an RValue struct. If this is an aggregate
/// expression, the aggloc/agglocvolatile arguments indicate where the result
/// should be returned.
RValue emitAnyExpr(const clang::Expr *e);

void finishFunction(SourceLocation endLoc);
mlir::LogicalResult emitFunctionBody(const clang::Stmt *body);

/// Build a debug stoppoint if we are emitting debug info.
void emitStopPoint(const Stmt *s);

// Build CIR for a statement. useCurrentScope should be true if no
// new scopes need be created when finding a compound statement.
mlir::LogicalResult
emitStmt(const clang::Stmt *s, bool useCurrentScope,
llvm::ArrayRef<const Attr *> attrs = std::nullopt);

mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s,
bool useCurrentScope);

mlir::LogicalResult emitForStmt(const clang::ForStmt &S);

void emitCompoundStmt(const clang::CompoundStmt &s);

void emitCompoundStmtWithoutScope(const clang::CompoundStmt &s);

/// Emit code to compute the specified expression,
/// ignoring the result.
void emitIgnoredExpr(const clang::Expr *e);

mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s);

mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s);

/// Given an expression that represents a value lvalue, this method emits
/// the address of the lvalue, then loads the result as an rvalue,
/// returning the rvalue.
RValue emitLoadOfLValue(LValue lv, SourceLocation loc);

/// EmitLoadOfScalar - Load a scalar value from an address, taking
/// care to appropriately convert from the memory representation to
/// the LLVM value representation. The l-value must be a simple
/// l-value.
mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc);

/// Emit code to compute a designator that specifies the location
/// of the expression.
/// FIXME: document this function better.
LValue emitLValue(const clang::Expr *e);

void emitDecl(const clang::Decl &d);

void emitScalarInit(const clang::Expr *init, mlir::Location loc,
LValue lvalue, bool capturedByInit = false);

LValue emitDeclRefLValue(const clang::DeclRefExpr *e);
LValue emitUnaryOpLValue(const clang::UnaryOperator *e);
LValue emitBinaryOperatorLValue(const BinaryOperator *e);

/// Determine whether the given initializer is trivial in the sense
/// that it requires no code to be generated.
bool isTrivialInitializer(const Expr *init);

/// Emit an expression as an initializer for an object (variable, field, etc.)
/// at the given location. The expression is not necessarily the normal
/// initializer for the object, and the address is not necessarily
/// its normal location.
///
/// \param init the initializing expression
/// \param d the object to act as if we're initializing
/// \param lvalue the lvalue to initialize
/// \param capturedByInit true if \p d is a __block variable whose address is
/// potentially changed by the initializer
void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d,
LValue lvalue, bool capturedByInit = false);

/// Emit code and set up symbol table for a variable declaration with auto,
/// register, or no storage class specifier. These turn into simple stack
/// objects, globals depending on target.
void emitAutoVarDecl(const clang::VarDecl &d);

struct AutoVarEmission {
const clang::VarDecl *Variable;
/// The address of the alloca for languages with explicit address space
@@ -297,30 +209,6 @@ class CIRGenFunction : public CIRGenTypeCache {
}
};

AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d);
void emitAutoVarInit(const AutoVarEmission &emission);
void emitAutoVarCleanups(const AutoVarEmission &emission);

void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile,
clang::QualType ty, bool isInit = false,
bool isNontemporal = false);
void emitStoreOfScalar(mlir::Value value, LValue lvalue, bool isInit);

/// Given a value and its clang type, returns the value casted to its memory
/// representation.
/// Note: CIR defers most of the special casting to the final lowering passes
/// to conserve the high level information.
mlir::Value emitToMemory(mlir::Value Value, clang::QualType Ty);

/// Store the specified rvalue into the specified
/// lvalue, where both are guaranteed to the have the same type, and that type
/// is 'Ty'.
void emitStoreThroughLValue(RValue Src, LValue Dst, bool isInit = false);

/// This method handles emission of any variable declaration
/// inside a function, including static vars etc.
void emitVarDecl(const clang::VarDecl &d);

/// Perform the usual unary conversions on the specified expression and
/// compare the result against zero, returning an Int1Ty value.
mlir::Value evaluateExprAsBool(const clang::Expr *e);
@@ -332,12 +220,6 @@ class CIRGenFunction : public CIRGenTypeCache {
// TODO: Add symbol table support
}

mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv,
bool isInc, bool isPre);

/// Emit the computation of the specified expression of scalar type.
mlir::Value emitScalarExpr(const clang::Expr *e);
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType);
cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
cir::FuncType funcType);

@@ -352,12 +234,6 @@ class CIRGenFunction : public CIRGenTypeCache {
FunctionArgList args, clang::SourceLocation loc,
clang::SourceLocation startLoc);

/// Emit a conversion from the specified type to the specified destination
/// type, both of which are CIR scalar types.
mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType,
clang::QualType dstType,
clang::SourceLocation loc);

/// Represents a scope, including function bodies, compound statements, and
/// the substatements of if/while/do/for/switch/try statements. This class
/// handles any automatic cleanup, along with the return value.
@@ -488,6 +364,143 @@ class CIRGenFunction : public CIRGenTypeCache {

LexicalScope *curLexScope = nullptr;

/// ----------------------
/// CIR emit functions
/// ----------------------
private:
void emitAndUpdateRetAlloca(clang::QualType type, mlir::Location loc,
clang::CharUnits alignment);

public:
mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
mlir::Location loc, clang::CharUnits alignment,
bool insertIntoFnEntryBlock,
mlir::Value arraySize = nullptr);
mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty,
mlir::Location loc, clang::CharUnits alignment,
mlir::OpBuilder::InsertPoint ip,
mlir::Value arraySize = nullptr);

/// Emit code to compute the specified expression which can have any type. The
/// result is returned as an RValue struct. If this is an aggregate
/// expression, the aggloc/agglocvolatile arguments indicate where the result
/// should be returned.
RValue emitAnyExpr(const clang::Expr *e);

AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d);

/// Emit code and set up symbol table for a variable declaration with auto,
/// register, or no storage class specifier. These turn into simple stack
/// objects, globals depending on target.
void emitAutoVarDecl(const clang::VarDecl &d);

void emitAutoVarCleanups(const AutoVarEmission &emission);
void emitAutoVarInit(const AutoVarEmission &emission);

LValue emitBinaryOperatorLValue(const BinaryOperator *e);

/// Emit an expression as an initializer for an object (variable, field, etc.)
/// at the given location. The expression is not necessarily the normal
/// initializer for the object, and the address is not necessarily
/// its normal location.
///
/// \param init the initializing expression
/// \param d the object to act as if we're initializing
/// \param lvalue the lvalue to initialize
/// \param capturedByInit true if \p d is a __block variable whose address is
/// potentially changed by the initializer
void emitExprAsInit(const clang::Expr *init, const clang::ValueDecl *d,
LValue lvalue, bool capturedByInit = false);

mlir::LogicalResult emitFunctionBody(const clang::Stmt *body);

mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType);

/// Emit the computation of the specified expression of scalar type.
mlir::Value emitScalarExpr(const clang::Expr *e);

mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv,
bool isInc, bool isPre);

/// Build a debug stoppoint if we are emitting debug info.
void emitStopPoint(const Stmt *s);

// Build CIR for a statement. useCurrentScope should be true if no
// new scopes need be created when finding a compound statement.
mlir::LogicalResult
emitStmt(const clang::Stmt *s, bool useCurrentScope,
llvm::ArrayRef<const Attr *> attrs = std::nullopt);

mlir::LogicalResult emitSimpleStmt(const clang::Stmt *s,
bool useCurrentScope);

mlir::LogicalResult emitForStmt(const clang::ForStmt &s);

void emitCompoundStmt(const clang::CompoundStmt &s);

void emitCompoundStmtWithoutScope(const clang::CompoundStmt &s);

void emitDecl(const clang::Decl &d);
mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s);
LValue emitDeclRefLValue(const clang::DeclRefExpr *e);

/// Emit code to compute the specified expression,
/// ignoring the result.
void emitIgnoredExpr(const clang::Expr *e);

/// Given an expression that represents a value lvalue, this method emits
/// the address of the lvalue, then loads the result as an rvalue,
/// returning the rvalue.
RValue emitLoadOfLValue(LValue lv, SourceLocation loc);

/// EmitLoadOfScalar - Load a scalar value from an address, taking
/// care to appropriately convert from the memory representation to
/// the LLVM value representation. The l-value must be a simple
/// l-value.
mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc);

/// Emit code to compute a designator that specifies the location
/// of the expression.
/// FIXME: document this function better.
LValue emitLValue(const clang::Expr *e);

mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s);

/// Emit a conversion from the specified type to the specified destination
/// type, both of which are CIR scalar types.
mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType,
clang::QualType dstType,
clang::SourceLocation loc);

void emitScalarInit(const clang::Expr *init, mlir::Location loc,
LValue lvalue, bool capturedByInit = false);

void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile,
clang::QualType ty, bool isInit = false,
bool isNontemporal = false);
void emitStoreOfScalar(mlir::Value value, LValue lvalue, bool isInit);

/// Store the specified rvalue into the specified
/// lvalue, where both are guaranteed to the have the same type, and that type
/// is 'Ty'.
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit = false);

/// Given a value and its clang type, returns the value casted to its memory
/// representation.
/// Note: CIR defers most of the special casting to the final lowering passes
/// to conserve the high level information.
mlir::Value emitToMemory(mlir::Value value, clang::QualType ty);

LValue emitUnaryOpLValue(const clang::UnaryOperator *e);

/// This method handles emission of any variable declaration
/// inside a function, including static vars etc.
void emitVarDecl(const clang::VarDecl &d);

/// ----------------------
/// CIR build helpers
/// -----------------
public:
Address createTempAlloca(mlir::Type ty, CharUnits align, mlir::Location loc,
const Twine &name, bool insertIntoFnEntryBlock);
};