Skip to content
Merged
Show file tree
Hide file tree
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
24 changes: 14 additions & 10 deletions gen/declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,35 +256,39 @@ class CodegenVisitor : public Visitor {
if (decl->ir->isDefined())
return;

// skip external declarations (IR-declared lazily)
if (decl->storage_class & STCextern)
return;

if (decl->type->ty == TY::Terror) {
error(decl->loc, "%s `%s` had semantic errors when compiling",
decl->kind(), decl->toPrettyChars());
decl->ir->setDefined();
return;
}

DtoResolveVariable(decl);
decl->ir->setDefined();

// just forward aliases
if (decl->aliasTuple) {
Logger::println("aliasTuple");
decl->toAlias()->accept(this);
return;
}

if (!decl->canTakeAddressOf()) {
Logger::println("manifest constant, skipping");
return;
}

// global variable
if (decl->isDataseg()) {
Logger::println("data segment");
// skip external declarations (IR-declared lazily)
if (decl->storage_class & STCextern) {
Logger::println("external global, skipping");
return;
}

assert(!(decl->storage_class & STCmanifest) &&
"manifest constant being codegen'd!");
Logger::println("global variable");
assert(!irs->dcomputetarget);

DtoResolveVariable(decl);
decl->ir->setDefined();

getIrGlobal(decl)->getValue(/*define=*/true);
}
}
Expand Down
75 changes: 35 additions & 40 deletions gen/llvmhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -935,75 +935,70 @@ void DtoVarDeclaration(VarDeclaration *vd) {
}
}

