Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions maldoca/js/ast/ast.generated.cc
Original file line number Diff line number Diff line change
Expand Up @@ -468,9 +468,11 @@ JsCommentLine::JsCommentLine(

JsSymbolId::JsSymbolId(
std::string name,
std::optional<int64_t> def_scope_uid)
std::optional<int64_t> def_scope_uid,
std::optional<int64_t> binding_uid)
: name_(std::move(name)),
def_scope_uid_(std::move(def_scope_uid)) {}
def_scope_uid_(std::move(def_scope_uid)),
binding_uid_(std::move(binding_uid)) {}

absl::string_view JsSymbolId::name() const {
return name_;
Expand All @@ -492,6 +494,18 @@ void JsSymbolId::set_def_scope_uid(std::optional<int64_t> def_scope_uid) {
def_scope_uid_ = std::move(def_scope_uid);
}

std::optional<int64_t> JsSymbolId::binding_uid() const {
if (!binding_uid_.has_value()) {
return std::nullopt;
} else {
return binding_uid_.value();
}
}

void JsSymbolId::set_binding_uid(std::optional<int64_t> binding_uid) {
binding_uid_ = std::move(binding_uid);
}

// =============================================================================
// JsNode
// =============================================================================
Expand Down
8 changes: 7 additions & 1 deletion maldoca/js/ast/ast.generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,8 @@ class JsSymbolId {
public:
explicit JsSymbolId(
std::string name,
std::optional<int64_t> def_scope_uid);
std::optional<int64_t> def_scope_uid,
std::optional<int64_t> binding_uid);

void Serialize(std::ostream& os) const;

Expand All @@ -307,6 +308,9 @@ class JsSymbolId {
std::optional<int64_t> def_scope_uid() const;
void set_def_scope_uid(std::optional<int64_t> def_scope_uid);

std::optional<int64_t> binding_uid() const;
void set_binding_uid(std::optional<int64_t> binding_uid);

protected:
// Internal function used by Serialize().
// Sets the fields defined in this class.
Expand All @@ -317,10 +321,12 @@ class JsSymbolId {
// Extracts a field from a JSON object.
static absl::StatusOr<std::string> GetName(const nlohmann::json& json);
static absl::StatusOr<std::optional<int64_t>> GetDefScopeUid(const nlohmann::json& json);
static absl::StatusOr<std::optional<int64_t>> GetBindingUid(const nlohmann::json& json);

private:
std::string name_;
std::optional<int64_t> def_scope_uid_;
std::optional<int64_t> binding_uid_;
};

enum class JsNodeType {
Expand Down
13 changes: 12 additions & 1 deletion maldoca/js/ast/ast_from_json.generated.cc
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,15 @@ JsSymbolId::GetDefScopeUid(const nlohmann::json& json) {
);
}

absl::StatusOr<std::optional<int64_t>>
JsSymbolId::GetBindingUid(const nlohmann::json& json) {
return GetOptionalField<int64_t>(
json,
"bindingUid",
JsonToInt64
);
}

absl::StatusOr<std::unique_ptr<JsSymbolId>>
JsSymbolId::FromJson(const nlohmann::json& json) {
if (!json.is_object()) {
Expand All @@ -254,10 +263,12 @@ JsSymbolId::FromJson(const nlohmann::json& json) {

MALDOCA_ASSIGN_OR_RETURN(auto name, JsSymbolId::GetName(json));
MALDOCA_ASSIGN_OR_RETURN(auto def_scope_uid, JsSymbolId::GetDefScopeUid(json));
MALDOCA_ASSIGN_OR_RETURN(auto binding_uid, JsSymbolId::GetBindingUid(json));

return absl::make_unique<JsSymbolId>(
std::move(name),
std::move(def_scope_uid));
std::move(def_scope_uid),
std::move(binding_uid));
}

// =============================================================================
Expand Down
4 changes: 4 additions & 0 deletions maldoca/js/ast/ast_to_json.generated.cc
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ void JsSymbolId::SerializeFields(std::ostream& os, bool &needs_comma) const {
MaybeAddComma(os, needs_comma);
os << "\"defScopeUid\":" << (nlohmann::json(def_scope_uid_.value())).dump();
}
if (binding_uid_.has_value()) {
MaybeAddComma(os, needs_comma);
os << "\"bindingUid\":" << (nlohmann::json(binding_uid_.value())).dump();
}
}

void JsSymbolId::Serialize(std::ostream& os) const {
Expand Down
7 changes: 6 additions & 1 deletion maldoca/js/babel/babel.proto
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,19 @@ message BabelBinding {

optional Kind kind = 1;
optional string name = 2;
optional int32 uid = 3;
repeated PositionPb constant_violations = 4;
}

message BabelScope {
optional int32 uid = 1;
optional int32 parent_uid = 2;
map<string, BabelBinding> bindings = 3;
// Deprecated: use binding_uids instead.
map<string, BabelBinding> bindings = 3 [deprecated = true];
map<string, int32> binding_uids = 4;
}

message BabelScopes {
map<int32, BabelScope> scopes = 1;
map<int32, BabelBinding> bindings = 2;
}
18 changes: 12 additions & 6 deletions maldoca/js/babel/babel_json_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@ TEST(BabelJsonTest, BabelScopes) {
BabelBinding binding;
binding.set_kind(BabelBinding::KIND_VAR);
binding.set_name("global");
binding.set_uid(1);

scope.mutable_bindings()->insert({binding.name(), binding});
scopes.mutable_bindings()->insert({binding.uid(), binding});
scope.mutable_binding_uids()->insert({binding.name(), binding.uid()});
}

scopes.mutable_scopes()->insert({scope.uid(), scope});
Expand All @@ -73,13 +75,17 @@ TEST(BabelJsonTest, BabelScopes) {
"scopes": {
"0": {
"uid": 0,
"bindings": {
"global": {
"kind": "KIND_VAR",
"name": "global"
}
"bindingUids": {
"global": 1
}
}
},
"bindings": {
"1": {
"kind": "KIND_VAR",
"name": "global",
"uid": 1
}
}
}
)json";
Expand Down
72 changes: 62 additions & 10 deletions maldoca/js/babel/scope.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,50 @@

namespace maldoca {

std::optional<int64_t> FindSymbol(const BabelScopes &scopes,
int64_t use_scope_uid,
absl::string_view name) {
std::optional<int64_t> FindSymbol(const BabelScopes& scopes,
int64_t use_scope_uid, absl::string_view name,
bool is_var_declaration) {
auto scope_it = scopes.scopes().find(use_scope_uid);
if (scope_it == scopes.scopes().end()) {
return std::nullopt;
}
const auto &scope = scope_it->second;
const auto& scope = scope_it->second;

auto binding_it = scope.bindings().find(name);
if (binding_it != scope.bindings().end()) {
bool found_matching_binding = false;

auto binding_it = scope.binding_uids().find(std::string(name));
if (binding_it != scope.binding_uids().end()) {
found_matching_binding = true;
if (is_var_declaration) {
int32_t binding_uid = binding_it->second;
auto b_it = scopes.bindings().find(binding_uid);
if (b_it != scopes.bindings().end()) {
const auto& binding = b_it->second;
if (binding.kind() == BabelBinding::KIND_LET ||
binding.kind() == BabelBinding::KIND_CONST ||
binding.kind() == BabelBinding::KIND_LOCAL) {
found_matching_binding = false; // skip
}
}
}
}

if (!found_matching_binding) {
auto old_binding_it = scope.bindings().find(std::string(name));
if (old_binding_it != scope.bindings().end()) {
found_matching_binding = true;
if (is_var_declaration) {
const auto& binding = old_binding_it->second;
if (binding.kind() == BabelBinding::KIND_LET ||
binding.kind() == BabelBinding::KIND_CONST ||
binding.kind() == BabelBinding::KIND_LOCAL) {
found_matching_binding = false; // skip
}
}
}
}

if (found_matching_binding) {
return use_scope_uid;
}

Expand All @@ -49,12 +82,31 @@ std::optional<int64_t> FindSymbol(const BabelScopes &scopes,
return std::nullopt;
}

return FindSymbol(scopes, parent_scope_uid, name);
return FindSymbol(scopes, parent_scope_uid, name, is_var_declaration);
}

JsSymbolId GetSymbolId(const BabelScopes &scopes, int64_t use_scope_uid,
absl::string_view name) {
return JsSymbolId{std::string(name), FindSymbol(scopes, use_scope_uid, name)};
JsSymbolId GetSymbolId(const BabelScopes& scopes, int64_t use_scope_uid,
absl::string_view name, bool is_var_declaration) {
auto def_scope_uid =
FindSymbol(scopes, use_scope_uid, name, is_var_declaration);
std::optional<int64_t> binding_uid = std::nullopt;
if (def_scope_uid.has_value()) {
auto scope_it = scopes.scopes().find(*def_scope_uid);
if (scope_it != scopes.scopes().end()) {
auto binding_it = scope_it->second.binding_uids().find(std::string(name));
if (binding_it != scope_it->second.binding_uids().end()) {
binding_uid = binding_it->second;
} else {
auto old_binding_it =
scope_it->second.bindings().find(std::string(name));
if (old_binding_it != scope_it->second.bindings().end() &&
old_binding_it->second.has_uid()) {
binding_uid = old_binding_it->second.uid();
}
}
}
}
return JsSymbolId{std::string(name), def_scope_uid, binding_uid};
}

} // namespace maldoca
33 changes: 20 additions & 13 deletions maldoca/js/babel/scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,31 @@ namespace maldoca {

template <typename H>
H AbslHashValue(H h, const JsSymbolId& s) {
return H::combine(std::move(h), s.name(), s.def_scope_uid());
return H::combine(std::move(h), s.name(), s.def_scope_uid(),
s.binding_uid().value_or(-1));
}

inline bool operator==(const JsSymbolId& lhs, const JsSymbolId& rhs) {
return std::forward_as_tuple(lhs.name(), lhs.def_scope_uid()) ==
std::forward_as_tuple(rhs.name(), rhs.def_scope_uid());
return lhs.name() == rhs.name() &&
lhs.def_scope_uid() == rhs.def_scope_uid() &&
lhs.binding_uid().value_or(-1) == rhs.binding_uid().value_or(-1);
}

inline bool operator<(const JsSymbolId& lhs, const JsSymbolId& rhs) {
return std::forward_as_tuple(lhs.def_scope_uid(), lhs.name()) <
std::forward_as_tuple(rhs.def_scope_uid(), rhs.name());
return std::make_tuple(lhs.binding_uid().value_or(-1), lhs.def_scope_uid(),
lhs.name()) <
std::make_tuple(rhs.binding_uid().value_or(-1), rhs.def_scope_uid(),
rhs.name());
}

template <typename Sink>
void AbslStringify(Sink& sink, const JsSymbolId& s) {
std::string def_scope_uid = s.def_scope_uid().has_value()
? absl::StrCat(*s.def_scope_uid())
: "undeclared";
absl::Format(&sink, "%s#%s", s.name(), def_scope_uid);
std::string id = s.binding_uid().has_value()
? absl::StrCat("b", *s.binding_uid())
: (s.def_scope_uid().has_value()
? absl::StrCat("s", *s.def_scope_uid())
: "undeclared");
absl::Format(&sink, "%s#%s", s.name(), id);
}

inline std::ostream& operator<<(std::ostream& os, const JsSymbolId& s) {
Expand All @@ -58,14 +64,15 @@ inline std::ostream& operator<<(std::ostream& os, const JsSymbolId& s) {

// Searches all scopes from `scope_uid` to the global scope for a symbol.
// Returns the uid of the scope where the symbol is defined.
std::optional<int64_t> FindSymbol(const BabelScopes &scopes, int64_t scope_uid,
absl::string_view name);
std::optional<int64_t> FindSymbol(const BabelScopes& scopes, int64_t scope_uid,
absl::string_view name,
bool is_var_declaration = false);

// Turns a symbol name into a JsSymbolId, by searching all scopes from
// `scope_uid` to the global scope. If the symbol is not found, assume it has
// `scope_uid` 0.
JsSymbolId GetSymbolId(const BabelScopes &scopes, int64_t scope_uid,
absl::string_view name);
JsSymbolId GetSymbolId(const BabelScopes& scopes, int64_t scope_uid,
absl::string_view name, bool is_var_declaration = false);

} // namespace maldoca

Expand Down
2 changes: 2 additions & 0 deletions maldoca/js/driver/driver.proto
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ message JsirAnalysisResult {
}
repeated ComputedConstant computed_constants = 3;
}

// Represents maldoca::JsSymbolId
}

message JsAnalysisOutput {
Expand Down
1 change: 1 addition & 0 deletions maldoca/js/ir/analyses/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ cc_library(
"//maldoca/js/ir",
"//maldoca/js/ir:utf16",
"//maldoca/js/ir/analyses/constant_propagation:analysis",
"@abseil-cpp//absl/base:no_destructor",
"@abseil-cpp//absl/base:nullability",
"@abseil-cpp//absl/container:flat_hash_map",
"@abseil-cpp//absl/status",
Expand Down
5 changes: 5 additions & 0 deletions maldoca/js/ir/analyses/analysis.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "maldoca/js/ir/analyses/analysis.h"

#include <cstdint>
#include <optional>
#include <string>
#include <type_traits>
Expand All @@ -26,11 +27,15 @@
#include "mlir/IR/Operation.h"
#include "mlir/IR/Value.h"
#include "mlir/Support/LogicalResult.h"
#include "absl/base/no_destructor.h"
#include "absl/base/nullability.h"
#include "absl/container/flat_hash_map.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "third_party/llvm/llvm-project/llvm/include/llvm/ADT/DenseMap.h"
#include "third_party/llvm/llvm-project/mlir/include/mlir/IR/Location.h"
#include "third_party/llvm/llvm-project/mlir/include/mlir/Support/LLVM.h"
#include "maldoca/base/ret_check.h"
#include "maldoca/base/status_macros.h"
#include "maldoca/js/ast/ast.generated.h"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class JsirConditionalForwardPerVarDataFlowAnalysis
void WriteDenseAfterState(mlir::Operation *op, llvm::StringRef name,
const ValueT &value, const StateT *before,
JsirStateRef<StateT> after) {
JsSymbolId target_symbol{std::string(name), FindSymbol(scopes_, op, name)};
JsSymbolId target_symbol = GetSymbolId(scopes_, op, name);

after.Join(*before);
after.Write([&](StateT *after) {
Expand All @@ -112,8 +112,7 @@ class JsirConditionalForwardPerVarDataFlowAnalysis
void VisitIdentifier(JsirIdentifierOp op,
OperandStates<JsirIdentifierOp> operands,
const StateT *before, JsirStateRef<ValueT> result) {
absl::string_view name = op.getName();
JsSymbolId symbol{std::string(name), FindSymbol(scopes_, op, name)};
JsSymbolId symbol = GetSymbolId(scopes_, op);
ValueT value = before->Get(symbol);
result.Join(value);
}
Expand All @@ -124,7 +123,7 @@ class JsirConditionalForwardPerVarDataFlowAnalysis
llvm::MutableArrayRef<JsirStateRef<ValueT>> results,
JsirStateRef<StateT> after) {
absl::string_view name = op.getId().getName().strref();
JsSymbolId symbol{std::string(name), FindSymbol(scopes_, op, name)};
JsSymbolId symbol = GetSymbolId(scopes_, op, name);
ValueT value = before->Get(symbol);

assert(results.size() == 1);
Expand Down
Loading
Loading