From 511ed579860b5d366d91ec5361ec53fe53bfbadf Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Thu, 6 Nov 2025 15:44:55 +0100 Subject: [PATCH 01/24] feat: add basic test --- include/Optimizer/GILPasses.def | 1 + lib/Optimizer/CMakeLists.txt | 1 + .../GILPasses/DetectUninitializedPass.cpp | 459 ++++++++++++++++++ stdlib/defaultImports/stringType.glu | 2 +- test/functional/run/use_unitialized_var.glu | 97 ++++ 5 files changed, 559 insertions(+), 1 deletion(-) create mode 100644 lib/Optimizer/GILPasses/DetectUninitializedPass.cpp create mode 100644 test/functional/run/use_unitialized_var.glu diff --git a/include/Optimizer/GILPasses.def b/include/Optimizer/GILPasses.def index 5382c8583..056177667 100644 --- a/include/Optimizer/GILPasses.def +++ b/include/Optimizer/GILPasses.def @@ -10,6 +10,7 @@ GIL_PASS("dce", DeadCodeEliminationPass) GIL_PASS("unreachable-checker", UnreachableInstChecker) // Lowering passes +GIL_PASS("detect-uninitialized", GILDetectUninitializedPass) GIL_PASS("drop-lowering", DropLoweringPass) GIL_PASS("copy-lowering", CopyLoweringPass) diff --git a/lib/Optimizer/CMakeLists.txt b/lib/Optimizer/CMakeLists.txt index 1bd221384..c6f979b56 100644 --- a/lib/Optimizer/CMakeLists.txt +++ b/lib/Optimizer/CMakeLists.txt @@ -24,4 +24,5 @@ target_sources(Optimizer GILPasses/UnreachableInstChecker.cpp GILPasses/DropLoweringPass.cpp GILPasses/CopyLoweringPass.cpp + GILPasses/DetectUninitializedPass.cpp ) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp new file mode 100644 index 000000000..f34f14636 --- /dev/null +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -0,0 +1,459 @@ +#include "Basic/Diagnostic.hpp" +#include "Basic/SourceLocation.hpp" +#include "GIL/BasicBlock.hpp" +#include "GIL/Function.hpp" +#include "GIL/InstVisitor.hpp" +#include "GIL/Instructions.hpp" +#include "GIL/Module.hpp" +#include "PassManager.hpp" + +#include +#include +#include +#include + +namespace glu::gil { +class BrInst; +class CondBrInst; +} + +namespace glu::optimizer { + +class DetectUninitializedPass + : public gil::InstVisitor { +private: + DiagnosticManager &diagManager; + + llvm::DenseMap> + predecessorMap; + + enum class MemoryState { Uninitialized, Initialized }; + + llvm::DenseMap currentState; + + llvm::DenseMap> + blockEndStates; + + void buildPredecessorMap(gil::Function *func) + { + predecessorMap.clear(); + + llvm::DenseSet visited; + llvm::SmallVector stack; + + if (func->getBasicBlockCount() > 0) { + stack.push_back(func->getEntryBlock()); + } + + while (!stack.empty()) { + gil::BasicBlock *currentBB = stack.pop_back_val(); + + if (!visited.insert(currentBB).second) { + continue; + } + + auto *terminator = currentBB->getTerminator(); + if (!terminator) + continue; + + llvm::SmallVector successors; + + if (auto *brInst = llvm::dyn_cast(terminator)) { + if (auto *dest = brInst->getDestination()) { + successors.push_back(dest); + } + } else if (auto *condBr + = llvm::dyn_cast(terminator)) { + if (auto *thenBlock = condBr->getThenBlock()) { + successors.push_back(thenBlock); + } + if (auto *elseBlock = condBr->getElseBlock()) { + successors.push_back(elseBlock); + } + } + + for (auto *successor : successors) { + predecessorMap[successor].push_back(currentBB); + + if (visited.find(successor) == visited.end()) { + stack.push_back(successor); + } + } + } + } + + llvm::ArrayRef getPredecessors(gil::BasicBlock *bb) + { + auto it = predecessorMap.find(bb); + if (it != predecessorMap.end()) { + return it->second; + } + return {}; + } + + void analyzeBasicBlockState( + gil::BasicBlock *bb, llvm::DenseMap &state + ) + { + // std::cout << " Analyzing basic block: " << bb->getLabel().str() + // << std::endl; + + for (auto &inst : bb->getInstructions()) { + if (auto *store = llvm::dyn_cast(&inst)) { + gil::Value destPtr = store->getDest(); + state[destPtr] = MemoryState::Initialized; + // std::cout + // << " Found store - marking location as initialized" + // << std::endl; + } else if (auto *load = llvm::dyn_cast(&inst)) { + gil::Value srcPtr = load->getValue(); + // std::cout + // << " Found load - checking if location was + // initialized" + // << std::endl; + auto it = state.find(srcPtr); + if (it == state.end() + || it->second == MemoryState::Uninitialized) { + // std::cout << " WARNING: Loading from potentially " + // "uninitialized location" + // << std::endl; + } + } else if (auto *alloca = llvm::dyn_cast(&inst)) { + gil::Value allocatedPtr = alloca->getResult(0); + state[allocatedPtr] = MemoryState::Uninitialized; + // std::cout + // << " Found alloca - marking location as + // uninitialized" + // << std::endl; + } else if (auto *ptrOffsets + = llvm::dyn_cast(&inst)) { + gil::Value basePtr = ptrOffsets->getBasePointer(); + + state[ptrOffsets->getResult(0)] = state[basePtr]; + } else if (auto *structFieldPtr + = llvm::dyn_cast(&inst)) { + gil::Value basePtr = structFieldPtr->getResult(0); + + state[structFieldPtr->getResult(0)] = state[basePtr]; + } + } + } + + void traversePredecessorsForState(gil::BasicBlock *bb) + { + auto preds = getPredecessors(bb); + // std::cout << " Traversing predecessors to check initialization + // state:" + // << std::endl; + + if (preds.empty()) { + // std::cout << " Entry block - all values start uninitialized" + // << std::endl; + return; + } + + for (auto *pred : preds) { + // std::cout << " Checking predecessor: " << + // pred->getLabel().str() + // << std::endl; + + auto predIt = blockEndStates.find(pred); + if (predIt == blockEndStates.end()) { + llvm::DenseMap predState; + analyzeBasicBlockState(pred, predState); + blockEndStates[pred] = predState; + predIt = blockEndStates.find(pred); + } + + auto const &predState = predIt->second; + // std::cout << " Predecessor state contains " << + // predState.size() + // << " memory locations" << std::endl; + + for (auto const &entry : predState) { + std::string stateStr + = (entry.second == MemoryState::Initialized) + ? "initialized" + : "uninitialized"; + // std::cout << " Memory location: " << stateStr + // << std::endl; + } + } + } + +public: + DetectUninitializedPass(DiagnosticManager &diagManager) + : diagManager(diagManager) + { + } + + void beforeVisitFunction(gil::Function *func) + { + buildPredecessorMap(func); + + // Initialize all block states to empty first + blockEndStates.clear(); + currentState.clear(); + + // Perform fixed-point iteration until states stabilize + bool changed = true; + int iteration = 0; + while (changed && iteration < 100) { // Prevent infinite loops + changed = false; + iteration++; + + // std::cout << "\n=== ITERATION " << iteration << " ===" << + // std::endl; + + for (auto &bb : func->getBasicBlocks()) { + // Save the old state for this block + auto oldState = blockEndStates.find(&bb) != blockEndStates.end() + ? blockEndStates[&bb] + : llvm::DenseMap {}; + + // Merge states from predecessors + mergeStatesFromPredecessors(&bb); + + // Analyze this block with the merged state + analyzeBasicBlockState(&bb, currentState); + + // Check if the end state for this block changed + if (blockEndStates[&bb] != oldState) { + changed = true; + // std::cout << "Block " << bb.getLabel().str() << " state + // changed" << std::endl; + } + + // Update the end state for this block + blockEndStates[&bb] = currentState; + } + } + + if (iteration >= 100) { + // std::cout << "WARNING: Fixed-point iteration did not converge!" + // << std::endl; + } + } + + void beforeVisitBasicBlock(gil::BasicBlock *bb) + { + // std::cout << "\n========================================" << + // std::endl; std::cout << "FINAL VISIT BASIC BLOCK: " << + // bb->getLabel().str() + // << std::endl; + // std::cout << "========================================" << std::endl; + + // Use the pre-computed state from fixed-point iteration + auto it = blockEndStates.find(bb); + if (it != blockEndStates.end()) { + // Start with the state at the beginning of this block + mergeStatesFromPredecessors(bb); + } else { + // Entry block case + currentState.clear(); + } + + // std::cout << "Starting state for this block:" << std::endl; + for (auto const &entry : currentState) { + printVariableState(entry.first, entry.second, " "); + } + // std::cout << "----------------------------------------\n" << + // std::endl; + } + + void afterVisitBasicBlock(gil::BasicBlock *bb) + { + blockEndStates[bb] = currentState; + } + + void visitStoreInst(gil::StoreInst *store) + { + gil::Value destPtr = store->getDest(); + + auto it = currentState.find(destPtr); + MemoryState prevState = (it != currentState.end()) + ? it->second + : MemoryState::Uninitialized; + + // std::cout << "Found store instruction to memory location:" << + // std::endl; + + if (prevState == MemoryState::Uninitialized) { + store->setOwnershipKind(gil::StoreOwnershipKind::Init); + // std::cout + // << " Setting ownership to Init (location was uninitialized)" + // << std::endl; + } else { + store->setOwnershipKind(gil::StoreOwnershipKind::Set); + // std::cout << " Setting ownership to Set (location was + // initialized)" + // << std::endl; + } + + currentState[destPtr] = MemoryState::Initialized; + // std::cout << " Location is now initialized" << std::endl; + } + + void visitLoadInst(gil::LoadInst *load) + { + gil::Value srcPtr = load->getValue(); + + auto it = currentState.find(srcPtr); + MemoryState state = (it != currentState.end()) + ? it->second + : MemoryState::Uninitialized; // Default to uninitialized for + // unknown values + + // Show which memory location we're loading from + if (auto *defInst = srcPtr.getDefiningInstruction()) { + // std::cout << "Found load from memory location (result " + // << srcPtr.getIndex() << " of instruction):" << + // std::endl; + } else { + // std::cout << "Found load from memory location (block argument " + // << srcPtr.getIndex() << "):" << std::endl; + } + + if (state == MemoryState::Uninitialized) { + // std::cout << " ERROR: Load from uninitialized memory location" + // << std::endl; + // show error with diagnostic manager + diagManager.warning( + load->getLocation(), "Load from uninitialized memory location" + ); + } else { + // std::cout << " OK: Load from initialized memory location" + // << std::endl; + } + + if (load->getOwnershipKind() == gil::LoadOwnershipKind::Take) { + currentState[srcPtr] = MemoryState::Uninitialized; + // std::cout << " Load is Take - marking location as uninitialized + // " + // "after load" + // << std::endl; + } + } + + void visitAllocaInst(gil::AllocaInst *alloca) + { + if (alloca->getResultCount() > 0) { + gil::Value allocatedPtr = alloca->getResult(0); + currentState[allocatedPtr] = MemoryState::Uninitialized; + // std::cout + // << "Found alloca - marking new allocation as uninitialized" + // << std::endl; + } + } + +private: + void printVariableState( + gil::Value ptr, MemoryState state, std::string const &indent + ) + { + std::string stateStr + = (state == MemoryState::Initialized ? "INITIALIZED" + : "UNINITIALIZED"); + + if (auto *defInst = ptr.getDefiningInstruction()) { + // It's a result of an instruction - try to identify what it is + if (llvm::isa(defInst)) { + // std::cout << indent << "%" << ptr.getIndex() + // << " (alloca): " << stateStr << std::endl; + } else { + // std::cout << indent << "%" << ptr.getIndex() + // << " (instruction result): " << stateStr << + // std::endl; + } + } else { + // It's a block argument (function parameter) + // std::cout << indent << "%" << ptr.getIndex() + // << " (function parameter): " << stateStr << std::endl; + } + } + + void mergeStatesFromPredecessors(gil::BasicBlock *bb) + { + auto preds = getPredecessors(bb); + if (preds.empty()) { + // Entry block - start with empty state + currentState.clear(); + return; + } + + bool first = true; + llvm::DenseSet allValues; + + // Collect all values from all predecessors first + for (auto *pred : preds) { + auto predIt = blockEndStates.find(pred); + if (predIt != blockEndStates.end()) { + for (auto const &entry : predIt->second) { + allValues.insert(entry.first); + } + } + } + + // Initialize current state + currentState.clear(); + + // For each value, check consistency across all predecessors + for (gil::Value value : allValues) { + bool isConsistent = true; + MemoryState consensusState = MemoryState::Uninitialized; + bool hasAnyState = false; + + for (auto *pred : preds) { + auto predIt = blockEndStates.find(pred); + if (predIt != blockEndStates.end()) { + auto valueIt = predIt->second.find(value); + if (valueIt != predIt->second.end()) { + if (!hasAnyState) { + consensusState = valueIt->second; + hasAnyState = true; + } else if (consensusState != valueIt->second) { + isConsistent = false; + break; + } + } else { + // Value not found in this predecessor + if (hasAnyState + && consensusState != MemoryState::Uninitialized) { + isConsistent = false; + break; + } + } + } + } + + if (!isConsistent) { + // Inconsistent state across predecessors - mark as + // uninitialized + currentState[value] = MemoryState::Uninitialized; + } else { + currentState[value] = consensusState; + } + } + } + +public: + void afterVisitFunction(gil::Function *func) + { + predecessorMap.clear(); + blockEndStates.clear(); + currentState.clear(); + } +}; + +void PassManager::runGILDetectUninitializedPass() +{ + DetectUninitializedPass pass(_diagManager); + pass.visit(_module); +} + +} // namespace glu::optimizer + +// load take 면 그 다음에 uninitialzed +// 좋아 +// allias structFieldPtn은 +// ptr offset => operator [] diff --git a/stdlib/defaultImports/stringType.glu b/stdlib/defaultImports/stringType.glu index 2fa6a2369..0cad481c4 100644 --- a/stdlib/defaultImports/stringType.glu +++ b/stdlib/defaultImports/stringType.glu @@ -5,7 +5,7 @@ public struct String { } @inline @no_mangling public func glu_createConstantString(s: *Char, length: Int) -> String { - var str: String; + var str: String = ""; str.data = s; str.length = length; diff --git a/test/functional/run/use_unitialized_var.glu b/test/functional/run/use_unitialized_var.glu new file mode 100644 index 000000000..5e9d04fc6 --- /dev/null +++ b/test/functional/run/use_unitialized_var.glu @@ -0,0 +1,97 @@ +// +// RUN: gluc %s -c -o %t 2>&1 | FileCheck -v %s +// + +import allocation::allocate; +import io; + +func rfeergerg(machin: Bool) -> Void { + var x : Int; + + if (machin) { + x = 0; + } + // CHECK: warning: Load from uninitialized memory location + io::printLine(x); +} + +func ergfer(machin: Bool) -> Void { + var x : Int; + + if (machin) { + x = 0; + } else { + x = 1; + } + // OK + io::printLine(x); +} + +func qewrff(machin: Bool) -> Void { + var x : Int; + + if (machin) { + x = 0; // init + } else { + x = 1; // init + } + x = x + 1; // set + // OK + io::printLine(x); +} + + +func rthg(machin: Bool) -> Void { + var x : Int; + + if (machin) { + x = 0; // init + } + x = 1; // don't know if init or check + // CHECK: warning: Load from uninitialized memory location + io::printLine(x); +} + + +func qewrffasddd(machin: Bool) -> Void { + var x : Int; + + if (machin) { + x = 0; // init + } else { + x = 1; // init + } + + if (machin) { + x = 0; // set + } else { + x = 1; // set + } + x = x + 1; // set + // OK + io::printLine(x); +} + +func qewrffasddd() -> Void { + var result: String = ""; + result.data = allocate(1); + // OK + result.data[0]; +} + +func <(lhs: Char, rhs: Char) -> Bool { + return (lhs as UInt8) < (rhs as UInt8); +} + +public func stringToInt(s: String) -> Int { + var i: Int = 0; + var result: Int = 0; + + // Skip leading whitespace + while (i < s.length) { + i = i + 1; + } + + // OK + return result; +} From 4436f43d74adc7e125b6589bfa4bba12d0803e10 Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Thu, 6 Nov 2025 17:44:41 +0100 Subject: [PATCH 02/24] chore: add prints --- .../GILPasses/DetectUninitializedPass.cpp | 135 +++++++-------- test/functional/run/use_unitialized_var.glu | 156 +++++++++--------- 2 files changed, 141 insertions(+), 150 deletions(-) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index f34f14636..890e73629 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -102,29 +102,27 @@ class DetectUninitializedPass if (auto *store = llvm::dyn_cast(&inst)) { gil::Value destPtr = store->getDest(); state[destPtr] = MemoryState::Initialized; - // std::cout - // << " Found store - marking location as initialized" - // << std::endl; + std::cout + << " Found store - marking location as initialized" + << std::endl; } else if (auto *load = llvm::dyn_cast(&inst)) { gil::Value srcPtr = load->getValue(); - // std::cout - // << " Found load - checking if location was - // initialized" - // << std::endl; + std::cout + << " Found load - checking if location was initialized" + << std::endl; auto it = state.find(srcPtr); if (it == state.end() || it->second == MemoryState::Uninitialized) { - // std::cout << " WARNING: Loading from potentially " - // "uninitialized location" - // << std::endl; + std::cout << " WARNING: Loading from potentially " + "uninitialized location" + << std::endl; } } else if (auto *alloca = llvm::dyn_cast(&inst)) { gil::Value allocatedPtr = alloca->getResult(0); state[allocatedPtr] = MemoryState::Uninitialized; - // std::cout - // << " Found alloca - marking location as - // uninitialized" - // << std::endl; + std::cout + << " Found alloca - marking location as uninitialized" + << std::endl; } else if (auto *ptrOffsets = llvm::dyn_cast(&inst)) { gil::Value basePtr = ptrOffsets->getBasePointer(); @@ -142,20 +140,18 @@ class DetectUninitializedPass void traversePredecessorsForState(gil::BasicBlock *bb) { auto preds = getPredecessors(bb); - // std::cout << " Traversing predecessors to check initialization - // state:" - // << std::endl; + std::cout << " Traversing predecessors to check initialization state:" + << std::endl; if (preds.empty()) { - // std::cout << " Entry block - all values start uninitialized" - // << std::endl; + std::cout << " Entry block - all values start uninitialized" + << std::endl; return; } for (auto *pred : preds) { - // std::cout << " Checking predecessor: " << - // pred->getLabel().str() - // << std::endl; + std::cout << " Checking predecessor: " << pred->getLabel().str() + << std::endl; auto predIt = blockEndStates.find(pred); if (predIt == blockEndStates.end()) { @@ -166,17 +162,16 @@ class DetectUninitializedPass } auto const &predState = predIt->second; - // std::cout << " Predecessor state contains " << - // predState.size() - // << " memory locations" << std::endl; + std::cout << " Predecessor state contains " << predState.size() + << " memory locations" << std::endl; for (auto const &entry : predState) { std::string stateStr = (entry.second == MemoryState::Initialized) ? "initialized" : "uninitialized"; - // std::cout << " Memory location: " << stateStr - // << std::endl; + std::cout << " Memory location: " << stateStr + << std::endl; } } } @@ -202,8 +197,7 @@ class DetectUninitializedPass changed = false; iteration++; - // std::cout << "\n=== ITERATION " << iteration << " ===" << - // std::endl; + std::cout << "\n=== ITERATION " << iteration << " ===" << std::endl; for (auto &bb : func->getBasicBlocks()) { // Save the old state for this block @@ -220,8 +214,8 @@ class DetectUninitializedPass // Check if the end state for this block changed if (blockEndStates[&bb] != oldState) { changed = true; - // std::cout << "Block " << bb.getLabel().str() << " state - // changed" << std::endl; + std::cout << "Block " << bb.getLabel().str() + << " state changed" << std::endl; } // Update the end state for this block @@ -230,18 +224,17 @@ class DetectUninitializedPass } if (iteration >= 100) { - // std::cout << "WARNING: Fixed-point iteration did not converge!" - // << std::endl; + std::cout << "WARNING: Fixed-point iteration did not converge!" + << std::endl; } } void beforeVisitBasicBlock(gil::BasicBlock *bb) { - // std::cout << "\n========================================" << - // std::endl; std::cout << "FINAL VISIT BASIC BLOCK: " << - // bb->getLabel().str() - // << std::endl; - // std::cout << "========================================" << std::endl; + std::cout << "\n========================================" << std::endl; + std::cout << "FINAL VISIT BASIC BLOCK: " << bb->getLabel().str() + << std::endl; + std::cout << "========================================" << std::endl; // Use the pre-computed state from fixed-point iteration auto it = blockEndStates.find(bb); @@ -257,8 +250,7 @@ class DetectUninitializedPass for (auto const &entry : currentState) { printVariableState(entry.first, entry.second, " "); } - // std::cout << "----------------------------------------\n" << - // std::endl; + std::cout << "----------------------------------------\n" << std::endl; } void afterVisitBasicBlock(gil::BasicBlock *bb) @@ -275,23 +267,21 @@ class DetectUninitializedPass ? it->second : MemoryState::Uninitialized; - // std::cout << "Found store instruction to memory location:" << - // std::endl; + std::cout << "Found store instruction to memory location:" << std::endl; if (prevState == MemoryState::Uninitialized) { store->setOwnershipKind(gil::StoreOwnershipKind::Init); - // std::cout - // << " Setting ownership to Init (location was uninitialized)" - // << std::endl; + std::cout + << " Setting ownership to Init (location was uninitialized)" + << std::endl; } else { store->setOwnershipKind(gil::StoreOwnershipKind::Set); - // std::cout << " Setting ownership to Set (location was - // initialized)" - // << std::endl; + std::cout << " Setting ownership to Set (location was initialized)" + << std::endl; } currentState[destPtr] = MemoryState::Initialized; - // std::cout << " Location is now initialized" << std::endl; + std::cout << " Location is now initialized" << std::endl; } void visitLoadInst(gil::LoadInst *load) @@ -301,37 +291,35 @@ class DetectUninitializedPass auto it = currentState.find(srcPtr); MemoryState state = (it != currentState.end()) ? it->second - : MemoryState::Uninitialized; // Default to uninitialized for - // unknown values + : MemoryState::Initialized; // Default to initialized for + // unknown values // Show which memory location we're loading from if (auto *defInst = srcPtr.getDefiningInstruction()) { - // std::cout << "Found load from memory location (result " - // << srcPtr.getIndex() << " of instruction):" << - // std::endl; + std::cout << "Found load from memory location (result " + << srcPtr.getIndex() << " of instruction):" << std::endl; } else { - // std::cout << "Found load from memory location (block argument " - // << srcPtr.getIndex() << "):" << std::endl; + std::cout << "Found load from memory location (block argument " + << srcPtr.getIndex() << "):" << std::endl; } if (state == MemoryState::Uninitialized) { - // std::cout << " ERROR: Load from uninitialized memory location" - // << std::endl; + std::cout << " ERROR: Load from uninitialized memory location" + << std::endl; // show error with diagnostic manager diagManager.warning( load->getLocation(), "Load from uninitialized memory location" ); } else { - // std::cout << " OK: Load from initialized memory location" - // << std::endl; + std::cout << " OK: Load from initialized memory location" + << std::endl; } if (load->getOwnershipKind() == gil::LoadOwnershipKind::Take) { currentState[srcPtr] = MemoryState::Uninitialized; - // std::cout << " Load is Take - marking location as uninitialized - // " - // "after load" - // << std::endl; + std::cout << " Load is Take - marking location as uninitialized " + "after load" + << std::endl; } } @@ -340,9 +328,9 @@ class DetectUninitializedPass if (alloca->getResultCount() > 0) { gil::Value allocatedPtr = alloca->getResult(0); currentState[allocatedPtr] = MemoryState::Uninitialized; - // std::cout - // << "Found alloca - marking new allocation as uninitialized" - // << std::endl; + std::cout + << "Found alloca - marking new allocation as uninitialized" + << std::endl; } } @@ -358,17 +346,16 @@ class DetectUninitializedPass if (auto *defInst = ptr.getDefiningInstruction()) { // It's a result of an instruction - try to identify what it is if (llvm::isa(defInst)) { - // std::cout << indent << "%" << ptr.getIndex() - // << " (alloca): " << stateStr << std::endl; + std::cout << indent << "%" << ptr.getIndex() + << " (alloca): " << stateStr << std::endl; } else { - // std::cout << indent << "%" << ptr.getIndex() - // << " (instruction result): " << stateStr << - // std::endl; + std::cout << indent << "%" << ptr.getIndex() + << " (instruction result): " << stateStr << std::endl; } } else { // It's a block argument (function parameter) - // std::cout << indent << "%" << ptr.getIndex() - // << " (function parameter): " << stateStr << std::endl; + std::cout << indent << "%" << ptr.getIndex() + << " (function parameter): " << stateStr << std::endl; } } diff --git a/test/functional/run/use_unitialized_var.glu b/test/functional/run/use_unitialized_var.glu index 5e9d04fc6..27606aa1d 100644 --- a/test/functional/run/use_unitialized_var.glu +++ b/test/functional/run/use_unitialized_var.glu @@ -5,40 +5,40 @@ import allocation::allocate; import io; -func rfeergerg(machin: Bool) -> Void { - var x : Int; - - if (machin) { - x = 0; - } - // CHECK: warning: Load from uninitialized memory location - io::printLine(x); -} - -func ergfer(machin: Bool) -> Void { - var x : Int; - - if (machin) { - x = 0; - } else { - x = 1; - } - // OK - io::printLine(x); -} - -func qewrff(machin: Bool) -> Void { - var x : Int; - - if (machin) { - x = 0; // init - } else { - x = 1; // init - } - x = x + 1; // set - // OK - io::printLine(x); -} +// func rfeergerg(machin: Bool) -> Void { +// var x : Int; + +// if (machin) { +// x = 0; +// } +// // CHECK: warning: Load from uninitialized memory location +// io::printLine(x); +// } + +// func ergfer(machin: Bool) -> Void { +// var x : Int; + +// if (machin) { +// x = 0; +// } else { +// x = 1; +// } +// // OK +// io::printLine(x); +// } + +// func qewrff(machin: Bool) -> Void { +// var x : Int; + +// if (machin) { +// x = 0; // init +// } else { +// x = 1; // init +// } +// x = x + 1; // set +// // OK +// io::printLine(x); +// } func rthg(machin: Bool) -> Void { @@ -53,45 +53,49 @@ func rthg(machin: Bool) -> Void { } -func qewrffasddd(machin: Bool) -> Void { - var x : Int; - - if (machin) { - x = 0; // init - } else { - x = 1; // init - } - - if (machin) { - x = 0; // set - } else { - x = 1; // set - } - x = x + 1; // set - // OK - io::printLine(x); -} - -func qewrffasddd() -> Void { - var result: String = ""; - result.data = allocate(1); - // OK - result.data[0]; -} - -func <(lhs: Char, rhs: Char) -> Bool { - return (lhs as UInt8) < (rhs as UInt8); -} - -public func stringToInt(s: String) -> Int { - var i: Int = 0; - var result: Int = 0; - - // Skip leading whitespace - while (i < s.length) { - i = i + 1; - } - - // OK - return result; -} +// func qewrffasddd(machin: Bool) -> Void { +// var x : Int; + +// if (machin) { +// x = 0; // init +// } else { +// x = 1; // init +// } + +// if (machin) { +// x = 0; // set +// } else { +// x = 1; // set +// } +// x = x + 1; // set +// // OK +// io::printLine(x); +// } + +// func qewrffasddd() -> Void { +// var result: String = ""; +// result.data = allocate(1); +// // OK +// result.data[0]; +// } + +// func <(lhs: Char, rhs: Char) -> Bool { +// return (lhs as UInt8) < (rhs as UInt8); +// } + +// public func stringToInt(s: String) -> Int { +// var i: Int = 0; +// var result: Int = 0; + +// // Skip leading whitespace +// while (i < s.length) { +// i = i + 1; +// } + +// // OK +// return result; +// } + +// func asd(s: String) -> Void { +// s.data[0]; +// } From a86644d80e1ca92058995f1536d70c8854e7de2a Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Thu, 6 Nov 2025 18:27:34 +0100 Subject: [PATCH 03/24] fix: idk --- .../GILPasses/DetectUninitializedPass.cpp | 151 ++++++++++++----- test/functional/run/use_unitialized_var.glu | 160 +++++++++--------- 2 files changed, 192 insertions(+), 119 deletions(-) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index 890e73629..3e8ae0bb2 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -27,13 +27,22 @@ class DetectUninitializedPass llvm::DenseMap> predecessorMap; - enum class MemoryState { Uninitialized, Initialized }; + enum class MemoryState { Uninitialized, MaybeInitialized, Initialized }; llvm::DenseMap currentState; llvm::DenseMap> blockEndStates; + static MemoryState mergeMemoryStates(MemoryState lhs, MemoryState rhs) + { + if (lhs == rhs) { + return lhs; + } + + return MemoryState::MaybeInitialized; + } + void buildPredecessorMap(gil::Function *func) { predecessorMap.clear(); @@ -95,16 +104,30 @@ class DetectUninitializedPass gil::BasicBlock *bb, llvm::DenseMap &state ) { - // std::cout << " Analyzing basic block: " << bb->getLabel().str() - // << std::endl; + std::cout << " Analyzing basic block: " << bb->getLabel().str() + << std::endl; for (auto &inst : bb->getInstructions()) { if (auto *store = llvm::dyn_cast(&inst)) { gil::Value destPtr = store->getDest(); - state[destPtr] = MemoryState::Initialized; - std::cout - << " Found store - marking location as initialized" - << std::endl; + auto prevStateIt = state.find(destPtr); + MemoryState prevState = prevStateIt != state.end() + ? prevStateIt->second + : MemoryState::Uninitialized; + + MemoryState newState = MemoryState::Initialized; + if (prevState == MemoryState::MaybeInitialized) { + newState = MemoryState::MaybeInitialized; + } + + state[destPtr] = newState; + std::string stateStr = (newState == MemoryState::Initialized) + ? "initialized" + : (newState == MemoryState::MaybeInitialized + ? "maybe-initialized" + : "uninitialized"); + std::cout << " Found store - marking location as " + << stateStr << std::endl; } else if (auto *load = llvm::dyn_cast(&inst)) { gil::Value srcPtr = load->getValue(); std::cout @@ -112,7 +135,7 @@ class DetectUninitializedPass << std::endl; auto it = state.find(srcPtr); if (it == state.end() - || it->second == MemoryState::Uninitialized) { + || it->second != MemoryState::Initialized) { std::cout << " WARNING: Loading from potentially " "uninitialized location" << std::endl; @@ -127,12 +150,22 @@ class DetectUninitializedPass = llvm::dyn_cast(&inst)) { gil::Value basePtr = ptrOffsets->getBasePointer(); - state[ptrOffsets->getResult(0)] = state[basePtr]; + auto baseStateIt = state.find(basePtr); + MemoryState baseState = baseStateIt != state.end() + ? baseStateIt->second + : MemoryState::Uninitialized; + + state[ptrOffsets->getResult(0)] = baseState; } else if (auto *structFieldPtr = llvm::dyn_cast(&inst)) { gil::Value basePtr = structFieldPtr->getResult(0); - state[structFieldPtr->getResult(0)] = state[basePtr]; + auto baseStateIt = state.find(basePtr); + MemoryState baseState = baseStateIt != state.end() + ? baseStateIt->second + : MemoryState::Uninitialized; + + state[structFieldPtr->getResult(0)] = baseState; } } } @@ -169,7 +202,9 @@ class DetectUninitializedPass std::string stateStr = (entry.second == MemoryState::Initialized) ? "initialized" - : "uninitialized"; + : (entry.second == MemoryState::MaybeInitialized + ? "maybe-initialized" + : "uninitialized"); std::cout << " Memory location: " << stateStr << std::endl; } @@ -246,7 +281,7 @@ class DetectUninitializedPass currentState.clear(); } - // std::cout << "Starting state for this block:" << std::endl; + std::cout << "Starting state for this block:" << std::endl; for (auto const &entry : currentState) { printVariableState(entry.first, entry.second, " "); } @@ -256,6 +291,11 @@ class DetectUninitializedPass void afterVisitBasicBlock(gil::BasicBlock *bb) { blockEndStates[bb] = currentState; + std::cout << "Ending state for this block:" << std::endl; + for (auto const &entry : currentState) { + printVariableState(entry.first, entry.second, " "); + } + std::cout << "----------------------------------------\n" << std::endl; } void visitStoreInst(gil::StoreInst *store) @@ -269,19 +309,31 @@ class DetectUninitializedPass std::cout << "Found store instruction to memory location:" << std::endl; + MemoryState newState = MemoryState::Initialized; + if (prevState == MemoryState::Uninitialized) { store->setOwnershipKind(gil::StoreOwnershipKind::Init); std::cout << " Setting ownership to Init (location was uninitialized)" << std::endl; - } else { + } else if (prevState == MemoryState::Initialized) { store->setOwnershipKind(gil::StoreOwnershipKind::Set); std::cout << " Setting ownership to Set (location was initialized)" << std::endl; + } else { + store->setOwnershipKind(gil::StoreOwnershipKind::Set); + std::cout + << " Setting ownership to Set (location state is uncertain)" + << std::endl; + newState = MemoryState::MaybeInitialized; } - currentState[destPtr] = MemoryState::Initialized; - std::cout << " Location is now initialized" << std::endl; + currentState[destPtr] = newState; + if (newState == MemoryState::Initialized) { + std::cout << " Location is now initialized" << std::endl; + } else { + std::cout << " Location remains maybe-initialized" << std::endl; + } } void visitLoadInst(gil::LoadInst *load) @@ -303,7 +355,7 @@ class DetectUninitializedPass << srcPtr.getIndex() << "):" << std::endl; } - if (state == MemoryState::Uninitialized) { + if (state != MemoryState::Initialized) { std::cout << " ERROR: Load from uninitialized memory location" << std::endl; // show error with diagnostic manager @@ -340,22 +392,43 @@ class DetectUninitializedPass ) { std::string stateStr - = (state == MemoryState::Initialized ? "INITIALIZED" - : "UNINITIALIZED"); + = (state == MemoryState::Initialized + ? "INITIALIZED" + : (state == MemoryState::MaybeInitialized + ? "MAYBE_INITIALIZED" + : "UNINITIALIZED")); if (auto *defInst = ptr.getDefiningInstruction()) { // It's a result of an instruction - try to identify what it is + auto *parentBlock = defInst->getParent(); + std::string blockLabel + = parentBlock ? parentBlock->getLabel().str() : ""; + void const *instAddr = static_cast(defInst); + if (llvm::isa(defInst)) { - std::cout << indent << "%" << ptr.getIndex() - << " (alloca): " << stateStr << std::endl; + std::cout << indent << "%" << ptr.getIndex() << " (alloca" + << ", block=" << blockLabel << ", inst=" << instAddr + << "): " << stateStr << std::endl; } else { + llvm::StringRef instName = defInst->getInstName(); std::cout << indent << "%" << ptr.getIndex() - << " (instruction result): " << stateStr << std::endl; + << " (instruction result" + << ", block=" << blockLabel << ", inst=" << instAddr; + if (!instName.empty()) { + std::cout << ", name=" << instName.str(); + } + std::cout << "): " << stateStr << std::endl; } } else { // It's a block argument (function parameter) + auto *defBlock = ptr.getDefiningBlock(); + std::string blockLabel + = defBlock ? defBlock->getLabel().str() : ""; std::cout << indent << "%" << ptr.getIndex() - << " (function parameter): " << stateStr << std::endl; + << " (function parameter" + << ", block=" << blockLabel + << ", blockPtr=" << static_cast(defBlock) + << "): " << stateStr << std::endl; } } @@ -368,7 +441,6 @@ class DetectUninitializedPass return; } - bool first = true; llvm::DenseSet allValues; // Collect all values from all predecessors first @@ -386,9 +458,9 @@ class DetectUninitializedPass // For each value, check consistency across all predecessors for (gil::Value value : allValues) { - bool isConsistent = true; - MemoryState consensusState = MemoryState::Uninitialized; bool hasAnyState = false; + bool missingInPred = false; + MemoryState mergedState = MemoryState::Uninitialized; for (auto *pred : preds) { auto predIt = blockEndStates.find(pred); @@ -396,29 +468,30 @@ class DetectUninitializedPass auto valueIt = predIt->second.find(value); if (valueIt != predIt->second.end()) { if (!hasAnyState) { - consensusState = valueIt->second; + mergedState = valueIt->second; hasAnyState = true; - } else if (consensusState != valueIt->second) { - isConsistent = false; - break; + } else { + mergedState = mergeMemoryStates( + mergedState, valueIt->second + ); } } else { - // Value not found in this predecessor - if (hasAnyState - && consensusState != MemoryState::Uninitialized) { - isConsistent = false; - break; - } + missingInPred = true; } + } else { + missingInPred = true; } } - if (!isConsistent) { - // Inconsistent state across predecessors - mark as - // uninitialized + if (!hasAnyState) { currentState[value] = MemoryState::Uninitialized; } else { - currentState[value] = consensusState; + if (missingInPred) { + mergedState = mergeMemoryStates( + mergedState, MemoryState::Uninitialized + ); + } + currentState[value] = mergedState; } } } diff --git a/test/functional/run/use_unitialized_var.glu b/test/functional/run/use_unitialized_var.glu index 27606aa1d..6aec8a186 100644 --- a/test/functional/run/use_unitialized_var.glu +++ b/test/functional/run/use_unitialized_var.glu @@ -5,40 +5,40 @@ import allocation::allocate; import io; -// func rfeergerg(machin: Bool) -> Void { -// var x : Int; - -// if (machin) { -// x = 0; -// } -// // CHECK: warning: Load from uninitialized memory location -// io::printLine(x); -// } - -// func ergfer(machin: Bool) -> Void { -// var x : Int; - -// if (machin) { -// x = 0; -// } else { -// x = 1; -// } -// // OK -// io::printLine(x); -// } - -// func qewrff(machin: Bool) -> Void { -// var x : Int; - -// if (machin) { -// x = 0; // init -// } else { -// x = 1; // init -// } -// x = x + 1; // set -// // OK -// io::printLine(x); -// } +func rfeergerg(machin: Bool) -> Void { + var x : Int; + + if (machin) { + x = 0; + } + // CHECK: warning: Load from uninitialized memory location + io::printLine(x); +} + +func ergfer(machin: Bool) -> Void { + var x : Int; + + if (machin) { + x = 0; + } else { + x = 1; + } + // OK + io::printLine(x); +} + +func qewrff(machin: Bool) -> Void { + var x : Int; + + if (machin) { + x = 0; // init + } else { + x = 1; // init + } + x = x + 1; // set + // OK + io::printLine(x); +} func rthg(machin: Bool) -> Void { @@ -53,49 +53,49 @@ func rthg(machin: Bool) -> Void { } -// func qewrffasddd(machin: Bool) -> Void { -// var x : Int; - -// if (machin) { -// x = 0; // init -// } else { -// x = 1; // init -// } - -// if (machin) { -// x = 0; // set -// } else { -// x = 1; // set -// } -// x = x + 1; // set -// // OK -// io::printLine(x); -// } - -// func qewrffasddd() -> Void { -// var result: String = ""; -// result.data = allocate(1); -// // OK -// result.data[0]; -// } - -// func <(lhs: Char, rhs: Char) -> Bool { -// return (lhs as UInt8) < (rhs as UInt8); -// } - -// public func stringToInt(s: String) -> Int { -// var i: Int = 0; -// var result: Int = 0; - -// // Skip leading whitespace -// while (i < s.length) { -// i = i + 1; -// } - -// // OK -// return result; -// } - -// func asd(s: String) -> Void { -// s.data[0]; -// } +func qewrffasddd(machin: Bool) -> Void { + var x : Int; + + if (machin) { + x = 0; // init + } else { + x = 1; // init + } + + if (machin) { + x = 0; // set + } else { + x = 1; // set + } + x = x + 1; // set + // OK + io::printLine(x); +} + +func qewrffasddd() -> Void { + var result: String = ""; + result.data = allocate(1); + // OK + result.data[0]; +} + +func <(lhs: Char, rhs: Char) -> Bool { + return (lhs as UInt8) < (rhs as UInt8); +} + +public func stringToInt(s: String) -> Int { + var i: Int = 0; + var result: Int = 0; + + // Skip leading whitespace + while (i < s.length) { + i = i + 1; + } + + // OK + return result; +} + +func asd(s: String) -> Void { + s.data[0]; +} From 6ca6e37b5e6ec3698b5443d2915b1fa08d867244 Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Thu, 6 Nov 2025 19:54:41 +0100 Subject: [PATCH 04/24] chore: fk every tests works --- .../GILPasses/DetectUninitializedPass.cpp | 75 +++++++++---------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index 3e8ae0bb2..a372c677f 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -115,19 +115,10 @@ class DetectUninitializedPass ? prevStateIt->second : MemoryState::Uninitialized; - MemoryState newState = MemoryState::Initialized; - if (prevState == MemoryState::MaybeInitialized) { - newState = MemoryState::MaybeInitialized; - } - - state[destPtr] = newState; - std::string stateStr = (newState == MemoryState::Initialized) - ? "initialized" - : (newState == MemoryState::MaybeInitialized - ? "maybe-initialized" - : "uninitialized"); - std::cout << " Found store - marking location as " - << stateStr << std::endl; + state[destPtr] = MemoryState::Initialized; + std::cout + << " Found store - marking location as initialized" + << std::endl; } else if (auto *load = llvm::dyn_cast(&inst)) { gil::Value srcPtr = load->getValue(); std::cout @@ -309,31 +300,38 @@ class DetectUninitializedPass std::cout << "Found store instruction to memory location:" << std::endl; - MemoryState newState = MemoryState::Initialized; + bool warnOnUncertainSet = (prevState == MemoryState::MaybeInitialized); if (prevState == MemoryState::Uninitialized) { store->setOwnershipKind(gil::StoreOwnershipKind::Init); std::cout << " Setting ownership to Init (location was uninitialized)" << std::endl; - } else if (prevState == MemoryState::Initialized) { - store->setOwnershipKind(gil::StoreOwnershipKind::Set); - std::cout << " Setting ownership to Set (location was initialized)" - << std::endl; } else { store->setOwnershipKind(gil::StoreOwnershipKind::Set); - std::cout - << " Setting ownership to Set (location state is uncertain)" - << std::endl; - newState = MemoryState::MaybeInitialized; + if (prevState == MemoryState::Initialized) { + std::cout + << " Setting ownership to Set (location was initialized)" + << std::endl; + } else { + std::cout << " Setting ownership to Set (location state is " + "uncertain)" + << std::endl; + } } - currentState[destPtr] = newState; - if (newState == MemoryState::Initialized) { - std::cout << " Location is now initialized" << std::endl; - } else { - std::cout << " Location remains maybe-initialized" << std::endl; + if (warnOnUncertainSet) { + std::cout << " ERROR: Store performed as Set but prior state is " + "only maybe-initialized" + << std::endl; + diagManager.warning( + store->getLocation(), + "Store to memory location with uncertain initialization" + ); } + + currentState[destPtr] = MemoryState::Initialized; + std::cout << " Location is now initialized" << std::endl; } void visitLoadInst(gil::LoadInst *load) @@ -464,19 +462,18 @@ class DetectUninitializedPass for (auto *pred : preds) { auto predIt = blockEndStates.find(pred); - if (predIt != blockEndStates.end()) { - auto valueIt = predIt->second.find(value); - if (valueIt != predIt->second.end()) { - if (!hasAnyState) { - mergedState = valueIt->second; - hasAnyState = true; - } else { - mergedState = mergeMemoryStates( - mergedState, valueIt->second - ); - } + if (predIt == blockEndStates.end()) { + continue; // No information from this predecessor yet + } + + auto valueIt = predIt->second.find(value); + if (valueIt != predIt->second.end()) { + if (!hasAnyState) { + mergedState = valueIt->second; + hasAnyState = true; } else { - missingInPred = true; + mergedState + = mergeMemoryStates(mergedState, valueIt->second); } } else { missingInPred = true; From 2e1f7b837536052bd94615a9812be07ad57a528a Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Thu, 6 Nov 2025 20:34:17 +0100 Subject: [PATCH 05/24] fix: err in while --- .../GILPasses/DetectUninitializedPass.cpp | 64 +++++++++++++++++++ test/functional/run/use_unitialized_var.glu | 12 ++++ 2 files changed, 76 insertions(+) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index a372c677f..d87a58c40 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -384,6 +384,57 @@ class DetectUninitializedPass } } + void visitPtrOffsetInst(gil::PtrOffsetInst *inst) + { + if (inst->getResultCount() == 0) { + return; + } + + gil::Value basePtr = inst->getBasePointer(); + MemoryState baseState = getTrackedStateOrDefault( + basePtr, currentState, MemoryState::Uninitialized + ); + + gil::Value resultPtr = inst->getResult(0); + currentState[resultPtr] = baseState; + + std::cout << "Found ptr_offset - propagating state from base pointer" + << std::endl; + } + + void visitStructFieldPtrInst(gil::StructFieldPtrInst *inst) + { + if (inst->getResultCount() == 0) { + return; + } + + gil::Value basePtr = inst->getStructValue(); + MemoryState baseState = getTrackedStateOrDefault( + basePtr, currentState, MemoryState::Uninitialized + ); + + gil::Value resultPtr = inst->getResult(0); + currentState[resultPtr] = baseState; + + std::cout + << "Found struct_field_ptr - propagating state from base struct" + << std::endl; + } + + void visitStructExtractInst(gil::StructExtractInst *inst) + { + if (inst->getResultCount() == 0) { + return; + } + + gil::Value fieldValue = inst->getResult(0); + currentState[fieldValue] = MemoryState::Initialized; + + std::cout << "Found struct_extract - marking extracted value as" + " initialized" + << std::endl; + } + private: void printVariableState( gil::Value ptr, MemoryState state, std::string const &indent @@ -430,6 +481,19 @@ class DetectUninitializedPass } } + static MemoryState getTrackedStateOrDefault( + gil::Value value, + llvm::DenseMap const &stateMap, + MemoryState defaultState + ) + { + auto it = stateMap.find(value); + if (it != stateMap.end()) { + return it->second; + } + return defaultState; + } + void mergeStatesFromPredecessors(gil::BasicBlock *bb) { auto preds = getPredecessors(bb); diff --git a/test/functional/run/use_unitialized_var.glu b/test/functional/run/use_unitialized_var.glu index 6aec8a186..c10608d12 100644 --- a/test/functional/run/use_unitialized_var.glu +++ b/test/functional/run/use_unitialized_var.glu @@ -2,6 +2,9 @@ // RUN: gluc %s -c -o %t 2>&1 | FileCheck -v %s // +@no_mangling +func memcmp(s1: *Char, s2: *Char, n: Int) -> Int; + import allocation::allocate; import io; @@ -99,3 +102,12 @@ public func stringToInt(s: String) -> Int { func asd(s: String) -> Void { s.data[0]; } + +public func stringIndexOf(i: Int, s: String) -> Int { + + while (i <= s.length) { + s.data[i]; + } + + return -1; +} From b48b8884460dd4290923523af813b22ddc125651 Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Thu, 6 Nov 2025 20:44:24 +0100 Subject: [PATCH 06/24] fix: err in multile condition in while --- .../GILPasses/DetectUninitializedPass.cpp | 8 - test/functional/run/use_unitialized_var.glu | 246 ++++++++++-------- 2 files changed, 144 insertions(+), 110 deletions(-) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index d87a58c40..4cf10b5a1 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -521,7 +521,6 @@ class DetectUninitializedPass // For each value, check consistency across all predecessors for (gil::Value value : allValues) { bool hasAnyState = false; - bool missingInPred = false; MemoryState mergedState = MemoryState::Uninitialized; for (auto *pred : preds) { @@ -539,19 +538,12 @@ class DetectUninitializedPass mergedState = mergeMemoryStates(mergedState, valueIt->second); } - } else { - missingInPred = true; } } if (!hasAnyState) { currentState[value] = MemoryState::Uninitialized; } else { - if (missingInPred) { - mergedState = mergeMemoryStates( - mergedState, MemoryState::Uninitialized - ); - } currentState[value] = mergedState; } } diff --git a/test/functional/run/use_unitialized_var.glu b/test/functional/run/use_unitialized_var.glu index c10608d12..6a898c4f6 100644 --- a/test/functional/run/use_unitialized_var.glu +++ b/test/functional/run/use_unitialized_var.glu @@ -5,109 +5,151 @@ @no_mangling func memcmp(s1: *Char, s2: *Char, n: Int) -> Int; +@no_mangling +func memcpy(dst: *Char, src: *Char, n: Int) -> *Char; + import allocation::allocate; import io; -func rfeergerg(machin: Bool) -> Void { - var x : Int; - - if (machin) { - x = 0; - } - // CHECK: warning: Load from uninitialized memory location - io::printLine(x); -} - -func ergfer(machin: Bool) -> Void { - var x : Int; - - if (machin) { - x = 0; - } else { - x = 1; - } - // OK - io::printLine(x); -} - -func qewrff(machin: Bool) -> Void { - var x : Int; - - if (machin) { - x = 0; // init - } else { - x = 1; // init - } - x = x + 1; // set - // OK - io::printLine(x); -} - - -func rthg(machin: Bool) -> Void { - var x : Int; - - if (machin) { - x = 0; // init - } - x = 1; // don't know if init or check - // CHECK: warning: Load from uninitialized memory location - io::printLine(x); -} - - -func qewrffasddd(machin: Bool) -> Void { - var x : Int; - - if (machin) { - x = 0; // init - } else { - x = 1; // init - } - - if (machin) { - x = 0; // set - } else { - x = 1; // set - } - x = x + 1; // set - // OK - io::printLine(x); -} - -func qewrffasddd() -> Void { - var result: String = ""; - result.data = allocate(1); - // OK - result.data[0]; -} - -func <(lhs: Char, rhs: Char) -> Bool { - return (lhs as UInt8) < (rhs as UInt8); -} - -public func stringToInt(s: String) -> Int { - var i: Int = 0; - var result: Int = 0; - - // Skip leading whitespace - while (i < s.length) { - i = i + 1; - } - - // OK - return result; -} - -func asd(s: String) -> Void { - s.data[0]; -} - -public func stringIndexOf(i: Int, s: String) -> Int { - - while (i <= s.length) { - s.data[i]; - } - - return -1; +// func rfeergerg(machin: Bool) -> Void { +// var x : Int; + +// if (machin) { +// x = 0; +// } +// // CHECK: warning: Load from uninitialized memory location +// io::printLine(x); +// } + +// func ergfer(machin: Bool) -> Void { +// var x : Int; + +// if (machin) { +// x = 0; +// } else { +// x = 1; +// } +// // OK +// io::printLine(x); +// } + +// func qewrff(machin: Bool) -> Void { +// var x : Int; + +// if (machin) { +// x = 0; // init +// } else { +// x = 1; // init +// } +// x = x + 1; // set +// // OK +// io::printLine(x); +// } + + +// func rthg(machin: Bool) -> Void { +// var x : Int; + +// if (machin) { +// x = 0; // init +// } +// x = 1; // don't know if init or check +// // CHECK: warning: Load from uninitialized memory location +// io::printLine(x); +// } + + +// func qewrffasddd(machin: Bool) -> Void { +// var x : Int; + +// if (machin) { +// x = 0; // init +// } else { +// x = 1; // init +// } + +// if (machin) { +// x = 0; // set +// } else { +// x = 1; // set +// } +// x = x + 1; // set +// // OK +// io::printLine(x); +// } + +// func qewrffasddd() -> Void { +// var result: String = ""; +// result.data = allocate(1); +// // OK +// result.data[0]; +// } + +// func <(lhs: Char, rhs: Char) -> Bool { +// return (lhs as UInt8) < (rhs as UInt8); +// } + +// public func stringToInt(s: String) -> Int { +// var i: Int = 0; +// var result: Int = 0; + +// // Skip leading whitespace +// while (i < s.length) { +// i = i + 1; +// } + +// // OK +// return result; +// } + +// func asd(s: String) -> Void { +// s.data[0]; +// } + +// public func stringIndexOf(i: Int, s: String) -> Int { + +// while (i <= s.length) { +// s.data[i]; +// } + +// return -1; +// } + +// func createStringFromPointer(s: *Char, length: Int, allocated: Bool) -> String { +// return { s, length, allocated }; +// } + +// public func stringTrim(s: String) -> String { +// if (s.length == 0) { +// return s; +// } + +// var start: Int = 0; +// var end: Int = s.length - 1; + +// // Find first non-space character +// while (start <= end && (s.data[start] == " " || s.data[start] == "\n" || s.data[start] == "\t")) { +// start = start + 1; +// } + +// // Find last non-space character +// while (end >= start && (s.data[end] == " " || s.data[end] == "\n" || s.data[end] == "\t")) { +// end = end - 1; +// } + +// // Create trimmed string +// let newLength: Int = end - start + 1; +// if (newLength <= 0) { +// return createStringFromPointer(null, 0, false); +// } + +// var str: *Char = allocate(newLength); +// memcpy(str, &s.data[start], newLength); +// return createStringFromPointer(str, newLength, true); +// } + +public func +(lhs: String, rhs: String) -> Void { + var result: *Char = allocate(lhs.length + rhs.length + 1); + + memcpy(&result[lhs.length], rhs.data, rhs.length); } From 1fc674f8059dc93cb64c80b056e03b4aa6a6c9de Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Thu, 6 Nov 2025 21:24:57 +0100 Subject: [PATCH 07/24] chore: delete all print lines --- .../GILPasses/DetectUninitializedPass.cpp | 196 +++++++------ test/functional/run/use_unitialized_var.glu | 272 +++++++++--------- 2 files changed, 246 insertions(+), 222 deletions(-) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index 4cf10b5a1..d8b5b78cc 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -104,8 +104,8 @@ class DetectUninitializedPass gil::BasicBlock *bb, llvm::DenseMap &state ) { - std::cout << " Analyzing basic block: " << bb->getLabel().str() - << std::endl; + // std::cout << " Analyzing basic block: " << bb->getLabel().str() + // << std::endl; for (auto &inst : bb->getInstructions()) { if (auto *store = llvm::dyn_cast(&inst)) { @@ -116,27 +116,29 @@ class DetectUninitializedPass : MemoryState::Uninitialized; state[destPtr] = MemoryState::Initialized; - std::cout - << " Found store - marking location as initialized" - << std::endl; + // std::cout + // << " Found store - marking location as initialized" + // << std::endl; } else if (auto *load = llvm::dyn_cast(&inst)) { gil::Value srcPtr = load->getValue(); - std::cout - << " Found load - checking if location was initialized" - << std::endl; + // std::cout + // << " Found load - checking if location was + // initialized" + // << std::endl; auto it = state.find(srcPtr); if (it == state.end() || it->second != MemoryState::Initialized) { - std::cout << " WARNING: Loading from potentially " - "uninitialized location" - << std::endl; + // std::cout << " WARNING: Loading from potentially " + // "uninitialized location" + // << std::endl; } } else if (auto *alloca = llvm::dyn_cast(&inst)) { gil::Value allocatedPtr = alloca->getResult(0); state[allocatedPtr] = MemoryState::Uninitialized; - std::cout - << " Found alloca - marking location as uninitialized" - << std::endl; + // std::cout + // << " Found alloca - marking location as + // uninitialized" + // << std::endl; } else if (auto *ptrOffsets = llvm::dyn_cast(&inst)) { gil::Value basePtr = ptrOffsets->getBasePointer(); @@ -164,18 +166,20 @@ class DetectUninitializedPass void traversePredecessorsForState(gil::BasicBlock *bb) { auto preds = getPredecessors(bb); - std::cout << " Traversing predecessors to check initialization state:" - << std::endl; + // std::cout << " Traversing predecessors to check initialization + // state:" + // << std::endl; if (preds.empty()) { - std::cout << " Entry block - all values start uninitialized" - << std::endl; + // std::cout << " Entry block - all values start uninitialized" + // << std::endl; return; } for (auto *pred : preds) { - std::cout << " Checking predecessor: " << pred->getLabel().str() - << std::endl; + // std::cout << " Checking predecessor: " << + // pred->getLabel().str() + // << std::endl; auto predIt = blockEndStates.find(pred); if (predIt == blockEndStates.end()) { @@ -186,8 +190,9 @@ class DetectUninitializedPass } auto const &predState = predIt->second; - std::cout << " Predecessor state contains " << predState.size() - << " memory locations" << std::endl; + // std::cout << " Predecessor state contains " << + // predState.size() + // << " memory locations" << std::endl; for (auto const &entry : predState) { std::string stateStr @@ -196,8 +201,8 @@ class DetectUninitializedPass : (entry.second == MemoryState::MaybeInitialized ? "maybe-initialized" : "uninitialized"); - std::cout << " Memory location: " << stateStr - << std::endl; + // std::cout << " Memory location: " << stateStr + // << std::endl; } } } @@ -223,7 +228,8 @@ class DetectUninitializedPass changed = false; iteration++; - std::cout << "\n=== ITERATION " << iteration << " ===" << std::endl; + // std::cout << "\n=== ITERATION " << iteration << " ===" << + // std::endl; for (auto &bb : func->getBasicBlocks()) { // Save the old state for this block @@ -240,8 +246,8 @@ class DetectUninitializedPass // Check if the end state for this block changed if (blockEndStates[&bb] != oldState) { changed = true; - std::cout << "Block " << bb.getLabel().str() - << " state changed" << std::endl; + // std::cout << "Block " << bb.getLabel().str() + // << " state changed" << std::endl; } // Update the end state for this block @@ -250,17 +256,18 @@ class DetectUninitializedPass } if (iteration >= 100) { - std::cout << "WARNING: Fixed-point iteration did not converge!" - << std::endl; + // std::cout << "WARNING: Fixed-point iteration did not converge!" + // << std::endl; } } void beforeVisitBasicBlock(gil::BasicBlock *bb) { - std::cout << "\n========================================" << std::endl; - std::cout << "FINAL VISIT BASIC BLOCK: " << bb->getLabel().str() - << std::endl; - std::cout << "========================================" << std::endl; + // std::cout << "\n========================================" << + // std::endl; std::cout << "FINAL VISIT BASIC BLOCK: " << + // bb->getLabel().str() + // << std::endl; + // std::cout << "========================================" << std::endl; // Use the pre-computed state from fixed-point iteration auto it = blockEndStates.find(bb); @@ -272,21 +279,23 @@ class DetectUninitializedPass currentState.clear(); } - std::cout << "Starting state for this block:" << std::endl; + // std::cout << "Starting state for this block:" << std::endl; for (auto const &entry : currentState) { printVariableState(entry.first, entry.second, " "); } - std::cout << "----------------------------------------\n" << std::endl; + // std::cout << "----------------------------------------\n" << + // std::endl; } void afterVisitBasicBlock(gil::BasicBlock *bb) { blockEndStates[bb] = currentState; - std::cout << "Ending state for this block:" << std::endl; + // std::cout << "Ending state for this block:" << std::endl; for (auto const &entry : currentState) { printVariableState(entry.first, entry.second, " "); } - std::cout << "----------------------------------------\n" << std::endl; + // std::cout << "----------------------------------------\n" << + // std::endl; } void visitStoreInst(gil::StoreInst *store) @@ -298,32 +307,35 @@ class DetectUninitializedPass ? it->second : MemoryState::Uninitialized; - std::cout << "Found store instruction to memory location:" << std::endl; + // std::cout << "Found store instruction to memory location:" << + // std::endl; bool warnOnUncertainSet = (prevState == MemoryState::MaybeInitialized); if (prevState == MemoryState::Uninitialized) { store->setOwnershipKind(gil::StoreOwnershipKind::Init); - std::cout - << " Setting ownership to Init (location was uninitialized)" - << std::endl; + // std::cout + // << " Setting ownership to Init (location was uninitialized)" + // << std::endl; } else { store->setOwnershipKind(gil::StoreOwnershipKind::Set); if (prevState == MemoryState::Initialized) { - std::cout - << " Setting ownership to Set (location was initialized)" - << std::endl; + // std::cout + // << " Setting ownership to Set (location was + // initialized)" + // << std::endl; } else { - std::cout << " Setting ownership to Set (location state is " - "uncertain)" - << std::endl; + // std::cout << " Setting ownership to Set (location state is " + // "uncertain)" + // << std::endl; } } if (warnOnUncertainSet) { - std::cout << " ERROR: Store performed as Set but prior state is " - "only maybe-initialized" - << std::endl; + // std::cout << " ERROR: Store performed as Set but prior state is + // " + // "only maybe-initialized" + // << std::endl; diagManager.warning( store->getLocation(), "Store to memory location with uncertain initialization" @@ -331,7 +343,7 @@ class DetectUninitializedPass } currentState[destPtr] = MemoryState::Initialized; - std::cout << " Location is now initialized" << std::endl; + // std::cout << " Location is now initialized" << std::endl; } void visitLoadInst(gil::LoadInst *load) @@ -346,30 +358,40 @@ class DetectUninitializedPass // Show which memory location we're loading from if (auto *defInst = srcPtr.getDefiningInstruction()) { - std::cout << "Found load from memory location (result " - << srcPtr.getIndex() << " of instruction):" << std::endl; + // std::cout << "Found load from memory location (result " + // << srcPtr.getIndex() << " of instruction):" << + // std::endl; } else { - std::cout << "Found load from memory location (block argument " - << srcPtr.getIndex() << "):" << std::endl; + // std::cout << "Found load from memory location (block argument " + // << srcPtr.getIndex() << "):" << std::endl; } if (state != MemoryState::Initialized) { - std::cout << " ERROR: Load from uninitialized memory location" - << std::endl; + // std::cout << " ERROR: Load from uninitialized memory location" + // << std::endl; // show error with diagnostic manager diagManager.warning( load->getLocation(), "Load from uninitialized memory location" ); } else { - std::cout << " OK: Load from initialized memory location" - << std::endl; + // std::cout << " OK: Load from initialized memory location" + // << std::endl; + } + + if (load->getResultCount() > 0) { + gil::Value loadedValue = load->getResult(0); + currentState[loadedValue] = state; + // std::cout + // << " Propagating memory state to load result value" + // << std::endl; } if (load->getOwnershipKind() == gil::LoadOwnershipKind::Take) { currentState[srcPtr] = MemoryState::Uninitialized; - std::cout << " Load is Take - marking location as uninitialized " - "after load" - << std::endl; + // std::cout << " Load is Take -- marking location as uninitialized + // " + // "after load" + // << std::endl; } } @@ -378,9 +400,9 @@ class DetectUninitializedPass if (alloca->getResultCount() > 0) { gil::Value allocatedPtr = alloca->getResult(0); currentState[allocatedPtr] = MemoryState::Uninitialized; - std::cout - << "Found alloca - marking new allocation as uninitialized" - << std::endl; + // std::cout + // << "Found alloca - marking new allocation as uninitialized" + // << std::endl; } } @@ -398,8 +420,8 @@ class DetectUninitializedPass gil::Value resultPtr = inst->getResult(0); currentState[resultPtr] = baseState; - std::cout << "Found ptr_offset - propagating state from base pointer" - << std::endl; + // std::cout << "Found ptr_offset - propagating state from base pointer" + // << std::endl; } void visitStructFieldPtrInst(gil::StructFieldPtrInst *inst) @@ -416,9 +438,9 @@ class DetectUninitializedPass gil::Value resultPtr = inst->getResult(0); currentState[resultPtr] = baseState; - std::cout - << "Found struct_field_ptr - propagating state from base struct" - << std::endl; + // std::cout + // << "Found struct_field_ptr - propagating state from base struct" + // << std::endl; } void visitStructExtractInst(gil::StructExtractInst *inst) @@ -430,9 +452,9 @@ class DetectUninitializedPass gil::Value fieldValue = inst->getResult(0); currentState[fieldValue] = MemoryState::Initialized; - std::cout << "Found struct_extract - marking extracted value as" - " initialized" - << std::endl; + // std::cout << "Found struct_extract - marking extracted value as" + // " initialized" + // << std::endl; } private: @@ -455,29 +477,31 @@ class DetectUninitializedPass void const *instAddr = static_cast(defInst); if (llvm::isa(defInst)) { - std::cout << indent << "%" << ptr.getIndex() << " (alloca" - << ", block=" << blockLabel << ", inst=" << instAddr - << "): " << stateStr << std::endl; + // std::cout << indent << "%" << ptr.getIndex() << " (alloca" + // << ", block=" << blockLabel << ", inst=" << + // instAddr + // << "): " << stateStr << std::endl; } else { llvm::StringRef instName = defInst->getInstName(); - std::cout << indent << "%" << ptr.getIndex() - << " (instruction result" - << ", block=" << blockLabel << ", inst=" << instAddr; + // std::cout << indent << "%" << ptr.getIndex() + // << " (instruction result" + // << ", block=" << blockLabel << ", inst=" << + // instAddr; if (!instName.empty()) { - std::cout << ", name=" << instName.str(); + // std::cout << ", name=" << instName.str(); } - std::cout << "): " << stateStr << std::endl; + // std::cout << "): " << stateStr << std::endl; } } else { // It's a block argument (function parameter) auto *defBlock = ptr.getDefiningBlock(); std::string blockLabel = defBlock ? defBlock->getLabel().str() : ""; - std::cout << indent << "%" << ptr.getIndex() - << " (function parameter" - << ", block=" << blockLabel - << ", blockPtr=" << static_cast(defBlock) - << "): " << stateStr << std::endl; + // std::cout << indent << "%" << ptr.getIndex() + // << " (function parameter" + // << ", block=" << blockLabel + // << ", blockPtr=" << static_cast(defBlock) + // << "): " << stateStr << std::endl; } } diff --git a/test/functional/run/use_unitialized_var.glu b/test/functional/run/use_unitialized_var.glu index 6a898c4f6..fb6ccd97f 100644 --- a/test/functional/run/use_unitialized_var.glu +++ b/test/functional/run/use_unitialized_var.glu @@ -11,142 +11,142 @@ func memcpy(dst: *Char, src: *Char, n: Int) -> *Char; import allocation::allocate; import io; -// func rfeergerg(machin: Bool) -> Void { -// var x : Int; - -// if (machin) { -// x = 0; -// } -// // CHECK: warning: Load from uninitialized memory location -// io::printLine(x); -// } - -// func ergfer(machin: Bool) -> Void { -// var x : Int; - -// if (machin) { -// x = 0; -// } else { -// x = 1; -// } -// // OK -// io::printLine(x); -// } - -// func qewrff(machin: Bool) -> Void { -// var x : Int; - -// if (machin) { -// x = 0; // init -// } else { -// x = 1; // init -// } -// x = x + 1; // set -// // OK -// io::printLine(x); -// } - - -// func rthg(machin: Bool) -> Void { -// var x : Int; - -// if (machin) { -// x = 0; // init -// } -// x = 1; // don't know if init or check -// // CHECK: warning: Load from uninitialized memory location -// io::printLine(x); -// } - - -// func qewrffasddd(machin: Bool) -> Void { -// var x : Int; - -// if (machin) { -// x = 0; // init -// } else { -// x = 1; // init -// } - -// if (machin) { -// x = 0; // set -// } else { -// x = 1; // set -// } -// x = x + 1; // set -// // OK -// io::printLine(x); -// } - -// func qewrffasddd() -> Void { -// var result: String = ""; -// result.data = allocate(1); -// // OK -// result.data[0]; -// } - -// func <(lhs: Char, rhs: Char) -> Bool { -// return (lhs as UInt8) < (rhs as UInt8); -// } - -// public func stringToInt(s: String) -> Int { -// var i: Int = 0; -// var result: Int = 0; - -// // Skip leading whitespace -// while (i < s.length) { -// i = i + 1; -// } - -// // OK -// return result; -// } - -// func asd(s: String) -> Void { -// s.data[0]; -// } - -// public func stringIndexOf(i: Int, s: String) -> Int { - -// while (i <= s.length) { -// s.data[i]; -// } - -// return -1; -// } - -// func createStringFromPointer(s: *Char, length: Int, allocated: Bool) -> String { -// return { s, length, allocated }; -// } - -// public func stringTrim(s: String) -> String { -// if (s.length == 0) { -// return s; -// } - -// var start: Int = 0; -// var end: Int = s.length - 1; - -// // Find first non-space character -// while (start <= end && (s.data[start] == " " || s.data[start] == "\n" || s.data[start] == "\t")) { -// start = start + 1; -// } - -// // Find last non-space character -// while (end >= start && (s.data[end] == " " || s.data[end] == "\n" || s.data[end] == "\t")) { -// end = end - 1; -// } - -// // Create trimmed string -// let newLength: Int = end - start + 1; -// if (newLength <= 0) { -// return createStringFromPointer(null, 0, false); -// } - -// var str: *Char = allocate(newLength); -// memcpy(str, &s.data[start], newLength); -// return createStringFromPointer(str, newLength, true); -// } +func rfeergerg(machin: Bool) -> Void { + var x : Int; + + if (machin) { + x = 0; + } + // CHECK: warning: Load from uninitialized memory location + io::printLine(x); +} + +func ergfer(machin: Bool) -> Void { + var x : Int; + + if (machin) { + x = 0; + } else { + x = 1; + } + // OK + io::printLine(x); +} + +func qewrff(machin: Bool) -> Void { + var x : Int; + + if (machin) { + x = 0; // init + } else { + x = 1; // init + } + x = x + 1; // set + // OK + io::printLine(x); +} + + +func rthg(machin: Bool) -> Void { + var x : Int; + + if (machin) { + x = 0; // init + } + x = 1; // don't know if init or check + // CHECK: warning: Load from uninitialized memory location + io::printLine(x); +} + + +func qewrffasddd(machin: Bool) -> Void { + var x : Int; + + if (machin) { + x = 0; // init + } else { + x = 1; // init + } + + if (machin) { + x = 0; // set + } else { + x = 1; // set + } + x = x + 1; // set + // OK + io::printLine(x); +} + +func qewrffasddd() -> Void { + var result: String = ""; + result.data = allocate(1); + // OK + result.data[0]; +} + +func <(lhs: Char, rhs: Char) -> Bool { + return (lhs as UInt8) < (rhs as UInt8); +} + +public func stringToInt(s: String) -> Int { + var i: Int = 0; + var result: Int = 0; + + // Skip leading whitespace + while (i < s.length) { + i = i + 1; + } + + // OK + return result; +} + +func asd(s: String) -> Void { + s.data[0]; +} + +public func stringIndexOf(i: Int, s: String) -> Int { + + while (i <= s.length) { + s.data[i]; + } + + return -1; +} + +func createStringFromPointer(s: *Char, length: Int, allocated: Bool) -> String { + return { s, length, allocated }; +} + +public func stringTrim(s: String) -> String { + if (s.length == 0) { + return s; + } + + var start: Int = 0; + var end: Int = s.length - 1; + + // Find first non-space character + while (start <= end && (s.data[start] == " " || s.data[start] == "\n" || s.data[start] == "\t")) { + start = start + 1; + } + + // Find last non-space character + while (end >= start && (s.data[end] == " " || s.data[end] == "\n" || s.data[end] == "\t")) { + end = end - 1; + } + + // Create trimmed string + let newLength: Int = end - start + 1; + if (newLength <= 0) { + return createStringFromPointer(null, 0, false); + } + + var str: *Char = allocate(newLength); + memcpy(str, &s.data[start], newLength); + return createStringFromPointer(str, newLength, true); +} public func +(lhs: String, rhs: String) -> Void { var result: *Char = allocate(lhs.length + rhs.length + 1); From 907b57627792b84e22651e874fe66cad808dc2d1 Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Thu, 6 Nov 2025 21:38:32 +0100 Subject: [PATCH 08/24] fix: createConstantString --- lib/Optimizer/GILPasses/DetectUninitializedPass.cpp | 10 +++++----- stdlib/defaultImports/stringType.glu | 8 +------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index d8b5b78cc..4880a7acc 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -582,11 +582,11 @@ class DetectUninitializedPass } }; -void PassManager::runGILDetectUninitializedPass() -{ - DetectUninitializedPass pass(_diagManager); - pass.visit(_module); -} +// void PassManager::runGILDetectUninitializedPass() +// { +// DetectUninitializedPass pass(_diagManager); +// pass.visit(_module); +// } } // namespace glu::optimizer diff --git a/stdlib/defaultImports/stringType.glu b/stdlib/defaultImports/stringType.glu index 0cad481c4..4b519946e 100644 --- a/stdlib/defaultImports/stringType.glu +++ b/stdlib/defaultImports/stringType.glu @@ -5,11 +5,5 @@ public struct String { } @inline @no_mangling public func glu_createConstantString(s: *Char, length: Int) -> String { - var str: String = ""; - - str.data = s; - str.length = length; - str.isAllocated = false; - - return str; + return {s, length, false}; } From 6b001579acbc5ee463282b94380d83ed8ce6e1a7 Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Thu, 6 Nov 2025 21:47:42 +0100 Subject: [PATCH 09/24] chore: change all comments --- .../GILPasses/DetectUninitializedPass.cpp | 169 +----------------- test/functional/run/use_unitialized_var.glu | 2 +- 2 files changed, 9 insertions(+), 162 deletions(-) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index 4880a7acc..4a4dd0884 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -104,9 +104,6 @@ class DetectUninitializedPass gil::BasicBlock *bb, llvm::DenseMap &state ) { - // std::cout << " Analyzing basic block: " << bb->getLabel().str() - // << std::endl; - for (auto &inst : bb->getInstructions()) { if (auto *store = llvm::dyn_cast(&inst)) { gil::Value destPtr = store->getDest(); @@ -116,29 +113,14 @@ class DetectUninitializedPass : MemoryState::Uninitialized; state[destPtr] = MemoryState::Initialized; - // std::cout - // << " Found store - marking location as initialized" - // << std::endl; } else if (auto *load = llvm::dyn_cast(&inst)) { gil::Value srcPtr = load->getValue(); - // std::cout - // << " Found load - checking if location was - // initialized" - // << std::endl; auto it = state.find(srcPtr); if (it == state.end() - || it->second != MemoryState::Initialized) { - // std::cout << " WARNING: Loading from potentially " - // "uninitialized location" - // << std::endl; - } + || it->second != MemoryState::Initialized) { } } else if (auto *alloca = llvm::dyn_cast(&inst)) { gil::Value allocatedPtr = alloca->getResult(0); state[allocatedPtr] = MemoryState::Uninitialized; - // std::cout - // << " Found alloca - marking location as - // uninitialized" - // << std::endl; } else if (auto *ptrOffsets = llvm::dyn_cast(&inst)) { gil::Value basePtr = ptrOffsets->getBasePointer(); @@ -166,20 +148,12 @@ class DetectUninitializedPass void traversePredecessorsForState(gil::BasicBlock *bb) { auto preds = getPredecessors(bb); - // std::cout << " Traversing predecessors to check initialization - // state:" - // << std::endl; if (preds.empty()) { - // std::cout << " Entry block - all values start uninitialized" - // << std::endl; return; } for (auto *pred : preds) { - // std::cout << " Checking predecessor: " << - // pred->getLabel().str() - // << std::endl; auto predIt = blockEndStates.find(pred); if (predIt == blockEndStates.end()) { @@ -190,9 +164,6 @@ class DetectUninitializedPass } auto const &predState = predIt->second; - // std::cout << " Predecessor state contains " << - // predState.size() - // << " memory locations" << std::endl; for (auto const &entry : predState) { std::string stateStr @@ -201,8 +172,6 @@ class DetectUninitializedPass : (entry.second == MemoryState::MaybeInitialized ? "maybe-initialized" : "uninitialized"); - // std::cout << " Memory location: " << stateStr - // << std::endl; } } } @@ -217,85 +186,53 @@ class DetectUninitializedPass { buildPredecessorMap(func); - // Initialize all block states to empty first blockEndStates.clear(); currentState.clear(); - // Perform fixed-point iteration until states stabilize bool changed = true; int iteration = 0; - while (changed && iteration < 100) { // Prevent infinite loops + while (changed && iteration < 100) { changed = false; iteration++; - // std::cout << "\n=== ITERATION " << iteration << " ===" << - // std::endl; - for (auto &bb : func->getBasicBlocks()) { - // Save the old state for this block auto oldState = blockEndStates.find(&bb) != blockEndStates.end() ? blockEndStates[&bb] : llvm::DenseMap {}; - // Merge states from predecessors mergeStatesFromPredecessors(&bb); - // Analyze this block with the merged state analyzeBasicBlockState(&bb, currentState); - // Check if the end state for this block changed if (blockEndStates[&bb] != oldState) { changed = true; - // std::cout << "Block " << bb.getLabel().str() - // << " state changed" << std::endl; } - // Update the end state for this block blockEndStates[&bb] = currentState; } } - - if (iteration >= 100) { - // std::cout << "WARNING: Fixed-point iteration did not converge!" - // << std::endl; - } } void beforeVisitBasicBlock(gil::BasicBlock *bb) { - // std::cout << "\n========================================" << - // std::endl; std::cout << "FINAL VISIT BASIC BLOCK: " << - // bb->getLabel().str() - // << std::endl; - // std::cout << "========================================" << std::endl; - - // Use the pre-computed state from fixed-point iteration auto it = blockEndStates.find(bb); if (it != blockEndStates.end()) { - // Start with the state at the beginning of this block mergeStatesFromPredecessors(bb); } else { - // Entry block case currentState.clear(); } - // std::cout << "Starting state for this block:" << std::endl; for (auto const &entry : currentState) { printVariableState(entry.first, entry.second, " "); } - // std::cout << "----------------------------------------\n" << - // std::endl; } void afterVisitBasicBlock(gil::BasicBlock *bb) { blockEndStates[bb] = currentState; - // std::cout << "Ending state for this block:" << std::endl; for (auto const &entry : currentState) { printVariableState(entry.first, entry.second, " "); } - // std::cout << "----------------------------------------\n" << - // std::endl; } void visitStoreInst(gil::StoreInst *store) @@ -307,35 +244,15 @@ class DetectUninitializedPass ? it->second : MemoryState::Uninitialized; - // std::cout << "Found store instruction to memory location:" << - // std::endl; - bool warnOnUncertainSet = (prevState == MemoryState::MaybeInitialized); if (prevState == MemoryState::Uninitialized) { store->setOwnershipKind(gil::StoreOwnershipKind::Init); - // std::cout - // << " Setting ownership to Init (location was uninitialized)" - // << std::endl; } else { store->setOwnershipKind(gil::StoreOwnershipKind::Set); - if (prevState == MemoryState::Initialized) { - // std::cout - // << " Setting ownership to Set (location was - // initialized)" - // << std::endl; - } else { - // std::cout << " Setting ownership to Set (location state is " - // "uncertain)" - // << std::endl; - } } if (warnOnUncertainSet) { - // std::cout << " ERROR: Store performed as Set but prior state is - // " - // "only maybe-initialized" - // << std::endl; diagManager.warning( store->getLocation(), "Store to memory location with uncertain initialization" @@ -343,7 +260,6 @@ class DetectUninitializedPass } currentState[destPtr] = MemoryState::Initialized; - // std::cout << " Location is now initialized" << std::endl; } void visitLoadInst(gil::LoadInst *load) @@ -356,42 +272,19 @@ class DetectUninitializedPass : MemoryState::Initialized; // Default to initialized for // unknown values - // Show which memory location we're loading from - if (auto *defInst = srcPtr.getDefiningInstruction()) { - // std::cout << "Found load from memory location (result " - // << srcPtr.getIndex() << " of instruction):" << - // std::endl; - } else { - // std::cout << "Found load from memory location (block argument " - // << srcPtr.getIndex() << "):" << std::endl; - } - if (state != MemoryState::Initialized) { - // std::cout << " ERROR: Load from uninitialized memory location" - // << std::endl; - // show error with diagnostic manager diagManager.warning( load->getLocation(), "Load from uninitialized memory location" ); - } else { - // std::cout << " OK: Load from initialized memory location" - // << std::endl; } if (load->getResultCount() > 0) { gil::Value loadedValue = load->getResult(0); currentState[loadedValue] = state; - // std::cout - // << " Propagating memory state to load result value" - // << std::endl; } if (load->getOwnershipKind() == gil::LoadOwnershipKind::Take) { currentState[srcPtr] = MemoryState::Uninitialized; - // std::cout << " Load is Take -- marking location as uninitialized - // " - // "after load" - // << std::endl; } } @@ -400,9 +293,6 @@ class DetectUninitializedPass if (alloca->getResultCount() > 0) { gil::Value allocatedPtr = alloca->getResult(0); currentState[allocatedPtr] = MemoryState::Uninitialized; - // std::cout - // << "Found alloca - marking new allocation as uninitialized" - // << std::endl; } } @@ -419,9 +309,6 @@ class DetectUninitializedPass gil::Value resultPtr = inst->getResult(0); currentState[resultPtr] = baseState; - - // std::cout << "Found ptr_offset - propagating state from base pointer" - // << std::endl; } void visitStructFieldPtrInst(gil::StructFieldPtrInst *inst) @@ -437,10 +324,6 @@ class DetectUninitializedPass gil::Value resultPtr = inst->getResult(0); currentState[resultPtr] = baseState; - - // std::cout - // << "Found struct_field_ptr - propagating state from base struct" - // << std::endl; } void visitStructExtractInst(gil::StructExtractInst *inst) @@ -451,10 +334,6 @@ class DetectUninitializedPass gil::Value fieldValue = inst->getResult(0); currentState[fieldValue] = MemoryState::Initialized; - - // std::cout << "Found struct_extract - marking extracted value as" - // " initialized" - // << std::endl; } private: @@ -470,38 +349,15 @@ class DetectUninitializedPass : "UNINITIALIZED")); if (auto *defInst = ptr.getDefiningInstruction()) { - // It's a result of an instruction - try to identify what it is auto *parentBlock = defInst->getParent(); std::string blockLabel = parentBlock ? parentBlock->getLabel().str() : ""; void const *instAddr = static_cast(defInst); - if (llvm::isa(defInst)) { - // std::cout << indent << "%" << ptr.getIndex() << " (alloca" - // << ", block=" << blockLabel << ", inst=" << - // instAddr - // << "): " << stateStr << std::endl; - } else { - llvm::StringRef instName = defInst->getInstName(); - // std::cout << indent << "%" << ptr.getIndex() - // << " (instruction result" - // << ", block=" << blockLabel << ", inst=" << - // instAddr; - if (!instName.empty()) { - // std::cout << ", name=" << instName.str(); - } - // std::cout << "): " << stateStr << std::endl; - } } else { - // It's a block argument (function parameter) auto *defBlock = ptr.getDefiningBlock(); std::string blockLabel = defBlock ? defBlock->getLabel().str() : ""; - // std::cout << indent << "%" << ptr.getIndex() - // << " (function parameter" - // << ", block=" << blockLabel - // << ", blockPtr=" << static_cast(defBlock) - // << "): " << stateStr << std::endl; } } @@ -522,14 +378,12 @@ class DetectUninitializedPass { auto preds = getPredecessors(bb); if (preds.empty()) { - // Entry block - start with empty state currentState.clear(); return; } llvm::DenseSet allValues; - // Collect all values from all predecessors first for (auto *pred : preds) { auto predIt = blockEndStates.find(pred); if (predIt != blockEndStates.end()) { @@ -539,10 +393,8 @@ class DetectUninitializedPass } } - // Initialize current state currentState.clear(); - // For each value, check consistency across all predecessors for (gil::Value value : allValues) { bool hasAnyState = false; MemoryState mergedState = MemoryState::Uninitialized; @@ -550,7 +402,7 @@ class DetectUninitializedPass for (auto *pred : preds) { auto predIt = blockEndStates.find(pred); if (predIt == blockEndStates.end()) { - continue; // No information from this predecessor yet + continue; } auto valueIt = predIt->second.find(value); @@ -582,15 +434,10 @@ class DetectUninitializedPass } }; -// void PassManager::runGILDetectUninitializedPass() -// { -// DetectUninitializedPass pass(_diagManager); -// pass.visit(_module); -// } +void PassManager::runGILDetectUninitializedPass() +{ + DetectUninitializedPass pass(_diagManager); + pass.visit(_module); +} } // namespace glu::optimizer - -// load take 면 그 다음에 uninitialzed -// 좋아 -// allias structFieldPtn은 -// ptr offset => operator [] diff --git a/test/functional/run/use_unitialized_var.glu b/test/functional/run/use_unitialized_var.glu index fb6ccd97f..17bea470a 100644 --- a/test/functional/run/use_unitialized_var.glu +++ b/test/functional/run/use_unitialized_var.glu @@ -53,8 +53,8 @@ func rthg(machin: Bool) -> Void { if (machin) { x = 0; // init } + // CHECK: warning: Store to memory location with uncertain initialization x = 1; // don't know if init or check - // CHECK: warning: Load from uninitialized memory location io::printLine(x); } From a51d68b508dfcb828c10ebcf306a97788a46e402 Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Thu, 6 Nov 2025 21:54:22 +0100 Subject: [PATCH 10/24] chore: delete comment in tests --- test/functional/run/use_unitialized_var.glu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/run/use_unitialized_var.glu b/test/functional/run/use_unitialized_var.glu index 17bea470a..75fb4140f 100644 --- a/test/functional/run/use_unitialized_var.glu +++ b/test/functional/run/use_unitialized_var.glu @@ -54,7 +54,7 @@ func rthg(machin: Bool) -> Void { x = 0; // init } // CHECK: warning: Store to memory location with uncertain initialization - x = 1; // don't know if init or check + x = 1; io::printLine(x); } From c32af0946bfdcf3ec8524e508d95b9262d63533a Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Fri, 7 Nov 2025 16:06:02 +0100 Subject: [PATCH 11/24] chore: change for that tests works --- .../GILPasses/DetectUninitializedPass.cpp | 11 ++++++++-- test/functional/run/use_unitialized_var.glu | 20 +++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index 4a4dd0884..90b56ce18 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -253,13 +253,20 @@ class DetectUninitializedPass } if (warnOnUncertainSet) { - diagManager.warning( + diagManager.error( store->getLocation(), "Store to memory location with uncertain initialization" ); } currentState[destPtr] = MemoryState::Initialized; + if (auto *structFieldPtr + = llvm::dyn_cast_or_null( + destPtr.getDefiningInstruction() + )) { + gil::Value baseStruct = structFieldPtr->getStructValue(); + currentState[baseStruct] = MemoryState::Initialized; + } } void visitLoadInst(gil::LoadInst *load) @@ -273,7 +280,7 @@ class DetectUninitializedPass // unknown values if (state != MemoryState::Initialized) { - diagManager.warning( + diagManager.error( load->getLocation(), "Load from uninitialized memory location" ); } diff --git a/test/functional/run/use_unitialized_var.glu b/test/functional/run/use_unitialized_var.glu index 75fb4140f..3c48421f6 100644 --- a/test/functional/run/use_unitialized_var.glu +++ b/test/functional/run/use_unitialized_var.glu @@ -1,5 +1,5 @@ // -// RUN: gluc %s -c -o %t 2>&1 | FileCheck -v %s +// RUN: not gluc %s -c -o %t 2>&1 | FileCheck -v %s // @no_mangling @@ -8,8 +8,8 @@ func memcmp(s1: *Char, s2: *Char, n: Int) -> Int; @no_mangling func memcpy(dst: *Char, src: *Char, n: Int) -> *Char; -import allocation::allocate; -import io; +import std::allocate; +import std::print; func rfeergerg(machin: Bool) -> Void { var x : Int; @@ -17,8 +17,8 @@ func rfeergerg(machin: Bool) -> Void { if (machin) { x = 0; } - // CHECK: warning: Load from uninitialized memory location - io::printLine(x); + // CHECK: use_unitialized_var.glu:21:11: error: Load from uninitialized memory location + print(x); } func ergfer(machin: Bool) -> Void { @@ -30,7 +30,7 @@ func ergfer(machin: Bool) -> Void { x = 1; } // OK - io::printLine(x); + print(x); } func qewrff(machin: Bool) -> Void { @@ -43,7 +43,7 @@ func qewrff(machin: Bool) -> Void { } x = x + 1; // set // OK - io::printLine(x); + print(x); } @@ -53,9 +53,9 @@ func rthg(machin: Bool) -> Void { if (machin) { x = 0; // init } - // CHECK: warning: Store to memory location with uncertain initialization + // CHECK: use_unitialized_var.glu:57:7: error: Store to memory location with uncertain initialization x = 1; - io::printLine(x); + print(x); } @@ -75,7 +75,7 @@ func qewrffasddd(machin: Bool) -> Void { } x = x + 1; // set // OK - io::printLine(x); + print(x); } func qewrffasddd() -> Void { From d0093425b59bcb13ec1c52013ba6d7e1b1e7a052 Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Fri, 7 Nov 2025 16:07:13 +0100 Subject: [PATCH 12/24] chore: detect-uninitialized not in lowering --- include/Optimizer/GILPasses.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Optimizer/GILPasses.def b/include/Optimizer/GILPasses.def index 056177667..c89653937 100644 --- a/include/Optimizer/GILPasses.def +++ b/include/Optimizer/GILPasses.def @@ -8,9 +8,9 @@ GIL_PASS("void-main", VoidMainPass) GIL_PASS("dce", DeadCodeEliminationPass) GIL_PASS("unreachable-checker", UnreachableInstChecker) +GIL_PASS("detect-uninitialized", GILDetectUninitializedPass) // Lowering passes -GIL_PASS("detect-uninitialized", GILDetectUninitializedPass) GIL_PASS("drop-lowering", DropLoweringPass) GIL_PASS("copy-lowering", CopyLoweringPass) From 4dda8ae2c2f8609c91b13875385bf54c7cce38fe Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Fri, 7 Nov 2025 16:21:44 +0100 Subject: [PATCH 13/24] chore: add some tests --- test/functional/run/use_unitialized_var.glu | 61 +++++++++++++-------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/test/functional/run/use_unitialized_var.glu b/test/functional/run/use_unitialized_var.glu index 3c48421f6..8846c41a7 100644 --- a/test/functional/run/use_unitialized_var.glu +++ b/test/functional/run/use_unitialized_var.glu @@ -119,37 +119,52 @@ func createStringFromPointer(s: *Char, length: Int, allocated: Bool) -> String { return { s, length, allocated }; } -public func stringTrim(s: String) -> String { - if (s.length == 0) { - return s; +func ddsdadasfasf(machin: Bool) -> Void { + var x : Int; + var y : Int = 0; + + if (machin) { + x = 0; } - var start: Int = 0; - var end: Int = s.length - 1; + while (machin) { + y = y + 1; - // Find first non-space character - while (start <= end && (s.data[start] == " " || s.data[start] == "\n" || s.data[start] == "\t")) { - start = start + 1; + if (y > 10) { + y = 10; + break; + } } + // CHECK: use_unitialized_var.glu:139:11: error: Load from uninitialized memory location + print(x); +} - // Find last non-space character - while (end >= start && (s.data[end] == " " || s.data[end] == "\n" || s.data[end] == "\t")) { - end = end - 1; - } +func ddsdadasdadasfasf(machin: Bool) -> Void { + var x : Int; + var y : Int = 0; + var z : Int; - // Create trimmed string - let newLength: Int = end - start + 1; - if (newLength <= 0) { - return createStringFromPointer(null, 0, false); + if (machin) { + x = 0; } - var str: *Char = allocate(newLength); - memcpy(str, &s.data[start], newLength); - return createStringFromPointer(str, newLength, true); -} + while (machin) { + y = y + 1; -public func +(lhs: String, rhs: String) -> Void { - var result: *Char = allocate(lhs.length + rhs.length + 1); + if (y > 10) { + y = 10; + break; + } + // CHECK: use_unitialized_var.glu:159:15: error: Load from uninitialized memory location + print(z); - memcpy(&result[lhs.length], rhs.data, rhs.length); + // CHECK: use_unitialized_var.glu:162:13: error: Load from uninitialized memory location + if (z == 1) { + z = 0; + } + } + // CHECK: use_unitialized_var.glu:167:11: error: Load from uninitialized memory location + print(x); + // CHECK: use_unitialized_var.glu:169:11: error: Load from uninitialized memory location + print(z); } From 5d4991dc7413b65575357aa0aa210696d76f25af Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Fri, 7 Nov 2025 17:04:42 +0100 Subject: [PATCH 14/24] chore: change some find to look up --- .../GILPasses/DetectUninitializedPass.cpp | 39 +++++-------------- 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index 90b56ce18..7401b4717 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -7,7 +7,6 @@ #include "GIL/Module.hpp" #include "PassManager.hpp" -#include #include #include #include @@ -107,11 +106,6 @@ class DetectUninitializedPass for (auto &inst : bb->getInstructions()) { if (auto *store = llvm::dyn_cast(&inst)) { gil::Value destPtr = store->getDest(); - auto prevStateIt = state.find(destPtr); - MemoryState prevState = prevStateIt != state.end() - ? prevStateIt->second - : MemoryState::Uninitialized; - state[destPtr] = MemoryState::Initialized; } else if (auto *load = llvm::dyn_cast(&inst)) { gil::Value srcPtr = load->getValue(); @@ -124,22 +118,12 @@ class DetectUninitializedPass } else if (auto *ptrOffsets = llvm::dyn_cast(&inst)) { gil::Value basePtr = ptrOffsets->getBasePointer(); - - auto baseStateIt = state.find(basePtr); - MemoryState baseState = baseStateIt != state.end() - ? baseStateIt->second - : MemoryState::Uninitialized; - + MemoryState baseState = state.lookup(basePtr); state[ptrOffsets->getResult(0)] = baseState; } else if (auto *structFieldPtr = llvm::dyn_cast(&inst)) { gil::Value basePtr = structFieldPtr->getResult(0); - - auto baseStateIt = state.find(basePtr); - MemoryState baseState = baseStateIt != state.end() - ? baseStateIt->second - : MemoryState::Uninitialized; - + MemoryState baseState = state.lookup(basePtr); state[structFieldPtr->getResult(0)] = baseState; } } @@ -196,9 +180,7 @@ class DetectUninitializedPass iteration++; for (auto &bb : func->getBasicBlocks()) { - auto oldState = blockEndStates.find(&bb) != blockEndStates.end() - ? blockEndStates[&bb] - : llvm::DenseMap {}; + auto oldState = blockEndStates.lookup(&bb); mergeStatesFromPredecessors(&bb); @@ -239,10 +221,7 @@ class DetectUninitializedPass { gil::Value destPtr = store->getDest(); - auto it = currentState.find(destPtr); - MemoryState prevState = (it != currentState.end()) - ? it->second - : MemoryState::Uninitialized; + MemoryState prevState = currentState.lookup(destPtr); bool warnOnUncertainSet = (prevState == MemoryState::MaybeInitialized); @@ -273,11 +252,11 @@ class DetectUninitializedPass { gil::Value srcPtr = load->getValue(); - auto it = currentState.find(srcPtr); - MemoryState state = (it != currentState.end()) - ? it->second - : MemoryState::Initialized; // Default to initialized for - // unknown values + MemoryState state = currentState.lookup(srcPtr); + if (!currentState.contains(srcPtr)) { + state = MemoryState::Initialized; // Default to initialized for + // unknown values + } if (state != MemoryState::Initialized) { diagManager.error( From adcc6e904e4378367c3fb68fb1790fb2086ad9b8 Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Fri, 7 Nov 2025 17:21:33 +0100 Subject: [PATCH 15/24] fix: copilot comments --- .../GILPasses/DetectUninitializedPass.cpp | 54 ++----------------- 1 file changed, 4 insertions(+), 50 deletions(-) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index 7401b4717..92448cc72 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -7,15 +7,13 @@ #include "GIL/Module.hpp" #include "PassManager.hpp" +#include "GIL/Instructions/BrInst.hpp" +#include "GIL/Instructions/CondBrInst.hpp" +#include #include #include #include -namespace glu::gil { -class BrInst; -class CondBrInst; -} - namespace glu::optimizer { class DetectUninitializedPass @@ -110,8 +108,6 @@ class DetectUninitializedPass } else if (auto *load = llvm::dyn_cast(&inst)) { gil::Value srcPtr = load->getValue(); auto it = state.find(srcPtr); - if (it == state.end() - || it->second != MemoryState::Initialized) { } } else if (auto *alloca = llvm::dyn_cast(&inst)) { gil::Value allocatedPtr = alloca->getResult(0); state[allocatedPtr] = MemoryState::Uninitialized; @@ -122,7 +118,7 @@ class DetectUninitializedPass state[ptrOffsets->getResult(0)] = baseState; } else if (auto *structFieldPtr = llvm::dyn_cast(&inst)) { - gil::Value basePtr = structFieldPtr->getResult(0); + gil::Value basePtr = structFieldPtr->getStructValue(); MemoryState baseState = state.lookup(basePtr); state[structFieldPtr->getResult(0)] = baseState; } @@ -146,17 +142,6 @@ class DetectUninitializedPass blockEndStates[pred] = predState; predIt = blockEndStates.find(pred); } - - auto const &predState = predIt->second; - - for (auto const &entry : predState) { - std::string stateStr - = (entry.second == MemoryState::Initialized) - ? "initialized" - : (entry.second == MemoryState::MaybeInitialized - ? "maybe-initialized" - : "uninitialized"); - } } } @@ -203,18 +188,11 @@ class DetectUninitializedPass } else { currentState.clear(); } - - for (auto const &entry : currentState) { - printVariableState(entry.first, entry.second, " "); - } } void afterVisitBasicBlock(gil::BasicBlock *bb) { blockEndStates[bb] = currentState; - for (auto const &entry : currentState) { - printVariableState(entry.first, entry.second, " "); - } } void visitStoreInst(gil::StoreInst *store) @@ -323,30 +301,6 @@ class DetectUninitializedPass } private: - void printVariableState( - gil::Value ptr, MemoryState state, std::string const &indent - ) - { - std::string stateStr - = (state == MemoryState::Initialized - ? "INITIALIZED" - : (state == MemoryState::MaybeInitialized - ? "MAYBE_INITIALIZED" - : "UNINITIALIZED")); - - if (auto *defInst = ptr.getDefiningInstruction()) { - auto *parentBlock = defInst->getParent(); - std::string blockLabel - = parentBlock ? parentBlock->getLabel().str() : ""; - void const *instAddr = static_cast(defInst); - - } else { - auto *defBlock = ptr.getDefiningBlock(); - std::string blockLabel - = defBlock ? defBlock->getLabel().str() : ""; - } - } - static MemoryState getTrackedStateOrDefault( gil::Value value, llvm::DenseMap const &stateMap, From 19efdc2403b22743a71fd72e35f108fe5c50bcd8 Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Fri, 7 Nov 2025 17:31:36 +0100 Subject: [PATCH 16/24] chore: delete unused include --- .../GILPasses/DetectUninitializedPass.cpp | 1 - ...itialized_var.glu => use_uninitialized_var.glu} | 14 +++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) rename test/functional/run/{use_unitialized_var.glu => use_uninitialized_var.glu} (77%) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index 92448cc72..8696e9438 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -9,7 +9,6 @@ #include "GIL/Instructions/BrInst.hpp" #include "GIL/Instructions/CondBrInst.hpp" -#include #include #include #include diff --git a/test/functional/run/use_unitialized_var.glu b/test/functional/run/use_uninitialized_var.glu similarity index 77% rename from test/functional/run/use_unitialized_var.glu rename to test/functional/run/use_uninitialized_var.glu index 8846c41a7..26beda632 100644 --- a/test/functional/run/use_unitialized_var.glu +++ b/test/functional/run/use_uninitialized_var.glu @@ -17,7 +17,7 @@ func rfeergerg(machin: Bool) -> Void { if (machin) { x = 0; } - // CHECK: use_unitialized_var.glu:21:11: error: Load from uninitialized memory location + // CHECK: use_uninitialized_var.glu:21:11: error: Load from uninitialized memory location print(x); } @@ -53,7 +53,7 @@ func rthg(machin: Bool) -> Void { if (machin) { x = 0; // init } - // CHECK: use_unitialized_var.glu:57:7: error: Store to memory location with uncertain initialization + // CHECK: use_uninitialized_var.glu:57:7: error: Store to memory location with uncertain initialization x = 1; print(x); } @@ -135,7 +135,7 @@ func ddsdadasfasf(machin: Bool) -> Void { break; } } - // CHECK: use_unitialized_var.glu:139:11: error: Load from uninitialized memory location + // CHECK: use_uninitialized_var.glu:139:11: error: Load from uninitialized memory location print(x); } @@ -155,16 +155,16 @@ func ddsdadasdadasfasf(machin: Bool) -> Void { y = 10; break; } - // CHECK: use_unitialized_var.glu:159:15: error: Load from uninitialized memory location + // CHECK: use_uninitialized_var.glu:159:15: error: Load from uninitialized memory location print(z); - // CHECK: use_unitialized_var.glu:162:13: error: Load from uninitialized memory location + // CHECK: use_uninitialized_var.glu:162:13: error: Load from uninitialized memory location if (z == 1) { z = 0; } } - // CHECK: use_unitialized_var.glu:167:11: error: Load from uninitialized memory location + // CHECK: use_uninitialized_var.glu:167:11: error: Load from uninitialized memory location print(x); - // CHECK: use_unitialized_var.glu:169:11: error: Load from uninitialized memory location + // CHECK: use_uninitialized_var.glu:169:11: error: Load from uninitialized memory location print(z); } From 28d0c5f9dd502cd748b0fa4e874aba6bfa49e3d8 Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Fri, 7 Nov 2025 17:36:11 +0100 Subject: [PATCH 17/24] fix: copilot comments --- .../GILPasses/DetectUninitializedPass.cpp | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index 8696e9438..f81027bad 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -106,7 +106,6 @@ class DetectUninitializedPass state[destPtr] = MemoryState::Initialized; } else if (auto *load = llvm::dyn_cast(&inst)) { gil::Value srcPtr = load->getValue(); - auto it = state.find(srcPtr); } else if (auto *alloca = llvm::dyn_cast(&inst)) { gil::Value allocatedPtr = alloca->getResult(0); state[allocatedPtr] = MemoryState::Uninitialized; @@ -124,26 +123,6 @@ class DetectUninitializedPass } } - void traversePredecessorsForState(gil::BasicBlock *bb) - { - auto preds = getPredecessors(bb); - - if (preds.empty()) { - return; - } - - for (auto *pred : preds) { - - auto predIt = blockEndStates.find(pred); - if (predIt == blockEndStates.end()) { - llvm::DenseMap predState; - analyzeBasicBlockState(pred, predState); - blockEndStates[pred] = predState; - predIt = blockEndStates.find(pred); - } - } - } - public: DetectUninitializedPass(DiagnosticManager &diagManager) : diagManager(diagManager) From e974f839c3c6210103deb105f6dff8daa3b5f8e8 Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Fri, 7 Nov 2025 18:04:00 +0100 Subject: [PATCH 18/24] refactore: private functions in one area --- .../GILPasses/DetectUninitializedPass.cpp | 130 +++++++++--------- 1 file changed, 64 insertions(+), 66 deletions(-) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index f81027bad..a4b0cf4ee 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -123,6 +123,70 @@ class DetectUninitializedPass } } + static MemoryState getTrackedStateOrDefault( + gil::Value value, + llvm::DenseMap const &stateMap, + MemoryState defaultState + ) + { + auto it = stateMap.find(value); + if (it != stateMap.end()) { + return it->second; + } + return defaultState; + } + + void mergeStatesFromPredecessors(gil::BasicBlock *bb) + { + auto preds = getPredecessors(bb); + if (preds.empty()) { + currentState.clear(); + return; + } + + llvm::DenseSet allValues; + + for (auto *pred : preds) { + auto predIt = blockEndStates.find(pred); + if (predIt != blockEndStates.end()) { + for (auto const &entry : predIt->second) { + allValues.insert(entry.first); + } + } + } + + currentState.clear(); + + for (gil::Value value : allValues) { + bool hasAnyState = false; + MemoryState mergedState = MemoryState::Uninitialized; + + for (auto *pred : preds) { + auto predIt = blockEndStates.find(pred); + if (predIt == blockEndStates.end()) { + continue; + } + + auto valueIt = predIt->second.find(value); + if (valueIt != predIt->second.end()) { + if (!hasAnyState) { + mergedState = valueIt->second; + hasAnyState = true; + } else { + mergedState + = mergeMemoryStates(mergedState, valueIt->second); + } + } + } + + if (!hasAnyState) { + currentState[value] = MemoryState::Uninitialized; + } else { + currentState[value] = mergedState; + } + } + } + public: DetectUninitializedPass(DiagnosticManager &diagManager) : diagManager(diagManager) @@ -278,72 +342,6 @@ class DetectUninitializedPass currentState[fieldValue] = MemoryState::Initialized; } -private: - static MemoryState getTrackedStateOrDefault( - gil::Value value, - llvm::DenseMap const &stateMap, - MemoryState defaultState - ) - { - auto it = stateMap.find(value); - if (it != stateMap.end()) { - return it->second; - } - return defaultState; - } - - void mergeStatesFromPredecessors(gil::BasicBlock *bb) - { - auto preds = getPredecessors(bb); - if (preds.empty()) { - currentState.clear(); - return; - } - - llvm::DenseSet allValues; - - for (auto *pred : preds) { - auto predIt = blockEndStates.find(pred); - if (predIt != blockEndStates.end()) { - for (auto const &entry : predIt->second) { - allValues.insert(entry.first); - } - } - } - - currentState.clear(); - - for (gil::Value value : allValues) { - bool hasAnyState = false; - MemoryState mergedState = MemoryState::Uninitialized; - - for (auto *pred : preds) { - auto predIt = blockEndStates.find(pred); - if (predIt == blockEndStates.end()) { - continue; - } - - auto valueIt = predIt->second.find(value); - if (valueIt != predIt->second.end()) { - if (!hasAnyState) { - mergedState = valueIt->second; - hasAnyState = true; - } else { - mergedState - = mergeMemoryStates(mergedState, valueIt->second); - } - } - } - - if (!hasAnyState) { - currentState[value] = MemoryState::Uninitialized; - } else { - currentState[value] = mergedState; - } - } - } - -public: void afterVisitFunction(gil::Function *func) { predecessorMap.clear(); From b063171f822224c5c392feea2264f3c2cda66c7c Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Fri, 7 Nov 2025 18:05:07 +0100 Subject: [PATCH 19/24] chore: delete unused imcludes --- lib/Optimizer/GILPasses/DetectUninitializedPass.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index a4b0cf4ee..b5f1f6252 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -7,8 +7,6 @@ #include "GIL/Module.hpp" #include "PassManager.hpp" -#include "GIL/Instructions/BrInst.hpp" -#include "GIL/Instructions/CondBrInst.hpp" #include #include #include From 955c6e40da109787ec2a4ef79a6b4664769484e8 Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Fri, 7 Nov 2025 18:05:52 +0100 Subject: [PATCH 20/24] chore: delete unused condition --- lib/Optimizer/GILPasses/DetectUninitializedPass.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index b5f1f6252..90a684b93 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -102,8 +102,6 @@ class DetectUninitializedPass if (auto *store = llvm::dyn_cast(&inst)) { gil::Value destPtr = store->getDest(); state[destPtr] = MemoryState::Initialized; - } else if (auto *load = llvm::dyn_cast(&inst)) { - gil::Value srcPtr = load->getValue(); } else if (auto *alloca = llvm::dyn_cast(&inst)) { gil::Value allocatedPtr = alloca->getResult(0); state[allocatedPtr] = MemoryState::Uninitialized; From 9ac7ffcfa558c01112b5e7ec9a3964eda765de84 Mon Sep 17 00:00:00 2001 From: Yunse LEE Date: Fri, 7 Nov 2025 18:14:06 +0100 Subject: [PATCH 21/24] chore: add some tests --- .../GILPasses/DetectUninitializedPass.cpp | 8 +++++++ test/functional/run/use_uninitialized_var.glu | 22 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index 90a684b93..9b6368bfc 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -13,6 +13,14 @@ namespace glu::optimizer { +/// @brief GIL optimizer pass that reports loads and stores involving +/// uninitialized memory locations. +/// +/// The pass performs a fixed-point data-flow analysis across all basic +/// blocks in a GIL function, tracking a tri-state initialization lattice for +/// each memory value. Diagnostics are emitted when a load observes an +/// uninitialized location or a store that expects an initialized target sees +/// only a maybe-initialized state. class DetectUninitializedPass : public gil::InstVisitor { private: diff --git a/test/functional/run/use_uninitialized_var.glu b/test/functional/run/use_uninitialized_var.glu index 26beda632..8259ed904 100644 --- a/test/functional/run/use_uninitialized_var.glu +++ b/test/functional/run/use_uninitialized_var.glu @@ -168,3 +168,25 @@ func ddsdadasdadasfasf(machin: Bool) -> Void { // CHECK: use_uninitialized_var.glu:169:11: error: Load from uninitialized memory location print(z); } + +func gjkjalshdlhaskld () -> Void { + var x : Int; + + while(true) { + x = 1; + break; + } + // Check: use_uninitialized_var.glu:180:11: error: Load from uninitialized memory location + print(x); +} + +func gjkjaldasdshdlhaskld () -> Void { + var x : Int; + + while(true) { + // Check: use_uninitialized_var.glu:188:11: error: Store to memory location with uncertain initialization + x = 1; + } + // Check: use_uninitialized_var.glu:191:11: error: Load from uninitialized memory location + print(x); +} From c72837a2b1a92843220dff342eb53582f5ca6e96 Mon Sep 17 00:00:00 2001 From: Emil Pedersen Date: Fri, 14 Nov 2025 22:09:53 +0100 Subject: [PATCH 22/24] fix: uninitialized checks for arrays (handle bitcast) --- .../GILPasses/DetectUninitializedPass.cpp | 60 +++++++++++-------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index 9b6368bfc..42c138ba9 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -115,14 +115,23 @@ class DetectUninitializedPass state[allocatedPtr] = MemoryState::Uninitialized; } else if (auto *ptrOffsets = llvm::dyn_cast(&inst)) { - gil::Value basePtr = ptrOffsets->getBasePointer(); + gil::Value basePtr = ptrOffsets->getBasePtr(); MemoryState baseState = state.lookup(basePtr); state[ptrOffsets->getResult(0)] = baseState; } else if (auto *structFieldPtr = llvm::dyn_cast(&inst)) { - gil::Value basePtr = structFieldPtr->getStructValue(); + gil::Value basePtr = structFieldPtr->getStructPtr(); MemoryState baseState = state.lookup(basePtr); state[structFieldPtr->getResult(0)] = baseState; + } else if (auto *bitcastInst + = llvm::dyn_cast(&inst)) { + auto source = bitcastInst->getOperand(); + auto result = bitcastInst->getResult(0); + + if (llvm::isa(&*source.getType()) + && llvm::isa(&*result.getType())) { + state[result] = state.lookup(source); + } } } } @@ -267,7 +276,7 @@ class DetectUninitializedPass = llvm::dyn_cast_or_null( destPtr.getDefiningInstruction() )) { - gil::Value baseStruct = structFieldPtr->getStructValue(); + gil::Value baseStruct = structFieldPtr->getStructPtr(); currentState[baseStruct] = MemoryState::Initialized; } } @@ -278,8 +287,8 @@ class DetectUninitializedPass MemoryState state = currentState.lookup(srcPtr); if (!currentState.contains(srcPtr)) { - state = MemoryState::Initialized; // Default to initialized for - // unknown values + // Default to initialized for untracked values + state = MemoryState::Initialized; } if (state != MemoryState::Initialized) { @@ -288,10 +297,8 @@ class DetectUninitializedPass ); } - if (load->getResultCount() > 0) { - gil::Value loadedValue = load->getResult(0); - currentState[loadedValue] = state; - } + gil::Value loadedValue = load->getResult(0); + currentState[loadedValue] = state; if (load->getOwnershipKind() == gil::LoadOwnershipKind::Take) { currentState[srcPtr] = MemoryState::Uninitialized; @@ -300,19 +307,13 @@ class DetectUninitializedPass void visitAllocaInst(gil::AllocaInst *alloca) { - if (alloca->getResultCount() > 0) { - gil::Value allocatedPtr = alloca->getResult(0); - currentState[allocatedPtr] = MemoryState::Uninitialized; - } + gil::Value allocatedPtr = alloca->getResult(0); + currentState[allocatedPtr] = MemoryState::Uninitialized; } void visitPtrOffsetInst(gil::PtrOffsetInst *inst) { - if (inst->getResultCount() == 0) { - return; - } - - gil::Value basePtr = inst->getBasePointer(); + gil::Value basePtr = inst->getBasePtr(); MemoryState baseState = getTrackedStateOrDefault( basePtr, currentState, MemoryState::Uninitialized ); @@ -323,11 +324,7 @@ class DetectUninitializedPass void visitStructFieldPtrInst(gil::StructFieldPtrInst *inst) { - if (inst->getResultCount() == 0) { - return; - } - - gil::Value basePtr = inst->getStructValue(); + gil::Value basePtr = inst->getStructPtr(); MemoryState baseState = getTrackedStateOrDefault( basePtr, currentState, MemoryState::Uninitialized ); @@ -336,12 +333,25 @@ class DetectUninitializedPass currentState[resultPtr] = baseState; } - void visitStructExtractInst(gil::StructExtractInst *inst) + void visitBitcastInst(gil::BitcastInst *inst) { - if (inst->getResultCount() == 0) { + auto value = inst->getOperand(); + auto result = inst->getResult(0); + + if (!llvm::isa(&*value.getType()) + || !llvm::isa(&*result.getType())) { return; } + MemoryState sourceState = getTrackedStateOrDefault( + value, currentState, MemoryState::Uninitialized + ); + + currentState[result] = sourceState; + } + + void visitStructExtractInst(gil::StructExtractInst *inst) + { gil::Value fieldValue = inst->getResult(0); currentState[fieldValue] = MemoryState::Initialized; } From 38a254731984de24b53e90865ad05c71858712d5 Mon Sep 17 00:00:00 2001 From: Emil Pedersen Date: Fri, 14 Nov 2025 22:15:16 +0100 Subject: [PATCH 23/24] style: simplify uninitialized pass --- .../GILPasses/DetectUninitializedPass.cpp | 45 ++++++------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp index 42c138ba9..556eb59dc 100644 --- a/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp +++ b/lib/Optimizer/GILPasses/DetectUninitializedPass.cpp @@ -108,21 +108,17 @@ class DetectUninitializedPass { for (auto &inst : bb->getInstructions()) { if (auto *store = llvm::dyn_cast(&inst)) { - gil::Value destPtr = store->getDest(); - state[destPtr] = MemoryState::Initialized; + state[store->getDest()] = MemoryState::Initialized; } else if (auto *alloca = llvm::dyn_cast(&inst)) { - gil::Value allocatedPtr = alloca->getResult(0); - state[allocatedPtr] = MemoryState::Uninitialized; + state[alloca->getResult(0)] = MemoryState::Uninitialized; } else if (auto *ptrOffsets = llvm::dyn_cast(&inst)) { - gil::Value basePtr = ptrOffsets->getBasePtr(); - MemoryState baseState = state.lookup(basePtr); - state[ptrOffsets->getResult(0)] = baseState; + state[ptrOffsets->getResult(0)] + = state.lookup(ptrOffsets->getBasePtr()); } else if (auto *structFieldPtr = llvm::dyn_cast(&inst)) { - gil::Value basePtr = structFieldPtr->getStructPtr(); - MemoryState baseState = state.lookup(basePtr); - state[structFieldPtr->getResult(0)] = baseState; + state[structFieldPtr->getResult(0)] + = state.lookup(structFieldPtr->getStructPtr()); } else if (auto *bitcastInst = llvm::dyn_cast(&inst)) { auto source = bitcastInst->getOperand(); @@ -256,15 +252,13 @@ class DetectUninitializedPass MemoryState prevState = currentState.lookup(destPtr); - bool warnOnUncertainSet = (prevState == MemoryState::MaybeInitialized); - if (prevState == MemoryState::Uninitialized) { store->setOwnershipKind(gil::StoreOwnershipKind::Init); } else { store->setOwnershipKind(gil::StoreOwnershipKind::Set); } - if (warnOnUncertainSet) { + if (prevState == MemoryState::MaybeInitialized) { diagManager.error( store->getLocation(), "Store to memory location with uncertain initialization" @@ -297,8 +291,7 @@ class DetectUninitializedPass ); } - gil::Value loadedValue = load->getResult(0); - currentState[loadedValue] = state; + currentState[load->getResult(0)] = state; if (load->getOwnershipKind() == gil::LoadOwnershipKind::Take) { currentState[srcPtr] = MemoryState::Uninitialized; @@ -307,30 +300,21 @@ class DetectUninitializedPass void visitAllocaInst(gil::AllocaInst *alloca) { - gil::Value allocatedPtr = alloca->getResult(0); - currentState[allocatedPtr] = MemoryState::Uninitialized; + currentState[alloca->getResult(0)] = MemoryState::Uninitialized; } void visitPtrOffsetInst(gil::PtrOffsetInst *inst) { - gil::Value basePtr = inst->getBasePtr(); - MemoryState baseState = getTrackedStateOrDefault( - basePtr, currentState, MemoryState::Uninitialized + currentState[inst->getResult(0)] = getTrackedStateOrDefault( + inst->getBasePtr(), currentState, MemoryState::Uninitialized ); - - gil::Value resultPtr = inst->getResult(0); - currentState[resultPtr] = baseState; } void visitStructFieldPtrInst(gil::StructFieldPtrInst *inst) { - gil::Value basePtr = inst->getStructPtr(); - MemoryState baseState = getTrackedStateOrDefault( - basePtr, currentState, MemoryState::Uninitialized + currentState[inst->getResult(0)] = getTrackedStateOrDefault( + inst->getStructPtr(), currentState, MemoryState::Uninitialized ); - - gil::Value resultPtr = inst->getResult(0); - currentState[resultPtr] = baseState; } void visitBitcastInst(gil::BitcastInst *inst) @@ -352,8 +336,7 @@ class DetectUninitializedPass void visitStructExtractInst(gil::StructExtractInst *inst) { - gil::Value fieldValue = inst->getResult(0); - currentState[fieldValue] = MemoryState::Initialized; + currentState[inst->getResult(0)] = MemoryState::Initialized; } void afterVisitFunction(gil::Function *func) From 06df8b48ae2e32e0c9f6c00d60e059329fc021e8 Mon Sep 17 00:00:00 2001 From: Emil Pedersen Date: Fri, 14 Nov 2025 22:26:25 +0100 Subject: [PATCH 24/24] test: fix uninitialized var sema test --- .../{run => Sema}/use_uninitialized_var.glu | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) rename test/functional/{run => Sema}/use_uninitialized_var.glu (87%) diff --git a/test/functional/run/use_uninitialized_var.glu b/test/functional/Sema/use_uninitialized_var.glu similarity index 87% rename from test/functional/run/use_uninitialized_var.glu rename to test/functional/Sema/use_uninitialized_var.glu index 8259ed904..1f0205f3e 100644 --- a/test/functional/run/use_uninitialized_var.glu +++ b/test/functional/Sema/use_uninitialized_var.glu @@ -160,23 +160,23 @@ func ddsdadasdadasfasf(machin: Bool) -> Void { // CHECK: use_uninitialized_var.glu:162:13: error: Load from uninitialized memory location if (z == 1) { + // CHECK: use_uninitialized_var.glu:164:15: error: Store to memory location with uncertain initialization z = 0; } } - // CHECK: use_uninitialized_var.glu:167:11: error: Load from uninitialized memory location + // CHECK: use_uninitialized_var.glu:168:11: error: Load from uninitialized memory location print(x); - // CHECK: use_uninitialized_var.glu:169:11: error: Load from uninitialized memory location + // CHECK: use_uninitialized_var.glu:170:11: error: Load from uninitialized memory location print(z); } func gjkjalshdlhaskld () -> Void { var x : Int; - while(true) { x = 1; break; } - // Check: use_uninitialized_var.glu:180:11: error: Load from uninitialized memory location + // CHECK: use_uninitialized_var.glu:180:11: error: Load from uninitialized memory location print(x); } @@ -184,9 +184,11 @@ func gjkjaldasdshdlhaskld () -> Void { var x : Int; while(true) { - // Check: use_uninitialized_var.glu:188:11: error: Store to memory location with uncertain initialization + // CHECK: use_uninitialized_var.glu:188:11: error: Store to memory location with uncertain initialization x = 1; } - // Check: use_uninitialized_var.glu:191:11: error: Load from uninitialized memory location + // CHECK: use_uninitialized_var.glu:191:11: error: Load from uninitialized memory location print(x); } + +// CHECK: 11 error(s)