Revision: 1103
Author:
jo...@lunarg.com
Date: Wed Aug 5 20:31:54 2015 UTC
Log: Metadata: Add a "single-walk" mode and form of metadata, that
allows walking a metadata type node on its own, without walking the LLVM
type tree in parallel.
https://code.google.com/p/lunarglass/source/detail?r=1103
Modified:
/trunk/Backends/GLSL/BottomToGLSL.cpp
/trunk/Core/Backend.h
/trunk/Core/TopBuilder.cpp
/trunk/Core/TopBuilder.h
/trunk/Core/metadata.h
/trunk/Frontends/glslang/GlslangToTopVisitor.cpp
=======================================
--- /trunk/Backends/GLSL/BottomToGLSL.cpp Fri Jul 24 20:27:07 2015 UTC
+++ /trunk/Backends/GLSL/BottomToGLSL.cpp Wed Aug 5 20:31:54 2015 UTC
@@ -304,6 +304,11 @@
{
return UseLogicalIO;
}
+
+ virtual bool useSingleTypeTree()
+ {
+ return false;
+ }
};
//
=======================================
--- /trunk/Core/Backend.h Sun May 31 21:29:58 2015 UTC
+++ /trunk/Core/Backend.h Wed Aug 5 20:31:54 2015 UTC
@@ -374,6 +374,18 @@
{
return false;
}
+
+ // Set this to true to have metadata generated with:
+ //
+ // - A single self-recursive node, the same one used to root IO
nodes,
+ // rather than have the IO root node point to a self-recursive
aggregate node.
+ //
+ // - Enable a single type tree walker through the nodes,
+ // rather than have to walk the nodes and LLVM Type in parallel.
+ virtual bool useSingleTypeTree()
+ {
+ return false;
+ }
protected:
bool decompose[EDiCount];
=======================================
--- /trunk/Core/TopBuilder.cpp Fri Jul 24 20:27:07 2015 UTC
+++ /trunk/Core/TopBuilder.cpp Wed Aug 5 20:31:54 2015 UTC
@@ -2814,5 +2814,12 @@
// we wouldn't need the first test.
return manager->getPrivateManager() &&
manager->getPrivateManager()->getBackEnd()->useLogicalIo();
}
+
+bool Builder::useSingleTypeTree() const
+{
+ // Note: if we knew all users of managers really derived from
PrivateManager,
+ // we wouldn't need the first test.
+ return manager->getPrivateManager() &&
manager->getPrivateManager()->getBackEnd()->useSingleTypeTree();
+}
}; // end gla namespace
=======================================
--- /trunk/Core/TopBuilder.h Thu Jul 9 19:01:49 2015 UTC
+++ /trunk/Core/TopBuilder.h Wed Aug 5 20:31:54 2015 UTC
@@ -477,6 +477,7 @@
void closeLoop();
bool useLogicalIo() const;
+ bool useSingleTypeTree() const;
protected:
bool insertNoPredecessorBlocks; // means to insert blocks
that have no predecessor
=======================================
--- /trunk/Core/metadata.h Fri Jul 24 20:27:07 2015 UTC
+++ /trunk/Core/metadata.h Wed Aug 5 20:31:54 2015 UTC
@@ -58,6 +58,16 @@
// Only the names starting with "!gla." actually appear in the IR, the
other names here are
// for ease of understanding the linkage between the nodes.
//
+// NOTE: There are *two* forms the recursive type-walking metadata can
appear in:
+// - Single-Walk form: A single self-recursive node, the same one used to
root
+// !gla.input/output/uniform nodes. This enables a single type tree
walker
+// through the metadata nodes.
+// - Dual-Walk form: The type is rooted by a !gla.input/output/uniform
node, which
+// points to a recursive !aggregate node. This requires walking the
LLVM type
+// in parallel with walking the metadata nodes.
+// Only one of these forms should be used in a given module.
+//
+// Node forms:
//
// !gla.entrypoint -> { name, EMIoEntrypoint }
// Notes:
@@ -65,17 +75,31 @@
//
// !gla.precision -> { EMdPrecision }
//
-// !gla.input -> { name, EMdInputOutput,
Value*, !typeLayout, !aggregate }
-// !gla.output -> same as above
-// !gla.uniform -> same as above
+// !
gla.io is shorthand for one
of !gla.input, !gla.output, !gla.uniform
+//
+// !
gla.io -> { name, EMdInputOutput, Value*, !typeLayout, !aggregate }
+// This is Dual-Walk form: only of
// Notes:
-// - the name is the name of the object (instance name for a block)
-// - Value* is a proxy for getting the LLVM type
+// - the name is the name of the object (instance-name for a block)
+// * for a block with no instance name, the name here will be
empty ("")
+// - Value* is a proxy for getting the LLVM type of the root of
the type
// - !aggregate is for blocks and structures
-// it's a block when EMdInputOutput is
EMio*Block*, !typeLayout will say how the block is laid out
-// it's a structure when the EMdTypeLayout is EMtlAggregate
+// * it's a block when EMdInputOutput is
EMio*Block*, !typeLayout will say how the block is laid out
+// * it's a structure when the EMdTypeLayout is EMtlAggregate
// - for blocks, the instance name is the name above, while the
interface name is the name in the !aggregate
-// - for a block with no instance name, the name here will be
empty ("")
+//
+// !
gla.io: { instanceName, EMdInputOutput, Value*, !typeLayout,
typeName, !
gla.io, !
gla.io, !
gla.io, ... }
+// This is Single-Walk form
+// - the instanceName is the name of the object instance
(instance-name for a block)
+// * for a block with no instance name, the name here will be
empty ("")
+// - Value* is a proxy for getting the LLVM type of this root or
intermediate type in the tree
+// * this must be looked at to get the current level's
arrayness information
+// - typeName is for block interface name or struct type name
+// * will be empty ("") if this level is not a struct or block
+// * it's a block when EMdInputOutput is
EMio*Block*, !typeLayout will say how the block is laid out
+// * it's a structure when the EMdTypeLayout is EMtlAggregate
+// * the !
gla.io operands are the child members, in order, of
the type
+// - for blocks, the interface name is typeName
//
// !sampler -> { EMdSampler, Value*, EMdSamplerDim, array, shadow,
EMdSamplerBaseType }
// Notes:
@@ -604,7 +628,7 @@
return (EMdSamplerBaseType)constInt->getSExtValue();
}
-// Return the value the integere metadata operand to the named metadata
node.
+// Return the value the integer metadata operand to the named metadata
node.
// Return 0 if the named node is missing, or was there and it's metadata
node was 0 or false.
inline int GetMdNamedInt(llvm::Module& module, const char* name)
{
@@ -627,7 +651,7 @@
public:
Metadata(llvm::LLVMContext& c, llvm::Module* m) : context(c), module(m)
{
- // Pre cache the precision qualifier nodes, there are only 4 to
reuse
+ // cache the precision qualifier nodes, there are only 4 to reuse
for (int i = 0; i < EMpCount; ++i) {
llvm::Value* args[] = {
gla::MakeIntConstant(context, i),
@@ -636,7 +660,7 @@
}
}
- // "input/output/uniform ->" as per comment at top of file
+ // "!gla.input/output/uniform ->" as per comment at top of file
llvm::MDNode* makeMdInputOutput(llvm::StringRef symbolName,
llvm::StringRef sectionName, EMdInputOutput qualifier,
llvm::Value* typeProxy, EMdTypeLayout
layout, EMdPrecision precision, int location,
llvm::MDNode* sampler = 0,
llvm::MDNode* aggregate = 0, int interpMode = -1, EMdBuiltIn builtIn =
EmbNone)
@@ -669,7 +693,26 @@
return md;
}
- // "sampler ->" as per comment at top of file
+ // "!gla.input/output/uniform ->" as per comment at top of file, for
Single-Walk form
+ llvm::MDNode* makeMdSingleTypeIo(llvm::StringRef symbolName, const
char* typeName, EMdInputOutput qualifier,
+ llvm::Value* typeProxy, llvm::MDNode*
layoutMd, llvm::ArrayRef<llvm::MDNode*> members)
+ {
+ llvm::MDNode* md;
+ llvm::SmallVector<llvm::Value*, 10> args;
+ args.push_back(llvm::MDString::get(context, symbolName));
+ args.push_back(gla::MakeIntConstant(context, qualifier));
+ args.push_back(typeProxy);
+ args.push_back(layoutMd);
+ args.push_back(llvm::MDString::get(context, typeName));
+ if (members.size() > 0) {
+ args.append(members.begin(), members.end());
+ }
+ md = llvm::MDNode::get(context, args);
+
+ return md;
+ }
+
+ // "!sampler ->" as per comment at top of file
llvm::MDNode* makeMdSampler(EMdSampler sampler, llvm::Value*
typeProxy, EMdSamplerDim dim, bool isArray, bool isShadow,
EMdSamplerBaseType baseType)
{
llvm::Value* args[] = {
=======================================
--- /trunk/Frontends/glslang/GlslangToTopVisitor.cpp Wed Aug 5 01:35:14
2015 UTC
+++ /trunk/Frontends/glslang/GlslangToTopVisitor.cpp Wed Aug 5 20:31:54
2015 UTC
@@ -118,10 +118,11 @@
int assignSlot(glslang::TIntermSymbol* node, bool input, int&
numSlots);
llvm::Value* getSymbolStorage(const glslang::TIntermSymbol* node,
bool& firstTime);
llvm::Constant* createLLVMConstant(const glslang::TType& type, const
glslang::TConstUnionArray&, int& nextConst);
- llvm::Value* MakePermanentTypeProxy(llvm::Value*);
+ llvm::Value* MakePermanentTypeProxy(llvm::Type*, llvm::StringRef name);
llvm::MDNode* declareUniformMetadata(glslang::TIntermSymbol* node,
llvm::Value*);
- llvm::MDNode* declareMdIo(llvm::StringRef symbolName, const
glslang::TType&, llvm::Value*, int slot, const char* kind);
- llvm::MDNode* makeMdSampler(const glslang::TType&, llvm::Value*);
+ llvm::MDNode* declareMdIo(llvm::StringRef symbolName, const
glslang::TType&, llvm::Type* proxyType, llvm::StringRef proxyName, int
slot, const char* kind = nullptr);
+ void declareChildMdIo(const glslang::TType& type, llvm::Type*
proxyType, llvm::SmallVector<llvm::MDNode*, 10>& members);
+ llvm::MDNode* makeMdSampler(const glslang::TType&, llvm::Type*,
llvm::StringRef name);
llvm::MDNode* declareMdType(const glslang::TType&);
void setOutputMetadata(glslang::TIntermSymbol* node, llvm::Value*, int
slot, int numSlots);
llvm::MDNode* makeInputMetadata(glslang::TIntermSymbol* node,
llvm::Value*, int slot);
@@ -2845,31 +2846,30 @@
return glaBuilder->getConstant(llvmConsts, type);
}
-llvm::Value* TGlslangToTopTraverser::MakePermanentTypeProxy(llvm::Value*
value)
+llvm::Value* TGlslangToTopTraverser::MakePermanentTypeProxy(llvm::Type*
type, llvm::StringRef name)
{
// Make a type proxy that won't be optimized away (we still want the
real llvm::Value to get optimized away when it can)
- llvm::Type* type = value->getType();
while (type->getTypeID() == llvm::Type::PointerTyID)
type =
llvm::dyn_cast<llvm::PointerType>(type)->getContainedType(0);
// Don't hook this global into the module, that will cause LLVM to
optimize it away.
- llvm::Value* typeProxy = new llvm::GlobalVariable(type, true,
llvm::GlobalVariable::ExternalLinkage, 0, value->getName() + "_typeProxy");
+ llvm::Value* typeProxy = new llvm::GlobalVariable(type, true,
llvm::GlobalVariable::ExternalLinkage, 0, name + "_typeProxy");
manager.addToFreeList(typeProxy);
return typeProxy;
}
-llvm::MDNode* TGlslangToTopTraverser::makeMdSampler(const glslang::TType&
type, llvm::Value* value)
+llvm::MDNode* TGlslangToTopTraverser::makeMdSampler(const glslang::TType&
type, llvm::Type* llvmType, llvm::StringRef name)
{
// Figure out sampler information, if it's a sampler
if (type.getBasicType() == glslang::EbtSampler) {
- llvm::Value* typeProxy = 0;
- if (! value) {
+ llvm::Value* typeProxy;
+ if (llvmType == nullptr) {
// Don't hook this global into the module, that will cause
LLVM to optimize it away.
typeProxy = new
llvm::GlobalVariable(convertGlslangToGlaType(type), true,
llvm::GlobalVariable::ExternalLinkage, 0, "sampler_typeProxy");
manager.addToFreeList(typeProxy);
} else
- typeProxy = MakePermanentTypeProxy(value);
+ typeProxy = MakePermanentTypeProxy(llvmType, name);
return metadata.makeMdSampler(GetMdSampler(type), typeProxy,
GetMdSamplerDim(type), type.getSampler().arrayed,
type.getSampler().shadow,
GetMdSamplerBaseType(type.getSampler().type));
@@ -2877,11 +2877,11 @@
return 0;
}
-// Make an aggregate, hierarchically, in metadata, recursively, as per
metadata.h.
+// Make a !aggregate, hierarchically, in metadata, recursively, as per
metadata.h.
llvm::MDNode* TGlslangToTopTraverser::declareMdType(const glslang::TType&
type)
{
// Figure out sampler information if it's a sampler
- llvm::MDNode* samplerMd = makeMdSampler(type, 0);
+ llvm::MDNode* samplerMd = makeMdSampler(type, nullptr, "");
std::vector<llvm::Value*> mdArgs;
@@ -2914,10 +2914,10 @@
}
// Make a !gla.uniform/input/output node, as per metadata.h, selected
by "kind"
-llvm::MDNode* TGlslangToTopTraverser::declareMdIo(llvm::StringRef
instanceName, const glslang::TType& type, llvm::Value* value, int slot,
const char* kind)
+llvm::MDNode* TGlslangToTopTraverser::declareMdIo(llvm::StringRef
instanceName, const glslang::TType& type, llvm::Type* proxyType,
llvm::StringRef proxyName,
+ int slot, const char*
kind)
{
- llvm::MDNode* samplerMd = makeMdSampler(type, value);
- llvm::MDNode* aggregate = 0;
+ llvm::MDNode* samplerMd = makeMdSampler(type, proxyType, proxyName);
gla::EInterpolationMode interpolationMode = -1;
int location;
gla::EMdTypeLayout layout = GetMdTypeLayout(type);
@@ -2942,14 +2942,63 @@
break;
}
- // Make hierarchical type information
- if (type.getBasicType() == glslang::EbtStruct || type.getBasicType()
== glslang::EbtBlock)
- aggregate = declareMdType(type);
+ if (glaBuilder->useSingleTypeTree()) {
+ // Make hierarchical type information (a recursive !
gla.io node,
mutually-recursive with the current function)
+ const char* typeName = nullptr;
+ llvm::SmallVector<llvm::MDNode*, 10> members;
+ if (type.getBasicType() == glslang::EbtStruct ||
type.getBasicType() == glslang::EbtBlock) {
+ typeName = type.getTypeName().c_str();
+ declareChildMdIo(type, proxyType, members);
+ }
+
+ // Make the !typeLayout for this level
+ llvm::MDNode* layoutMd = metadata.makeMdTypeLayout(layout,
GetMdPrecision(type), location, samplerMd, interpolationMode,
GetMdBuiltIn(type));
+
+ // Make the !gla.uniform/input/output for this level
+ llvm::MDNode* ioMd = metadata.makeMdSingleTypeIo(instanceName,
typeName, ioType, MakePermanentTypeProxy(proxyType, proxyName), layoutMd,
members);
+
+ // If we're top level (should correspond to having 'kind'), add
this to the right !gla.XXXX list
+ if (kind) {
+ llvm::NamedMDNode* namedNode =
module->getOrInsertNamedMetadata(kind);
+ namedNode->addOperand(ioMd);
+ }
+
+ return ioMd;
+ } else {
+ // Make hierarchical type information (a recursive !aggregate node)
+ llvm::MDNode* aggregate = nullptr;
+ if (type.getBasicType() == glslang::EbtStruct ||
type.getBasicType() == glslang::EbtBlock)
+ aggregate = declareMdType(type);
+
+ // Make the top-level !gla.uniform/input/output node that points
to the recursive !aggregate node
+ return metadata.makeMdInputOutput(instanceName, kind, ioType,
MakePermanentTypeProxy(proxyType, proxyName),
+ layout, GetMdPrecision(type),
location, samplerMd, aggregate,
+ interpolationMode,
GetMdBuiltIn(type));
+ }
+}
+
+// Make a !gla.uniform/input/output child node, as per metadata.h
+void TGlslangToTopTraverser::declareChildMdIo(const glslang::TType& type,
llvm::Type* proxyType, llvm::SmallVector<llvm::MDNode*, 10>& members)
+{
+ const glslang::TTypeList* typeList = type.getStruct();
+ if (typeList) {
+ // Get the llvm type of the struct holding the members (bypassing
arrays and pointers)
+ llvm::Type* structType = proxyType;
+ while (structType->getTypeID() == llvm::Type::PointerTyID ||
+ structType->getTypeID() == llvm::Type::ArrayTyID)
+ structType = structType->getContainedType(0);
- // Make the main node
- return metadata.makeMdInputOutput(instanceName, kind, ioType,
MakePermanentTypeProxy(value),
- layout, GetMdPrecision(type),
location, samplerMd, aggregate,
- interpolationMode,
GetMdBuiltIn(type));
+ int nonHiddenCount = 0;
+ for (int t = 0; t < (int)typeList->size(); ++t) {
+ const glslang::TType* fieldType = (*typeList)[t].type;
+ if (fieldType->hiddenMember())
+ continue;
+ // build a child md node and add it as an argument
+
members.push_back(declareMdIo(fieldType->getFieldName().c_str(),
*fieldType, structType->getContainedType(nonHiddenCount),
fieldType->getFieldName().c_str(),
+ GetMdSlotLocation(type)));
+ ++nonHiddenCount;
+ }
+ }
}
llvm::MDNode*
TGlslangToTopTraverser::declareUniformMetadata(glslang::TIntermSymbol*
node, llvm::Value* value)
@@ -2960,7 +3009,7 @@
if (md)
return md;
- md = declareMdIo(filterMdName(node->getName().c_str()),
node->getType(), value, 0, gla::UniformListMdName);
+ md = declareMdIo(filterMdName(node->getName().c_str()),
node->getType(), value->getType(), value->getName(), 0,
gla::UniformListMdName);
uniformMdMap[name] = md;
if (linkageOnly)
@@ -2973,7 +3022,7 @@
// output-variable cache in the gla builder.
void TGlslangToTopTraverser::setOutputMetadata(glslang::TIntermSymbol*
node, llvm::Value* storage, int slot, int numSlots)
{
- llvm::MDNode* md = declareMdIo(filterMdName(node->getName().c_str()),
node->getType(), storage, slot, gla::OutputListMdName);
+ llvm::MDNode* md = declareMdIo(filterMdName(node->getName().c_str()),
node->getType(), storage->getType(), storage->getName(), slot,
gla::OutputListMdName);
if (node->getQualifier().invariant)
module->getOrInsertNamedMetadata(gla::InvariantListMdName)->addOperand(md);
@@ -2989,7 +3038,7 @@
llvm::MDNode* mdNode = inputMdMap[slot];
if (mdNode == 0) {
// set up metadata for pipeline intrinsic read
- mdNode = declareMdIo(filterMdName(node->getName().c_str()),
node->getType(), value, slot, gla::InputListMdName);
+ mdNode = declareMdIo(filterMdName(node->getName().c_str()),
node->getType(), value->getType(), value->getName(), slot,
gla::InputListMdName);
inputMdMap[slot] = mdNode;
if (linkageOnly)
metadata.addNoStaticUse(mdNode);