fixed rcu
[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
126                         // Last generate the definition
127                         newCode = new ArrayList<String>();
128                         newCode.addAll(CodeVariables.generateInterfaceWrapperDeclaration(_semantics, construct));
129                         newCode.addAll(CodeVariables.generateInterfaceWrapperDefinition(
130                                         _semantics, construct));
131                         lineNum = construct.beginLineNum;
132                         // Add the wrapper declaration
133                         addition = new CodeAddition(lineNum, newCode);
134                         if (!codeAdditions.containsKey(construct.file)) {
135                                 codeAdditions
136                                                 .put(construct.file, new ArrayList<CodeAddition>());
137                         }
138                         codeAdditions.get(construct.file).add(addition);
139                 }
140
141                 // Don't forget to rename the interface
142                 CodeVariables.renameInterface(_semantics, construct);
143         }
144
145         private void potentialCPDefine2Code(PotentialCPDefineConstruct construct) {
146                 int lineNum = construct.beginLineNum;
147                 ArrayList<String> newCode = CodeVariables.generatePotentialCPDefine(
148                                 _semantics, construct);
149
150                 CodeAddition addition = new CodeAddition(lineNum, newCode);
151                 if (!codeAdditions.containsKey(construct.file)) {
152                         codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
153                 }
154                 codeAdditions.get(construct.file).add(addition);
155         }
156
157         private void CPDefine2Code(CPDefineConstruct construct) {
158                 int lineNum = construct.beginLineNum;
159                 ArrayList<String> newCode = CodeVariables.generateCPDefine(_semantics,
160                                 construct);
161
162                 CodeAddition addition = new CodeAddition(lineNum, newCode);
163                 if (!codeAdditions.containsKey(construct.file)) {
164                         codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
165                 }
166                 codeAdditions.get(construct.file).add(addition);
167         }
168
169         private void CPDefineCheck2Code(CPDefineCheckConstruct construct) {
170                 int lineNum = construct.beginLineNum;
171                 ArrayList<String> newCode = CodeVariables.generateCPDefineCheck(
172                                 _semantics, construct);
173
174                 CodeAddition addition = new CodeAddition(lineNum, newCode);
175                 if (!codeAdditions.containsKey(construct.file)) {
176                         codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
177                 }
178                 codeAdditions.get(construct.file).add(addition);
179         }
180
181         private void EntryPoint2Code(EntryPointConstruct construct) {
182                 int lineNum = construct.beginLineNum;
183                 ArrayList<String> newCode = new ArrayList<String>();
184                 newCode.addAll(CodeVariables.generateEntryPointInitCall());
185
186                 CodeAddition addition = new CodeAddition(lineNum, newCode);
187                 if (!codeAdditions.containsKey(construct.file)) {
188                         codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
189                 }
190                 codeAdditions.get(construct.file).add(addition);
191         }
192
193         private ArrayList<String> insertAnnotation2Src(
194                         ArrayList<CodeAddition> additions, ArrayList<String> content) {
195                 int totalSize = content.size();
196                 for (int i = 0; i < additions.size(); i++) {
197                         totalSize += additions.size();
198                 }
199                 ArrayList<String> newContent = new ArrayList<String>(totalSize);
200                 int curSrcLine = 0;
201                 for (int i = 0; i < additions.size(); i++) {
202                         CodeAddition addition = additions.get(i);
203                         if (curSrcLine < addition.lineNum) {
204                                 // Be careful, subList is the interval [begin, end)
205                                 newContent
206                                                 .addAll(content.subList(curSrcLine, addition.lineNum));
207                                 curSrcLine = addition.lineNum;
208                         }
209                         newContent.addAll(addition.newCode);
210                 }
211                 newContent.addAll(content.subList(curSrcLine, content.size()));
212                 return newContent;
213         }
214
215         public void generateCode() {
216                 for (int i = 0; i < _semantics.constructs.size(); i++) {
217                         Construct construct = _semantics.constructs.get(i);
218                         if (construct instanceof GlobalConstruct) {
219                                 globalConstruct2Code((GlobalConstruct) construct);
220                         } else if (construct instanceof InterfaceConstruct) {
221                                 interface2Code((InterfaceConstruct) construct);
222                         } else if (construct instanceof PotentialCPDefineConstruct) {
223                                 potentialCPDefine2Code((PotentialCPDefineConstruct) construct);
224                         } else if (construct instanceof CPDefineConstruct) {
225                                 CPDefine2Code((CPDefineConstruct) construct);
226                         } else if (construct instanceof CPDefineCheckConstruct) {
227                                 CPDefineCheck2Code((CPDefineCheckConstruct) construct);
228                         } else if (construct instanceof EntryPointConstruct) {
229                                 EntryPoint2Code((EntryPointConstruct) construct);
230                         }
231                 }
232                 // Sort code additions
233                 HashSet<String> headers = CodeVariables.getAllHeaders(_semantics);
234                 ArrayList<String> headerCode = new ArrayList<String>(headers.size());
235                 for (String header : headers) {
236                         headerCode.add("#include " + header);
237                 }
238                 for (File file : codeAdditions.keySet()) {
239                         ArrayList<CodeAddition> additions = codeAdditions.get(file);
240
241                         if (additions.size() == 0) // Simply do nothing
242                                 continue;
243                         ArrayList<String> content = _semantics.srcFilesInfo.get(file).content;
244                         Collections.sort(additions, CodeAddition.lineNumComparator);
245                         // Insert generated annotation to the source files
246                         ArrayList<String> newContent = insertAnnotation2Src(additions,
247                                         content);
248                         ArrayList<String> finalContent = new ArrayList<String>(
249                                         headerCode.size() + newContent.size());
250                         finalContent.addAll(headerCode);
251                         finalContent.addAll(newContent);
252                         // Write it back to file
253                         ParserUtils.write2File(file, finalContent);
254                 }
255
256         }
257
258         public static void main(String[] argvs) {
259                 String homeDir = Environment.HOME_DIRECTORY;
260                 File[] srcFiles = {
261 //                              new File(homeDir
262 //                              + "/benchmark/linuxrwlocks/linuxrwlocks.c") };
263                 // new File(homeDir
264                 // +
265                 // "/benchmark/cliffc-hashtable/simplified_cliffc_hashtable.h"),
266                 // };
267 //               new File(homeDir + "/benchmark/ms-queue/my_queue.c"),
268 //               new File(homeDir + "/benchmark/ms-queue/main.c"),
269 //               new File(homeDir + "/benchmark/ms-queue/my_queue.h") };
270
271                  new File(homeDir + "/benchmark/read-copy-update/rcu.cc") };
272                 CodeGenerator gen = new CodeGenerator(srcFiles);
273                 gen.generateCode();
274         }
275 }