diff --git a/compiler/forget/src/HIR/BuildAliasSets.ts b/compiler/forget/src/HIR/BuildAliasSets.ts index 726f359db7..efcde31a76 100644 --- a/compiler/forget/src/HIR/BuildAliasSets.ts +++ b/compiler/forget/src/HIR/BuildAliasSets.ts @@ -17,58 +17,47 @@ class AbstractState { aliases = new DisjointSet(); #values = new Map(); - // Simple lvalue: - // lvalue = alias; - // lvalue = alias.memberPath; - alias(lvalue: LValue, alias: Place) { + read(alias: Place): AbstractValue { // Simple alias: - // lvalue = alias; + // read(alias); if (alias.memberPath === null) { let value = this.#values.get(alias.identifier); - // Don't know what this, let's default to an Object conservatively. + // Don't know what this is, let's default to an Object conservatively. if (value === undefined) { value = { kind: "Object", values: new Map() }; } - this.#values.set(lvalue.place.identifier, value); - - // No need to alias Primitives - if (value.kind !== "Primitive") { - this.aliases.union([lvalue.place.identifier, alias.identifier]); - } - return; + this.#values.set(alias.identifier, value); + return value; } // Complex alias: - // lvalue = alias.memberPath; - if (alias.memberPath.length > 1) { - // TODO(gsn): Handle nested member paths - return; - } - + // read(alias.memberPath); let object = this.#values.get(alias.identifier); - // Don't know what this, let's default to an Object conservatively. + // Don't know what this is, let's default to an Object conservatively. if (object === undefined) { object = { kind: "Object", values: new Map() }; + this.#values.set(alias.identifier, object); } // We're doing a member lookup on a non object. // // alias = 1; - // lvalue = alias.memberPath; + // read(alias.memberPath); if (object.kind !== "Object") { + // Update alias to be an object + object = { kind: "Object", values: new Map() }; + this.#values.set(alias.identifier, object); + // Conservatively type the value as object. // // NOTE(gsn): Should this be an AbstractUnknown rather than an // AbstractObject? - this.#values.set(lvalue.place.identifier, { - kind: "Object", - values: new Map(), - }); - this.aliases.union([lvalue.place.identifier, alias.identifier]); - return; + let value: AbstractObject = { kind: "Object", values: new Map() }; + object.values.set(alias.memberPath[0], value); + return value; } let value = object.values.get(alias.memberPath[0]); @@ -76,21 +65,34 @@ class AbstractState { // We don't have a value for this member path. // // alias = {}; - // lvalue = alias.memberPath; + // read(alias.memberPath); if (value === undefined) { // Conservatively type the value as object. - this.#values.set(lvalue.place.identifier, { + value = { kind: "Object", values: new Map(), - }); - this.aliases.union([lvalue.place.identifier, alias.identifier]); - return; + }; + object.values.set(alias.memberPath[0], value); + return value; } // We have a value for this memberPath! // - // alias.memberPath = value; - // lvalue = alias.memberPath; + // alias.memberPath = value; + // read(alias.memberPath); + return value; + } + + // Simple lvalue: + // lvalue = alias; + // lvalue = alias.memberPath; + alias(lvalue: LValue, alias: Place) { + if (alias.memberPath !== null && alias.memberPath.length > 1) { + // TODO(gsn): Handle nested member paths + return; + } + + const value = this.read(alias); this.#values.set(lvalue.place.identifier, value); // No need to alias Primitives.