summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/slang-emit-c-like.cpp132
-rw-r--r--source/slang/slang-emit-c-like.h89
2 files changed, 122 insertions, 99 deletions
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index 8e106fe55..522e5ef12 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -31,45 +31,6 @@
namespace Slang {
-// represents a declarator for use in emitting types
-struct CLikeSourceEmitter::EDeclarator
-{
- enum class Flavor
- {
- Name,
- Array,
- UnsizedArray,
- };
- Flavor flavor;
- EDeclarator* next = nullptr;
-
- // Used for `Flavor::name`
- const StringSliceLoc* nameAndLoc;
-
- // Used for `Flavor::Array`
- IRInst* elementCount;
-};
-
-struct CLikeSourceEmitter::IRDeclaratorInfo
-{
- enum class Flavor
- {
- Simple,
- Ptr,
- Array,
- };
-
- Flavor flavor;
- IRDeclaratorInfo* next;
- union
- {
- String const* name;
- IRInst* elementCount;
- };
-};
-
-
-
struct CLikeSourceEmitter::ComputeEmitActionsContext
{
IRInst* moduleInst;
@@ -148,7 +109,7 @@ SlangResult CLikeSourceEmitter::init()
// Types
//
-void CLikeSourceEmitter::emitDeclarator(EDeclarator* declarator)
+void CLikeSourceEmitter::emitDeclarator(DeclaratorInfo* declarator)
{
if (!declarator) return;
@@ -156,23 +117,45 @@ void CLikeSourceEmitter::emitDeclarator(EDeclarator* declarator)
switch (declarator->flavor)
{
- case EDeclarator::Flavor::Name:
- m_writer->emitName(*declarator->nameAndLoc);
+ case DeclaratorInfo::Flavor::Name:
+ {
+ auto nameDeclarator = (NameDeclaratorInfo*)declarator;
+ m_writer->emitName(*nameDeclarator->nameAndLoc);
+ }
break;
- case EDeclarator::Flavor::Array:
- emitDeclarator(declarator->next);
- m_writer->emit("[");
- if(auto elementCount = declarator->elementCount)
+ case DeclaratorInfo::Flavor::SizedArray:
{
- emitVal(elementCount, getInfo(EmitOp::General));
+ auto arrayDeclarator = (SizedArrayDeclaratorInfo*)declarator;
+ emitDeclarator(arrayDeclarator->next);
+ m_writer->emit("[");
+ if(auto elementCount = arrayDeclarator->elementCount)
+ {
+ emitVal(elementCount, getInfo(EmitOp::General));
+ }
+ m_writer->emit("]");
+ }
+ break;
+
+ case DeclaratorInfo::Flavor::UnsizedArray:
+ {
+ auto arrayDeclarator = (UnsizedArrayDeclaratorInfo*)declarator;
+ emitDeclarator(arrayDeclarator->next);
+ m_writer->emit("[]");
}
- m_writer->emit("]");
break;
- case EDeclarator::Flavor::UnsizedArray:
- emitDeclarator(declarator->next);
- m_writer->emit("[]");
+ case DeclaratorInfo::Flavor::Ptr:
+ {
+ // TODO: When there are both pointer and array declarators
+ // as part of a type, paranetheses may be needed in order
+ // to disambiguate between a pointer-to-array and an
+ // array-of-poiners.
+ //
+ auto ptrDeclarator = (PtrDeclaratorInfo*)declarator;
+ m_writer->emit("*");
+ emitDeclarator(ptrDeclarator->next);
+ }
break;
default:
@@ -253,26 +236,19 @@ List<IRWitnessTableEntry*> CLikeSourceEmitter::getSortedWitnessTableEntries(IRWi
return sortedWitnessTableEntries;
}
-void CLikeSourceEmitter::_emitArrayType(IRArrayType* arrayType, EDeclarator* declarator)
+void CLikeSourceEmitter::_emitArrayType(IRArrayType* arrayType, DeclaratorInfo* declarator)
{
- EDeclarator arrayDeclarator;
- arrayDeclarator.flavor = EDeclarator::Flavor::Array;
- arrayDeclarator.next = declarator;
- arrayDeclarator.elementCount = arrayType->getElementCount();
-
+ SizedArrayDeclaratorInfo arrayDeclarator(declarator, arrayType->getElementCount());
_emitType(arrayType->getElementType(), &arrayDeclarator);
}
-void CLikeSourceEmitter::_emitUnsizedArrayType(IRUnsizedArrayType* arrayType, EDeclarator* declarator)
+void CLikeSourceEmitter::_emitUnsizedArrayType(IRUnsizedArrayType* arrayType, DeclaratorInfo* declarator)
{
- EDeclarator arrayDeclarator;
- arrayDeclarator.flavor = EDeclarator::Flavor::UnsizedArray;
- arrayDeclarator.next = declarator;
-
+ UnsizedArrayDeclaratorInfo arrayDeclarator(declarator);
_emitType(arrayType->getElementType(), &arrayDeclarator);
}
-void CLikeSourceEmitter::_emitType(IRType* type, EDeclarator* declarator)
+void CLikeSourceEmitter::_emitType(IRType* type, DeclaratorInfo* declarator)
{
switch (type->getOp())
{
@@ -327,9 +303,7 @@ void CLikeSourceEmitter::emitTypeImpl(IRType* type, const StringSliceLoc* nameAn
// be done so before the type name appears.
m_writer->advanceToSourceLocationIfValid(nameAndLoc->loc);
- EDeclarator nameDeclarator;
- nameDeclarator.flavor = EDeclarator::Flavor::Name;
- nameDeclarator.nameAndLoc = nameAndLoc;
+ NameDeclaratorInfo nameDeclarator(nameAndLoc);
_emitType(type, &nameDeclarator);
}
else
@@ -777,32 +751,6 @@ String CLikeSourceEmitter::getName(IRInst* inst)
return name;
}
-void CLikeSourceEmitter::emitDeclarator(IRDeclaratorInfo* declarator)
-{
- if(!declarator)
- return;
-
- switch( declarator->flavor )
- {
- case IRDeclaratorInfo::Flavor::Simple:
- m_writer->emit(" ");
- m_writer->emit(*declarator->name);
- break;
-
- case IRDeclaratorInfo::Flavor::Ptr:
- m_writer->emit("*");
- emitDeclarator(declarator->next);
- break;
-
- case IRDeclaratorInfo::Flavor::Array:
- emitDeclarator(declarator->next);
- m_writer->emit("[");
- emitOperand(declarator->elementCount, getInfo(EmitOp::General));
- m_writer->emit("]");
- break;
- }
-}
-
void CLikeSourceEmitter::emitSimpleValueImpl(IRInst* inst)
{
switch(inst->getOp())
diff --git a/source/slang/slang-emit-c-like.h b/source/slang/slang-emit-c-like.h
index a969fa334..1a813b1e5 100644
--- a/source/slang/slang-emit-c-like.h
+++ b/source/slang/slang-emit-c-like.h
@@ -52,8 +52,84 @@ public:
kESemanticMask_Default = kESemanticMask_NoPackOffset,
};
- struct IRDeclaratorInfo;
- struct EDeclarator;
+ /// A C-style declarator, used for emitting types and declarations.
+ ///
+ /// A C-style declaration typically has a *type specifier* (like
+ /// `int` or `MyType`) and a *declarator* (like `myVar` or
+ /// `myArray[]` or `*myPtr`).
+ ///
+ /// The type of a declaration depends on both the type specifier
+ /// the declarator, and we already have logic to "unwrap" the
+ /// syntax of a declarator as part of the parser.
+ ///
+ /// A `DeclaratorInfo` is used for the inverse process: taking
+ /// a complete type and splitting out the parts that need to be
+ /// handled as declarators when emitting code in a C-like language.
+ ///
+ struct DeclaratorInfo
+ {
+ public:
+ enum class Flavor
+ {
+ Name,
+ Ptr,
+ SizedArray,
+ UnsizedArray,
+ };
+ Flavor flavor;
+
+ protected:
+ DeclaratorInfo(Flavor flavor)
+ : flavor(flavor)
+ {}
+ };
+
+ /// A simple declarator that only includes a name
+ struct NameDeclaratorInfo : DeclaratorInfo
+ {
+ const StringSliceLoc* nameAndLoc;
+
+ NameDeclaratorInfo(StringSliceLoc const* nameAndLoc)
+ : DeclaratorInfo(Flavor::Name), nameAndLoc(nameAndLoc)
+ {}
+ };
+
+ /// A "chained" declarator that may a nested declarator.
+ struct ChainedDeclaratorInfo : DeclaratorInfo
+ {
+ DeclaratorInfo* next = nullptr;
+
+ protected:
+ ChainedDeclaratorInfo(Flavor flavor, DeclaratorInfo* next)
+ : DeclaratorInfo(flavor)
+ , next(next)
+ {}
+ };
+
+ struct PtrDeclaratorInfo : ChainedDeclaratorInfo
+ {
+ PtrDeclaratorInfo(DeclaratorInfo* next)
+ : ChainedDeclaratorInfo(Flavor::Ptr, next)
+ {}
+ };
+
+ struct SizedArrayDeclaratorInfo : ChainedDeclaratorInfo
+ {
+ IRInst* elementCount;
+
+ SizedArrayDeclaratorInfo(DeclaratorInfo* next, IRInst* elementCount)
+ : ChainedDeclaratorInfo(Flavor::SizedArray, next)
+ , elementCount(elementCount)
+ {}
+ };
+
+ struct UnsizedArrayDeclaratorInfo : ChainedDeclaratorInfo
+ {
+ UnsizedArrayDeclaratorInfo(DeclaratorInfo* next)
+ : ChainedDeclaratorInfo(Flavor::UnsizedArray, next)
+ {}
+ };
+
struct ComputeEmitActionsContext;
// An action to be performed during code emit.
@@ -120,7 +196,7 @@ public:
// Types
//
- void emitDeclarator(EDeclarator* declarator);
+ void emitDeclarator(DeclaratorInfo* declarator);
void emitType(IRType* type, const StringSliceLoc* nameLoc) { emitTypeImpl(type, nameLoc); }
void emitType(IRType* type, Name* name);
@@ -164,7 +240,6 @@ public:
String getName(IRInst* inst);
- void emitDeclarator(IRDeclaratorInfo* declarator);
void emitSimpleValue(IRInst* inst) { emitSimpleValueImpl(inst); }
bool shouldFoldInstIntoUseSites(IRInst* inst);
@@ -374,9 +449,9 @@ public:
virtual void emitPostKeywordTypeAttributesImpl(IRInst* inst) { SLANG_UNUSED(inst); }
- void _emitArrayType(IRArrayType* arrayType, EDeclarator* declarator);
- void _emitUnsizedArrayType(IRUnsizedArrayType* arrayType, EDeclarator* declarator);
- void _emitType(IRType* type, EDeclarator* declarator);
+ void _emitArrayType(IRArrayType* arrayType, DeclaratorInfo* declarator);
+ void _emitUnsizedArrayType(IRUnsizedArrayType* arrayType, DeclaratorInfo* declarator);
+ void _emitType(IRType* type, DeclaratorInfo* declarator);
void _emitInst(IRInst* inst);
// Emit the argument list (including paranthesis) in a `CallInst`