changes to mpmc spec and add notes to ms-queue
[cdsspec-compiler.git] / src / edu / uci / eecs / specCompiler / codeGenerator / CodeGenerator.java
1 package edu.uci.eecs.specCompiler.codeGenerator;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.FileNotFoundException;
6 import java.io.FileReader;
7 import java.io.IOException;
8 import java.util.ArrayList;
9 import java.util.Collections;
10 import java.util.HashMap;
11 import java.util.HashSet;
12 import java.util.Iterator;
13
14 import edu.uci.eecs.specCompiler.specExtraction.CPClearConstruct;
15 import edu.uci.eecs.specCompiler.specExtraction.CPDefineCheckConstruct;
16 import edu.uci.eecs.specCompiler.specExtraction.CPDefineConstruct;
17 import edu.uci.eecs.specCompiler.specExtraction.ClassEndConstruct;
18 import edu.uci.eecs.specCompiler.specExtraction.ConditionalInterface;
19 import edu.uci.eecs.specCompiler.specExtraction.Construct;
20 import edu.uci.eecs.specCompiler.specExtraction.EntryPointConstruct;
21 import edu.uci.eecs.specCompiler.specExtraction.FunctionHeader;
22 import edu.uci.eecs.specCompiler.specExtraction.GlobalConstruct;
23 import edu.uci.eecs.specCompiler.specExtraction.IDExtractor;
24 import edu.uci.eecs.specCompiler.specExtraction.InterfaceConstruct;
25 import edu.uci.eecs.specCompiler.specExtraction.InterfaceDefineConstruct;
26 import edu.uci.eecs.specCompiler.specExtraction.ParserUtils;
27 import edu.uci.eecs.specCompiler.specExtraction.PotentialCPDefineConstruct;
28 import edu.uci.eecs.specCompiler.specExtraction.SequentialDefineSubConstruct;
29 import edu.uci.eecs.specCompiler.specExtraction.SourceFileInfo;
30 import edu.uci.eecs.specCompiler.specExtraction.SpecExtractor;
31
32 /**
33  * <p>
34  * This class will generate the annotated C code that can run on the current
35  * model checker.
36  * </p>
37  * 
38  * @author peizhaoo
39  * 
40  */
41 public class CodeGenerator {
42         private SemanticsChecker _semantics;
43         private SpecExtractor _extractor;
44
45         private File[] srcFiles;
46
47         private HashMap<File, SourceFileInfo> srcFilesInfo;
48
49         private HashMap<File, ArrayList<CodeAddition>> codeAdditions;
50         private String homeDir;
51
52         public CodeGenerator(File[] srcFiles) {
53                 this.srcFiles = srcFiles;
54                 _extractor = new SpecExtractor();
55                 _extractor.extract(srcFiles);
56
57                 this.srcFilesInfo = _extractor.srcFilesInfo;
58
59                 this.codeAdditions = new HashMap<File, ArrayList<CodeAddition>>();
60
61                 _semantics = new SemanticsChecker(_extractor);
62                 try {
63                         _semantics.check();
64                         System.out.println(_semantics);
65                 } catch (SemanticsCheckerException e) {
66                         e.printStackTrace();
67                 }
68         }
69
70         /**
71          * <p>
72          * Generate all the global code, including the "@DefineVar" in each
73          * "@Interface" define
74          * </p>
75          */
76         private void globalConstruct2Code(GlobalConstruct construct) {
77                 ArrayList<String> newCode = CodeVariables.generateGlobalVarDeclaration(
78                                 _semantics, construct);
79                 // Add it to the codeAdditions
80                 if (!codeAdditions.containsKey(construct.file)) {
81                         codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
82                 }
83                 CodeAddition addition = new CodeAddition(construct.beginLineNum,
84                                 newCode);
85                 codeAdditions.get(construct.file).add(addition);
86                 newCode = CodeVariables.generateStaticVarDefine(_semantics, construct);
87                 if (newCode.size() > 0) {
88                         addition = new CodeAddition(
89                                         _semantics.getClassEndConstruct().beginLineNum, newCode);
90                         codeAdditions.get(construct.file).add(addition);
91                 }
92         }
93
94         // Wrap the interface and then renaem it
95         private void interface2Code(InterfaceConstruct construct) {
96                 // If there's no define construct for it, we generate the wrapper just
97                 // in place without declaration
98                 InterfaceDefineConstruct defineConstruct = _semantics.interfaceName2DefineConstruct
99                                 .get(construct.name);
100                 ArrayList<String> newCode;
101                 int lineNum;
102                 CodeAddition addition;
103                 // Then generate the wrapper if necessary
104                 if (defineConstruct != null) { // Need to have a wrapper declaration
105                         newCode = CodeVariables.generateInterfaceWrapperDeclaration(
106                                         _semantics, construct);
107                         lineNum = construct.beginLineNum;
108                         // Add the wrapper declaration
109                         addition = new CodeAddition(lineNum, newCode);
110                         if (!codeAdditions.containsKey(construct.file)) {
111                                 codeAdditions
112                                                 .put(construct.file, new ArrayList<CodeAddition>());
113                         }
114                         codeAdditions.get(construct.file).add(addition);
115
116                         // Add the wrapper definition
117                         newCode = CodeVariables.generateInterfaceWrapperDefinition(
118                                         _semantics, construct);
119                         lineNum = defineConstruct.beginLineNum;
120                         // Add the wrapper declaration
121                         addition = new CodeAddition(lineNum, newCode);
122                         if (!codeAdditions.containsKey(defineConstruct.file)) {
123                                 codeAdditions.put(defineConstruct.file,
124                                                 new ArrayList<CodeAddition>());
125                         }
126                         codeAdditions.get(defineConstruct.file).add(addition);
127                 } else { // No declaration needed but should add forward declaration in
128                                         // Class
129                         // Last generate the definition
130                         newCode = new ArrayList<String>();
131                         if (_semantics.getOption("CLASS") == null) {
132                                 newCode.addAll(CodeVariables
133                                                 .generateInterfaceWrapperDeclaration(_semantics,
134                                                                 construct));
135                         }
136                         newCode.addAll(CodeVariables.generateInterfaceWrapperDefinition(
137                                         _semantics, construct));
138                         lineNum = construct.beginLineNum;
139                         // Add the wrapper declaration
140                         addition = new CodeAddition(lineNum, newCode);
141                         if (!codeAdditions.containsKey(construct.file)) {
142                                 codeAdditions
143                                                 .put(construct.file, new ArrayList<CodeAddition>());
144                         }
145                         codeAdditions.get(construct.file).add(addition);
146                 }
147
148                 // Don't forget to rename the interface
149                 CodeVariables.renameInterface(_semantics, construct);
150         }
151
152         private void potentialCPDefine2Code(PotentialCPDefineConstruct construct) {
153                 int lineNum = construct.beginLineNum;
154                 ArrayList<String> newCode = CodeVariables.generatePotentialCPDefine(
155                                 _semantics, construct);
156
157                 CodeAddition addition = new CodeAddition(lineNum, newCode);
158                 if (!codeAdditions.containsKey(construct.file)) {
159                         codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
160                 }
161                 codeAdditions.get(construct.file).add(addition);
162         }
163
164         private void CPDefine2Code(CPDefineConstruct construct) {
165                 int lineNum = construct.beginLineNum;
166                 ArrayList<String> newCode = CodeVariables.generateCPDefine(_semantics,
167                                 construct);
168
169                 CodeAddition addition = new CodeAddition(lineNum, newCode);
170                 if (!codeAdditions.containsKey(construct.file)) {
171                         codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
172                 }
173                 codeAdditions.get(construct.file).add(addition);
174         }
175
176         private void CPDefineCheck2Code(CPDefineCheckConstruct construct) {
177                 int lineNum = construct.beginLineNum;
178                 ArrayList<String> newCode = CodeVariables.generateCPDefineCheck(
179                                 _semantics, construct);
180
181                 CodeAddition addition = new CodeAddition(lineNum, newCode);
182                 if (!codeAdditions.containsKey(construct.file)) {
183                         codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
184                 }
185                 codeAdditions.get(construct.file).add(addition);
186         }
187         
188         private void CPClear2Code(CPClearConstruct construct) {
189                 int lineNum = construct.beginLineNum;
190                 ArrayList<String> newCode = CodeVariables.generateCPClear(
191                                 _semantics, construct);
192
193                 CodeAddition addition = new CodeAddition(lineNum, newCode);
194                 if (!codeAdditions.containsKey(construct.file)) {
195                         codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
196                 }
197                 codeAdditions.get(construct.file).add(addition);
198         }
199         
200
201         /**
202          * private void ClassEnd2Code(ClassEndConstruct construct) { int lineNum =
203          * construct.beginLineNum; ArrayList<String> newCode =
204          * CodeVariables.generateStaticVarDefine(_semantics,
205          * _semantics.getGlobalConstruct());
206          * 
207          * CodeAddition addition = new CodeAddition(lineNum, newCode); if
208          * (!codeAdditions.containsKey(construct.file)) {
209          * codeAdditions.put(construct.file, new ArrayList<CodeAddition>()); }
210          * codeAdditions.get(construct.file).add(addition); }
211          */
212
213         private void EntryPoint2Code(EntryPointConstruct construct) {
214                 int lineNum = construct.beginLineNum;
215                 ArrayList<String> newCode = new ArrayList<String>();
216                 newCode.addAll(CodeVariables.generateEntryPointInitCall());
217
218                 CodeAddition addition = new CodeAddition(lineNum, newCode);
219                 if (!codeAdditions.containsKey(construct.file)) {
220                         codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
221                 }
222                 codeAdditions.get(construct.file).add(addition);
223         }
224
225         private ArrayList<String> insertAnnotation2Src(
226                         ArrayList<CodeAddition> additions, ArrayList<String> content) {
227                 int totalSize = content.size();
228                 for (int i = 0; i < additions.size(); i++) {
229                         totalSize += additions.size();
230                 }
231                 ArrayList<String> newContent = new ArrayList<String>(totalSize);
232                 int curSrcLine = 0;
233                 for (int i = 0; i < additions.size(); i++) {
234                         CodeAddition addition = additions.get(i);
235                         if (curSrcLine < addition.lineNum) {
236                                 // Be careful, subList is the interval [begin, end)
237                                 newContent
238                                                 .addAll(content.subList(curSrcLine, addition.lineNum));
239                                 curSrcLine = addition.lineNum;
240                         }
241                         newContent.addAll(addition.newCode);
242                 }
243                 newContent.addAll(content.subList(curSrcLine, content.size()));
244                 return newContent;
245         }
246
247         public void generateCode() {
248                 for (int i = 0; i < _semantics.constructs.size(); i++) {
249                         Construct construct = _semantics.constructs.get(i);
250                         if (construct instanceof GlobalConstruct) {
251                                 globalConstruct2Code((GlobalConstruct) construct);
252                         } else if (construct instanceof InterfaceConstruct) {
253                                 interface2Code((InterfaceConstruct) construct);
254                         } else if (construct instanceof PotentialCPDefineConstruct) {
255                                 potentialCPDefine2Code((PotentialCPDefineConstruct) construct);
256                         } else if (construct instanceof CPDefineConstruct) {
257                                 CPDefine2Code((CPDefineConstruct) construct);
258                         } else if (construct instanceof CPDefineCheckConstruct) {
259                                 CPDefineCheck2Code((CPDefineCheckConstruct) construct);
260                         } else if (construct instanceof CPClearConstruct) {
261                                 CPClear2Code((CPClearConstruct) construct);
262                         } else if (construct instanceof EntryPointConstruct) {
263                                 EntryPoint2Code((EntryPointConstruct) construct);
264                         }
265                 }
266
267                 // ClassEndConstruct endConstruct = _semantics.getClassEndConstruct();
268                 // if (endConstruct != null) {
269                 // ClassEnd2Code(endConstruct);
270                 // }
271
272                 // Sort code additions
273                 for (File file : codeAdditions.keySet()) {
274                         ArrayList<CodeAddition> additions = codeAdditions.get(file);
275
276                         if (additions.size() == 0) // Simply do nothing
277                                 continue;
278                         ArrayList<String> content = _semantics.srcFilesInfo.get(file).content;
279                         Collections.sort(additions, CodeAddition.lineNumComparator);
280                         // Insert generated annotation to the source files
281                         ArrayList<String> newContent = insertAnnotation2Src(additions,
282                                         content);
283                         // Write it back to file
284                         ParserUtils.write2File(file, newContent);
285                 }
286         }
287
288         public static void main(String[] argvs) {
289                 String homeDir = Environment.HOME_DIRECTORY;
290
291                 File[] srcLinuxRWLocks = { new File(homeDir
292                                 + "/benchmark/linuxrwlocks/linuxrwlocks.c") };
293
294                 File[] srcHashtable = {
295                                 new File(homeDir
296                                                 + "/benchmark/cliffc-hashtable/cliffc_hashtable.h"),
297                                 new File(homeDir + "/benchmark/cliffc-hashtable/main.cc") };
298
299                 File[] srcMSQueue = {
300                                 new File(homeDir + "/benchmark/ms-queue/my_queue.c"),
301                                 new File(homeDir + "/benchmark/ms-queue/testcase.c"),
302                                 new File(homeDir + "/benchmark/ms-queue/testcase1.c"),
303                                 new File(homeDir + "/benchmark/ms-queue/main.c"),
304                                 new File(homeDir + "/benchmark/ms-queue/my_queue.h") };
305
306                 File[] srcRCU = { new File(homeDir
307                                 + "/benchmark/read-copy-update/rcu.cc") };
308
309                 File[] srcDeque = {
310                                 new File(homeDir + "/benchmark/chase-lev-deque-bugfix/deque.c"),
311                                 new File(homeDir + "/benchmark/chase-lev-deque-bugfix/main.c"),
312                                 new File(homeDir + "/benchmark/chase-lev-deque-bugfix/deque.h") };
313
314                 File[] srcMCSLock = {
315                                 new File(homeDir + "/benchmark/mcs-lock/mcs-lock.cc"),
316                                 new File(homeDir + "/benchmark/mcs-lock/mcs-lock.h") };
317
318                 File[] srcSPSCQueue = {
319                                 new File(homeDir + "/benchmark/spsc-bugfix/spsc-queue.cc"),
320                                 new File(homeDir + "/benchmark/spsc-bugfix/eventcount.h"),
321                                 new File(homeDir + "/benchmark/spsc-bugfix/queue.h") };
322
323                 File[] srcMPMCQueue = {
324                                 new File(homeDir + "/benchmark/mpmc-queue/mpmc-queue.h"),
325                                 new File(homeDir + "/benchmark/mpmc-queue/mpmc-queue.cc") };
326 //
327 //              File[][] sources = { srcLinuxRWLocks,  srcMSQueue, srcRCU,
328 //                              srcDeque, srcMCSLock, srcSPSCQueue, srcMPMCQueue, srcHashtable };
329
330                  File[][] sources = {srcMSQueue, srcMPMCQueue };
331                 // Compile all the benchmarks
332                 for (int i = 0; i < sources.length; i++) {
333                         CodeGenerator gen = new CodeGenerator(sources[i]);
334                         gen.generateCode();
335                 }
336         }
337 }