Commit b7946d16 by Andrew Woloszyn

Free memory associated with SPIR-V generation.

parent 863aa667
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#include "spvIR.h" #include "spvIR.h"
#include <algorithm> #include <algorithm>
#include <memory>
#include <stack> #include <stack>
#include <map> #include <map>
...@@ -201,11 +202,13 @@ public: ...@@ -201,11 +202,13 @@ public:
void setBuildPoint(Block* bp) { buildPoint = bp; } void setBuildPoint(Block* bp) { buildPoint = bp; }
Block* getBuildPoint() const { return buildPoint; } Block* getBuildPoint() const { return buildPoint; }
// Make the main function. // Make the main function. The returned pointer is only valid
// for the lifetime of this builder.
Function* makeMain(); Function* makeMain();
// Make a shader-style function, and create its entry block if entry is non-zero. // Make a shader-style function, and create its entry block if entry is non-zero.
// Return the function, pass back the entry. // Return the function, pass back the entry.
// The returned pointer is only valid for the lifetime of this builder.
Function* makeFunctionEntry(Id returnType, const char* name, std::vector<Id>& paramTypes, Block **entry = 0); Function* makeFunctionEntry(Id returnType, const char* name, std::vector<Id>& paramTypes, Block **entry = 0);
// Create a return. An 'implicit' return is one not appearing in the source // Create a return. An 'implicit' return is one not appearing in the source
...@@ -516,7 +519,7 @@ protected: ...@@ -516,7 +519,7 @@ protected:
void createSelectionMerge(Block* mergeBlock, unsigned int control); void createSelectionMerge(Block* mergeBlock, unsigned int control);
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control); void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control);
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
void dumpInstructions(std::vector<unsigned int>&, const std::vector<Instruction*>&) const; void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
struct Loop; // Defined below. struct Loop; // Defined below.
void createBranchToLoopHeaderFromInside(const Loop& loop); void createBranchToLoopHeaderFromInside(const Loop& loop);
...@@ -535,14 +538,15 @@ protected: ...@@ -535,14 +538,15 @@ protected:
AccessChain accessChain; AccessChain accessChain;
// special blocks of instructions for output // special blocks of instructions for output
std::vector<Instruction*> imports; std::vector<std::unique_ptr<Instruction> > imports;
std::vector<Instruction*> entryPoints; std::vector<std::unique_ptr<Instruction> > entryPoints;
std::vector<Instruction*> executionModes; std::vector<std::unique_ptr<Instruction> > executionModes;
std::vector<Instruction*> names; std::vector<std::unique_ptr<Instruction> > names;
std::vector<Instruction*> lines; std::vector<std::unique_ptr<Instruction> > lines;
std::vector<Instruction*> decorations; std::vector<std::unique_ptr<Instruction> > decorations;
std::vector<Instruction*> constantsTypesGlobals; std::vector<std::unique_ptr<Instruction> > constantsTypesGlobals;
std::vector<Instruction*> externals; std::vector<std::unique_ptr<Instruction> > externals;
std::vector<std::unique_ptr<Function> > functions;
// not output, internally used for quick & dirty canonical (unique) creation // not output, internally used for quick & dirty canonical (unique) creation
std::vector<Instruction*> groupedConstants[OpConstant]; // all types appear before OpConstant std::vector<Instruction*> groupedConstants[OpConstant]; // all types appear before OpConstant
......
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
#include <vector> #include <vector>
#include <iostream> #include <iostream>
#include <memory>
#include <assert.h> #include <assert.h>
namespace spv { namespace spv {
...@@ -155,15 +156,14 @@ public: ...@@ -155,15 +156,14 @@ public:
Block(Id id, Function& parent); Block(Id id, Function& parent);
virtual ~Block() virtual ~Block()
{ {
// TODO: free instructions
} }
Id getId() { return instructions.front()->getResultId(); } Id getId() { return instructions.front()->getResultId(); }
Function& getParent() const { return parent; } Function& getParent() const { return parent; }
void addInstruction(Instruction* inst); void addInstruction(std::unique_ptr<Instruction> inst);
void addPredecessor(Block* pred) { predecessors.push_back(pred); } void addPredecessor(Block* pred) { predecessors.push_back(pred); }
void addLocalVariable(Instruction* inst) { localVariables.push_back(inst); } void addLocalVariable(std::unique_ptr<Instruction> inst) { localVariables.push_back(std::move(inst)); }
int getNumPredecessors() const { return (int)predecessors.size(); } int getNumPredecessors() const { return (int)predecessors.size(); }
void setUnreachable() { unreachable = true; } void setUnreachable() { unreachable = true; }
bool isUnreachable() const { return unreachable; } bool isUnreachable() const { return unreachable; }
...@@ -205,9 +205,9 @@ protected: ...@@ -205,9 +205,9 @@ protected:
// To enforce keeping parent and ownership in sync: // To enforce keeping parent and ownership in sync:
friend Function; friend Function;
std::vector<Instruction*> instructions; std::vector<std::unique_ptr<Instruction> > instructions;
std::vector<Block*> predecessors; std::vector<Block*> predecessors;
std::vector<Instruction*> localVariables; std::vector<std::unique_ptr<Instruction> > localVariables;
Function& parent; Function& parent;
// track whether this block is known to be uncreachable (not necessarily // track whether this block is known to be uncreachable (not necessarily
...@@ -240,7 +240,7 @@ public: ...@@ -240,7 +240,7 @@ public:
Module& getParent() const { return parent; } Module& getParent() const { return parent; }
Block* getEntryBlock() const { return blocks.front(); } Block* getEntryBlock() const { return blocks.front(); }
Block* getLastBlock() const { return blocks.back(); } Block* getLastBlock() const { return blocks.back(); }
void addLocalVariable(Instruction* inst); void addLocalVariable(std::unique_ptr<Instruction> inst);
Id getReturnType() const { return functionInstruction.getTypeId(); } Id getReturnType() const { return functionInstruction.getTypeId(); }
void dump(std::vector<unsigned int>& out) const void dump(std::vector<unsigned int>& out) const
{ {
...@@ -341,22 +341,24 @@ __inline Function::Function(Id id, Id resultType, Id functionType, Id firstParam ...@@ -341,22 +341,24 @@ __inline Function::Function(Id id, Id resultType, Id functionType, Id firstParam
} }
} }
__inline void Function::addLocalVariable(Instruction* inst) __inline void Function::addLocalVariable(std::unique_ptr<Instruction> inst)
{ {
blocks[0]->addLocalVariable(inst); Instruction* raw_instruction = inst.get();
parent.mapInstruction(inst); blocks[0]->addLocalVariable(std::move(inst));
parent.mapInstruction(raw_instruction);
} }
__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false) __inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false)
{ {
instructions.push_back(new Instruction(id, NoType, OpLabel)); instructions.push_back(std::unique_ptr<Instruction>(new Instruction(id, NoType, OpLabel)));
} }
__inline void Block::addInstruction(Instruction* inst) __inline void Block::addInstruction(std::unique_ptr<Instruction> inst)
{ {
instructions.push_back(inst); Instruction* raw_instruction = inst.get();
if (inst->getResultId()) instructions.push_back(std::move(inst));
parent.getParent().mapInstruction(inst); if (raw_instruction->getResultId())
parent.getParent().mapInstruction(raw_instruction);
} }
}; // end spv namespace }; // end spv namespace
......
...@@ -784,7 +784,9 @@ class TIntermAggregate : public TIntermOperator { ...@@ -784,7 +784,9 @@ class TIntermAggregate : public TIntermOperator {
public: public:
TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0) { } TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0) { }
TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { } TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { }
~TIntermAggregate() { delete pragmaTable; } // Since pragmaTable is allocated with the PoolAllocator, we
// only want to destroy it, not free the associated memory.
~TIntermAggregate() { pragmaTable->~TPragmaTable(); }
virtual TIntermAggregate* getAsAggregate() { return this; } virtual TIntermAggregate* getAsAggregate() { return this; }
virtual const TIntermAggregate* getAsAggregate() const { return this; } virtual const TIntermAggregate* getAsAggregate() const { return this; }
virtual void setOperator(TOperator o) { op = o; } virtual void setOperator(TOperator o) { op = o; }
......
...@@ -1613,7 +1613,13 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC ...@@ -1613,7 +1613,13 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable) void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
{ {
assert(!pragmaTable); assert(!pragmaTable);
pragmaTable = new TPragmaTable();
// We allocate this with the thread-pool allocator because the destructors
// for TIntermNode's are never called. When TIntermNodes are no longer
// needed, the pool allocator destroys all memory at once without
// destruction.
void* memory = GetThreadPoolAllocator().allocate(sizeof(TPragmaTable));
pragmaTable = new(memory) TPragmaTable();
*pragmaTable = pTable; *pragmaTable = pTable;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment