Fix LOAD_GLOBAL and cell var references in Python 3.11+
This commit is contained in:
@@ -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);
|
||||||
|
14
bytecode.cpp
14
bytecode.cpp
@@ -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);
|
||||||
}
|
}
|
||||||
|
10
pyc_code.cpp
10
pyc_code.cpp
@@ -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>();
|
||||||
|
}
|
||||||
|
12
pyc_code.h
12
pyc_code.h
@@ -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; }
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user