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.Iterator;
13 import edu.uci.eecs.specCompiler.specExtraction.CPDefineCheckConstruct;
14 import edu.uci.eecs.specCompiler.specExtraction.CPDefineConstruct;
15 import edu.uci.eecs.specCompiler.specExtraction.ClassEndConstruct;
16 import edu.uci.eecs.specCompiler.specExtraction.ConditionalInterface;
17 import edu.uci.eecs.specCompiler.specExtraction.Construct;
18 import edu.uci.eecs.specCompiler.specExtraction.EntryPointConstruct;
19 import edu.uci.eecs.specCompiler.specExtraction.GlobalConstruct;
20 import edu.uci.eecs.specCompiler.specExtraction.IDExtractor;
21 import edu.uci.eecs.specCompiler.specExtraction.InterfaceConstruct;
22 import edu.uci.eecs.specCompiler.specExtraction.InterfaceDefineConstruct;
23 import edu.uci.eecs.specCompiler.specExtraction.ParserUtils;
24 import edu.uci.eecs.specCompiler.specExtraction.PotentialCPDefineConstruct;
25 import edu.uci.eecs.specCompiler.specExtraction.SequentialDefineSubConstruct;
26 import edu.uci.eecs.specCompiler.specExtraction.SourceFileInfo;
27 import edu.uci.eecs.specCompiler.specExtraction.SpecExtractor;
31 * This class will generate the annotated C code that can run on the current
38 public class CodeGenerator {
39 private SemanticsChecker _semantics;
40 private SpecExtractor _extractor;
42 private File[] srcFiles;
44 private HashMap<File, SourceFileInfo> srcFilesInfo;
46 private HashMap<File, ArrayList<CodeAddition>> codeAdditions;
48 public CodeGenerator(File[] srcFiles) {
49 this.srcFiles = srcFiles;
50 _extractor = new SpecExtractor();
51 _extractor.extract(srcFiles);
53 this.srcFilesInfo = _extractor.srcFilesInfo;
55 this.codeAdditions = new HashMap<File, ArrayList<CodeAddition>>();
57 _semantics = new SemanticsChecker(_extractor);
60 System.out.println(_semantics);
61 } catch (SemanticsCheckerException e) {
68 * Generate all the global code, including the "@DefineVar" in each
72 private void globalConstruct2Code(GlobalConstruct construct) {
73 ArrayList<String> newCode = CodeVariables.generateGlobalVarDeclaration(
74 _semantics, construct);
75 // Add it to the codeAdditions
76 if (!codeAdditions.containsKey(construct.file)) {
77 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
79 CodeAddition addition = new CodeAddition(construct.beginLineNum,
81 codeAdditions.get(construct.file).add(addition);
82 newCode = CodeVariables.generateStaticVarDefine(_semantics, construct);
83 if (newCode.size() > 0) {
84 addition = new CodeAddition(
85 _semantics.getClassEndConstruct().beginLineNum, newCode);
86 codeAdditions.get(construct.file).add(addition);
90 // Wrap the interface and then renaem it
91 private void interface2Code(InterfaceConstruct construct) {
92 // If there's no define construct for it, we generate the wrapper just
93 // in place without declaration
94 InterfaceDefineConstruct defineConstruct = _semantics.interfaceName2DefineConstruct
96 ArrayList<String> newCode;
98 CodeAddition addition;
99 // Then generate the wrapper if necessary
100 if (defineConstruct != null) { // Need to have a wrapper declaration
101 newCode = CodeVariables.generateInterfaceWrapperDeclaration(
102 _semantics, construct);
103 lineNum = construct.beginLineNum;
104 // Add the wrapper declaration
105 addition = new CodeAddition(lineNum, newCode);
106 if (!codeAdditions.containsKey(construct.file)) {
108 .put(construct.file, new ArrayList<CodeAddition>());
110 codeAdditions.get(construct.file).add(addition);
112 // Add the wrapper definition
113 newCode = CodeVariables.generateInterfaceWrapperDefinition(
114 _semantics, construct);
115 lineNum = defineConstruct.beginLineNum;
116 // Add the wrapper declaration
117 addition = new CodeAddition(lineNum, newCode);
118 if (!codeAdditions.containsKey(defineConstruct.file)) {
119 codeAdditions.put(defineConstruct.file,
120 new ArrayList<CodeAddition>());
122 codeAdditions.get(defineConstruct.file).add(addition);
123 } else { // No declaration needed
124 // Last generate the definition
125 newCode = CodeVariables.generateInterfaceWrapperDefinition(
126 _semantics, construct);
127 lineNum = construct.beginLineNum;
128 // Add the wrapper declaration
129 addition = new CodeAddition(lineNum, newCode);
130 if (!codeAdditions.containsKey(construct.file)) {
132 .put(construct.file, new ArrayList<CodeAddition>());
134 codeAdditions.get(construct.file).add(addition);
137 // Don't forget to rename the interface
138 CodeVariables.renameInterface(_semantics, construct);
141 private void potentialCPDefine2Code(PotentialCPDefineConstruct construct) {
142 int lineNum = construct.beginLineNum;
143 ArrayList<String> newCode = CodeVariables.generatePotentialCPDefine(
144 _semantics, construct);
146 CodeAddition addition = new CodeAddition(lineNum, newCode);
147 if (!codeAdditions.containsKey(construct.file)) {
148 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
150 codeAdditions.get(construct.file).add(addition);
153 private void CPDefine2Code(CPDefineConstruct construct) {
154 int lineNum = construct.beginLineNum;
155 ArrayList<String> newCode = CodeVariables.generateCPDefine(_semantics,
158 CodeAddition addition = new CodeAddition(lineNum, newCode);
159 if (!codeAdditions.containsKey(construct.file)) {
160 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
162 codeAdditions.get(construct.file).add(addition);
165 private void CPDefineCheck2Code(CPDefineCheckConstruct construct) {
166 int lineNum = construct.beginLineNum;
167 ArrayList<String> newCode = CodeVariables.generateCPDefineCheck(
168 _semantics, construct);
170 CodeAddition addition = new CodeAddition(lineNum, newCode);
171 if (!codeAdditions.containsKey(construct.file)) {
172 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
174 codeAdditions.get(construct.file).add(addition);
177 private void EntryPoint2Code(EntryPointConstruct construct) {
178 int lineNum = construct.beginLineNum;
179 ArrayList<String> newCode = new ArrayList<String>();
180 newCode.addAll(CodeVariables.generateEntryPointInitCall());
182 CodeAddition addition = new CodeAddition(lineNum, newCode);
183 if (!codeAdditions.containsKey(construct.file)) {
184 codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
186 codeAdditions.get(construct.file).add(addition);
189 private ArrayList<String> insertAnnotation2Src(
190 ArrayList<CodeAddition> additions, ArrayList<String> content) {
191 int totalSize = content.size();
192 for (int i = 0; i < additions.size(); i++) {
193 totalSize += additions.size();
195 ArrayList<String> newContent = new ArrayList<String>(totalSize);
197 for (int i = 0; i < additions.size(); i++) {
198 CodeAddition addition = additions.get(i);
199 if (curSrcLine < addition.lineNum) {
200 // Be careful, subList is the interval [begin, end)
202 .addAll(content.subList(curSrcLine, addition.lineNum));
203 curSrcLine = addition.lineNum;
205 newContent.addAll(addition.newCode);
207 newContent.addAll(content.subList(curSrcLine, content.size()));
211 public void generateCode() {
212 for (int i = 0; i < _semantics.constructs.size(); i++) {
213 Construct construct = _semantics.constructs.get(i);
214 if (construct instanceof GlobalConstruct) {
215 globalConstruct2Code((GlobalConstruct) construct);
216 } else if (construct instanceof InterfaceConstruct) {
217 interface2Code((InterfaceConstruct) construct);
218 } else if (construct instanceof PotentialCPDefineConstruct) {
219 potentialCPDefine2Code((PotentialCPDefineConstruct) construct);
220 } else if (construct instanceof CPDefineConstruct) {
221 CPDefine2Code((CPDefineConstruct) construct);
222 } else if (construct instanceof CPDefineCheckConstruct) {
223 CPDefineCheck2Code((CPDefineCheckConstruct) construct);
224 } else if (construct instanceof EntryPointConstruct) {
225 EntryPoint2Code((EntryPointConstruct) construct);
228 // Sort code additions
229 for (File file : codeAdditions.keySet()) {
230 ArrayList<CodeAddition> additions = codeAdditions.get(file);
231 if (additions.size() == 0) // Simply do nothing
233 ArrayList<String> content = _semantics.srcFilesInfo.get(file).content;
234 Collections.sort(additions, CodeAddition.lineNumComparator);
235 // Insert generated annotation to the source files
236 ArrayList<String> newContent = insertAnnotation2Src(additions,
238 // Write it back to file
239 ParserUtils.write2File(file, newContent);
244 public static void main(String[] argvs) {
245 String homeDir = Environment.HOME_DIRECTORY;
247 // new File(Environment.MODEL_CHECKER_TEST_DIR +
248 // "/backup_linuxrwlocks.c") };
249 new File(homeDir + "/benchmark/linuxrwlocks/linuxrwlocks.c")
253 // "/benchmark/cliffc-hashtable/simplified_cliffc_hashtable.h"),
255 // new File(homeDir + "/benchmark/ms-queue/my_queue.c"),
256 // new File(homeDir + "/benchmark/ms-queue/main.c"),
257 // new File(homeDir + "/benchmark/ms-queue/my_queue.h") };
258 // new File(homeDir + "/benchmark/test/test.c") };
259 CodeGenerator gen = new CodeGenerator(srcFiles);