1 package edu.uci.eecs.specCompiler.codeGenerator;
3 import java.io.BufferedReader;
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;
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;
34 * This class will generate the annotated C code that can run on the current
41 public class CodeGenerator {
42 private SemanticsChecker _semantics;
43 private SpecExtractor _extractor;
45 private File[] srcFiles;
47 private HashMap<File, SourceFileInfo> srcFilesInfo;
49 private HashMap<File, ArrayList<CodeAddition>> codeAdditions;
50 private String homeDir;
52 public CodeGenerator(File[] srcFiles) {
53 this.srcFiles = srcFiles;
54 _extractor = new SpecExtractor();
55 _extractor.extract(srcFiles);
57 this.srcFilesInfo = _extractor.srcFilesInfo;
59 this.codeAdditions = new HashMap<File, ArrayList<CodeAddition>>();
61 _semantics = new SemanticsChecker(_extractor);
64 System.out.println(_semantics);
65 } catch (SemanticsCheckerException e) {
72 * Generate all the global code, including the "@DefineVar" in each
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>());
83 CodeAddition addition = new CodeAddition(construct.beginLineNum,
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);
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
100 ArrayList<String> newCode;
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)) {
112 .put(construct.file, new ArrayList<CodeAddition>());
114 codeAdditions.get(construct.file).add(addition);
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>());
126 codeAdditions.get(defineConstruct.file).add(addition);
127 } else { // No declaration needed but should add forward declaration in
129 // Last generate the definition
130 newCode = new ArrayList<String>();
131 if (_semantics.getOption("CLASS") == null) {
132 newCode.addAll(CodeVariables
133 .generateInterfaceWrapperDeclaration(_semantics,
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)) {
143 .put(construct.file, new ArrayList<CodeAddition>());
145 codeAdditions.get(construct.file).add(addition);
148 // Don't forget to rename the interface
149 CodeVariables.renameInterface(_semantics, construct);
152 private void potentialCPDefine2Code(PotentialCPDefineConstruct construct) {
153 int lineNum = construct.beginLineNum;
154 ArrayList<String> newCode = CodeVariables.generatePotentialCPDefine(
155 _semantics, construct);
157 CodeAddition addition = new CodeAddition(lineNum, newCode);
158 if (!codeAdditions.containsKey(construct.file)) {
159 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
161 codeAdditions.get(construct.file).add(addition);
164 private void CPDefine2Code(CPDefineConstruct construct) {
165 int lineNum = construct.beginLineNum;
166 ArrayList<String> newCode = CodeVariables.generateCPDefine(_semantics,
169 CodeAddition addition = new CodeAddition(lineNum, newCode);
170 if (!codeAdditions.containsKey(construct.file)) {
171 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
173 codeAdditions.get(construct.file).add(addition);
176 private void CPDefineCheck2Code(CPDefineCheckConstruct construct) {
177 int lineNum = construct.beginLineNum;
178 ArrayList<String> newCode = CodeVariables.generateCPDefineCheck(
179 _semantics, construct);
181 CodeAddition addition = new CodeAddition(lineNum, newCode);
182 if (!codeAdditions.containsKey(construct.file)) {
183 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
185 codeAdditions.get(construct.file).add(addition);
188 private void CPClear2Code(CPClearConstruct construct) {
189 int lineNum = construct.beginLineNum;
190 ArrayList<String> newCode = CodeVariables.generateCPClear(
191 _semantics, construct);
193 CodeAddition addition = new CodeAddition(lineNum, newCode);
194 if (!codeAdditions.containsKey(construct.file)) {
195 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
197 codeAdditions.get(construct.file).add(addition);
202 * private void ClassEnd2Code(ClassEndConstruct construct) { int lineNum =
203 * construct.beginLineNum; ArrayList<String> newCode =
204 * CodeVariables.generateStaticVarDefine(_semantics,
205 * _semantics.getGlobalConstruct());
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); }
213 private void EntryPoint2Code(EntryPointConstruct construct) {
214 int lineNum = construct.beginLineNum;
215 ArrayList<String> newCode = new ArrayList<String>();
216 newCode.addAll(CodeVariables.generateEntryPointInitCall());
218 CodeAddition addition = new CodeAddition(lineNum, newCode);
219 if (!codeAdditions.containsKey(construct.file)) {
220 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
222 codeAdditions.get(construct.file).add(addition);
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();
231 ArrayList<String> newContent = new ArrayList<String>(totalSize);
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)
238 .addAll(content.subList(curSrcLine, addition.lineNum));
239 curSrcLine = addition.lineNum;
241 newContent.addAll(addition.newCode);
243 newContent.addAll(content.subList(curSrcLine, content.size()));
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);
267 // ClassEndConstruct endConstruct = _semantics.getClassEndConstruct();
268 // if (endConstruct != null) {
269 // ClassEnd2Code(endConstruct);
272 // Sort code additions
273 for (File file : codeAdditions.keySet()) {
274 ArrayList<CodeAddition> additions = codeAdditions.get(file);
276 if (additions.size() == 0) // Simply do nothing
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,
283 // Write it back to file
284 ParserUtils.write2File(file, newContent);
288 public static void main(String[] argvs) {
289 String homeDir = Environment.HOME_DIRECTORY;
291 File[] srcLinuxRWLocks = { new File(homeDir
292 + "/benchmark/linuxrwlocks/linuxrwlocks.c") };
294 File[] srcHashtable = {
296 + "/benchmark/cliffc-hashtable/cliffc_hashtable.h"),
297 new File(homeDir + "/benchmark/cliffc-hashtable/main.cc") };
299 File[] srcMSQueue = {
300 new File(homeDir + "/benchmark/ms-queue/my_queue.c"),
301 new File(homeDir + "/benchmark/ms-queue/main.c"),
302 new File(homeDir + "/benchmark/ms-queue/my_queue.h") };
304 File[] srcRCU = { new File(homeDir
305 + "/benchmark/read-copy-update/rcu.cc") };
308 new File(homeDir + "/benchmark/chase-lev-deque-bugfix/deque.c"),
309 new File(homeDir + "/benchmark/chase-lev-deque-bugfix/main.c"),
310 new File(homeDir + "/benchmark/chase-lev-deque-bugfix/deque.h") };
312 File[] srcMCSLock = {
313 new File(homeDir + "/benchmark/mcs-lock/mcs-lock.cc"),
314 new File(homeDir + "/benchmark/mcs-lock/mcs-lock.h") };
316 File[] srcSPSCQueue = {
317 new File(homeDir + "/benchmark/spsc-bugfix/spsc-queue.cc"),
318 new File(homeDir + "/benchmark/spsc-bugfix/eventcount.h"),
319 new File(homeDir + "/benchmark/spsc-bugfix/queue.h") };
321 File[] srcMPMCQueue = {
322 new File(homeDir + "/benchmark/mpmc-queue/mpmc-queue.h"),
323 new File(homeDir + "/benchmark/mpmc-queue/mpmc-queue.cc") };
325 // File[][] sources = { srcLinuxRWLocks, srcMSQueue, srcRCU,
326 // srcDeque, srcMCSLock, srcSPSCQueue, srcMPMCQueue, srcHashtable };
328 File[][] sources = {srcMSQueue };
329 // Compile all the benchmarks
330 for (int i = 0; i < sources.length; i++) {
331 CodeGenerator gen = new CodeGenerator(sources[i]);