1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include "SCBase.h"
24 #include "InitAlloc.h"
25 #include "ByteCodeArray.h"
26 #include "Opcodes.h"
27
28 ByteCodes gCompilingByteCodes;
29 long totalByteCodes = 0;
30
initByteCodes()31 void initByteCodes() {
32 if (gCompilingByteCodes) {
33 freeByteCodes(gCompilingByteCodes);
34 gCompilingByteCodes = nullptr;
35 }
36 }
37
compileOpcode(long opcode,long operand1)38 int compileOpcode(long opcode, long operand1) {
39 int retc;
40 if (operand1 <= 15) {
41 compileByte((opcode << 4) | operand1);
42 retc = 1;
43 } else {
44 compileByte(opcode);
45 compileByte(operand1);
46 if (opcode == opSendMsg || opcode == opSendSpecialMsg || opcode == opSendSuper) {
47 // these expect numKeyArgsPushed to be passed.
48 compileByte(0);
49 }
50 retc = 2;
51 }
52 return retc;
53 }
54
compileJump(long opcode,long jumplen)55 void compileJump(long opcode, long jumplen) {
56 compileByte((opSpecialOpcode << 4) | opcode);
57 compileByte((jumplen >> 8) & 0xFF);
58 compileByte(jumplen & 0xFF);
59 }
60
compileByte(long byte)61 void compileByte(long byte) {
62 if (gCompilingByteCodes == nullptr) {
63 gCompilingByteCodes = allocByteCodes();
64 }
65
66 if ((gCompilingByteCodes->ptr - gCompilingByteCodes->bytes) >= gCompilingByteCodes->size) {
67 reallocByteCodes(gCompilingByteCodes);
68 }
69 totalByteCodes++;
70 *gCompilingByteCodes->ptr++ = byte;
71 }
72
compileNumber(unsigned long value)73 int compileNumber(unsigned long value) {
74 compileByte((value >> 24) & 0xFF);
75 compileByte((value >> 16) & 0xFF);
76 compileByte((value >> 8) & 0xFF);
77 compileByte(value & 0xFF);
78 return 4;
79 }
80
compileNumber24(unsigned long value)81 int compileNumber24(unsigned long value) {
82 compileByte((value >> 16) & 0xFF);
83 compileByte((value >> 8) & 0xFF);
84 compileByte(value & 0xFF);
85 return 4;
86 }
87
compileAndFreeByteCodes(ByteCodes byteCodes)88 void compileAndFreeByteCodes(ByteCodes byteCodes) {
89 compileByteCodes(byteCodes);
90 freeByteCodes(byteCodes);
91 }
92
copyByteCodes(Byte * dest,ByteCodes byteCodes)93 void copyByteCodes(Byte* dest, ByteCodes byteCodes) { memcpy(dest, byteCodes->bytes, byteCodeLength(byteCodes)); }
94
getByteCodes()95 ByteCodes getByteCodes() {
96 ByteCodes curByteCodes;
97
98 curByteCodes = gCompilingByteCodes;
99 gCompilingByteCodes = nullptr;
100
101 return curByteCodes;
102 }
103
saveByteCodeArray()104 ByteCodes saveByteCodeArray() {
105 ByteCodes curByteCodes;
106
107 curByteCodes = gCompilingByteCodes;
108 gCompilingByteCodes = nullptr;
109
110 return curByteCodes;
111 }
112
restoreByteCodeArray(ByteCodes byteCodes)113 void restoreByteCodeArray(ByteCodes byteCodes) { gCompilingByteCodes = byteCodes; }
114
byteCodeLength(ByteCodes byteCodes)115 size_t byteCodeLength(ByteCodes byteCodes) {
116 if (!byteCodes)
117 return 0;
118 return (byteCodes->ptr - byteCodes->bytes);
119 }
120
121 /***********************************************************************
122 *
123 * Internal routines.
124 *
125 ***********************************************************************/
126
compileByteCodes(ByteCodes byteCodes)127 void compileByteCodes(ByteCodes byteCodes) {
128 Byte* ptr;
129 int i;
130
131 if (byteCodes == nullptr)
132 return;
133
134 // postfl("[%d]\n", byteCodes->ptr - byteCodes->bytes);
135 for (i = 0, ptr = byteCodes->bytes; ptr < byteCodes->ptr; ptr++, ++i) {
136 compileByte(*ptr);
137
138 // postfl("%02X ", *ptr);
139 // if ((i & 15) == 15) postfl("\n");
140 }
141 // postfl("\n\n");
142 }
143
allocByteCodes()144 ByteCodes allocByteCodes() {
145 ByteCodes newByteCodes;
146
147 // pyrmalloc: I think that all bytecodes are copied to objects
148 // lifetime: kill after compile
149 newByteCodes = (ByteCodes)pyr_pool_compile->Alloc(sizeof(ByteCodeArray));
150 MEMFAIL(newByteCodes);
151 newByteCodes->bytes = (Byte*)pyr_pool_compile->Alloc(BYTE_CODE_CHUNK_SIZE);
152 MEMFAIL(newByteCodes->bytes);
153 newByteCodes->ptr = newByteCodes->bytes;
154 newByteCodes->size = BYTE_CODE_CHUNK_SIZE;
155 // postfl("allocByteCodes %0X\n", newByteCodes);
156 return newByteCodes;
157 }
158
reallocByteCodes(ByteCodes byteCodes)159 void reallocByteCodes(ByteCodes byteCodes) {
160 Byte* newBytes;
161
162 if (byteCodes->size != (byteCodes->ptr - byteCodes->bytes)) {
163 error("reallocByteCodes called with size != byteCode len");
164 }
165
166 size_t newLen = byteCodes->size << 1;
167 // pyrmalloc: I think that all bytecodes are copied to objects
168 // lifetime: kill after compile
169 newBytes = (Byte*)pyr_pool_compile->Alloc(newLen);
170 MEMFAIL(newBytes);
171 memcpy(newBytes, byteCodes->bytes, byteCodes->size);
172 pyr_pool_compile->Free(byteCodes->bytes);
173
174 byteCodes->bytes = newBytes;
175 byteCodes->ptr = newBytes + byteCodes->size;
176 byteCodes->size = newLen;
177 }
178
179
freeByteCodes(ByteCodes byteCodes)180 void freeByteCodes(ByteCodes byteCodes) {
181 // postfl("freeByteCodes %0X\n", byteCodes);
182 if (byteCodes != nullptr) {
183 pyr_pool_compile->Free(byteCodes->bytes);
184 pyr_pool_compile->Free(byteCodes);
185 }
186 }
187