Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/xlint/lint1 lint: extend developer documentation



details:   https://anonhg.NetBSD.org/src/rev/c7064d760225
branches:  trunk
changeset: 373156:c7064d760225
user:      rillig <rillig%NetBSD.org@localhost>
date:      Sat Jan 21 21:14:38 2023 +0000

description:
lint: extend developer documentation

diffstat:

 usr.bin/xlint/lint1/README.md |  66 +++++++++++++++++++++++++++++++++---------
 1 files changed, 51 insertions(+), 15 deletions(-)

diffs (97 lines):

diff -r 0bb3059814c1 -r c7064d760225 usr.bin/xlint/lint1/README.md
--- a/usr.bin/xlint/lint1/README.md     Sat Jan 21 20:07:01 2023 +0000
+++ b/usr.bin/xlint/lint1/README.md     Sat Jan 21 21:14:38 2023 +0000
@@ -1,4 +1,4 @@
-[//]: # ($NetBSD: README.md,v 1.9 2022/07/08 20:27:36 rillig Exp $)
+[//]: # ($NetBSD: README.md,v 1.10 2023/01/21 21:14:38 rillig Exp $)
 
 # Introduction
 
@@ -68,21 +68,23 @@
 
 Lint mainly analyzes expressions (`tnode_t`), which are formed from operators
 (`op_t`) and their operands (`tnode_t`).
-Each node has a type (`type_t`) and a few other properties.
+Each node has a data type (`type_t`) and a few other properties that depend on
+the operator.
 
 ## type_t
 
-The elementary types are `int`, `_Bool`, `unsigned long`, `pointer` and so on,
+The basic types are `int`, `_Bool`, `unsigned long`, `pointer` and so on,
 as defined in `tspec_t`.
 
-Actual types like `int`, `const char *` are created by `gettyp(INT)`,
+Concrete types like `int` or `const char *` are created by `gettyp(INT)`,
 or by deriving new types from existing types, using `block_derive_pointer`,
 `block_derive_array` and `block_derive_function`.
 (See [below](#memory-management) for the meaning of the prefix `block_`.)
 
 After a type has been created, it should not be modified anymore.
-Ideally all references to types would be `const`, but that's a lot of work.
-Before modifying a type,
+Ideally all references to types would be `const`, but that's still on the
+to-do list and not trivial.
+In the meantime, before modifying a type,
 it needs to be copied using `block_dup_type` or `expr_dup_type`.
 
 ## tnode_t
@@ -93,15 +95,49 @@
 The operators and their properties are defined in `ops.def`.
 Some examples for operators:
 
-| Operator | Meaning                                                 |
-|----------|---------------------------------------------------------|
-| CON      | compile-time constant in `tn_val`                       |
-| NAME     | references the identifier in `tn_sym`                   |
-| UPLUS    | the unary operator `+tn_left`                           |
-| PLUS     | the binary operator `tn_left + tn_right`                |
-| CALL     | a function call, typically CALL(LOAD(NAME("function"))) |
-| ICALL    | an indirect function call                               |
-| CVT      | an implicit conversion or an explicit cast              |
+| Operator | Meaning                                    |
+|----------|--------------------------------------------|
+| CON      | compile-time constant in `tn_val`          |
+| NAME     | references the identifier in `tn_sym`      |
+| UPLUS    | the unary operator `+tn_left`              |
+| PLUS     | the binary operator `tn_left + tn_right`   |
+| CALL     | a direct function call                     |
+| ICALL    | an indirect function call                  |
+| CVT      | an implicit conversion or an explicit cast |
+
+As an example, the expression `strcmp(names[i], "name")` has this internal
+structure:
+
+~~~text
+ 1: 'call' type 'int'
+ 2:  '&' type 'pointer to function(pointer to const char, pointer to const char) returning int'
+ 3:    'name' 'strcmp' with extern 'function(pointer to const char, pointer to const char) returning int'
+ 4:  'push' type 'pointer to const char'
+ 5:    'convert' type 'pointer to const char'
+ 6:      '&' type 'pointer to char'
+ 7:        'string' type 'array[5] of char', lvalue, length 4, "name"
+ 8:    'push' type 'pointer to const char'
+ 9:      'load' type 'pointer to const char'
+10:        '*' type 'pointer to const char', lvalue
+11:          '+' type 'pointer to pointer to const char'
+12:            'load' type 'pointer to pointer to const char'
+13:              'name' 'names' with auto 'pointer to pointer to const char', lvalue
+14:            '*' type 'long'
+15:              'convert' type 'long'
+16:                'load' type 'int'
+17:                  'name' 'i' with auto 'int', lvalue
+18:              'constant' type 'long', value 8
+~~~
+
+| Lines  | Notes                                                            |
+|--------|------------------------------------------------------------------|
+| 4, 8   | Each argument of the function call corresponds to a `PUSH` node. |
+| 5, 9   | The left operand of a `PUSH` node is the actual argument.        |
+| 8      | The right operand is the `PUSH` node of the previous argument.   |
+| 5, 9   | The arguments of a call are ordered from right to left.          |
+| 10, 11 | Array access is represented as `*(left + right)`.                |
+| 14, 18 | Array and struct offsets are in premultiplied form.              |
+| 18     | The size of a pointer on this platform is 8 bytes.               |
 
 See `debug_node` for how to interpret the members of `tnode_t`.
 



Home | Main Index | Thread Index | Old Index