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