Fix LOAD_GLOBAL and cell var references in Python 3.11+

This commit is contained in:
Michael Hansen
2023-01-19 13:05:06 -08:00
parent 379c0c94d0
commit 5d855f0bd2
4 changed files with 30 additions and 12 deletions

View File

@@ -1606,7 +1606,7 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
} }
break; break;
case Pyc::LOAD_DEREF_A: case Pyc::LOAD_DEREF_A:
stack.push(new ASTName(code->getCellVar(operand))); stack.push(new ASTName(code->getCellVar(mod, operand)));
break; break;
case Pyc::LOAD_FAST_A: case Pyc::LOAD_FAST_A:
if (mod->verCompare(1, 3) < 0) if (mod->verCompare(1, 3) < 0)
@@ -2100,7 +2100,7 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
case Pyc::STORE_DEREF_A: case Pyc::STORE_DEREF_A:
{ {
if (unpack) { if (unpack) {
PycRef<ASTNode> name = new ASTName(code->getCellVar(operand)); PycRef<ASTNode> name = new ASTName(code->getCellVar(mod, operand));
PycRef<ASTNode> tup = stack.top(); PycRef<ASTNode> tup = stack.top();
if (tup.type() == ASTNode::NODE_TUPLE) if (tup.type() == ASTNode::NODE_TUPLE)
@@ -2122,7 +2122,7 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
} else { } else {
PycRef<ASTNode> value = stack.top(); PycRef<ASTNode> value = stack.top();
stack.pop(); stack.pop();
PycRef<ASTNode> name = new ASTName(code->getCellVar(operand)); PycRef<ASTNode> name = new ASTName(code->getCellVar(mod, operand));
if (value.type() == ASTNode::NODE_CHAINSTORE) { if (value.type() == ASTNode::NODE_CHAINSTORE) {
append_to_chain_store(value, name, stack, curblock); append_to_chain_store(value, name, stack, curblock);

View File

@@ -363,7 +363,7 @@ void bc_disasm(PycRef<PycCode> code, PycModule* mod, int indent)
fprintf(pyc_output, "%-7d ", pos); // Current bytecode position fprintf(pyc_output, "%-7d ", pos); // Current bytecode position
bc_next(source, mod, opcode, operand, pos); bc_next(source, mod, opcode, operand, pos);
fprintf(pyc_output, "%-24s", Pyc::OpcodeName(opcode)); fprintf(pyc_output, "%-30s", Pyc::OpcodeName(opcode));
if (opcode >= Pyc::PYC_HAVE_ARG) { if (opcode >= Pyc::PYC_HAVE_ARG) {
if (Pyc::IsConstArg(opcode)) { if (Pyc::IsConstArg(opcode)) {
@@ -374,6 +374,16 @@ void bc_disasm(PycRef<PycCode> code, PycModule* mod, int indent)
} catch (const std::out_of_range &) { } catch (const std::out_of_range &) {
fprintf(pyc_output, "%d <INVALID>", operand); fprintf(pyc_output, "%d <INVALID>", operand);
} }
} else if (opcode == Pyc::LOAD_GLOBAL_A) {
// Special case for Python 3.11+
try {
if (operand & 1)
fprintf(pyc_output, "%d: NULL + %s", operand, code->getName(operand >> 1)->value());
else
fprintf(pyc_output, "%d: %s", operand, code->getName(operand >> 1)->value());
} catch (const std::out_of_range &) {
fprintf(pyc_output, "%d <INVALID>", operand);
}
} else if (Pyc::IsNameArg(opcode)) { } else if (Pyc::IsNameArg(opcode)) {
try { try {
fprintf(pyc_output, "%d: %s", operand, code->getName(operand)->value()); fprintf(pyc_output, "%d: %s", operand, code->getName(operand)->value());
@@ -388,7 +398,7 @@ void bc_disasm(PycRef<PycCode> code, PycModule* mod, int indent)
} }
} else if (Pyc::IsCellArg(opcode)) { } else if (Pyc::IsCellArg(opcode)) {
try { try {
fprintf(pyc_output, "%d: %s", operand, code->getCellVar(operand)->value()); fprintf(pyc_output, "%d: %s", operand, code->getCellVar(mod, operand)->value());
} catch (const std::out_of_range &) { } catch (const std::out_of_range &) {
fprintf(pyc_output, "%d <INVALID>", operand); fprintf(pyc_output, "%d <INVALID>", operand);
} }

View File

@@ -87,3 +87,13 @@ void PycCode::load(PycData* stream, PycModule* mod)
else else
m_exceptTable = new PycString; m_exceptTable = new PycString;
} }
PycRef<PycString> PycCode::getCellVar(PycModule* mod, int idx) const
{
if (mod->verCompare(3, 11) >= 0)
return getLocal(idx);
return (idx >= m_cellVars->size())
? m_freeVars->get(idx - m_cellVars->size()).cast<PycString>()
: m_cellVars->get(idx).cast<PycString>();
}

View File

@@ -5,6 +5,9 @@
#include "pyc_string.h" #include "pyc_string.h"
#include <vector> #include <vector>
class PycData;
class PycModule;
class PycCode : public PycObject { class PycCode : public PycObject {
public: public:
typedef std::vector<PycRef<PycString>> globals_t; typedef std::vector<PycRef<PycString>> globals_t;
@@ -32,7 +35,7 @@ public:
: PycObject(type), m_argCount(), m_posOnlyArgCount(), m_kwOnlyArgCount(), : PycObject(type), m_argCount(), m_posOnlyArgCount(), m_kwOnlyArgCount(),
m_numLocals(), m_stackSize(), m_flags(), m_firstLine() { } m_numLocals(), m_stackSize(), m_flags(), m_firstLine() { }
void load(class PycData* stream, class PycModule* mod) override; void load(PycData* stream, PycModule* mod) override;
int argCount() const { return m_argCount; } int argCount() const { return m_argCount; }
int posOnlyArgCount() const { return m_posOnlyArgCount; } int posOnlyArgCount() const { return m_posOnlyArgCount; }
@@ -69,12 +72,7 @@ public:
return m_localNames->get(idx).cast<PycString>(); return m_localNames->get(idx).cast<PycString>();
} }
PycRef<PycString> getCellVar(int idx) const PycRef<PycString> getCellVar(PycModule* mod, int idx) const;
{
return (idx >= m_cellVars->size())
? m_freeVars->get(idx - m_cellVars->size()).cast<PycString>()
: m_cellVars->get(idx).cast<PycString>();
}
const globals_t& getGlobals() const { return m_globalsUsed; } const globals_t& getGlobals() const { return m_globalsUsed; }