aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/shedlang/compiler/shidtopatio/ShidToPatioTuples.java
blob: cdbe334ca021ba2f1b90d57566eba18fa41efd0e (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
package org.shedlang.compiler.shidtopatio;

import org.shedlang.compiler.patio.instructions.*;
import org.shedlang.compiler.patio.operands.PatioIntConst;
import org.shedlang.compiler.patio.operands.PatioLocalRef;
import org.shedlang.compiler.patio.operands.PatioOperand;
import org.shedlang.compiler.patio.types.PatioDataLayout;
import org.shedlang.compiler.patio.types.PatioDataLayouts;
import org.shedlang.compiler.patio.types.PatioTypes;
import org.shedlang.compiler.sources.Source;
import org.shedlang.compiler.util.Lists;

import java.util.List;

public class ShidToPatioTuples {
    private ShidToPatioTuples() {
    }

    private record TupleRuntimeType(int elementCount) implements RuntimeType {
        @Override
        public PatioDataLayout layout() {
            return ShidToPatioGc.gcObjectDataLayout(PatioDataLayouts.struct(Lists.repeat(
                PatioDataLayouts.INT,
                elementCount
            )));
        }

        private static final List<Integer> GC_CHILDREN_OFFSET =
            ShidToPatioGc.gcObjectOffset(List.of());

        @Override
        public List<Integer> gcChildrenOffset() {
            return GC_CHILDREN_OFFSET;
        }

        @Override
        public int gcChildrenCount() {
            return elementCount;
        }

        public List<Integer> elementOffset(int elementIndex) {
            return ShidToPatioGc.gcObjectOffset(List.of(elementIndex));
        }
    }

    public static ShidToPatioResult<PatioLocalRef> create(
        List<PatioOperand> elements,
        Source source,
        ShidToPatioContext context
    ) {
        var tupleResult = context.allocateVal(
            ShidToPatioLocalSpace.TUPLE,
            ShidToPatioTypes.VALUE_TYPE
        );
        var tuple = tupleResult.value();
        context = tupleResult.context();

        if (elements.size() == 0) {
            context = context.addInstruction(new PatioLocalStore(
                tuple,
                PatioIntConst.of(0),
                source
            ));

            return context.toResult(tuple);
        }

        var tuplePointerResult = context.allocateVal(
            ShidToPatioLocalSpace.TUPLE_POINTER,
            PatioTypes.DATA_PTR
        );
        var tuplePointer = tuplePointerResult.value();
        context = tuplePointerResult.context();

        var tupleRuntimeType = new TupleRuntimeType(elements.size());

        context = ShidToPatioGc.alloc(
            tuplePointer,
            tupleRuntimeType,
            source,
            context
        );

        for (var elementIndex = 0; elementIndex < elements.size(); elementIndex++) {
            var element = elements.get(elementIndex);

            context = context.addInstruction(new PatioMemoryStore(
                tuplePointer,
                tupleRuntimeType.layout(),
                tupleRuntimeType.elementOffset(elementIndex),
                element,
                source
            ));
        }

        context = context.addInstruction(new PatioDataPtrToInt(
            tuple,
            tuplePointer,
            source
        ));

        return context.toResult(tuple);
    }

    public static ShidToPatioResult<PatioLocalRef> get(
        PatioOperand tuple,
        int elementIndex,
        int elementCount,
        Source source,
        ShidToPatioContext context
    ) {
        var tuplePointerResult = context.allocateVal(
            ShidToPatioLocalSpace.TUPLE,
            PatioTypes.DATA_PTR
        );
        var tuplePointer = tuplePointerResult.value();
        context = tuplePointerResult.context();

        context = context.addInstruction(new PatioIntToDataPtr(
            tuplePointer,
            tuple,
            source
        ));

        var destinationResult = context.allocateVal(
            ShidToPatioLocalSpace.TUPLE_ELEMENT,
            Integer.toString(elementIndex),
            ShidToPatioTypes.VALUE_TYPE
        );
        var destination = destinationResult.value();
        context = destinationResult.context();

        var tupleRuntimeType = new TupleRuntimeType(elementCount);

        context = context.addInstruction(new PatioMemoryLoad(
            destination,
            tuplePointer,
            tupleRuntimeType.layout(),
            tupleRuntimeType.elementOffset(elementIndex),
            source
        ));

        return context.toResult(destination);
    }
}