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