mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
125 lines
3.9 KiB
C++
125 lines
3.9 KiB
C++
#pragma once
|
|
|
|
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
#include "revng/Clift/Clift.h"
|
|
#include "revng/Clift/CliftTypes.h"
|
|
#include "revng/PTML/CDoxygenEmitter.h"
|
|
#include "revng/PTML/CTokenEmitter.h"
|
|
#include "revng/Support/CDataModel.h"
|
|
|
|
template<typename Type>
|
|
concept EntityWithComment = requires(Type const &Value) {
|
|
{ Value.getComment() } -> std::convertible_to<llvm::StringRef>;
|
|
};
|
|
|
|
/// Base class with common utilities for emitters emitting C from Clift.
|
|
class CEmitter {
|
|
protected:
|
|
using CTE = ptml::CTokenEmitter;
|
|
|
|
ptml::CTokenEmitter &Tokens;
|
|
const CDataModel &DataModel;
|
|
|
|
public:
|
|
explicit CEmitter(ptml::CTokenEmitter &Emitter, const CDataModel &DataModel) :
|
|
Tokens(Emitter), DataModel(DataModel) {}
|
|
|
|
//===------------------------------- Types ------------------------------===//
|
|
|
|
void emitPrimitiveType(clift::PrimitiveType Type);
|
|
void emitType(mlir::Type Type);
|
|
|
|
//===---------------------------- Attributes ----------------------------===//
|
|
|
|
static bool isValidCAttributeArray(mlir::ArrayAttr Array);
|
|
mlir::ArrayAttr getDeclarationOpCAttributes(mlir::Operation *Op);
|
|
|
|
void emitCAttribute(clift::CAttributeAttr Attribute);
|
|
void emitCAttributes(llvm::ArrayRef<clift::CAttributeAttr> Attributes,
|
|
bool SpaceBefore,
|
|
bool SpaceAfter);
|
|
void emitCAttributes(mlir::ArrayAttr Attributes,
|
|
bool SpaceBefore,
|
|
bool SpaceAfter);
|
|
|
|
//===---------------------------- Prototype -----------------------------===//
|
|
|
|
void emitFunctionPrototype(clift::FunctionOp Function);
|
|
|
|
//===--------------------------- Declarations ---------------------------===//
|
|
|
|
/// Describes a function parameter declarator.
|
|
struct ParameterDeclaratorInfo {
|
|
llvm::StringRef Identifier;
|
|
llvm::StringRef Location;
|
|
mlir::ArrayAttr CAttributes;
|
|
};
|
|
|
|
/// Describes a declarator. This can be any function or variable declarator,
|
|
/// including a function parameter declarator. When emitting a function
|
|
/// declaration, the parameters declarators array must contain entries for
|
|
/// each parameter of the outermost function type.
|
|
struct DeclaratorInfo {
|
|
llvm::StringRef Identifier;
|
|
llvm::StringRef Location;
|
|
mlir::ArrayAttr CAttributes;
|
|
CTE::EntityKind Kind;
|
|
|
|
std::optional<llvm::ArrayRef<ParameterDeclaratorInfo>> Parameters;
|
|
};
|
|
|
|
/// Emit a function or variable declaration of the specified type.
|
|
void emitDeclaration(mlir::Type Type, DeclaratorInfo const &Declarator);
|
|
|
|
private:
|
|
class DeclarationEmitter;
|
|
|
|
public:
|
|
//===----------------------------- Comments -----------------------------===//
|
|
template<EntityWithComment Type>
|
|
void emitDoxygenComment(const Type &Value) {
|
|
llvm::StringRef CommentContent = Value.getComment();
|
|
if (CommentContent.empty())
|
|
return;
|
|
|
|
Tokens.emitNewline();
|
|
ptml::CDoxygenEmitter::emitLineComment(Tokens, CommentContent);
|
|
}
|
|
|
|
void emitFunctionDoxygenComment(clift::FunctionOp Function);
|
|
|
|
void emitGlobalDoxygenComment(clift::GlobalVariableOp Global);
|
|
|
|
public:
|
|
/// A convenience function for emitting a comment with extra empty lines
|
|
/// before and after it. For example:
|
|
///
|
|
/// ```cpp
|
|
/// //
|
|
/// // All of the content, no matter how long it is,
|
|
/// // goes *here*.
|
|
/// //
|
|
/// ```
|
|
void emitCategoryComment(llvm::StringRef Content) {
|
|
Tokens.emitComment("\n " + Content.str() + "\n\n",
|
|
ptml::CTokenEmitter::CommentKind::Line);
|
|
Tokens.emitNewline();
|
|
}
|
|
|
|
public:
|
|
//===--------------------------- Other Helpers --------------------------===//
|
|
|
|
static ptml::CTokenEmitter::EntityKind
|
|
chooseEntityKind(clift::DefinedType Type);
|
|
};
|
|
|
|
/// Determines whether the type can be forward-declared or not.
|
|
///
|
|
/// This is true for `struct`s and `union`s. False for everything else.
|
|
inline bool isSeparateDeclarationAllowed(clift::DefinedType Type) {
|
|
return mlir::isa<clift::ClassType>(Type) or mlir::isa<clift::EnumType>(Type);
|
|
}
|