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.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;
33 * This class will generate the annotated C code that can run on the current
40 public class CodeGenerator {
41 private SemanticsChecker _semantics;
42 private SpecExtractor _extractor;
44 private File[] srcFiles;
46 private HashMap<File, SourceFileInfo> srcFilesInfo;
48 private HashMap<File, ArrayList<CodeAddition>> codeAdditions;
49 private String homeDir;
51 public CodeGenerator(File[] srcFiles) {
52 this.srcFiles = srcFiles;
53 _extractor = new SpecExtractor();
54 _extractor.extract(srcFiles);
56 this.srcFilesInfo = _extractor.srcFilesInfo;
58 this.codeAdditions = new HashMap<File, ArrayList<CodeAddition>>();
60 _semantics = new SemanticsChecker(_extractor);
63 System.out.println(_semantics);
64 } catch (SemanticsCheckerException e) {
71 * Generate all the global code, including the "@DefineVar" in each
75 private void globalConstruct2Code(GlobalConstruct construct) {
76 ArrayList<String> newCode = CodeVariables.generateGlobalVarDeclaration(
77 _semantics, construct);
78 // Add it to the codeAdditions
79 if (!codeAdditions.containsKey(construct.file)) {
80 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
82 CodeAddition addition = new CodeAddition(construct.beginLineNum,
84 codeAdditions.get(construct.file).add(addition);
85 newCode = CodeVariables.generateStaticVarDefine(_semantics, construct);
86 if (newCode.size() > 0) {
87 addition = new CodeAddition(
88 _semantics.getClassEndConstruct().beginLineNum, newCode);
89 codeAdditions.get(construct.file).add(addition);
93 // Wrap the interface and then renaem it
94 private void interface2Code(InterfaceConstruct construct) {
95 // If there's no define construct for it, we generate the wrapper just
96 // in place without declaration
97 InterfaceDefineConstruct defineConstruct = _semantics.interfaceName2DefineConstruct
99 ArrayList<String> newCode;
101 CodeAddition addition;
102 // Then generate the wrapper if necessary
103 if (defineConstruct != null) { // Need to have a wrapper declaration
104 newCode = CodeVariables.generateInterfaceWrapperDeclaration(
105 _semantics, construct);
106 lineNum = construct.beginLineNum;
107 // Add the wrapper declaration
108 addition = new CodeAddition(lineNum, newCode);
109 if (!codeAdditions.containsKey(construct.file)) {
111 .put(construct.file, new ArrayList<CodeAddition>());
113 codeAdditions.get(construct.file).add(addition);
115 // Add the wrapper definition
116 newCode = CodeVariables.generateInterfaceWrapperDefinition(
117 _semantics, construct);
118 lineNum = defineConstruct.beginLineNum;
119 // Add the wrapper declaration
120 addition = new CodeAddition(lineNum, newCode);
121 if (!codeAdditions.containsKey(defineConstruct.file)) {
122 codeAdditions.put(defineConstruct.file,
123 new ArrayList<CodeAddition>());
125 codeAdditions.get(defineConstruct.file).add(addition);
126 } else { // No declaration needed but should add forward declaration in
128 // Last generate the definition
129 newCode = new ArrayList<String>();
130 if (_semantics.getOption("CLASS") == null) {
131 newCode.addAll(CodeVariables
132 .generateInterfaceWrapperDeclaration(_semantics,
135 newCode.addAll(CodeVariables.generateInterfaceWrapperDefinition(
136 _semantics, construct));
137 lineNum = construct.beginLineNum;
138 // Add the wrapper declaration
139 addition = new CodeAddition(lineNum, newCode);
140 if (!codeAdditions.containsKey(construct.file)) {
142 .put(construct.file, new ArrayList<CodeAddition>());
144 codeAdditions.get(construct.file).add(addition);
147 // Don't forget to rename the interface
148 CodeVariables.renameInterface(_semantics, construct);
151 private void potentialCPDefine2Code(PotentialCPDefineConstruct construct) {
152 int lineNum = construct.beginLineNum;
153 ArrayList<String> newCode = CodeVariables.generatePotentialCPDefine(
154 _semantics, construct);
156 CodeAddition addition = new CodeAddition(lineNum, newCode);
157 if (!codeAdditions.containsKey(construct.file)) {
158 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
160 codeAdditions.get(construct.file).add(addition);
163 private void CPDefine2Code(CPDefineConstruct construct) {
164 int lineNum = construct.beginLineNum;
165 ArrayList<String> newCode = CodeVariables.generateCPDefine(_semantics,
168 CodeAddition addition = new CodeAddition(lineNum, newCode);
169 if (!codeAdditions.containsKey(construct.file)) {
170 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
172 codeAdditions.get(construct.file).add(addition);
175 private void CPDefineCheck2Code(CPDefineCheckConstruct construct) {
176 int lineNum = construct.beginLineNum;
177 ArrayList<String> newCode = CodeVariables.generateCPDefineCheck(
178 _semantics, construct);
180 CodeAddition addition = new CodeAddition(lineNum, newCode);
181 if (!codeAdditions.containsKey(construct.file)) {
182 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
184 codeAdditions.get(construct.file).add(addition);
188 * private void ClassEnd2Code(ClassEndConstruct construct) { int lineNum =
189 * construct.beginLineNum; ArrayList<String> newCode =
190 * CodeVariables.generateStaticVarDefine(_semantics,
191 * _semantics.getGlobalConstruct());
193 * CodeAddition addition = new CodeAddition(lineNum, newCode); if
194 * (!codeAdditions.containsKey(construct.file)) {
195 * codeAdditions.put(construct.file, new ArrayList<CodeAddition>()); }
196 * codeAdditions.get(construct.file).add(addition); }
199 private void EntryPoint2Code(EntryPointConstruct construct) {
200 int lineNum = construct.beginLineNum;
201 ArrayList<String> newCode = new ArrayList<String>();
202 newCode.addAll(CodeVariables.generateEntryPointInitCall());
204 CodeAddition addition = new CodeAddition(lineNum, newCode);
205 if (!codeAdditions.containsKey(construct.file)) {
206 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
208 codeAdditions.get(construct.file).add(addition);
211 private ArrayList<String> insertAnnotation2Src(
212 ArrayList<CodeAddition> additions, ArrayList<String> content) {
213 int totalSize = content.size();
214 for (int i = 0; i < additions.size(); i++) {
215 totalSize += additions.size();
217 ArrayList<String> newContent = new ArrayList<String>(totalSize);
219 for (int i = 0; i < additions.size(); i++) {
220 CodeAddition addition = additions.get(i);
221 if (curSrcLine < addition.lineNum) {
222 // Be careful, subList is the interval [begin, end)
224 .addAll(content.subList(curSrcLine, addition.lineNum));
225 curSrcLine = addition.lineNum;
227 newContent.addAll(addition.newCode);
229 newContent.addAll(content.subList(curSrcLine, content.size()));
233 public void generateCode() {
234 for (int i = 0; i < _semantics.constructs.size(); i++) {
235 Construct construct = _semantics.constructs.get(i);
236 if (construct instanceof GlobalConstruct) {
237 globalConstruct2Code((GlobalConstruct) construct);
238 } else if (construct instanceof InterfaceConstruct) {
239 interface2Code((InterfaceConstruct) construct);
240 } else if (construct instanceof PotentialCPDefineConstruct) {
241 potentialCPDefine2Code((PotentialCPDefineConstruct) construct);
242 } else if (construct instanceof CPDefineConstruct) {
243 CPDefine2Code((CPDefineConstruct) construct);
244 } else if (construct instanceof CPDefineCheckConstruct) {
245 CPDefineCheck2Code((CPDefineCheckConstruct) construct);
246 } else if (construct instanceof EntryPointConstruct) {
247 EntryPoint2Code((EntryPointConstruct) construct);
251 // ClassEndConstruct endConstruct = _semantics.getClassEndConstruct();
252 // if (endConstruct != null) {
253 // ClassEnd2Code(endConstruct);
256 // Sort code additions
257 for (File file : codeAdditions.keySet()) {
258 ArrayList<CodeAddition> additions = codeAdditions.get(file);
260 if (additions.size() == 0) // Simply do nothing
262 ArrayList<String> content = _semantics.srcFilesInfo.get(file).content;
263 Collections.sort(additions, CodeAddition.lineNumComparator);
264 // Insert generated annotation to the source files
265 ArrayList<String> newContent = insertAnnotation2Src(additions,
267 // Write it back to file
268 ParserUtils.write2File(file, newContent);
272 public static void main(String[] argvs) {
273 String homeDir = Environment.HOME_DIRECTORY;
275 File[] srcLinuxRWLocks = { new File(homeDir
276 + "/benchmark/linuxrwlocks/linuxrwlocks.c") };
278 File[] srcHashtable = {
280 + "/benchmark/cliffc-hashtable/cliffc_hashtable.h"),
281 new File(homeDir + "/benchmark/cliffc-hashtable/main.cc") };
283 File[] srcMSQueue = {
284 new File(homeDir + "/benchmark/ms-queue/my_queue.c"),
285 new File(homeDir + "/benchmark/ms-queue/main.c"),
286 new File(homeDir + "/benchmark/ms-queue/my_queue.h") };
288 File[] srcRCU = { new File(homeDir
289 + "/benchmark/read-copy-update/rcu.cc") };
292 new File(homeDir + "/benchmark/chase-lev-deque-bugfix/deque.c"),
293 new File(homeDir + "/benchmark/chase-lev-deque-bugfix/main.c"),
294 new File(homeDir + "/benchmark/chase-lev-deque-bugfix/deque.h") };
296 File[] srcMCSLock = {
297 new File(homeDir + "/benchmark/mcs-lock/mcs-lock.cc"),
298 new File(homeDir + "/benchmark/mcs-lock/mcs-lock.h") };
300 File[] srcSPSCQueue = {
301 new File(homeDir + "/benchmark/spsc-bugfix/spsc-queue.cc"),
302 new File(homeDir + "/benchmark/spsc-bugfix/eventcount.h"),
303 new File(homeDir + "/benchmark/spsc-bugfix/queue.h") };
305 File[] srcMPMCQueue = {
306 new File(homeDir + "/benchmark/mpmc-queue/mpmc-queue.h"),
307 new File(homeDir + "/benchmark/mpmc-queue/mpmc-queue.cc") };
309 File[][] sources = { srcLinuxRWLocks, srcMSQueue, srcRCU,
310 srcDeque, srcMCSLock, srcSPSCQueue, srcMPMCQueue, srcHashtable };
312 // File[][] sources = { srcHashtable, srcMPMCQueue };
313 // Compile all the benchmarks
314 for (int i = 0; i < sources.length; i++) {
315 CodeGenerator gen = new CodeGenerator(sources[i]);