diff options
author | Iain Sandoe <iain@sandoe.co.uk> | 2023-01-16 14:07:20 +0000 |
---|---|---|
committer | Iain Sandoe <iain@sandoe.co.uk> | 2023-01-25 15:23:32 +0000 |
commit | 80cf2c5e8f496bed9c6facf55f9ae31d0d90fd28 (patch) | |
tree | f02f7767cecade575300675f1fd35e5c3992ed70 | |
parent | 9d4c00cdaccc3decd07740e817387ce844ef3ac9 (diff) | |
download | gcc-80cf2c5e8f496bed9c6facf55f9ae31d0d90fd28.zip gcc-80cf2c5e8f496bed9c6facf55f9ae31d0d90fd28.tar.gz gcc-80cf2c5e8f496bed9c6facf55f9ae31d0d90fd28.tar.bz2 |
modula-2: Fixes for preprocessing [PR102343, PR108182].
Modula-2 uses the C preprocessor to implement handling for conditional
code and macros. However, this is not done directly, because the process
is applied recursively to imported definitions and modules.
The cc1gm2 executable records the parameters as a template command line
needed to create a composite 'cc1 -E' for each file to be preprocessed
starting with the main file from the original command line.
This patch fixes the capture of the C preprocessor template to include
the target information needed for correct multilib operation.
In order to match the existing semantics of '-E, -M and -MM' these have
to be handled as a 'pre-processor only' job (i.e. the recursion is omitted
and only the main file is processed).
Whereas C-family front ends always pre-process, Modula-2 only does so
when specifically requested (via the -fcpp option).
'-MD, -MMD and -MQ' also require special handling, since (in principle)
these options can be applied to any command line (with -fcpp) providing
dependency information as a by-product.
TODO: the preprocessor is not able to determine def and mod dependencies
for Modula-2 and so the output of this only shows the object to module
dep. We should be able to append the .def and .mod dependencies.
The patch amends save-temps handling to cater for the preprocessor
recursion and to avoid writing saved files into the source directories.
The patch changes the extension for Modula-2 preprocessed source to .m2i
to avoid clashes with .i.
The main driver code is amended to add default handlers for .mod and .m2i
so that a useful error message will be emitted if the Modula-2 compiler
is not built-in.
The compiler will now also handle code generation from a .m2i preprocessed
source.
TODO: We should not need to pass the '-c' option to the compiler to alter
the processing of init code.
Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>
PR modula2/102343
PR modula2/108182
gcc/ChangeLog:
* gcc.cc: Provide default specs for Modula-2 so that when the
language is not built-in better diagnostics are emitted for
attempts to use .mod or .m2i file extensions.
gcc/m2/ChangeLog:
* gm2-compiler/M2Comp.mod: Early exit for pre-processor-only jobs.
* gm2-compiler/M2Options.def (SetPPOnly, GetPPOnly, SetMD, GetMD,
SetMMD, GetMMD, SetMQ, GetMQ, SetObj, GetObj, SetDumpDir,
GetDumpDir):New.
* gm2-compiler/M2Options.mod:(SetPPOnly, GetPPOnly, SetMD, GetMD,
SetMMD, GetMMD, SetMQ, GetMQ, SetObj, GetObj, SetDumpDir,
GetDumpDir):New.
* gm2-compiler/M2Preprocess.def (PreprocessModule): Add flag to
indicate the main file.
* gm2-compiler/M2Preprocess.mod: Handle Preprocess-only jobs,
handle MD, MMD and MQ options.
* gm2-gcc/m2options.h (M2Options_SetPPOnly, M2Options_GetPPOnly,
M2Options_SetDumpDir, M2Options_SetMD, M2Options_GetMD,
M2Options_SetMMD, M2Options_GetMMD, M2Options_SetMQ, M2Options_GetMQ,
M2Options_SetObj, M2Options_GetObj): New.
* gm2-gcc/m2type.cc (m2type_InitBaseTypes): Early exit for pre-
processor-only jobs.
* gm2-lang.cc (gm2_langhook_init): Handle preprocess-only commands.
(gm2_langhook_option_lang_mask): Claim C and Driver options so that
we can intercept them for building pre-processor commands.
(gm2_langhook_init_options): Collect the preprocessor line here.
Save options that have different actions for preprocessor and compile
commands.
(gm2_langhook_handle_option): Only handle the modula-2 options here.
(gm2_langhook_post_options): Do not create a back-end for pre-
processor-only jobs.
* gm2spec.cc (lang_specific_driver): Ignore PCH options, append a
scaffold-main for cases where we are building a main module with
-c.
* lang-specs.h: Revise to handle preprocessor-only jobs and to
consume pre-processed files.
* lang.opt: Remove Driver and C options copies (we claim these
separately).
-rw-r--r-- | gcc/gcc.cc | 1 | ||||
-rw-r--r-- | gcc/m2/gm2-compiler/M2Comp.mod | 38 | ||||
-rw-r--r-- | gcc/m2/gm2-compiler/M2Options.def | 90 | ||||
-rw-r--r-- | gcc/m2/gm2-compiler/M2Options.mod | 139 | ||||
-rw-r--r-- | gcc/m2/gm2-compiler/M2Preprocess.def | 2 | ||||
-rw-r--r-- | gcc/m2/gm2-compiler/M2Preprocess.mod | 130 | ||||
-rw-r--r-- | gcc/m2/gm2-gcc/m2options.h | 11 | ||||
-rw-r--r-- | gcc/m2/gm2-gcc/m2type.cc | 4 | ||||
-rw-r--r-- | gcc/m2/gm2-lang.cc | 237 | ||||
-rw-r--r-- | gcc/m2/gm2spec.cc | 33 | ||||
-rw-r--r-- | gcc/m2/lang-specs.h | 40 | ||||
-rw-r--r-- | gcc/m2/lang.opt | 119 |
12 files changed, 619 insertions, 225 deletions
@@ -1423,6 +1423,7 @@ static const struct compiler default_compilers[] = {".r", "#Ratfor", 0, 0, 0}, {".go", "#Go", 0, 1, 0}, {".d", "#D", 0, 1, 0}, {".dd", "#D", 0, 1, 0}, {".di", "#D", 0, 1, 0}, + {".mod", "#Modula-2", 0, 0, 0}, {".m2i", "#Modula-2", 0, 0, 0}, /* Next come the entries for C. */ {".c", "@c", 0, 0, 1}, {"@c", diff --git a/gcc/m2/gm2-compiler/M2Comp.mod b/gcc/m2/gm2-compiler/M2Comp.mod index fd5ea1b..05eaacc 100644 --- a/gcc/m2/gm2-compiler/M2Comp.mod +++ b/gcc/m2/gm2-compiler/M2Comp.mod @@ -22,7 +22,8 @@ along with GNU Modula-2; see the file COPYING3. If not see IMPLEMENTATION MODULE M2Comp ; -FROM M2Options IMPORT Statistics, Quiet, WholeProgram, ExtendedOpaque, GenModuleList ; +FROM M2Options IMPORT PPonly, Statistics, Quiet, WholeProgram, + ExtendedOpaque, GenModuleList ; FROM M2Pass IMPORT SetPassToPass0, SetPassToPass1, SetPassToPass2, SetPassToPassC, SetPassToPass3, SetPassToNoPass, SetPassToPassHidden ; @@ -60,11 +61,12 @@ FROM SymbolTable IMPORT GetSymName, IsDefImp, NulSym, ResolveConstructorTypes, SanityCheckConstants, IsDefinitionForC, IsBuiltinInModule, PutModLink, IsDefLink, IsModLink ; -FROM FIO IMPORT StdErr ; +FROM FIO IMPORT StdErr, StdOut ; FROM NameKey IMPORT Name, GetKey, KeyToCharStar, makekey ; FROM M2Printf IMPORT fprintf1 ; FROM M2Quiet IMPORT qprintf0, qprintf1, qprintf2 ; FROM DynamicStrings IMPORT String, InitString, KillString, InitStringCharStar, Dup, Mark, string ; +FROM M2Options IMPORT Verbose ; CONST Debugging = FALSE ; @@ -126,6 +128,10 @@ PROCEDURE Compile (s: String) ; BEGIN DoPass0(s) ; FlushWarnings ; FlushErrors ; + IF PPonly + THEN + RETURN + END; ResetForNewPass ; ResetErrorScope ; qprintf0('Pass 1: scopes, enumerated types, imports and exports\n') ; DoPass1 ; @@ -198,7 +204,7 @@ VAR name : ADDRESS ; isdefimp: BOOLEAN ; BEGIN - IF OpenSource(PreprocessModule(s)) + IF OpenSource(s) THEN ExamineCompilationUnit(name, isdefimp) ; IF isdefimp @@ -226,15 +232,26 @@ VAR Sym : CARDINAL ; i : CARDINAL ; SymName, - FileName: String ; + FileName, + PPSource: String ; BEGIN P0Init ; SetPassToPass0 ; - PeepInto(s) ; + (* Maybe preprocess the main file. *) + PPSource := PreprocessModule(s, TRUE); + IF PPonly + THEN + RETURN + END; + PeepInto (PPSource) ; Main := GetMainModule() ; i := 1 ; Sym := GetModuleNo(i) ; - qprintf1('Compiling: %s\n', s) ; + qprintf1('Compiling: %s\n', PPSource) ; + IF Verbose + THEN + fprintf1(StdOut, 'Compiling: %s\n', PPSource) ; + END ; qprintf0('Pass 0: lexical analysis, parsing, modules and associated filenames\n') ; WHILE Sym#NulSym DO SymName := InitStringCharStar(KeyToCharStar(GetSymName(Sym))) ; @@ -243,7 +260,7 @@ BEGIN IF FindSourceDefFile(SymName, FileName) THEN ModuleType := Definition ; - IF OpenSource(AssociateDefinition(PreprocessModule(FileName), Sym)) + IF OpenSource(AssociateDefinition(PreprocessModule(FileName, FALSE), Sym)) THEN IF NOT P0SyntaxCheck.CompilationUnit() THEN @@ -280,15 +297,16 @@ BEGIN (* only need to read implementation module if hidden types are declared or it is the main module *) IF Main=Sym THEN - FileName := Dup(s) + FileName := Dup (PPSource) ELSE IF FindSourceModFile (SymName, FileName) THEN + FileName := PreprocessModule (FileName, FALSE) END END ; IF FileName#NIL THEN - IF OpenSource (AssociateModule (PreprocessModule (FileName), Sym)) + IF OpenSource (AssociateModule (Dup (FileName), Sym)) THEN IF NOT P0SyntaxCheck.CompilationUnit() THEN @@ -325,7 +343,7 @@ BEGIN IF FindSourceModFile (SymName, FileName) THEN qprintf2 (' Module %-20s : %s (linking)\n', SymName, FileName) ; - IF OpenSource (AssociateModule (PreprocessModule (FileName), Sym)) + IF OpenSource (AssociateModule (PreprocessModule (FileName, FALSE), Sym)) THEN PutModLink (Sym, TRUE) ; (* This source is only used to determine link time info. *) IF NOT P0SyntaxCheck.CompilationUnit () diff --git a/gcc/m2/gm2-compiler/M2Options.def b/gcc/m2/gm2-compiler/M2Options.def index e7b34cf..df42a4a 100644 --- a/gcc/m2/gm2-compiler/M2Options.def +++ b/gcc/m2/gm2-compiler/M2Options.def @@ -52,11 +52,12 @@ EXPORT QUALIFIED SetReturnCheck, SetNilCheck, SetCaseCheck, SetWholeValueCheck, GetWholeValueCheck, SetLowerCaseKeywords, SetIndex, SetRange, SetWholeDiv, SetStrictTypeChecking, - Setc, Getc, SetUselist, GetUselist, GetUselistFilename, - SetShared, SetB, + Setc, Getc, SetPPOnly, GetPPOnly, + SetUselist, GetUselist, GetUselistFilename, + SetShared, Iso, Pim, Pim2, Pim3, Pim4, - cflag, + PPonly, cflag, PositiveModFloorDiv, Pedantic, Verbose, Statistics, UnboundedByReference, VerboseUnbounded, @@ -83,7 +84,7 @@ EXPORT QUALIFIED SetReturnCheck, SetNilCheck, SetCaseCheck, DebugBuiltins, setdefextension, setmodextension, SetStatistics, SetWall, SetSaveTemps, SetSaveTempsDir, SaveTemps, GetSaveTempsDir, - GenModuleList, + SetDumpDir, GetDumpDir, GenModuleList, CppArg, CppCommandLine, CppRemember, SetDebugFunctionLineNumbers, DebugFunctionLineNumbers, SetGenerateStatementNote, GenerateStatementNote, @@ -92,10 +93,11 @@ EXPORT QUALIFIED SetReturnCheck, SetNilCheck, SetCaseCheck, SetScaffoldMain, ScaffoldMain, SetRuntimeModuleOverride, GetRuntimeModuleOverride, SetGenModuleList, GetGenModuleFilename, SharedFlag, - GetB ; + SetB, GetB, SetMD, GetMD, SetMMD, GetMMD, SetObj, GetObj ; VAR + PPonly, (* -E/M/MM present? - preprocessing only *) cflag, (* -c flag present? *) Iso, (* -fiso use ISO SYSTEM.def *) Pim, (* -fpim use PIM [234] SYSTEM.def *) @@ -174,6 +176,18 @@ VAR Coding, Profiling : BOOLEAN ; +(* + SetPPOnly - set the PPonly to value (on E, M, MM). +*) + +PROCEDURE SetPPOnly (value: BOOLEAN) ; + + +(* + GetPPOnly - get the PPonly (Preprocess only). +*) + +PROCEDURE GetPPOnly () : BOOLEAN ; (* Setc - set the cflag (compile only flag -c) to value. @@ -195,13 +209,64 @@ PROCEDURE Getc () : BOOLEAN ; PROCEDURE SetB (arg: ADDRESS) ; - (* GetB - returns argument to the -B option as a string or NIL if it were never set. *) PROCEDURE GetB () : ADDRESS ; +(* + SetMD - assigns MD file to arg. +*) + +PROCEDURE SetMD (arg: ADDRESS) ; + +(* + GetMD - returns the filename set for MD or NIL if it was never set. +*) + +PROCEDURE GetMD () : ADDRESS ; + + +(* + SetMMD - assigns MMD file to arg. +*) + +PROCEDURE SetMMD (arg: ADDRESS) ; + +(* + GetMMD - returns the filename set for MMD or NIL if it was never set. +*) + +PROCEDURE GetMMD () : ADDRESS ; + +(* + SetMQ - assigns MQ file to arg. +*) + +PROCEDURE SetMQ (arg: ADDRESS) ; + +(* + GetMQ - returns the filename set for MQ or NIL if it was never set. +*) + +PROCEDURE GetMQ () : ADDRESS ; + +(* + SetScaffoldDynamic - set the -fscaffold-dynamic flag. +*) + +(* + SetObj - assigns given object file to arg. +*) + +PROCEDURE SetObj (arg: ADDRESS) ; + +(* + GetObj - returns the filename set for Object or NIL if it was never set. +*) + +PROCEDURE GetObj () : ADDRESS ; (* SetScaffoldDynamic - set the -fscaffold-dynamic flag. @@ -784,6 +849,19 @@ PROCEDURE SetSaveTempsDir (arg: ADDRESS) ; PROCEDURE GetSaveTempsDir () : String ; +(* + SetDumpDir - Specify dump dir. +*) + +PROCEDURE SetDumpDir (arg: ADDRESS) ; + + +(* + GetDumpDir - return DumpDir or NIL. +*) + +PROCEDURE GetDumpDir () : String ; + (* SetGenModuleList - set the GenModuleList flag to value and pass diff --git a/gcc/m2/gm2-compiler/M2Options.mod b/gcc/m2/gm2-compiler/M2Options.mod index 14e978a..865b857 100644 --- a/gcc/m2/gm2-compiler/M2Options.mod +++ b/gcc/m2/gm2-compiler/M2Options.mod @@ -54,7 +54,12 @@ CONST VAR Barg, + MDarg, + MMDarg, + MQarg, + CmdLineObj, SaveTempsDir, + DumpDir, GenModuleListFilename, UselistFilename, RuntimeModuleOverride, @@ -133,6 +138,94 @@ END GetB ; (* + SetMD - assigns MDarg to the filename from arg. + This overrides any previous MMD. +*) + +PROCEDURE SetMD (arg: ADDRESS) ; +BEGIN + MMDarg := KillString (MMDarg) ; + MDarg := KillString (MDarg) ; + MDarg := InitStringCharStar (arg) +END SetMD ; + + +(* + GetMD - returns MDarg filename as a c-string or NIL if it was never set. +*) + +PROCEDURE GetMD () : ADDRESS ; +BEGIN + RETURN string (MDarg) +END GetMD ; + + +(* + SetMMD - assigns MMDarg to the filename from arg. + This overrides any previous MD. +*) + +PROCEDURE SetMMD (arg: ADDRESS) ; +BEGIN + MDarg := KillString (MDarg) ; + MMDarg := KillString (MMDarg) ; + MMDarg := InitStringCharStar (arg) +END SetMMD ; + + +(* + GetMMD - returns MMDarg filename as a c-string or NIL if it was never set. +*) + +PROCEDURE GetMMD () : ADDRESS ; +BEGIN + RETURN string (MMDarg) +END GetMMD ; + + +(* + SetMQ - assigns MQarg to the filename from arg. +*) + +PROCEDURE SetMQ (arg: ADDRESS) ; +BEGIN + MQarg := KillString (MQarg) ; + MQarg := InitStringCharStar (arg) +END SetMQ ; + + +(* + GetMMD - returns MQarg filename as a c-string or NIL if it was never set. +*) + +PROCEDURE GetMQ () : ADDRESS ; +BEGIN + RETURN string (MQarg) +END GetMQ ; + + +(* + SetObj - assigns CmdLineObj to the filename from arg. +*) + +PROCEDURE SetObj (arg: ADDRESS) ; +BEGIN + CmdLineObj := KillString (CmdLineObj) ; + CmdLineObj := InitStringCharStar (arg) +END SetObj ; + + +(* + GetObj - returns CmdLineObj filename as a c-string or NIL if it was never set. +*) + +PROCEDURE GetObj () : ADDRESS ; +BEGIN + RETURN string (CmdLineObj) +END GetObj ; + + +(* CppCommandLine - returns the Cpp command line and all arguments. NIL is returned if the -fcpp is absent. *) @@ -365,6 +458,25 @@ END GetCpp ; (* + SetPPOnly - set the PPonly (preprocess only) to value. +*) + +PROCEDURE SetPPOnly (value: BOOLEAN) ; +BEGIN + PPonly := value +END SetPPOnly ; + +(* + GetPPOnly - get the PPonly (preprocess only). +*) + +PROCEDURE GetPPOnly () : BOOLEAN ; +BEGIN + RETURN PPonly +END GetPPOnly ; + + +(* Setc - set the cflag (compile only flag -c) to value. *) @@ -1050,7 +1162,8 @@ END SetSaveTemps ; PROCEDURE SetSaveTempsDir (arg: ADDRESS) ; BEGIN - SaveTempsDir := InitStringCharStar (arg) + SaveTempsDir := InitStringCharStar (arg) ; + SaveTemps := TRUE END SetSaveTempsDir ; @@ -1063,6 +1176,24 @@ BEGIN RETURN SaveTempsDir END GetSaveTempsDir ; +(* + SetDumpDir - Set the dump dir. +*) + +PROCEDURE SetDumpDir (arg: ADDRESS) ; +BEGIN + DumpDir := InitStringCharStar (arg) +END SetDumpDir ; + + +(* + GetDumpDir - return DumpDir or NIL. +*) + +PROCEDURE GetDumpDir () : String ; +BEGIN + RETURN DumpDir +END GetDumpDir ; (* SetScaffoldDynamic - set the -fscaffold-dynamic flag. @@ -1247,5 +1378,9 @@ BEGIN GenModuleListFilename := NIL ; SharedFlag := FALSE ; Barg := NIL ; - SaveTempsDir := NIL + MDarg := NIL ; + MMDarg := NIL ; + MQarg := NIL ; + SaveTempsDir := NIL ; + DumpDir := NIL END M2Options. diff --git a/gcc/m2/gm2-compiler/M2Preprocess.def b/gcc/m2/gm2-compiler/M2Preprocess.def index 08fe192..0258580 100644 --- a/gcc/m2/gm2-compiler/M2Preprocess.def +++ b/gcc/m2/gm2-compiler/M2Preprocess.def @@ -45,7 +45,7 @@ EXPORT QUALIFIED PreprocessModule ; All temporary files will be deleted when the compiler exits. *) -PROCEDURE PreprocessModule (filename: String) : String ; +PROCEDURE PreprocessModule (filename: String; isMain: BOOLEAN) : String ; END M2Preprocess. diff --git a/gcc/m2/gm2-compiler/M2Preprocess.mod b/gcc/m2/gm2-compiler/M2Preprocess.mod index eb08015..ebd9cb9 100644 --- a/gcc/m2/gm2-compiler/M2Preprocess.mod +++ b/gcc/m2/gm2-compiler/M2Preprocess.mod @@ -25,7 +25,7 @@ IMPLEMENTATION MODULE M2Preprocess ; FROM SYSTEM IMPORT WORD ; FROM DynamicStrings IMPORT string, InitString, Mark, KillString, EqualArray, InitStringCharStar, - Dup, ConCat, ConCatChar, RIndex, Slice ; + Dup, ConCat, ConCatChar, RIndex, Slice, Length ; FROM choosetemp IMPORT make_temp_file ; FROM pexecute IMPORT pexecute ; @@ -33,7 +33,8 @@ FROM libc IMPORT system, exit, unlink, printf, atexit ; FROM Lists IMPORT List, InitList, KillList, IncludeItemIntoList, ForeachItemInListDo ; FROM FIO IMPORT StdErr, StdOut ; FROM M2Printf IMPORT fprintf1 ; -FROM M2Options IMPORT Verbose, CppCommandLine, SaveTemps ; +FROM M2Options IMPORT Verbose, PPonly, GetObj, GetMD, GetMMD, GetMQ, + CppCommandLine, SaveTemps, GetSaveTempsDir, GetDumpDir ; FROM NameKey IMPORT Name, MakeKey, KeyToCharStar, makekey ; @@ -77,14 +78,80 @@ BEGIN RETURN 0 END RemoveFiles ; +(* + Return the filename with no path. +*) + +PROCEDURE GetFileName (Path: String) : String ; +VAR + fstart: INTEGER ; +BEGIN + fstart := RIndex(Path, '/', 0) ; + IF fstart=-1 + THEN + fstart := 0 + ELSE + fstart := fstart + 1 + END ; + RETURN Dup (Slice(Path, fstart, Length (Path))) +END GetFileName ; + + +(* + Return basename. +*) + +PROCEDURE BaseName (Path: String) : String ; +VAR + ext, + basename: INTEGER ; +BEGIN + basename := RIndex(Path, '/', 0) ; + IF basename=-1 + THEN + basename := 0 + ELSE + basename := basename + 1 + END ; + ext := RIndex(Path, '.', 0) ; + IF ext=-1 + THEN + ext := 0 + END ; + RETURN Dup (Slice(Path, basename, ext)) +END BaseName ; (* - MakeSaveTempsFileName - return a temporary file "filename.i". + MakeSaveTempsFileName - return a temporary file like + "./filename.{def,mod}.m2i" in the CWD unless SaveTempsDir = obj, + when we put it in the dumpdir if that is specified (or fallback to '.' + if not). + We have to keep the original extension because that disambiguates .def + and .mod files (otherwise, we'd need two 'preprocessed' extensions). *) PROCEDURE MakeSaveTempsFileName (filename: String) : String ; +VAR + NewName, + DumpDir, + NewDir: String ; BEGIN - RETURN ConCat (Dup (filename), InitString ('.i')) + NewName := ConCat (GetFileName (filename), InitString ('.m2i')) ; + NewDir := GetSaveTempsDir () ; + DumpDir := GetDumpDir () ; +(* IF Verbose + THEN + fprintf1 (StdOut, "newname: %s", NewName) ; + fprintf1 (StdOut, " NewDir: %s", NewDir) ; + fprintf1 (StdOut, " DumpDir: %s\n", DumpDir) + END ; +*) + IF (NewDir AND EqualArray (NewDir, 'obj')) AND DumpDir + THEN + RETURN Dup (ConCat (DumpDir, NewName)) + ELSE + RETURN Dup (ConCat (InitString ('./'), NewName)) + END ; END MakeSaveTempsFileName ; @@ -98,7 +165,7 @@ END MakeSaveTempsFileName ; All temporary files will be deleted when the compiler exits. *) -PROCEDURE PreprocessModule (filename: String) : String ; +PROCEDURE PreprocessModule (filename: String; isMain: BOOLEAN) : String ; VAR tempfile, command, @@ -107,18 +174,55 @@ BEGIN command := CppCommandLine () ; IF (command = NIL) OR EqualArray (command, '') THEN - RETURN filename + RETURN Dup (filename) ELSE - IF SaveTemps + commandLine := Dup (command) ; + tempfile := NIL ; + (* We support MD and MMD for the main file only, at present. *) + IF isMain OR PPonly + THEN + IF GetMD () + THEN + tempfile := ConCat( Mark (InitString(' -MD ')), + InitStringCharStar (GetMD ())) + ELSIF GetMMD () + THEN + tempfile := ConCat( Mark (InitString(' -MMD ')), + InitStringCharStar (GetMMD ())) + END ; + IF tempfile + THEN + commandLine := ConCat (Dup (commandLine), Dup (tempfile)) ; + (* We can only add MQ if we already have an MD/MMD. *) + IF GetMQ () + THEN + tempfile := ConCat( Mark (InitString(' -MQ ')), + InitStringCharStar (GetMQ ())) ; + commandLine := ConCat (Dup (commandLine), Dup (tempfile)) + END ; + END ; + END ; + (* The output file depends on whether we are in stand-alone PP mode, and + if an output file is specified. *) + tempfile := NIL ; + IF PPonly + THEN + IF GetObj() + THEN + tempfile := InitStringCharStar (GetObj ()) + END ; + ELSIF SaveTemps THEN - tempfile := InitStringCharStar (MakeSaveTempsFileName (filename)) + tempfile := MakeSaveTempsFileName (filename) ELSE - tempfile := InitStringCharStar (make_temp_file (KeyToCharStar (MakeKey('i')))) + tempfile := InitStringCharStar (make_temp_file (KeyToCharStar (MakeKey('.m2i')))) + END ; + commandLine := ConCat (ConCatChar (Dup (commandLine), ' '), filename) ; + IF tempfile + THEN + commandLine := ConCat (ConCat (Dup (commandLine), + Mark (InitString(' -o '))), tempfile) ; END ; - commandLine := Dup (command) ; - commandLine := ConCat (ConCat (ConCat (ConCatChar (Dup (commandLine), ' '), filename), - Mark (InitString(' -o '))), - tempfile) ; (* use pexecute in the future res := pexecute(string(Slice(commandLine, 0, Index(commandLine, ' ', 0))), etc etc ); *) diff --git a/gcc/m2/gm2-gcc/m2options.h b/gcc/m2/gm2-gcc/m2options.h index 9cccb37..92b4fd5 100644 --- a/gcc/m2/gm2-gcc/m2options.h +++ b/gcc/m2/gm2-gcc/m2options.h @@ -61,6 +61,8 @@ EXTERN int M2Options_GetWholeValueCheck (void); EXTERN void M2Options_Setc (int value); EXTERN int M2Options_Getc (void); +EXTERN void M2Options_SetPPOnly (int value); +EXTERN int M2Options_GetPPOnly (void); EXTERN void M2Options_SetUselist (int value, const char *filename); EXTERN void M2Options_SetAutoInit (int value); @@ -112,6 +114,7 @@ EXTERN void M2Options_SetStrictTypeChecking (int value); EXTERN void M2Options_SetWall (int value); EXTERN void M2Options_SetSaveTemps (int value); EXTERN void M2Options_SetSaveTempsDir (const char *arg); +EXTERN void M2Options_SetDumpDir (const char *arg); EXTERN int M2Options_GetSaveTemps (void); EXTERN void M2Options_SetScaffoldStatic (int value); EXTERN void M2Options_SetScaffoldDynamic (int value); @@ -121,6 +124,14 @@ EXTERN void M2Options_SetGenModuleList (int value, const char *filename); EXTERN void M2Options_SetShared (int value); EXTERN void M2Options_SetB (const char *arg); EXTERN char *M2Options_GetB (void); +EXTERN void M2Options_SetMD (const char *arg); +EXTERN char *M2Options_GetMD (void); +EXTERN void M2Options_SetMMD (const char *arg); +EXTERN char *M2Options_GetMMD (void); +EXTERN void M2Options_SetMQ (const char *arg); +EXTERN char *M2Options_GetMQ (void); +EXTERN void M2Options_SetObj (const char *arg); +EXTERN char *M2Options_GetObj (void); #undef EXTERN #endif /* m2options_h. */ diff --git a/gcc/m2/gm2-gcc/m2type.cc b/gcc/m2/gm2-gcc/m2type.cc index ad5064f..634fad8 100644 --- a/gcc/m2/gm2-gcc/m2type.cc +++ b/gcc/m2/gm2-gcc/m2type.cc @@ -36,6 +36,7 @@ along with GNU Modula-2; see the file COPYING3. If not see #include "m2tree.h" #include "m2treelib.h" #include "m2type.h" +#include "m2options.h" #undef USE_BOOLEAN static int broken_set_debugging_info = TRUE; @@ -1782,6 +1783,9 @@ m2type_InitBaseTypes (location_t location) m2_packed_boolean_type_node = build_nonstandard_integer_type (1, TRUE); + if (M2Options_GetPPOnly ()) + return; + m2builtins_init (location); m2except_InitExceptions (location); m2expr_init (location); diff --git a/gcc/m2/gm2-lang.cc b/gcc/m2/gm2-lang.cc index 9870743..4d9cae2 100644 --- a/gcc/m2/gm2-lang.cc +++ b/gcc/m2/gm2-lang.cc @@ -107,6 +107,8 @@ struct GTY (()) language_function /* Language hooks. */ +static void gm2_langhook_parse_file (void); + bool gm2_langhook_init (void) { @@ -120,6 +122,13 @@ gm2_langhook_init (void) /* GNU Modula-2 uses exceptions. */ using_eh_for_cleanups (); + + if (M2Options_GetPPOnly ()) + { + /* preprocess the file here. */ + gm2_langhook_parse_file (); + return false; /* Finish now, no further compilation. */ + } return true; } @@ -128,7 +137,9 @@ gm2_langhook_init (void) static unsigned int gm2_langhook_option_lang_mask (void) { - return CL_ModulaX2; + /* We need to process some driver options and pass through some C + ones to build our preprocessing lines. */ + return CL_ModulaX2 | CL_C | CL_DRIVER; } /* Initialize the options structure. */ @@ -155,27 +166,146 @@ gm2_langhook_init_options_struct (struct gcc_options *opts) static vec<bool> filename_cpp; +/* Build the C preprocessor command line here, since we need to include + options that are not passed to the handle_option function. */ + void gm2_langhook_init_options (unsigned int decoded_options_count, struct cl_decoded_option *decoded_options) { unsigned int i; bool in_cpp_args = false; + bool building_cpp_command = false; for (i = 1; i < decoded_options_count; i++) { - switch (decoded_options[i].opt_index) - { - case OPT_fcpp_begin: - in_cpp_args = true; - break; - case OPT_fcpp_end: - in_cpp_args = false; - break; - case OPT_SPECIAL_input_file: - case OPT_SPECIAL_program_name: - filename_cpp.safe_push (in_cpp_args); - } + enum opt_code code = (enum opt_code)decoded_options[i].opt_index; + const struct cl_option *option = &cl_options[code]; + const char *opt = (const char *)option->opt_text; + const char *arg = decoded_options[i].arg; + HOST_WIDE_INT value = decoded_options[i].value; + switch (code) + { + case OPT_fcpp: + gcc_checking_assert (building_cpp_command); + break; + case OPT_fcpp_begin: + in_cpp_args = true; + building_cpp_command = true; + break; + case OPT_fcpp_end: + in_cpp_args = false; + break; + case OPT_SPECIAL_input_file: + filename_cpp.safe_push (in_cpp_args); + break; + + /* C and driver opts that are not passed to the preprocessor for + modula-2, but that we use internally for building preprocesor + command lines. */ + case OPT_B: + M2Options_SetB (arg); + break; + case OPT_c: + M2Options_Setc (value); + break; + case OPT_dumpdir: + if (building_cpp_command) + M2Options_SetDumpDir (arg); + break; + case OPT_save_temps: + if (building_cpp_command) + M2Options_SetSaveTemps (value); + break; + case OPT_save_temps_: + if (building_cpp_command) + /* Also sets SaveTemps. */ + M2Options_SetSaveTempsDir (arg); + break; + + case OPT_E: + if (!in_cpp_args) + { + M2Options_SetPPOnly (value); + building_cpp_command = true; + } + M2Options_CppArg (opt, arg, (option->flags & CL_JOINED) + && !(option->flags & CL_SEPARATE)); + break; + case OPT_M: + case OPT_MM: + gcc_checking_assert (building_cpp_command); + M2Options_SetPPOnly (value); + /* This is a preprocessor command. */ + M2Options_CppArg (opt, arg, (option->flags & CL_JOINED) + && !(option->flags & CL_SEPARATE)); + break; + + /* We can only use MQ when the command line is either PP-only, or + when there is a MD/MMD on it. */ + case OPT_MQ: + M2Options_SetMQ (arg); + break; + + case OPT_o: + M2Options_SetObj (arg); + break; + + /* C and driver options that we ignore for the preprocessor lines. */ + case OPT_fpch_deps: + case OPT_fpch_preprocess: + break; + + case OPT_fplugin_: + /* FIXME: We might need to handle this specially, since the modula-2 + plugin is not usable here, but others might be. + For now skip all plugins to avoid fails with the m2 one. */ + break; + + /* Preprocessor arguments with a following filename. */ + case OPT_MD: + case OPT_MMD: + /* Save the filename associated with the MD/MMD which will also + mark the option as used. FIXME: maybe we should diagnose a + missing filename here, rather than assert. */ + gcc_checking_assert (i+1 < decoded_options_count); + gcc_checking_assert (decoded_options[i+1].opt_index + == OPT_SPECIAL_input_file); + /* Pick up the following filename. */ + arg = decoded_options[i+1].arg; + if (code == OPT_MD) + M2Options_SetMD (arg); + else + M2Options_SetMMD (arg); + break; + + /* Options we act on and also pass to the preprocessor. */ + case OPT_O: + M2Options_SetOptimizing (value); + if (building_cpp_command) + M2Options_CppArg (opt, arg, (option->flags & CL_JOINED) + && !(option->flags & CL_SEPARATE)); + break; + case OPT_v: + M2Options_SetVerbose (value); + /* FALLTHROUGH */ + default: + if (code >= N_OPTS) + { + // FIXME remove debug. + fprintf(stderr, "%s : %s\n", opt, (arg ? arg : "")); + break; + } + /* Do not pass Modula-2 args to the preprocessor, any that we care + about here should already have been handled above. */ + if (option->flags & CL_ModulaX2) + break; + /* Otherwise, add this to the CPP command line. */ + if (building_cpp_command) + M2Options_CppArg (opt, arg, (option->flags & CL_JOINED) + && !(option->flags & CL_SEPARATE)); + break; + } } filename_cpp.safe_push (false); } @@ -197,28 +327,16 @@ gm2_langhook_handle_option ( { enum opt_code code = (enum opt_code)scode; + const struct cl_option *option = &cl_options[scode]; + const char *opt = (const char *)option->opt_text; /* ignore file names. */ if (code == N_OPTS) return 1; switch (code) { - case OPT_B: - M2Options_SetB (arg); - return 1; - case OPT_c: - M2Options_Setc (value); - return 1; case OPT_I: - if (insideCppArgs) - { - const struct cl_option *option = &cl_options[scode]; - const char *opt = (const char *)option->opt_text; - M2Options_CppArg (opt, arg, (option->flags & CL_JOINED) - && !(option->flags & CL_SEPARATE)); - } - else - Ipaths.push_back (arg); + Ipaths.push_back (arg); return 1; case OPT_fiso: M2Options_SetISO (value); @@ -358,6 +476,9 @@ gm2_langhook_handle_option ( case OPT_fcpp: M2Options_SetCpp (value); return 1; + case OPT_fpreprocessed: + /* Provided for compatibility; ignore for now. */ + return 1; case OPT_fcpp_begin: insideCppArgs = TRUE; return 1; @@ -396,31 +517,25 @@ gm2_langhook_handle_option ( return 1; break; case OPT_iprefix: + iprefix = arg; + return 1; + break; case OPT_imultilib: + imultilib = arg; + return 1; + break; case OPT_isystem: + isystem.push_back (arg); + return 1; + break; case OPT_iquote: + iquote.push_back (arg); + return 1; + break; case OPT_isysroot: - if (insideCppArgs) - { - const struct cl_option *option = &cl_options[scode]; - const char *opt = (const char *)option->opt_text; - M2Options_CppArg (opt, arg, (option->flags & CL_JOINED) - && !(option->flags & CL_SEPARATE)); - } - if (code == OPT_iprefix) - iprefix = arg; - else if (code == OPT_imultilib) - imultilib = arg; - else if (code == OPT_iquote) - iquote.push_back (arg); - else if (code == OPT_isystem) - isystem.push_back (arg); /* Otherwise, ignored, at least for now. */ return 1; break; - case OPT_O: - M2Options_SetOptimizing (value); - return 1; case OPT_quiet: M2Options_SetQuiet (value); return 1; @@ -445,24 +560,19 @@ gm2_langhook_handle_option ( } else return 0; - case OPT_save_temps: - M2Options_SetSaveTemps (value); - return 1; - case OPT_save_temps_: - M2Options_SetSaveTempsDir (arg); - return 1; - case OPT_v: - M2Options_SetVerbose (value); + case OPT_o: + /* Options we ignore, always. */ return 1; default: if (insideCppArgs) - { - const struct cl_option *option = &cl_options[scode]; - const char *opt = (const char *)option->opt_text; - M2Options_CppArg (opt, arg, (option->flags & CL_JOINED) - && !(option->flags & CL_SEPARATE)); - return 1; - } + /* Already handled. */ + return 1; + else if (option->flags & CL_DRIVER) + /* Ignore driver options we do not specifically use. */ + return 1; + else if (option->flags & CL_C) + /* Ignore C options we do not specifically use. */ + return 1; return 0; } return 0; @@ -574,7 +684,7 @@ gm2_langhook_post_options (const char **pfilename) add_m2_import_paths (flibs); /* Returning false means that the backend should be used. */ - return false; + return M2Options_GetPPOnly (); } /* Call the compiler for every source filename on the command line. */ @@ -597,7 +707,8 @@ static void gm2_langhook_parse_file (void) { gm2_parse_input_files (in_fnames, num_in_fnames); - write_globals (); + if (!M2Options_GetPPOnly ()) + write_globals (); } static tree diff --git a/gcc/m2/gm2spec.cc b/gcc/m2/gm2spec.cc index c248d1b..bc93133 100644 --- a/gcc/m2/gm2spec.cc +++ b/gcc/m2/gm2spec.cc @@ -133,8 +133,10 @@ static const char *add_include (const char *libpath, const char *library); static bool seen_scaffold_static = false; static bool seen_scaffold_dynamic = false; -static bool scaffold_dynamic = true; // Default uses -fscaffold-dynamic. +static bool seen_scaffold_main = false; static bool scaffold_static = false; +static bool scaffold_dynamic = true; // Default uses -fscaffold-dynamic. +static bool scaffold_main = false; static bool seen_gen_module_list = false; static bool seen_uselist = false; static bool uselist = false; @@ -525,17 +527,20 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, scaffold_static = decoded_options[i].value; args[i] |= SKIPOPT; /* We will add the option if it is needed. */ break; + case OPT_fscaffold_main: + seen_scaffold_main = true; + scaffold_main = decoded_options[i].value; + args[i] |= SKIPOPT; /* We will add the option if it is needed. */ + break; case OPT_fgen_module_list_: seen_gen_module_list = true; gen_module_list = decoded_options[i].value; if (gen_module_list) gen_module_filename = decoded_options[i].arg; - args[i] |= SKIPOPT; /* We will add the option if it is needed. */ break; case OPT_fuse_list_: seen_uselist = true; uselist = decoded_options[i].value; - args[i] |= SKIPOPT; /* We will add the option if it is needed. */ break; case OPT_nostdlib: @@ -592,6 +597,14 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, library = -1; break; + /* PCH makes no sense here, we do not catch -output-pch on purpose, + that should flag an error. */ + case OPT_fpch_deps: + case OPT_fpch_preprocess: + case OPT_Winvalid_pch: + args[i] |= SKIPOPT; + break; + case OPT_static: static_link = 1; break; @@ -694,8 +707,10 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, We also add default scaffold linking options. */ /* If we have not seen either uselist or gen_module_list and we need - to link then we turn on -fgen_module_list=- as the default. */ - if ((! (seen_uselist || seen_gen_module_list)) && linking) + to link or compile a module list then we turn on -fgen_module_list=- + as the default. */ + if (!seen_uselist && !seen_gen_module_list + && (linking || scaffold_main)) append_option (OPT_fgen_module_list_, "-", 1); /* We checked that they were not both enabled above, if there was a set @@ -705,6 +720,14 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, if (seen_scaffold_static) append_option (OPT_fscaffold_static, NULL, scaffold_static); + /* If the user has set fscaffold-main specifically, use that. Otherwise, if + we are linking then set it so that we generate the relevant code for the + main module. */ + if (seen_scaffold_main) + append_option (OPT_fscaffold_main, NULL, scaffold_main); + else if (linking) + append_option (OPT_fscaffold_main, NULL, true); + if (allow_libraries) { /* If the libraries have not been specified by the user, select the diff --git a/gcc/m2/lang-specs.h b/gcc/m2/lang-specs.h index bf88264..6228c3c 100644 --- a/gcc/m2/lang-specs.h +++ b/gcc/m2/lang-specs.h @@ -21,19 +21,35 @@ along with GCC; see the file COPYING3. If not see /* This is the contribution to the `default_compilers' array in gcc.c for GNU Modula-2. */ -/* Pass the preprocessor options on the command line together with - the exec prefix. */ - +/* A spec for the 'integrated' preprocessor implementation for Modula-2. */ #define M2CPP \ - "%{fcpp:-fcpp-begin " \ - " -E -lang-asm -traditional-cpp " \ - " %(cpp_unique_options) -fcpp-end; \ - : %I } " + "%{E|M|MM|fcpp: %{E} -fcpp-begin " \ + " %{!E:-E} %(cpp_unique_options) -traditional-cpp -ansi " \ + " -fcpp-end %{B*} %{save-temps*} ; \ + : %{v} %I } " + +/* We have three modes: + 1. When the preprocessing step is explict and there is no following + compilation. Here we do a similar process to cc1 -E where most of + the compilation is short-circuited. + 2. When we are mimicking an integrated preprocessor. Here we use the + modula-2 'fcpp' to construct a command line for the preprocessor and + snarf save-temps and dumpdir inputs to try and be consistent. + 3. We can consume a pre-processed modula-2 source. */ {".mod", "@modula-2", 0, 0, 0}, {"@modula-2", - "cc1gm2 " M2CPP - " %(cc1_options) %{B*} %{c*} %{+e*} %{I*} " - " %{i*} %{save-temps*} %{v} " - " %i %{!fsyntax-only:%(invoke_as)}", - 0, 0, 0}, + /* For preprocessing we use cc1 but wrap it in cc1gm2. */ + "%{E|M|MM:\ + cc1gm2 " M2CPP " %{!fcpp:-fcpp;:%{fcpp}} %{I*} %i } \ + %{!E:%{!M:%{!MM:\ + cc1gm2 " M2CPP " %(cc1_options) %{I*} %i %{c} \ + %{MF*:%eto generate dependencies you must specify either '-M' or '-MM'} \ + %{!fsyntax-only:%(invoke_as)} \ + }}}", 0, 0, 0}, + {".m2i", "@modula-2-cpp-output", 0, 0, 0}, + {"@modula-2-cpp-output", + "%{!M:%{!MM:%{!E: \ + cc1gm2 %<fcpp %(cc1_options) %{v} %I -fmod=.mod.m2i -fdef=.def.m2i %{I*} \ + -fpreprocessed %i %{c} \ + %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0}, diff --git a/gcc/m2/lang.opt b/gcc/m2/lang.opt index 7a19adc..43d6ba5 100644 --- a/gcc/m2/lang.opt +++ b/gcc/m2/lang.opt @@ -26,78 +26,6 @@ Language Modula-2 -B -Modula-2 -; Documented in c.opt - -D -Modula-2 -; Documented in c.opt - -E -Modula-2 -; Documented in c.opt (passed to the preprocessor if -fcpp is used) - -I -Modula-2 Joined Separate -; Documented in c.opt - -L -Modula-2 Joined Separate -; Not documented - -M -Modula-2 -; Documented in c.opt - -MD -Modula-2 -; Documented in c.opt - -MF -Modula-2 -; Documented in c.opt - -MG -Modula-2 -; Documented in c.opt - -MM -Modula-2 -; Documented in c.opt - -MMD -Modula-2 -; Documented in c.opt - -Mmodules -Modula-2 -; Documented in c.opt - -Mno-modules -Modula-2 -; Documented in c.opt - -MP -Modula-2 -; Documented in c.opt - -MQ -Modula-2 -; Documented in c.opt - -MT -Modula-2 -; Documented in c.opt - -P -Modula-2 -; Documented in c.opt - -O -Modula-2 -; Documented in c.opt - Wall Modula-2 ; Documented in c.opt @@ -274,6 +202,10 @@ fpositive-mod-floor-div Modula-2 force positive result from MOD and DIV result floor +fpreprocessed +Modula-2 +; Documented in c.opt + fpthread Modula-2 link against the pthread library (default on) @@ -350,53 +282,14 @@ fwholevalue Modula-2 turns on runtime checking to check whether a whole number is about to exceed range -iprefix -Modula-2 -; Documented in c.opt - -iquote -Modula-2 -; Documented in c.opt - -isystem -Modula-2 -; Documented in c.opt - -idirafter -Modula-2 -; Documented in c.opt - -imultilib -Modula-2 +;fworking-directory +;Modula-2 ; Documented in c.opt lang-asm Modula-2 ; Documented in c.opt --save-temps -Modula-2 Alias(save-temps) - -save-temps -Modula-2 -save temporary preprocessed files - -save-temps= -Modula-2 Joined -save temporary preprocessed files - -traditional-cpp -Modula-2 -; Documented in c.opt - -v -Modula-2 -; Documented in c.opt - -x -Modula-2 Joined -specify the language from the compiler driver - static-libgm2 Driver Link the standard Modula-2 libraries statically in the compilation. |