Skip to content

Commit c136280

Browse files
committed
style: Apply clang-format to copy function implementation
Fix code formatting for copy function overload feature: - Fix line wrapping in CopyLoweringPass comments and long lines - Fix whitespace in StoreInst.hpp - Align header includes alphabetically - Fix string concatenation formatting in ValidCopyOverloadChecker - Remove trailing whitespace
1 parent 7a5b319 commit c136280

23 files changed

Lines changed: 575 additions & 17 deletions

include/GIL/Instructions/StoreInst.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class StoreInst : public InstBase {
4242
Value getSource() const { return _source; }
4343
Value getDest() const { return _dest; }
4444

45+
void setSource(Value source) { _source = source; }
46+
4547
StoreOwnershipKind getOwnershipKind() const { return _ownershipKind; }
4648
void setOwnershipKind(StoreOwnershipKind kind) { _ownershipKind = kind; }
4749

include/GILGen/Context.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,32 @@ class Context {
467467
auto *loadInst = buildLoad(valueType, ptr, gil::LoadOwnershipKind::Take);
468468
return buildDrop(loadInst->getResult(0));
469469
}
470+
471+
gil::CopyInst *buildCopy(gil::Value value)
472+
{
473+
if (value.getType()->isTrivial()) {
474+
// No need to copy trivial types
475+
return nullptr;
476+
}
477+
if (auto *structure
478+
= llvm::dyn_cast<types::StructTy>(value.getType().getType())) {
479+
if (structure->getDecl()->hasOverloadedCopyFunction()) {
480+
// Make sure the copy function is created
481+
getOrCreateGILFunction(structure->getDecl()->getCopyFunction());
482+
}
483+
}
484+
return insertInstruction(new (_arena) gil::CopyInst(value));
485+
}
486+
487+
gil::CopyInst *buildCopyPtr(gil::Type valueType, gil::Value ptr)
488+
{
489+
if (valueType->isTrivial()) {
490+
// No need to copy trivial types
491+
return nullptr;
492+
}
493+
auto *loadInst = buildLoad(valueType, ptr, gil::LoadOwnershipKind::Take);
494+
return buildCopy(loadInst->getResult(0));
495+
}
470496
};
471497

472498
} // namespace glu::gilgen

include/Optimizer/GILPasses.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ GIL_PASS("void-main", VoidMainPass)
99
GIL_PASS("dce", DeadCodeEliminationPass)
1010
GIL_PASS("unreachable-checker", UnreachableInstChecker)
1111
GIL_PASS("drop-lowering", DropLoweringPass)
12+
GIL_PASS("copy-lowering", CopyLoweringPass)
1213

1314
#undef GIL_PASS

