summaryrefslogtreecommitdiff
path: root/source/slang/slang-serialize-factory.cpp
blob: 351742e60196258c9035e079e7a8d73b232d10f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// slang-serialize-factory.cpp
#include "slang-serialize-factory.h"

#include "../core/slang-math.h"

#include "slang-ast-builder.h"

#include "slang-ref-object-reflect.h"
#include "slang-ast-reflect.h"

#include "slang-serialize-ast.h"
#include "slang-ref-object-reflect.h"

// Needed for ModuleSerialFilter
// Needed for 'findModuleForDecl'
#include "slang-legalize-types.h"
#include "slang-mangle.h"

namespace Slang {

/* !!!!!!!!!!!!!!!!!!!!!! DefaultSerialObjectFactory !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */

void* DefaultSerialObjectFactory::create(SerialTypeKind typeKind, SerialSubType subType)
{
    switch (typeKind)
    {
        case SerialTypeKind::NodeBase:
        {
            return m_astBuilder->createByNodeType(ASTNodeType(subType));
        }
        case SerialTypeKind::RefObject:
        {
            const ReflectClassInfo* info = SerialRefObjects::getClassInfo(RefObjectType(subType));

            if (info && info->m_createFunc)
            {
                RefObject* obj = reinterpret_cast<RefObject*>(info->m_createFunc(nullptr));
                return _add(obj);
            }
            return nullptr;
        }
        default: break;
    }

    return nullptr;
}

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ModuleSerialFilter  !!!!!!!!!!!!!!!!!!!!!!!!

SerialIndex ModuleSerialFilter::writePointer(SerialWriter* writer, const RefObject* inPtr)
{
    // We don't serialize Module
    if (as<Module>(inPtr))
    {
        writer->setPointerIndex(inPtr, SerialIndex(0));
        return SerialIndex(0);
    }

    // For now for everything else just write it
    return writer->writeObject(inPtr);
}

SerialIndex ModuleSerialFilter::writePointer(SerialWriter* writer, const NodeBase* inPtr)
{
    NodeBase* ptr = const_cast<NodeBase*>(inPtr);
    SLANG_ASSERT(ptr);

    // We don't serialize Scope
    if (as<Scope>(ptr))
    {
        writer->setPointerIndex(inPtr, SerialIndex(0));
        return SerialIndex(0);
    }

    if (Decl* decl = as<Decl>(ptr))
    {
        ModuleDecl* moduleDecl = findModuleForDecl(decl);
        if (moduleDecl && moduleDecl != m_moduleDecl)
        {
            ASTBuilder* astBuilder = m_moduleDecl->module->getASTBuilder();

            // It's a reference to a declaration in another module, so first get the symbol name. 
            String mangledName = getMangledName(astBuilder, decl);
            // Add as an import symbol
            return writer->addImportSymbol(mangledName);
        }
        else
        {
            // Okay... we can just write it out then
            return writer->writeObject(ptr);
        }
    }

    // TODO(JS): If I enable this section then the stdlib doesn't work correctly, it appears to be because of
    // `addCatchAllIntrinsicDecorationIfNeeded`. If this is enabled when AST is serialized, the 'body' (ie Stmt)
    // will not be serialized. When serialized back in, it will appear to be a function without a body.
    // In that case `addCatchAllIntrinsicDecorationIfNeeded` will add an intrinsic which in some cases is incorrect.
    // This happens during lowering. 
    //
    // So it seems the fix is for some other mechanism. Another solution is perhaps to run something like `addCatchAllIntrinsicDecorationIfNeeded`
    // on the stdlib after compilation, and before serialization. Then removing it from lowering.

#if 0
    // TODO(JS): What we really want to do here is to ignore bodies functions.
    // It's not 100% clear if this is even right though - for example does type inference
    // imply the body is needed to say infer a return type?
    // Also not clear if statements in other scenarios (if there are others) might need to be kept.
    //
    // For now we just ignore all stmts

    // TODO(yong): We should by default serialize everything. The logic to skip bodies need to be
    // behind a option flag.
    if (Stmt* stmt = as<Stmt>(ptr))
    {
        //
        writer->setPointerIndex(stmt, SerialIndex(0));
        return SerialIndex(0);
    }
#endif

    // For now for everything else just write it
    return writer->writeObject(ptr);
}

/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SerialClassesUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */

/* static */SlangResult SerialClassesUtil::addSerialClasses(SerialClasses* serialClasses)
{
    ASTSerialUtil::addSerialClasses(serialClasses);
    SerialRefObjects::addSerialClasses(serialClasses);

    // Check if it seems ok
    SLANG_ASSERT(serialClasses->isOk());

    return SLANG_OK;
}

/* static */SlangResult SerialClassesUtil::create(RefPtr<SerialClasses>& out)
{
    RefPtr<SerialClasses> classes(new SerialClasses);
    SLANG_RETURN_ON_FAIL(addSerialClasses(classes));

    out = classes;
    return SLANG_OK;
}

} // namespace Slang