demangler-1.3.2.0: src/Demangler/Structure.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
module Demangler.Structure
where
import Data.List.NonEmpty ( NonEmpty )
import Data.Text ( Text )
import Numeric.Natural
import Demangler.Context
-- | The Demangled data structure holds the demangled name in data-oriented
-- format. This format encodes the various roles and portions of the mangled
-- name in an AST-like structure that closely matches the mangled specification.
-- Unfortunately, this is a relatively messy representation that is not easy to
-- work with, and where things that might seem simple (e.g. the base function
-- name) can be encoded in a number of different ways. Therefore, the details of
-- this structure are not exported and it should either be rendered to printable
-- version via the 'sayable' package or inspected via accessor functions (like
-- 'functionName').
data Demangled = Original Coord
| Encoded Encoding
| VendorExtended Encoding Coord
data Encoding = EncFunc FunctionName (Maybe Type_) (NonEmpty Type_)
| EncStaticFunc FunctionName (Maybe Type_) (NonEmpty Type_)
| EncData Name
| EncSpecial SpecialName
| EncConstStructData UnqualifiedName
-- ^ Const data that is not a builtin data type. Undocumented.
--
-- struct foo { int x; };
-- const struct foo = { 9 };
--
-- or:
--
-- class foo { int x; };
-- const class foo = { 9 };
--
-- Is encoded as _ZLname where name is the size followed by that
-- many characters (e.g. _ZL3foo).
deriving (Eq, Show)
data FunctionName = FunctionName Name
deriving (Eq, Show)
data Name = NameNested NestedName
| UnscopedName UnscopedName
| UnscopedTemplateName Name TemplateArgs
| LocalName Encoding Name (Maybe Discriminator)
| StringLitName Encoding (Maybe Discriminator)
deriving (Eq, Show)
data UnscopedName = UnScName Bool UnqualifiedName -- Bool is "std::" prefix
| UnScSubst Substitution
deriving (Eq, Show)
data NestedName = NestedName Prefix UnqualifiedName
[CVQualifier] (Maybe RefQualifier)
| NestedTemplateName TemplatePrefix TemplateArgs
[CVQualifier] (Maybe RefQualifier)
deriving (Eq, Show)
type FunctionEntity = Coord
-- The Discriminator is simply a non-negative number used to identify a
-- particular instance of a name. It is the rather unusual case for C++ that
-- there may be several distinct functions that have the exact same demangled
-- representation. This can also happen if multiple entities with the same name
-- in different scopes. The Discriminator is used to identify which actual
-- function is being referenced, even though it's not possible to tell which one
-- based on the visible demangled name.
newtype Discriminator = Discriminator Natural
deriving (Eq, Show)
data ModuleName = ModuleName IsPartition SourceName
deriving (Eq, Show)
type IsPartition = Bool
data UnqualifiedName = SourceName SourceName [ABI_Tag]
| OperatorName Operator [ABI_Tag]
| CtorDtorName CtorDtor
| StdSubst Substitution
| ModuleNamed [ModuleName] UnqualifiedName
| UnnamedTypeName (Maybe Natural) -- Nothing = first instance
-- | StructuredBinding ...
deriving (Eq, Show)
newtype SourceName = SrcName Coord
deriving (Eq, Show)
data CtorDtor = CompleteCtor
| BaseCtor
| CompleteAllocatingCtor
| CompleteInheritingCtor Type_
| BaseInheritingCtor Type_
| DeletingDtor
| CompleteDtor
| BaseDtor
deriving (Eq, Show)
data Operator = OpNew
| OpNewArr
| OpDel
| OpDelArr
| OpCoAwait
| OpPositive
| OpNegative
| OpAddress
| OpDeReference
| OpComplement
| OpPlus
| OpMinus
| OpMultiply
| OpDivide
| OpRemainder
| OpAnd
| OpOr
| OpXOR
| OpAssign
| OpAssignPlus
| OpAssignMinus
| OpAssignMul
| OpAssignDiv
| OpAssignRem
| OpAssignAnd
| OpAssignOr
| OpAssignXOR
| OpLeftShift
| OpRightShift
| OpAssignShL
| OpAssignShR
| OpEq
| OpNotEq
| OpLT
| OpGT
| OpLTE
| OpGTE
| OpSpan
| OpNot
| OpLogicalAnd
| OpLogicalOr
| OpPlusPlus
| OpMinusMinus
| OpComma
| OpPointStar
| OpPoint
| OpCall
| OpIndex
| OpQuestion
| OpSizeOfType
| OpSizeOfExpr
| OpAlignOfType
| OpAlignOfExpr
| OpCast Type_
| OpString SourceName
| OpVendor Natural SourceName
deriving (Eq, Show)
data ABI_Tag = ABITag SourceName
deriving (Eq, Show)
data SpecialName = VirtualTable Type_
| TemplateParameterObj TemplateArg
| VTT Type_
| TypeInfo Type_ -- struct
| TypeInfoName Type_
| Thunk CallOffset Encoding
| CtorVTable ()
deriving (Eq, Show)
data CallOffset = VirtualOffset Int Int -- base override, vcall offset
| NonVirtualOffset Int -- base override
deriving (Eq, Show)
data Substitution' = SubsFirst
| Subs Natural -- Note: converted from Base36 in mangled form
| SubsConst Substitution
deriving Show
data Substitution = SubStd -- "std::", a prefix, needing subsequent name
| SubAlloc -- "std::allocator", a prefix, needs template arg
| SubBasicString -- "std::basic_string", needs template args
| SubStdType StdType
deriving (Eq, Show)
data Type_ = BaseType BaseType
| QualifiedType [ExtendedQualifier] [CVQualifier] Type_
| ClassUnionStructEnum Name
| ClassStruct Name
| Union Name
| Enum Name
| Function [CVQualifier] (Maybe ExceptionSpec)
Transaction Bool Type_ (NonEmpty Type_) (Maybe RefQualifier)
| Template TemplateParam TemplateArgs
| Pointer Type_
| LValRef Type_
| RValRef Type_
| ComplexPair Type_
| Imaginary Type_
| Cpp11PackExpansion (NonEmpty Type_)
| StdType StdType
| ArrayType ArrayBound Type_
| DeclType_ DeclType
| PointerToMember Type_ Type_ -- class type, member type
deriving (Eq, Show)
data ArrayBound = NumBound Int
| ExprBound Expression
| NoBounds
deriving (Eq, Show)
data ExceptionSpec = NonThrowing
| ComputedThrow Expression
| Throwing (NonEmpty Type_)
deriving (Eq, Show)
data Transaction = TransactionSafe | TransactionUnsafe
deriving (Eq, Show)
data BaseType = Void | Wchar_t | Bool_
| Char_ | SChar | UChar
| Short | UShort
| Int_ | UInt
| Long | ULong
| LongLong | ULongLong
| Int128 | UInt128
| Float_ | Double_ | LongDouble80 | Float128
| Ellipsis
| IEE754rDecFloat64
| IEE754rDecFloat128
| IEE754rDecFloat32
| IEE754rDecFloat16
| FloatN Natural
| FloatNx Natural
| BFloat16
| SBitInt Natural | UBitInt Natural
| Char32 | Char16 | Char8
| Auto | DeclTypeAuto
| NullPtr
| N1168FixedPointAccum
| N1168FixedPointAccumSat
| N1168FixedPointFract
| N1168FixedPointFractSat
| VendorExtendedType SourceName (Maybe TemplateArgs)
deriving (Eq, Show)
data StdType = BasicStringChar
| BasicIStream
| BasicOStream
| BasicIOStream
deriving (Eq, Show)
-- Qualifiers: there may be 0 or more (as expressed via an array) but there will
-- only be one of each, and they are usually expressed in the order shown here,
-- and printed on the right side of the output they qualify in the reverse order
-- shown here.
data CVQualifier = Restrict | Volatile | Const_
deriving (Eq, Show)
data RefQualifier = Ref | RefRef
deriving (Eq, Show)
type ExtendedQualifier = () -- XXX TBD
data Prefix = PrefixTemplateParam TemplateParam PrefixR
| PrefixDeclType DeclType PrefixR
| PrefixClosure ClosurePrefix -- ??
| Prefix PrefixR
deriving (Eq, Show)
data PrefixR = PrefixUQName UnqualifiedName PrefixR
| PrefixTemplateArgs TemplateArgs PrefixR
| PrefixEnd
deriving (Eq, Show)
pattern EmptyPrefix :: Prefix
pattern EmptyPrefix = Prefix PrefixEnd
data TemplatePrefix = GlobalTemplate (NonEmpty UnqualifiedName)
| NestedTemplate Prefix (NonEmpty UnqualifiedName)
| TemplateTemplateParam TemplateParam
deriving (Eq, Show)
type TemplateName = Name
type TemplateArgs = NonEmpty TemplateArg
data TemplateArg = TArgType Type_
| TArgExpr Expression
| TArgSimpleExpr ExprPrimary
| TArgPack [TemplateArg]
deriving (Eq, Show)
type TemplateParam = TemplateArg
data Expression = ExprUnary Operator Expression
| ExprBinary Operator Expression Expression
| ExprTrinary Operator Expression Expression Expression
| ExprPfxPlus Expression
| ExprPfxMinus Expression
| ExprCall (NonEmpty Expression) -- call target :| [args]
| ExprConvert1 Type_ Expression
| ExprConvertSome Type_ (NonEmpty Expression)
| ExprConvertInit Type_ [BracedExpression]
| ExprBracedInit [BracedExpression]
| ExprNew GlobalScope [Expression] Type_
| ExprNewInit GlobalScope [Expression] Type_ InitializerExpr
| ExprNewArray GlobalScope [Expression] Type_
| ExprNewInitArray GlobalScope [Expression] Type_ InitializerExpr
| ExprDel GlobalScope Expression
| ExprDelArray GlobalScope Expression
| ExprDynamicCast Type_ Expression
| ExprStaticCast Type_ Expression
| ExprConstCast Type_ Expression
| ExprReinterpretCast Type_ Expression
| ExprTypeIdType Type_
| ExprTypeId Expression
| ExprSizeOfType Type_
| ExprSizeOf Expression
| ExprAlignOfType Type_
| ExprAlignOf Expression
| ExprNoException Expression
| ExprTemplateParam TemplateParam
| ExprFunctionParam FunctionParam
| ExprField Expression UnresolvedName
| ExprFieldPtr Expression UnresolvedName
| ExprFieldExpr Expression Expression
| ExprSizeOfTmplParamPack TemplateParam
| ExprSizeOfFuncParamPack FunctionParam
| ExprSizeOfCapturedTmplParamPack [TemplateArg]
| ExprPack Expression
| ExprUnaryLeftFold Operator Expression
| ExprUnaryRightFold Operator Expression
| ExprBinaryLeftFold Operator Expression Expression
| ExprBinaryRightFold Operator Expression Expression
| ExprThrow Expression
| ExprReThrow
| ExprVendorExtended SourceName [TemplateArg]
| ExprUnresolvedName UnresolvedName
| ExprPrim ExprPrimary
deriving (Eq, Show)
type GlobalScope = Bool
data ExprPrimary = IntLit Type_ Int
| FloatLit Type_ Float
| DirectLit Type_ -- String or NullPtr
| NullPtrTemplateArg Type_
| ComplexFloatLit Type_ Float Float
| ExternalNameLit Encoding
deriving (Eq, Show)
data BracedExpression = BracedExpr Expression
| BracedFieldExpr SourceName BracedExpression -- .name = expr
| BracedIndexExpr Expression BracedExpression -- [idx] = expr
| BracedRangedExpr Expression Expression BracedExpression
-- [expr ... expr] = expr
deriving (Eq, Show)
data InitializerExpr = Initializer [Expression]
deriving (Eq, Show)
data FunctionParam = FP_This
| FP_ [CVQualifier] Natural
deriving (Eq, Show)
data UnresolvedName = URN_Base GlobalScope BaseUnresolvedName
| URNScopedRef UnresolvedType BaseUnresolvedName
| URNSubScopedRef UnresolvedType
UnresolvedQualifierLevels BaseUnresolvedName
| URNQualRef GlobalScope
UnresolvedQualifierLevels BaseUnresolvedName
deriving (Eq, Show)
type UnresolvedQualifierLevels = NonEmpty UnresolvedQualifierLevel
data BaseUnresolvedName = BUName SourceName (Maybe TemplateArgs)
| BUOnOperatorT Operator TemplateArgs
| BUOnOperator Operator
| BUDestructorUnresolvedType UnresolvedType
| BUDestructorSimpleId SourceName (Maybe TemplateArgs)
deriving (Eq, Show)
data UnresolvedType = URTTemplate TemplateParam (Maybe TemplateArgs)
| URTDeclType DeclType
| URTSubstPrefix Prefix -- never parsed: subst insertion
deriving (Eq, Show)
data UnresolvedQualifierLevel = URQL SourceName (Maybe TemplateArgs)
deriving (Eq, Show)
type ClosurePrefix = () -- XXX TBD
data DeclType = DeclType Expression
| DeclTypeExpr Expression
deriving (Eq, Show)
-- | Table of builtin types as the internal BaseType representation, followed by
-- a tuple of strings. The first string is the reference to this type in a
-- mangled name. The second string is the C/C++ type name to be used when
-- writing a value cast. The third string, if specified, is a C/C++ suffix that
-- can be written after literal values to indicate the type instead (for example,
-- emit `10ul` instead of `(unsigned long)10`).
builtinTypeTable :: [ (BaseType, (Text, Text, Maybe Text)) ]
builtinTypeTable =
[ (Void, ("v", "void", Nothing))
, (Wchar_t, ("w", "wchar_t", Nothing))
, (Bool_, ("b", "bool", Nothing))
, (Char_, ("c", "char", Nothing))
, (SChar, ("a", "signed char", Nothing))
, (UChar, ("h", "unsigned char", Nothing))
, (Short, ("s", "short", Nothing))
, (UShort, ("t", "unsigned short", Nothing))
, (Int_, ("i", "int", Just ""))
, (UInt, ("j", "unsigned int", Just "u"))
, (Long, ("l", "long", Just "l"))
, (ULong, ("m", "unsigned long", Just "ul"))
, (LongLong, ("x", "long long", Nothing)) -- __int64
, (ULongLong, ("y", "unsigned long long", Nothing)) -- __int64
, (Int128, ("n", "__int128", Nothing))
, (UInt128, ("o", "unsigned __int128", Nothing))
, (Float_, ("f", "float", Nothing))
, (Double_, ("d", "double", Nothing))
, (LongDouble80, ("e", "long double", Nothing)) -- __float80
, (Float128, ("g", "__float128", Nothing))
, (Ellipsis, ("z", "...", Nothing))
, (IEE754rDecFloat64, ("Dd", "__ieeefloat64", Nothing)) -- ??
, (IEE754rDecFloat128, ("De", "__ieeefloat128", Nothing)) -- ??
, (IEE754rDecFloat32, ("Df", "__ieeefloat32", Nothing)) -- ??
, (IEE754rDecFloat16, ("Dh", "__ieeefloat16", Nothing)) -- ??
, (BFloat16, ("DF16b", "std::bfloat16_t", Nothing))
, (Char32, ("Di", "char32_t", Nothing))
, (Char16, ("Ds", "char16_t", Nothing))
, (Char8, ("Du", "char8_t", Nothing))
, (Auto, ("Da", "auto", Nothing))
, (DeclTypeAuto, ("Dc", "decltype(auto)", Nothing)) -- ??
, (NullPtr, ("Dn", "std::nullptr_t", Nothing)) -- decltype(nullptr)
, (N1168FixedPointAccum, ("DA", "T _Accum", Nothing)) -- ??
, (N1168FixedPointAccumSat, ("DS DA", "_Sat T _Accum", Nothing)) -- ??
, (N1168FixedPointFract, ("DR", "T _Fract", Nothing)) -- ??
, (N1168FixedPointFractSat, ("DS DR", "_Sat T _Fract", Nothing)) -- ??
]
data Arity = Unary | Binary | Trinary | NoArity
deriving Eq
opTable :: [ (Operator, (Arity, (Text, Text))) ]
opTable =
[ (OpNew, (NoArity, ("nw", " new")))
, (OpNewArr, (NoArity, ("na", " new[]")))
, (OpDel, (NoArity, ("dl", " delete")))
, (OpDelArr, (NoArity, ("da", " delete[]")))
, (OpCoAwait, (NoArity, ("aw", " co_await")))
, (OpPositive, (Unary, ("ps", "+")))
, (OpNegative, (Unary, ("ng", "-")))
, (OpAddress, (Unary, ("ad", "&")))
, (OpDeReference, (Unary, ("de", "*")))
, (OpComplement, (Unary, ("co", "~")))
, (OpPlus, (Binary, ("pl", "+")))
, (OpMinus, (Binary, ("mi", "-")))
, (OpMultiply, (Binary, ("ml", "*")))
, (OpDivide, (Binary, ("dv", "/")))
, (OpRemainder, (Binary, ("rm", "%")))
, (OpAnd, (Binary, ("an", "&")))
, (OpOr, (Binary, ("or", "|")))
, (OpXOR, (Binary, ("eo", "^")))
, (OpAssign, (Binary, ("aS", "=")))
, (OpAssignPlus, (Binary, ("pL", "+=")))
, (OpAssignMinus, (Binary, ("mI", "-=")))
, (OpAssignMul, (Binary, ("mL", "*=")))
, (OpAssignDiv, (Binary, ("dV", "/=")))
, (OpAssignRem, (Binary, ("rM", "%=")))
, (OpAssignAnd, (Binary, ("aN", "&=")))
, (OpAssignOr, (Binary, ("oR", "|=")))
, (OpAssignXOR, (Binary, ("eO", "^=")))
, (OpLeftShift, (Binary, ("ls", "<<")))
, (OpRightShift, (Binary, ("rs", ">>")))
, (OpAssignShL, (Binary, ("lS", "<<=")))
, (OpAssignShR, (Binary, ("rS", ">>=")))
, (OpEq, (Binary, ("eq", "==")))
, (OpNotEq, (Binary, ("ne", "!=")))
, (OpLT, (Binary, ("lt", "<")))
, (OpGT, (Binary, ("gt", ">")))
, (OpLTE, (Binary, ("le", "<=")))
, (OpGTE, (Binary, ("ge", ">=")))
, (OpSpan, (Binary, ("ss", "<=>")))
, (OpNot, (Unary, ("nt", "!")))
, (OpLogicalAnd, (Binary, ("aa", "&&")))
, (OpLogicalOr, (Binary, ("oo", "||")))
, (OpPlusPlus, (Unary, ("pp", "++")))
, (OpMinusMinus, (Unary, ("mm", "--")))
, (OpComma, (Binary, ("cm", ",")))
, (OpPointStar, (Binary, ("pm", "->*")))
, (OpPoint, (Binary, ("pt", "->")))
, (OpCall, (NoArity, ("cl", "()")))
, (OpIndex, (NoArity, ("ix", "[]")))
, (OpQuestion, (Trinary, ("qu", "?")))
, (OpSizeOfType, (Unary, ("st", " sizeof")))
, (OpAlignOfType, (Unary, ("at", " alignof")))
, (OpSizeOfExpr, (Unary, ("sz", " sizeof")))
, (OpAlignOfExpr, (Unary, ("az", " alignof")))
]
----------------------------------------------------------------------
-- Core data structure utilized by Substitution but which must be defined for
-- other users.
data SubsCandidate = SC_Type Type_
| SC_UQName Bool UnqualifiedName
-- ^ Bool is True for std:: namespace prefix
| SC_Prefix Prefix
| SC_TemplatePrefix TemplatePrefix
| SC_UnresolvedType UnresolvedType
deriving (Eq, Show)