lib/ASTPrinter/ASTPrinter.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,6 @@ class ASTPrinter : public ASTVisitor<ASTPrinter> {
6767
llvm::WithColor(out, llvm::raw_ostream::MAGENTA) << node->getKind();
6868
out << " " << node;
6969

70-
auto &sm = *_srcManager;
71-
7270
printSourceLocation(node);
7371

7472
if (auto *expr = llvm::dyn_cast<ExprBase>(node)) {
@@ -170,6 +168,12 @@ class ASTPrinter : public ASTVisitor<ASTPrinter> {
170168
printSourceLocation(node->getDropFunction());
171169
out << '\n';
172170
}
171+
if (node->hasOverloadedCopyFunction()) {
172+
out.indent(_indent - 2);
173+
out << "-->Copy function: " << node->getCopyFunction();
174+
printSourceLocation(node->getCopyFunction());
175+
out << '\n';
176+
}
173177
}
174178

175179
/// @brief Visits a TypeAliasDecl node.

lib/GILGen/GILGenExpr.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ struct GILGenExpr : public ASTVisitor<GILGenExpr, gil::Value> {
159159
// Handle Char to Int
160160
if (llvm::isa<types::CharTy>(sourceType)
161161
&& llvm::isa<types::IntTy>(destType)) {
162-
types::CharTy *charTy = llvm::cast<types::CharTy>(sourceType);
163162
types::IntTy *intTy = llvm::cast<types::IntTy>(destType);
164163

165164
// Char to Int conversion - extend based on signedness
@@ -391,7 +390,7 @@ struct GILGenExpr : public ASTVisitor<GILGenExpr, gil::Value> {
391390
{
392391
// Look up the variable in the current scope
393392
auto varDecl = expr->getVariable();
394-
if (auto fn = llvm::dyn_cast<FunctionDecl *>(varDecl)) {
393+
if (/*auto fn = */ llvm::dyn_cast<FunctionDecl *>(varDecl)) {
395394
// FIXME: probably wrong between function typeand function pointer
396395
// TODO: need gil::Function from ast::FunctionDecl
397396
// return ctx.buildFunctionPtr(

lib/GILGen/GILGenStmt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ struct GILGenStmt : public ASTVisitor<GILGenStmt, void> {
209209
ctx.buildDrop(value);
210210
}
211211

212-
void visitForStmt(ForStmt *stmt)
212+
void visitForStmt([[maybe_unused]] ForStmt *stmt)
213213
{
214214
// TODO: We need sema to can implement this
215215

lib/Optimizer/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ target_sources(Optimizer
2323
GILPasses/DeadCodeEliminationPass.cpp
2424
GILPasses/UnreachableInstChecker.cpp
2525
GILPasses/DropLoweringPass.cpp
26+
GILPasses/CopyLoweringPass.cpp
2627
)
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#include "GIL/InstVisitor.hpp"
2+
#include "GIL/Module.hpp"
3+
#include "GILGen/Context.hpp"
4+
#include "Instructions/LoadInst.hpp"
5+
#include "Instructions/ReturnInst.hpp"
6+
#include "PassManager.hpp"
7+
8+
namespace glu::optimizer {
9+
10+
class CopyLoweringPass : public gil::InstVisitor<CopyLoweringPass> {
11+
private:
12+
gil::Module *module;
13+
std::optional<gilgen::Context> ctx = std::nullopt;
14+
llvm::BumpPtrAllocator &arena;
15+
llvm::SmallVector<gil::InstBase *, 8> toErase;
16+
bool inCopyFunction = false; // Track if we're inside a copy function
17+
18+
public:
19+
CopyLoweringPass(gil::Module *module, llvm::BumpPtrAllocator &arena)
20+
: module(module), arena(arena)
21+
{
22+
}
23+
24+
~CopyLoweringPass()
25+
{
26+
for (auto *inst : toErase) {
27+
inst->eraseFromParent();
28+
}
29+
}
30+
31+
void visitLoadInst(gil::LoadInst *loadInst)
32+
{
33+
// Don't transform loads inside copy functions (would cause infinite
34+
// recursion)
35+
if (inCopyFunction)
36+
return;
37+
38+
// Only handle load [copy] instructions
39+
if (loadInst->getOwnershipKind() != gil::LoadOwnershipKind::Copy)
40+
return;
41+
42+
if (!ctx)
43+
return;
44+
45+
// Generate code to call the copy function if it exists
46+
auto *structure = llvm::dyn_cast<types::StructTy>(
47+
loadInst->getResultType(0).getType()
48+
);
49+
if (structure && structure->getDecl()->hasOverloadedCopyFunction()) {
50+
// Change the load to trivial ownership (no copy semantics)
51+
loadInst->setOwnershipKind(gil::LoadOwnershipKind::Trivial);
52+
53+
// Insert a call to the copy function after the load
54+
auto *bb = loadInst->getParent();
55+
auto it = std::next(loadInst->getIterator());
56+
gil::InstBase *nextInst
57+
= (it != bb->getInstructions().end()) ? &*it : nullptr;
58+
59+
ctx->setInsertionPoint(bb, nextInst);
60+
ctx->setSourceLoc(loadInst->getLocation());
61+
62+
// Call the copy function with the loaded value
63+
auto *callInst = ctx->buildCall(
64+
structure->getDecl()->getCopyFunction(),
65+
{ loadInst->getResult(0) }
66+
);
67+
68+
// Find the store that uses this load's result and update it
69+
if (nextInst && llvm::isa<gil::StoreInst>(nextInst)) {
70+
auto *storeInst = llvm::cast<gil::StoreInst>(nextInst);
71+
if (storeInst->getSource() == loadInst->getResult(0)) {
72+
// Replace the store's source with the call result
73+
storeInst->setSource(callInst->getResult(0));
74+
}
75+
}
76+
}
77+
}
78+
79+
void visitCopyInst(gil::CopyInst *copyInst)
80+
{
81+
if (!ctx)
82+
return;
83+
84+
auto *bb = copyInst->getParent();
85+
ctx->setInsertionPoint(bb, copyInst);
86+
ctx->setSourceLoc(copyInst->getLocation());
87+
88+
// Generate code to call the copy function if it exists
89+
if (auto *structure = llvm::dyn_cast<types::StructTy>(
90+
copyInst->getSource().getType().getType()
91+
)) {
92+
if (structure->getDecl()->hasOverloadedCopyFunction()) {
93+
auto *callInst = ctx->buildCall(
94+
structure->getDecl()->getCopyFunction(),
95+
{ copyInst->getSource() }
96+
);
97+
// Replace the copy instruction with the call instruction
98+
bb->replaceInstruction(copyInst, callInst);
99+
return; // Don't erase, we replaced it
100+
}
101+
}
102+
103+
// Remove the original copy instruction if no custom copy function
104+
toErase.push_back(copyInst);
105+
}
106+
107+
void beforeVisitFunction(gil::Function *func)
108+
{
109+
// Check if this is a copy function
110+
if (func->getName() == "copy") {
111+
inCopyFunction = true;
112+
}
113+
114+
// Create context for this function
115+
ctx.emplace(module, func, arena);
116+
}
117+
118+
void afterVisitFunction(gil::Function *)
119+
{
120+
ctx.reset();
121+
inCopyFunction = false;
122+
}
123+
};
124+
125+
void PassManager::runCopyLoweringPass()
126+
{
127+
CopyLoweringPass pass(_module, _gilArena);
128+
pass.visit(_module);
129+
}
130+
131+
} // namespace glu::optimizer

lib/Sema/ConstraintSystem/ConcreteTypeVisitor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class ConcreteTypeVisitor
1414

1515
bool visitTypeBase(glu::types::TypeBase * /*type*/) { return true; }
1616

17-
bool visitTypeVariableTy(glu::types::TypeVariableTy *type)
17+
bool visitTypeVariableTy([[maybe_unused]] glu::types::TypeVariableTy *type)
1818
{
1919
return false; // Type variables are not concrete
2020
}

lib/Sema/ConstraintSystem/Constraint.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ Constraint::Constraint(
6565
llvm_unreachable(
6666
"Wrong constructor for ExpressibleByLiteral constraint"
6767
);
68+
default: llvm_unreachable("Unsupported constraint kind");
6869
}
6970
}
7071

0 commit comments

Comments
 (0)