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.GlobalConstruct;
21 import edu.uci.eecs.specCompiler.specExtraction.IDExtractor;
22 import edu.uci.eecs.specCompiler.specExtraction.InterfaceConstruct;
23 import edu.uci.eecs.specCompiler.specExtraction.InterfaceDefineConstruct;
24 import edu.uci.eecs.specCompiler.specExtraction.ParserUtils;
25 import edu.uci.eecs.specCompiler.specExtraction.PotentialCPDefineConstruct;
26 import edu.uci.eecs.specCompiler.specExtraction.SequentialDefineSubConstruct;
27 import edu.uci.eecs.specCompiler.specExtraction.SourceFileInfo;
28 import edu.uci.eecs.specCompiler.specExtraction.SpecExtractor;
32 * This class will generate the annotated C code that can run on the current
39 public class CodeGenerator {
40 private SemanticsChecker _semantics;
41 private SpecExtractor _extractor;
43 private File[] srcFiles;
45 private HashMap<File, SourceFileInfo> srcFilesInfo;
47 private HashMap<File, ArrayList<CodeAddition>> codeAdditions;
49 public CodeGenerator(File[] srcFiles) {
50 this.srcFiles = srcFiles;
51 _extractor = new SpecExtractor();
52 _extractor.extract(srcFiles);
54 this.srcFilesInfo = _extractor.srcFilesInfo;
56 this.codeAdditions = new HashMap<File, ArrayList<CodeAddition>>();
58 _semantics = new SemanticsChecker(_extractor);
61 System.out.println(_semantics);
62 } catch (SemanticsCheckerException e) {
69 * Generate all the global code, including the "@DefineVar" in each
73 private void globalConstruct2Code(GlobalConstruct construct) {
74 ArrayList<String> newCode = CodeVariables.generateGlobalVarDeclaration(
75 _semantics, construct);
76 // Add it to the codeAdditions
77 if (!codeAdditions.containsKey(construct.file)) {
78 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
80 CodeAddition addition = new CodeAddition(construct.beginLineNum,
82 codeAdditions.get(construct.file).add(addition);
83 newCode = CodeVariables.generateStaticVarDefine(_semantics, construct);
84 if (newCode.size() > 0) {
85 addition = new CodeAddition(
86 _semantics.getClassEndConstruct().beginLineNum, newCode);
87 codeAdditions.get(construct.file).add(addition);
91 // Wrap the interface and then renaem it
92 private void interface2Code(InterfaceConstruct construct) {
93 // If there's no define construct for it, we generate the wrapper just
94 // in place without declaration
95 InterfaceDefineConstruct defineConstruct = _semantics.interfaceName2DefineConstruct
97 ArrayList<String> newCode;
99 CodeAddition addition;
100 // Then generate the wrapper if necessary
101 if (defineConstruct != null) { // Need to have a wrapper declaration
102 newCode = CodeVariables.generateInterfaceWrapperDeclaration(
103 _semantics, construct);
104 lineNum = construct.beginLineNum;
105 // Add the wrapper declaration
106 addition = new CodeAddition(lineNum, newCode);
107 if (!codeAdditions.containsKey(construct.file)) {
109 .put(construct.file, new ArrayList<CodeAddition>());
111 codeAdditions.get(construct.file).add(addition);
113 // Add the wrapper definition
114 newCode = CodeVariables.generateInterfaceWrapperDefinition(
115 _semantics, construct);
116 lineNum = defineConstruct.beginLineNum;
117 // Add the wrapper declaration
118 addition = new CodeAddition(lineNum, newCode);
119 if (!codeAdditions.containsKey(defineConstruct.file)) {
120 codeAdditions.put(defineConstruct.file,
121 new ArrayList<CodeAddition>());
123 codeAdditions.get(defineConstruct.file).add(addition);
124 } else { // No declaration needed
125 // Last generate the definition
126 newCode = CodeVariables.generateInterfaceWrapperDefinition(
127 _semantics, construct);
128 lineNum = construct.beginLineNum;
129 // Add the wrapper declaration
130 addition = new CodeAddition(lineNum, newCode);
131 if (!codeAdditions.containsKey(construct.file)) {
133 .put(construct.file, new ArrayList<CodeAddition>());
135 codeAdditions.get(construct.file).add(addition);
138 // Don't forget to rename the interface
139 CodeVariables.renameInterface(_semantics, construct);
142 private void potentialCPDefine2Code(PotentialCPDefineConstruct construct) {
143 int lineNum = construct.beginLineNum;
144 ArrayList<String> newCode = CodeVariables.generatePotentialCPDefine(
145 _semantics, construct);
147 CodeAddition addition = new CodeAddition(lineNum, newCode);
148 if (!codeAdditions.containsKey(construct.file)) {
149 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
151 codeAdditions.get(construct.file).add(addition);
154 private void CPDefine2Code(CPDefineConstruct construct) {
155 int lineNum = construct.beginLineNum;
156 ArrayList<String> newCode = CodeVariables.generateCPDefine(_semantics,
159 CodeAddition addition = new CodeAddition(lineNum, newCode);
160 if (!codeAdditions.containsKey(construct.file)) {
161 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
163 codeAdditions.get(construct.file).add(addition);
166 private void CPDefineCheck2Code(CPDefineCheckConstruct construct) {
167 int lineNum = construct.beginLineNum;
168 ArrayList<String> newCode = CodeVariables.generateCPDefineCheck(
169 _semantics, construct);
171 CodeAddition addition = new CodeAddition(lineNum, newCode);
172 if (!codeAdditions.containsKey(construct.file)) {
173 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
175 codeAdditions.get(construct.file).add(addition);
178 private void EntryPoint2Code(EntryPointConstruct construct) {
179 int lineNum = construct.beginLineNum;
180 ArrayList<String> newCode = new ArrayList<String>();
181 newCode.addAll(CodeVariables.generateEntryPointInitCall());
183 CodeAddition addition = new CodeAddition(lineNum, newCode);
184 if (!codeAdditions.containsKey(construct.file)) {
185 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
187 codeAdditions.get(construct.file).add(addition);
190 private ArrayList<String> insertAnnotation2Src(
191 ArrayList<CodeAddition> additions, ArrayList<String> content) {
192 int totalSize = content.size();
193 for (int i = 0; i < additions.size(); i++) {
194 totalSize += additions.size();
196 ArrayList<String> newContent = new ArrayList<String>(totalSize);
198 for (int i = 0; i < additions.size(); i++) {
199 CodeAddition addition = additions.get(i);
200 if (curSrcLine < addition.lineNum) {
201 // Be careful, subList is the interval [begin, end)
203 .addAll(content.subList(curSrcLine, addition.lineNum));
204 curSrcLine = addition.lineNum;
206 newContent.addAll(addition.newCode);
208 newContent.addAll(content.subList(curSrcLine, content.size()));
212 public void generateCode() {
213 for (int i = 0; i < _semantics.constructs.size(); i++) {
214 Construct construct = _semantics.constructs.get(i);
215 if (construct instanceof GlobalConstruct) {
216 globalConstruct2Code((GlobalConstruct) construct);
217 } else if (construct instanceof InterfaceConstruct) {
218 interface2Code((InterfaceConstruct) construct);
219 } else if (construct instanceof PotentialCPDefineConstruct) {
220 potentialCPDefine2Code((PotentialCPDefineConstruct) construct);
221 } else if (construct instanceof CPDefineConstruct) {
222 CPDefine2Code((CPDefineConstruct) construct);
223 } else if (construct instanceof CPDefineCheckConstruct) {
224 CPDefineCheck2Code((CPDefineCheckConstruct) construct);
225 } else if (construct instanceof EntryPointConstruct) {
226 EntryPoint2Code((EntryPointConstruct) construct);
229 // Sort code additions
230 HashSet<String> headers = CodeVariables.getAllHeaders(_semantics);
231 ArrayList<String> headerCode = new ArrayList<String>(headers.size());
232 for (String header : headers) {
233 headerCode.add("#include " + header + ";");
235 for (File file : codeAdditions.keySet()) {
236 ArrayList<CodeAddition> additions = codeAdditions.get(file);
238 if (additions.size() == 0) // Simply do nothing
240 ArrayList<String> content = _semantics.srcFilesInfo.get(file).content;
241 Collections.sort(additions, CodeAddition.lineNumComparator);
242 // Insert generated annotation to the source files
243 ArrayList<String> newContent = insertAnnotation2Src(additions,
245 ArrayList<String> finalContent = new ArrayList<String>(headerCode.size() + newContent.size());
246 finalContent.addAll(headerCode);
247 finalContent.addAll(newContent);
248 // Write it back to file
249 ParserUtils.write2File(file, finalContent);
254 public static void main(String[] argvs) {
255 String homeDir = Environment.HOME_DIRECTORY;
257 // new File(Environment.MODEL_CHECKER_TEST_DIR +
258 // "/backup_linuxrwlocks.c") };
259 // new File(homeDir + "/benchmark/linuxrwlocks/linuxrwlocks.c")
263 // "/benchmark/cliffc-hashtable/simplified_cliffc_hashtable.h"),
265 new File(homeDir + "/benchmark/ms-queue/my_queue.c"),
266 new File(homeDir + "/benchmark/ms-queue/main.c"),
267 new File(homeDir + "/benchmark/ms-queue/my_queue.h") };
268 // new File(homeDir + "/benchmark/test/test.c") };
269 CodeGenerator gen = new CodeGenerator(srcFiles);