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
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)) {
136 .put(construct.file, new ArrayList<CodeAddition>());
138 codeAdditions.get(construct.file).add(addition);
141 // Don't forget to rename the interface
142 CodeVariables.renameInterface(_semantics, construct);
145 private void potentialCPDefine2Code(PotentialCPDefineConstruct construct) {
146 int lineNum = construct.beginLineNum;
147 ArrayList<String> newCode = CodeVariables.generatePotentialCPDefine(
148 _semantics, construct);
150 CodeAddition addition = new CodeAddition(lineNum, newCode);
151 if (!codeAdditions.containsKey(construct.file)) {
152 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
154 codeAdditions.get(construct.file).add(addition);
157 private void CPDefine2Code(CPDefineConstruct construct) {
158 int lineNum = construct.beginLineNum;
159 ArrayList<String> newCode = CodeVariables.generateCPDefine(_semantics,
162 CodeAddition addition = new CodeAddition(lineNum, newCode);
163 if (!codeAdditions.containsKey(construct.file)) {
164 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
166 codeAdditions.get(construct.file).add(addition);
169 private void CPDefineCheck2Code(CPDefineCheckConstruct construct) {
170 int lineNum = construct.beginLineNum;
171 ArrayList<String> newCode = CodeVariables.generateCPDefineCheck(
172 _semantics, construct);
174 CodeAddition addition = new CodeAddition(lineNum, newCode);
175 if (!codeAdditions.containsKey(construct.file)) {
176 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
178 codeAdditions.get(construct.file).add(addition);
181 private void EntryPoint2Code(EntryPointConstruct construct) {
182 int lineNum = construct.beginLineNum;
183 ArrayList<String> newCode = new ArrayList<String>();
184 newCode.addAll(CodeVariables.generateEntryPointInitCall());
186 CodeAddition addition = new CodeAddition(lineNum, newCode);
187 if (!codeAdditions.containsKey(construct.file)) {
188 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
190 codeAdditions.get(construct.file).add(addition);
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();
199 ArrayList<String> newContent = new ArrayList<String>(totalSize);
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)
206 .addAll(content.subList(curSrcLine, addition.lineNum));
207 curSrcLine = addition.lineNum;
209 newContent.addAll(addition.newCode);
211 newContent.addAll(content.subList(curSrcLine, content.size()));
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);
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);
238 for (File file : codeAdditions.keySet()) {
239 ArrayList<CodeAddition> additions = codeAdditions.get(file);
241 if (additions.size() == 0) // Simply do nothing
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,
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);
257 public static void main(String[] argvs) {
258 String homeDir = Environment.HOME_DIRECTORY;
261 // + "/benchmark/linuxrwlocks/linuxrwlocks.c") };
264 // "/benchmark/cliffc-hashtable/simplified_cliffc_hashtable.h"),
266 new File(homeDir + "/benchmark/ms-queue/my_queue.c"),
267 new File(homeDir + "/benchmark/ms-queue/main.c"),
268 new File(homeDir + "/benchmark/ms-queue/my_queue.h") };
270 // new File(homeDir + "/benchmark/read-copy-update/rcu.cc") };
272 // new File(homeDir + "/benchmark/chase-lev-deque-bugfix/deque.c"),
273 // new File(homeDir + "/benchmark/chase-lev-deque-bugfix/main.c"),
274 // new File(homeDir + "/benchmark/chase-lev-deque-bugfix/deque.h") };
276 CodeGenerator gen = new CodeGenerator(srcFiles);