X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=docs%2Fcoding-style.html;h=8fbb27688cc975c3823ed19517201e9f299a7a72;hb=1ee08bbe86b03ba74a9be309a84602b34e41cbb4;hp=2bcf715470036b7aad119b2331094b0fd564eb27;hpb=ba53144974730a4a6fecc4ec120ad25eed91848e;p=ghc-hetmet.git diff --git a/docs/coding-style.html b/docs/coding-style.html index 2bcf715..8fbb276 100644 --- a/docs/coding-style.html +++ b/docs/coding-style.html @@ -1,22 +1,23 @@
-These coding style guidelines are mainly intended for use in +ghc/rts and ghc/includes. +
NB These are just suggestions. They're not set in stone. Some of +them are probably misguided. If you disagree with them, feel free to +modify this document (and make your commit message reasonably +informative) or mail someone (eg. The GHC mailing list)
Rts.h,
-POSIX_SOURCE
is automatically defined for you before any
-system headers are slurped in, unless you define
-NON_POSIX_SOURCE
prior to including Rts.h
.
-A good C library will use the POSIX_SOURCE
define to
-eliminate non-posix types and function prototypes, so the compiler
-should complain if you venture outside the POSIX spec.
In addition we use ANSI-C-style function declarations and +prototypes exclusively. Every function should have a prototype; +static function prototypes may be placed near the top of the file in +which they are declared, and external prototypes are usually placed in +a header file with the same basename as the source file (although there +are exceptions to this rule, particularly when several source files +together implement a subsystem which is described by a single external +header file). + +
no_return
and
+unused
)
+POSIX_SOURCE
by default, but found that this caused more
+problems than it solved, so now we require any code that is
+POSIX-compliant to explicitly say so by having #include
+"PosixSource.h"
at the top. Try to do this whenever possible.
+
+/* minimum alignment of unsigned int */ @@ -110,50 +124,39 @@ These macros tell you which alignment to use #define ALIGNMENT_DOUBLE 4-
sizeof(int) != sizeof(ptr)
on that platform.
--Use PK_FLT(addr), PK_DBL(addr) to read StgFloat and -StgDouble values from the stack/heap, and ASSIGN_FLT(val,addr)/ -ASSIGN_DBL(val,addr) to assign StgFloat/StgDouble values to heap/stack -locations. These macros take care of alignment restrictions. - -
-Heap/Stack locations are StgWord aligned; the alignment requirements -of an StgDouble may be more than that of StgWord, but we don't pad -misaligned StgDoubles (doing so would be too much hassle). +
-Doing a direct assignment/read of an StgDouble to/from a mis-aligned
-location may not work, so we use the ASSIGN_DBL(,)/PK_DBL() macro,
-which goes via a temporary.
+Use PK_FLT(addr)
, PK_DBL(addr)
to read
+StgFloat and StgDouble values from the stack/heap,
+and ASSIGN_FLT(val,addr)
/
+ASSIGN_DBL(val,addr)
to assign StgFloat/StgDouble values
+to heap/stack locations. These macros take care of alignment
+restrictions.
-Problem: if the architecture allows mis-aligned accesses, but prefers
-aligned accesses, these macros just add an extra level of indirection.
-We need to distinguish between an architecture that allows mis-aligned
-accesses and one that just imposes a performance penalty (this is most
-of them). Perhaps have PREFERRED_ALIGNMENT and REQUIRED_ALIGMENT
-configurations?
+Heap/Stack locations are always StgWord aligned; the
+alignment requirements of an StgDouble may be more than that
+of StgWord, but we don't pad misaligned StgDoubles
+because doing so would be too much hassle (see PK_DBL
&
+co above).
-
@@ -162,7 +165,7 @@ Avoid conditional code like this: #endif-Instead, add an appropriate test to the configure.in script and use +Instead, add an appropriate test to the configure.ac script and use the result of that test instead.
@@ -171,7 +174,7 @@ the result of that test instead. #endif-The problem is that things change from one version of an OS to another +
The problem is that things change from one version of an OS to another - things get added, things get deleted, things get broken, some things are optional extras. Using "feature tests" instead of "system tests" makes things a lot less brittle. Things also tend to get documented @@ -189,19 +192,48 @@ than trying to find a bug which only shows up when running GHC on itself and doesn't manifest itself until 10 seconds after the actual cause of the problem. +
We put all our debugging code inside #ifdef DEBUG. The +general policy is we don't ship code with debugging checks and +assertions in it, but we do run with those checks in place when +developing and testing. Anything inside #ifdef DEBUG should +not slow down the code by more than a factor of 2. + +
We also have more expensive "sanity checking" code for hardcore +debugging - this can slow down the code by a large factor, but is only +enabled on demand by a command-line flag. General sanity checking in +the RTS is currently enabled with the -DS RTS flag. + +
There are a number of RTS flags which control debugging output and +sanity checking in various parts of the system when DEBUG is +defined. For example, to get the scheduler to be verbose about what +it is doing, you would say +RTS -Ds -RTS. See +includes/RtsFlags.h and rts/RtsFlags.c for the full +set of debugging flags. To check one of these flags in the code, +write: + +
+ IF_DEBUG(gc, fprintf(stderr, "...")); ++ +would check the gc flag before generating the output (and the +code is removed altogether if DEBUG is not defined). + +
All debugging output should go to stderr. +
-The ideas in this section are mostly aimed at this issue: +Particular guidelines for writing robust code:
- #define ASSIGN_CC_ID(ccID) \ - { \ - ccID = CC_ID; \ - CC_ID++; \ - } -- -but it's better to use the "do { ... } while (0)" trick instead: - -
- #define ASSIGN_CC_ID(ccID) \ - do { \ - ccID = CC_ID; \ - CC_ID++; \ - } while(0) -- -The following explanation comes from -The Usenet C programming FAQ -
-10.4: What's the best way to write a multi-statement macro? - -A: The usual goal is to write a macro that can be invoked as if it - were a statement consisting of a single function call. This - means that the "caller" will be supplying the final semicolon, - so the macro body should not. The macro body cannot therefore - be a simple brace-enclosed compound statement, because syntax - errors would result if it were invoked (apparently as a single - statement, but with a resultant extra semicolon) as the if - branch of an if/else statement with an explicit else clause. - - The traditional solution, therefore, is to use - - #define MACRO(arg1, arg2) do { \ - /* declarations */ \ - stmt1; \ - stmt2; \ - /* ... */ \ - } while(0) /* (no trailing ; ) */ - - When the caller appends a semicolon, this expansion becomes a - single statement regardless of context. (An optimizing compiler - will remove any "dead" tests or branches on the constant - condition 0, although lint may complain.) - - If all of the statements in the intended macro are simple - expressions, with no declarations or loops, another technique is - to write a single, parenthesized expression using one or more - comma operators. (For an example, see the first DEBUG() macro - in question 10.26.) This technique also allows a value to be - "returned." - - References: H&S Sec. 3.3.2 p. 45; CT&P Sec. 6.3 pp. 82-3. -- -
- #define doNothing() do { } while (0) --
+ #define ASSIGN_CC_ID(ccID) \ + { \ + ccID = CC_ID; \ + CC_ID++; \ + } ++ +(but it's usually better to use an inline function instead - see above). + +
+ #define doNothing() do { } while (0) ++
@@ -423,7 +414,7 @@ You could also write this:int *p, *q;-but Alastair prefers to split the declarations. +but it is preferrable to split the declarations.
-#define stgCast(ty,e) ((ty)(e)) -
#ifdef 0
+... #endif
rather than /* ... */
because C doesn't
+have nested comments.
+
+-On which note: -Hugs related pieces of code often start with the line: -
- /* -*- mode: hugs-c; -*- */ --which helps Emacs mimic the indentation style used by Mark P Jones -within Hugs. Add this to your .emacs file.
- (defun hugs-c-mode () - "C mode with adjusted defaults for use with Hugs (based on linux-c-mode)" - (interactive) - (c-mode) - (setq c-basic-offset 4) - (setq indent-tabs-mode nil) ; don't use tabs to indent - (setq c-recognize-knr-r nil) ; no K&R here - don't pay the price - ; no: (setq tab-width 4) - - (c-set-offset 'knr-argdecl-intro 0) - (c-set-offset 'case-label 0) - (c-set-offset 'statement-case-intro '++) - (c-set-offset 'statement-case-open '+) - ) + typedef struct _Foo { + ... + } Foo;+
-If you must reindent or reorganise, don't do anything else in that commit -and give advance warning that you're about to do it in case anyone else -is changing that file. +If you must reindent or reorganise, don't include any functional +changes that commit and give advance warning that you're about to do +it in case anyone else is changing that file. +
-v
and --verbose
options should be
+used to generate verbose output (intended for the user).
+
+-d
and --debug
options should be
+used to generate debugging output (intended for the developer).
+
+-?
and --help
options should be used
+to display usage information on stdout. The program should exit
+successfully afterwards.
+
+-V
and --version
options should be
+used to output version information on stdout, which includes one line
+of the form 'Program version
+Major.Minor[.Patchlevel] ...
'. The program
+should exit successfully afterwards.
+