/* Source code for RCC-Legacy.
Copyright (C) 2026 Richard Qin
This file is part of RCC.
RCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
RCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with RCC; see the file LICENSE. If not see
. */
#pragma once
/// @file symtab.h
/// @brief Scope chain symbol table.
#include "rcc/sysy_type.h"
#include
#include
#include
#include
#include
namespace rcc {
/// Symbol information
struct Symbol {
std::string name;
BType type = BType::Int;
bool is_const = false;
bool is_array = false;
bool is_param = false;
bool is_global = false;
std::vector dims; // Array dimensions
// Compile-time constant value (for constant folding and const array initialization)
std::variant, std::vector>
const_val;
// IR phase: If variable needs an address (array, global), store its alloca/global address here
int alloca_temp_id = -1; // Stack-allocated temp ID, -1 means unallocated
// Unique ID for Braun SSA: unique within a function, across scopes.
// Allocated by SymbolTable::allocate_uid() during Symbol construction.
int uid = -1;
};
/// Function signature
struct FuncSig {
std::string name;
BType ret_type = BType::Void;
std::vector> params; // (type, is_array)
};
/// Chained scope symbol table
class SymbolTable {
public:
void enter_scope() { scopes_.emplace_back(); }
void leave_scope() {
assert(!scopes_.empty());
scopes_.pop_back();
}
/// Insert symbol in current scope. Returns false on duplicate definition.
bool insert(const std::string& name, Symbol sym) {
auto& cur = scopes_.back().symbols;
if (cur.count(name)) {
return false;
}
cur[name] = std::move(sym);
return true;
}
/// Lookup variable symbol from inner to outer scopes.
Symbol* lookup(const std::string& name) {
for (auto it = scopes_.rbegin(); it != scopes_.rend(); ++it) {
auto found = it->symbols.find(name);
if (found != it->symbols.end()) {
return &found->second;
}
}
return nullptr;
}
/// Register function signature.
void register_func(FuncSig sig) { func_table_[sig.name] = std::move(sig); }
/// Lookup function signature.
FuncSig* lookup_func(const std::string& name) {
auto it = func_table_.find(name);
return it != func_table_.end() ? &it->second : nullptr;
}
/// Register SysY runtime library functions.
void register_builtins();
/// Allocate a new Symbol uid.
/// Counter increments monotonically across enter/leave_scope without resetting.
int allocate_uid() { return next_uid_++; }
private:
struct Scope {
std::unordered_map symbols;
};
std::vector scopes_;
std::unordered_map func_table_;
int next_uid_ = 0;
};
} // namespace rcc