GCBASIC supports user-defined CONSTANTS, which allow a programmer to assign a
fixed value to a named symbol. GCBASIC also supports two directives, #samevar
and #samebit, which are intended to resolve the changing nature of the flat
Microchip namespace across registers and bits.
The problem is that Microchip does not maintain a universally consistent
namespace across all microcontrollers. This inconsistency, combined with the
way GCBASIC handles #samevar and #samebit, can introduce ambiguity that is
difficult to detect and harder to debug.
Prior to this change, the user has no way of knowing that a conflict exists.
There is no warning, no error, and no indication that the compiler has
encountered an ambiguous name. Incorrect code may be generated silently, and
the resulting behaviour can be extremely difficult to diagnose because the
compiled output appears valid.
This capability is in build 1605 or greater.
A Real-World Example That Triggered This Investigation
A user reported that the following code, targeting the PIC10F200, produced
incorrect assembly output.
OSCCAL.FOSC4 = 1
The user expected this to set bit 0 of OSCCAL. Instead, the compiler generated
code that modified CAL0, which is bit 1. The generated assembly was syntactically
valid and assembled without error, but the hardware behaviour was wrong. There
was no warning from the compiler.
The workaround at the time was to use the explicit bit address directly.
OSCCAL.0 = 1
This confirmed that the compiler knew the correct register, but the name FOSC4
was being resolved incorrectly. The root cause was that FOSC4 exists as both
a CONSTANT (used to control timers) and as a register bit in OSCCAL. The
compiler resolved FOSC4 as the CONSTANT rather than the register bit, and
produced the wrong result silently.
The Problem in Detail
Example 1: FOSC4 on the PIC10F200
The 10F200 range has a register bit called FOSC4, located at OSCCAL.0.
However, FOSC4 is also defined as a CONSTANT used to control timers, with a
value of 1. When a programmer references FOSC4 in code targeting the 10Fxxx
family, the meaning is ambiguous.
As a CONSTANT, FOSC4 has a value of 1.
As a register bit, FOSC4 refers to OSCCAL,0, which has a value of 0.
The compiler resolves the name as a CONSTANT, generates incorrect assembly, and
produces no diagnostic. This affects six microcontrollers in the 10F2xx range.
Example 2: TWBR on the ATmega328P
The register TWBR is common across many AVR microcontrollers and serves as
the control register for I2C. On the ATmega328P, however, this register is
named TWBR0 to support two or more I2C channels.
In the past, GCBASIC addressed this by allowing TWBR to be mapped to TWBR0
using #samevar. The difficulty is that #samevar operates universally and
is not chip-specific. As a result, TWBR0 is created as a CONSTANT regardless
of whether TWBR0 exists as a real register on the target microcontroller.
Any programmer who then references TWBR0 directly is in an ambiguous
situation. The compiler sees both a CONSTANT called TWBR0 and a register
called TWBR0, and it cannot reliably determine which one was intended.
The Solution
This change introduces a detection step that examines the microcontroller
namespace specifically. It reports any case where a CONSTANT shares a name
with either a register or a register bit. Two checks are performed.
CONSTANT vs register bit — iterates the SysVarBits map and checks
each name against the Constants map.
CONSTANT vs register — iterates the SysVars map and checks each name
against the Constants map.
Any collision is reported as AMBIGUOUS in the compiler diagnostic output file,
and is also printed to the terminal in red so that it is immediately visible.
With the old compiler, the FOSC4 conflict would now be reported as follows.
Ambiguous names are also reported directly in the compilation output, so they
are visible immediately without needing to inspect the CDF file. For example.
In this example, OSCCON exists as both a CONSTANT and a register. The
compiler reports it as a warning, and since warnings are treated as errors,
compilation is halted. The programmer is directed to the issue immediately
rather than receiving silently incorrect output.
Resolution
The good news is that any ambiguity can be resolved, and in practice only a
small number of specific cases need attention. Once an ambiguous name is
identified, the offending #samevar or #samebit directive can be removed or
made chip-specific, eliminating the collision entirely.
This detection step makes those cases visible for the first time, so they can
be resolved deliberately rather than discovered accidentally by a programmer
whose code produces the wrong result.
👍
1
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Background
GCBASIC supports user-defined CONSTANTS, which allow a programmer to assign a
fixed value to a named symbol. GCBASIC also supports two directives,
#samevarand
#samebit, which are intended to resolve the changing nature of the flatMicrochip namespace across registers and bits.
The problem is that Microchip does not maintain a universally consistent
namespace across all microcontrollers. This inconsistency, combined with the
way GCBASIC handles
#samevarand#samebit, can introduce ambiguity that isdifficult to detect and harder to debug.
Prior to this change, the user has no way of knowing that a conflict exists.
There is no warning, no error, and no indication that the compiler has
encountered an ambiguous name. Incorrect code may be generated silently, and
the resulting behaviour can be extremely difficult to diagnose because the
compiled output appears valid.
This capability is in build 1605 or greater.
A Real-World Example That Triggered This Investigation
A user reported that the following code, targeting the PIC10F200, produced
incorrect assembly output.
The user expected this to set bit 0 of OSCCAL. Instead, the compiler generated
code that modified CAL0, which is bit 1. The generated assembly was syntactically
valid and assembled without error, but the hardware behaviour was wrong. There
was no warning from the compiler.
The workaround at the time was to use the explicit bit address directly.
This confirmed that the compiler knew the correct register, but the name
FOSC4was being resolved incorrectly. The root cause was that
FOSC4exists as botha CONSTANT (used to control timers) and as a register bit in
OSCCAL. Thecompiler resolved
FOSC4as the CONSTANT rather than the register bit, andproduced the wrong result silently.
The Problem in Detail
Example 1: FOSC4 on the PIC10F200
The 10F200 range has a register bit called
FOSC4, located atOSCCAL.0.However,
FOSC4is also defined as a CONSTANT used to control timers, with avalue of
1. When a programmer referencesFOSC4in code targeting the 10Fxxxfamily, the meaning is ambiguous.
FOSC4has a value of1.FOSC4refers toOSCCAL,0, which has a value of0.The compiler resolves the name as a CONSTANT, generates incorrect assembly, and
produces no diagnostic. This affects six microcontrollers in the 10F2xx range.
Example 2: TWBR on the ATmega328P
The register
TWBRis common across many AVR microcontrollers and serves asthe control register for I2C. On the ATmega328P, however, this register is
named
TWBR0to support two or more I2C channels.In the past, GCBASIC addressed this by allowing
TWBRto be mapped toTWBR0using
#samevar. The difficulty is that#samevaroperates universally andis not chip-specific. As a result,
TWBR0is created as a CONSTANT regardlessof whether
TWBR0exists as a real register on the target microcontroller.Any programmer who then references
TWBR0directly is in an ambiguoussituation. The compiler sees both a CONSTANT called
TWBR0and a registercalled
TWBR0, and it cannot reliably determine which one was intended.The Solution
This change introduces a detection step that examines the microcontroller
namespace specifically. It reports any case where a CONSTANT shares a name
with either a register or a register bit. Two checks are performed.
SysVarBitsmap and checkseach name against the
Constantsmap.SysVarsmap and checks each nameagainst the
Constantsmap.Any collision is reported as
AMBIGUOUSin the compiler diagnostic output file,and is also printed to the terminal in red so that it is immediately visible.
With the old compiler, the FOSC4 conflict would now be reported as follows.
Once the conflict is resolved by correcting the offending
#samevaror#samebitdirective, the output becomes.Where the Results Are Reported
The results of the examination are available in two places.
CDF Diagnostic File
The compiler diagnostic file (CDF) contains the full examination results,
showing every ambiguous name found, or confirming that none were found.
Compilation Messages
Ambiguous names are also reported directly in the compilation output, so they
are visible immediately without needing to inspect the CDF file. For example.
In this example,
OSCCONexists as both a CONSTANT and a register. Thecompiler reports it as a warning, and since warnings are treated as errors,
compilation is halted. The programmer is directed to the issue immediately
rather than receiving silently incorrect output.
Resolution
The good news is that any ambiguity can be resolved, and in practice only a
small number of specific cases need attention. Once an ambiguous name is
identified, the offending
#samevaror#samebitdirective can be removed ormade chip-specific, eliminating the collision entirely.
This detection step makes those cases visible for the first time, so they can
be resolved deliberately rather than discovered accidentally by a programmer
whose code produces the wrong result.
New: Added EnableAmmbiguityInspection. Compiler will not report ambiguous use of constant when register or register.bit have the same title name.
Added to use.ini
This was a little more complex than I thought to add this inspection but it works well.
In the 1000s of demos.. there were seven cases when the use of a constant was the same as a register.bit.
UP, DOWN, ON, OFFand a few I2c registers.
Enjoy this improvement in the quality of the compiler.