aboutsummaryrefslogtreecommitdiff
path: root/rcc-legacy/include/rcc/symtab.h
blob: 78507b9dce8f4b3083ee51890c2ab25cebf43856 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/* 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
<http://www.gnu.org/licenses/>.  */

#pragma once

/// @file symtab.h
/// @brief Scope chain symbol table.

#include "rcc/sysy_type.h"

#include <cassert>
#include <string>
#include <unordered_map>
#include <variant>
#include <vector>

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<int> dims;  // Array dimensions

    // Compile-time constant value (for constant folding and const array initialization)
    std::variant<std::monostate, int32_t, float, std::vector<int32_t>, std::vector<float>>
        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<std::pair<BType, bool>> 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<std::string, Symbol> symbols;
    };
    std::vector<Scope> scopes_;
    std::unordered_map<std::string, FuncSig> func_table_;
    int next_uid_ = 0;
};

}  // namespace rcc