summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-target-program.cpp
blob: d7e7a73bb0058945c085fe000b13b534112a82ea (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
// slang-target-program.cpp
#include "slang-target-program.h"

#include "slang-compiler.h"
#include "slang-type-layout.h"

namespace Slang
{

//
// TargetProgram
//

TargetProgram::TargetProgram(ComponentType* componentType, TargetRequest* targetReq)
    : m_program(componentType), m_targetReq(targetReq)
{
    m_entryPointResults.setCount(componentType->getEntryPointCount());
    m_optionSet.overrideWith(m_program->getOptionSet());
    m_optionSet.inheritFrom(targetReq->getOptionSet());
}

IArtifact* TargetProgram::_createWholeProgramResult(
    DiagnosticSink* sink,
    EndToEndCompileRequest* endToEndReq)
{
    // We want to call `emitEntryPoints` function to generate code that contains
    // all the entrypoints defined in `m_program`.
    // The current logic of `emitEntryPoints` takes a list of entry-point indices to
    // emit code for, so we construct such a list first.
    List<Int> entryPointIndices;

    m_entryPointResults.setCount(m_program->getEntryPointCount());
    entryPointIndices.setCount(m_program->getEntryPointCount());
    for (Index i = 0; i < entryPointIndices.getCount(); i++)
        entryPointIndices[i] = i;

    CodeGenContext::Shared sharedCodeGenContext(this, entryPointIndices, sink, endToEndReq);
    CodeGenContext codeGenContext(&sharedCodeGenContext);

    if (SLANG_FAILED(codeGenContext.emitEntryPoints(m_wholeProgramResult)))
    {
        return nullptr;
    }

    return m_wholeProgramResult;
}

IArtifact* TargetProgram::_createEntryPointResult(
    Int entryPointIndex,
    DiagnosticSink* sink,
    EndToEndCompileRequest* endToEndReq)
{
    // It is possible that entry points got added to the `Program`
    // *after* we created this `TargetProgram`, so there might be
    // a request for an entry point that we didn't allocate space for.
    //
    // TODO: Change the construction logic so that a `Program` is
    // constructed all at once rather than incrementally, to avoid
    // this problem.
    //
    if (entryPointIndex >= m_entryPointResults.getCount())
        m_entryPointResults.setCount(entryPointIndex + 1);


    CodeGenContext::EntryPointIndices entryPointIndices;
    entryPointIndices.add(entryPointIndex);

    CodeGenContext::Shared sharedCodeGenContext(this, entryPointIndices, sink, endToEndReq);
    CodeGenContext codeGenContext(&sharedCodeGenContext);

    codeGenContext.emitEntryPoints(m_entryPointResults[entryPointIndex]);

    return m_entryPointResults[entryPointIndex];
}

IArtifact* TargetProgram::getOrCreateWholeProgramResult(DiagnosticSink* sink)
{
    if (m_wholeProgramResult)
        return m_wholeProgramResult;

    // If we haven't yet computed a layout for this target
    // program, we need to make sure that is done before
    // code generation.
    //
    if (!getOrCreateIRModuleForLayout(sink))
    {
        return nullptr;
    }

    return _createWholeProgramResult(sink);
}

IArtifact* TargetProgram::getOrCreateEntryPointResult(Int entryPointIndex, DiagnosticSink* sink)
{
    if (entryPointIndex >= m_entryPointResults.getCount())
        m_entryPointResults.setCount(entryPointIndex + 1);

    if (IArtifact* artifact = m_entryPointResults[entryPointIndex])
        return artifact;

    try
    {
        // If we haven't yet computed a layout for this target
        // program, we need to make sure that is done before
        // code generation.
        //
        if (!getOrCreateIRModuleForLayout(sink))
        {
            return nullptr;
        }

        return _createEntryPointResult(entryPointIndex, sink);
    }
    catch (const Exception& e)
    {
        sink->diagnose(
            SourceLoc(),
            Diagnostics::compilationAbortedDueToException,
            typeid(e).name(),
            e.Message);
        return nullptr;
    }
}

} // namespace Slang