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;
50 public CodeGenerator(File[] srcFiles) {
51 this.srcFiles = srcFiles;
52 _extractor = new SpecExtractor();
53 _extractor.extract(srcFiles);
55 this.srcFilesInfo = _extractor.srcFilesInfo;
57 this.codeAdditions = new HashMap<File, ArrayList<CodeAddition>>();
59 _semantics = new SemanticsChecker(_extractor);
62 System.out.println(_semantics);
63 } catch (SemanticsCheckerException e) {
70 * Generate all the global code, including the "@DefineVar" in each
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>());
81 CodeAddition addition = new CodeAddition(construct.beginLineNum,
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);
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
98 ArrayList<String> newCode;
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)) {
110 .put(construct.file, new ArrayList<CodeAddition>());
112 codeAdditions.get(construct.file).add(addition);
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>());
124 codeAdditions.get(defineConstruct.file).add(addition);
125 } else { // No declaration needed but should add forward declaration in
127 // Last generate the definition
128 newCode = new ArrayList<String>();
129 if (_semantics.getOption("CLASS") == null) {
130 newCode.addAll(CodeVariables
131 .generateInterfaceWrapperDeclaration(_semantics,
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)) {
141 .put(construct.file, new ArrayList<CodeAddition>());
143 codeAdditions.get(construct.file).add(addition);
146 // Don't forget to rename the interface
147 CodeVariables.renameInterface(_semantics, construct);
150 private void potentialCPDefine2Code(PotentialCPDefineConstruct construct) {
151 int lineNum = construct.beginLineNum;
152 ArrayList<String> newCode = CodeVariables.generatePotentialCPDefine(
153 _semantics, construct);
155 CodeAddition addition = new CodeAddition(lineNum, newCode);
156 if (!codeAdditions.containsKey(construct.file)) {
157 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
159 codeAdditions.get(construct.file).add(addition);
162 private void CPDefine2Code(CPDefineConstruct construct) {
163 int lineNum = construct.beginLineNum;
164 ArrayList<String> newCode = CodeVariables.generateCPDefine(_semantics,
167 CodeAddition addition = new CodeAddition(lineNum, newCode);
168 if (!codeAdditions.containsKey(construct.file)) {
169 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
171 codeAdditions.get(construct.file).add(addition);
174 private void CPDefineCheck2Code(CPDefineCheckConstruct construct) {
175 int lineNum = construct.beginLineNum;
176 ArrayList<String> newCode = CodeVariables.generateCPDefineCheck(
177 _semantics, construct);
179 CodeAddition addition = new CodeAddition(lineNum, newCode);
180 if (!codeAdditions.containsKey(construct.file)) {
181 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
183 codeAdditions.get(construct.file).add(addition);
187 private void ClassEnd2Code(ClassEndConstruct construct) {
188 int lineNum = construct.beginLineNum;
189 ArrayList<String> newCode = CodeVariables.generateStaticVarDefine(_semantics,
190 _semantics.getGlobalConstruct());
192 CodeAddition addition = new CodeAddition(lineNum, newCode);
193 if (!codeAdditions.containsKey(construct.file)) {
194 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
196 codeAdditions.get(construct.file).add(addition);
200 private void EntryPoint2Code(EntryPointConstruct construct) {
201 int lineNum = construct.beginLineNum;
202 ArrayList<String> newCode = new ArrayList<String>();
203 newCode.addAll(CodeVariables.generateEntryPointInitCall());
205 CodeAddition addition = new CodeAddition(lineNum, newCode);
206 if (!codeAdditions.containsKey(construct.file)) {
207 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
209 codeAdditions.get(construct.file).add(addition);
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();
218 ArrayList<String> newContent = new ArrayList<String>(totalSize);
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)
225 .addAll(content.subList(curSrcLine, addition.lineNum));
226 curSrcLine = addition.lineNum;
228 newContent.addAll(addition.newCode);
230 newContent.addAll(content.subList(curSrcLine, content.size()));
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);
252 // ClassEndConstruct endConstruct = _semantics.getClassEndConstruct();
253 // if (endConstruct != null) {
254 // ClassEnd2Code(endConstruct);
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);
263 for (File file : codeAdditions.keySet()) {
264 ArrayList<CodeAddition> additions = codeAdditions.get(file);
266 if (additions.size() == 0) // Simply do nothing
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,
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);
282 public static void main(String[] argvs) {
283 String homeDir = Environment.HOME_DIRECTORY;
286 // + "/benchmark/linuxrwlocks/linuxrwlocks.c") };
289 // "/benchmark/cliffc-hashtable/simplified_cliffc_hashtable.h"),
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") };
295 // new File(homeDir + "/benchmark/read-copy-update/rcu.cc") };
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") };
304 // new File(homeDir + "/benchmark/mcs-lock/mcs-lock.cc"),
305 // new File(homeDir + "/benchmark/mcs-lock/mcs-lock.h") };
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") };
312 CodeGenerator gen = new CodeGenerator(srcFiles);