Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

?ASlink-Warning-Undefined Global #4

Closed
dzantemir opened this issue Jun 17, 2024 · 7 comments
Closed

?ASlink-Warning-Undefined Global #4

dzantemir opened this issue Jun 17, 2024 · 7 comments
Labels
bug Something isn't working

Comments

@dzantemir
Copy link

dzantemir commented Jun 17, 2024

platformio + sdcc 4.4.1

font.h:

extern CONST  u8 Font_JSE_ZXSpectrum_8px[];

build err

?ASlink-Warning-Undefined Global '_Font_JSE_ZXSpectrum_8px' referenced by module 'font'

stm8-dce apparently removes the declaration of a constant, although it is used, the CONST label is needed to load the font from flash memory, if you remove it, everything will be ok, but now the entire array will go into RAM memory

I also checked the v1.1.0 which still errors.

@CTXz
Copy link
Owner

CTXz commented Jun 17, 2024

The extern keyword expects the the array/buffer to be defined somewhere else in your code. Where exactly is it defined?

@dzantemir
Copy link
Author

dzantemir commented Jun 17, 2024

here is the path to the file spl_blink -> src -> fonts -> Font_JSE_ZXSpectrum_8px.c
and a byte array is declared there

#include<stm8s.h>
CONST u8 Font_JSE_ZXSpectrum_8px[]={0x1C,0xA0,0xA0,0xA0,0x7C,0x00,...};

@CTXz
Copy link
Owner

CTXz commented Jun 17, 2024

I'm having a hard time reproducing this issue.

Here's what I came up with to test it:

test.c

#include<stm8s.h>

CONST u8 test[] = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
    0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
    0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
    0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
    0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
    0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};

test.h

#include <stm8s.h>
extern CONST u8 test[];

main.c

#include <stm8s.h>
#include <stm8s_it.h>

#include <test.h>

void main(void)
{
	for (u8 i = 0; ; i++)
	{
		for (u8 j = 0; j < test[i]; j++)
		{
			__asm__("nop");
		}
	}
}

This works just fine without optimizing away the const test array.

If possible, could you send me:

  • The full -d output of stm8dce in a pastebin or txt file. You'll have to add this in use_stm8dce.py.
  • The full pio build process (use pio run --verbose) in a pastebin or txt file.

@dzantemir
Copy link
Author

I'll try your version of the code

@dzantemir
Copy link
Author

dzantemir commented Jun 17, 2024

I found a problem: I access the array not directly but through the address like this

u8 * font_adr= Font_JSE_ZXSpectrum_8px;

This is why the error comes out

font_adr is like a global variable for me; I declare it at the very beginning of the font.c file.

#include "font.h"

u8 *font_adr = Font_JSE_ZXSpectrum_8px;

// если написать так 
// u8 *font_adr;
// то все работает я сделал так u8 *font_adr = Font_JSE_ZXSpectrum_8px; 
// что бы по умолчанию сразу был адрес шрифта 

void Set_Font(u8 f_index) {
    switch (f_index) {
        case 0:
            font_adr = Font_JSE_ZXSpectrum_8px;
            break;

        default:
            break;
    }
}

@CTXz CTXz added the bug Something isn't working label Jun 17, 2024
@CTXz
Copy link
Owner

CTXz commented Jun 17, 2024

Okay, that gives me the full picture.

_Font_JSE_ZXSpectrum_8px is referenced in the INITIALIZER section and is copied to _font_adr in the GSINIT section. Since stm8dce doesn't analyze the INITIALIZER area at all, it doesn't catch this.

I'll push a commit to the v1.1.0wip branch to fix this soon and keep you updated 🎉

CTXz added a commit that referenced this issue Jun 17, 2024
In circumstances where global pointers would be defined to reference an extern constant or function, the extern constants and functions would still be mistakenly optimized out.

Here's an example:

test.c:
```c
const uint8_t test[] = {0xA, 0xB, 0xC, ...};

void testf() {
	__asm__("nop");
}
```

main.c
```c
extern const uint8_t test[];
uint8_t *testptr = test;
void testf();
void (*testfptr)(void) = testf

void main() {
...
```

This would result in the following linker errors:
```
?ASlink-Warning-Undefined Global '_testf' referenced by module 'main'

?ASlink-Warning-Undefined Global '_test' referenced by module 'main
```

This is because SDCC places pointers to `_test` and `_testf` in the INITIALIZER section which then get loaded
to `_testptr` and `_testfptr` in GSINIT section.

Up until this commit, stm8dce did not consider the INITIALIZER section, hence, it'd mistakenly optimize the referenced constants and functions out.

Now, stm8dce parses through the INITIALIZER section and resolves all references to symbols. These can resolve into:

- functions
- constants
- external symbols (i.e. symbols in rel/lib files)

Unfortunately, symbols in hte INITIALIZER section will be excluded from DCE unconditionally. This is because they're loaded using offsets in
GSINIT, instead of being addressed directly, which makes it harder to analyze.

Perhaps in a future commit the tool will also be able to analyze if these constants and functions are acctually being used.

This commit should also fix this issue: #4

Signed-off-by: Patrick Pedersen <ctx.xda@gmail.com>
@CTXz
Copy link
Owner

CTXz commented Jun 17, 2024

Alright, this commit in the v1.1.0wip branch should hopefully fix this issue.

Please close the issue if that fixed it.

CTXz added a commit that referenced this issue Jun 17, 2024
In circumstances where global pointers were defined to reference an extern constant or function, the extern constants and functions would still be mistakenly optimized out.

Here's an example:

test.c:
```c
const uint8_t test[] = {0xA, 0xB, 0xC, ...};

void testf() {
	__asm__("nop");
}
```

main.c:
```c
extern const uint8_t test[];
uint8_t *testptr = test;
void testf();
void (*testfptr)(void) = testf;

void main() {
...
```

This would result in the following linker errors:
```
?ASlink-Warning-Undefined Global '_testf' referenced by module 'main'

?ASlink-Warning-Undefined Global '_test' referenced by module 'main'
```

This is because SDCC places pointers to `_test` and `_testf` in the INITIALIZER section, which then get loaded to `_testptr` and `_testfptr` in the GSINIT section.

Up until this commit, stm8dce did not consider the INITIALIZER section, hence, it would mistakenly optimize the referenced constants and functions out.

Now, stm8dce parses through the INITIALIZER section and resolves all references to symbols. These can resolve into:

- functions
- constants
- external symbols (i.e., symbols in rel/lib files)

Unfortunately, symbols in the INITIALIZER section will be excluded from DCE unconditionally. This is because they're loaded using offsets in GSINIT, instead of being addressed directly. This makes it harder to analyze.

Perhaps in a future commit, the tool will also be able to analyze if these constants and functions are actually being used.

This commit should also fix this issue: #4

Signed-off-by: Patrick Pedersen <ctx.xda@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants