source: trunk/Compiler/Modules/GCC/ProducerGCC.pas

Last change on this file was 77, checked in by chronos, 6 months ago
  • Modified: Compiler targets moved into modules.
File size: 10.7 KB
Line 
1unit ProducerGCC;
2
3interface
4
5uses
6 SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,
7 SourceCodePascal, Producer, StrUtils;
8
9type
10
11 { TProducerGCCC }
12
13 TProducerGCCC = class(TProducer)
14 private
15 function TranslateType(Name: string): string;
16 function TranslateOperator(Name: string): string;
17 procedure Emit(AText: string);
18 procedure EmitLn(AText: string = '');
19 procedure GenerateUses(UsedModules: TUsedModules);
20 procedure GenerateModule(Module: TSourceModule);
21 procedure GenerateCommonBlock(CommonBlock: TCommonBlock;
22 LabelPrefix: string);
23 procedure GenerateType(AType: TType);
24 procedure GenerateTypes(Types: TTypes);
25 procedure GenerateProgram(ProgramBlock: TProgram);
26 procedure GenerateFunctions(Functions: TFunctions;
27 Prefix: string = '');
28 procedure GenerateBeginEnd(BeginEnd: TBeginEnd);
29 procedure GenerateVariableList(VariableList: TVariables);
30 procedure GenerateVariable(Variable: TVariable);
31 procedure GenerateCommand(Command: TCommand);
32 procedure GenerateWhileDo(WhileDo: TWhileDo);
33 procedure GenerateForToDo(ForToDo: TForToDo);
34 procedure GenerateIfThenElse(IfThenElse: TIfThenElse);
35 procedure GenerateAssignment(Assignment: TAssignment);
36 procedure GenerateFunctionCall(FunctionCall: TFunctionCall);
37 function GenerateExpression(Expression: TExpression): string;
38 public
39 TextSource: TStringList;
40 IndentationLength: Integer;
41 Indetation: Integer;
42 procedure AssignToStringList(Target: TStringList); override;
43 procedure Produce(Module: TSourceModule); override;
44 constructor Create;
45 destructor Destroy; override;
46 end;
47
48
49implementation
50
51{ TProducerGCCC }
52
53constructor TProducerGCCC.Create;
54begin
55 TextSource := TStringList.Create;
56 IndentationLength := 2;
57 {$IFDEF Windows}
58 CompilerPath := 'c:\Program Files\MinGW\bin\gcc.exe -o %1:s';
59 {$ENDIF}
60 {$IFDEF Linux}
61 CompilerPath := '/usr/bin/gcc';
62 {$ENDIF}
63end;
64
65destructor TProducerGCCC.Destroy;
66begin
67 FreeAndNil(TextSource);
68 inherited;
69end;
70
71function TProducerGCCC.TranslateType(Name: string): string;
72begin
73 if Name = 'Byte' then Result := 'uint8'
74 else if Name = 'ShortInt' then Result := 'int8'
75 else if Name = 'Word' then Result := 'int16'
76 else if Name = 'SmallInt' then Result := 'int16'
77 else if Name = 'Cardinal' then Result := 'uint32'
78 else if Name = 'Integer' then Result := 'int32'
79 else if Name = 'Void' then Result := 'void'
80 else Result := Name;
81end;
82
83function TProducerGCCC.TranslateOperator(Name: string): string;
84begin
85 if Name = '=' then Result := '=='
86 else if Name = 'shl' then Result := '<<'
87 else if Name = 'shr' then Result := '>>'
88 else if Name = 'not' then Result := '!'
89 else if Name = 'mod' then Result := '^'
90 else if Name = ':=' then Result := '='
91 else if Name = '@' then Result := '*'
92 else if Name = 'and' then Result := '&'
93 else if Name = 'or' then Result := '|'
94 else if Name = 'xor' then Result := '^'
95 else Result := Name;
96end;
97
98procedure TProducerGCCC.EmitLn(AText: string = '');
99begin
100 Emit(AText);
101 TextSource.Add('');
102end;
103
104procedure TProducerGCCC.Emit(AText: string);
105begin
106 with TextSource do begin
107 if Count = 0 then Add('');
108 if Strings[Count - 1] = '' then
109 Strings[Count - 1] := Strings[Count - 1] + DupeString(' ', IndentationLength * Indetation);
110 Strings[Count - 1] := Strings[Count - 1] + AText;
111 end;
112end;
113
114procedure TProducerGCCC.GenerateUses(UsedModules: TUsedModules);
115var
116 I: Integer;
117begin
118 for I := 0 to UsedModules.Count - 1 do
119 EmitLn('#include "' + TUsedModule(UsedModules[I]).Name + '.h"');
120 EmitLn;
121end;
122
123procedure TProducerGCCC.GenerateModule(Module: TSourceModule);
124begin
125 Module.TargetFile := Module.Name + '.c';
126 EmitLn('#include "platform.h"');
127 EmitLn;
128 if Module is TModuleProgram then begin
129 TModuleProgram(Module).Body.Name := 'main';
130 GenerateUses(TModuleProgram(Module).UsedModules);
131 GenerateCommonBlock(TModuleProgram(Module).Body, '');
132 end else
133 if Module is TModuleUnit then begin
134 GenerateUses(TModuleProgram(Module).UsedModules);
135 GenerateCommonBlock(TModuleUnit(Module).Body, '');
136 end;
137end;
138
139procedure TProducerGCCC.Produce(Module: TSourceModule);
140begin
141 inherited;
142 TextSource.Clear;
143 GenerateModule(Module);
144end;
145
146procedure TProducerGCCC.GenerateProgram(ProgramBlock: TProgram);
147var
148 I: Integer;
149begin
150 Indetation := 0;
151 with ProgramBlock do
152 for I := 0 to Modules.Count - 1 do
153 GenerateModule(TSourceModule(Modules[I]));
154end;
155
156procedure TProducerGCCC.GenerateFunctions(Functions: TFunctions;
157 Prefix: string = '');
158var
159 I: Integer;
160 J: Integer;
161 Line: string;
162begin
163 for I := 0 to Functions.Count - 1 do
164 with TFunction(Functions[I]) do
165 if not Internal then begin
166 if (FunctionType = ftFunction) and Assigned(ResultType) then
167 Line := TranslateType(ResultType.Name) + ' '
168 else Line := 'void ';
169 Line := Line + Prefix + Name + '(';
170 if Parameters.Count > 0 then
171 for J := 0 to Parameters.Count - 1 do begin
172 Line := Line + TranslateType(TParameter(Parameters[J]).ValueType.Name) +
173 ' ' + TParameter(Parameters[J]).Name;
174 if J < Parameters.Count - 1 then Line := Line + ', ';
175 end;
176 Line := Line + ')';
177 EmitLn(Line);
178 GenerateBeginEnd(Code);
179 EmitLn;
180 end;
181end;
182
183procedure TProducerGCCC.GenerateBeginEnd(BeginEnd: TBeginEnd);
184var
185 I: Integer;
186begin
187 EmitLn('{');
188 Inc(Indetation);
189
190 // Variables
191 if BeginEnd.Parent is TCommonBlock then begin
192 GenerateVariableList(BeginEnd.CommonBlock.Variables);
193 end;
194
195 // Commands
196 for I := 0 to BeginEnd.Commands.Count - 1 do
197 GenerateCommand(TCommand(BeginEnd.Commands[I]));
198
199 Dec(Indetation);
200 EmitLn('}');
201end;
202
203procedure TProducerGCCC.GenerateVariableList(VariableList: TVariables);
204var
205 I: Integer;
206begin
207 for I := 0 to VariableList.Count - 1 do
208 GenerateVariable(TVariable(VariableList[I]));
209// EmitLn;
210end;
211
212procedure TProducerGCCC.GenerateVariable(Variable: TVariable);
213begin
214 with Variable do
215 EmitLn(TranslateType(ValueType.Name) + ' ' + Name + ';');
216end;
217
218procedure TProducerGCCC.GenerateCommand(Command: TCommand);
219begin
220 if Command is TBeginEnd then GenerateBeginEnd(TBeginEnd(Command))
221 else if Command is TWhileDo then GenerateWhileDo(TWhileDo(Command))
222 else if Command is TForToDo then GenerateForToDo(TForToDo(Command))
223 else if Command is TIfThenElse then GenerateIfThenElse(TIfThenElse(Command))
224 else if Command is TAssignment then GenerateAssignment(TAssignment(Command))
225 else if Command is TFunctionCall then GenerateFunctionCall(TFunctionCall(Command));
226end;
227
228procedure TProducerGCCC.GenerateWhileDo(WhileDo: TWhileDo);
229begin
230 EmitLn('while (' + GenerateExpression(WhileDo.Condition) + ')');
231 if Assigned(WhileDo.Command) then GenerateCommand(WhileDo.Command);
232end;
233
234procedure TProducerGCCC.GenerateForToDo(ForToDo: TForToDo);
235begin
236 with ForToDo do begin
237 if Assigned(ControlVariable) then
238 EmitLn('for(' + ControlVariable.Name + ' = ' +
239 GenerateExpression(Start) + '; ' + ControlVariable.Name + ' < ' +
240 GenerateExpression(Stop) + '; ' + ControlVariable.Name + '++)');
241 GenerateCommand(Command);
242 end;
243end;
244
245procedure TProducerGCCC.GenerateIfThenElse(IfThenElse: TIfThenElse);
246begin
247 EmitLn('if(' + GenerateExpression(IfThenElse.Condition) + ')');
248 GenerateCommand(IfThenElse.Command);
249 if Assigned(IfThenElse.ElseCommand) then begin
250 EmitLn('else ');
251 GenerateCommand(IfThenElse.ElseCommand);
252 end;
253end;
254
255procedure TProducerGCCC.GenerateAssignment(Assignment: TAssignment);
256begin
257 if Assignment.Target.Name = 'Result' then EmitLn('return(' + GenerateExpression(Assignment.Source) + ');')
258 else EmitLn(Assignment.Target.Name + ' = ' + GenerateExpression(Assignment.Source) + ';');
259end;
260
261procedure TProducerGCCC.GenerateFunctionCall(FunctionCall: TFunctionCall);
262var
263 Line: string;
264 I: Integer;
265begin
266 with FunctionCall do begin
267 Line := FunctionRef.Name + '(';
268 if ParameterExpression.Count > 0 then begin
269 for I := 0 to ParameterExpression.Count - 1 do begin
270 Line := Line + GenerateExpression(TExpression(ParameterExpression[I]));
271 if I < ParameterExpression.Count - 1 then Line := Line + ', ';
272 end;
273 end;
274 Line := Line + ');';
275 EmitLn(Line);
276 end;
277end;
278
279function TProducerGCCC.GenerateExpression(Expression: TExpression): string;
280begin
281 case Expression.NodeType of
282 ntConstant: begin
283 if VarType(Expression.Value) = varString then
284 Result := '"' + Expression.Value + '"'
285 else Result := Expression.Value;
286 end;
287 ntVariable: Result := Expression.Variable.Name;
288 ntFunction: Result := Expression.FunctionCall.FunctionRef.Name;
289 ntOperator: begin
290 Result := GenerateExpression(TExpression(Expression.SubItems.First))
291 + ' ' + TranslateOperator(Expression.OperatorName) + ' ' +
292 GenerateExpression(TExpression(Expression.SubItems.Last));
293 end;
294 ntNone: ;
295 end;
296end;
297
298procedure TProducerGCCC.AssignToStringList(Target: TStringList);
299begin
300 Target.Assign(TextSource);
301end;
302
303procedure TProducerGCCC.GenerateCommonBlock(CommonBlock: TCommonBlock; LabelPrefix: string);
304var
305 I: Integer;
306 LabelName: string;
307begin
308 with CommonBlock do begin
309 GenerateTypes(Types);
310 GenerateFunctions(Functions);
311 EmitLn('void ' + Name + '()');
312 GenerateBeginEnd(Code);
313 end;
314end;
315
316procedure TProducerGCCC.GenerateType(AType: TType);
317var
318 I: Integer;
319begin
320 if Assigned(AType) then begin
321 if AType is TTypeRecord then begin
322 EmitLn('struct');
323 EmitLn('{');
324 Inc(Indetation);
325 GenerateVariableList(TTypeRecord(AType).CommonBlock.Variables);
326 Dec(Indetation);
327 EmitLn('} ' + TranslateType(AType.Name) + ';');
328 EmitLn;
329 GenerateFunctions(TTypeRecord(AType).CommonBlock.Functions, AType.Name + '_');
330 end else
331 if AType is TTypeArray then begin
332 GenerateType(TTypeArray(AType).ItemType);
333 EmitLn('* ');
334
335(* if Assigned(TTypeArray(AType).IndexType) then begin
336 Emit(AType.Name + '[');
337 Emit('[');
338 GenerateType(TTypeArray(AType).IndexType);
339 Emit(']');
340 end;
341 Emit(' of ');
342 if Assigned(TTypeArray(AType).ItemType) then*)
343 Emit(TranslateType(AType.Name));
344 end else
345 if AType is TTypePointer then begin
346 if Assigned(AType.UsedType) then begin
347 Emit(AType.UsedType.Name);
348 Emit(' *');
349 end;
350 Emit(TranslateType(AType.Name));
351 end else begin
352 if Assigned(AType.UsedType) then begin
353 //GenerateType(AType.UsedType);
354 Emit(AType.UsedType.Name);
355 Emit(' ');
356 end;
357 Emit(TranslateType(AType.Name));
358 end;
359 end;
360end;
361
362procedure TProducerGCCC.GenerateTypes(Types: TTypes);
363var
364 I: Integer;
365begin
366 if Types.Count > 0 then begin
367 Inc(Indetation);
368 for I := 0 to Types.Count - 1 do
369 with TType(Types[I]) do
370 if (not Internal) then begin
371 Emit('typedef ');
372 GenerateType(TType(Types[I]));
373 EmitLn(';');
374 end;
375 Dec(Indetation);
376 EmitLn('');
377 end;
378end;
379
380end.
Note: See TracBrowser for help on using the repository browser.