From d6ae67160c33460bf952c9959077dc481a16eca2 Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Tue, 2 Mar 2021 15:46:28 -0800 Subject: Clean up declarator handling during source emit (#1732) This change tidies up some code related to the handling of declarators for the purpose of "unparsing" types into C-like declarations. The big change is that the `EDeclarator` type is changed to `DeclaratorInfo` and now has a bit of a subtype hierarchy under it rather than just using a `union`. The declarations have been moved to the header for CLikeSourceEmitter` so that they can be used by subclasses. I also removed the `IRDeclaratorInfo` type that was being declared but never actually used, and moved the case for pointers from that type into the main `EDeclarator`/`DeclaratorInfo`. --- source/slang/slang-emit-c-like.cpp | 132 +++++++++++-------------------------- source/slang/slang-emit-c-like.h | 89 +++++++++++++++++++++++-- 2 files changed, 122 insertions(+), 99 deletions(-) (limited to 'source') 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 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` -- cgit v1.2.3