DValue *DtoDeclarationExp(Dsymbol *declaration) {
void DtoDeclarationExp(Dsymbol *declaration) {
IF_LOG Logger::print("DtoDeclarationExp: %s\n", declaration->toChars());
LOG_SCOPE;

if (VarDeclaration *vd = declaration->isVarDeclaration()) {
if (auto vd = declaration->isVarDeclaration()) {
Logger::println("VarDeclaration");

// if aliasTuple is set, this VarDecl is redone as an alias to another symbol
// this seems to be done to rewrite Tuple!(...) v;
// as a TupleDecl that contains a bunch of individual VarDecls
if (vd->aliasTuple) {
return DtoDeclarationExp(vd->aliasTuple);
Logger::println("aliasTuple");
DtoDeclarationExp(vd->toAlias());
return;
}

if (vd->storage_class & STCmanifest) {
IF_LOG Logger::println("Manifest constant, nothing to do.");
return nullptr;
if (!vd->canTakeAddressOf()) {
Logger::println("Manifest constant, nothing to do.");
return;
}

// static
if (vd->isDataseg()) {
if (vd->isDataseg()) { // global variable
Declaration_codegen(vd);
if (vd->storage_class & STCextern) {
DtoResolveVariable(vd); // make sure there's an IR declaration
}
} else {
} else { // local variable
DtoVarDeclaration(vd);
if (vd->needsScopeDtor()) {
gIR->funcGen().scopes.pushVarDtorCleanup(vd);
}
}
return makeVarDValue(vd->type, vd);
}

if (StructDeclaration *s = declaration->isStructDeclaration()) {
} else if (auto cd = declaration->isClassDeclaration()) {
Logger::println("ClassDeclaration");
Declaration_codegen(cd);
} else if (auto sd = declaration->isStructDeclaration()) {
Logger::println("StructDeclaration");
Declaration_codegen(s);
} else if (FuncDeclaration *f = declaration->isFuncDeclaration()) {
Declaration_codegen(sd);
} else if (auto fd = declaration->isFuncDeclaration()) {
Logger::println("FuncDeclaration");
Declaration_codegen(f);
} else if (ClassDeclaration *e = declaration->isClassDeclaration()) {
Logger::println("ClassDeclaration");
Declaration_codegen(e);
} else if (AttribDeclaration *a = declaration->isAttribDeclaration()) {
Declaration_codegen(fd);
} else if (auto ad = declaration->isAttribDeclaration()) {
Logger::println("AttribDeclaration");
// choose the right set in case this is a conditional declaration
if (auto d = include(a, nullptr)) {
for (unsigned i = 0; i < d->length; ++i) {
DtoDeclarationExp((*d)[i]);
if (auto d = include(ad, nullptr)) {
for (auto sym : *d) {
DtoDeclarationExp(sym);
}
}
} else if (TemplateMixin *m = declaration->isTemplateMixin()) {
} else if (auto tm = declaration->isTemplateMixin()) {
Logger::println("TemplateMixin");
for (Dsymbol *mdsym : *m->members) {
DtoDeclarationExp(mdsym);
for (auto sym : *tm->members) {
DtoDeclarationExp(sym);
}
} else if (TupleDeclaration *tupled = declaration->isTupleDeclaration()) {
} else if (auto td = declaration->isTupleDeclaration()) {
Logger::println("TupleDeclaration");
assert(tupled->isexp && "Non-expression tuple decls not handled yet.");
assert(tupled->objects);
for (unsigned i = 0; i < tupled->objects->length; ++i) {
auto exp = static_cast<DsymbolExp *>((*tupled->objects)[i]);
DtoDeclarationExp(exp->s);
// mimicking `foreachVar()`
for (auto o : *td->objects) {
if (auto e = isExpression(o)) {
if (auto ve = e->isVarExp()) {
DtoDeclarationExp(ve->var);
}
}
}
} else {
// Do nothing for template/alias/enum declarations and static
// assertions. We cannot detect StaticAssert without RTTI, so don't
// even bother to check.
IF_LOG Logger::println("Ignoring Symbol: %s", declaration->kind());
}

return nullptr;
}

// does pretty much the same as DtoDeclarationExp, except it doesn't initialize,
Expand Down
2 changes: 1 addition & 1 deletion gen/llvmhelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ void DtoResolveVariable(VarDeclaration *var);

// declaration inside a declarationexp
void DtoVarDeclaration(VarDeclaration *var);
DValue *DtoDeclarationExp(Dsymbol *declaration);
void DtoDeclarationExp(Dsymbol *declaration);
LLValue *DtoRawVarDeclaration(VarDeclaration *var, LLValue *addr = nullptr);

// initializer helpers
Expand Down
19 changes: 2 additions & 17 deletions gen/toir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,15 +211,6 @@ static void write_struct_literal(Loc loc, LLValue *mem, StructDeclaration *sd,
}

namespace {
void pushVarDtorCleanup(IRState *p, VarDeclaration *vd) {
llvm::BasicBlock *beginBB = p->insertBB(llvm::Twine("dtor.") + vd->toChars());

const auto savedInsertPoint = p->saveInsertPoint();
p->ir->SetInsertPoint(beginBB);
toElemDtor(vd->edtor);
p->funcGen().scopes.pushCleanup(beginBB, p->scopebb());
}

// Zero-extends a scalar i1 to an integer type, or creates a vector mask from an
// i1 vector.
DImValue *zextBool(LLValue *val, Type *to) {
Expand Down Expand Up @@ -318,13 +309,7 @@ class ToElemVisitor : public Visitor {
auto &PGO = gIR->funcGen().pgo;
PGO.setCurrentStmt(e);

result = DtoDeclarationExp(e->declaration);

if (auto vd = e->declaration->isVarDeclaration()) {
if (!vd->isDataseg() && vd->needsScopeDtor()) {
pushVarDtorCleanup(p, vd);
Copy link
Member Author

@kinke kinke Dec 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check was insufficient, as it turned out during intermediate refactorings - IIRC, missing temporaries inside an outer align(N) declaration (as e->declaration).

}
}
DtoDeclarationExp(e->declaration);
}

//////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -838,7 +823,7 @@ class ToElemVisitor : public Visitor {

if (delayedDtorVar) {
delayedDtorVar->edtor = delayedDtorExp;
pushVarDtorCleanup(p, delayedDtorVar);
p->funcGen().scopes.pushVarDtorCleanup(delayedDtorVar);
}

return result;
Expand Down
15 changes: 13 additions & 2 deletions gen/trycatchfinally.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ void TryCatchScope::emitCatchBodies(IRState &irs, llvm::Value *ehPtrSlot) {
if (c->var) {
// This will alloca if we haven't already and take care of nested refs
// if there are any.
DtoDeclarationExp(c->var);
DtoVarDeclaration(c->var);

// Copy the exception reference over from the _d_eh_enter_catch return
// value.
Expand Down Expand Up @@ -214,7 +214,7 @@ void emitBeginCatchMSVC(IRState &irs, Catch *ctch,
// catchpad
const auto savedInsertPoint = irs.saveInsertPoint();
irs.ir->SetInsertPoint(gIR->topallocapoint());
DtoDeclarationExp(var);
DtoVarDeclaration(var);

// catch handler will be outlined, so always treat as a nested reference
exnObj = getIrValue(var);
Expand Down Expand Up @@ -524,6 +524,17 @@ void TryCatchFinallyScopes::pushCleanup(llvm::BasicBlock *beginBlock,
landingPadsPerCleanupScope.emplace_back();
}

void TryCatchFinallyScopes::pushVarDtorCleanup(VarDeclaration *vd) {
llvm::BasicBlock *beginBB = irs.insertBB(llvm::Twine("dtor.") + vd->toChars());

const auto savedInsertPoint = irs.saveInsertPoint();

irs.ir->SetInsertPoint(beginBB);
toElemDtor(vd->edtor);

pushCleanup(beginBB, irs.scopebb());
}

void TryCatchFinallyScopes::popCleanups(CleanupCursor targetScope) {
assert(targetScope <= currentCleanupScope());
if (targetScope == currentCleanupScope())
Expand Down
5 changes: 4 additions & 1 deletion gen/trycatchfinally.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//===-- gen/trycatchfinally.h - Try/catch/finally scopes --------*- C++ -*-===//
//
// LDC the LLVM D compiler
// LDC the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
Expand All @@ -16,6 +16,7 @@
class Identifier;
struct IRState;
class TryCatchStatement;
class VarDeclaration;

namespace llvm {
class AllocaInst;
Expand Down Expand Up @@ -206,6 +207,8 @@ class TryCatchFinallyScopes {
/// scope will branch to.
void pushCleanup(llvm::BasicBlock *beginBlock, llvm::BasicBlock *endBlock);

void pushVarDtorCleanup(VarDeclaration *vd);

/// Terminates the current basic block with a branch to the cleanups needed
/// for leaving the current scope and continuing execution at the target
/// scope stack level.
Expand Down